scanner.nextInt() is moving to the next line, how is this possible? - java

Input
Integer N
N lines follow, each line has two space seperated integers p and q.
So, I know that nextLine() reads the whole line and moves the cursor to the next line and nextFoo() reads only up till it encounters a space and keeps the cursor there (doesn't move it to a new line).
So initially I tried this:-
int N = Integer.parseInt(in.nextLine()); //reading the whole line and parsing it to Integer. The cursor pointer is moved to the next line
while(--N>=0){
p = in.nextInt(); q = in.nextInt(); //reading the two space seperated integers
in.nextLine();//to move the cursor to the next line
}
But this wasn't working properly, couldn't read the last p and q I was inputting.
Changed it to:
int N = in.nextInt();
while(--N>=0){
p = in.nextInt(); q = in.nextInt();
}
And it is working fine. How is nextInt() going to the next line? All .nextFoo() and .next() except .nextLine() read only up till there is a space and keep the cursor pointer there, right? How is this going to the newline then?

From the Scanner Javadoc:
The next() and hasNext() methods and their primitive-type companion methods (such as nextInt() and hasNextInt()) first skip any input that matches the delimiter pattern, and then attempt to return the next token.
So the cursor is before the newline, then when you call nextInt(), skips through the newline and any other whitespace, before consuming the number.
Your code containing nextLine() will work, as long as your input file ends in a newline. It's conventional to end text files with a newline character -- many editors will either force you to have one, or display a warning if it's missing.

Related

Multiline console input in Java

I have some multiline text as a console input. Something like that:
first string with some text
second string with another text
third text with its own text
Number of lines may be different (one, two, three, four, etc., but not zero) every time, but this text is always putted in an instant with line separators (one pasting, not several inputs with pressing the enter key). This Java app has to immediately start to do something with those lines, but for some reason I can't understand, how to make this behavior. I mean, it has to save all these lines into String, or String[], or List<String>, or something else. If it's possible, I also would like to know, how to do this for "paste multiline text and Enter" input, but the main thing is for "paste multiline text (and no Enter)".
Of course, I tried to do that with Scanner, but I can't find working solution. It either gives me only the first line, or it doesn't understand, that the last line is the last one waiting for the next input.
There are two ways I can think of to make your scanner stop waiting for input and save your whole string as entered.
The first approach is to input your text into the console, hit Enter and then press CTRL+D, which will add an endline character. This endline character will make the scanner.hasNextLine() method return false, and therefore it will stop waiting for input. The code for this is pretty straightforward:
Scanner scanner = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
while (scanner.hasNextLine()) {
sb.append(scanner.nextLine()).append("\n");
}
sb.deleteCharAt(sb.length() - 1); // delete the last \n character
String s = sb.toString();
Using this approach, even though your input is a whole multiline string, it will be read line by line using the scanner.nextLine() method. Each line will be appended to the StringBuilder, plus a newline character \n to keep the original input. As you can see, I then easily converted the sb into a String s.
StringBuilder is the recommended way of composing a string from multiple parts.
The second approach does not require CTRL+D and it is very similar to the first one. The addition is that every line of input is checked to see if it is empty, using the line.isEmpty() method. If it is empty, you'll simply break from the while loop without that line being appended to the sb:
Scanner scanner = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.isEmpty()) {
break;
} // else
sb.append(line).append("\n");
}
sb.deleteCharAt(sb.length() - 1); // delete the last \n character
String s = sb.toString();
Now, this approach will obviously not work if your input contains empty lines in it (like breaks between paragraphs), because it will stop there and the rest of the string will be left out. However, instead of if (line.isEmpty()) you can decide on a stopping character and check if the line starts with it. If so, break:
if (line.startsWith("&")) {
break;
}
Again, this character won't be included in your sb.
Have a good one!

Is there a way around not advancing a line with Scanner (Java)

