如何在Java中计算注释(单行和多行)的行数?

5

我正在进行Java项目。其中有一个部分,我需要识别程序中的单行注释、多行注释和总注释数量。我需要您的指导来计算Java中的单行注释、多行注释和总注释行数。


1
你尝试过什么了吗?如果有,你卡在哪里了? - Bart Kiers
@Bart 自己完成这个任务并不容易,因为需要考虑到Unicode转义序列(\u000a或\u002f\u002f)、字符串字面量("http: //example.com")以及单行注释中的多行注释(// test /* test)等问题,可能还有其他一些陷阱。 - Christian Semrau
@Christian Semrau,我并没有说他/她应该自己做。我只是问他/她已经尝试过什么。这包括(在作业的情况下)执行这些计算的自己的代码,或者(在“专业”工作的情况下)他/她已经尝试过哪些工具和/或API。 - Bart Kiers
你是对的。没有冒犯之意! - Christian Semrau
你可以查看这个相关的答案 - trashgod
@Christian,不用在意。在我看来,为这样的任务编写自定义词法分析器并不是很难,只是有点繁琐。 :) - Bart Kiers
9个回答

3

如果你只想要有关注释和代码行数的摘要,可以查看CLOC。将其指向源目录,例如:

cloc src

...它将为您显示摘要。

CLOC还处理使自己解决此问题变得困难的边角情况-多行注释、字符串中的注释查找行等。以下内容:

package test;

public class Main {

/**
 * A javadoc comment.
 * @param args
 */
public static void main(String[] args) {
    System.out.println("/* This isn't a comment */");
    /* This is a comment */
    //Comment
    System.out.println("//Not comment");
}
//Comment
}

CLOC给出了2个空行、7个注释行和7个代码行。

是的,你可以自己用Java编写一些东西,但除非这是一个特定的作业问题(在这种情况下应该标记),否则为什么要重新发明轮子呢?你需要处理大量边角情况,进行大量测试以确保它工作正常,将其与现有工具进行比较等等,而当你已经有一个很好地完成工作的东西时,这样做真的没有意义。


cloc 是否考虑了我在问题评论中提到的陷阱? - Christian Semrau
@Christian Semrau 是的,它可以。我已经用一个例子更新了我的答案。 - Michael Berry
请问Java的实现在哪里?您提供的链接只有PHP的实现。 - Deepak
Cloc可以处理单行注释中的多行注释开头(它会正确地忽略它们)。但它不能处理Unicode转义序列,也不能处理字符串字面量中的块注释。这些已经是众所周知的限制,可以在Cloc文档中阅读到相关信息。 - Christian Semrau
@Christian Semrau 确实,它不是百分百可靠的。但对于大多数情况来说,它已经足够好了,要想出更好的东西需要付出相当大的努力(很可能不切实际)。 - Michael Berry
@Christian:对于你自己编写的代码,不应该有Unicode转义序列(用于换行或/)。如果我们有一些带有这种转义序列的代码,那么我们可以在首先转换为UTF-8后使用native2ascii(在“-reverse”模式下)来删除它们。 - Paŭlo Ebermann

2

这是我针对同样问题做的一个作业的链接,希望能对你有所帮助。

注意:它不完整,因为它没有计算Java中字符串(双引号内)中包含转义字符的双引号(如“/\”/”)作为代码行,而是将其视为注释。这个问题仍需要解决。

http://bit.ly/PDasu9

以下是解释:

Note :- This program is not optimized for performance, performance is not an attribute i care about here. I chose not to use Pattern.compile() among many other decisions.

I count the empty lines, comment lines and lines of code separately.

if there is any sentence which has a some tabs or just spaces, they are counted as
empty lines. They match with the regular expression \s*
\s - any whitespace character (\n\t\b)
 * - this means there can be any number of whitespace characters


comment lines are the ones that match any of the following conditions :-
1) have a // outside of a string
2) have a /* some comment */
3) have a /* but the '*/' is not found on the same line

The regular expression for the above can be found inside the code!

Lines of code are the ones that end in ')' , '}' , '{' or ';' (one problem with this approach is that it does not count lines that have code followed by comment as a line of code)

The summary of these three types of lines are provided by this program.

这并没有真正回答问题。你应该直接解释如何完成,而不仅仅是链接到一个代码示例,当其他人在以后遇到这个问题时,可能已经不存在了。 - PhonicUK
你应该在这里解释解决方案,而不是链接到一个文件。 - GenericJon
谢谢您的评论,我已经添加了解释。请告诉我如何使链接文件更加永久(是否有网站可以让我这样做?),这样您就不必担心我会意外删除它了。 - wlan0

1

它适用于我。它计算了Java文件中单行和多行注释的总数。

public class CountComment {

