Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
strcmp返回意外结果_C_Char_Strcmp - Fatal编程技术网

strcmp返回意外结果

strcmp返回意外结果,c,char,strcmp,C,Char,Strcmp,我认为如果第一个字符串大于第二个字符串,strcmp应该返回一个正数。但是这个节目 #include <stdio.h> #include <string.h> int main() { char A[] = "A"; char Aumlaut[] = "Ä"; printf("%i\n", A[0]); printf("%i\n", Aumlaut[0]); printf("%i\n", strcmp(A, Aumlaut));

我认为如果第一个字符串大于第二个字符串,strcmp应该返回一个正数。但是这个节目

#include <stdio.h>
#include <string.h>

int main()
{
    char A[] = "A";
    char Aumlaut[] = "Ä";
    printf("%i\n", A[0]);
    printf("%i\n", Aumlaut[0]);
    printf("%i\n", strcmp(A, Aumlaut));
    return 0;
}
#包括
#包括
int main()
{
字符A[]=“A”;
char Aumlaut[]=“Ä”;
printf(“%i\n”,A[0]);
printf(“%i\n”,Aumlaut[0]);
printf(“%i\n”,strcmp(A,Aumlaut));
返回0;
}
打印
65
-61
-1

为什么??有什么我忽略的吗?
我想也许我作为UTF-8保存的事实会影响一些事情。。你知道,因为那里的
Ä
由两个字符组成。但是保存为8位编码并确保字符串的长度都为1并没有帮助,最终结果是相同的。
我做错了什么


在32位Linux下使用GCC4.3,以防万一。

strcmp
和其他字符串函数实际上不支持utf。在大多数posix机器上,C/C++
char
在内部是utf8,这使得大多数东西在读写方面“正常工作”,并提供了一个库理解和操作utf代码点的选项。但是默认的
string.h
函数不区分区域性,并且不知道如何比较utf字符串。您可以查看strcmp的源代码,自己看看,这是一个尽可能幼稚的实现(这意味着它也比国际化感知比较函数更快)


我刚才回答了这个问题,你需要使用一个UTF感知的字符串库,比如IBM的优秀的.< /P> < P>保存为一个8位ASCII编码,<代码> 'A'=65 和<代码> '< /代码>等于任何- 61,如果你认为它是<代码>无符号char 。无论如何,

“Ä”
是严格的正值,大于2^7-1,您只是将其打印为签名


如果你认为<代码> 'Auth' <代码>是一个<代码>无符号char <代码>(它是),它的值在你的字符集中为195。因此,

strcmp(65195)
正确地报告
-1

strcmp()将字符作为无符号ASCII值。所以,你的双点A不是char-61,而是char-195(如果我的数学计算错了,可能是196)。

查看strcmp手册:

The strcmp() function compares the two strings s1 and s2. It returns
an integer less than, equal to, or greater than zero if s1 is found,
respectively, to be less than, to match, or be greater than s2.

当输入字符集超过 UTF8您应该使用标准库的宽字符功能 字符串和i/o。你的计划应该是:

#include <wchar.h>
#include <stdio.h>

int main()
{
    wchar_t A[] = L"A";
    wchar_t Aumlaut[] = L"Ä";
    wprintf(L"%i\n", A[0]);
    wprintf(L"%i\n", Aumlaut[0]);
    wprintf(L"%i\n", wcscmp(A, Aumlaut));
    return 0;
}
#包括
#包括
int main()
{
wchar_t A[]=L“A”;
wchar_t Aumlaut[]=L“Ä”;
wprintf(L“%i\n”,A[0]);
wprintf(L“%i\n”,Aumlaut[0]);
wprintf(L“%i\n”,wcscmp(A,Aumlaut));
返回0;
}

然后给出正确的结果(GCC 4.6.3)。您不需要特殊的库。

strcmp和类似的比较函数将字符串中的字节视为
无符号字符
s,如第7.24.4节第1点(C99中的was 7.21.4)中的标准所规定

比较函数memcmp、strcmp和strncmp返回的非零值的符号由第一对字符(均解释为无符号字符)值之间的差值符号确定,这些字符在被比较的对象中不同

(我的重点)


原因可能是这样的解释保持了普通编码中代码点之间的顺序,而将它们解释为s符号的
char
s则不然。

我意识到-这就是为什么我说我还尝试保存在另一个charset(本例中为Windows-1252)中,
是一个值为-60的char。但这没有帮助,它仍然打印-1。你是说
strcmp
将其参数视为未签名字符吗?我从来没有读过这方面的任何东西。@MrLister:没有。我是说它的实现定义了
char
是真正的
signed char
还是
unsigned char
。在您的例子中,它似乎是
无符号字符
,但您正在使用
%i
打印它的值。告诉
printf()。当它的参数确实是<代码>无符号char < /代码>时,告诉Prtff()将它的参数视为<代码>签名INT/COM>。使用正确的格式说明符,在本例中为
%c
。否。这是:
printf(“%u%u%u\n”),(无符号字符)‘Ä’,(有符号字符)‘Ä’,(字符)‘Ä’
将为无符号字符打印196,但为其他两个字符打印4294967236,证明(字符)与(有符号字符)具有相同的标识。这很有趣,因为将值强制转换为大小相等的整数类型不会影响输出。此外,4294967236不能用8位表示。您使用了错误的格式说明符。请尝试
%c
以获得正确的结果。@Philip好的,那么您如何在实现中显示字符已签名?我不在乎。编辑:只要我在2的补码机上。但它并没有说-60大于65。这就是我问这个问题的原因。它说-1,因为字符串“A”小于“Ä”。您之所以看到-61,是因为您只打印“Ä”字符串的第一个字节。但是为什么呢?@MrLister在iso-8859-1或Windows-1252等8位编码中,代码点编号为0-255。将字符串的内容视为
无符号字符
会保留代码点的顺序,而将其视为有符号字符则不会。类似地,对于utf-8这样的编码,当将字节视为无符号时,更高的unicode码点数会产生按字典顺序排列的更大字节序列,而当将字节视为有符号时则不会。可能这就是strcmp使用无符号字符的原因。@DanielFischer是有意义的。你是说它甚至不依赖于实现?哦,好吧,我想我可以接受这一点,但我真的很感激如果手册上有