Okay so I'm having a slight problem with scanner advancing an extra line. I have a file that has many lines containing integers each separated by one space. Somewhere in the file there is a line with no integers and just the word "done".
When done is found we exit the loop and print out the largest prime integer that is less than each given integer in each line(if integer is already prime do nothing to it). We do this all the way up until the line with "done".
My problem: lets say the file contains 6 lines and on the 6th line is the word done. My output would skip lines 1, 3 and 5. It would only return the correct values for line 2 and 4.
Here's a snippet of code where I read the values in:
Scanner in = new Scanner(
new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
while(in.nextLine() != "done"){
String[] arr = in.nextLine().split(" ");
Now I sense the problem is that the nextLine call in my loop advances the line and then the nextline.split call also advances the line. Thus, all odd number lines will be lost. Would there be another way to check for "done" without advancing a line or is there a possible command I could call to somehow reset the scanner back to the start of the loop?
The problem is you have 2 calls to nextLine() try something like this
String line = in.nextLine();
while (!"done".equals(line)) {
String[] arr = line.split(" ");
// Process the line
if (!in.hasNextLine()) {
// Error reached end of file without finding done
}
line = in.nextLine();
}
Also note I fixed the check for "done" you should be using equals().
I think you are looking for this
while(in.hasNextLine()){
String str = in.nextLine();
if(str.trim().equals("done"){
break;
}else{
String[] arr = str.split("\\s+");
//then do whatever you want to do
}
}

Array adds 0 as the first element instead of my input [java]

I've been writing this program to count the vowels in string/a line of strings. Now, I've got the whole program worked out and it does correctly output the number of vowels for all inputs, but the problem is that the first input of the array is always 0 / nonexistant for some reason.
I'll give you an example and the code here, it's kind of hard to explain:
Scanner sc = new Scanner(System.in);
int numberOfEntries = sc.nextInt() //this would be the number of lines of strings
String[] array = new String[numberOfEntries];
int k = 0;
while(sc.hasNext() && k < numberOfEntries){
array[k] = sc.nextLine();
k++;
}
So this is the part of the code that is relevant to the problem, the rest of it is fine. For some reason, when I input the following lines:
5
abcd
efgh
ijkl
mnop
qrst
The output I will get if I outprint the array is this:
[, abcd, efgh, ijkl, mnop]
I've tried using just the
for(int i = 0; i < array.length; i++){
array[i] = sc.nextLine();
}
thinking that it might solve the issue but nothing changed. I am out of ideas now, though I am sure I just made some silly little error somewhere and I just don't see it.
Kind regards, George
You get the empty line because of the '\n' that sits in the buffer after you call nextInt(). You press Enter after typing in your integer. Scanner consumes the integer in the call of nextInt(), but it does not touch '\n' that follows.
To fix this problem, call nextLine after reading your int, and discard the result:
int numberOfEntries = sc.nextInt();
sc.nextLine(); // Throw away the '\n' after the int
The statement int numberOfEntries = sc.nextInt(); reads the number, leaving the next character (a newline) as the next character to be read.
The first call to sc.nextLine() see this newline and recognizes it as the end on an (empty) line. For your sample input, this causes the call to return an empty string.
The solution is to add an extra call to sc.nextLine() after the sc.nextInt() to consume (and then discard) any characters after the last digit up to the end of the line.
(Actually ... this is a fairly common beginner's mistake with the Scanner API.)
Thats because the Scanner.nextInt() method does not read the last newline character of your input, and thus that newline is consumed in the next call to Scanner.nextLine().

Integer.parseInt(scanner.nextLine()) vs scanner.nextInt()

My professor tends to do the following to get a number from the user:
Scanner scanner = new Scanner(System.in);
Integer.parseInt(scanner.nextLine());
What are the benefits as opposed to simply doing scanner.nextInt() ?
java.util.Scanner.java has the following in it:
public int nextInt() {
return nextInt(defaultRadix);
}
public int nextInt(int radix) {
// Check cached result
if ((typeCache != null) && (typeCache instanceof Integer)
&& this.radix == radix) {
int val = ((Integer)typeCache).intValue();
useTypeCache();
return val;
}
setRadix(radix);
clearCaches();
// Search for next int
try {
String s = next(integerPattern());
if (matcher.group(SIMPLE_GROUP_INDEX) == null)
s = processIntegerToken(s);
return Integer.parseInt(s, radix);
} catch (NumberFormatException nfe) {
position = matcher.start(); // don't skip bad token
throw new InputMismatchException(nfe.getMessage());
}
}
As I see it, Scanner calls Integer.parseInt() itself as well, on top of additional hocus pocus. Are there significant performance gains in doing simply Integer.parseInt(scanner.nextLine()) ? Are there on the other hand any drawbacks?
How about when scanning through a file with significant amount of data, and not a user input?
There are 2 observations :
Using myScannerInstance.nextInt() leaves behind a new line character. So, if you call nextLine() after nextInt(), the nextLine() will read the new line character instead of the actual data. Consequently, you will have to add another nextLine() after the nextInt() to gobble up that dangling new-line character. nextLine() doesn't leave behind a new line character.
code :
int age=myScannerInstance.nextInt();
String name = myScannerInstance.nextLine();// here the actual name will not be read. The new line character will be read.
nextInt() will again go back to the underlying stream and read. IO calls take time (expensive). It will do lot of checks to get the next integer. nextLine() will do those checks only once. So, if you call nextLine() once and read 5 integers (as a single line String), split them and parse them as integers (using Integer.parseInt()), it will be faster and more efficient than reading each int individually.
Using nextLine() + parseInt() will give you enormous performance benefit when you are running a very large loop.
Usage :
Using nextInt() gives you an additional advantage wherein you will get an exception if the input text is not an integer. example 123 is accepted.. 123sdsa will throw an InputMismatchException. So, you can catch it and handle it appropriately.
Using nextLine() will read the entire line, so, it will read the entire String sada1231 and then fail with NumberFormatException if it cannot parse the String as a number. You will have to handle that exception.
Generally, one nextLine() / nextInt() call won't make much of a difference. If you have a loop or if you are reading lot of data, then using readLine() with parseInt() will be very efficient.
nextInt() reads a number, but doesn’t consume line separator. While nextLine() reads the String and consumes the new-line character. According to Java Docs:
… This method returns the rest of the current line, excluding any line
separator at the end. The position is set to the beginning of the next
line.
In other words when you enter a number then press Enter, input.nextInt() consumes only the number, not the "end of line", primitive data types like int, double etc does not consume "end of line", due which this "end of line" remain in buffer ane When input.next() executes, it consumes the "end of line" from buffer from the first input. So you professor is trying to get to the next line after he reads the user input. You have to look at the logic of his codes only then you can understand it.
I also used to face this problem often. So i use to code like this..
public static void main(String[] args) {
Scanner key= new Scanner(System.in);
String name;
int age;
age = key.nextInt();
key.nextLine();
name = key.nextLine(); //to carry the new line character left behind nextInt()
System.out.println("Age : "+age);
System.out.println("Name: "+name);
}
here as the key.nextInt() leaves a new line character we are using key.nextLine() to carry the new Line character and then move to the nextline where the actual data is present. As we discussed above using Integer.parseInt() will be more efficient than using nextInt(). But this is also one of the way to code to overcome the problem.
nextInt() leaves behind a new line character. So, if you call nextLine() after nextInt() , the nextLine() will read the new line character instead of the actual data. Consequently, you will have to add another nextLine() after the nextInt() to gobble up that dangling new-line character.
public class Solution {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
double d = scan.nextDouble();
scan.nextLine();
String s = scan.nextLine();
scan.close();
System.out.println("String: " + s);
System.out.println("Double: " + d);
System.out.println("Int: " + i);
}
}

Program unable to read from file and save to variable

When I run my code it says that there is an InputMismatchException? Works for the two first read-lines, but hwne I try to read the int and double-lines it doesn't and the string-line doesn't actually read anything into the variable, it is empty as it doesn't print anything at the system.out.println(a +b)... Any tips?
import java.util.*;
import java.io.*;
class Uke55{
public static void main(String[]args){
Scanner input=new Scanner(System.in);
try{
PrintWriter utfil=new PrintWriter(new File("minfil55.txt"));
utfil.println('A');
utfil.println("Canis familiaris betyr hund");
utfil.println(15);
utfil.printf("%.2f", 3.1415);
utfil.close();
}catch(Exception e){
e.printStackTrace();
}
try{
Scanner innfil=new Scanner(new File("minfil55.txt"));
char a=innfil.next().charAt(0);
String b=innfil.nextLine();
System.out.println(a +b);
int c=(int)innfil.nextInt();
double d=(double)innfil.nextDouble();
innfil.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
That's because when you use next(), nextInt(), and nextDouble(), it doesn't go to a new line. Only newLine() moves the cursor to the next line. Do this:
try{
Scanner innfil=new Scanner(new File("minfil55.txt"));
char a=innfil.nextLine().charAt(0); //first error was here. calling next() only
//read A and not the \r\n at the end of the
//line. Therefore, the line after this one was
//only reading a newline character and the
//nextInt() was trying to read the "Canis" line.
String b=innfil.nextLine();
System.out.println(a +b);
int c=(int)innfil.nextInt();
innfil.nextLine(); //call next line here to move to the next line.
double d=(double)innfil.nextDouble();
innfil.close();
}
catch(Exception e){
e.printStackTrace();
}
next(), nextInt(), nextDouble(), nextLong(), etc... all stop right before any whitespace (including the end of a line).
That is because you have in file:
A\n
Canis familiaris betyr hund\n
15\n
3.14
Where \n represents new line character.
When you call first time
innfil.nextLine().charAt(0)
it reads A, and scanner reading points to first \n
Then you call
innfil.nextLine()
it reads till \n (nextLine() reads till \n and puts scanner reading pointer past \n), and makes reading pointer past \n. Reading pointer will be at C in next line.
Then you call
innfil.nextInt()
duh! scanner can't recognize Canis as integer, input mismatch!
According to the documentation on Scanner.nextLine() it
"Advances this scanner past the current line and returns the input that was skipped."
So, after calling char a=innfil.next().charAt(0); the "cursor" is at the end of the first line. Calling String b=innfil.nextLine(); reads until the end of the current line (where there is nothing left to read) and advances to the next line (where the actual String is).
Solution
You need to advance to the next line before calling String b=innfil.nextLine();:
...
char a=innfil.next().charAt(0);
innfil.nextLine();
String b=innfil.nextLine();
...
Note:
Although Scanner.nextInt() and Scanner.nextDouble() behave the same way as Scanner.next(), you don't face the same problem, because those methods will read the next complete token (where "A complete token is preceded and followed by input that matches the delimiter pattern") and white-space characters (such as newline-characters) are considered delimiters. So, those methods will automatically advance to the next line if needed, in order to find the next complete token.
Did you check something is actually written to your file? I doubt that. Try calling flush() before you close your PrintWriter. EDIT: sorry I was wrong here because I was thinking of the auto line flush.

Categories

Resources