2011-01-16 15 views
11

uruchamiając następujące w Eclipse początkowo spowodowało Scanner nie rozpoznaje powrotu karetki w konsoli skutecznie blokując dalsze wejście:dziwne zachowanie ze skanerem # nextFloat

price = sc.nextFloat(); 

Dodanie tej linii przed kod powoduje Scanner przyjąć 0,23 (notacja francuska) jako zmiennoprzecinkowa:

Locale.setDefault(Locale.US); 

Jest to najprawdopodobniej spowodowane ustawieniami regionalnymi w systemie Windows XP Pro (francuski/belgijski). Po ponownym uruchomieniu kodu wartość 0,23 jest nadal akceptowana, a wprowadzenie wartości 0,23 powoduje, że zostanie ona przesłana java.util.InputMismatchException.

Jakiekolwiek wyjaśnienie, dlaczego tak się dzieje? Czy istnieje obejście problemu, czy powinienem po prostu użyć Float#parseFloat?

Edytuj: Pokazuje sposób działania skanera w różnych ustawieniach regionalnych (odkomentuj jedną z linii na początku).

import java.util.Locale; 
import java.util.Scanner; 


public class NexFloatTest { 

    public static void main(String[] args) { 

     //Locale.setDefault(Locale.US); 
     //Locale.setDefault(Locale.FRANCE); 

     // Gives fr_BE on this system 
     System.out.println(Locale.getDefault()); 

     float price; 

     String uSDecimal = "0.23"; 
     String frenchDecimal = "0,23"; 

     Scanner sc = new Scanner(uSDecimal); 

     try{ 
      price = sc.nextFloat(); 
      System.out.println(price); 
     } catch (java.util.InputMismatchException e){ 
      e.printStackTrace(); 
     } 

     try{ 
      sc = new Scanner(frenchDecimal); 
      price = sc.nextFloat(); 
      System.out.println(price); 
     } catch (java.util.InputMismatchException e){ 
      e.printStackTrace(); 
     } 

     System.out.println("Switching Scanner to System.in"); 

     try{ 
      sc = new Scanner(System.in); 
      System.out.println("Enter a float value"); 
      price = sc.nextFloat(); 
      System.out.println(price); 
     } catch (java.util.InputMismatchException e){ 
      e.printStackTrace(); 
     } 

     System.out.print("Enter title:"); 

     String title = sc.nextLine(); // This line is skipped 

     System.out.print(title); 
    } 

} 

Edit: To odtwarza problem gdzie skaner czeka na wartości pływaka ale nie trafia wywołać po naciśnięciu przycisku powrotu:

import java.util.Scanner; 

public class IgnoreCRTest { 

    public static void main(String[] args) { 
     Scanner sc = new Scanner(System.in); 
     System.out.println("Enter a float value:"); 
     // On french Locale use , as the decimal separator 
     float testFloat = sc.nextFloat(); 
     System.out.println(testFloat); 
     //sc.skip("\n"); // This doesn't solve the issue 
     sc.nextLine(); 
     System.out.println("Enter an integer value:"); 
     int testInt = sc.nextInt(); 
     System.out.println(testInt); 
     // Will either block or skip here 
     System.out.println("Enter a string value :"); 
     String testString = sc.nextLine(); 
     System.out.println(testString); 
    } 

} 
+3

Czy możesz podać wykonywalny przykład pokazujący rzeczywisty fragment kodu, który właśnie uruchamiasz i przedstawiający problem? –

+0

Pewnie. Dodam kod za kilka minut. –

Odpowiedz

13

Zastanawiam się, czy nie jesteś obsługi kres linii token odpowiednio. Często, jeśli używasz skanera # następnego ###() (z wyjątkiem nextLine), i osiągasz koniec tokena linii, gdy użytkownik naciśnie klawisz Enter, jeśli nie zajmie się tokenem końca linii, zapobiegnie skanerowi obiekt z właściwej pracy. Aby rozwiązać ten problem, wywołaj Scanner # nextLine(), gdy ten token będzie wymagał obsługi. Jeśli opublikujesz jakiś kod, zobaczymy, czy to rzeczywiście jest twój problem i czy moja propozycja oferuje rozwiązanie.

edytuj: nie, nie używasz System.in, więc to nie jest problem. Z drugiej strony, musisz ustawić ustawienia regionalne skanera przed zaakceptowaniem francuskiego numeru. tj.,

 sc = new Scanner(frenchDecimal); 
    sc.useLocale(Locale.FRENCH); 
    price = sc.nextFloat(); 
+3

jeśli nie wywołasz funkcji UseLocale (...), skaner zostanie skonstruowany z domyślnymi ustawieniami narodowymi. Domyślnym Locale OP jest francuski. –

+1

Dzięki za odpowiedź, ale przykro mi, że jakoś to przeoczyłem. Skąd on stwierdza, że ​​domyślne ustawienie regionalne to francuski? –

+0

Dzięki. Ustawienie Locale dla skanera działa (chciałem użyć dziesiętnego w USA). Jakieś pomysły na temat tego, co powoduje pomijanie następnej linii w zmodyfikowanym kodzie? Ponadto, ponieważ ustawiono Locale, nie udało mi się odtworzyć problemu, w którym skaner wydaje się akceptować tekst, ale nie rozpoznaje powrotu karetki. –