C語言直方圖 && EOF釋疑

用C語言統計單詞長度出現的頻率
#include <stdio.h>

#define MAX_LEN 10  //單詞的最大長度
#define IN  1
#define OUT 0

int main(void)
{
    int len;    //每個單詞的長度
    int wc[MAX_LEN+1] = {0};  //每個長度對應的單詞數
    int c, i, j;
    int state;
	int maxnum=0;	//wc[]中的最大數

    len = c = i = 0;
	state = OUT;
    while((c = getchar()) != EOF)  {
		if(c == ' ' || c == '\t' || c == '\n') {
            if(state == IN)  {	//或者 if(len > 0)
				if(len >= MAX_LEN) {
					wc[MAX_LEN]++;
					len = MAX_LEN;	//單詞長度大於MAX_LEN
				}
				else {
					wc[len]++;
				}
				if(maxnum < wc[len])
					maxnum = wc[len];
                len = 0;
				state = OUT;
            }
		}
		else if(state == OUT) {
			state = IN;
			len = 0;	//單詞真實的長度爲len+1
		}
			else
				len++;
	}

	putchar('\n');

	for(i = maxnum; i > 0; i--) {
		printf("%3d|", i);
		for(j = 0; j <= MAX_LEN; j++) {
			if(wc[j] >= i)
				printf(" * ");
			else
				printf("   ");
		}
		putchar('\n');
	}
	printf("   +");
	for(i = 0; i <= MAX_LEN; i++)
		printf("___");
	printf("\n   ");
	for(i = 0; i < MAX_LEN; i++) {
		printf("%3d", i+1);
	}
	printf(" >10");
	putchar('\n');
	return 0;
}

效果圖


EOF釋疑(轉自這裏)

首先要明白一點,EOF並不是標誌結尾的特殊字符,而是文字流(stream,標準輸入或者文件)達到結尾時返回的一個信號量,在stdio.h中定義爲常量,其值常常爲-1,只在文本文件中存在,二進制文件中不存在。

1.如果是從標準輸入中讀取stream,如下程序

int c;//定義爲int類型,因爲返回值EOF(-1)是int類型的
while((c=getchar()) != EOF)
    putchar(c);
由於標準輸入中無法事先判斷長度,無法判斷是否是End Of File,所以需要手動輸入一個字符表示達到EOF。

Windows中,在新的一行開頭中按下Ctrl+Z,表示達到EOF(因爲Windows輸入是阻塞式的,所以在敲下換行鍵之前不會檢測Ctrl+Z);

Linux中,在新的一行開頭,按下Ctrl-D,表示達到EOF(或者在一行的中間按兩次Ctrl-D,因爲在一行的中間按下Ctrl-D,表示輸出"標準輸入"的緩存區);

2.如果是從文件中讀取stream,一般寫成如下形式

int c;
while ((c = fgetc(fp)) != EOF){
    c = fgetc(fp);
    do something;
}

這樣寫有一個問題。fgetc()不僅是遇到文件結尾時返回EOF,而且當發生錯誤時,也會返回EOF。因此,C語言又提供了feof()函數,用來保證確實是到了文件結尾。上面的代碼feof()版本的寫法就是:
int c;
while (!feof(fp)) {
  c = fgetc(fp);
  do something;
}
但是,這樣寫也有問題。fgetc()讀取文件的最後一個字符以後,C語言的feof()函數依然返回0,表明沒有到達文件結尾;只有當fgetc()向後再讀取一個字符(即越過最後一個字符),feof()纔會返回一個非零值,表示到達文件結尾。
所以,按照上面這樣寫法,如果一個文件含有n個字符,那麼while循環的內部操作會運行n+1次。所以,最保險的寫法是像下面這樣:
int c = fgetc(fp);
while (c != EOF) {
  do something;
  c = fgetc(fp);
}
if (feof(fp)) {
  printf("\n End of file reached.");
} else {
  printf("\n Something went wrong.");
}


這樣在讀取stream時,如果c = fgetc(fp) 讀到的是二進制的-1,怎麼區分讀到的c(-1)跟信號值(-1)呢?

一種解釋(不一定對,歡迎討論):

在文本文件中,數據以字符的ASCII碼值的形式存放。ASCII碼值的範圍是0~255,不可能出現-1,-1實際上是‘-’ 和‘1’,而fgetc是文本視圖處理文件的,因此可以用EOF作爲文件結束標誌輸入的。

注意:EOF只存在文本視圖中,二進制視圖是通過比較文件長度來判斷是否達到文件結尾。

發佈了33 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章