你可以使用這一節的函式來執行字串和陣列內容的比較,而且為了檢查字串的相等,這些函式也用做排序操作函式,見 Searching and Sorting,有一個例子。
不像C語言裡多數的比較運算,假如字串不相等,字串的比較函式會傳回非零值,這個表示值說明不相同的字串裡第一個字元的相對順序:負值表示第一個字串”小於”第二個字串,而正值表示第一個字串是 “較大的”。
最常使用的函式只是檢查相等,照規範使用這樣的表示式 ‘! strcmp (s1, s2)’。
— 函式: int memcmp (const void *a1, const void *a2, size_t size)
函式
memcmp
比較 a1 跟 a2 記憶體前面 size 個位元組,傳回值跟第一對不同的字元的差異有相同的符號(以unsigned char
物件表示,然後轉成int)。
假如這兩個記憶體內容相同時,
memcmp
傳回0。
— 函式: int wmemcmp (const wchar_t *a1, const wchar_t *a2, size_t size)
函式
wmemcmp
比較 a1 跟 a2 前面 size 個寬字元,傳回值小於零或大於零取決於 a1 第一個不同的寬字元小於或大於相對應的 a2 字元。假如這兩個記憶體內容相同時,
wmemcmp
傳回0。
對任意陣列來說, memcmp
函式在測試相等時相當有用,在陣列的內容上以逐字元順序而非位元組做比較通常比較沒有意義,例如,在以浮點數組成的位元組做逐字元的比較是不太可能告訴你你任何關於浮點數的值之間的關係。
wmemcmp
真的只有在型態 wchar_t
的陣列比較才有用,因為函式一次以 sizeof (wchar_t)
位元組來檢查,而位元組的數目取決於作業系統。
你也應該小心使用 memcmp
來比較含有“holes”的物件,像是新增到結構物件的不明確位置的區塊(padding)、在同構(unions)結尾的空間,以及長度小於配置的大小時的字串結尾多餘的字元,這些 “holes” 的內容是不確定的,而且在執行逐位元比較時會有奇怪的狀況發生,為了得到可預期的結果,執行明確的組件比較。
例如,給定一個結構型態定義像:
struct foo { unsigned char tag; union { double f; long i; char *p; } value; };
你最好寫一個特製的比較函式來比較 struct foo
物件而不是用 memcmp
來比較他們。
— 函式: int strcmp (const char *s1, const char *s2)
strcmp
函式比較字串 s1 跟 s2,傳回一個跟第一對不同字元差異的符號值(以unsigned char
物件表示,然後轉成int)。
假如兩個字串相同,
strcmp
傳回0。使用
strcmp
排序的結果就是假如 s1 原來是 s2一部分的字串,那麼 s1 會被認為 “小於” s2。
strcmp
不會考慮字串被寫入的語言排序規範,要那樣做必須使用strcoll。
— 函式: int wcscmp (const wchar_t *ws1, const wchar_t *ws2)
wcscmp
函式比較寬字元字串 ws1 跟 ws2,傳回值小於或大於零取決於第一個不同的寬字元是 ws1 小於或大於相對應的 ws2 字元。假如兩個字串相同,
wcscmp
傳回0。使用
wcscmp
排序的結果就是假如 ws1 原來是 ws2 一部分的字串,那麼 ws1 會被認為 “小於” ws2。
wcscmp
不會考慮字串被寫入的語言排序規範,要那樣做必須使用wcscoll。
— 函式: int strcasecmp (const char *s1, const char *s2)
這函式像
strcmp
,除了大小寫會忽略外,大小寫字元的關係如何由目前選擇的語系決定,在標準的"C"
語系中字元 Ä 跟 ä 不一樣,但是在把這些字元當成是字母的一部份的語系裡,他們是一樣的。
strcasecmp
是從 BSD 衍生出來的。
— 函式: int wcscasecmp (const wchar_t *ws1, const wchar_t *ws2)
這函式像
wcscmp
,除了大小寫的差異會忽略外,大小寫字元的關係如何由目前選擇的語系來決定,在標準的"C"
語系中字元 Ä 和 ä 不一樣,但是在把這些字元當成是字母的一部份的語系裡,他們是一樣的。
wcscasecmp
是 GNU 的擴充函式。
— 函式: int strncmp (const char *s1, const char *s2, size_t size)
這函式類似
strcmp
,除了不超過 size 個的字元被比較之外,換句話說,假如兩個字串前面 size 個字元是一樣的話,傳回值是零。
— 函式: int wcsncmp (const wchar_t *ws1, const wchar_t *ws2, size_t size)
這函式類似
wcscmp
,除了不超過 size 個的寬字元比較之外,換句話說,假如兩個字串前面 size 個寬字元是一樣的話,傳回值是零。
— 函式: int strncasecmp (const char *s1, const char *s2, size_t n)
這函式像
strncmp
,除了大小寫會被忽略之外,像strcasecmp
,它也是取決於語系來決定大小寫字元的關係。
strncasecmp
是 GNU 的擴充函式。
— 函式: int wcsncasecmp (const wchar_t *ws1, const wchar_t *s2, size_t n)
這函式像
wcsncmp
,除了大小寫會被忽略之外,像wcscasecmp
,它也是取決於語系來決定大小寫字元的關係。
wcsncasecmp
是 GNU 的擴充函式。
這裡有一些例子顯示 strcmp
和 strncmp的使用(相同的例子可以建構於寬字元的函式)這些範例假設使用
ASCII 字元集,(假如改用其他的字元集–如 EBCDIC,那麼字型會有不同數值碼,傳回的值跟順序也會不同。)
strcmp ("hello", "hello") ⇒ 0 /* These two strings are the same. */ strcmp ("hello", "Hello") ⇒ 32 /* Comparisons are case-sensitive. */ strcmp ("hello", "world") ⇒ -15 /* The character'h'
comes before'w'
. */ strcmp ("hello", "hello, world") ⇒ -44 /* Comparing a null character against a comma. */ strncmp ("hello", "hello, world", 5) ⇒ 0 /* The initial 5 characters are the same. */ strncmp ("hello, world", "hello, stupid world!!!", 5) ⇒ 0 /* The initial 5 characters are the same. */
— 函式: int strverscmp (const char *s1, const char *s2)
strverscmp
函式比較字串 s1 跟 s2,但會考慮裡面的索引/版本數字,傳回值有跟strcmp
函式一樣的規範,事實上假如s1 和 s2 沒有數字,strverscmp
就像strcmp
一樣。基本上我們通常比較字串(逐字元),直到我們在字串裡發現數字 – 接著我們進入一個特殊比較模式,在這裡每個數字序列看成是一個數目,假如我們到達這兩個部份的最後沒有注意到差異,我們就會返回標準的比較模式,有兩種數值型態的部份:”整數的” 跟 “零數的” (以 ‘0’開始的數字),數值部份的型態會影響到我們排序它們的方式:
- 整數的/整數的:我們會如你預期的方式比較值。
- 零數的/整數的:零數的部份比整數的部份小,這也是我預期的。
- 零數的/零數的:這件事會變得有點複雜,如果常見的前綴只有零,最長的部份小於另一個;否則比較會是正常的。
strverscmp ("no digit", "no digit") ⇒ 0 /* same behavior as strcmp. */ strverscmp ("item#99", "item#100") ⇒ <0 /* same prefix, but 99 < 100. */ strverscmp ("alpha1", "alpha001") ⇒ >0 /* fractional part inferior to integral one. */ strverscmp ("part1_f012", "part1_f01") ⇒ >0 /* two fractional parts. */ strverscmp ("foo.009", "foo.0") ⇒ <0 /* idem, but with leading zeroes only. */這函式在處理檔案名稱的排序時特別有用,因為檔案名稱通常會有索引/版本數。
strverscmp
是 GNU 的擴充函式。
下一節: Collation Functions,上一節: Copying and Concatenation,這一章:字串和陣列的工具