2017-02-21 12 views
1

このプログラムでは、文字列からスキャンし、有効であればトークンを格納するトークンイテレータを実装する必要があります。これは簡単な処理のようですが、私のコードは文字列内の最初の有効なトークンを返すだけです。私は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: [)] 

答えて

4

あなた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; 

ソリューション: あなたがhasNext()の呼び出しの間の状態を保つように、クラス変数になるために必要scan変数。

+0

それは意味があります。ただし、lineはトークン化する必要のある入力文字列です。 2番目のメソッド呼び出しで、最初のトークンを越えて次のトークンまでスキップできますか? – Coder123

+0

が変更されました。私の編集を参照してください。まだ同じ出力を受け取っています – Coder123

+0

@Lewis 'scan = new Scanner(line);'という行はコンストラクタ内にある必要があります。 – Roland

2

既にコメントされているように、スキャナはコンストラクタ内で初期化する必要があります。

また、TokenIter.hasNext()はTokenIter.tokenを設定する場所ではなく、TokenIter.scan.hasNext()の場合にのみtrueまたはfalseを返します。割り当てはTokenIter.next()

さらにScannerクラスはデリミタ(デフォルトはスペース)を使用するので、"(true"を1つのトークンとして捕まえるのを待つ必要があります。おそらく"("で始まる単語をキャッチし、オーバーライド内の2つのトークンに分割したいと考えていますTokenIter.next()

関連する問題