個人項目作業(wc.exe)

  • 2020 年 3 月 15 日
  • 筆記

1.GitHub項目地址

https://github.com/QiuBin666/WC

項目介紹:

 

題目描述

 

Word Count
1. 實現一個簡單而完整的軟體工具(源程式特徵統計程式)。
2. 進行單元測試、回歸測試、效能測試,在實現上述程式的過程中使用相關的工具。
3. 進行個人軟體過程(PSP)的實踐,逐步記錄自己在每個軟體工程環節花費的時間。

WC 項目要求

 

wc.exe 是一個常見的工具,它能統計文本文件的字元數、單詞數和行數。這個項目要求寫一個命令行程式,模仿已有wc.exe 的功能,並加以擴充,給出某程式設計語言源文件的字元數、單詞數和行數。

 

實現一個統計程式,它能正確統計程式文件中的字元數、單詞數、行數,以及還具備其他擴展功能,並能夠快速地處理多個文件。
具體功能要求:
程式處理用戶需求的模式為:

 

wc.exe [parameter] [file_name]

 

 

 

 

 

基本功能列表:

 

wc.exe -c file.c     //返迴文件 file.c 的字元數

 

wc.exe -w file.c    //返迴文件 file.c 的詞的數目  

 

wc.exe -l file.c      //返迴文件 file.c 的行數

 

 

擴展功能:
    -s   遞歸處理目錄下符合條件的文件。
    -a   返回更複雜的數據(程式碼行 / 空行 / 注釋行)。

 

空行:本行全部是空格或格式控制字元,如果包括程式碼,則只有不超過一個可顯示的字元,例如“{”。

 

程式碼行:本行包括多於一個字元的程式碼。

 

注釋行:本行不是程式碼行,並且本行包括注釋。一個有趣的例子是有些程式設計師會在單字元後面加註釋:

 

    } //注釋
在這種情況下,這一行屬於注釋行。

 

[file_name]: 文件或目錄名,可以處理一般通配符。

高級功能:

 

 -x 參數。這個參數單獨使用。如果命令行有這個參數,則程式會顯示圖形介面,用戶可以通過介面選取單個文件,程式就會顯示文件的字元數、行數等全部統計資訊。

 

需求舉例:
  wc.exe -s -a *.c

 

返回當前目錄及子目錄中所有*.c 文件的程式碼行數、空行數、注釋行數。

 

 

2.PSP預計時間

 

 

 

PSP2.1

Personal Software Process Stages

預估耗時(分鐘)

實際耗時(分鐘)

Planning

計劃

 30

 

· Estimate

· 估計這個任務需要多少時間

 30

 

Development

開發

 180

 

· Analysis

· 需求分析 (包括學習新技術)

 200

 

· Design Spec

· 生成設計文檔

 30

 

· Design Review

· 設計複審 (和同事審核設計文檔)

 0

 

· Coding Standard

· 程式碼規範 (為目前的開發制定合適的規範)

20

 

· Design

· 具體設計

30

 

· Coding

· 具體編碼

 360

 

· Code Review

· 程式碼複審

 20

 

· Test

· 測試(自我測試,修改程式碼,提交修改)

120

 

Reporting

報告

 120

 

· Test Report

· 測試報告

 60

 

· Size Measurement

· 計算工作量

 30

 

· Postmortem & Process Improvement Plan

· 事後總結, 並提出過程改進計劃

 60

 

合計

 

 1290

 

 

 

 

 

3.解題思路

拿到題目後首先想到的是:要對文件進行讀寫操作,但這是以前的編程經歷中從未涉及到的,所以首先去學習了c語言文件讀寫相關的知識。

學習相關知識後,就到了該如何實現功能的問題了,解決方法是劃分為幾個功能模組,每個模組實現一個功能。

4.設計實現過程

設計字元數統計函數void CharCount():當判定為字元便計數,非字元則不計。

設計單詞數統計函數void WordCount():通過從第一個字母開始讀取連續的字母。

設計行數統計函數 void LineCount():判斷行數可以判斷是否出現‘n’或‘t’來判斷。
設計擴展功能統計函數int Extend():

    1、空行計算,如果一行中沒有字元或者最多有一個'{‘或者’}'(可能遇到‘ ’或者‘t’)算為空行。

    2、注釋行計算,通過讀取第一個字元為/進入判斷,讀取第二個字元為*或者/實現。

    3、程式碼行計算,排除空行和注釋行之外的即為程式碼行。

