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

C語言字符串處理實訓項目完整解決方案:統計字母、單詞、子串出現次數與菜單驅動

     編輯:C 語言問答

項目需求回顧

  1. 統計字母:讀入文本,分別統計 'a' 和 'b' 出現次數 (函數 Sum_letter)
  2. 統計單詞總數:用戶輸入文本,統計單詞數 (函數 All_word,單詞定義:非空白/標點字符序列)
  3. 統計指定單詞出現次數:輸入目標單詞,統計其在文本中出現次數 (函數 Sum_word_appear)
  4. 菜單驅動:主循環顯示選項,調用上述功能,支持退出

核心難點與設計決策

完整標準化代碼 (C99 風格、模塊化、錯誤處理)


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

#define MAX_WORD_LEN 100
#define TEMP_FILE "temp_text.dat"

void count_ab(void);
void count_total_words(void);
void count_target_word(void);
void write_text_to_file(void);

int main(void) {
    write_text_to_file();  // 統一入口:先獲取文本存文件
    
    int choice;
    while (true) {
        printf("\n=== 字符串處理菜單 ===\n");
        printf("1. 統計 'a' 和 'b' 出現次數\n");
        printf("2. 統計單詞總數\n");
        printf("3. 統計指定單詞出現次數\n");
        printf("4. 退出\n");
        printf("選擇 (1-4): ");
        if (scanf("%d", &choice) != 1) {  // 輸入非數字
            scanf("%*[^\n]"); getchar();  // 清理緩衝區
            puts("輸入無效,請輸入數字 1-4");
            continue;
        }
        switch (choice) {
            case 1: count_ab(); break;
            case 2: count_total_words(); break;
            case 3: count_target_word(); break;
            case 4: puts("再見!"); return 0;
            default: puts("選項範圍 1-4");
        }
    }
}

// 1. 統計 a/b
void count_ab(void) {
    FILE *fp = fopen(TEMP_FILE, "r");
    if (!fp) { perror("打開文件失敗"); return; }
    
    int cnt_a = 0, cnt_b = 0;
    int ch;
    while ((ch = fgetc(fp)) != EOF) {
        if (ch == 'a') cnt_a++;
        else if (ch == 'b') cnt_b++;
    }
    fclose(fp);
    printf("'a' 出現 %d 次\n'b' 出現 %d 次\n", cnt_a, cnt_b);
}

// 2. 統計單詞總數 (狀態機法)
void count_total_words(void) {
    FILE *fp = fopen(TEMP_FILE, "r");
    if (!fp) { perror("打開文件失敗"); return; }
    
    int count = 0;
    bool in_word = false;
    int ch;
    while ((ch = fgetc(fp)) != EOF) {
        if (isspace(ch) || ispunct(ch)) {
            in_word = false;
        } else if (!in_word) {
            in_word = true;
            count++;
        }
    }
    fclose(fp);
    printf("單詞總數: %d\n", count);
}

// 3. 統計目標單詞
void count_target_word(void) {
    char target[MAX_WORD_LEN];
    printf("輸入目標單詞: ");
    if (scanf("%99s", target) != 1) return;  // 讀取單詞 (自動跳過空白)
    
    FILE *fp = fopen(TEMP_FILE, "r");
    if (!fp) { perror("打開文件失敗"); return; }
    
    int count = 0;
    char word[MAX_WORD_LEN];
    int idx = 0;
    int ch;
    while ((ch = fgetc(fp)) != EOF) {
        if (isspace(ch) || ispunct(ch)) {
            if (idx > 0) {
                word[idx] = '\0';
                if (strcmp(word, target) == 0) count++;
                idx = 0;
            }
        } else {
            if (idx < MAX_WORD_LEN - 1) word[idx++] = ch;
        }
    }
    // 處理文件末尾單詞
    if (idx > 0) {
        word[idx] = '\0';
        if (strcmp(word, target) == 0) count++;
    }
    fclose(fp);
    printf("'%s' 出現 %d 次\n", target, count);
}

// 文本輸入 → 文件
void write_text_to_file(void) {
    FILE *fp = fopen(TEMP_FILE, "w");
    if (!fp) { perror("創建文件失敗"); exit(EXIT_FAILURE); }
    
    puts("請輸入文本 (Ctrl+D / Ctrl+Z 結束):");
    int ch;
    while ((ch = getchar()) != EOF) {
        fputc(ch, fp);
    }
    fclose(fp);
    puts("文本已保存。");
}

關鍵算法解析

單詞計數狀態機


in_word = false
for each char c:
    if c is separator:
        in_word = false
    else if not in_word:
        in_word = true
        count++

優勢:O(n) 時間、O(1) 空間、正確處理多重分隔符、行首行尾、標點符號。

目標單詞匹配

逐字符構建當前單詞,遇到分隔符或 EOF 時與目標 strcmp 比較。避免了 strstr 可能產生的子串誤匹配 (如 "the" 匹配 "other")。

測試用例與驗收標準

難點解決方案
文本輸入方式採用「先寫入臨時文件,再多次讀取」模式,避免標準輸入無法重讀問題
單詞分割規則isspace() + ispunct() 作為分隔符,連續非分隔符視為一個單詞
大小寫敏感題目未指定,採用**大小寫敏感** (區分 'A'/'a'),易於修改為 tolower() 統一
緩衝區管理文件操作用 fread 逐字符讀取,避免 scanf 格式化陷阱
輸入文本功能 1 (a/b)功能 2 (總詞數)功能 3 (目標 "the")
a b c\napple bananaa:2, b:24 (a, b, c, apple, banana → 5? 實際分割: "a" "b" "c" "apple" "banana" = 5)0
The quick brown fox jumps over the lazy dog.a:1, b:192 (The, the — 大小寫敏感則 1)
hello,world! hello...worlda:0, b:04 (hello, world, hello, world)0
空文件0, 000

實訓報告撰寫提綱 (按評分項)

  1. 流程圖與算法描述 (25分):
    • 主流程圖:輸入文本→寫文件→菜單循環→分支功能→輸出結果
    • 三大核心函數流程圖:字符計數、狀態機單詞計數、單詞構建匹配
    • 算法文字描述:時間/空間複雜度、邊界處理、狀態轉移條件
  2. 知識點描述 (15分):文件操作 (fopen/fclose/fgetc/fputc)、字符分類 (ctype.h)、字符串比較 (strcmp)、狀態機模式、緩衝區處理、EOF 判斷、錯誤碼返回
  3. 難點與解決 (10分):標準輸入不可重讀 → 文件中轉;單詞定義模糊 → 明確分隔符集;輸入緩衝區殘留 → scanf("%*[^\n]") 清理
  4. 學習總結 (10分):模塊化設計思想、防御性編程習慣、測試驅動思維、C 標準庫熟悉度提升

進階優化方向

  • 內存映射文件 (mmap) 替換逐字符讀取,大文件性能提升
  • Trie 樹 / Aho-Corasick 算法支持多模式同時匹配
  • Unicode/UTF-8 支持:wchar_t/char16_t + ICU 庫
  • 並行化:MapReduce 風格分塊統計再歸併

總結

本方案提供了**標準化、模塊化、可測試、可擴展**的完整實現。核心亮點:

  1. 文件中轉解決標準輸入不可重讀
  2. 狀態機單詞計數 O(1) 空間
  3. 逐字符構建單詞精確匹配避免子串干擾
  4. 完整錯誤處理與輸入驗證
  5. 清晰分離 I/O、業務邏輯、用戶交互

代碼可直接作為實訓報告附件,配合上述報告提綱,滿足所有評分要求。

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