跳轉到內容

C 程式設計/ctype.h

來自華夏公益教科書,開放的書籍,構建開放的世界

在 C 程式語言的 ANSI C 標準庫中,標頭檔案 ctype.h 包含字元分類函式的宣告。

早期在 Unix 下使用 C 語言的工具匠們開始以驚人的速度開發習語來將字元分類為不同的型別。例如,在 ASCII 字元集中,以下測試可以識別字母

if ('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z')

但是,此習語不一定適用於其他字元集,如 EBCDIC。

很快,程式中就充斥著類似上述測試,甚至更糟,幾乎與上述測試相同的測試。程式設計師可以以多種不同的方式編寫相同的習語,這會減慢理解速度並增加出錯的機會。

不久後,這些習語就被中的函式取代了<ctype.h>.

與上面的示例不同,字元分類例程不是以比較測試的方式編寫的。在大多數 C 庫中,它們是以靜態表查詢的方式編寫的,而不是宏或函式。

例如,可以建立一個包含 256 個 8 位整數的陣列,並將其排列為位域,其中每個位對應於字元的特定屬性,例如 isdigit、isalpha。如果整數的最低有效位對應於 isdigit 屬性,則程式碼可以這樣編寫

#define isdigit(x) (TABLE[x] & 1)

早期版本的 Linux 使用了類似第一個程式碼示例的潛在錯誤方法

#define isdigit(x) ((x) >= '0' && (x) <= '9')

如果以下情況,這可能會導致問題x有副作用——例如,如果呼叫isdigit(x++)isdigit(run_some_program()). 不會立即顯而易見的是,對isdigit的引數進行了兩次求值。出於這個原因,通常使用基於表的方。

<ctype.h> 的內容

[編輯 | 編輯原始碼]

<ctype.h> 包含十二個字元分類函式的原型。除了 isdigitisxdigit 之外,所有這些函式都是特定於語言環境的;它們的執行行為可能會隨著語言環境的更改而更改。

測試 int isfunc(int); 的形式
對 true 返回非零數,對 false 返回零。
isalnum 測試字母數字字元
isalpha 測試字母字元
isblank 測試空白字元(C99 中新增)
iscntrl 測試控制字元
isdigit 測試數字。不特定於語言環境。
isgraph 測試圖形字元,不包括空格字元。
islower 測試小寫字母字元
isprint 測試可列印字元,包括空格字元。
ispunct 測試標點符號字元
isspace 測試任何空白字元
isupper 測試大寫字母字元
isxdigit 測試十六進位制數字。不特定於語言環境。
字元轉換 int tofunc(int); 的形式
返回轉換後的字元,除非它不是字母。
tolower 將字元轉換為小寫字母
toupper 將字元轉換為大寫字母

單一 Unix 規範版本 3 添加了類似於上述的函式

isascii 測試引數是否在 0 到 127 之間
toascii 將字元轉換為 ASCII

不正確的用法

[編輯 | 編輯原始碼]

標準規定(§7.4-1)

在所有情況下,引數都是一個 int,其值應可表示為一個 unsigned char 或等於宏 EOF 的值。如果引數具有任何其他值,則行為未定義。

不幸的是,許多程式設計師忘記了 char 型別可能是帶符號的或無符號的,具體取決於實現。如果 char 型別是有符號的,則從 charint 的隱式轉換可能會生成負值,從而導致未定義的行為。這通常意味著如果引數用作查詢表的索引,它將訪問正確表之外的區域,甚至可能導致程式崩潰。

使用 char 引數的正確方法是在檢查 EOF 條件後先將其轉換為 unsigned char

getchargetcfgetc 返回的 int 型別值保證在 unsigned char(或 EOF)的範圍內,因此在這些情況下不需要轉換。

[編輯 | 編輯原始碼]
華夏公益教科書