Strange output when I read from scanner - java

I'm trying to create a videoStore with the basic CRUD operation. For creating each movie I need to read the title, the year and the gender as below:
System.out.print("name: ");
name = in.nextLine();
System.out.print("year: ");
year = in.nextInt();
in.nextLine();
System.out.print("gender: ");
gender = in.next();
When I enter the addMovie option, I get this print on the console
(name: year:)
Can someone explain to me why it happens as above?
Here is the rest of the method:
static ArrayList<Movie> movies = new ArrayList<Movie>();
static Scanner in = new Scanner(System.in);
public static void InserirFilme() {
String name;
int year;
String gender;
boolean existe = false;
System.out.print("name: ");
name = in.nextLine();
System.out.print("year: ");
year = in.nextInt();
in.nextLine();
System.out.print("gender: ");
gender = in.next();
Movie movie = new Movie(name, year, gender);
for(Movie m: movies)
{
if(movie == m)
{
existe = true;
}
}
if(!existe)
{
movies.add(movie);
}
else
{
System.out.println("the movie already exists in the videoStore");
}
}

Calling next does not remove the line break, which means the next time you call InserirFilme the call to read the name can complete immediately. Use nextLine.
System.out.print("gender: ");
gender = in.nextLine();
(You probably mean "genre" instead of "gender" though)
Also, as mentioned in the comments, this check will never succeed:
if(movie == f)

You run this method in loop (right?)
The first call reads input correctly, but it leaves the linebreak in System.in after the last in.next().
On next call the name: is printed, then scanner reads an empty string from System.in because the linebreak already exists here.
And after thet the year: is printed on the same line because no new linebreaks are entered.
So you just have to insert another in.nextLine() after reading gender (or genre :) )
Or use nextLine() for read genre instead of next(), because genre might have more than one word.
But there are some disadvantages with using fake nextLine() to 'eat' linebreak - there might be another text which you doesn't process. It's a bad practice - to loose the data user entered.
It is better to read all the data from line, then validate/parse it, check isn't there some extra data, and if the data is invalid show notification and let him try to enter the right value.
Here are some examples how to deal with user input manually - https://stackoverflow.com/a/3059367/1916536. This is helpful to teach yourself.
Try to generalize user input operations:
name = validatedReader.readPhrase("name: ");
year = validatedReader.readNumber("year: ");
genre = validatedReader.readWord("genre: ");
where ValidatedReader is a custom wrapper for Scanner which could use your own validation rules, and could gently re-ask user after a wrong input.
It could also validate dates, phone numbers, emails, url's or so
For production purposes, it is better to use validation frameworks with configurable validation rules. There are a lot of validation frameworks for different purposes - Web, UI, REST etc...

when i enter the addMovie option, i get this print on the console (name: year:) can someone explain me why it happens i already searched a lot and i cant understand why :S
The way i understood your question is that you are getting the output (name: year: ) in a line and want it in seperate lines? In that case you simply can use System.out.println(String); instead of System.out.print(String). On the other hand you can also use "\n" whenever you want a linebreak within a String. Hope i could help you :).
Edit: If this was not an answer to your question, feel free to tell me and clarify your question :)

For String name you are using in.nextLine(); i.e the data entered on the entire line will be added to name string.
After "name: " is displayed, enter some text and press enter key, so that the year and gender fields will get correct values.
The code written is correct but you are not giving appropriate input through the scanner.
I recommend to use
String name = in.next();//instead of String name = in.nextLine();

You may instantiate Scanner Class differently for String and Integer type input. It works for me :)
Example:
static Scanner in1 = new Scanner(System.in);
static Scanner in2 = new Scanner(System.in);
Please use nextLine() for 'name' and 'gender'. It may contain more than one word. Let me know if it works.
Example:
System.out.print("name: ");
name = in1.nextLine();
System.out.print("year: ");
year = in2.nextInt();
System.out.print("gender: ");
gender = in1.nextLine();

Related

scanner.nextLine() not working like I think it does

