初學者編寫單詞統計程序時,常因循環變量初始化順序錯誤、字符讀取邏輯缺陷導致程序無法正確處理輸入。本文通過一個典型錯誤案例,逐行剖析問題根因,提供修正版代碼並講解核心知識點。
#include <stdio.h>
int main() {
int ch, i, count = 0, flag = 0;
char bb[1000];
printf("please input some words:");
gets(bb); // 危險函數,已棄用
ch = bb[i]; // 【錯誤1】i 未初始化,訪問 bb[i] 行為未定義
for (i = 0; ch != '\0'; i++) { // 【錯誤2】循環條件使用舊 ch,未在循環內更新
if (ch == ' ') flag = 0;
else if (flag == 0) { count++; flag = 1; }
}
printf("單詞個數為%d", count);
}
int i; 未賦值,ch = bb[i] 讀取隨機內存地址,導致未定義行為。ch 在循環外賦值一次,循環內從未更新,導致要么不進循環,要么死循環,完全脫離輸入數據。gets() 不檢查緩衝區邊界,極易造成緩衝區溢出,C11 標準已移除,必須改用 fgets()。#include <stdio.h>
#include <string.h>
int main() {
char bb[1000];
int count = 0, flag = 0;
printf("please input some words: ");
// 安全讀取:指定最大長度,自動處理換行符
if (fgets(bb, sizeof(bb), stdin) == NULL) return 1;
// 遍歷字符串每個字符
for (int i = 0; bb[i] != '\0'; i++) {
char ch = bb[i]; // 關鍵:在循環內獲取當前字符
if (ch == ' ' || ch == '\t' || ch == '\n') {
flag = 0; // 遇到分隔符,重置標誌
} else if (flag == 0) {
count++; // 發現新單詞首字符
flag = 1; // 設置標誌,跳過單詞後續字符
}
}
printf("單詞個數為 %d\n", count);
return 0;
}
程序維護一個二狀態變量 flag:
flag = 0:當前處於「非單詞內」(分隔符或開頭)flag = 1:當前處於「單詞內」狀態轉移:分隔符 → 置 0;非分隔符且 flag=0 → 計數+1、置 1;非分隔符且 flag=1 → 保持。這是處理字符流分詞的經典模式,廣泛用於詞法分析。
strchr(" \t\n.,;!?", ch))