    public static void main(String[] args) throws IOException {
        try {
            String str;
            BufferedReader f = new BufferedReader(new FileReader("a.java"));
            LineNumberReader l = new LineNumberReader(f);
            int numberline = 0;
            int count = 0;
            while ((str = l.readLine()) != null) {
                numberline++;
                if (str.startsWith("/*")) {
                    while ((str = l.readLine()) != null) {
                        count++;
                        if (str.endsWith("*/")) {
                            count++;
                            break;
                        }
                    }
                }
                else if(str.startsWith("//")){
                    count++;
                }
            }
            System.out.println("" + count);
        } catch (FileNotFoundException e) {
            System.out.println("file not found");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

0

我的答案是:

public int countCommentLines(File file) throws IOException {
    BufferedReader input = new BufferedReader(new FileReader(file));
    int comments = 0;
    String line;
    while ((line = input.readLine()) != null) {
        line = line.trim();
        System.out.println(line);
        if (line.startsWith("//")) {
            //single line
            comments++;
        } else if (line.startsWith("/*")) {
            /* multiline
             * like this
             *  */
            comments++;
            while (!line.endsWith("*/")) {
                line = input.readLine().trim();
                comments++;
            }
        } else if (line.contains("/*")) { /* comments
        like this
        be careful with /* haha
        */
            Deque<Character> stack = new ArrayDeque<Character>();
            boolean hasStartOfComment = false;
            for (int i = 0; i < line.length() - 1; ++i) {
                if (stack.isEmpty() && line.charAt(i) == '/' && line.charAt(i + 1) == '*') {
                    // Yes this is the start of a block comment
                    hasStartOfComment = true;
                    break;
                } else if (line.charAt(i) == '\\'
                        && line.charAt(i + 1) == '\"' || line.charAt(i + 1) == '\'') {
                    // Well, it's escaped character
                    i++;
                    continue;
                } else if (line.charAt(i) == '\'' || line.charAt(i) == '\"') {
                    if (!stack.isEmpty() && stack.peek() == line.charAt(i)) {
                        stack.pop();
                    } else {
                        stack.push(line.charAt(i));
                    }
                    continue;
                }
            }
            if (!hasStartOfComment) {
                continue;
            }

            while (!line.endsWith("*/")) {
                line = input.readLine().trim();
                comments++;
            }
        }
    }
    return comments;
}

0

为了可靠地识别注释,需要解析语言的某些部分:不要计算字符串文字中的注释,在单行注释中忽略多行注释的开头以及反之,处理Unicode转义序列,如结束单行注释的\u000a。 - Christian Semrau

0

在Java中,您有两种类型的注释:

// - 行注释

/* */ - 块注释。

基于此,您可以做出简单的假设:

  • 如果行中存在“//”,则该行至少有一个注释。

  • 如果行中存在“/*”,则已打开注释块。

  • 如果注释块已打开(找到),请搜索关闭标记“*/”。

因此,您的任务是检查文件中的每一行是否符合这些假设。


你的假设必须小心处理:1)String s ="//";没有注释,2)行// single /* line不会开始块注释,3)序列*\u002f结束块注释。 - Christian Semrau

0

在我的一个课程作业中,我编写了一个简单的Java代码来完成这个任务。 https://github.com/chetanpawar0989/CommentAnalysis

我之前创建了这个文件,但最近添加到了Github上。 该程序逐行运行一个文件。它在运行时需要一个输入参数filename.java

例如,要运行此程序:java CommentAnalysis filename.java

它会计算单行注释(//)以及多行注释(/* ... */)。

我尝试涵盖this file中提到的不同注释场景。

我还在自述文件中写下了我的实现假设,但根据个人需求进行更改应该不难。请查看并告诉我是否遗漏了任何注释场景。


0
//Below is the working code 

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class CountComment {

    public static void main(String[] args) {
        String line="";
        int count=0;
        try {
            BufferedReader br=new BufferedReader(new FileReader("./src/numbers/comment.txt"));
                while((line=br.readLine())!=null)
                {
                    if(line.startsWith("//"))
                        count++;
                    if(line.startsWith("/*"))
                    {
                        count++;
                        while(!(line=br.readLine()).endsWith("'*\'"))
                        {
                        count++;
                        break;
                        }
                    }

                }
                br.close();
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
             catch (IOException e) {
                e.printStackTrace();
            }

        System.out.println("count="+count);
        } 


    }

0

我尝试过它,它运行得非常好。使用下面的代码,您将需要检查每一行:

                if (isEmpty(s) || s.IndexOf("\"//\"") != -1 || s.IndexOf("\"/*\"") != -1|| s.IndexOf("\"*/\"") != -1) continue;
                if (s.IndexOf("/*") != -1) checkCML = true;
                if (s.IndexOf("*/") != -1) checkCML = false;

                if (s.IndexOf("/*") != -1 && s.IndexOf("*/") != -1) ++commentLine;

                if (s.IndexOf("//") != -1 || checkCML) ++commentLine;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接