5.程式碼說明 

主函數:

 1 int a=0;   2 int b=0;   3 int c=0;   4 int main() { //主函數   5     void CharCount(char filename[]);//字元數統計函數    6     void WordCount(char filename[]);//單詞數統計函數   7     void LineCount(char filename[]);//行數統計函數     8     int Extend(char filename[]);//擴展功能統計函數    9     char input[10], filename[32];  10     while (1) {  11         //輸入指令  12         printf("wc.exe - c file.c      返迴文件的字元數nwc.exe - w file.c      返迴文件的詞的數目nwc.exe - l file.c      返迴文件的行數nwc.exe - a file.c      返回更複雜的數據(程式碼行 / 空行 / 注釋行)nwc.exe - o file.c      退出n請輸入指令:- ");  13         scanf("%s",&input);  14  15         switch(input[0]){  16             case 'c':  //字元數  17                 printf("請輸入文件名:");//輸入文件名  18                 scanf("%s", &filename);  19                 CharCount(filename);  20                 printf("文件的字元數為:%d",a);  21                 break;  22  23             case 'w':  //詞數                  24                 printf("請輸入文件名:");//輸入文件名  25                 scanf("%s", &filename);  26                 WordCount(filename);  27                 printf("文件的詞數為:%d", b);  28                 break;  29  30             case 'l':  //行數  31                 printf("請輸入文件名:");//輸入文件名  32                 scanf("%s", &filename);  33                 LineCount(filename);  34                 printf("文件的行數為:%d", c);  35                 break;  36  37             case 'a':    //返回更複雜的數據(程式碼行 / 空行 / 注釋行)。  38                 printf("請輸入文件名:");//輸入文件名  39                 scanf("%s", &filename);  40                 Extend(filename);  41                 break;  42  43             case 'o':  //退出  44                 return 0;  45  46             default:  47                 printf("你輸入的指令有誤!請重新輸入");  48                 break;  49         }  50  51     }  52     system("pause");  53     return 0;  54 }

各子模組功能函數:

計算字元數:

 1 void CharCount(char filename[]){//字元數統計函數    2     FILE *fp=NULL;   3     fp=fopen(filename,"r");   4     if(fp==NULL){   5         printf("尋找文件失敗n");   6         exit(-1);   7     }   8     char ch;   9     ch = fgetc(fp);  10     while(ch!=EOF){  11         if (ch != ' '&&ch != 'n'&&ch != 't'&&ch != ','&&ch != '.'&&ch != '!'&&ch != ';'&&ch != '=');  12         a++;  13         ch = fgetc(fp);  14     }  15     a--;  16     fclose(fp);  17 }

計算詞數:

 1 void WordCount(char filename[]){//單詞數統計函數    2     FILE *fp = NULL;   3     fp=fopen(filename,"r");   4     if(fp==NULL){   5         printf("尋找文件失敗n");   6         exit(-1);   7     }   8     char fchar = 0;   9     fchar = fgetc(fp);  10     while (fchar != EOF)  11     {  12         if ((fchar >= 'a' && fchar <= 'z') || (fchar >= 'A' && fchar <= 'Z') )//遇到字母  13         {  14             while ((fchar >= 'a' && fchar <= 'z') || (fchar >= 'A' && fchar <= 'Z'))  15                 fchar = fgetc(fp);  16                 b++;  17                 fchar = fgetc(fp);  18         }  19         else {  20             fchar = fgetc(fp);  21         }  22     }  23     fclose(fp);  24  25 }

計算行數:

 1 void LineCount(char filename[]){//行數統計函數    2     FILE *fp = NULL;   3     fp=fopen(filename,"r");   4     if(fp==NULL){   5         printf("尋找文件失敗n");   6         exit(-1);   7     }   8     char ch;   9     ch = fgetc(fp);  10     while (ch != EOF)  11     {  12         if (ch == 'n' || ch == 't')  13             c++;  14         ch = fgetc(fp);  15     }  16     fclose(fp);  17 }

擴展功能函數:

 1 int Extend(char filename[]) {  //擴展功能    2     FILE *fp = NULL;   3     fp = fopen(filename, "r");   4     if (fp == NULL) {   5         printf("尋找文件失敗n");   6         exit(-1);   7     }   8   9     char fchar = 0;  10     int emptyline = 0, code = 0, note = 0;  11     int l = 0, n = 0, c = 0;//l為空行類型,0是無字元空行,1是1字元空行;n為注釋類型,0為非注釋行,1為單注釋行,2為多注釋行,c為程式碼類型  12  13     while (fchar != EOF) {  14         fchar = fgetc(fp);  15             if (l == 0 || l == 1) {//如果開始是空格或製表,開始判斷是不是空行或者注釋行或者程式碼行  16                 if (fchar == 'n') {//回車之前沒有字元,空行;1字元進入後也是沒有其他字元  17                     emptyline++;  18                     l = 0;  19                     continue;  20                 }  21                 else if (fchar == '/') {//注釋判斷  22                     fchar = fgetc(fp);  23                     if (fchar == '/') {//單行注釋  24                         n = 1;  25                         while (fchar != EOF && fchar != 'n') {  26                             fchar = fgetc(fp);  27                         }  28                         n = 0;  29                         note++;  30                         continue;  31                     }  32                     else if (fchar == '*') {//多行注釋  33                         n = 2;  34                         continue;  35                     }  36                 }  37                 else if( fchar == '}' && l == 0){  38                     l = 1;        //一字元空行  39                     continue;  40                 }  41                 else if(fchar == ' ' || fchar == 't'){  42                     continue;  43                 }  44                 else {  45                     c = 1;  46                 }  47             }  48             if (c == 1) {//程式碼行  49                 while (fchar != EOF && fchar != 'n') {  50                     fchar = fgetc(fp);  51                 }  52                 l = 0;//狀態變回空行  53                 code++;  54                 continue;  55             }  56             if (n == 2) {//多行注釋  57                 while (fchar != EOF && fchar != '*') {  58                     while (fchar != EOF && fchar != 'n') {  59                         fchar = fgetc(fp);  60                     }  61                     note++;  62                     fchar = fgetc(fp);  63                 }  64                 fchar = fgetc(fp);  65                 if (fchar == '/') {//多行結束  66                     n = 0;  67                 }  68                 continue;  69             }  70     }  71     printf("n共有空行數: %d  n程式碼行數: %d  n注釋行數: %dn", emptyline, code, note);  72     fclose(fp);  73 }

6.測試運行

 

 

 

 

 

 

基本功能測試用例

 

 

 

測試-c功能:

 

 

 

 

 

 

 

 

 

 測試-w功能:

 

 

 

 

 

 

 測試-l功能:

 

 

 

擴展功能測試用例

 

 

 

 

 

 

 測試-a功能:

 

 

 

7.實際花費的時間

 

PSP2.1

Personal Software Process Stages

預估耗時(分鐘)

實際耗時(分鐘)

Planning

計劃

 30

 35

· Estimate

· 估計這個任務需要多少時間

 30

20

Development

開發

 180

 240

· Analysis

· 需求分析 (包括學習新技術)

 200

180 

· Design Spec

· 生成設計文檔

 30

20

· Design Review

· 設計複審 (和同事審核設計文檔)

 0

· Coding Standard

· 程式碼規範 (為目前的開發制定合適的規範)

20

10 

· Design

· 具體設計

30

60 

· Coding

· 具體編碼

 360

540

· Code Review

· 程式碼複審

 20

60

· Test

· 測試(自我測試,修改程式碼,提交修改)

120

180

Reporting

報告

 120

 100

· Test Report

· 測試報告

 60

 30

· Size Measurement

· 計算工作量

 30

 20

· Postmortem & Process Improvement Plan

· 事後總結, 並提出過程改進計劃

 60

 40

合計

 

1290

 1535

 

8.項目小結

收穫:作為第一次項目經歷,對軟體工程的設計流程有了新的認識,一個項目的實現,重要的往往不是程式碼的品質,而是一個好的框架和一個良好的開發習慣,在這次開發過程中深刻的認識到這兩點的重要性。

不足:基礎知識的不足,導致前期準備時間過長。解決問題能力不足,導致編碼所需時間長、錯誤多,部分功能完全沒能力實現,需多學、多練。開發經驗少,整個開發過程並不流暢。