Wednesday 3 January 2018

java - Weird behaviour with Scanner#nextFloat

itemprop="text">

Running the following in Eclipse
initially caused Scanner to not recognize carriage returns in the console effectively
blocking further input:



price =
sc.nextFloat();


Adding
this line before the code causes Scanner to accept 0,23 (french notation) as a
float:




Locale.setDefault(Locale.US);


This
is most probably due to regional settings in Windows XP Pro (French/Belgian). When the
code is run again 0,23 is still accepted and entering 0.23 causes it to throw a
java.util.InputMismatchException.



Any
explanation as to why this is happening? Also is there a workaround or should I just use
Float#parseFloat?



Edit:
This demonstrates how Scanner behaves with different Locales (uncomment one of the lines
at the
beginning).




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:
This reproduces the issue where the Scanner is waiting for a float value but fails to
trigger when you press
return:



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);

}


}


Answer




I wonder if you're not handling an end of
line token appropriately. Often if you use Scanner#next###() (except for nextLine), and
you reach an end of line token as when the user presses enter, if you don't handle the
end of line token, it will prevent the Scanner object from working appropriately. To
solve this, call Scanner#nextLine() when this token needs to be handled. If you post
some of your code, we can see if this indeed is your problem and if my suggestion offers
a solution.



edit: nope, you're not using
System.in so this is not the problem. On the other hand, you do need to set the locale
of the Scanner before accepting the French number.
i.e.,



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



No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...