User input for file reader - java

Not sure if the title will make much sense but I'm currently quite confused and not sure how to work around my problem.
I'm trying to request from the user, a destination, a max time period (in the format HH:MM) and a maximum number of changes, which so far I have done. It should then calculate each journey’s total mins along with number of changes and then compare both with the user’s criteria, I recently edited my program to use case statements.
It does link to a .txt file that has the following data in it:
York
1
60
60
Alnwick
0
130
Alnwick
2
30
20
20
So my program asks for a destination, either York or Alnwick and a number of changes, maximum time, and so on but I can't figure out how to make it work with the chosen destination, current code to follow:
import java.io.FileReader;
import java.util.Scanner;
public class InputOutput {
public static void main(String[] args) throws Exception {
// these will never change (be re-assigned)
final Scanner console = new Scanner(System.in);
final Scanner INPUT = new Scanner(new FileReader("C:\\Users\\Luke\\workspace\\Coursework\\input.txt"));
System.out.print("-- MENU -- \n");
System.out.print("1: Blahblahblah \n");
System.out.print("2: Blahblahblah \n");
System.out.print("Q: Blahblahblah \n");
System.out.print("Pick an option: ");
int option = console.nextInt();
switch(option) {
case 1 :
while(INPUT.hasNextLine()) {
System.out.println(INPUT.nextLine());
}
break;
case 2 :
System.out.print("Specify desired location: ");
String destination = console.next();
System.out.print("Specify Max Time (HH:MM): ");
String choice = console.next();
// save the index of the colon
int colon = choice.indexOf(':');
// strip the hours preceding the colon then convert to int
int givenHours = Integer.parseInt(choice.substring(0, colon));
// strip the mins following the colon then convert to int
int givenMins = Integer.parseInt(choice.substring(colon + 1, choice.length()));
// calculate the time's total mins
int maxMins = (givenHours * 60) + givenMins;
System.out.print("Specify maximum changes: ");
int maxChange = console.nextInt();
// gui spacing
System.out.println();
int mins = INPUT.nextInt();
int change = INPUT.nextInt();
if ((mins > maxMins) || (change > maxChange)) {
System.out.format("Time: %02d:%02d, Changes: %d = Unsuitable \n", (mins / 60), (mins % 60), change);
}
else {
System.out.format("Time: %02d:%02d, Changes: %d = Suitable \n", (mins / 60), (mins % 60), change);
}
//Do stuff
break;
case 3 :
default :
//Default case, reprint menu?
}
}
}
Have edited it to reduce the size of the question for StackOverflow but if more code is needed please let me know - any further help would be greatly appreciated!

You should really learn how the Scanner works:
int Scanner.nextInt() Returns the next int value that occurred in the next line.
String Scanner.next() Returns the next piece of String separated by the default delimiter which is space " ". (You could use a different Delimiter with Scanner.useDelimiter(String)). In default case this returns the next single Word.
String Scanner.nextLine() Returns the next full line separated with the "\n" Character.
So if you want to get a destination that has two words for Example "New York" and you fetch it with Scanner.next() like you do. Then you take the time the same way. You will get destination="New" and choice = "York" which is not parsable for : and will crash.
The other problem you have is that a Scanner works from start to end. So if you choose option 1 and print all the output from your input file you will reach the end and hasNextLine() == false. Means you cannot get any INPUT.nextInt() after that point. But you try when chosing option 2 after that.
Your prorgamm should start by reading in your input file into a data structure that stores all the informations for you. And get them from there in further process.
What is crashing in your code for now is that you start reading your text file with INPUT.nextInt() but the first line of your text file is York which has no Int value in it. You could repair that by adding:
[...]
System.out.println();
INPUT.nextLine(); // skips the first line which is York
int mins = INPUT.nextInt();
int change = INPUT.nextInt();
[...]

Related

I try to make a guess game and let user decide under what max number to guess

