2012-12-29 50 views
10

我試圖理解他們倆但strcoll()this參考說它strcmp()和strcoll()之間有什麼區別?

比較根據當前區域設置兩個空終止字符串由LC_COLLATE類別定義我沒有找到除任何差異。

關於第二個想法,我知道我問另一個問題的詳細答案,這個區域設置是什麼,對於C和C++?

+10

的[例如這裏(http://en.cppreference.com/w/cpp/string/byte/strcoll)在我看來很清楚。 – Rapptz

+0

@Rapptz ...哎呀...應該看到鏈接....在發佈之前... – Recker

+0

hrnec before chrt :) +1 – davak

回答

25

strcmp()由一個取一個字符串的字節並且是無論字節是對它們進行比較。

strcoll()需要的字節數,使用語言環境轉換它們,然後將結果進行比較。轉換根據語言重新排序。在法語中,突出的字母出現在非加重字母之後。所以之後是e。但是,之前是fstrcoll()正確。 strcmp()不太好。

然而,在許多情況下strcmp()是不夠,因爲你並不需要顯示在使用的語言(區域)排序結果。例如,如果您只需要快速訪問由字符串索引的大量數據,則可以使用由該字符串索引的映射。這可能是完全無用的排序使用strcoll()一般是非常慢(相比於strcmp()至少)

有關,你可能還需要檢查出Unicode網站字符的詳細信息的。

關於語言環境,這是語言。默認情況下它被設置爲「C」(或多或少,沒有語言環境)。一旦你選擇一個位置,相應地設置區域設置。您也可以設置LC_LOCALE環境變量。實際上有很多這樣的變量。但通常情況下,您會使用預定義的函數自動將這些變量考慮在內,併爲您做正確的事情。 (即格式化日期/時間,格式編號/度量,計算大小寫等)

+1

+1此答案中的字符比較樣本非常好地呈現,尤其是「然而,é在f之前。」例。同樣,有關使用'strcmp()'進行內部排序管理和顯示的說明同樣做得很好。有一些簡潔而且容量很大的答案,我希望我可以不止一次地對它們進行投票。這是其中之一。 – WhozCraig

2

由於某些原因,在我測試的所有unicode語言環境中,幾個不同版本的glibc中,strcoll()平假名。這打破了排序,uniq,以及以某種方式與字符串順序交互的一切。

$ echo -e -n'い\ nろ\ nは\ nに\ nほ\ nへ\ nと\ n'排序| uniq的

這簡直是壞無法修復。來自世界不同地方的人可能對'い'應該放在'ろ'之前還是之後有不同的想法,但是沒有人會認爲它們是相同的。

不,你的區域設置了日本一個無關緊要:

$ LC_ALL = ja_JP.utf8 LANG = ja_JP.utf8 LC_COLLATE = Ja_JP表示。utf8 echo -e -n'い\ nろ\ nは\ nに\ nほ\ nへ\ nと\ n'|排序| uniq的

有一些官方的郵件列表討論,但你猜怎麼着,那是在2002年,它被永遠定格,因爲人們不關心:https://www.mail-archive.com/[email protected]/msg02658.html

這個bug發生我們在一天之內,最後我們唯一的出路是將collat​​e locale設置爲「C」,並依靠utf-8編碼的優良屬性。這是一個非常糟糕的經歷,因爲在處理全日文數據時,不應該在「C」語言環境下真正工作。

因此,爲了您的理智,不要直接使用strcoll。一個更安全的變體可能是:

int safe_strcoll(const char *a, const char *b) 
{ 
    int ret = strcoll(a, b); 
    if (ret != 0) return ret; 
    return strcmp(a, b); 
} 

以防萬一的strcoll()決定擰你...

+1

我很幸運發現問題。你的環境改變只適用於'echo'。你應該把語言的變化應用到'sort'和'uniq';最簡單的就是'輸出LANG'。它可以很好地工作:'(export LANG = ja_JP.UTF-8; echo -e -n'い\ nろ\ nは\ nに\ nほ\ nへ\ nと\ n'| sort | uniq)' 。 – qsantos

+1

謝謝你指出。除了第一次做這個實驗時,我實際上正在使用export LANG = ja_JP.UTF-8。我在多臺機器上再次嘗試,並且仍然可以在一些但不是全部的問題中重現問題。 我想我需要進一步挖掘導致差異的原因。 glibc版本似乎不是我需要控制的唯一變量... –

相關問題