我目前正在按std :: string<排序运营商。问题在于:
30< 9. 30显示在9之前,因为3< 9,Windows 9x有这个问题。我怎样才能在数字上对它们进行排序,以便在“9只狗”之后出现“30只狐狸”。我还应该补充一点,我正在使用utf 8编码。
由于
答案 0 :(得分:8)
您可以创建自定义比较功能以与std::sort
一起使用。此函数必须检查字符串是否以数字值开头。如果是这样,使用像stringstream这样的机制将每个字符串的数字部分转换为int
。然后比较两个整数值。如果值相等,则按字典顺序比较字符串的非数字部分。否则,如果字符串不包含数字部分,只需按字典顺序比较两个字符串。
基本上,类似于以下(未经测试的)比较函数:
bool is_not_digit(char c)
{
return !std::isdigit(c);
}
bool numeric_string_compare(const std::string& s1, const std::string& s2)
{
// handle empty strings...
std::string::const_iterator it1 = s1.begin(), it2 = s2.begin();
if (std::isdigit(s1[0]) && std::isdigit(s2[0])) {
int n1, n2;
std::stringstream ss(s1);
ss >> n1;
ss.clear();
ss.str(s2);
ss >> n2;
if (n1 != n2) return n1 < n2;
it1 = std::find_if(s1.begin(), s1.end(), is_not_digit);
it2 = std::find_if(s2.begin(), s2.end(), is_not_digit);
}
return std::lexicographical_compare(it1, s1.end(), it2, s2.end());
}
然后......
std::sort(string_array.begin(), string_array.end(), numeric_string_compare);
编辑:当然,这个算法只有在排序数字部分出现在字符串开头的字符串时才有用。如果你正在处理数字部分可以在字符串中出现 where 的字符串,那么你需要一个更复杂的算法。有关详细信息,请参阅http://www.davekoelle.com/alphanum.html。
答案 1 :(得分:3)
如果您的目标是Windows(XP +)且能够将字符串转换为utf-16,则可以使用Shlwapi的StrCmpLogicalW
函数。有关详细信息,请参阅msdn。
否则,ICU在其合作者中提供此功能。请参阅UCOL_NUMERIC_COLLATION
。
答案 2 :(得分:2)
这是一个不转换为整数的版本,因此无论sizeof(int)如何都适用于长数字串。
#include <cctype>
#include <cstddef>
#include <cstring>
#include <string>
int numcmp(const char *a, const char *aend, const char *b, const char *bend)
{
for (;;) {
if (a == aend) {
if (b == bend)
return 0;
return -1;
}
if (b == bend)
return 1;
if (*a == *b) {
++a, ++b;
continue;
}
if (!isdigit((unsigned char) *a) || !isdigit((unsigned char) *b))
return *a - *b;
// skip leading zeros in both strings
while (*a == '0' && ++a != aend)
;
while (*b == '0' && ++b != aend)
;
// skip to end of the consecutive digits
const char *aa = a;
while (a != aend && isdigit((unsigned char) *a))
++a;
std::ptrdiff_t alen = a - aa;
const char *bb = b;
while (b != bend && isdigit((unsigned char) *b))
++b;
std::ptrdiff_t blen = b - bb;
if (alen != blen)
return alen - blen;
// same number of consecutive digits in both strings
while (aa != a) {
if (*aa != *bb)
return *aa - *bb;
++aa, ++bb;
}
}
}
int numcmp(const std::string& a, const std::string& b)
{
return numcmp(a.data(), a.data() + a.size(),
b.data(), b.data() + b.size());
}
int numcmp(const char *a, const char *b)
{
return numcmp(a, a + strlen(a), b, b + strlen(b));
}