【问题标题】:Iterator implementation is only reading first token in string?迭代器实现只读取字符串中的第一个标记?
【发布时间】:2017-02-21 06:28:04
【问题描述】:

对于这个程序,我需要实现一个令牌迭代器,它从字符串中扫描并存储一个有效的令牌。这似乎是一个简单的过程,但我的代码只返回字符串中的第一个有效标记。我需要调用 hasNext();在 next() 方法中的不同位置?

这是我的代码:

public class TokenIter implements Iterator<String>{

    //input line to be tokenized
    private String line;

    // the next Token, null if no next Token
    private String nextToken;

    //Edit
    private Scanner scan;

    public TokenIter(String line){
        this.line = line;
    }

    @Override
    public boolean hasNext() {
        //Edit
        scan = new Scanner(line);
            if(scan.hasNext()){
                nextToken = scan.next();
                return true;
            }
            scan.next();
            nextToken = null;
            return false;
    }

    @Override
    public String next() {
        if(!hasNext()){
            throw new NoSuchElementException();
        }
        else{
            if(nextToken.equals("true")){
                return nextToken;
            }
            if(nextToken.equals("false")){
                return nextToken;
            }
            if(nextToken.equals("or")){
                return nextToken;
            }
            if(nextToken.equals("and")){
                return nextToken;
            }
            if(nextToken.equals("not")){
                return nextToken;
            }
            if(nextToken.equals("(")){
                return nextToken;
            }
            if(nextToken.equals(")")){
                return nextToken;
            }
        }
        return "";      
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

    public static void main(String[] args){
        String line;
        args = Debug.init(args);
        if(args.length>0)
            line = args[0];
        else
            line = " not (true or error false) @# $% ";
        System.out.println("line: [" + line + "]");
        TokenIter tokIt = new TokenIter(line);
        while(tokIt.hasNext()){
            System.out.println("next token: [" + tokIt.next() + "]");
        }
    }

这是我正在运行的程序的输出:

line: [ not (true or error false) @# $% ]
next token: [not]
next token: [not]
next token: [not]
next token: [not]
next token: [not]
next token: [not]

这是我想要的输出:

line: [ not (true or error false) @# $% ]
next token: [not]
next token: [(]
next token: [true]
next token: [or]
next token: [false]
next token: [)]

【问题讨论】:

    标签: java iterator token


    【解决方案1】:

    您的hasNext() 方法不正确,您在每次调用时都在扫描line,因此您将始终返回第一个令牌:

     @Override
        public boolean hasNext() {
            Scanner scan = new Scanner(line);
                if(scan.hasNext()){
                    nextToken = scan.next();
                    return true;
                }
                scan.next();
                nextToken = null;
                return false;
    

    解决方案: 变量scan 需要成为一个类变量,这样您就可以在hasNext() 的调用之间保持状态。

    【讨论】:

    • 这是有道理的。但是,line 是需要标记的输入字符串。如何在第二个方法调用中跳过第一个标记到下一个标记?
    • 进行了更改,请参阅我的编辑。仍然收到相同的输出
    • @Lewis scan = new Scanner(line); 需要在构造函数中。
    • 我现在没有得到任何输出。只是空白令牌。这里发生了更大的事情,非常烦人的错误。感谢您的帮助。
    【解决方案2】:

    如前所述,扫描仪应该在构造函数中初始化。

    另外TokenIter.hasNext() 不是设置TokenIter.token 的地方,如果TokenIter.scan.hasNext() 应该只返回true 或false。赋值应该放在TokenIter.next()

    此外,Scanner 类使用分隔符(默认为空格),因此您应该等待将"(true" 作为一个标记来捕获。可能您想捕捉以"(" 开头的单词并将它们拆分为覆盖TokenIter.next() 内的两个标记

    【讨论】:

      猜你喜欢
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 2017-11-25
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      • 2019-07-23
      • 1970-01-01
      相关资源
      最近更新 更多