字符串指针的排序向量
Sorting vector of string pointers
很抱歉,如果已经在某处问过这个问题,但我无法找到我正在寻找的答案。
我有一个 std::string 指针的向量,我想按字母顺序排序,但我一直无法弄清楚如何做到这一点。我正在使用std::sort。
我编写了一个快速程序来测试我试图做什么(因为在实际实现中,我的代码是在子进程中运行的,所以很难调试):
#include <string>
#include <algorithm>
#include <vector>
#include <string.h>
bool cmpStrPtrs(std::string *a, std::string *b) {
std::string a1 = *a;
std::string a2 = *b;
if(a1 == a2) return 0;
return a1 > a2 ? 1 : -1;
}
int main(int argc, char *argv[]) {
std::vector<std::string *> vec;
std::string *str1 = new std::string("AAAAA");
std::string *str2 = new std::string("aaaaa");
std::string *str3 = new std::string("xxxxx");
std::string *str4 = new std::string("bfuen");
std::string *str5 = new std::string("xylophone");
vec.push_back(str1);
vec.push_back(str2);
vec.push_back(str3);
vec.push_back(str4);
vec.push_back(str5);
std::sort(vec.begin(), vec.end(), cmpStrPtrs);
for(std::string *str : vec) {
printf("%sn", str->c_str());
}
return 0;
}
当我运行这个时,我得到这个输出:
$ ./strsort
xylophone
bfuen
xxxxx
aaaaa
AAAAA
这似乎根本没有按字母顺序排列,所以我可以假设我要么错误地使用了 sort(),要么我的比较器函数有问题。我也在没有比较器功能的情况下尝试过,我认为这只是根据它们的内存位置从最小到最大对它们进行排序,这实际上并没有改变任何东西。我也尝试使用
bool cmpStrPtrs(std::string *a, std::string *b) {
return a->compare(*b);
}
但它给了我同样的结果。
如果相关,我将使用 c++17 标准使用 g++ 进行编译。
std::string::compare
返回一个int
,而不是一个bool
。根据 cppreference.com 返回值为
负值,如果 *这出现在参数指定的字符序列之前,按字典顺序排列
如果两个字符序列比较等效,则为零
正值,如果 *这出现在参数指定的字符序列之后,按字典顺序排列强文本
返回值将强制转换为bool
对于所有非零值,其计算结果为true
。这意味着您的函数为每对不相同的字符串返回true
。
C++ 标准实际上定义了字符串的operator<
,因此您可以将函数更改为
bool cmpStrPtrs(std::string *a, std::string *b) {
return *a < *b;
}
但这仍然会在您的代码中留下一个大问题。您绝对不需要指针。事实上,你现在正在泄漏记忆,因为你忽略了delete
它们。这项工作的正确工具是std::vector<std::string>
.这还有一个额外的好处,即如果没有额外的间接寻址级别,std::sort
可以在没有帮助程序函数的情况下隐式调用operator<
,从而导致以下解决方案。
std::vector<std::string> vec;
vec.emplace_back("AAAAA");
vec.emplace_back("aaaaa");
vec.emplace_back("xxxxx");
vec.emplace_back("bfuen");
vec.emplace_back("xylophone");
std::sort(vec.begin(), vec.end());
你可以用lambda来做到这一点:
std::sort(vec.begin(), vec.end(), [](std::string * a, std::string * b) {
return *a < *b;
});
您的比较函数旨在模拟小于运算符 - 这意味着如果 a 在 b 之前,它应该返回 true。如果 a 不等于 b,则当前实现返回 true。
你有:
if(a1 == a2) return 0;
return a1 > a2 ? 1 : -1;
应该是:
if(a1 == a2) return false;
return a1 > a2 ? false : true;
或只是:
return a1 < a2;
std::sort
期望严格弱排序。它不会给平等的废话;它只关心前后。
如果右侧先于左侧,则比较函数应返回 true。不幸的是,在
bool cmpStrPtrs(std::string *a, std::string *b) {
std::string a1 = *a;
std::string a2 = *b;
if(a1 == a2) return 0;
return a1 > a2 ? 1 : -1;
}
对于任何非 0 的值,bool
都是正确的。这意味着大于和小于都是真的。这使得逻辑排序几乎是不可能的,因为大于和小于之前。
改进切口 1:根据词典(字母顺序)排序返回bool
。字符串已经实现了一个小于运算符,它完全可以执行您想要的操作。让我们使用它。
bool cmpStrPtrs(std::string *a, std::string *b) {
std::string a1 = *a;
std::string a2 = *b;
return a1 < a2;
}
改进剪辑 2:std::string a1 = *a;
创建一个全新的字符串,该字符串是原始字符串的副本。由于您有一个指向原始指针的指针,因此您可以取消引用该指针并使用原始指针。不需要副本。
bool cmpStrPtrs(std::string *a, std::string *b) {
return *a < *b;
}
- 将结构向量排序为子组
- C++数组与向量排序(在我的情况下,向量比数组慢~2.5倍(无优化))
- 如何在对向量排序后更改索引值?c++
- C++向量排序给出0作为输出
- 将许多向量排序在一起
- 根据一个向量对多个向量排序
- 编译错误向量排序和联合
- C++我自己的函数进行向量排序
- 将字符串的向量排序为日期"yyyymmdd"
- C++ 通过使用旧向量进行预排序来改进向量排序
- C 向量排序 .h .cpp中的单独文件
- 向量排序-c++
- 将向量排序到一个无序映射c++11中
- 向量的向量排序
- c++向量排序方法编译失败,返回预期表达式
- 如何对bitset向量排序
- 向量排序的基础上只有先
- 我如何以相同的方式对两个向量排序,而条件只使用其中一个向量
- 列表排序和结构体向量排序之间的性能差距.c++
- 如何基于第二个字符串对字符串向量的向量排序