In oder to check the value entered by the user AND to see what random number has been calculated, I want to let those numbers projected in the console (eclipse). But what sketches my astonishment?? the last two system.out.println's (right above invoermax.close())) do NOT appear in the console screen after I entered the number???? It's like java doesn't even read or notice these code lines, How come???
Here my code:
package Package1;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
public class test6KOPIE1 {
public static void main(String[] args)
{
Scanner Invoermax = new Scanner(System.in);
System.out.println("Under which number you want to guess");
int Invoer = Invoermax.nextInt();
int Hoogte = ThreadLocalRandom.current().nextInt(1,Invoermax.nextInt());
System.out.println("So a guess under max: " + Invoer);
System.out.println("The random number has become " + Hoogte);
Invoermax.close();
}
}
every time you call Scanner.nextInt() it will wait for input from you.
The problem is that you are calling it twice, replace:
int Hoogte = ThreadLocalRandom.current().nextInt(1,Invoermax.nextInt());
With the variable you already got:
int Hoogte = ThreadLocalRandom.current().nextInt(1,Invoer);
And BTW, usually in java you start field/variable name with lower case letter, so should be hoogte, inoverMax, inover etc.
You can do something like this.
// code
Scanner Invoermax = new Scanner(System.in);
System.out.println("Under which number you want to guess");
int Invoer = Invoermax.nextInt();
Invoermax.nextLine(); // reading empty space left
int Hoogte = ThreadLocalRandom.current().nextInt(1,Invoermax.nextInt());
// code
You have two scanner.nextInt() calls, so there are two input readings, two input waitings.
int Invoer = Invoermax.nextInt(); // the first input reading
int Hoogte = ThreadLocalRandom.current().nextInt(1,
Invoermax.nextInt()); // the second input reading
When you enter two int values in a console (any of the kind) you'll see your ending print rows.
If your design was to have a single input, then use cashed value for the second usage
int Invoer = Invoermax.nextInt(); // the first input reading
int Hoogte = ThreadLocalRandom.current().nextInt(1,
Invoer ); // use cashed value

first line of code in do...while loop skipped while entering the loop the second time - Java

here is my code
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int[] data = new int[10];
int count = 0;
do {
System.out.print("Enter a number or ctrl + z when you are done: ");
data[count] = input.nextInt();
}
while (input.hasNextDouble());
}
}
output
Enter a number or ctrl + z when you are done: 2
4
Enter a number or ctrl + z when you are done: 6
Enter a number or ctrl + z when you are done: 8
My question is i don't know why the code jumps the System.out.print("Enter a number or ctrl + z when you are done: "); after do { when entering the loop the second time. This can be seen in second line of the output. Please what are my doing wrong?
I have searched for cases where my question might have already been answered but was only able to find solutions relating to code skipping nextLine()
The reason is first time do block is executed and then check for condition in while.
About hasNextDouble() in orcale doc:
Returns true if the next token in this scanner's input can be
interpreted as a double value using the nextDouble() method. The
scanner does not advance past any input.
As a solution you can change the condition like below:
do {
System.out.print("Enter a number or ctrl + z when you are done: ");
data[count] = input.nextInt();
count++;
}
while (count < 10);
Also:
If you are using input.nextInt();, better to check using hasNextInt().
ah your while loop is waiting to see if input hasNextDouble()
how can it know until your user has entered the next double or hit ctrl-z?
you'll have to do something Ugly like
System.out.print("Enter a number or ctrl + z when you are done: ");
do {
data[count++] = input.nextInt();
System.out.print("Enter a number or ctrl + z when you are done: ");
}
while (input.hasNextDouble());
note the count++ above as well i think it fixes another bug.
This happens because the first call to input.hasNextDouble() waits for a number to be entered before proceeding.
So the message in the second iteration of the loop won't appear until input.hasNextDouble() at the end of the first iteration of the loop has run - which of course fetches the second number.
You need to print the message before you call either hasNextDouble or hasNextInt.

Runtime Ignoring While Loops?

