拥有strcmp功能 - 非标准字符

时间:2013-01-08 08:57:50

标签: c strcmp

我目前正在编写一个小排序功能。我只能使用stdio libary,所以我写了'自己的strcmp'函数。

int ownstrcmp(char a[], char b[])
{
   int i = 0;

   while( a[i] == b[i] )  
   {

      if( a[i] == '\0' ) 
        return 0;
      ++i;
   }

   return  ( a[i] < b[i]) ? 1 : -1;
}

这对我很有用。但是有一个小问题:我可以为'非标准字符'做些什么?像“ä,ü,ß”他们的十进制ASCII值大于正常的字符,因此它将'ääää'后面的字符串'example'排序。 我已经阅读过有关语言环境的内容,但我可以使用的唯一库是stdio.h。这个问题有一个“简单”的解决方案吗?

5 个答案:

答案 0 :(得分:1)

您需要知道字符所在的编码,并确保正确处理字符串。如果编码是多字节的,则必须开始读取(和比较)单个字符,而不是字节。

此外,比较国际字符的方式因语言环境而异,没有单一的解决方案。在某些语言中,'ä'在'z'之后排序,有些语言在'a'旁边排序。

实现这一点的一个简单方法当然是创建一个表,其中包含每个字符的相对顺序,如下所示:

unsigned char character_order[256];

character_order[(unsigned char) 'a'] = 1;
character_order[(unsigned char) 'ä'] = character_order[(unsigned char) 'a'];
/* ... and so on ... */

然后,您不是减去角色的编码值(不再可以用作角色排序顺序的“代理”),而是比较character_order值。

上面假设是单字节编码,即Latin-1或其他东西,因为数组大小只有256个。

还要注意在使用字符文字进行索引时转换为unsigned char

答案 1 :(得分:1)

你的问题有些模糊。首先,如何表示变音符号的字符取决于您的编码。例如,我的计算机的语言环境设置为希腊语,这意味着我用希腊字符代替那些特殊的拉丁字符。就我所知,你不能假设这样的事情。

其次,您的问题的答案取决于您的陈述。你还在使用“每个char一个字符”吗?如果是这样,上面的代码可能仍然有用。

如果您使用多个char表示形式,例如每个字符两个char,则应更改代码,以便在连续两次 {{1 } {s}是char

通常,您可能希望了解\0及其函数族(具体为wchar_t)的实现方式。

答案 2 :(得分:1)

对于德语,变音符号ä,ö,ü和ß将按其“扩展”形式进行排序:

ä -> ae
ö -> oe
ü -> ue
ß -> ss

为了根据标准获得排序规则,您可以在比较之前扩展字符串。

答案 3 :(得分:0)

如果您使用的是ISO/IEC_8859-16编码,这是德语的正常加入,那么将char转换为unsigned char就足够了。

这样,字符可以在区间0-255中表示,适用于此标准。

答案 4 :(得分:0)

根据您的代码,在UTF8下,这可以提供帮助

if ((a[i] > 0) ^ (b[i] > 0))
    return a[i] > 0 ? 1 : -1;
else
    return a[i] < b[i] ? 1 : -1;

但您必须检查ownstrcmp("ab", "abc");

等案例

此外,您的代码与strcmp()

中的<string.h>不同

大于零的值表示第一个不匹配的字符在str1中的值大于在str2中的值;小于零的值表示相反。

我会这样做:

int ownstrcmp(char a[], char b[])
{
    int i = 0;

    while(a[i] == b[i]) {
        if (a[i] == 0) return 0;
        ++i;
    }
    if ((a[i] == 0) || (b[i] == 0))
        return a[i] != 0 ? 1 : -1;
    if ((a[i] > 0) ^ (b[i] > 0))
        return a[i] < 0 ? 1 : -1;
    else
        return a[i] > b[i] ? 1 : -1;
}