關於C語言中漢字排序的問題?

今天做到一個題,要求輸入學生名字以及成績並進行相應操作。其中一個小題是讓以姓名的字典順序排序,經查詢後得知可以strcmp實現,因此想請問一下漢字排序的原理是什麼?


這個和漢字的編碼方式有關,gb2312下一級漢字確實是按拼音排序,二級漢字按照偏旁部首排序;日文shiftjis的一級漢字是按漢字的最常用音讀(音讀不常用的漢字則用其最常用的訓讀)五十音排序,二級漢字則是按偏旁部首;而至於unicode,它的排序是完全無視其讀音的。

中國人名排序還有個問題,有時候會出現本來讀音相同或相似的漢字卻在不同區域,比如」鍾「和」鍾「讀音相似,但後者卻在gbk擴展區,碼位十萬八千里;大多數「閆」都是「閻」家的,但「閻」是一級漢字,「閆」是二級漢字。還有,就算在一級漢字區,其根據的讀音不一定是其漢字做姓氏時的讀音。比如大多數「肖」都是「蕭」家的,但gb2312里後者排在前者前面,當是取了「不肖」那個讀音。


Windows API:

int CompareString(
_In_ LCID Locale,
_In_ DWORD dwCmpFlags,
_In_ LPCTSTR lpString1,
_In_ int cchCount1,
_In_ LPCTSTR lpString2,
_In_ int cchCount2
);

支持指定 locale 的字元串比較,選擇

LANG_CHINESE_SIMPLIFIEDSUBLANG_CHINESE_SIMPLIFIED

作為locale id就是拼音排序了


Unicode 的漢字是部首排序的,而且用的是康熙字典的部首……

所以還是老老實實上 unihan 的資料庫吧


並不完全正確。只有GB2312編碼的一級編碼情況下,因為漢字編碼等長,且編碼表本身大體都是按照拼音排序的,才可以如此。二級編碼就已經是按照部首排序了。GBK因為兼容GB2312,情況類似。若是utf8等unicode表達就更不同了……


你要遇到多音字還排個毛線啊……

其實就按Unicode或者GBK排序得了,或者Windows API。只要排列順序是固定的就好。一般也沒人在乎那個順序到底是不是嚴格按拼音吧……


我在項目中一般用 setlocale + strcoll:

#include &
#include &
#include &
#include &
#include &

int strcoll_wrapper(const void *v1, const void *v2)
{
const char **s1 = (const char **)v1;
const char **s2 = (const char **)v2;

assert(v1 != NULL);
assert(v2 != NULL);

return strcoll(*s1, *s2);
}

int main(void)
{
int i = 0;
const char *names[] = {
"趙",
"錢",
"孫",
"李",
};

setlocale(LC_COLLATE, "");

qsort(names, 4, sizeof(names[0]), strcoll_wrapper);

for (i = 0; i &< sizeof(names)/sizeof(names[0]); i++) puts(names[i]); return 0; } // References: //http://www.anyexample.com/programming/c/qsort__sorting_array_of_strings__integers_and_structs.xml

----


全英文的話,可以用strcmp,因為ascii碼錶中的英文字元是有序的,"c" &> "b" 是成立的

中文就不行了,很多編碼如utf-8里的中文字元並不是按字典順序排的,比如 "吧" &> "啊" 是不成立的,因此需要先轉化成拼音,然後再排序


姓名排序可不是個簡單的計算問題,老羅專門做了一個姓名多音字的通訊錄排表,可以借鑒下。

如果只是完成作業的話也可以降低點要求,GB國標中有獲得漢字拼音的方法,然後變成漢語拼音的字元串排序問題就好了。


原理是出題者以為漢字是ASCII編碼了


看你用什麼方法排序了

strcmp本質上是比較2進位數值

那麼顯然就和當前字元串里漢字的編碼有關係


推薦閱讀:

LABVIEW 有哪些反人類的編程特性?
c++類成員變數為什麼不能做成員函數的默認實參?
VR 時代的主流編程語言是什麼?
C++/C/JAVA/Python之間的區別?

TAG:編程語言 | 編程 | C編程語言 | C語言函數 |