📄 countingdlg.cpp
字号:
BOOL bQuatoSet = FALSE; //字符串统计标识 首次一行有奇数个"时TRUE, 下一行有奇数个"时FALSE
int nLength = file.GetLength();
*pnLength = nLength;
CString bufRead;
int nLineCommentBegin = 0;
while(file.ReadString(bufRead)!=FALSE)
{
nLines++;
bufRead.TrimLeft(); //先将文件头的空格或制表符去掉
if(bufRead.GetLength()==0) //为空白行
{
nBlankLines++;
continue;
}
int nDoubleSplashFoundAt = bufRead.Find("//"); // 注释符//发现于何处
if(nDoubleSplashFoundAt!=-1 /*&& !bCommentSet*/)
{
if(nDoubleSplashFoundAt==0&&!bCommentSet&&!bQuatoSet)
{
nCommentLines++;
continue;
}
CString strRight = bufRead;
BOOL bCounted = FALSE;
do{
CString strLeft = strRight.Left(nDoubleSplashFoundAt);
if(strLeft.Find("\"")!=-1)
{
int nQuatos = HowManyCharsInString(strLeft, "\"", bCommentSet);
if((!bQuatoSet&&!IsOdd(nQuatos))&&(bQuatoSet&&IsOdd(nQuatos)))
//当前一行字符串继续时,只要//之前的"号为偶数个,则说明该//为注释符,否则,为引号内部//,非注释符
//其他,奇数个说明//未注释符
{
if(m_nStatMethod==0){ nCodeLines++; bCounted=TRUE;}
else if(m_nStatMethod==1){ nCodeLines++; nCommentLines++; bCounted=TRUE;}
else if(m_nStatMethod==2){ nCommentLines++; bCounted=TRUE;}
if(bQuatoSet&&IsOdd(nQuatos))bQuatoSet = FALSE;
}
}
strRight = strRight.Right(strRight.GetLength()-nDoubleSplashFoundAt-2);
}while(strRight.Find("//")!=-1&&!bCounted);
if(bCounted)continue;
strRight = bufRead;
bCounted = FALSE;
do{
CString strLeft = strRight.Left(nDoubleSplashFoundAt);
if(strLeft.Find("/*")!=-1)
{
int nCommB = HowManyCharsInString(strLeft, "/*", bCommentSet);
int nCommE = HowManyCharsInString(strLeft, "*/", bCommentSet);
if((!bCommentSet&&nCommB==nCommE)&&(bCommentSet&&nCommB==nCommE-1))
//当前一行字符串继续时,只要//之前的/*个数等于*/的个数,则说明该//为注释符
//其他,/*个数比*/个数少一个说明//未注释符
{
if(m_nStatMethod==0){ nCodeLines++; bCounted=TRUE;}
else if(m_nStatMethod==1){ nCodeLines++; nCommentLines++; bCounted=TRUE;}
else if(m_nStatMethod==2){ nCommentLines++; bCounted=TRUE;}
if(bCommentSet&&nCommB==nCommE-1)bCommentSet = FALSE;
}
}
strRight = strRight.Right(strRight.GetLength()-nDoubleSplashFoundAt-2);
}while(strRight.Find("/*")!=-1&&!bCounted);
if(bCounted)continue;
}
int nStartComment = bufRead.Find("/*");
if(nStartComment == 0 && !bCommentSet ) // "/*" is the first two chars
{
bCommentSet = TRUE;
// nLineCommentBegin = nLines;
}
else if(nStartComment != -1 &&!bCommentSet) // "/*" is not the first two chars though found. so it's a code line
{
bCommentSet = TRUE;
nLineCommentBegin = nLines;
nCommentLines --; //最终的nCommentLines会加1,所以此处要先减1
if(bufRead.Find("\"")!=-1) //防止/*在两个"之间,如 "...../*.....",这种/*不是注释符
{
CString strTemp = bufRead.Left(nStartComment); //开始到/*之间的代码
int nCountQuota=0;
int i=1;
if(strTemp[0]=='\"')nCountQuota++;
while((strTemp[i]=='\"'&&strTemp[i-1]!='\\')&&i<strTemp.GetLength() )
{
nCountQuota++;
i++;
}
if((nCountQuota/2)*2 != nCountQuota)//nCountQuota为奇数,则说明/*在引号中,此处非注释行,还原bCommentSet
{
bCommentSet = FALSE;
nCommentLines ++;
}
}
}
bufRead.TrimRight();
int nEndComment = bufRead.Find("*/");
if(bufRead.GetLength()>=2 && (nEndComment == (bufRead.GetLength()-2)) && bCommentSet)
//至少有两个字符 */在该行的最后 前面有/*
{
bCommentSet = FALSE;
nCommentLines ++;
}
else if(nEndComment != -1 && bCommentSet)// */不在该行最后,则需要继续判断
{
bCommentSet = FALSE;
if(nLineCommentBegin == nLines) // /* */ on the same line
nCommentLines++;
CString strRight = bufRead.Right(bufRead.GetLength()-nEndComment-2);
if(strRight.Find("//")!=-1) //it is very strange! such as "code */ (code or blank) // code"
{
strRight.TrimLeft();
if(strRight.Find("//")==0)
nCommentLines++;
}
else if(nLineCommentBegin != nLines && strRight.GetLength()==0)
nCommentLines++;
}
if(bCommentSet)
nCommentLines++;
if(IsOdd(HowManyCharsInString(bufRead, "\"", bCommentSet))&&!bCommentSet)
{
// if(bQuatoSet)
// {//本行继续前一行的字符串
// BOOL bCommentBegin = FALSE;
// for(int i=0; i<bufRead.GetLength(); i++)
// {
// if(bufRead[i]=='"' && !bCommentBegin)
// bQuatoSet = !bQuatoSet;
// if((!bQuatoSet && bufRead[i]=='/' && bufRead[i+1]=='/')||((!bQuatoSet && bufRead[i]=='/' && bufRead[i+1]=='*')))
// bCommentBegin = TRUE;
// }
// }
// else
// {//本行可能新起一行字符串
BOOL bCommentBegin = FALSE;
for(int i=0; i<bufRead.GetLength()-1; i++)
{
if(bufRead[i]=='"' && !bCommentBegin)
bQuatoSet = !bQuatoSet;
if((!bQuatoSet && bufRead[i]=='/' && bufRead[i+1]=='/')||((!bQuatoSet && bufRead[i]=='/' && bufRead[i+1]=='*')))
bCommentBegin = TRUE;
}
if(bQuatoSet && bufRead[bufRead.GetLength()-1]!='\\')//字符串本行未结束,但本行最后一个字符不是\,则可能有误
{
CString strMsg;
// strMsg.Format("文件%s的第%d行可能有问题");
AfxMessageBox(strMsg);
}
// }
}
}
*pnCommentLines = nCommentLines;
*pnBlankLines = nBlankLines;
file.Close();
return nLines;
}
/*********************************************************
统计c++文件 1.0版本
*********************************************************/
int CCountingDlg::GetCppFileLines_1_0(LPCTSTR strFileName, int* pnLength, int *pnCodeLines, int* pnCommentLines, int* pnBlankLines)
{
//there are two methods to count lines in files, by CStdioFile or CFile
*pnLength = 0;
*pnCommentLines = 0;
*pnBlankLines = 0;
CStdioFile file;
if(file.Open(strFileName, CFile::modeRead)==FALSE)
return 0;
int nLines = 0;
int nCommentLines = 0;
int nBlankLines = 0;
BOOL bCommentSet = FALSE; //注释行统计标识 有"/*"时TRUE, "*/"时FALSE
int nLength = file.GetLength();
*pnLength = nLength;
CString bufRead;
int nLineCommentBegin = 0;
while(file.ReadString(bufRead)!=FALSE)
{
nLines++;
bufRead.TrimLeft(); //先将文件头的空格或制表符去掉
if(bufRead.GetLength()==0) //为空白行
{
nBlankLines++;
continue;
}
if(bufRead.Find("//")==0 && !bCommentSet)
{
nCommentLines++;
continue;
}
int nStartComment = bufRead.Find("/*");
if(nStartComment == 0 && !bCommentSet ) // "/*" is the first two chars
{
bCommentSet = TRUE;
nLineCommentBegin = nLines;
}
else if(nStartComment != -1 &&!bCommentSet) // "/*" is not the first two chars though found. so it's a code line
{
bCommentSet = TRUE;
nLineCommentBegin = nLines;
nCommentLines --; //最终的nCommentLines会加1,所以此处要先减1
if(bufRead.Find("\"")!=-1) //防止/*在两个"之间,如 "...../*.....",这种/*不是注释符
{
CString strTemp = bufRead.Left(nStartComment); //开始到/*之间的代码
int nCountQuota=0;
int i=1;
if(strTemp[0]=='\"')nCountQuota++;
while((strTemp[i]=='\"'&&strTemp[i-1]!='\\')&&i<strTemp.GetLength() )
{
nCountQuota++;
i++;
}
if((nCountQuota/2)*2 != nCountQuota)//nCountQuota为奇数,则说明/*在引号中,此处非注释行,还原bCommentSet
{
bCommentSet = FALSE;
nCommentLines ++;
}
}
}
bufRead.TrimRight();
int nEndComment = bufRead.Find("*/");
if(bufRead.GetLength()>=2 && (nEndComment == (bufRead.GetLength()-2)) && bCommentSet)
//至少有两个字符 */在该行的最后 前面有/*
{
bCommentSet = FALSE;
nCommentLines ++;
}
else if(nEndComment != -1 && bCommentSet)// */不在该行最后,则需要继续判断
{
bCommentSet = FALSE;
if(nLineCommentBegin == nLines) // /* */ on the same line
nCommentLines++;
bufRead = bufRead.Right(bufRead.GetLength()-nEndComment-2);
if(bufRead.Find("//")!=-1) //it is very strange! such as "code */ (code or blank) // code"
{
bufRead.TrimLeft();
if(bufRead.Find("//")==0)
nCommentLines++;
}
else if(nLineCommentBegin != nLines && bufRead.GetLength()==0)
nCommentLines++;
}
if(bCommentSet)
nCommentLines++;
}
*pnCommentLines = nCommentLines;
*pnBlankLines = nBlankLines;
file.Close();
return nLines;
//下述代码不是使用CStdioFile,有错误
/* CFile file;
file.Open(strFileName, CFile::modeRead);
int nLines = 0;
int nCodeLines = 0;
int nCommentLines = 0;
int nBlankLines = 0;
BOOL bLastSplash = FALSE;
BOOL bDoubleSplash = FALSE;
BOOL bLastStar = FALSE;
BOOL bCommentCount = FALSE;
BOOL bBlankCount = TRUE;
int nLength = file.GetLength();
m_nSize += nLength;
*pnLength = nLength;
char buf[255];
int nRead = 0;
while(nLength>0)
{
nRead = file.Read(buf, 250);
if(buf[0] == '*' && bLastSplash)
{
bLastSplash = FALSE;
bCommentCount = TRUE;
}
if(buf[0] == '/' && bLastSplash && !bCommentCount && bBlankCount && !bDoubleSplash)
{
bLastSplash = FALSE;
bDoubleSplash = TRUE;
}
if(buf[0] == '/' && bLastStar)
{
bLastStar = FALSE;
bCommentCount = FALSE;
nCommentLines++;
}
for(int i=0; i<nRead; i++)
{
if(buf[i] == '/')
{
if(i<nRead-1 && buf[i+1]=='*' && !bDoubleSplash )
bCommentCount = TRUE;
if(i<nRead-1 && buf[i+1]=='/' && !bCommentCount && bBlankCount && !bDoubleSplash)
bDoubleSplash = TRUE;
if(i==nRead-1)
bLastSplash=TRUE;
}
if(buf[i] == '*')
{
if(i<nRead-1 && buf[i+1]=='/')
{
bCommentCount = FALSE;
nCommentLines++;
}
if(i==nRead-1)
bLastStar=TRUE;
}
if( buf[i]!=' ' && buf[i]!='\t' && buf[i]!='\r' && buf[i]!='\n')//&& bBlankCount)
bBlankCount = FALSE;
if(buf[i]=='\n')
{
nLines++;
if(bBlankCount)nBlankLines++;
if(bBlankCount && bCommentCount)nCommentLines--;
if(bDoubleSplash)
{
nCommentLines++;
bDoubleSplash = FALSE;
}
bBlankCount = TRUE;
if(bCommentCount) nCommentLines++;
}
}
nLength -= nRead;
}
if(buf[nRead-1]!='\n')
nLines++;
if(bDoubleSplash)
nCommentLines++;
*pnCommentLines = nCommentLines;
*pnBlankLines = nBlankLines;
file.Close();
return nLines;
*/
}
/*****************************************************************
统计SQL文件的行数
*****************************************************************/
int CCountingDlg::GetSqlFileLines(LPCTSTR strFileName, int *pnLength, int *pnCodeLines, int *pnCommentLines, int *pnBlankLines)
{
*pnLength = 0;
*pnCommentLines = 0;
*pnBlankLines = 0;
CStdioFile file;
if(file.Open(strFileName, CFile::modeRead)==FALSE)
return 0;
int nLines = 0;
int nCommentLines = 0;
int nBlankLines = 0;
BOOL bCommentSet = FALSE;
int nLength = file.GetLength();
m_nSize += nLength;
*pnLength = nLength;
CString bufRead;
while(file.ReadString(bufRead)!=FALSE)
{
nLines++;
bufRead.TrimLeft();
if(bufRead.GetLength()==0)
{
nBlankLines++;
continue;
}
if(bufRead.Find("--")==0 && !bCommentSet)
{
nCommentLines++;
continue;
}
int nStartComment = bufRead.Find("/*");
if(nStartComment == 0 && !bCommentSet ) // "/*" is the first two chars
{
bCommentSet = TRUE;
}
else if(nStartComment != -1 &&!bCommentSet) // "/*" is not the first two chars though found. so it's a code line
{
bCommentSet = TRUE;
nCommentLines --;
}
bufRead.TrimRight();
int nEndComment = bufRead.Find("*/");
if(bufRead.GetLength()>=2 && (nEndComment == bufRead.GetLength()-2))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -