2009-11-25 73 views
10

Tôi đang sử dụng đoạn mã sau:.Java: vòng lặp vô hạn sử dụng Scanner in.hasNextInt()

while (invalidInput) 
{ 
    // ask the user to specify a number to update the times by 
    System.out.print("Specify an integer between 0 and 5: "); 

    if (in.hasNextInt()) 
    { 
     // get the update value 
     updateValue = in.nextInt(); 

     // check to see if it was within range 
     if (updateValue >= 0 && updateValue <= 5) 
     { 
      invalidInput = false; 
     } 
     else 
     { 
      System.out.println("You have not entered a number between 0 and 5. Try again."); 
     } 
    } else 
    { 
     System.out.println("You have entered an invalid input. Try again."); 
    } 
} 

Tuy nhiên, nếu tôi nhập 'w' nó sẽ cho tôi biết "Bạn đã nhập vào không hợp lệ Try Again . " và sau đó nó sẽ đi vào một vòng lặp vô hạn hiển thị văn bản "Chỉ định một số nguyên từ 0 đến 5: Bạn đã nhập một đầu vào không hợp lệ. Hãy thử lại."

Tại sao điều này lại xảy ra? Không phải chương trình phải chờ người dùng nhập và nhấn enter mỗi lần đạt đến tuyên bố:

if (in.hasNextInt()) 
+0

Vì bạn chưa chỉ cho ai biết thứ 'in' là gì, hoặc cách bạn xây dựng nó, không có cách nào để nói nó sẽ hoạt động như thế nào! –

Trả lời

13

Trong khối else cuối cùng, bạn cần xóa 'w' hoặc đầu vào không hợp lệ khác khỏi Máy quét. Bạn có thể làm điều này bằng cách gọi next() trên Scanner và bỏ qua giá trị trả về của nó để vứt bỏ mà đầu vào không hợp lệ, như sau:

else 
{ 
     System.out.println("You have entered an invalid input. Try again."); 
     in.next(); 
} 
2

Biến cờ quá dễ bị sử dụng. Thay vào đó hãy sử dụng kiểm soát vòng lặp rõ ràng có nhận xét. Ngoài ra, hasNextInt() không chặn. Đó là kiểm tra không chặn để xem liệu cuộc gọi next trong tương lai có thể nhận dữ liệu nhập mà không chặn hay không. Nếu bạn muốn chặn, hãy sử dụng phương thức nextInt().

// Scanner that will read the integer 
final Scanner in = new Scanner(System.in); 
int inputInt; 
do { // Loop until we have correct input 
    System.out.print("Specify an integer between 0 and 5: "); 
    try { 
     inputInt = in.nextInt(); // Blocks for user input 
     if (inputInt >= 0 && inputInt <= 5) { 
      break; // Got valid input, stop looping 
     } else { 
      System.out.println("You have not entered a number between 0 and 5. Try again."); 
      continue; // restart loop, wrong number 
     } 
    } catch (final InputMismatchException e) { 
     System.out.println("You have entered an invalid input. Try again."); 
     in.next(); // discard non-int input 
     continue;  // restart loop, didn't get an integer input 
    } 
} while (true); 
+0

có lý do nào khiến bạn quét Máy quét không? – Tomek

+0

mã này vẫn tạo ra một vòng lặp vô hạn – Tomek

+0

Tôi làm cho nó cuối cùng vì nó sẽ không thay đổi. Trình biên dịch có thể thực hiện tối ưu hóa nhất định vì điều này. Đó là một thói quen tốt để tuyên bố mọi thứ có thể là cuối cùng. Vòng lặp sẽ bị hỏng khi người dùng nhập vào đúng đầu vào. Nó chỉ vô hạn nếu người dùng chọn để làm cho nó vô hạn. Nếu bạn muốn, tôi có thể chỉnh sửa nó để nó chỉ cho phép một số lần thử lại nhất định. –

8

Vấn đề là bạn không thúc đẩy Scanner quá khứ đầu vào vấn đề. Từ hasNextInt() tài liệu:

