Scanner, useDelimiter - java

I encounter some problem when using useDelimiter from the Scanner class.
Scanner sc = new Scanner(System.in).useDelimiter("-");
while(sc.hasNext())
{
System.out.println(sc.next());
}
if I have this input
A-B-C
the output will be
A B
and wait until I type in another "-" for it to print out the last character
However if I instead of having user input data, and insert a String to the Scanner instead the code will work. What's the reason for it, and how do I fix it? I don't want to use StringTokenzier

If the Scanner didn't wait for you to enter another - then it would erroneously assume that you were done typing input.
What I mean is, the Scanner must wait for you to enter a - because it has no way to know the length of the next input.
So, if a user wanted to type A-B-CDE and you stopped to take a sip of coffee at C, it woud not get the correct input. (You expect [ A, B, CDE ] but it would get [ A, B, C ])
When you pass it in a full String, Scanner knows where the end of the input is, and doesn't need to wait for another delimiter.
How I would do it follows:
Scanner stdin = new Scanner(System.in);
String input = stdin.nextLine();
String[] splitInput = input.split("-", -1);
You will now have an array of Strings that contain the data between all of the -s.
Here is a link to the String.split() documentation for your reading pleasure.

You could use an alternative delimiter string useDelimiter( "-|\n" );
It works with a String argument as well as by reading from System.in.
In case of System.in this requires you to press enter at the end of the line.

How I would do it follows:
Scanner stdin = new Scanner(System.in);
String s = stdin.nextLine();
String[] splitInput = s.split("-", -1);
You will now have an array of Strings that contain the data between all of the -s.

Related

Why do I get wrong mathematical results when using scanner class and delimiters for getting a double in Java?

I am writing a program where I have to get a user input, saved as a double. The user must be able to put it using both ',' and '.' as a delimiter - however they want. I tried using useDelimiter which works only partially - it does indeed accept both values (e.g 4.5 and 4,5) but when I later use the entered value in a mathematical equation, I get wrong results - it seems to round the user input down to the closest integer and as an effect no matter whether I enter, 4 or 4.5 or 4,5 or 4.8 etc., I get the same result, which is actually only true to 4.
Does anyone happen to know why it doesn't work?
double protectiveResistor=0; //must be a double, required by my teacher
double voltage= 5;
System.out.println("Please provide the resistance.");
Scanner sc= new Scanner(System.in);
sc.useDelimiter("(\\p{javaWhitespace}|\\.|,)");
try
{
protectiveResistor=sc.nextDouble();
}
catch(InputMismatchException exception)
{
System.out.println("Wrong input!");
System.exit(1);
}
if (protectiveResistor<0){
System.err.println("Wrong input!");
System.exit(1);
}
double current = (double)voltage/protectiveResistor;
double power = (double)current*current*protectiveResistor;
Thank you!
The useDelimiter method is for telling the Scanner what character will separate the numbers from each other. It's not for specifying what character will be the decimal point. So with your code, if the user enters either 4.5 or 4,5, the Scanner will see that as two separate inputs, 4 and 5.
Unfortunately, the Scanner doesn't have the facility to let you specify two different characters as decimal separators. The only thing you can really do is scan the two numbers separately, then join them together into a decimal number afterwards. You will want to scan them as String values, so that you don't lose any zeroes after the decimal point.
What useDelimiter() does is split the input on the specified delimiter.
As an example, if you have the input of 4,5, the following code will print "4".
Scanner sc= new Scanner(System.in);
sc.useDelimiter(",");
System.out.println(sc.next())
If you also want to print the second part, after the ',', you need to add another line to get the next value, which would in this example print
"4
5":
Scanner sc= new Scanner(System.in);
sc.useDelimiter(",");
System.out.println(sc.next())
System.out.println(sc.next())
In your code you can do it like this:
Scanner sc= new Scanner(System.in);
sc.useDelimiter("(\\p{javaWhitespace}|\\.|,)");
try
{
String firstPart = "0";
String secondPart = "0";
if (sc.hasNext()) {
firstPart = sc.next();
}
if (sc.hasNext()) {
secondPart = sc.next();
}
protectiveResistor = Double.parseDouble(firstPart + "." + secondPart)
}
// Rest of your code here
What this code does is split the input on whitespace, '.' and ','. For a floating point value you expect one part before the decimal point and one after it. Therefore, you expect the scanner to have split the input in two parts. These two parts are assigned to two variables, firstPart and secondPart. In the last step, the two parts are brought together with the '.' as decimal point, as expected by Java and parsed back into a variable of type Double.

