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

C 語言實作:統計輸入單詞長度與字元出現頻率的直方圖

     編輯:關於C

前言

近期研讀《C 語言程式設計 第二版》時,嘗試完成書中習題,其中兩題特別具有代表性:

  1. 編寫程式,列印輸入中單詞長度的直方圖。
  2. 編寫程式,列印輸入中各字元出現頻率的直方圖。

本文詳細記錄第一題的解題思路與程式碼實作,第二題邏輯類似,讀者可自行延伸。

題目需求分析

程式需讀取標準輸入,以空白字元(空格、換行、製表符)作為單詞分隔符。每當讀完一個單詞,即統計其長度;輸入結束(EOF)時,輸出各長度單詞的出現次數。

例如輸入:

i am a student

輸出應顯示:長度 1 的單詞 2 個(i, a),長度 2 的單詞 1 個(am),長度 7 的單詞 1 個(student)。

核心資料結構設計

單詞長度有上限。根據維基百科,英語最長單詞約 30 字母,故定義 MAXWORD = 30。使用陣列 wl[MAXWORD + 1] 記錄長度為 i 的單詞計數(索引 0 不用)。初始化時將所有元素歸零。

狀態機邏輯

採用「狀態機」處理輸入流:

  • IN:正在讀取單詞內部。
  • OUT:位於單詞之外(遇到分隔符)。

變數 nc 累計目前單詞長度。讀到分隔符且 nc > 0 時,表示一個單詞結束,將 wl[nc]++(超過 MAXWORD 另計 overflow),並重置 nc = 0、狀態轉為 OUT。讀到非分隔符且狀態為 OUT 時,進入 IN,nc = 1;若已在 IN,則 nc++。

完整程式碼

#include <stdio.h>

#define MAXWORD 30   /* 單詞最大長度 */
#define IN 1         /* 在單詞內 */
#define OUT 0        /* 在單詞外 */

int word_length_histogram(void)
{
    int c, i, nc, state, overflow;
    int wl[MAXWORD + 1];   /* 索引 1..MAXWORD */

    state = OUT;
    nc = 0;
    overflow = 0;

    for (i = 1; i <= MAXWORD; ++i)
        wl[i] = 0;

    while ((c = getchar()) != EOF) {
        if (c == ' ' || c == '\n' || c == '\t') {
            state = OUT;
            if (nc > 0) {
                if (nc <= MAXWORD)
                    ++wl[nc];
                else
                    ++overflow;
                nc = 0;
            }
        } else if (state == OUT) {
            state = IN;
            nc = 1;
        } else {
            ++nc;
        }
    }

    for (i = 1; i <= MAXWORD; ++i)
        printf("長度為 %2d 的單詞個數:%3d\n", i, wl[i]);
    if (overflow)
        printf("長度超過 %d 的單詞:%d\n", MAXWORD, overflow);

    return 0;
}

int main(void)
{
    return word_length_histogram();
}

執行範例

編譯執行後,輸入文字並以 Ctrl+D (Linux/macOS) 或 Ctrl+Z (Windows) 送出 EOF:

$ ./a.out
The quick brown fox jumps over the lazy dog
^D
長度為  1 的單詞個數:  0
長度為  2 的單詞個數:  0
長度為  3 的單詞個數:  4
長度為  4 的單詞個數:  1
長度為  5 的單詞個數:  3
長度為  6 的單詞個數:  1
長度超過 30 的單詞:0

延伸思考

第二題「字元頻率直方圖」只需將陣列大小擴充至 256(涵蓋所有 ASCII 碼),並在讀取每個字元時直接 ++freq[c],邏輯更簡單。讀者可嘗試自行實作。

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