FileWriter not receiving all input and mysterious dangling newline issue - java

I am trying to write a Java program in which the user specifies how many "student records" they would like to input, followed by the student's name, age, and GPA, which then gets stored as text. However, I am having a problem with my text not including all entered data and a mysterious dangling newline that I cannot get rid of.
Here is my program:
import java.io.*;
import java.util.Scanner;
public class CreateFile {
public static void main(String[] args) throws IOException {
Scanner input = new Scanner(System.in);
FileWriter fwriter = new FileWriter("c:\\Students.dat");
PrintWriter StudentFile = new PrintWriter(fwriter);
String name = " ";
String next = " ";
int age = 0;
int hm = 0;
double gpa = 0.0;
System.out.print("How many student records would you like to enter: ");
hm = input.nextInt();
for (int x = 1; x <= hm; x++) {
System.out.print("Enter Name: ");
name = input.nextLine();
input.nextLine();
System.out.print("Enter Age: ");
age = input.nextInt();
System.out.print("Enter GPA: ");
gpa = input.nextDouble();
next = input.nextLine();
StudentFile.println(name);
StudentFile.println(age);
StudentFile.println(gpa);
}
StudentFile.close();
System.exit(0);
}
}
Here is sample input and output to illustrate my issues:
run:
How many student records would you like to enter: 3
Enter Name: Jon
Enter Age: 20
Enter GPA: 3.4
Enter Name: Bill
Enter Age: 24
Enter GPA: 3.6
Enter Name: Ted
Enter Age: 34
Enter GPA: 3.9
This is the produced text file:
20
3.4
Bill
24
3.6
Ted
34
3.9
Why doesn't it store the first name entered? Why isn't there a newline in the first entry, but it is in the others?

The problem is that you're using nextLine() when you need to be using next(). I'm assuming you put the second input.nextLine() in there because you were initially having a problem where it would print out "Enter Name: " and then immediately "Enter Age: ". nextLine() is telling your program to skip whatever is there, and not to wait for it. The reason that this paradigm worked at all for any of your entries is that you put next = input.nextLine() at the bottom of your loop. Here's a fix:
package createfile;
import java.io.*;
import java.util.Scanner;
public class CreateFile {
public static void main(String[] args) throws IOException {
Scanner input = new Scanner(System.in);
FileWriter fwriter = new FileWriter("c:Students.dat");
PrintWriter StudentFile = new PrintWriter(fwriter);
String name = " ";
String next = " ";
int age = 0;
int hm = 0;
double gpa = 0.0;
System.out.print("How many student records would you like to enter: ");
hm = input.nextInt();
for (int x = 1; x <= hm; x++) {
System.out.print("Enter Name: ");
name = input.next();
System.out.print("Enter Age: ");
age = input.nextInt();
System.out.print("Enter GPA: ");
gpa = input.nextDouble();
StudentFile.println(name);
StudentFile.println(age);
StudentFile.println(gpa);
}
StudentFile.close();
System.exit(0);
}
}
You could also just move your input.nextLine() above name=input.nextLine() and it would have the same effect.

The other examples only work if you don't have names like "James Peter" - in their code examples only James would be saved as name.
I'd prefer this:
System.out.print("How many student records would you like to enter: ");
hm = input.nextInt();
input.nextLine();
for (int x = 1; x <= hm; x++) {
System.out.print("Enter Name: ");
name = input.nextLine();
System.out.print("Enter Age: ");
age = input.nextInt();
input.nextLine();
System.out.print("Enter GPA: ");
gpa = input.nextDouble();
input.nextLine();
StudentFile.println(name);
StudentFile.println(age);
StudentFile.println(gpa);
}

This is the corrected for loop:
for ( int x = 1; x <= hm; x++ )
{
System.out.print( "Enter Name: " );
name = input.next();
input.nextLine();
System.out.print( "Enter Age: " );
age = input.nextInt();
input.nextLine();
System.out.print( "Enter GPA: " );
gpa = input.nextDouble();
next = input.nextLine();
StudentFile.println( name );
StudentFile.println( age );
StudentFile.println( gpa );
}
Some things you may want to consider:
Handle the IOException - it should not be ignored!!
Use the methods hasNextXXX() of the Scanner to check if something is available.
Refactor your usage of the variable next, it's never really used.
It's not necessary to call System.exit( 0 ) from the main method - rather use the return statement with a meaningful value.

Related

How do I accept the user input and put it into the while condition

