首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言統計字符串單詞數:狀態機算法實現與邊界處理

     編輯:關於C語言

問題定義

輸入一行字符串,統計其中單詞的個數。單詞定義為:由非空格字符構成的連續序列,單詞間由一個或多個空格分隔。

狀態機算法核心邏輯

維護一個狀態變量 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;
}

關鍵細節解析

1. 為什麼用 fgets 而非 gets?

  • gets 已從 C11 標準中移除,極度不安全(無緩衝區長度檢查,必導致緩衝區溢出)
  • fgets 可指定最大讀取長度,包含換行符需手動移除

2. 狀態機的優勢

  • 單次掃描,O(n) 時間,O(1) 空間
  • 天然處理多個連續空格、首尾空格、制表符等邊界情況
  • 邏輯清晰,易於擴展(如統計行數、字符數)

3. 擴展:支持多種空白字符

#include <ctype.h>

// 將 if (c == ' ') 改為:
if (isspace((unsigned char)c)) {  // isspace 需 unsigned char 避免 UB
    word = 0;
}

可識別空格、制表符(\t)、換行符(\n)、垂直製表符(\v)、換頁符(\f)、回車符(\r)。

測試用例驗證

輸入預期輸出說明
Hello World2基本情況
Hello World 2首尾及多重空格
One1單詞
(空行)0空輸入
0純空格
Hello\tWorld\nTest3多種空白字符(需 isspace)

進階思考

若需統計「單詞頻率」,可結合哈希表(如 uthash)或排序後計數;若處理超大文本流,可逐塊讀取並維護跨塊邊界的狀態。

狀態機思想不僅適用於單詞統計,更是詞法分析、協議解析、文本處理的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved