2017-02-21 89 views
1

для этой программы, мне нужно реализовать токен-итератор, который сканирует из строки и сохраняет токен, если он действителен. Это похоже на простой процесс, но мой код возвращает только первый действительный токен внутри строки. Мне нужно вызвать hasNext(); в другом месте в следующем() методе?Реализация Итератора считывает только первый токен в строке?

Вот мой код:

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; 

Решение: Переменная scan должно стать переменным классом, так что вы держите состояние между сеансами hasNext().

+0

Это имеет смысл. Однако строка - это входная строка, которая должна быть маркирована. Как пропустить первый токен в следующий токен во втором вызове метода? – Coder123

+0

сделал это изменение, см. Мое редактирование. все еще получая тот же вывод – Coder123

+0

@Lewis строка 'scan = new Scanner (строка);' должно быть в конструкторе. – Roland

2

Как уже отмечалось, сканер должен быть инициализирован внутри конструктора.

Также TokenIter.hasNext() не является местом для установки TokenIter.token, должен возвращать только true или false, если TokenIter.scan.hasNext(). Назначение должно быть размещено внутри TokenIter.next()

дополнительно Scanner класса использует разделитель (пробел по умолчанию), так что вы должны ждать, чтобы поймать "(true" как один знак. Вероятно, вы хотели бы поймать слова, начинающиеся с "(", и разделить их на два токена внутри переопределения TokenIter.next()