This is my code, the while loop does not have an input and the rep variable does not accept an input:
import java.util.Scanner;
public class MixedData {
public static void main(String[] args) {
String rep = "";
do {
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter your full name");
String name = keyboard.nextLine();
System.out.print("Enter your GPA: ");
double gpa = keyboard.nextDouble();
System.out.println("Name: " + name + ", GPA: " + gpa);
System.out.println("Do you want to enter the data for another student?(y/n)");
rep = keyboard.nextLine();
} // This does not accept input
while (rep.equals("y"));
}
}
Either just add one more keyboard.nextLine() before rep = keyboard.nextLine(); (in order to clear the newline character), or read your double gpa value with:
double gpa = Double.parseDouble(keyboard.nextLine());
Important point to understand here (especially if you're a novice Java developer), about why your code doesn't work, is, that you invoke nextDouble() as a last method on your Scanner instance, and it doesn't move the cursor to the next line.
A bit more details:
All the methods patterned nextX() (like nextDouble(), nextInt(), etc.), except nextLine(), read next token you enter, but if the token isn't a new line character, then the cursor isn't moved to the next line. When you enter double value and hit Enter, you actually give to the input stream two tokens: a double value, and a new line character, the double value is initialized into the variable, and the new line character stays into input stream. The next time you invoke nextLine(), that very new line character is read, and that's what gives you an empty string.
Here's the same code using a while loop instead of do-while. It works the way you want it to.
import java.util.Scanner;
public class MixedData {
public static void main(String[] args) {
String rep = "y";
while (!rep.equals("n")) {
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter your full name: ");
String name = keyboard.nextLine();
System.out.print("Enter your GPA: ");
double gpa = keyboard.nextDouble();
System.out.println("Name: " + name + ",GPA: " + gpa);
System.out.println("Do you want to enter the data for another student?(y/n)");
rep = keyboard.next();
}
}
}
You need to skip blank lines.
public static void main(String[] args) {
String rep;
Scanner keyboard = new Scanner(System.in);
do {
System.out.print("Enter your full name");
String name = keyboard.nextLine();
System.out.print("Enter your GPA: ");
double gpa = keyboard.nextDouble();
System.out.println("Name: " + name + ", GPA: " + gpa);
System.out.println("Do you want to enter the data for another student?(y/n)");
rep = keyboard.next();
keyboard.skip("\r\n"); // to skip blank lines
}
while (rep.equalsIgnoreCase("y"));
keyboard.close();
}
Use nextLine instead of nextDouble:
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
String rep = "";
do {
System.out.println("Enter your full name:");
String name = keyboard.nextLine();
System.out.println("Enter your GPA:");
// double gpa = keyboard.nextDouble();
double gpa = Double.parseDouble(keyboard.nextLine());
System.out.println("Name: " + name + ", GPA: " + gpa);
System.out.println("Do you want to enter the data for another student?(y/n)");
rep = keyboard.nextLine();
} while (rep.equals("y"));
keyboard.close();
}

Making parallel array that accepts names, hours, payrates