after a integer input, I want to concatenate two strings, one already initialize and another one is user input

int i = 4;
String s ="Hi ";
Scanner scan = new Scanner(System.in);
System.out.println("enter Integer");
int m=scan.nextInt();
System.out.println("enter string");
*String t = scan.next();
**String t = scan.nextLine();
System.out.println(i+m);
System.out.println(s+t);
when I use *scan.next() then it will only read a single word, another side when I use **scan.nextLine() it will directly show the output
Call nextLine() after nextint() to consume \n.
int a = scanner.nextInt()
scanner.nextLine() // to flush end of line
... // Then read string
String s = scanner.next()
The whole story
After Entering a number, Say 5..
the stream looks like
5\n
When nextInt() is called,
the stream looks like
\n
After you enter string, say `hi
\nhi
After next() is called
the stream looks like
hi
The cause of problem: next() consume till \n.
When it is called \n was first character in the stream. so it read empty string "".

Scanner.next() and hasNext() creating infinite loop when reading from console [duplicate]

I ran into an issue. Below is my code, which asks user for input and prints out what the user inputs one word at a time.
The problem is that the program never ends, and from my limited understanding, it seem to get stuck inside the while loop. Could anyone help me a little?
import java.util.Scanner;
public class Test{
public static void main(String args[]){
System.out.print("Enter your sentence: ");
Scanner sc = new Scanner (System.in);
while (sc.hasNext() == true ) {
String s1 = sc.next();
System.out.println(s1);
}
System.out.println("The loop has been ended"); // This somehow never get printed.
}
}
You keep on getting new a new string and continue the loop if it's not empty. Simply insert a control in the loop for an exit string.
while(!s1.equals("exit") && sc.hasNext()) {
// operate
}
If you want to declare the string inside the loop and not to do the operations in the loop body if the string is "exit":
while(sc.hasNext()) {
String s1 = sc.next();
if(s1.equals("exit")) {
break;
}
//operate
}
The Scanner will continue to read until it finds an "end of file" condition.
As you're reading from stdin, that'll either be when you send an EOF character (usually ^d on Unix), or at the end of the file if you use < style redirection.
When you use scanner, as mentioned by Alnitak, you only get 'false' for hasNext() when you have a EOF character, basically... You cannot easily send and EOF character using the keyboard, therefore in situations like this, it's common to have a special character or word which you can send to stop execution, for example:
String s1 = sc.next();
if (s1.equals("exit")) {
break;
}
Break will get you out of the loop.
Your condition is right (though you should drop the == true). What is happening is that the scanner will keep going until it reaches the end of the input. Try Ctrl+D, or pipe the input from a file (java myclass < input.txt).
it doesn't work because you have not programmed a fail-safe into the code. java sees that the scanner can still collect input while there is input to be collected and if possible, while that is true, it keeps doing so. having a scanner test to see if a certain word, like EXIT for example, is fine, but you could also have it loop a certain number of times, like ten or so. but the most efficient approach is to ask the user of your program how many strings they wish to enter, and while the number of strings they enter is less than the number they put in, the program shall execute. an added option could be if they type EXIT, when they see they need less spaces than they put in and don't want to fill the next cells up with nothing but whitespace. and you could have the program ask if they want to enter more input, in case they realize they need to enter more data into the computer.
the program would be quite simplistic to make, as well because there are a plethera of ways you could do it. feel free to ask me for these ways, i'm running out of room though. XD
If you don't want to use an EOF character for this, you can use StringTokenizer :
import java.util.*;
public class Test{
public static void main(){
Scanner sc = new Scanner (System.in);
System.out.print("Enter your sentence: ");
String s=sc.nextLine();
StringTokenizer st=new StringTokenizer(s," ");//" " is the delimiter here.
while (st.hasMoreTokens() ) {
String s1 = st.nextToken();
System.out.println(s1);
}
System.out.println("The loop has been ended");
}
}
I had the same problem and I solved it by reading the full line from the console with one scanner object, and then parsing the resulting string using a second scanner object.
Scanner console = new Scanner(System.in);
System.out.println("Enter input here:");
String inputLine = console.nextLine();
Scanner input = new Scanner(inputLine);
List<String> arg = new ArrayList<>();
while (input.hasNext()) {
arg.add(input.next().toLowerCase());
}
You can simply use one of the system dependent end-of-file indicators ( d for Unix/Linux/Ubuntu, z for windows) to make the while statement false. This should get you out of the loop nicely. :)
Modify the while loop as below. Declare s1 as String s1; one time outside the loop. To end the loop, simply use ctrl+z.
while (sc.hasNext())
{
s1 = sc.next();
System.out.println(s1);
System.out.print("Enter your sentence: ");
}

What's the difference between next() and nextLine() methods from Scanner class?

What is the main difference between next() and nextLine()?
My main goal is to read the all text using a Scanner which may be "connected" to any source (file for example).
Which one should I choose and why?
I always prefer to read input using nextLine() and then parse the string.
Using next() will only return what comes before the delimiter (defaults to whitespace). nextLine() automatically moves the scanner down after returning the current line.
A useful tool for parsing data from nextLine() would be str.split("\\s+").
String data = scanner.nextLine();
String[] pieces = data.split("\\s+");
// Parse the pieces
For more information regarding the Scanner class or String class refer to the following links.
Scanner: http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
String: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html
next() can read the input only till the space. It can't read two words separated by a space. Also, next() places the cursor in the same line after reading the input.
nextLine() reads input including space between the words (that is, it reads till the end of line \n). Once the input is read, nextLine() positions the cursor in the next line.
For reading the entire line you can use nextLine().
From JavaDoc:
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
next(): Finds and returns the next complete token from this scanner.
nextLine(): Advances this scanner past the current line and returns the input that was skipped.
So in case of "small example<eol>text" next() should return "small" and nextLine() should return "small example"
The key point is to find where the method will stop and where the cursor will be after calling the methods.
All methods will read information which does not include whitespace between the cursor position and the next default delimiters(whitespace, tab, \n--created by pressing Enter). The cursor stops before the delimiters except for nextLine(), which reads information (including whitespace created by delimiters) between the cursor position and \n, and the cursor stops behind \n.
For example, consider the following illustration:
|23_24_25_26_27\n
| -> the current cursor position
_ -> whitespace
stream -> Bold (the information got by the calling method)
See what happens when you call these methods:
nextInt()
read 23|_24_25_26_27\n
nextDouble()
read 23_24|_25_26_27\n
next()
read 23_24_25|_26_27\n
nextLine()
read 23_24_25_26_27\n|
After this, the method should be called depending on your requirement.
What I have noticed apart from next() scans only upto space where as nextLine() scans the entire line is that next waits till it gets a complete token where as nextLine() does not wait for complete token, when ever '\n' is obtained(i.e when you press enter key) the scanner cursor moves to the next line and returns the previous line skipped. It does not check for the whether you have given complete input or not, even it will take an empty string where as next() does not take empty string
public class ScannerTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int cases = sc.nextInt();
String []str = new String[cases];
for(int i=0;i<cases;i++){
str[i]=sc.next();
}
}
}
Try this program by changing the next() and nextLine() in for loop, go on pressing '\n' that is enter key without any input, you can find that using nextLine() method it terminates after pressing given number of cases where as next() doesnot terminate untill you provide and input to it for the given number of cases.
next() and nextLine() methods are associated with Scanner and is used for getting String inputs. Their differences are...
next() can read the input only till the space. It can't read two words separated by space. Also, next() places the cursor in the same line after reading the input.
nextLine() reads input including space between the words (that is, it reads till the end of line \n). Once the input is read, nextLine() positions the cursor in the next line.
import java.util.Scanner;
public class temp
{
public static void main(String arg[])
{
Scanner sc=new Scanner(System.in);
System.out.println("enter string for c");
String c=sc.next();
System.out.println("c is "+c);
System.out.println("enter string for d");
String d=sc.next();
System.out.println("d is "+d);
}
}
Output:
enter string for c
abc def
c is abc
enter string for d
d is def
If you use nextLine() instead of next() then
Output:
enter string for c
ABC DEF
c is ABC DEF
enter string for d
GHI
d is GHI
In short: if you are inputting a string array of length t, then Scanner#nextLine() expects t lines, each entry in the string array is differentiated from the other by enter key.And Scanner#next() will keep taking inputs till you press enter but stores string(word) inside the array, which is separated by whitespace.
Lets have a look at following snippet of code
Scanner in = new Scanner(System.in);
int t = in.nextInt();
String[] s = new String[t];
for (int i = 0; i < t; i++) {
s[i] = in.next();
}
when I run above snippet of code in my IDE (lets say for string length 2),it does not matter whether I enter my string as
Input as :- abcd abcd or
Input as :-
abcd
abcd
Output will be like
abcd
abcd
But if in same code we replace next() method by nextLine()
Scanner in = new Scanner(System.in);
int t = in.nextInt();
String[] s = new String[t];
for (int i = 0; i < t; i++) {
s[i] = in.nextLine();
}
Then if you enter input on prompt as -
abcd abcd
Output is :-
abcd abcd
and if you enter the input on prompt as
abcd (and if you press enter to enter next abcd in another line, the input prompt will just exit and you will get the output)
Output is:-
abcd
From javadocs
next() Returns the next token if it matches the pattern constructed from the specified string.
nextLine() Advances this scanner past the current line and returns the input that was skipped.
Which one you choose depends which suits your needs best. If it were me reading a whole file I would go for nextLine until I had all the file.
From the documentation for Scanner:
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
From the documentation for next():
A complete token is preceded and followed by input that matches the delimiter pattern.
Just for another example of Scanner.next() and nextLine() is that like below :
nextLine() does not let user type while next() makes Scanner wait and read the input.
Scanner sc = new Scanner(System.in);
do {
System.out.println("The values on dice are :");
for(int i = 0; i < n; i++) {
System.out.println(ran.nextInt(6) + 1);
}
System.out.println("Continue : yes or no");
} while(sc.next().equals("yes"));
// while(sc.nextLine().equals("yes"));
Both functions are used to move to the next Scanner token.
The difference lies in how the scanner token is generated
next() generates scanner tokens using delimiter as White Space
nextLine() generates scanner tokens using delimiter as '\n' (i.e Enter
key presses)
A scanner breaks its input into tokens using a delimiter pattern, which is by default known the Whitespaces.
Next() uses to read a single word and when it gets a white space,it stops reading and the cursor back to its original position.
NextLine() while this one reads a whole word even when it meets a whitespace.the cursor stops when it finished reading and cursor backs to the end of the line.
so u don't need to use a delimeter when you want to read a full word as a sentence.you just need to use NextLine().
public static void main(String[] args) {
// TODO code application logic here
String str;
Scanner input = new Scanner( System.in );
str=input.nextLine();
System.out.println(str);
}
I also got a problem concerning a delimiter.
the question was all about inputs of
enter your name.
enter your age.
enter your email.
enter your address.
The problem
I finished successfully with name, age, and email.
When I came up with the address of two words having a whitespace (Harnet street) I just got the first one "harnet".
The solution
I used the delimiter for my scanner and went out successful.
Example
public static void main (String args[]){
//Initialize the Scanner this way so that it delimits input using a new line character.
Scanner s = new Scanner(System.in).useDelimiter("\n");
System.out.println("Enter Your Name: ");
String name = s.next();
System.out.println("Enter Your Age: ");
int age = s.nextInt();
System.out.println("Enter Your E-mail: ");
String email = s.next();
System.out.println("Enter Your Address: ");
String address = s.next();
System.out.println("Name: "+name);
System.out.println("Age: "+age);
System.out.println("E-mail: "+email);
System.out.println("Address: "+address);
}
The basic difference is next() is used for gettting the input till the delimiter is encountered(By default it is whitespace,but you can also change it) and return the token which you have entered.The cursor then remains on the Same line.Whereas in nextLine() it scans the input till we hit enter button and return the whole thing and places the cursor in the next line.
**
Scanner sc=new Scanner(System.in);
String s[]=new String[2];
for(int i=0;i<2;i++){
s[i]=sc.next();
}
for(int j=0;j<2;j++)
{
System.out.println("The string at position "+j+ " is "+s[j]);
}
**
Try running this code by giving Input as "Hello World".The scanner reads the input till 'o' and then a delimiter occurs.so s[0] will be "Hello" and cursor will be pointing to the next position after delimiter(that is 'W' in our case),and when s[1] is read it scans the "World" and return it to s[1] as the next complete token(by definition of Scanner).If we use nextLine() instead,it will read the "Hello World" fully and also more till we hit the enter button and store it in s[0].
We may give another string also by using nextLine(). I recommend you to try using this example and more and ask for any clarification.
The difference can be very clear with the code below and its output.
public static void main(String[] args) {
List<String> arrayList = new ArrayList<>();
List<String> arrayList2 = new ArrayList<>();
Scanner input = new Scanner(System.in);
String product = input.next();
while(!product.equalsIgnoreCase("q")) {
arrayList.add(product);
product = input.next();
}
System.out.println("You wrote the following products \n");
for (String naam : arrayList) {
System.out.println(naam);
}
product = input.nextLine();
System.out.println("Enter a product");
while (!product.equalsIgnoreCase("q")) {
arrayList2.add(product);
System.out.println("Enter a product");
product = input.nextLine();
}
System.out.println();
System.out.println();
System.out.println();
System.out.println();
System.out.println("You wrote the following products \n");
for (String naam : arrayList2) {
System.out.println(naam);
}
}
Output:
Enter a product
aaa aaa
Enter a product
Enter a product
bb
Enter a product
ccc cccc ccccc
Enter a product
Enter a product
Enter a product
q
You wrote the following products
aaa
aaa
bb
ccc
cccc
ccccc
Enter a product
Enter a product
aaaa aaaa aaaa
Enter a product
bb
Enter a product
q
You wrote the following products
aaaa aaaa aaaa
bb
Quite clear that the default delimiter space is adding the products separated by space to the list when next is used, so each time space separated strings are entered on a line, they are different strings.
With nextLine, space has no significance and the whole line is one string.

How to get out of while loop in java with Scanner method "hasNext" as condition?

I ran into an issue. Below is my code, which asks user for input and prints out what the user inputs one word at a time.
The problem is that the program never ends, and from my limited understanding, it seem to get stuck inside the while loop. Could anyone help me a little?
import java.util.Scanner;
public class Test{
public static void main(String args[]){
System.out.print("Enter your sentence: ");
Scanner sc = new Scanner (System.in);
while (sc.hasNext() == true ) {
String s1 = sc.next();
System.out.println(s1);
}
System.out.println("The loop has been ended"); // This somehow never get printed.
}
}
You keep on getting new a new string and continue the loop if it's not empty. Simply insert a control in the loop for an exit string.
while(!s1.equals("exit") && sc.hasNext()) {
// operate
}
If you want to declare the string inside the loop and not to do the operations in the loop body if the string is "exit":
while(sc.hasNext()) {
String s1 = sc.next();
if(s1.equals("exit")) {
break;
}
//operate
}
The Scanner will continue to read until it finds an "end of file" condition.
As you're reading from stdin, that'll either be when you send an EOF character (usually ^d on Unix), or at the end of the file if you use < style redirection.
When you use scanner, as mentioned by Alnitak, you only get 'false' for hasNext() when you have a EOF character, basically... You cannot easily send and EOF character using the keyboard, therefore in situations like this, it's common to have a special character or word which you can send to stop execution, for example:
String s1 = sc.next();
if (s1.equals("exit")) {
break;
}
Break will get you out of the loop.
Your condition is right (though you should drop the == true). What is happening is that the scanner will keep going until it reaches the end of the input. Try Ctrl+D, or pipe the input from a file (java myclass < input.txt).
it doesn't work because you have not programmed a fail-safe into the code. java sees that the scanner can still collect input while there is input to be collected and if possible, while that is true, it keeps doing so. having a scanner test to see if a certain word, like EXIT for example, is fine, but you could also have it loop a certain number of times, like ten or so. but the most efficient approach is to ask the user of your program how many strings they wish to enter, and while the number of strings they enter is less than the number they put in, the program shall execute. an added option could be if they type EXIT, when they see they need less spaces than they put in and don't want to fill the next cells up with nothing but whitespace. and you could have the program ask if they want to enter more input, in case they realize they need to enter more data into the computer.
the program would be quite simplistic to make, as well because there are a plethera of ways you could do it. feel free to ask me for these ways, i'm running out of room though. XD
If you don't want to use an EOF character for this, you can use StringTokenizer :
import java.util.*;
public class Test{
public static void main(){
Scanner sc = new Scanner (System.in);
System.out.print("Enter your sentence: ");
String s=sc.nextLine();
StringTokenizer st=new StringTokenizer(s," ");//" " is the delimiter here.
while (st.hasMoreTokens() ) {
String s1 = st.nextToken();
System.out.println(s1);
}
System.out.println("The loop has been ended");
}
}
I had the same problem and I solved it by reading the full line from the console with one scanner object, and then parsing the resulting string using a second scanner object.
Scanner console = new Scanner(System.in);
System.out.println("Enter input here:");
String inputLine = console.nextLine();
Scanner input = new Scanner(inputLine);
List<String> arg = new ArrayList<>();
while (input.hasNext()) {
arg.add(input.next().toLowerCase());
}
You can simply use one of the system dependent end-of-file indicators ( d for Unix/Linux/Ubuntu, z for windows) to make the while statement false. This should get you out of the loop nicely. :)
Modify the while loop as below. Declare s1 as String s1; one time outside the loop. To end the loop, simply use ctrl+z.
while (sc.hasNext())
{
s1 = sc.next();
System.out.println(s1);
System.out.print("Enter your sentence: ");
}

Categories