C++ 程式碼統計工具 & 判斷一行程式碼是否為註釋行
阿新 • • 發佈:2019-01-22
這兩天接手了一個專案,專案定義了一種自己語法,所以有了判斷註釋的需求。
這裡自己簡單實現了一個,程式碼非常精簡。
提供的註釋語法和C++是一模一樣的, 允許 // 和 /* */兩種註釋
兩個問題:
1、如何判斷某一行是否為註釋行。
2、如何判斷是否“進入”了註釋段,也就是在/* */中間。
先說第2點,思路:從上往下,一行一行的檢查。
用一個flag標識是否”進入”了註釋,具體在一行當中,遇到/* flag 置1,遇到 */ 置0;這樣即使一行中有多個/* */也不會判斷錯誤。
比如 /*int x*/ printf(); /* int y */ /*int z; 之後
就進入了註釋段了,在遇到*/之前接下里的行都是註釋行。但它本身並不是註釋行。
這就說到第1點了,除了這個以下幾種情況也都是註釋行,如果一行是以//開頭,僅有/*兩個字元 ,僅有*/兩個字元,以/*開頭類似這種的/* xx */ /* x xxx */ //xxx,以/*開頭類似 /* int x 這種的。
很自然的想到遞迴計算:
在一行中,前面部分閉合了就不用管了,把後面的子串繼續遞迴。只要遇到上面說的幾種情況中的一種就說明是註釋行。遞迴結束還沒遇到說明是普通行。
而且在遞迴中也可以更新flag是否進入了註釋段。 兩者可以在同一個函式中進行,非常方便。
判斷一行本身是否為註釋行以及更新/*、*/的函式如下。
bool Counter::judgeAndUpdateComment(string line, bool& flag) { // /* xxxxxx */ /* x xxx */ //xxxx // /*xx */ int x /* if(line[0] == '/' && line[1] == '/') return true; if(line[0] == '*' && line[1] == '/' && line.length()==2) {flag = false; return true;} if(line[0] == '/' && line[1] == '*' && line.length()==2) return flag = true; if(line[0] == '/' && line[1] == '*' && line.find("*/")==string::npos) return flag = true; string::size_type idx = line.find("/*"); if(idx != string::npos) { flag = true; } if(flag) { idx = line.find("*/"); if(idx != string::npos) { flag = false; line[idx] = line[idx+1] = ' '; string sub = line.substr(idx+2,line.length()-idx-2); trim(sub); if (judgeAndUpdateComment(sub,flag)) return true; } } return false; }
當然,要配合下面的函式裡呼叫
void Counter::countOneFile(string filepath) { ifstream file; file.open(filepath,ios::in); if (!file.is_open()) { cout << "can't open the file :" << filepath << endl; exit(1); } char buffer[10000]; bool comment_flag = false; while (!file.eof() ) { file.getline(buffer,10000); string line(buffer); trim(line); if (line.empty()) { m_blank_line++; } else if(comment_flag) //如果已經進入了註釋段 { m_comment_line++; judgeAndUpdateComment(line,comment_flag); //更新 */ } else if (judgeAndUpdateComment(line,comment_flag)) // 本身是註釋行 { m_comment_line++; } else { m_real_line++; } } cout << "finish: " << filepath << endl; }
這裡我沒有考慮雙引號的影響。雙引號裡的東西應該忽略的,但是我沒有考慮,如果出現類似
string str = "abcd /* "; 的程式碼,程式得出的結果是災難性的錯誤。有需要的同學自己加上。