欢迎您来到芯片的主页!

Welcome to Chipset's homepage!

统计代码行和注释行

想找段代码统计注释行和代码行,在网上搜了半天也没有找到,干脆自己写一个算啦。。。
懒得罗嗦,直接看代码就行了,下面的代码里如果不用map,用vector更好。
  1 // parse_code_comment.hpp
  2 
  3 #pragma once
  4 
  5 #include <map>
  6 #include <fstream>
  7 #include <utility>
  8 
  9 
 10 namespace Comment
 11 {
 12 
 13 // source file Line types
 14 enum LineType { Blank = 0, Code = 1, CComment = 2, CppComment = 3,
 15                          CCodeComment = 4, CppCodeComment = 5 };
 16 
 17 // source file line type in string literal style
 18 static std::string LineArray[CppCodeComment + 1U=
 19 "Blank line""Code only""C Comment""C++ Comment",
 20   "Code and C Comment""Code and C++ Comment" };
 21 
 22 // read all characters of a txt style file into buffer and figure out the number of
 23 // code lines and the number of comment lines
 24 class file_code_comment
 25 {
 26 public:
 27   typedef std::map<int, LineType>::size_type size_type;
 28 
 29 public:
 30 
 31   file_code_comment(const std::string&);
 32 
 33   virtual ~file_code_comment();
 34 
 35   size_type size() const;
 36 
 37   std::pair<intint> code_comment() const;
 38 
 39   // list line number and type
 40   const std::map<int, LineType>& line_types() const;
 41 
 42 private:
 43 
 44   // in case of comment marks in string literals
 45   size_type skip_double_quotes(const std::string&const std::string&, size_type) const;
 46 
 47   std::pair<LineType, bool> cppcode_comment(const std::string&, size_type, size_type) const;
 48 
 49   std::pair<LineType, bool> multicomment(const std::string&, size_type, size_type, size_type) const;
 50 
 51 //  [Blank]
 52 //  if(a == b) [Code]
 53 //  //  [CppComment]
 54 //  /*  */ [CComment]
 55 //  /*  [CComment]
 56 //  */ [CComment]
 57 //   */ [CComment]
 58 //  if(a == b) /*  */ [CCodeComment]
 59 //  if(a == b) /*  [CCodeComment]
 60 //  */ [CCodeComment]
 61 //   [CCodeComment]
 62 // /*  */ if(a == b) [CCodeComment]
 63 // if(a == b) //  [CppCodeComment]
 64 
 65   // deduce what line type is for a string literal
 66   std::pair<LineType, bool> line_type(const std::string&, size_type&const;
 67 
 68   void read_ccomment(const std::string&, std::ifstream&int&);
 69 
 70   // Read source and figure out code lines, blank lines, comment lines
 71   void read_file(const std::string&);
 72 
 73   size_type skip_leading_space(const std::string&, size_type = 0const;
 74 
 75 
 76 private:
 77 
 78   void initialize(const std::string&);
 79 
 80   static const std::string cppcmt;     // C++ comment //
 81   static const std::string ccmt_start; // C comment start /*
 82   static const std::string ccmt_end;   // C comment end */
 83 
 84   std::map<int, LineType> m_code_comment; // <line number, LineType>
 85 };
 86 
 87 file_code_comment::file_code_comment(const std::string& file) :
 88   m_code_comment()
 89 {
 90   initialize(file);
 91 }
 92 
 93 file_code_comment::~file_code_comment() { m_code_comment.clear(); }
 94 
 95 file_code_comment::size_type file_code_comment::
 96   skip_leading_space(const std::string& str, size_type idx) const
 97 {
 98   for(; idx < str.size() && (' ' == str[idx] || '\t' == str[idx]); ++idx);
 99   return idx;
100 }
101 
102 file_code_comment::size_type file_code_comment::size() const
103 {
104   return m_code_comment.size();
105 }
106 
107 std::pair<intint> file_code_comment::code_comment() const
108 {
109   int code = 0// the number of code lines
110   int cmt = 0;  // the number of comment lines
111   for(std::map<int, LineType>::const_iterator cit(m_code_comment.begin());
112       cit != m_code_comment.end(); ++cit)
113     switch(cit->second)
114     {
115       case Code: ++code; break;
116       case CComment:
117       case CppComment: ++cmt; break;
118       case CCodeComment:
119       case CppCodeComment: ++code; ++cmt; break;
120       case Blank:
121       defaultbreak;
122     }
123   return std::make_pair(code, cmt);
124 }
125 
126 // list line number and type
127 const std::map<int, LineType>& file_code_comment::line_types() const
128 {
129   return m_code_comment;
130 }
131 
132 // ignore comment marks in double quotes
133 // "/*" "*/"
134 // " // "
135 file_code_comment::size_type file_code_comment::skip_double_quotes
136   (const std::string& str, const std::string& cmt, size_type idx) const
137 {
138   for(; idx < str.size(); ++idx)
139   {
140     idx = str.find(cmt, idx);
141     if(str.size() < idx)
142     {
143       idx = str.size();
144       break;
145     }
146     size_type ridx = str.find('"', idx);
147     if(str.size() < ridx)
148       break;
149     size_type lidx = str.rfind('"', idx);
150     if(str.size() < lidx)
151       break;
152     if(lidx < idx && idx < ridx)
153       idx = ridx;
154     else
155       break;
156   }
157   return idx;
158 }
159 
160 // many C style comment blocks in one single line match?
161 std::pair<LineType, bool> file_code_comment::cppcode_comment(const std::string& str,
162                                                              size_type lidx,
163                                                              size_type idx) const
164 {
165   if(lidx == idx)
166     return std::make_pair(CppComment, false);
167   else
168   {
169     idx = str.size();
170     if(lidx < str.size())
171       return std::make_pair(CppCodeComment, false);
172     else
173       return std::make_pair(Code, false);
174   }
175 }
176 
177 // /* */ while /* */ // /*
178 // /* ************** */ while {} /* ** */  //  
179 // /* ******* */
180 
181 std::pair<LineType, bool> file_code_comment::multicomment(const std::string& str,
182                                                                                            size_type eidx,
183                                                                                            size_type ridx,
184                                                                                            size_type idx) const
185 {
186   size_type cnts = 0;
187   size_type cnte = 0;
188   LineType type = CComment;
189   if(idx < ridx)
190     type = CCodeComment;
191   bool code_found = false;
192   while(ridx < eidx)
193   {
194     ++cnts;
195     ridx = skip_double_quotes(str, ccmt_end, ridx + 2U); // +2 skip /*
196     if(ridx < eidx)
197     {
198       ridx += 2U// +2 skip */
199       idx = ridx;
200       ++cnte;
201       ridx = skip_double_quotes(str, ccmt_start, ridx);
202       if(skip_leading_space(str, idx) < ridx)
203         code_found = true;
204     }
205   }
206   if(code_found)
207     type = CCodeComment;
208   return std::make_pair(type, cnte < cnts);
209 }
210 
211 // deduce what line type is for a string literal
212 std::pair<LineType, bool> file_code_comment::line_type(const std::string& str,
213                                                        size_type& idx) const
214 {
215   idx = skip_leading_space(str);
216   if(str.size() == idx)
217     return std::make_pair(Blank, false);
218   else
219   {
220     size_type lidx = skip_double_quotes(str, cppcmt, idx);
221     size_type ridx = skip_double_quotes(str, ccmt_start, idx);
222     /* Somettimes C comments and C++ comments (or Code) are mixed in a single line */
223     if(lidx < ridx)      // C++ comment first then CppComment or CppCodeComment
224       return cppcode_comment(str, lidx, idx);
225     else if(ridx < lidx) // C comment first then CComment or CCodeComment
226       return multicomment(str, lidx, ridx, idx);
227     else // no comment
228       return std::make_pair(Code, false);
229   }
230 }
231 
232 
233 void file_code_comment::read_ccomment(const std::string& str, std::ifstream& fin,
234                                       int& line)
235 {
236   std::string tstr;
237   while(std::getline(fin, tstr))
238   {
239     ++line;
240     size_type idx = skip_leading_space(tstr);
241     if(tstr.size() == idx)
242     {
243       m_code_comment.insert(std::make_pair(line, Blank));
244     }
245     else
246     {
247       m_code_comment.insert(std::make_pair(line, CComment));
248       if(skip_double_quotes(tstr, ccmt_end, 0< tstr.size()) // found */
249         break;
250     }
251   }
252 }
253 
254 // Read source and figure out code lines, blank lines, comment lines
255 void file_code_comment::read_file(const std::string& file)
256 {
257   std::ifstream fin(file.c_str());
258   if(!fin.is_open())
259   {
260     std::cerr << "Failed to open file '" << file
261               << "' @ Comment::file_code_comment\n";
262     return;
263   }
264   std::string str;
265   size_type idx = 0;
266   int line = 0;
267   while(std::getline(fin, str))
268   {
269     ++line;
270     std::pair<LineType, bool> tp = line_type(str, idx);
271     m_code_comment.insert(std::make_pair(line, tp.first));
272     switch(tp.first)
273     {
274       case Blank:
275       case Code:
276       case CppComment:
277       case CppCodeComment: break;
278       case CComment:
279       case CCodeComment: if(tp.second)
280                                          read_ccomment(str, fin, line);
281                                        break;
282       defaultbreak;
283     }
284   }
285 }
286 
287 void file_code_comment::initialize(const std::string& file)
288 {
289   read_file(file);
290 }
291 
292 const std::string file_code_comment::cppcmt("//");     // C++ comment //
293 const std::string file_code_comment::ccmt_start("/*"); // C comment start /*
294 const std::string file_code_comment::ccmt_end("*/");   // C Comment end */
295 
296 // namespace Comment
297 

posted on 2013-08-24 23:46 Chipset 阅读(1562) 评论(0)  编辑 收藏 引用 所属分类: 算法和数据结构消遣


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理