I am creating a random name generator for a fantasy table top game I play with my friends. Everything is working so for, except for when I go to scan a nextLine() for my description, the program doesn't wait for input, and instead goes back to the start of the while loop. What I want to do, is be able to type in a short sentence about the character they are interacting with, and have it set to the String value Description, later my goal is to print these values out in a text document as I create them for future use. My code for that section looks like as follows. Any help is greatly appreciated.
System.out.println("Male (m) Female (f) Quit (q)");
ui = UserInput.next();
while(!(ui.equals("q"))){
if(ui.equals("m")){
mName = maleNameGenerator(MS, SS, MaleNamesArray, SurnamesArray);
System.out.println(mName);
System.out.print("Location: ");
Location = UserInput.next();
System.out.print("Profession: ");
Profession = UserInput.next();
System.out.print("Description: ");
Description = UserInput.nextLine();
}
else if(ui.equals("f")){
fName = femaleNameGenerator(FS, SS, FemaleNamesArray, SurnamesArray);
System.out.println(fName);
}
else if(!(ui.equals("q"))){
System.out.println("Please input valid choice.");
}
System.out.println("Male (m) Female (f) Quit (q)");
ui = UserInput.next();
ui.toLowerCase();
}
UserInput.close();
The next() method leaves behind a newline character after taking input. In your code, the nextLine() method simply consumes this newline character and ignores the actual input. You can add another nextLine() to make sure the input is received.
...
System.out.print("Description: ");
UserInput.nextLine();
Description = UserInput.nextLine();
This problem can also occur when using other non-String type Scanner input methods (nextInt(), nextDouble(), etc). The explanation and solution would be the same.

Java - Scanner execute only the Int and "skip" the Strings data types when i input String data before the Int ones [duplicate]

This question already has answers here:
Scanner is skipping nextLine() after using next() or nextFoo()?
(24 answers)
Closed 7 years ago.
While I'm working with java.util.Scanner, I tried to use integers and Strings at data input.
The problem that I faced is, when I input an Int data before a String one, the console skip the String data and go immediately to the next Int one.
Here is my simple problem where the problem is happening :
package justForTest;
import java.util.Scanner;
public class EmptySpaceWorkshop {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("- Enter your Name : ");
String name = input.nextLine();
System.out.print("- Enter your IC number : ");
int icNumber = input.nextInt();
System.out.print("- Enter your Place of birth : ");
String placeOfBirth = input.nextLine();
System.out.print("- Enter your Age : ");
int age = input.nextInt();
System.out.println("There once was a wonderful person named " + name+ ", His IC number is " + icNumber );
System.out.println(". He/She is " + age + " years old. She/He was born at " + placeOfBirth );
}
}
And here is my output:
- Enter your Name : Ali HISOKA
- Enter your IC number : 123456
- Enter your Place of birth : - Enter your Age :
I tried a lot to fix this problem. The only solution I could came up with is using input.next(); instead of input.nextLine(); . However, this solution is USELESS for me because as you guys know, when using input.next(); we can only type One Single Word, unlike input.nextLine(); we can type a lot of words which is the thing that I'm looking for. Also I DO NOT want to re-sort (re-arrange) my input and type the Strings data first, then following by the Int data to solve my problem. I want my data to be at the same sort as you seen above in my simple program ( Enter Name, Enter IC Number, Enter Place of Birth, then Enter age). So can I solve this problem ?
I searched a lot on the internet for someone got a problem as mine, but I couldn't find a question and solution for a problem looks exactly like mine.
I already know the reason and the explanation of my problem which is explained by
Joshua
"The reason for the error is that the nextInt only pulls the integer,
not the newline. If you add a in.nextLine() before your for loop, it
will eat the empty new line and allow you to enter 3 names."
but still it's not helpful for solving my problem.
Think of your input as a single string:
"Ali HISOKA\n123456\nPLACE\n99"
next() consumes the first word, up to first white space - e.g. " " or "\n"
nextLine() consumes the first word, up to first new line character
nextInt() consumes first word, as next(), and parses it to int - it will throw an exception if the word cannot be parsed.
Now, let's have a look what your calls are consuming:
nextLine() will return "Ali HISOKA", the remaining string is "123456\nPLACE\n99"
nextInt() will return int 123456, the remaining string is "\nPLACE\n99"
nextLine() will return empty string "", the remaining string is "PLACE\n99"
nextInt() will throw an exception, because it will try to parse "PLACE" to int.
The trick is in step 2 - although nextInt() consumes all white spaces between words, it however does not consume new line character, hence nextLine() in step 3 reads empty string because "\n" is first character in the remaining string.
There are two solutions:
Instead of using nextInt() you can read and parse the whole line Integer.parseInt(input.nextLine()). If the line contains a few words, e.g. "1234 abc" it will throw the exception.
Call input.nextLine() after calling nextInt(), so it consumes the remaining string up to first new line character. For input "1234 abc" it will ignore everything after the number.
I would recommend the first solution, because when you are asked for the number and you answer "123 abc", it is not a valid answer. In such case the user should be told that the input is invalid, instead of taking only a valid part from that answer - user would have no clue that part of his answer was ignored.
From what I can see it appears that the readLine() is just consuming the newline left after the int was taken from the buffer. A better way to fix this is to use nextLine() to get a string value and convert it:
int icNumber = Integer.parseInt(input.nextLine());
This is a bit confusing because the code you posted does not show your original problem, but the situation after putting in a workaround.
You need to skip the newline after nextInt()
System.out.print("- Enter your IC number : ");
int icNumber = input.nextInt();
input.skip("\\n");
Without the skip, input.newLine (for the place of birth) will match the newline after the entered IC number and you will be prompted for the age.
I tried your code at my machine without making any changes and Its working fine.Below is my output.
Enter your Name : yash
Enter your IC number : 12
Enter your Place of birth : alg
Enter your Age : 25
There once was a wonderful person named yash, His IC number is 12
. He/She is 25 years old. She/He was born at alg

Trouble with Scanner taking data from a command line using Java

I will admit, this is a school assignment... But I simply cannot figure out what I am doing wrong.
I have a hash table with an insert function. The following code is supposed to take a line of data from System.in in the format "Long String" (i.e. "32452 John"). The first token must be a Long for the ID number, and it must be followed by a String token for the name. When I run the program and I get to the portion where this must be executed (It is in a switch statement), I entered 'a' and hit enter. The command line immediately reads "Invalid value." (note: not VALUES, as that would mean it hit the nested if statement. It won't let me type in any data. Thank you in advance!
System.out.println("Enter ID and Name.");
//temp to take in the next line entered by the user
//inScan is the Scanner for System.in
temp = inScan.nextLine();
//Create Scanner for the line
Scanner tempScan = new Scanner(temp);
if(tempScan.hasNextLong()){
thisID = tempScan.nextLong();
if((tempScan.hasNext()) && (thisID>0)){
thisName = tempScan.next();
//The data will only be inserted if both segments of data are entered
myTable.insert(new Student(thisID, thisName));
}else{
System.out.println("Invalid values.");
}
}else{
System.out.println("Invalid value.");
}
Why do you need the second Scanner?
Example
String input = scanner.nextLine();
String[] tokens = input.split(" ");
Long id = Long.parseLong(tokens[0]);
String name = tokens[1];
And if you wanted to add your validation:
String input = scanner.nextLine();
if(input.contains(" ")) {
// You know there's a space in it.
String[] tokens = input.split(" ");
if(tokens.length == 2) {
// You know it's a value, followed by a space, followed by a value.
if(tokens[0].matches("[0-9]+")) {
// You know it only contains numbers.
Long id = Long.parseLong(tokens[0]);
}
}
}
I've not run it, but i guess your problem is that when you enter the text 'a' and hit enter, this line is false:
if(tempScan.hasNextLong()){
as you haven't entered a number. hence why it drops to the next block. If you enter something numerical first, i suspect your code with work. you probably need to add a 'while' loop around it, to run until it gets a number.
You already have a Scanner which reads from System.in, there's no need for another one. The second one you've made is a scanner for a String, which will never have a nextLong as it has nothing to scan after your String.
I won't write any code for you as this is homework, but stick to your original scanner when checking for user input instead.

Ignore space, blanks

Does anybody know how i could make scanner ignore space? I wanna type a first and second name, but scanner wont let me, i want to save the full name
String name;
System.out.print("Enter name: ");
name = scan.next(); //Ex: John Smith
System.out.println(name);
Edit:
New problem.. While using nextLine in my extended program, nextLine just ignores the whole question and moves on without a chance to scan the name.
Scanner#next() splits lines around whitespace. Scanner.nextLine() does not, therefore leaving spaces in.
name = scan.nextLine(); //Ex: John Smith
Well, first your System.out.print(); call is flawed. Everything inside must be inside quotations
System.out.print("Enter name: ");
scan.next() gets the next character in the stream, whereas scan.nextLine() gets the next line (terminated by an EOL character), which may be more helpful to you.
After that, you can create an array of words, like
String[] broken = name.split(" ");
which will place into broken all of the words that you've typed in delimited by spaces.
Then you can go something like
for(int i = 0; i < broken.size; i++)
{
System.out.print(broken[i] + " ");
}
System.out.println();
Scanner.next delimits using whitespaces, to read a full line you can use:
name = scan.nextLine();
use scanner.nextLine() which reads full line, instead of scan.next();
Example:
name = scan.nextLine();
Read oracle documentation for Scanner class for available methods.
sounds like you want to read the entire line (minus the line ending). if someone enters, "helen r. smith", you can read the line in with:
name = scan.nextLine();
YOU CAN DO LIKE THIS
import java.util.*;
class scanner2
{
public static void main(String args[])
{
Scanner in= new Scanner(System.in);
System.out.println("enter the name");
String name= in.nextLine();//for name with spaces with more than one word or for one word.
System.out.println("enter single word");
String rl= in.next();//single word name
System.out.println("name is "+name+" rl is "+rl);
}
}
Execute it you will get your answer.

Algorithm to output the initials of a name

I have just started the java programming and at the moment I am doing the basic things. I came across a problem that I can't solve and didn't found any answers around so I thought you might give me a hand. I want to write a program to prompt the user to enter their full name (first name, second name and surname) and output their initials.
Assuming that the user always types three names and does not include any unnecessary spaces. So the input data will always look like this : Name Middlename Surname
Some of my code that I have done and stuck in there as I get number of the letter that is in the code instead of letter itself.
import java.util.*;
public class Initials
{
public static void main (String[] args)
{
//create Scanner to read in data
Scanner myKeyboard = new Scanner(System.in);
//prompt user for input – use print to leave cursor on line
System.out.print("Please enter Your full Name , Middle name And Surname: ");
String name = myKeyboard.nextLine();
String initials1 = name.substring(0, 1);
int initials2 = name.
//output Initials
System.out.println ("Initials Are " + initials1 + initials2 + initials3);
}
}
Users will enter a string like
"first middle last"
so therefore you need to get each word from the string.
Loot at split.
After you get each word of the user-entered data, you need to use a loop to get the first letter of each part of the name.
First, the nextLine Function will return the full name. First, you need to .split() the string name on a space, perhaps. This requires a correctly formatted string from the user, but I wouldn't worry about that yet.
Once you split the string, it returns an array of strings. If the user put them in correectly, you can do a for loop on the array.
StringBuilder builder = new StringBuilder(3);
for(int i = 0; i < splitStringArray.length; i++)
{
builder.append(splitStringArray[i].substring(0,1));
}
System.out.println("Initials Are " + builder.toString());
Use the String split() method. This allows you to split a String using a certain regex (for example, spliting a String by the space character). The returned value is an array holding each of the split values. See the documentation for the method.
Scanner myKeyboard = new Scanner(System.in);
System.out.print("Please enter Your full Name , Middle name And Surname: ");
String name = myKeyboard.nextLine();
String[] nameParts = name.split(" ");
char firstInitial = nameParts[0].charAt(0);
char middleInitial = nameParts[1].charAt(0);
char lastInitial = nameParts[2].charAt(0);
System.out.println ("Initials Are " + firstInitial + middleInitial + lastInitial);
Note that the above assumes the user has entered the right number of names. You'll need to do some catching or checking if you need to safeguard against the users doing "weird" things.

Categories