I am new to the forums so first of all I'd like to say "Hi"! I'm new to Java programming and am trying to make a simple payroll calculating program with three while loops.
The first while loop keeps the program going until the user enters the sentinel "stop". The second and third loops are error traps that ensure the user enters a positive number before continuing.
For some reason, the while loops are not working and I have tried every variation I can think of. The program runs just fine, it just ignores the while loops. If someone could provide some suggestions as to what I'm doing wrong, I'd really appreciate it.
I'm using NetBeans 8.0 IDE if that helps.
Here is my code:
Import java.util.*;
Import java.text.*;
public class PayrollProgramVersion2
{
//begin main program
public static void main(String[] args)
{
//declare new scanner
Scanner sc = new Scanner (System.in); // declare new scanner object
DecimalFormat Dollars = new DecimalFormat ("$0.00"); //format for dollars
String Employee; //employee's name
Double Hours, //hours worked
Rate, //pay rate
Pay; // Hours * Rate
Boolean Continue = true; // sentinel for program loop
//welcome user, prompt for employee name, and assign input to Employee
System.out.println ("Welcome to the payroll program!");
System.out.println ("What is the employee's name? (Enter stop to quit.)");
Employee = sc.nextLine();
// while loop continues program until user enters "stop"
while (Continue == true)
{
if (Employee.equalsIgnoreCase("stop"))
{
Continue = false;
} // end if
else
{
//prompt for hours worked and assign to Hours
System.out.println ("How many hours did " +Employee+ " work?");
Hours = sc.nextDouble();
//this block is an error trap to ensure input is positive before continuing
while (Hours < 0)
{
System.out.println( "Error - input must be a positive number");
System.out.println ("How many hours did " +Employee+ " work?");
Hours = sc.nextDouble();
}
//prompt for pay rate and assign to Rate
System.out.println( "How much does " +Employee+ " make per hour?");
Rate = sc.nextDouble();
//this block is an error trap to ensure input is positive before continuing
while (Rate < 0)
{
System.out.println( "Error - input must be a positive number");
System.out.println( "How much does " +Employee+ " make per hour?");
Rate = sc.nextDouble();
}
Pay = Hours * Rate; // calculate payrate
//display results
System.out.println(Employee+ "'s paycheck is " +(Dollars.format(Pay))+ ".");
System.out.println ("What is the employee's name? (Enter stop to quit.)");
Employee = sc.nextLine();
} //end else
} //end while
System.out.println ("Thank you for using the payroll program. Goodbye!");
} // end main
} // end program
From what I can see you should make your while (hours<0) to while (hours<0 || hours == null).
This is because... As far as I can see you initialise hours. But no value is input into it. So it remains as null. You could also try changing the while to an if.
Hope this helps. It may be that it does default to 0 but it may be worth for testin purposes to have a console output.
System.out.println(hours);
Befor the while loop to see what your program is reading hours as.
Hope this helps.
The error is that nextDouble does not eat the newline. It skips newlines at the beginning, so in effect only the last nextDouble is concerned.
Best to make a utility function:
Instead of
Hours = sc.nextDouble();
call your own function:
Hours = nextDouble(sc);
private static double nextDouble(Scanner sc) {
double value = -1.0;
if (sc.hasNextDouble()) {
value = sc.nextDouble();
}
sc.nextLine();
return value;
}
Use a small initial letter for field and method names.
Use double/boolean/int instead of the Double/Boolean/Integer as the latter are Object wrappers (classes); the first primitive types.
Call sc.close(); (for good order).
Aside from what has been said above:
sc.nextDouble consumes and returns the next input from the current line. It does not forward the line.
sc.nextLine consumes and returns the input from the current line and forwards to the next line
At the end of your while loop you call Employee = sc.nextLine(); If you follow your logic and only input allowed values, this will always return an empty string as it consumes the current line where your most previously removed double was stored(now empty string "")
When you do something like:
Hours = sc.nextDouble();
you trust the user to enter a double value, and in case the user entered illegal value, a String for example, this line will throw an exception.
You can solve it like this:
while (Hours < 0)
{
System.out.println( "Error - input must be a positive number");
System.out.println ("How many hours did " +Employee+ " work?");
String hours = sc.nextLine();
try {
Hours = Double.valueOf(hours);
}
catch (NumberFormatException e) {
// keep looping until we get a legal value
Hours = -1.0;
}
}

Limiting the length of an input to x amount of digits