So for this program I need to have three arrays accept data and display the gross pay, It seems to work at first but after enter the first person's data, my code begins to stack on top of itself in the window, please help me fix this to work properly.
I am required to use arrays. Objects are not allowed.
import java.util.Scanner;
public class ThreeArrays {
public static void main(String args[]) {
float[] payRate = new float[5];
float[] hours = new float[5];
String[] name = new String[5];
getPayData(name, hours, payRate);
displayGrossPay(name, hours, payRate);
}
public static void getPayData(String[] name, float[] hours, float[] payRate) {
Scanner kb = new Scanner(System.in);
for (int i = 0; i < hours.length; i++) {
System.out.print("Enter the employee's name: ");
name[i] = kb.nextLine();
System.out.print("Enter the employee's hours: ");
hours[i] = kb.nextFloat();
System.out.print("Enter the employee's hourly rate: ");
payRate[i] = kb.nextFloat();
}
}
public static void displayGrossPay(String[] name, float[] hours, float[] payRate) {
for (int i = 0; i < hours.length; i++) {
System.out.println("Employee name: " + name[i] + " Gross Pay: " + hours[i] *
payRate[i]);
}
}
}
Put System.out.println(); between each statement where you ask for data.
EDIT: It could also be that the \n character isn't being read with .nextInt(). To fix it, put kb.nextLine(); after kb.nextFloat();
for (int i = 0; i < hours.length; i++) {
System.out.print("Enter the employee's name: ");
name[i] = kb.nextLine();
System.out.println("");
System.out.print("Enter the employee's hours: ");
hours[i] = kb.nextFloat();
kb.nextLine();
System.out.println("");
System.out.print("Enter the employee's hourly rate: ");
payRate[i] = kb.nextFloat();
kb.nextLine();
System.out.println("");
}
// Enter the employee's name: Foo
// (Blank Line)
// Enter the employee's hours: 1
// (Blank Line)
// Enter the employee's hourly rate: -20.00 // They owe me now. :D
// (Blank Line)
The problem is related to stdin flushing. Because last entered float value for line payRate[i] = kb.nextFloat(); don't removes \n character. This \n character is being fetched by line name[i] = kb.nextLine(); in next iteration. Which further leaves a String value for line hours[i] = kb.nextFloat();. Since it is not a valid float hence you are getting exception: java.util.InputMismatchException.
To solve this use line if(i < hours.length-1) kb.next(); after line payRate[i] = kb.nextFloat();.
Following is corrected code. See complete working code here:
public class ThreeArrays {
public static void main(String args[]) {
float[] payRate = new float[5];
float[] hours = new float[5];
String[] name = new String[5];
getPayData(name, hours, payRate);
displayGrossPay(name, hours, payRate);
}
public static void getPayData(String[] name, float[] hours, float[] payRate) {
Scanner kb = new Scanner(System.in);
for (int i = 0; i < hours.length; i++) {
System.out.print("Enter the employee's name: ");
name[i] = kb.nextLine();
System.out.print("Enter the employee's hours: ");
hours[i] = kb.nextFloat();
System.out.print("Enter the employee's hourly rate: ");
payRate[i] = kb.nextFloat();
if(i < hours.length-1) kb.next();
}
}
public static void displayGrossPay(String[] name, float[] hours, float[] payRate) {
for (int i = 0; i < hours.length; i++) {
System.out.println("Employee name: " + name[i] + " Gross Pay: " + (hours[i] *
payRate[i]));
}
}
}
I have figured it out everyone
The problem lies with using
System.out.print("Enter the employee's name: ");
name[i] = kb.nextLine();
I had to change it to
System.out.print("Enter the employee's name: ");
name[i] = kb.next();

How do i take an integer that was inputed through a in.nextInt(); and in.nextDouble(); and multiply those two together?

Code:
public static void main (String[] args)
{
//last name,first name
Scanner in = new Scanner(System.in);
System.out.print(" Enter the name (Last, First): ");
String firstToken = in.next();
String restOfSentence = in.nextLine();
String sentence = firstToken + restOfSentence;
//phone number
System.out.print(" Enter the phone number (###) ###-####: ");
String phoneNum = in.next();
String restOfNum = in.nextLine();
String sentence2 = phoneNum + restOfNum;
//Name of book
System.out.print(" Enter the title of the book: ");
String bookName = in.next();
String restOfName = in.nextLine();
String sentence3 = bookName + restOfName;
//Date checked out
System.out.print(" Enter the date checked out (mm/dd/yyyy): ");
String bookDate = in.next();
String restOfDate = in.nextLine();
String sentence4 = bookDate + restOfDate;
// Days late
System.out.print("Days late: ");
in.nextInt();
// Daily Fine
System.out.print("Daily fine: ");
in.nextDouble();
//daily fine calculation
fine =
}
I need to take the days overdue and multiply it by the daily fine to get the total price of the fine. I Do not need it to be shown on the screen I just need it to be calculated for later when I do need it on the screen
How about something like:
// Days late
System.out.print("Days late: ");
int daysLate = in.nextInt();
// You will probably need to get rid of the new line character here
in.nextLine();
// Daily Fine
System.out.print("Daily fine: ");
double dailyFine = in.nextDouble();
// And here..
in.nextLine();
//daily fine calculation
double fine = daysLate * dailyFine;
Store them in variables, multiply them.
Use Scanner#nextLine to clear away the new line character after integer and double inputs

Trouble using nextInt and nextLine()

It's not letting me put my name in but it does the age works fine.
I know i can change the order of the statements but is there another way I could do it?
import java.util.Scanner;
public class ScannerErr2
{
public static void main(String [] args)
{
Scanner keyboard= new Scanner(System.in);
String name;
int age;
System.out.print("Enter your age : ");
age= keyboard.nextInt();
System.out.print("Enter your name: ");
name= keyboard.nextLine();
System.out.println("Age : "+age);
System.out.println("Name: "+name);
}
}
You problem is that the next int doesn't consider the new line character which goes in the input for your name part. Hence name is returned as blank.
You can change your code in 2 ways:
System.out.print("Enter your age : ");
age = keyboard.nextInt();
keyboard.nextLine();
System.out.print("Enter your name: ");
name = keyboard.nextLine();
or
System.out.print("Enter your age : ");
age = Integer.parseInt(keyboard.nextLine().trim());
System.out.print("Enter your name: ");
name = keyboard.nextLine();
I personally like the second way.

