文档名称:软件总代码行数_软件注释率分析作者:日期:1. cncc1.1 工具简介度量工具名称cncc网址/操作方式命令行实现语言C++适用的操作系统Windows可以度量的属性code-lines, empty-lines, comment-lines, total-lines备注1.2 工具优缺点总结最新版本 cncc-1-3-1,在sourceforge中2004年已经停止更新。
最大的优点是源代码全部存于一个cpp文件,便于集成。
缺点:1.代码基本没有注释。
2.下载的代码编译有9个错误。
3.费了2个多小时也没搞定。
1.3 使用例程无。
2. CodeCount2.1 工具简介度量工具名称CodeCount网址/downloads421/sourcecode/windows/control/detail1783204.html操作方式GUI实现语言C++适用的操作系统Windows可以度量的属性total-lines, empty-lines, comment-lines, code-lines,备注2.2 工具优缺点总结优点:工具比较精简,统计源文件总行数、代码行数、空白行数、注释行数,代码有一定的注释。
缺点:下载的源码是vc7工程,由于机器并没有vc7,利用工具进行工程类型转换,将vc7的工程转换为vc6的工作,编译出错。
核心代码如下:BOOL bCommentSet = FALSE; //注释行统计标识有"/*"时TRUE, "*/"时FALSEBOOL bQuatoSet = FALSE; //字符串统计标识首次一行有奇数个"时TRUE, 下一行有奇数个"时FALSEint nLength = (int)file.GetLength();CString bufRead;int nLineCommentBegin = 0;while(file.ReadString(bufRead)!=FALSE){BOOL bStatedComment = FALSE;//本行作为注释行是否已统计过BOOL bStatedCode = FALSE; //本行作为代码行是否已统计过nLines++;bufRead.TrimLeft(); //先将文件头的空格或制表符去掉if(bufRead.GetLength()==0) //为空白行{nBlankLines++;continue;}if(bCommentSet && bufRead.Find(_T("*/"))==-1){nCommentLines++;continue;}if(bufRead.Find(_T("//"))==-1 && bufRead.Find(_T("/*"))==-1 &&bufRead.Find(_T("*/"))==-1){//如果本行根本就无注释符,则要不是注释符,要不是代码行if(bCommentSet){nCommentLines++; continue;}else{if(bufRead.Find('"')==-1){nCodeLines++; continue;}}}if(bufRead.Find(_T("//"))==0 && !bCommentSet && !bQuatoSet){nCommentLines++;continue;}BOOL bDoubleSplashFound = FALSE;BOOL bSplashStarFound = FALSE;for(int i=0; i<bufRead.GetLength()-1; i++){//char cTemp = bufRead[i];wchar_t cTemp = bufRead[i];if(bufRead[i]=='/' && bufRead[i+1]=='/' && !bCommentSet && !bQuatoSet){if(!bStatedComment && (m_nStatMethod==1 || m_nStatMethod ==2)){bStatedComment = TRUE;nCommentLines++;}bDoubleSplashFound = TRUE;//i++;//应该+1,但也没有什么用处break;}else if(bufRead[i]=='/' && bufRead[i+1]=='*' && !bCommentSet && !bQuatoSet) {if(!bStatedComment && (m_nStatMethod==1 || m_nStatMethod ==2)){bStatedComment = TRUE;nCommentLines++;}bCommentSet = TRUE;bSplashStarFound = TRUE;i++;}//计算代码行必须在bCommentSet关闭之前else if(bufRead[i]!=' ' && bufRead[i]!='\t' && !bCommentSet){if(!bStatedCode){bStatedCode = TRUE;nCodeLines++;}if(bufRead[i]=='\\'){//\之后的字符要跳过i++;continue;}if(bufRead[i]=='\''){if(bufRead[i+1]=='\\')i+=2;elsei+=1;continue;}if(bufRead[i]=='"'){//"必须引起重视,感谢ltzhoubQuatoSet = !bQuatoSet;}}else if(bufRead[i]=='*' && bufRead[i+1]=='/' && bCommentSet && !bQuatoSet){if(!bStatedComment && (m_nStatMethod==1 || m_nStatMethod ==2)){bStatedComment = TRUE;nCommentLines++;}bCommentSet = FALSE;bSplashStarFound = TRUE;i++;}}if(bDoubleSplashFound){if(m_nStatMethod==2 && bStatedCode) //如果统计方法为第三种,且同时有代码行与注释行,则只计注释行{nCodeLines--;}if(m_nStatMethod==0 && !bStatedCode)//如果统计方法为第一种,且未作为代码行统计过,那么必为注释行{nCommentLines++;}continue;}if(bufRead[bufRead.GetLength()-1]=='"'&&!bCommentSet){//若某行最后一个是",则必定用来关闭bQuatoSet,记代码行一行,否则报错bQuatoSet = !bQuatoSet;if(!bQuatoSet){if(!bStatedCode){bStatedCode = TRUE;nCodeLines++;}}else{CStdioFile fileLog;if(fileLog.Open(m_strLogFile,CFile::modeCreate|CFile::modeWrite|CFile::modeNoTruncate)==TRUE){CString strMsg;if(fileLog.GetLength()==0){strMsg.Format(_T("文件\t行\t问题\n"), strFileName, nLines);fileLog.WriteString(strMsg);}strMsg.Format(_T("%s\t%d\t字符串换行未用\\\n"), strFileName, nLines);fileLog.WriteString(strMsg);fileLog.Close();}}continue;}if(bufRead[bufRead.GetLength()-1]!=' ' && bufRead[bufRead.GetLength()-1]!='\t'&& !bCommentSet&& bufRead[bufRead.GetLength()-2]!='*' && bufRead[bufRead.GetLength()-1]!='/') {//如果最后一个字符非空格或制表符,且前面无/*,最后两个字符不是*/,则为代码行if(!bStatedCode){bStatedCode = TRUE;nCodeLines++;}}if(bSplashStarFound){if(m_nStatMethod==2 && bStatedCode) //如果统计方法为第三种,且同时有代码行与注释行,则只计注释行{nCodeLines--;}if(m_nStatMethod==0 && !bStatedCode && !bStatedComment) //若该行无代码如/*abc*/ //222//但是统计方法是第一种,则需要追加注释行计数一次{bStatedComment = TRUE;nCommentLines++;}}if(!bStatedComment && bCommentSet)//可能是前面有/*,在第一种统计方法中,未作为代码行计算过,那么本行肯定是注释行{if(m_nStatMethod==0 && !bStatedCode){bStatedComment = TRUE;nCommentLines++;}}if(bQuatoSet && bufRead[bufRead.GetLength()-1]!='\\'){CStdioFile fileLog;if(fileLog.Open(m_strLogFile,CFile::modeCreate|CFile::modeWrite|CFile::modeNoTruncate)==TRUE){CString strMsg;if(fileLog.GetLength()==0){strMsg.Format(_T("文件\t行\t问题\n"), strFileName, nLines);fileLog.WriteString(strMsg);}strMsg.Format(_T("%s\t%d\t字符串换行未用\\\n"), strFileName, nLines);fileLog.WriteString(strMsg);fileLog.Close();}}}file.Close();2.3 使用例程通过分析其源代码,抽取解析源文件部分的功能代码,构建独立的工程,经测试可以完成代码行等数据的统计工作,但仍需要进一步测试。