程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++代碼注釋行和函數個數統計

C++代碼注釋行和函數個數統計

編輯:C++入門知識

C++代碼注釋行和函數個數統計


問題來源,在14年的暑假的一次小項目當中遇到了一個這樣的問題,要求統計C++代碼的注釋行數,有效代碼行數,代碼注釋公共行數,以及函數個數。

下面稍微解釋一下問題,

1)注釋行數:指有注釋的行,包括有代碼和注釋的公共行(如:3,4,15,22...)

2)有效代碼行:指有代碼的行,包括有代碼和注釋的公共行(如:1,4,11,15,25....)

3)代碼注釋公共行:指又有代碼又有注釋的行(如:4,15...)

4)函數個數:這個不用說明了吧。

以下為注釋情況展示代碼:

復制代碼
 1 #include 
 2 
 3 //follow is a common line
 4 void swap(char *p/* = NULL */)
 5 {
 6     printf("this is a function /*is not comments*/");
 7 }
 8 
 9 int main(void)
10 {
11     int a = 10;
12     int b;
13     char *p = NULL;
14 
15     swap(p);  //common line
16     if (10 == a)
17     {
18         printf("is not function;//is not comments");
19     }
20     //pure comments/*no use*/
21 
22     /*a = 5;
23     printf("not use\n");*/
24 
25     b = 3;/*i'm a comment*/ a = 5; /*comments line
26     pure //comments line;"*/......"look there*/
27     printf("test \" escape char");
28     //and the follow,maybe affect the count of function
29     if (*p == '{')
30     {
31         printf("the '{' is a question\n");
32     }
33     //
34 
35     return 0;
36 }
復制代碼

上面的這個代碼片段,已經基本上展示了各種注釋可能出現的情況,接著我們來分析一下注釋出現的位置:

一、“//”雙斜槓注釋

1)可能出現在行頭部,如:第3行;

2)可能出現在行末尾,如:第15行;

注意:第18行,第26行。第18行中,//位於雙引號中,注釋失效;第26行中,//位於/**/注釋中,//失效。

二、“/**/”斜槓星注釋

1)可能出現在函數參數裡,如:第4行;

2)可能注釋一個段落,如:22,23行;

3)也可能出現在代碼中部,如25,26行那樣的復雜注釋;

注意:第20行,第26行。第20行,/**/位於//注釋中,失效。第26行,有一個*/位於“”中,*/失效。

好了,位置分析完畢,下面分析一下如何設計算法:

三、具體算法設計思路

1)解決文件讀取

這裡我們用c++文件讀取,每次讀取一行,將讀取結果放到string變量裡面,這樣string變量尾部自動為'\0'。我們用於判斷行尾部。

2)雙引號問題

由於雙引號裡面的內容都是無效的,所以我們可以直接來個過濾雙引號裡面的內容。(具體實現見代碼)

3)單引號問題

上面的展示代碼裡面也看到了,單引號裡面的內容(如:if (ch == '{'))可能會影響函數個數的統計,所以我們需要過濾單引號。

4)空行

這個最簡單,如果string為空就是空行。包括(\t\n\r' '等等,無效字符,都算空行)。

5)“//”注釋

這個較為簡單,遇到//就可以進行統計,同時該行也不需要繼續遍歷了,直接break;然後讀取下一行。

6)“/**/”注釋

較麻煩,我們這裡用到了代碼標記,注釋標記,同時還設置了當遍歷到行最尾部的時候,才進行行數統計,這樣避免了一行被統計多次。(具體實現見代碼)

7)函數個數

首先說一下統計思路,我們統計函數的時候,只是以大括號({})為統計標記。用棧來表示,遇到左括號,入棧;遇到右括號,彈出一個左括號。知道彈到棧空,函數個數+1,

這樣的話,就實現了只保留最外層那對{},裡層的括號全部抵銷。我們又想了一下,簡化了一下,不用棧,直接用一個變量來表示括號個數,遇到左括號,++top;遇到右括號--top,直到top==0,也就相當於棧空,函數個數+1。

其實如下代碼的函數個數統計還有問題:

