我正在对 C++ 项目的行计数器进行一些研究,我对他们使用的算法非常感兴趣。有谁知道我在哪里可以查看此类算法的一些实现?
4 回答
有cloc,这是一个免费的开源代码行数计数器。它支持多种语言,包括 C++。我个人使用它来获取我的项目的行数。
在它的sourceforge页面上,您可以找到 perl 源代码以供下载。
好吧,如果通过行计数器,您的意思是计算行数的程序,那么算法非常简单:只需计算'\n'
代码中的数量。另一方面,如果您的意思是计算 C++ 语句或产生其他指标的程序......虽然不是 100% 准确,但我过去仅通过计算 '}' 和 ';' 就得到了很好的结果 (当然,忽略注释以及字符串和字符文字中的那些)。任何更准确的东西都可能需要解析实际的 C++。
您不需要实际解析代码来计算行号,只需对其进行标记即可。
该算法可能如下所示:
int lastLine = -1;
int lines = 0;
for each token {
if (isCode(token) && lastLine != token.line) {
++lines;
lastLine = token.line;
}
}
在标记化期间您需要收集的唯一信息是:
- 它是什么类型的令牌(运算符,标识符,注释......)实际上您不需要在这里非常精确,因为您只需要区分“非代码令牌”(注释)和“代码代币”(其他)
- 令牌出现在文件中的哪一行。
关于如何标记,这是你自己想办法,但是为这样一个简单的案例手写标记器应该不难。您可以使用flex
,但这可能是多余的。
编辑
我已经提到了“标记化”,让我快速为您描述一下:
标记化是编译的第一阶段。分词的输入是文本(多行程序),输出是一个“令牌”序列,如:具有某种意义的符号。例如,以下程序:
#include "something.h"
/*
This is my program.
It is quite useless.
*/
int main() {
return something(2+3); // this is equal to 5
}
可能看起来像:
PreprocessorDirective("include")
StringLiteral("something.h")
PreprocessorDirectiveEnd
MultiLineComment(...)
Keyword(INT)
Identifier("main")
Symbol(LeftParen)
Symbol(RightParen)
Symbol(LeftBrace)
Keyword(RETURN)
Identifier("something")
Symbol(LeftParen)
NumericLiteral(2)
Operator(PLUS)
NumericLiteral(3)
Symbol(RightParen)
Symbol(Semicolon)
SingleLineComment(" this is equal to 5")
Symbol(RightBrace)
等等。
令牌,取决于它们的类型,可能具有附加到它们的任意元数据(即符号类型、运算符类型、标识符文本,或者可能是发现令牌的行号)。
然后将此类标记流馈送到解析器,解析器使用根据这些标记编写的语法生成规则,例如,构建语法树。
做一个完整的解析器会给你一个完整的代码语法树是具有挑战性的,尤其是如果它是我们正在谈论的 C++ 的话。但是,标记化(或“词法分析”或“词法分析”)更容易,尤其是。当您不关心太多细节时,您应该能够使用有限状态机自己编写标记器。
关于如何实际使用输出来计算代码行数(即至少“代码”标记(即除注释之外的任何标记)开始的行) - 请参阅我之前描述的算法。
I think part of the reason people are having so much trouble understanding your problem is because "Count the lines of c++" is itself an algorithm. Perhaps what you're trying to ask is "How do I identify a line of c++ in a file?" That is an entirely different question which Kos seems to have done a pretty good job trying to explain.