簡體   English   中英

strcmp返回意外結果

[英]strcmp returning unexpected results

我認為如果第一個字符串大於第二個字符串,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;
}

打印65-61-1

為什么? 我有什么東西可以俯瞰嗎?
我認為也許我保存為UTF-8的事實會影響事情。你知道因為Ä由2個字符組成。 但是保存為8位編碼並確保字符串都具有長度1沒有幫助,最終結果是相同的。
我究竟做錯了什么?

在這里使用32位Linux下的GCC 4.3,以防萬一。

strcmp和其他字符串函數實際上並不知道。 在大多數posix機器上,C / C ++ char在內部是utf8,這使得大多數東西在讀取和寫入方面“正常工作”,並提供了庫理解和操作utf代碼點的選項 但是默認的string.h函數對文化不敏感,並且對比較utf字符串一無所知。 您可以查看strcmp的源代碼並親眼看看,這是一個盡可能天真的實現(這意味着它也比國際化感知的比較函數更快)。

我剛才在另一個問題中回答了這個問題 - 您需要使用支持UTF的字符串庫,例如IBM出色的ICU - Unicode的國際組件

保存為8位ASCII編碼, 'A' == 65'Ä'等於-61,如果你認為它是unsigned char 無論如何, 'Ä'是嚴格正面的並且大於2 ^ 7-1,你只是打印它就像簽名一樣。

如果你認為'Ä'unsigned char (它是),它的字符集中的值為195。 因此, strcmp(65, 195)正確報告-1

strcmp()將字符作為無符號ASCII值。 所以,你的A-with-double-dots不是char -61,它是char 195(或者196,如果我的數學錯了)。

strcmp和類似的比較函數將字符串中的字節視為unsigned char s,如第7.24.4節第1點(C99中的7.21.4)中的標准所規定

比較函數memcmp,strcmp和strncmp返回的非零值的符號由所比較的對象中不同的第一對字符(均被解釋為unsigned char)的值之間的差異的符號確定。

(強調我的)。

原因可能是這樣的解釋維持了常見編碼中代碼點之間的順序,而將它們解釋為簽名char則不然。

檢查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時在C中正確執行字符串處理,您應該使用標准庫的字符串和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;
}

然后它將給出正確的結果(GCC 4.6.3)。 您不需要特殊的庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM