Scanner next() confusion - java

In class java.util.Scanner,method public String next() finds and returns the next complete token from this Scanner,I am confused,if I write a program like this:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println(in.next());
in.close();
}
and run this program,then input a word and the word will be printed,it seems that method next() returns the current token,why does the API say next() returns the next complete token?

I will describe what all of this is about, since you are confused.
Scanner input = new Scanner(System.in)
java.lang.System is a public final class extending java.lang.Object and it has static fields namely err and out being of type PrintStream and in being of type InputStream hence,
System.in
java.util.Scanner extends java.lang.Object and implements the following interfaces:
Iterator
Closeable
AutoCloseable
Now that we understood the hierarchy. What happens during execution?
Execution of > Scanner input = new Scanner(System.in)
Constructs a new Scanner object passing it the source through which it should expect the input.
Execution of > input.next()
does the following steps
Block execution while waiting for input to scan
As soon as you provide an input (assume below)
"Hello World! This is a test."
and hit Enter the following steps take place
Scanner read the data from Input Stream
Tokenizes the input using the delimiter (default whitespace)
Construct an iterator similiar to Iterator iterate = tokens.iterator() for iteration through tokens
Find the first complete token being "Hello" in the scanner, returns the token and waits before next token.
The reason the first complete token is returned is because that is how next() method that is inherited from java.util.Iterator behaves. Basically think of it a pointer pointing to bunch of tokens in scanner arranged in an order. As soon as next() is invoked, returns first token and moves the pointer ahead.
hasNext() on the other hand, returns true if this scanner has another token from the location the iterator is pointing to. Unlike next() it does not advance past the token.
The documentation says the following about next()
Finds and returns the next complete token from this scanner. A
complete token is preceded and followed by input that matches the
delimiter pattern. This method may block while waiting for input to
scan, even if a previous invocation of hasNext() returned true.

This is because you assigned the Scanner to standart input (System.in).
If you use your exact program in this
IDEONE DEMO
OUTPUT (check in the link how stdin is assigned prior to execute)
Success!
stdin // this is what you assign
hello word
stdout // this is the output of main method
hello
word
If this does not clarify, maybe you will find this example useful. Check how I assign the Scanner to a created String:
String input = "hello my name is Jordi";
Scanner s = new Scanner(input); // assign the scanner to String s!!!!
System.out.println(s.next()); // prints: hello
System.out.println(s.next()); // prints: my
System.out.println(s.next()); // prints: name
System.out.println(s.next()); // prints: is
System.out.println(s.next()); // prints: Jordi
s.close();

You can think, that initially Scanner point on the beginning of the string, then when you call next() it reads starts from the current position.
Like this:
[h][e][l][l][o][_]
^
Scanner behave similar to iterators and starts "before" first character.

Related

Explanation for Java (palindrom string) and method next();

I want to know more about how next method work and Java utill scanner if someone can help me...
Scanner s = new Scanner(System.in);
System.out.println("Unesite string za proveru: ");
if(palindrom(s.next()))
System.out.println("String je palindrom");
else
System.out.println("String nije palindrom");
s.close();
what does next do? and how exactly scanner working also what means method close(); ??
next
public String next()
Finds and returns the next complete token from this scanner.A complete token is preceded and followed by input that matchesthe delimiter pattern. This method may block while waiting for input to scan, even if a previous invocation of hasNext() returned true.
Specified by:next in interface IteratorReturns:the next tokenThrows:NoSuchElementException
1 - if no more tokens are availableIllegalStateException
2- if this scanner is closedSee Also:Iterator
example :-
sc = "hello world"
1st time sc.next() output will be "hello"
2nd time sc.next() output will be "world"
close
public void close()
Closes this scanner.
If this scanner has not yet been closed then if its underlying readable also implements the Closeable interface then the readable's close methodwill be invoked. If this scanner is already closed then invoking thismethod will have no effect.
Attempting to perform search operations after a scanner hasbeen closed will result in an IllegalStateException.
Specified by:close in interface CloseableSpecified by:close in interface AutoCloseable
Scanner is a class that parses, and in some cases converts inputs. It uses whitespace as its default delimiter between tokens.
Scanner.next is a method that finds and returns the next token, if there is one.
Scanner.close is a method that releases the resource that the Scanner object is holding, such as an open file.

How to add a char into an array?

I have a question based on character arrays. At the moment I have an input variable that takes the first letter of the word.
char input = scanner.nextLine().charAt(0);
What I want to do is for every enter, I want to put it in an array so that I can keep a log of all the letters that have been retrievied. I am assuming this is using char[] but I am having trouble implementing added each input into the array.
char input = scanner.nextLine().charAt(0);
First thing that's unclear is what Object type is scanner?
But for now I'll assume scanner is the Scanner object from Java.util.Scanner
If that's the case scanner.nextLine() actually returns a String.
String has a charAt() method that will allow you to pick out a character anywhere in the string.
However scanner.nextLine() is getting the entire line, not just one word. So really scanner.nextLine().charAt(0) is getting the first character in the line.
scanner.next() will give you the next word in the line.
If the line contained "Hello World"
scanner.next().charAt(0) would return the character 'H'.
the next call of scanner.next().charAt(0) would then return the character 'W'
public static void main(String[] args) {
boolean finished = false;
ArrayList<Character> firstLetters = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
while (!finished) {
firstLetters.add(scanner.next().charAt(0));
}
}
The above code sample might give you the behavior you're looking for.
Please note that the while loop will run forever until finished becomes true.
Your program will have to decide when to set finished to true.
AND here's a couple of links about Java's Scanner class
tutorials point
Java Docs

How input was taken just using object of Scanner class?

public class Two {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int c=0;
while(sc.hasNext())System.out.println(++c+" "+sc.nextLine());
}
}
I came across this code and i want to confirm that by taking input directly without using object of any datatype all we are doing is taking input and displaying it and we are not storing it anywhere?
and also how is the condition inside while loop is true for the first time? As we have not given any input yet.
Sure, your code doesn't store sc.nextLine() , so this value will be discarded past the System.out.println instruction.
Also for hasNext() :
This method may block while waiting for input to scan.
so the condition will be met once the stream begins to provide input, and the method will block waiting for this to happen or an Exception to happen (e.g : if the Scanner gets closed ).
As long as nothing of those things happen, hasNext() method doesn't return, so the condition in while is still not evaluated, so the loop is blocked there .
Let's go through your code:
Scanner sc = new Scanner(System.in)
The java.util.Scanner.Scanner(InputStream) constructor is called, and you have an object sc of type Scanner which reads from System.in.
int c = 0;
You now have a primitive c of primitive type int.
while(sc.hasNext()) { ... }
The while loop evaluates sc.hasNext(), which is true. As per the documentation, sc.hasNext() returns true if and only if the input has another token in it. In your case, this means that the InputStream is open.
{... System.out.println(++c + " " + sc.nextLine()); ...}
sc.nextLine() is the problem. Assuming you have not changed System.in, the console/terminal will block the loop (i.e. hold the loop paused) until you give it an input (type in some text and hit [ENTER]).
So, overall:
Scanner::hasNext() will return true if and only if it is possible to get more input (if you are using System.in, this will always be true until you close the scanner).
If you are printing the input directly, you will not be storing any references to it, and no memory will be allocated for it (unless Scanner.nextLine() stores it somewhere).

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.

while (scanner.hasNext()) loop not working twice? Java

I have made a program which is like a vending machine!
My code is similar to:
public static void main (String [] args) {
Scanner sc = new Scanner (System.in);
while(sc.hasNext()) {
String string = sc.next();
sum = generateSum(sum)
.....
}
}
public static int generateSum(int sum) {
Scanner sc = new Scanner (System.in);
while (sc.hasNext()) {
....
}
return sum;
}
Sorry for simplifying my code, but the normal one is very long! However, the problem is that I use while (sc.hasNext()) loop twice. Basically I want to continue my main method until the input from the user is TERMINATE, but my program terminates after running once.
I figured that if I take out my generateSum method, then the loop in my main method works fine so i guess it has to be something to do with have the while (sc.hasNext()) loop twice.
Any ideas how I can fix the problem?
The hasNext() method is going to block until you hit the end of file marker on System.in because it doesn't know if there's more input until it reads a full buffers worth or hits end of file (which you can signal with Control-Z on windows and Control-D on unix). At that point System.in is at the EOF mark and there's no way to re-open it from your code.
If you need to process multiple streams of data from System.in you are going to have to use some sort of sentinel value (such as the word END) to mark the end of one input stream and the beginning of another.
I'm quite sure that if you consume the input being scanned with sc.next() the state changes and hasNext() returns accordingly.The problem may be there.
The hasNext() method can be called as much as you want. But if in the inner loop you are calling the next() method, then that can eat the values from your outer loop.
So the inner loop most probably breaks after hasNext() is false and thus the outer loop also finishes.

Categories

Resources