I'm running a java program I created that stores data inputted by user. Specifically 4 array lists which are songName, songArtist, songYear & songAlbum.
I have a user input for "songYear" and I only want the program to accept a maximum of 4 digits in length and give an error otherwise, how can this be achieved?
here's the code I have for my add entry method:
public void addEntry(){
String newName = ui.getString("Enter the name of the track");
songName.add(newName);
String newArtist = ui.getString("Who performs this track");
songArtist.add(newArtist);
String newAlbum = ui.getString("What album is this track from");
songAlbum.add(newAlbum);
System.out.print("What year was the track released? ");
int newYear=input.nextInt(4);
songYear.add(newYear);
System.out.println("\n" + "Thank you, " +songName.get(songName.size()-1) + " has been added to the library.");
System.out.println("\n" + "Press 2 to view your library." + "\n");
}
You can use regex like: ^.{4}$
Means only if user typed 4 digits - return true, otherwise return false
To be sure that user used 4 numbers YYYY use something like:
^(?=[1-9]+)\d{4}$
Makes sure the year is 1 or 2 followed by three numbers; valid ranges in this case would be 1000-2999
^(?=[1-2][0-9]+)\d{4}$
Finally your code should be like:
if(inputUserStr.matches("^(?=[1-2][0-9]+)\d{4}$")){
// do some stuff
}
else{
// print error about valid input form [YYYY]
}
Depends entirely on the language but some approaches are:
check the string input using a len function; or
convert it to an integer and ensure it's less than 10,000; or
a regular expression like ^\d{1,4}.
No doubt there'll be other validation checks such as ensuring string input is all-numeric, and you're not trying to input a song that was written twenty years in the future, but they're added checks you should consider.
1) Accept the user's input and using the substring method, save only the first four characters (Specify to user that first 4 characters are considered).
2) You can ask the user to reenter the value if it is not 4 characters:
Scanner sc = new Scanner(System.in);
String a = sc.next();
if (a.matches("...."))
{
System.out.print(a);
}
else
{
System.out.print("Input again:" );
a = sc.next();
}
I've written a sample regex for 4 characters. But you can always change it.

Print formatting while taking user input

I have a college assignment where I need to print out items sold by a hardware store, take input from a user, perform some calculations on that input, and then print out an invoice.
I have been able to successfully print out the items sold by the hardware store, but am encountering problems with the while loop that takes the input.
The program asks the user to enter a CODE and then asks for the corresponding QUANTITY. This works fine on the first iteration of the loop, but on the second iteration the user prompts for "CODE:" and "QUANTITY:" appear on the same line, despite my use of println when prompting the user.
I would greatly appreciate a detailed response appropriate for someone new in programming.
Here's the code:
import java.util.Scanner;
class HardwareStore {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("WELCOME TO THE HARDWARE STORE!");
System.out.println("----------------------------------------------------------------------");
String sticky = "G22";
String keyring = "K13";
String screwy = "S21";
String padlock = "I30";
int stickyprice = 10989;
int keyringprice = 5655;
int screwyprice = 1099;
int padlockprice = 4005;
System.out.println("CODE\t\tDESCRIPTION\t\t\t\t\tPRICE");
System.out.println("----\t\t-----------\t\t\t\t\t-----");
System.out.println(sticky + "\t\tSTICKY Construction Glue, Heavy Duty, \n\t\t7oz, 12 Pack \t\t\t\t\t$" + stickyprice);
System.out.println(keyring + "\t\tCAR-LO Key Ring, Quick Release, \n\t\t1 Pack\t\t\t\t\t\t$ " + keyringprice);
System.out.println(screwy + "\t\t!GREAT DEAL! SCREW-DUP Screwy Screws, \n\t\tDry Wall Screws, 3 in. Long, 50 Pack\t\t$ " + screwyprice);
System.out.println(padlock + "\t\tLET-IT-RAIN, Weather Proof Padlock, \n\t\tPortable, One Push Functionality\t\t$ " + padlockprice);
System.out.println("----------------------------------------------------------------------");
int i = 10000;
String [] usercode = new String[i];
int [] userquantity = new int[i];
System.out.println("PLEASE ENTER YOUR ORDER:");
while (true) {
System.out.println("CODE: (X to terminate)");
usercode[i] = in.nextLine();
if (usercode[i].equalsIgnoreCase("x")) {
break;
}
System.out.println("QUANTITY: ");
userquantity[i] = in.nextInt();
}
}
}
when you enter the QUANTITY you're pressing enter. That newline character isn't used by in.nextInt();, it remains in the scanner buffer, until you roll around to in.nextLine() again.
At that point in.nextLine() reads until it finds a newline character, which just happens to be the next one in the buffer. So it skips straight to QUANTITY again.

Categories

Resources