C 程式設計/ctype.h
在 C 程式語言的 ANSI C 標準庫中,標題 ctype.h 包含字元分類函式的宣告。
早期的 C 語言工具開發者在 Unix 下開始快速開發習語來將字元分類成不同的型別。例如,在 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> 包含十幾個字元分類函式的原型。除 isdigit 和 isxdigit 外,所有這些函式都是特定於區域設定的;如果區域設定發生變化,它們的執行行為可能會改變。
| 測試 | 形式為 int isfunc(int);對於真返回非零數,對於假返回零。 |
|---|---|
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 型別是帶符號的,則從 char 到 int 的隱式轉換可能會生成負值,導致未定義的行為。這通常意味著,如果引數用作查詢表的索引,它將訪問超出正確表的區域,甚至可能使程式崩潰。
使用 char 引數的正確方法是在檢查 EOF 條件後先將它們強制轉換為 unsigned char。
getchar、getc 和 fgetc 返回的 int 型別的值保證在 unsigned char(或 EOF)的範圍內,因此在這些情況下不需要強制轉換。