java字符串StringTokenizer在“//”之后无法识别令牌?

Posted

技术标签:

【中文标题】java字符串StringTokenizer在“//”之后无法识别令牌?【英文标题】:java string StringTokenizer doesn't recognize token after "//"? 【发布时间】: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);
               
    

【问题讨论】:

【参考方案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 并检查结束 */

【讨论】:

太棒了,我实际上正在更改我所有的代码来做你所说的,但我有一个小问题,在我的代码中我也可以得到这样的评论 /* 评论 / ,我想出了如何找到 / 并查看它是否出现在 // 之前,但现在的问题是如何不打印 */ 最后

以上是关于java字符串StringTokenizer在“//”之后无法识别令牌?的主要内容,如果未能解决你的问题,请参考以下文章

java StringTokenizer

java字符串分解 StringTokenizer用法

Java字符串StringTokenizer学习

Java--字符串使用StringTokenizer来分割字符,由小写转大写,由大写转小写

java.util.StringTokenizer的作用是啥?如何使用?

StringTokenizer类与String.split()的区别