我试图按字母顺序(而不是按字典顺序)对文件中的列表输入进行排序。所以,如果列表是:
CdA.b
我需要它变成:A.bCd
不是字典排序:A.Cbd
我使用字符串变量来保存输入,所以我正在寻找一些方法来修改我比较的字符串,使其全部大写或小写,或者如果有更简单的方法来强制进行字母比较,请传授这种智慧。谢谢
我还应该提到,我们仅限于以下库用于此任务:iostream、iomanip、fstream、string,以及C库,如cstring、cctype等。
看起来我只需要通过一些非常乏味的字符提取和每个字符串的倾倒方法来解决这个问题。
将单个字符串转换为大写并进行比较并不会因为被限制使用算法、迭代器等而变得特别糟糕。比较逻辑大约有四行代码。即使不必写这四行也很好,但必须写一个排序算法要困难和乏味得多。(好吧,假设toupper
的通常C版本首先是可以接受的。)
下面我展示了一个简单的strcasecmp()
实现,然后将其用于使用受限库的完整程序中。strcasecmp()
的实现本身不使用受限制的库。
#include <string>
#include <cctype>
#include <iostream>
void toupper(std::string &s) {
for (char &c : s)
c = std::toupper(c);
}
bool strcasecmp(std::string lhs, std::string rhs) {
toupper(lhs); toupper(rhs);
return lhs < rhs;
}
// restricted libraries used below
#include <algorithm>
#include <iterator>
#include <vector>
// Example usage:
// > ./a.out <<< "C d A b"
// A b C d
int main() {
std::vector<std::string> input;
std::string word;
while(std::cin >> word) {
input.push_back(word);
}
std::sort(std::begin(input), std::end(input), strcasecmp);
std::copy(std::begin(input), std::end(input),
std::ostream_iterator<std::string>(std::cout, " "));
std::cout << 'n';
}
排序前不必修改字符串。您可以使用不区分大小写的单字符比较器和std::sort
:对它们进行适当排序
bool case_insensitive_cmp(char lhs, char rhs) {
return ::toupper(static_cast<unsigned char>(lhs) <
::toupper(static_cast<unsigned char>(rhs);
}
std::string input = ....;
std::sort(input.begin(), input.end(), case_insensitive_cmp);
std::vector<string> vec {"A", "a", "lorem", "Z"};
std::sort(vec.begin(),
vec.end(),
[](const string& s1, const string& s2) -> bool {
return strcasecmp(s1.c_str(), s2.c_str()) < 0 ? true : false;
});
在qsort()中使用strcasecmp()作为比较函数。
我不完全确定如何编写它,但您想做的是将字符串转换为小写或大写。
如果字符串一开始就在一个数组中,那么您将遍历列表,并将索引按顺序保存在(int)数组中。
如果你只是在比较字母,那么一个可怕的破解方法就是屏蔽每个字符的上两位。然后大写字母和小写字母叠放在一起。