在 C 語言開發中,字元與字串操作是基礎且高頻的任務。標準庫提供了豐富的函數來處理字元分類、大小寫轉換、字串複製、比較、搜尋以及記憶體操作。本文系統整理了 ``、``、`` 三大標頭檔中的核心函數,並按功能分類,方便開發者快速查閱與選用。
一、字元分類與轉換函數 (``)
這些函數接受 `int` 參數(通常為 `unsigned char` 或 `EOF`),返回非零值表示真,零表示假。常用於輸入驗證、文字解析等場景。
1. 字元類型判斷
- isalnum(c):判斷是否為字母或數字(A-Z, a-z, 0-9)。
- isalpha(c):判斷是否為字母(A-Z, a-z)。
- iscsym(c):判斷是否為字母、底線或數字(識別字元首字元)。
- iscsymf(c):判斷是否為字母或底線(識別字元首字元,非標準)。
- isdigit(c):判斷是否為十進位數字(0-9)。
- isxdigit(c):判斷是否為十六進位數字(0-9, A-F, a-f)。
- islower(c):判斷是否為小寫字母。
- isupper(c):判斷是否為大寫字母。
- ispunct(c):判斷是否為標點符號。
- isspace(c):判斷是否為空白字元(空格、換行、定位鍵等)。
- isgraph(c):判斷是否為可列印且非空白字元。
- isascii(c):判斷是否為 ASCII 字元(0-127)。
2. 大小寫轉換
- toascii(c):將字元轉換為 ASCII(僅保留低 7 位)。
- tolower(c):將大寫字母轉為小寫,其他字元不變。
- toupper(c):將小寫字母轉為大寫,其他字元不變。
二、字串與數值轉換函數 (``)
用於字串與數值類型之間的雙向轉換,是處理使用者輸入、配置檔解析的關鍵工具。
1. 字串轉數值
- atof(const char *nptr):轉換為 `double`。無錯誤回報機制。
- atoi(const char *nptr):轉換為 `int`。無錯誤回報。
- atol(const char *nptr):轉換為 `long`。無錯誤回報。
- strtod(const char *nptr, char **endptr):轉換為 `double`,`endptr` 指向解析結束位置,支援錯誤檢查。
- strtol(const char *nptr, char **endptr, int base):轉換為 `long`,支援指定進制(2-36),健壯性最佳。
- strtoul(const char *nptr, char **endptr, int base):轉換為 `unsigned long`。
2. 數值轉字串
- gcvt(double number, size_t ndigits, char *buf):將浮點數轉為字串(四捨五入),非標準函數,建議改用 `snprintf`。
三、字串操作函數 (``)
核心字串處理工具集,涵蓋複製、連接、比較、搜尋、切分等高頻操作。
1. 複製與連接
- strcpy(char *dest, const char *src):複製字串(含結束符),注意緩衝區溢位風險。
- strncpy(char *dest, const char *src, size_t n):複製前 n 個字元,不足補 `\0`,超出截斷(可能不以 `\0` 結尾)。
- strcat(char *dest, const char *src):追加字串到 `dest` 末尾,需確保空間足夠。
- strncat(char *dest, const char *src, size_t n):追加前 n 個字元,保證以 `\0` 結尾。
2. 比較與搜尋
- strcmp(const char *s1, const char *s2):字典序比較,返回 `<0, 0, >0`。
- strncmp(const char *s1, const char *s2, size_t n):比較前 n 個字元。
- strchr(const char *s, int c):尋找字元 `c` 首次出現位置,返回指標或 `NULL`。
- strrchr(const char *s, int c):尋找字元 `c` 最後一次出現位置。
- strstr(const char *haystack, const char *needle):尋找子字串首次出現位置。
- strpbrk(const char *s1, const char *s2):尋找 `s2` 中任一字元在 `s1` 首次出現位置。
3. 字串切分與跨度計算
- strtok(char *s1, const char *s2):按 `s2` 中字元分割 `s1`,非執行緒安全,修改原字串。現代建議用 `strtok_r` 或 C++ `stringstream`。
- strcspn(const char *s1, const char *s2):返回 `s1` 開頭不含 `s2` 任一字元的長度。
- strspn(const char *s1, const char *s2):返回 `s1` 開頭僅含 `s2` 字元的長度。
四、記憶體操作函數 (``)
處理任意二進位資料塊,不以 `\0` 判斷結尾,需指定長度 `n`。
- memcpy(void *dest, const void *src, size_t n):複製記憶體區塊,來源與目的不可重疊。
- memmove(void *dest, const void *src, size_t n):安全複製,支援重疊區塊。
- memcmp(const void *s1, const void *s2, size_t n):比較記憶體區塊,返回 `<0, 0, >0`。
- memchr(const void *s, int c, size_t n):在記憶體區塊中尋找字元 `c`。
- memset(void *s, int c, size_t n):將記憶體區塊設定為指定字元值(常用於初始化結構體/陣列為 0)。
五、其他實用函數
- strlen(const char *s):計算字串長度(不含 `\0`),時間複雜度 O(n)。
- strerror(int errnum):將錯誤碼轉換為人類可讀的錯誤訊息字串。
最佳實踐提醒
- 安全優先:優先使用 `strncpy`、`strncat`、`snprintf` 等帶長度限制的函數,避免緩衝區溢位。
- 記憶體重疊:涉及記憶體搬移時,優先選 `memmove` 而非 `memcpy`。
- 執行緒安全:避免使用 `strtok`,改用 `strtok_r` (POSIX) 或 C++ 標準庫。
- 字元編碼:上述函數針對單位元組字元集(ASCII/擴展 ASCII),處理 UTF-8 等多位元組編碼時需使用專用庫(如 ICU)。
掌握這些函數的特性、限制與適用場景,能顯著提升 C 語言文字處理代碼的健壯性與效率。建議配合編譯器警告(如 `-Wstringop-overflow`)與靜態分析工具使用。