why do i have this infinite for loop

I am working on this airline program. The program should ask the user how many seats on the plane are sold and then I have this for loop to allow a user to enter a name and a meal choice for each person on the plane.
I have tried reading through some different questions about infinite for loops on stackoverflow, but I can't seem to figure out exactly what is going wrong with my code. I feel like there must be something about for loops that I am not understanding because I thought that it would only go through until your i < someNumber is no longer true.
So when I run this program, say I enter 2 seats I would expect it to go through the loop just twice, but It just keeps going. asking for a name and then a meal.
import java.util.Scanner;
public class Flyers
{
String name;
String mealType;
int economySeats;
int businessSeats;
int firstClassSeats;
int count;
public Flyers()
{
}
public String toString()
{
Scanner in = new Scanner(System.in);
System.out.print("Enter a name: ");
name = in.next();
System.out.print("Enter a meal: ");
mealType = in.next();
return "Name: " + name + ", Meal " + mealType;
}
public void addEconomyFlyers()
{
Scanner in = new Scanner(System.in);
System.out.print("Enter number of economy seats sold: ");
economySeats = in.nextInt();
for(count = 0; count < economySeats; count++)
{
System.out.print("Enter a name: ");
name = in.next();
System.out.print("Enter a meal: ");
mealType = in.next();
Flyers newFlyer = new Flyers();
String seat = newFlyer.toString();
}
}
Here is my main class if that is helpful.
import java.util.Scanner;
public class Aviation
{
public Aviation()
{
}
public static void main(String[] args)
{
int option;
FlightCost newFlight = new FlightCost();
FlightProfit flight = new FlightProfit();
Flyers newFlyers = new Flyers();
Scanner in = new Scanner(System.in);
System.out.print("Enter new flight location: ");
String location = in.next();
do{
String menu = "\n Please select an option to perform"
+ "\n1 (1) Get flight costs."
+ "\n2 (2) Get flight profits."
+ "\n3 (3) Enter names/meals."
+ "\n4 (4) Exit.";
System.out.println(menu);
option = in.nextInt();
}while (option < 0 || option > 4);
switch(option)
{
case 1:
newFlight.getCost(location);
break;
case 2:
flight.addEconomySeats();
flight.addBusinessSeats();
flight.addFirstClassSeats();
flight.getProfit(location);
break;
case 3:
newFlyers.addEconomyFlyers();
break;
case 4:
System.out.println("Exit");
break;
default:
System.out.println("Error: must select menu option.");
}
}
}
remove below code from toString()
Scanner in = new Scanner(System.in);
System.out.print("Enter a name: ");
name = in.next();
System.out.print("Enter a meal: ");
mealType = in.next();
You are already reading these from the for loop.
Also, your do-while loop is all wrong. The condition doesn't make sense. It should be option > 0 && option <4
As Pat said:
Scanner in = new Scanner(System.in);
System.out.print("Enter a name: ");
name = in.next();
System.out.print("Enter a meal: ");
mealType = in.next();
this code in the toString() is obsolete
however the do while does make sense, to me at least, as i see it you want the menu printed out each time the user gives an invalid int, however you are still letting 0 get through although that is not a valid choice, the do while should be:
while (option <= 0 || option > 4);
or
while (option < 1 || option > 4);
Another quirk in your code:
System.out.print("Enter a name: ");
name = in.next();
System.out.print("Enter a meal: ");
mealType = in.next();
Flyers newFlyer = new Flyers();
String seat = newFlyer.toString();
you create a new instance of the class you have just modified and call toString() on, even though you have not populated that class with data, so the toString method as it would be after the edit pat suggested will return "Name: Meal "
As i see your code is a work in progress, try adding more System.out.print on various variables for debugging purpose or use a debugger, though i know using debugger when learning can be difficult, it sure was for me. Also remember that every time you create a new instance ex:
Flyers newFlyer = new Flyers();
it has only the data that is either set by default or set in your constructor ex:
public Flyers()
{
}
I hope what i wrote was helpful, have a nice day and keep at it.

Categories