【问题标题】:java string StringTokenizer doesn't recognize token after "//"?java字符串StringTokenizer在“//”之后无法识别令牌?
【发布时间】:2021-03-03 00:02:56
【问题描述】:

我正在编写一个代码,我只想在 java 文件中打印 cmets,当我有这样的 cmets 时它就可以工作

// a comment

但是当我有这样的评论时:

// /* cdcdf

它不会打印 "/* cdcdf" ,它只会打印一个空行 有人知道为什么会这样吗?

这是我的代码:

package printC;

import java.io.*; 
import java.util.StringTokenizer;
import java.lang.String ;


public class PrintComments {
    

    public static void main(String[] args) {
        try {
            String line;
            BufferedReader br = new BufferedReader(new FileReader(args[0]));
            while ((line = br.readLine()) != null) {
                if  (line.contains("//") ) {
                     StringTokenizer st1 =  new StringTokenizer(line, "//"); 
                     if(!(line.startsWith("//"))) {
                         st1.nextToken();
                     }
                     System.out.println(st1.nextToken()); 
                }
            }   
        }catch (Exception e) {
            System.out.println(e);
        }       
    }
}

【问题讨论】:

    标签: java


    【解决方案1】:

    StringTokenizer 采用分隔符集合,而不是单个字符串分隔符。所以它在'/'字符上分裂。 “第二个”标记是两个初始“//”之间的空标记。

    如果您只想要“//”之后的其余行,您可以使用:

    if(line.startsWith("//")) {
      line = line.substring(2);
    }
    

    【讨论】:

    • 如何在“//”字符串上拆分?因为这段代码不完整,我只是放了一小部分来理解问题,我实际上需要在“//”上进行拆分,因为有时有 cmet 是这样开头的“*/”
    • 我不明白这个解决方案。它不工作..
    【解决方案2】:

    @jtahlborn 答案的补充。您可以通过迭代令牌来检查所有令牌: 例如:

    ...
     StringTokenizer st1 =  new StringTokenizer(line, "//"); 
     while (st1.hasMoreTokens()){
            System.out.println("token found:" + st1.nextToken());
    }
    ...
    

    【讨论】:

    • 如何在“//”字符串上拆分?因为这段代码不完整,我只是放了一小部分来理解问题,我实际上需要在“//”上进行拆分,因为有时有 cmet 是这样开头的“*/”
    • 你真的想split 还是只想得到'//' 之后的剩余字符串?
    • 我想要剩下的
    • 但有时我有 */ 所以如果它只分裂 * 薄就会有问题
    【解决方案3】:

    如果您按行阅读,则 StringTokenizer 在您的代码中不会做太多事情。试试这个,把 if 的内容改成这样:

    if(line.trim().startWith("//")){//true only if líne start with //,aka: comment line
    //Do stuff with líne
    String cleanLine = line.trim().replace("//"," ");//to remove all // in line
    String cleanLine = línea.trim().substring(2,línea.trim().lenght());//to remove only the first //
    }
    

    注意:尝试始终使用 trim() 删除字符串开头和结尾的所有 Blanc 空格。

    按 // 分割线: líne.split("//")

    更多一般用途,请查看:

    Java - regular expression finding comments in code

    【讨论】:

      【解决方案4】:

      您可以通过查找// 的第一个位置来简化代码。 indexOf 可以很好地解决这个问题。您不需要标记,因为您真的只想要某个位置(或文本)之后的所有内容,您不需要将行分成多个部分。

      如果您找到//indexOf 不会为“未找到”返回 -1),则使用 substring 仅打印从该位置开始的字符。

      这个最小的例子应该做你想做的事:

      import java.io.*;
      import java.util.StringTokenizer;
      
      
      public class PrintComments {
          public static void main(String[] args) throws IOException {
              String line;    // comment
              BufferedReader br = new BufferedReader(new FileReader(args[0]));
              while ((line = br.readLine()) != null) {
                  int commentStart = line.indexOf("//");
                  if (commentStart != -1) {
                      System.out.println(line.substring(commentStart));
                  }
              } // /* that's it
          }
      }
      

      如果您不想打印 //,只需将 2 添加到 commentStart

      请注意,这种解析 cmets 的原始方法非常脆弱。如果您在自己的源代码上运行该程序,它也会很高兴地报告//");,对于indexOf 的行。任何认真的寻找 cmets 的尝试都需要正确解析源代码。

      编辑:如果您还想查找标记为/**/ 的其他 cmets,请对开始注释执行相同操作,然后在行尾查找结束注释。当所有评论都在一行上时,这将找到/* comment */。当它看到开头的/* 时,它会查看该行是否以结尾的*/ 结尾,如果是,则再次使用substring 来仅选择注释标记之间的部分。

      import java.io.*;
      import java.util.StringTokenizer;
      
      
      public class PrintComments {
          public static void main(String[] args) throws IOException {
              String line;    // comment
              BufferedReader br = new BufferedReader(new FileReader(args[0]));
              while ((line = br.readLine()) != null) {
                  int commentStart;
                  String comment = null;
      
                  commentStart = line.indexOf("//");
                  if (commentStart != -1) {
                      comment = line.substring(commentStart + 2);
                  }
      
                  commentStart = line.indexOf("/*");
                  if (commentStart != -1) {
                      comment = line.substring(commentStart + 2);
                      if (comment.endsWith("*/")) {
                          comment = comment.substring(0, comment.length() - 2);
                      }
                  }
      
                  if (comment != null) {
                      System.out.println(comment);
                  }
              } // /* that's it
              /* test */
          }
      }
      

      要为跨多行的 cmets 扩展此功能,您需要记住您是否处于多行注释中,以及是否继续打印 line 并检查结束 */

      【讨论】:

      • 太棒了,我实际上正在更改我所有的代码来做你所说的,但我有一个小问题,在我的代码中我也可以得到这样的评论 /* 评论 / ,我想出了如何找到 / 并查看它是否出现在 // 之前,但现在的问题是如何不打印 */ 最后
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      相关资源
      最近更新 更多