Returns true nếu token kế tiếp trong đầu vào của máy quét này có thể được hiểu như là một giá trị int trong radix mặc định sử dụng phương pháp nextInt(). Máy quét không vượt qua bất kỳ đầu vào nào.

Điều này đúng với tất cả hasNextXXX() phương pháp: họ trở true hoặc false, không thúc đẩy Scanner.

Dưới đây là một đoạn mã để minh họa cho vấn đề:

String input = "1 2 3 oops 4 5 6"; 
    Scanner sc = new Scanner(input); 
    while (sc.hasNext()) { 
     if (sc.hasNextInt()) { 
      int num = sc.nextInt(); 
      System.out.println("Got " + num); 
     } else { 
      System.out.println("int, please!"); 
      //sc.next(); // uncomment to fix! 
     } 
    } 

Bạn sẽ thấy rằng chương trình này sẽ đi vào một vòng lặp vô hạn, yêu cầu int, please! lặp đi lặp lại.

Nếu bạn bỏ ghi chú sc.next(), thì nó sẽ làm cho Scanner vượt qua mã thông báo không thành công hasNextInt(). Chương trình sau đó sẽ in:

Got 1 
Got 2 
Got 3 
int, please! 
Got 4 
Got 5 
Got 6 

Thực tế là một thất bại hasNextXXX() kiểm tra không bỏ qua đầu vào là có chủ ý: nó cho phép bạn thực hiện kiểm tra bổ sung đối với dấu hiệu rằng nếu cần thiết. Dưới đây là một ví dụ để minh họa:

String input = " 1 true foo 2 false bar 3 "; 
    Scanner sc = new Scanner(input); 
    while (sc.hasNext()) { 
     if (sc.hasNextInt()) { 
      System.out.println("(int) " + sc.nextInt()); 
     } else if (sc.hasNextBoolean()) { 
      System.out.println("(boolean) " + sc.nextBoolean()); 
     } else { 
      System.out.println(sc.next()); 
     } 
    } 

Nếu bạn chạy chương trình này, nó sẽ đưa ra như sau:

(int) 1 
(boolean) true 
foo 
(int) 2 
(boolean) false 
bar 
(int) 3 
3

Tuyên bố này bởi Ben S.về cuộc gọi không chặn là sai:

Ngoài ra, hasNextInt() không chặn. Đó là kiểm tra không chặn để xem liệu cuộc gọi tiếp theo có thể nhận được dữ liệu nhập mà không bị chặn hay không.

... mặc dù tôi nhận thấy rằng documentation có thể dễ dàng bị đọc nhầm để đưa ra ý kiến ​​này và tên chính nó ngụ ý nó sẽ được sử dụng cho mục đích này. Các báo giá liên quan, với sự nhấn mạnh thêm:

Tiếp theo() và hasNext() phương pháp và nguyên thủy loại phương pháp bạn đồng hành của họ (ví dụ như nextInt() và hasNextInt()) đầu tiên bỏ qua bất kỳ đầu vào phù hợp với mẫu dấu phân cách và sau đó cố trả về mã thông báo tiếp theo. Cả hai phương thức này đều có phương pháp tiếp theo và tiếp theo có thể chặn chờ nhập thêm. Cho dù khối phương thức hasNext không có kết nối đến việc liệu phương thức tiếp theo có liên quan sẽ chặn hay không.

Đó là một điểm tinh tế, để chắc chắn. Hoặc nói "Cả hai đều có phương thức tiếp theo và tiếp theo" hoặc "Cả hai hasnext() và tiếp theo()" đều ngụ ý rằng các phương thức đồng hành sẽ hoạt động khác nhau. Nhưng nhìn thấy chúng phù hợp với cùng quy ước đặt tên (và tài liệu, tất nhiên), nó là hợp lý để mong đợi chúng hoạt động giống nhau, và hasNext() nói rõ ràng rằng nó có thể chặn. Lưu ý: điều này có lẽ là nhận xét cho bài đăng không chính xác, nhưng có vẻ như là một người dùng mới, tôi chỉ có thể đăng câu trả lời này (hoặc chỉnh sửa wiki có vẻ thích hợp hơn cho thay đổi sytlistic, chứ không phải là chất).

Các vấn đề liên quan