1 需求分析
1) 問題描述: 讀入一個(最多9個)C程式碼檔案,統計程式中代碼、注釋和空行數以及函數的個數,顯示函數名並產生相應的記錄日誌。
2) 基本要求如下:
(1)、把程式檔案(如.c或者.txt等)按字元順序讀入來源程式;
(2)、輸入正確性檢查;
(3)、邊讀入程式,邊識別統計程式碼、注釋行和空行,同時還要識別函數,統計代碼個數;
(4)、最多允許一次分析9個檔案
2 顯示結果
備忘:本文的代碼實驗IDE為VS2013。本代碼對比較常規的編程習慣下編寫的C代碼可以比較好的識別,但是對一些特殊情況不能識別。
1)輸入正確的檔案個數和路徑
2)輸入正確時產生的記錄檔
3 程式結構
1)整體結構
2)分析模組結構
4 原始碼
整個工程共有三個檔案構成:statist.h;source.c;main.c
1) statist.h
#define SIZE_N 100#define SIZE_L 200#define NUM_F 9#define title "------------------------Life is a Fight-----------------------------------"extern bool com_flag;void getline(FILE* pfile, char* pt);char* clearblank(char*pt);char* mystrstr(char* s1, char* s2);bool Isblank(char* pt);int Iscom(char* pt);bool Isfunc(char* pt);bool Qtycheck(int* pt);
2) source.c
#include<stdio.h>#include<string.h>#include<stdbool.h>#include"statist.h"void getline(FILE* pfile,char* pt){while (!feof(pfile)){*pt = fgetc(pfile);if (*pt=='\n')//成功讀取完一行,直到分行符號{*pt = '\0';return;}pt++;}*pt = '\0';//如果還沒有檢測到分行符號,檔案已經結束,則在末尾添加終止符} char* clearblank(char* pt){while ((*pt == ' ') || (*pt == ' ')){pt++;}return pt;}char* mystrstr(char* s1, char* s2){char*s, *sp1, *temp1, *temp2;int q_flag = 0;if (strstr(s1, "\"") == NULL)//如果沒有發現引號{s = strstr(s1, s2);return s;}else//如果發現引號{sp1 = s1;while (*sp1){temp1 = strstr(sp1, "\"");temp2 = strstr(sp1, s2);if ((temp1 != NULL) && (temp1 == sp1)){if (q_flag == 0)q_flag = 1;elseq_flag = 0;}if ((temp2 != NULL) && (q_flag == 0) && (temp2 == sp1))return sp1;sp1++;}return NULL;}}bool Isblank(char* pt){clearblank(pt);if (*pt == '\0')return 1;return 0;}int Iscom(char* pt){char* pt1,*pt2,*pt3;clearblank(pt);pt1 = mystrstr(pt, "//");pt2 = mystrstr(pt, "/*");pt3 = mystrstr(pt, "*/");if (com_flag == 0){if ((pt2!=NULL) && (pt3 == NULL))//如果只有/*表明注釋開始com_flag = 1;if (pt1 == pt)//雙斜杠開頭的注釋return 1;else if (pt1 - pt > 0 || pt2 - pt > 0)//有注釋符號,但是不是頂頭開始return 2;else if ((pt2 == pt) && ((pt3 != NULL && (*(pt3 + 2) == '\0')) || (pt3 == NULL)))//以/*開頭以*/結尾,或者以/*開頭,沒有檢測到*/return 1;else if ((pt2 == pt) && (pt3 != NULL) && (*(pt3 + 2) != '\0'))//以/*開頭但是沒有以*/結尾return 2;else if (pt1 == NULL || pt2 == NULL)//沒有檢測到注釋符號return 0;}else if (com_flag == 1){if (pt3!=NULL){com_flag = 0;return 1;}printf("\nYYYY\n");return 1;//如果com_flag==1,且沒有檢測到*/則是一句注釋}}bool Isfunc(char* pt){char* pt1, *pt2, *pt3,*pt4,*pt5,*pt6;clearblank(pt);pt1 = mystrstr(pt, "(");pt2 = mystrstr(pt, ";");pt3 = mystrstr(pt, "if");pt4 = mystrstr(pt, "while");pt5 = mystrstr(pt, "for");pt6 = mystrstr(pt, "switch");if (pt1 != NULL&&pt2 == NULL&&pt3 == NULL&&pt4 == NULL&&pt5 == NULL&&pt6 == NULL)return true;return false;}bool Qtycheck(int* pt)//只允許輸入一個1到9的數字{char temp[3];char c;fflush(stdin);gets(temp);if (temp[0]>'0'&&temp[0] <= '9'&&temp[1] == '\0')*pt = (int)(temp[0] - 48);else{fflush(stdin);printf("Please re-enter the file quantity(0<n<10):");return 0;}return 1;}
3) main.c
#include<stdio.h>#include<string.h>#include<stdbool.h>#include"statist.h"#include<stdlib.h>//system()的標頭檔#include<malloc.h>bool com_flag;int main(void){FILE* in,*log;char con;char temp[SIZE_L + 1];char name[SIZE_N];char* pt;char* name_t;int* result;int n = 0;struct FIL{int cod;int blk;int com;int fct;}fil = { 0, 0, 0, 0 };com_flag = 0;do{printf("%s", title);printf("\n\n\nPlease enter the file quantity(0<n<10):");while (!Qtycheck(&n));name_t = (char*)malloc(n*sizeof(name));result = (int*)malloc(n * 4 * sizeof(int));log = fopen("log.txt", "w");fprintf(log, "%s\n\n\n", title);for (int i = 0; i < n; i++){printf("please enter file \"%d\" name:", i + 1);scanf("%s", name_t + i*SIZE_N);in = fopen(name_t + i*SIZE_N, "r");while (!in){fflush(stdin);printf("please re-enter file \"%d\" name:", i + 1);scanf("%s", name_t + i*SIZE_N);in = fopen(name_t + i*SIZE_N, "r");}fclose(in);}for (int i = 0; i < n; i++){in = fopen(name_t + i*SIZE_N, "r");while (!feof(in)){getline(in, temp);pt = clearblank(temp);if (Isblank(pt) == 1 && com_flag == 0){fil.blk++;continue;}else if (Iscom(pt) == 1){fil.com++;continue;}else if (Iscom(pt) == 2 && Isfunc(pt) == 0)fil.com++;else if (Iscom(pt) == 2 && Isfunc(pt) == 1){fil.com++;fil.fct++;fil.cod++;fprintf(log, "%s%s\n", name_t + i*SIZE_N, temp);continue;}else if (Isfunc(pt) == 1){fil.fct++;fprintf(log, "%s%s\n", name_t + i*SIZE_N, temp);}fil.cod++;}*(result + 4 * i) = fil.blk;*(result + 4 * i + 1) = fil.cod;*(result + 4 * i + 2) = fil.com;*(result + 4 * i + 3) = fil.fct;fil.blk = 0;fil.cod = 0;fil.com = 0;fil.fct = 0;com_flag = 0;fclose(in);if (fil.fct)fprintf(log, "\n\n\n");}fprintf(log, "%s", "\n\n\n==========================================================");printf("==========================================================");printf("\nFile No.BlankCodeCommenFunction\n");fprintf(log, "\n%s\n", "File No.BlankCodeCommenFunction");for (int i = 0; i < n; i++){printf("%d%d%d%d%d\n", i + 1, *(result + 4 * i), *(result + 4 * i + 1), *(result + 4 * i + 2), *(result + 4 * i + 3));fprintf(log, "%d%d%d%d%d\n", i + 1, *(result + 4 * i), *(result + 4 * i + 1), *(result + 4 * i + 2), *(result + 4 * i + 3));}fclose(log);free(name_t);free(result);printf("\n\n\nPress 'Y' to continue\n");fflush(stdin);con = getchar();printf("\n\n\n");} while (con=='Y'||con=='y');system("pause");return 0;}