| 函數 | 功能 | 返回值 |
isalpha(c) | 判斷是否字母 | 非零/零 |
isupper(c) | 判斷是否大寫字母 | 非零/零 |
islower(c) | 判斷是否小寫字母 | 非零/零 |
toupper(c) | 轉為大寫 | 轉換後的字符(int) |
tolower(c) | 轉為小寫 | 轉換後的字符(int) |
關鍵規範:這些函數參數為 int,值必須是 unsigned char 範圍(0-255)或 EOF。直接傳入 char 可能導致負值未定義行為,正確用法:
char ch = ...;
if (isalpha((unsigned char)ch)) { ... }
ch = toupper((unsigned char)ch);
標準實現代碼
#include <stdio.h>
#include <ctype.h>
int main(void) {
int ch; // 用 int 接收 getchar 返回值,兼容 EOF
while ((ch = getchar()) != EOF && ch != '#') {
if (isalpha((unsigned char)ch)) {
if (isupper((unsigned char)ch)) {
ch = tolower((unsigned char)ch);
} else {
ch = toupper((unsigned char)ch);
}
}
putchar(ch);
}
return 0;
}
關鍵細節深度解析
1. 循環條件的運算符優先級陷阱
// 錯誤寫法:>> 結合性導致邏輯錯誤
while (ch = getchar() != '#') // 實際解析為:ch = (getchar() != '#')
// 正確寫法:顯式括號
while ((ch = getchar()) != '#')
!= 優先級高於 =,必須加括號確保先賦值再比較。
2. 為什麼不用 freopen 重定向?
題目要求交互式輸入輸出,重定向到文件會導致無法看到提示、無法手動輸入結束符 #。保持標準輸入輸出最穩妥。
3. putchar vs printf
putchar(ch):單字符輸出,無格式解析開銷,返回寫入字符或 EOF
printf("%c", ch):功能重疊但較重,適合格式化輸出
4. 處理非 ASCII 字符
標準 ctype.h 函數行為依賴于當前 locale(setlocale)。中文環境下對中文字符通常返回 0(非字母),保持原樣輸出,符合題意。
測試用例
| 輸入 | 輸出 | 說明 |
Hello World! 123# | hELLO wORLD! 123 | 樣例 |
ABCxyz# | abcXYZ | 純字母 |
12345# | 12345 | 純數字 |
!@#$%^&*()# | !@#$%^&*() | 特殊符號 |
a# | A | 單字符 |
常見錯誤總結
- 忘記
(unsigned char) 轉換 → 未定義行為
- 循環條件缺少括號 → 邏輯錯誤
- 用
char ch 接收 getchar() → 無法檢測 EOF(-1)
- 輸出包含
# → 未正確終止循環
- 使用自定義 ASCII 運算(
ch ^ 32) → 不可移植,依賴 ASCII 編碼
熟練使用 ctype.h 是 C 語言處理文本的基本功,標準庫函數兼顧可移植性、正確性與可讀性。
- 上一篇文章: PAT 06-1 簡單計算器:左到右等優先級四則運算解題詳解
- 下一篇文章: C語言技巧:通過成員地址反推結構體首地址(container_of 宏原理)
Copyright ©
程式碼之家 All Rights Reserved