1. 程式人生 > >c語言練手專案(一)

c語言練手專案(一)

統計檔案的字元數、單詞數以及總行數,包括:

  • 每行的字元數和單詞數
  • 檔案的總字元數、總單詞數以及總行數


注意:

  • 空白字元(空格和tab縮排)不計入字元總數;
  • 單詞以空格為分隔;
  • 不考慮一個單詞在兩行的情況;
  • 限制每行的字元數不能超過1000。


請先看程式碼:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int *getCharNum(char *filename, int *totalNum);
  4. int main(){
  5. char filename[30];
  6. // totalNum[0]: 總行數 totalNum[1]: 總字元數 totalNum[2]: 總單詞數
  7. int totalNum[3] = {0, 0, 0};
  8. printf("Input file name: ");
  9. scanf("%s", filename);
  10. if(getCharNum(filename, totalNum)){
  11. printf("Total: %d lines, %d words, %d chars\n", totalNum[0], totalNum[2], totalNum[1]);
  12. }else{
  13. printf("Error!\n");
  14. }
  15. return 0;
  16. }
  17. /**
  18. * 統計檔案的字元數、單詞數、行數
  19. *
  20. * @param filename 檔名
  21. * @param totalNum 檔案統計資料
  22. *
  23. * @return 成功返回統計資料,否則返回NULL
  24. **/
  25. int *getCharNum(char *filename, int *totalNum){
  26. FILE *fp; // 指向檔案的指標
  27. char buffer[1003]; //緩衝區,儲存讀取到的每行的內容
  28. int bufferLen; // 緩衝區中實際儲存的內容的長度
  29. int i; // 當前讀到緩衝區的第i個字元
  30. char c; // 讀取到的字元
  31. int isLastBlank = 0; // 上個字元是否是空格
  32. int charNum = 0; // 當前行的字元數
  33. int wordNum = 0; // 當前行的單詞數
  34. if( (fp=fopen(filename, "rb")) == NULL ){
  35. perror(filename);
  36. return NULL;
  37. }
  38. printf("line words chars\n");
  39. // 每次讀取一行資料,儲存到buffer,每行最多隻能有1000個字元
  40. while(fgets(buffer, 1003, fp) != NULL){
  41. bufferLen = strlen(buffer);
  42. // 遍歷緩衝區的內容
  43. for(i=0; i<bufferLen; i++){
  44. c = buffer[i];
  45. if( c==' ' || c=='\t'){ // 遇到空格
  46. !isLastBlank && wordNum++; // 如果上個字元不是空格,那麼單詞數加1
  47. isLastBlank = 1;
  48. }else if(c!='\n'&&c!='\r'){ // 忽略換行符
  49. charNum++; // 如果既不是換行符也不是空格,字元數加1
  50. isLastBlank = 0;
  51. }
  52. }
  53. !isLastBlank && wordNum++; // 如果最後一個字元不是空格,那麼單詞數加1
  54. isLastBlank = 1; // 每次換行重置為1
  55. // 一行結束,計算總字元數、總單詞數、總行數
  56. totalNum[0]++; // 總行數
  57. totalNum[1] += charNum; // 總字元數
  58. totalNum[2] += wordNum; // 總單詞數
  59. printf("%-7d%-7d%d\n", totalNum[0], wordNum, charNum);
  60. // 置零,重新統計下一行
  61. charNum = 0;
  62. wordNum = 0;
  63. }
  64. return totalNum;
  65. }

在D盤下建立檔案demo.txt,並輸入如下的內容:

I am Chinese. I love my country.
China has 960 square kilometers of territory.
China has a population of 1.35 billion.
The capital of China is Beijing.

                                By gunge

                                2014-10-12

執行程式,輸出結果為:

Input file name: d://demo.txt
line   words  chars
1      7      26
2      7      39
3      7      33
4      6      27
5      0      0
6      2      7
7      0      0
8      1      10
Total: 8 lines, 30 words, 142 chars


上面的程式,每次從檔案中讀取一行,放到緩衝區buffer,然後遍歷緩衝區,統計當前行的字元和單詞數。

fgets()函式用於從檔案中讀取一行或指定個數的字元,其原型為:
   char * fgets(char *buffer, int size, FILE * stream);
引數說明:

  • buffer為緩衝區,用來儲存讀取到的資料。
  • size為要讀取的字元的個數。如果該行字元數大於size-1,則讀到 size-1 個字元時結束,並在最後補充' \0';如果該行字元數小於等於 size-1,則讀取所有字元,並在最後補充 '\0'。即,每次最多讀取 size-1 個字元。讀取的字元包括換行符。
  • stream為檔案指標。


有的讀者問,為什麼不使用getc(),每次從檔案中讀取一個字元,也無需開闢緩衝區。

這樣沒有問題,但是在處理換行時要注意跨平臺問題,因為不同的平臺對文字檔案換行的處理不一樣,Linux以'\n'為換行符,Windows以'\n\r'為換行符,Mac又以'\r\n'為換行符。所以,使用getc()函式處理換行時比較麻煩。

這裡去繁就簡,通過fgets()讀取整行資料,然後再處理每個字元,直接忽略'\n'和'\r'。

注意:由於每行的結尾會有最多2個位元組長度的換行符,fgets()還會新增NUL,所以緩衝區的長度至少為1003,才能容納每行1000個字元,否則strlen()可能返回垃圾值。

請看程式碼第43行,開啟檔案出錯時,返回NULL,而不是生硬的exit()。這樣可以通知主調函式發生了錯誤,讓主調函式做出適當的處理,或者通知使用者,提高軟體的使用者體驗。

分享個C/C++學習交流QQ群:389318488,群內提供免費教學視訊及資料編譯器,原始碼等等,有大牛解答疑問,能給你提供職業生涯的一些建議!