验证有问题:即使逻辑看起来很好,也会发生无限循环

时间:2016-02-21 17:20:36

标签: java while-loop java.util.scanner

我正在为这家'餐厅'程序,它需要两个输入:账单金额和满意度从1到3.我试图使用hasNextDouble()验证每个输出,但由于某些原因,当我运行程序时,第一个if语句中的else语句无限运行。有人可以看一下吗?

package tips;

import java.util.Scanner;

public class Tips {

public static void main(String[] args) {
    /* Ask for the diners’ satisfaction level using these ratings: 
    1 = Totally satisfied, 2 = Satisfied, 3 = Dissatisfied.
    If the diner is totally satisfied, calculate a 20 percent tip.
    If the diner is satisfied, calculate a 15 percent tip.
    If the diner is dissatisfied, calculate a 10 percent tip.
    Report the satisfaction level and tip in dollars and cents.*/

    Scanner in = new Scanner(System.in);

    boolean isDouble = false;
    boolean isInt = false;

    TipsCalculator tips = new TipsCalculator();

    while (!isDouble && !isInt) {
          System.out.print("Please enter the bill amount: ");
          //Checks if the input is a double.
          if(in.hasNextDouble()) {
              tips.setBill(in.nextDouble());
              isDouble = true;
          } else {
              System.out.println("The value entered is not a valid amount.");
              continue;
          }

          System.out.println("Please enter your satisfaction level: \n1 = Totally Satisfied.\n2 = Satisfied.\n3 = Dissatisfied.");
          //Checks if the input is an integer.
          if(in.hasNextInt()) {
              tips.setSatisfactionLevel(in.nextInt());
              isInt = true;
              //Prints different outputs depending on the satisfaction level.
              if (tips.getSatisfactionLevel() == 1) {
                  System.out.println("You are totally satisfied! :-)" + 
                          ". \n" + 
                          "Your tip amount is: " + 
                          tips.calculateTips());
              } else if (tips.getSatisfactionLevel() == 2){
                  System.out.println("You are satisfied! :-)" + 
                          ". \n" + 
                          "Your tip amount is: " + 
                          tips.calculateTips());
              } else if (tips.getSatisfactionLevel() == 3) {
                  System.out.println("You are dissatisfied! :-(" + 
                          ". \n" + 
                          "Your tip amount is: " + 
                          tips.calculateTips());
              } else {
                  //Error if the level is not from 1 to 3.
                  System.out.println("The value entered is not between 1 and 3");
              }
          } else {
              System.out.println("The value entered is not between 1 and 3");
              continue;
          }
    } in.close();

}

}

3 个答案:

答案 0 :(得分:2)

isDoubl& isInt两者都是假的,因此!isDouble && !isInt将永远为真。这是无限循环背后的根本原因

答案 1 :(得分:1)

不要将输入读为double和int。将其读作字符串,然后在代码中将其解析为Double或Integer。在Integer和Double类中使用方法valueOf(String)。解析你的字符串

答案 2 :(得分:0)

无限循环的原因是: 扫描程序类中的 hasNextDouble 方法在内部调用 hasNext 方法。 它写得像这样

public boolean hasNext(Pattern pattern) {
        ensureOpen();
        if (pattern == null)
            throw new NullPointerException();
        hasNextPattern = null;
        saveState();

        while (true) {
            if (getCompleteTokenInBuffer(pattern) != null) {
                matchValid = true;
                cacheResult();
                return revertState(true);
            }
            if (needInput)
                readInput();
            else
                return revertState(false);
        }
    }

在上面的方法中, getCompleteTokenInBuffer 方法调用是真正的罪魁祸首。此 getCompleteTokenInBuffer 可以返回以下3种可能性

/*
 * 1. valid string means it was found
 * 2. null with needInput=false means we won't ever find it
 * 3. null with needInput=true means try again after readInput
 */

hasNext 方法中,每当我们第一次输入非double值时,我们就能读取数据, getCompleteTokenInBuffer 返回null,并且还会设置 needInput = false 第一次。但是,第二次 hasNext 方法将返回值 false ,因为 needInput = false 条件将为true。

对于后续的 hasNextDouble 方法调用,此 needInput = false 条件将保持为true。因此,我们无法读取任何数据,这导致无限循环。

相关问题