輸入一行字符串,統計其中單詞的個數。單詞定義為:由非空格字符構成的連續序列,單詞間由一個或多個空格分隔。
維護一個狀態變量 word:
word = 0:當前處於「非單詞內」(剛過空格或剛開始)word = 1:當前處於「單詞內」狀態 0 (非單詞內) ── 讀到非空格 ──→ 狀態 1 (單詞內), count++ 狀態 1 (單詞內) ── 讀到空格 ──→ 狀態 0 (非單詞內) 狀態 1 (單詞內) ── 讀到非空格 ──→ 狀態 1 (單詞內) 狀態 0 (非單詞內) ── 讀到空格 ──→ 狀態 0 (非單詞內)
#include <stdio.h>
#include <string.h>
int main(void) {
char string[100];
int num = 0; // 單詞計數
int word = 0; // 狀態標誌:0=非單詞內,1=單詞內
int i;
char c;
printf("請輸入一行字符串:\n");
if (fgets(string, sizeof(string), stdin) == NULL) {
return 1;
}
// 移除 fgets 可能讀入的換行符
string[strcspn(string, "\n")] = '\0';
for (i = 0; (c = string[i]) != '\0'; ++i) {
if (c == ' ') {
word = 0; // 遇到空格,重置狀態
} else if (word == 0) { // 遇到非空格且之前不在單詞內
word = 1; // 進入單詞狀態
++num; // 單詞計數 +1
}
// else: 非空格且 word==1,繼續在單詞內,不計數
}
printf("這串字符中有單詞 %d 個\n", num);
return 0;
}
fgets 而非 gets?gets 已從 C11 標準中移除,極度不安全(無緩衝區長度檢查,必導致緩衝區溢出)fgets 可指定最大讀取長度,包含換行符需手動移除#include <ctype.h>
// 將 if (c == ' ') 改為:
if (isspace((unsigned char)c)) { // isspace 需 unsigned char 避免 UB
word = 0;
}
可識別空格、制表符(\t)、換行符(\n)、垂直製表符(\v)、換頁符(\f)、回車符(\r)。
| 輸入 | 預期輸出 | 說明 |
|---|---|---|
Hello World | 2 | 基本情況 |
Hello World | 2 | 首尾及多重空格 |
One | 1 | 單詞 |
(空行) | 0 | 空輸入 |
| 0 | 純空格 |
Hello\tWorld\nTest | 3 | 多種空白字符(需 isspace) |
若需統計「單詞頻率」,可結合哈希表(如 uthash)或排序後計數;若處理超大文本流,可逐塊讀取並維護跨塊邊界的狀態。
狀態機思想不僅適用於單詞統計,更是詞法分析、協議解析、文本處理的基石。