【问题标题】:Counting lines of code计算代码行数
【发布时间】:2012-07-04 15:14:14
【问题描述】:

我正在研究 C++ 项目的行计数器,我对他们使用的算法非常感兴趣。有谁知道我在哪里可以查看此类算法的一些实现?

【问题讨论】:

  • 请原谅我的无知,但什么是行数?
  • #SamIam 原谅你的无知,因为我从来没有提到行计数,而是行计数器。如果您向我提供 Google,我会为您输入,以便您了解我所说的 C++ 项目行计数器的含义。
  • ??标题是Algorithms for line counting
  • 你对线的确切定义是什么?
  • @smallB:我再次概述了上面的算法。通过源代码,确定每一行是否包含代码,如果是,则增加计数器。你不需要超过这个算法。但是你说这是错误的。所以请告诉我们,当您想计算其中包含代码的行数时,计算其中包含代码的行数的算法可能会出错。

标签: c++ lines-of-code


【解决方案1】:

cloc,这是一个免费的开源代码行数计数器。它支持多种语言,包括 C++。我个人使用它来获取我的项目的行数。

在其sourceforge 页面,您可以找到下载的 perl 源代码。

【讨论】:

    【解决方案2】:

    好吧,如果用行计数器,你的意思是计算行数的程序,那么 算法非常简单:只需计算'\n' 中的数量 代码。另一方面,如果您的意思是计算 C++ 的程序 陈述,或产生其他指标......虽然不是 100% 准确, 过去我只计算'}'和 ';' (忽略 cmets 以及字符串和字符文字中的那些, 课程)。任何更准确的东西都可能需要解析 实际的 C++。

    【讨论】:

    • 我的意思是计算 C++ 文件中物理代码行数的算法。我害怕数'}'和';'除了最简单的情况外,其他任何事情都太原始了。
    • @smallB 这取决于您要测量的内容。如果真的是线条,请使用wc -l。这个算法真的是只计算'\n';计算 '}' 和 ';' 更加原始(这确实给出了程序中语句数量的良好一阶近似值)。
    • @smallB 计数行数行数。不清楚你想要什么。剥离 cmets 并计算非空行?鉴于 C++ 不是面向行的,什么是一行代码?
    • 正如我向 PlasmaHH 解释的那样,代码行与其中的代码一致。它可以变得多简单?
    • @smallB:看,这就是问题所在。 /You/ 是决定一行代码是什么的人,因为 /you/ 是要求算法的人。您在上面抱怨它很简单(“代码行与其中的代码一致。它可以变得多么简单?”),但是您没有定义其中的代码行是什么。为你。显然,困难来自您没有正确定义的事实,这就是为什么您必须询问“int a = 0;”的原因是代码。但关键是/你/想要一个算法,拒绝很多现有的工具,说它没有做你想做的事。但你永远不会说出你想要什么。
    【解决方案3】:

    您不需要实际解析代码来计算行号,将其标记化就足够了。

    算法可能如下所示:

    int lastLine = -1;
    int lines = 0;
    for each token {
        if (isCode(token) && lastLine != token.line) {
            ++lines; 
            lastLine = token.line;
        }
    }
    

    在标记化过程中您需要收集的唯一信息是:

    • 它是什么类型的标记(操作符、标识符、注释...)您实际上不需要在这里非常精确,因为您只需要区分“非代码标记”(cmets)和“代码令牌”(其他)
    • 令牌出现在文件中的哪一行。

    关于如何标记化,这是你自己想办法,但是为这样一个简单的案例手写标记器应该不难。你可以使用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++ 时。但是,标记化(或“词法分析”或“词法分析”)更容易,尤其是。当您不关心太多细节时,您应该能够使用Finite state machine 自己编写标记器。

    关于如何实际使用输出来计算代码行数(即至少“代码”标记的行,即除注释之外的任何标记) - 请参阅我之前描述的算法。

    【讨论】:

    • 除了简单的情况外,这对任何事情都不起作用。多行注释呢?我需要的是,不要在五分钟内看到某人编造的某种算法,我看了 2 秒后发现它不起作用。而是一种实际应用在实际应用中的真实世界算法。
    • 恐怕您还没有理解我所描述的内容。我会尽量详细说明
    • 我已经扩展了我的答案,希望你现在明白;也请尽量保持礼貌,避免鄙视那些花时间帮助你的回答者
    • 感谢您的回答,但我仍然相信您的算法不会正确计算每一行。如果您有跨越几行的多行注释怎么办?您的算法没有考虑到这一点。
    • 我在哪个地方不礼貌?
    【解决方案4】:

    我认为人们难以理解您的问题的部分原因是“计算 c++ 的行数”本身是一种算法。也许您想问的是“我如何识别文件中的一行 c++?”这是一个完全不同的问题,科斯似乎在试图解释方面做得很好。

    【讨论】:

    • 他的 (Kos's) 算法不正确。在更复杂的场景中不会正确计算代码行数。
    • 如:line 1: /*comment */ code; /*注释*/ 代码;他的算法会将这一行视为两行代码。这是错误的。你不能发挥你的想象力吗?在你问我什么是代码行之前,请参阅我的其他 cmets,我在其中不止一次解释了这一点。
    • @smallB:他的解决方案很好地涵盖了这一点。您所要做的就是在一行中看到代码标记后,停止阅读该行。
    • 但他的算法不这样做是吗?还有其他场景,他的算法没有被削减(是的,没有被削减)。因此,当我说他的算法不正确时,这意味着他提出的算法不会在每种可能的情况下正确计算代码行数。
    • @smallB 我要把自己从这个对话中删除。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多