示例:對於類、結構體、枚舉體、全局數組,會被統計為一個函數。也就是說,那些在函數體外面的,但是又帶有大括號({})的代碼,都會被識別為函數。

以下為實現代碼:

復制代碼
  1 #include 
  2 #include 
  3 #include 
  4 using namespace std;
  5 
  6 int main(void)
  7 {
  8     string line="";
  9     ifstream ifs;
 10     ifs.open("Test.cpp");
 11     if (!ifs)
 12     {
 13         cout<<"文件打開失敗"< 0 && line[i-1] != '\\') || (i == 0))) 
 48             {
 49                 ++i;
 50                 bSyh = 1;
 51                 continue;
 52             }
 53             //“正在進行雙引號屏蔽....”
 54             if (bSyh)
 55             {
 56                 //“ \”結束”
 57                 if (line[i] == '\"' && ((i > 0 && line[i-1] != '\\') || (i == 0)))
 58                 {
 59                     bSyh = 0;
 60                 }
 61                 else if (line[i] == '\0')  //行末尾
 62                 {
 63                     if (bZs)        
 64                         ++nZs;       
 65                     if (bCode)
 66                         ++nDm;      
 67                     if (bZs && bCode)
 68                         ++nGg;
 69                     break;
 70                 }
 71                 ++i;
 72                 continue;
 73             }
 74             //遇到單引號(避免'{','}'),且非轉義字符\',連續跳過3個(第二個'後位置)
 75             if (line[i] == '\'' && ((i > 0 && line[i-1] != '\\') || (i == 0)))
 76             {
 77                 i += 3;
 78                 continue;
 79             }
 80             //“//注釋行”
 81             if (!bXgx && line[i] == '/' && line[i+1] == '/')  
 82             {
 83                 if (bCode)     //“前有代碼,混合注釋行”
 84                 {
 85                     ++nZs;     //注釋
 86                     ++nDm;     //代碼
 87                     ++nGg;     //公共
 88                 }
 89                 else          //純注釋行
 90                 { 
 91                     ++nZs;
 92                 }
 93                 break;  //跳出當前行(即,內while循環),“//”後代碼不做判斷
 94             }
 95             //“/*注釋開始”
 96             if (!bXgx && line[i] == '/' && line[i+1] == '*')
 97             {
 98                 i += 2;        //跳過/*符號
 99                 bXgx = 1;      //標記“/*”開始
100                 bZs = 1;       //“發現注釋”
101                 continue;
102             }
103             //“正在進行多行注釋....”
104             if (bXgx)
105             {
106                 //“*/注釋結束”
107                 if (line[i] == '*' && line[i+1] == '/')
108                 {
109                     ++i;     //“跳過*/”注意後有一個 ++i;
110                     bXgx = 0;
111                 }
112                 else if (line[i] == '\0')  //行末尾
113                 {
114                     if (bCode)       //注釋前有代碼,即“混合行”
115                     {
116                         ++nDm;
117                         ++nZs;       
118                         ++nGg;
119                     }
120                     else
121                     {
122                         ++nZs;       //“純注釋”
123                     }
124                     break;
125                 }
126                 ++i;
127                 continue;
128             }
129             if (line[i] == '\0')
130             {
131                 if (bZs)        
132                     ++nZs;       
133                 if (bCode)
134                     ++nDm;      
135                 if (bZs && bCode)
136                     ++nGg;
137                 break;
138             }
139             //“以下全是有效代碼區域”
140             //“函數個數統計區域:開始”
141             if (line[i] == '{')      //記錄函數左括號
142             {
143                 ++bHs;
144             }
145             else if (line[i] == '}') //遇到函數右括號
146             {
147                 if (bHs == 0)        //“發現一個函數”
148                     ++nHs;
149                 --bHs;
150             }
151             //“函數統計:結束”
152             ++i;
153             bCode = 1;    //能執行到這裡,說明該行存在代碼
154         }
155     }
156     
157     cout<<"注釋: "<
復制代碼

原文地址:http://www.cnblogs.com/nchar/p/3915889.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved