I am coding a rainfall averaging program. The program lets the user input a file name and if the file cannot be found, then the user is prompted to reenter the file name. The user gets 4 tries before the application quits without processing the data, and the application itself is a rainfall averaging program like I said.
package experiment8;
import java.io.*;
import java.util.Scanner;
public class Exceptions
{
static Scanner inFile;
public static void main(String[] args) throws IOException
{
int fileTry = 0;
String fileName;
Scanner inName = new Scanner(System.in);
System.out.println("Enter file name>");
fileName = inName.nextLine();
boolean fileOk;
do
{
fileOk = false;
try
{
Scanner scan = new Scanner (System.in);
Scanner file = new Scanner(new File("inData.dat"));
fileOk = true;
}
catch(FileNotFoundException error)
{
System.out.println("Reenter file name>");
fileName = inName.nextLine();
fileTry++;
}
} while (!fileOk && fileTry < 4);
PrintWriter outFile = new PrintWriter(new FileWriter("outData.dat"));
if (fileOk && fileTry < 4 )
{
int numDays = 0;
double average;
double inches = 0.0;
double total = 0.0;
while (inFile.hasNextFloat())
{
inches = inFile.nextFloat();
total = total + inches;
outFile.println(inches);
numDays++;
}
if (numDays == 0)
System.out.println("Average cannot be computed " +
" for 0 days.");
else
{
average = total / numDays;
outFile.println("The average rainfall over " +
numDays + " days is " + average);
}
inFile.close();
}
else
System.out.println("Error");
outFile.close();
}
}
I am trying to code this program so when I input the correct file name, "inData.dat", I will get the proper output. However, when I do this, I continue to get prompted to reenter the file name for the next 3 times, after which I get the "Error" message. Is there something wrong with my try/catch blocks or if statements?
There are lot of issues with your program. Here are a few to get you on the way.
The file inData.dat does not exist. Please create it in the appropriate place.
After you get over that hump, there would be a Null Pointer on Line 40: inFile is null.
My recommendation is to open it in an editor such as Visual Studio Code. It would point you to a lot of warnings and you could debug your program as well.
I have two questions about your code.
What is the purpose of the line Scanner scan = new Scanner (System.in); in the try-block?
Why do you have an if statement check if (fileOk && fileTry < 4) after the do-while block for getting the file? It seems redundant. The do-while block checks for the same condition. Once the program gets to the location of this if-statement this condition must have been met. If it wasn't, the do-while would have run again.
It is possible for you to get to a case where the do-while ends because the file was found, and the condition of this if-statement is false because fileTry < 4. I don't understand why you would care about the fileTry counter once you found the correct file. If the user tried to enter the file name 4 times and got it correct on the last try, the program will go to the else part of this if-statement and print "Error".
Related
I was tasked with reading a data.txt file using the scanner import. The data.txt file looks like this:
1 2 3 4 5 6 7 8 9 Q
I need to read and find the average of these numbers, but stop when I get to something that is not an integer.
This is the code that I have so far.
public static double fileAverage(String filename) throws FileNotFoundException {
Scanner input = new Scanner(System.in);
String i = input.nextLine();
while (i.hasNext);
return fileAverage(i); // dummy return value. You must return the average here.
} // end of method fileAverage
As you can see I did not get very far and I cannot figure this out. Thank you for your help.
First, your Scanner should be over the file filename (not System.in). Second, you should be using Scanner.hasNextInt() and Scanner.nextInt() (not Scanner.hasNext() and Scanner.nextLine()). Finally, you should add each int you read to a running total and keep track of the count of numbers read. And, I would use a try-with-resources statement to ensure the Scanner is closed. Something like,
public static double fileAverage(String filename) throws FileNotFoundException {
try (Scanner input = new Scanner(new File(filename))) {
int total = 0, count = 0;
while (input.hasNextInt()) {
total += input.nextInt();
count++;
}
if (count < 1) {
return 0;
}
return total / (double) count;
}
}
I made a simple program which generates a random number between 1 to 100 and asks the user to enter a number between 1 and 100. If the number is more than the random number a message is displayed saying that it is more than the random number and if it is less it displays the opposite. The user only has 10 chances to guess the correct number. Here is the code:
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int random_num = (int) (Math.random() * 100) + 1;
System.out.println("guess a number between 1 and 100");
boolean isCorrect = false;
for (int i = 1; i <= 10; i++) {
int input = sc.nextInt();
if (input > random_num)
System.out.println("It is less than " + input);
else if (input < random_num)
System.out.println("It is more than " + input);
else {
isCorrect = true;
break;
}
}
if (isCorrect)
System.out.println("Congragulation you have guessd the correct number i.e " + random_num);
else
System.out.println("Game over it was " + random_num);
}
}
But I get errors here is the output:
guess a number between 1 and 100
It is more than 10
Exception in thread "main" java.util.NoSuchElementException
at java.base/ java.util.Scanner.throwFor(Scanner.java: 937)
at java.base/ java.util.Scanner.next(Scanner.java: 1594)
at java.base/ java.util.Scanner.nextInt(Scanner.java: 2258)
at java.base/ java.util.Scanner.nextInt(Scanner.java: 2212)
at Program.main(Program.java:15)
You are looping over the Scanner, but not checking if you have any input to fetch.
Here is an excerpt from the Java docs:
public int nextInt()
Scans the next token of the input as an int.
An invocation of this method of the form nextInt() behaves in exactly the same way as the invocation nextInt(radix), where radix is the default radix of this scanner.
Returns:
the int scanned from the input
Throws:
InputMismatchException - if the next token does not match the Integer regular expression,
or is out of range
NoSuchElementException - if input is exhausted
IllegalStateException - if this scanner is closed
Spot your error message ;)
Your code is valid for a standard Java environment.
However since you run the code in the SoloLearn Java container, you run into an error case that normally shouldn't happen.
Which is another thread already closed the input stream.
As Ivar already mentioned, you simply need to change your code to this to make it work on SoloLearn without errors:
for (int i = 1; i <= 10 && sc.hasNextInt(); i++) {
// Your logic
}
But since SoloLearn's implementation needs you to feed all of your input at once (different inputs seperated by a line break), you won't be able to run this correctly with different guesses.
SoloLearn will take those inputs, seperated by line breaks, and reads the different lines one at a time.
Then returns the inputs one at a time to your program.
Once it has no more input, it will close the stream.
However your program still tries to read this stream and then gets a java.util.NoSuchElementException error.
Here is reproducable code of the error with wath I believe happens behind the scenes at SoloLearn:
import java.io.ByteArrayInputStream;
import java.util.Scanner;
public class Program {
private String[] userInput;
private int inputNumber;
public Program(String input) {
this.userInput = input.split(" ");
this.inputNumber = 0;
}
public void startGame() {
int random_num = (int)(Math.random()*100)+1;
System.out.println("Guess the number between 1 and 100!");
boolean isCorrect = false;
for (int i = 1; i <= 10; i++) {
System.out.print("Guess "+ i +": ");
int input = getInput();
if (input > random_num)
System.out.println("It is less than " + input);
else if (input < random_num)
System.out.println("It is more than " + input);
else {
isCorrect = true;
break;
}
}
if(isCorrect)
System.out.println("Congratulations, you have guessed the correct number i.e " + random_num);
else
System.out.println("Game over! The number was " + random_num);
}
private int getInput() {
if (inputNumber < userInput.length)
fakeUserInput();
Scanner sc = new Scanner(System.in);
int input = -1;
input = sc.nextInt();
if (inputNumber == userInput.length)
sc.close();
return input;
}
private void fakeUserInput() {
System.setIn(new ByteArrayInputStream(userInput[inputNumber].getBytes()));
inputNumber++;
}
public static void main(String[] args) {
Program p = new Program("10 20 30");
p.startGame();
}
}
We feed it 3 guesses: 10, 20 and 30
And this is the output:
Guess the number between 1 and 100!
Guess 1: It is more than 10
Guess 2: It is more than 20
Guess 3: It is more than 30
Guess 4: Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:873)
at java.util.Scanner.next(Scanner.java:1496)
at java.util.Scanner.nextInt(Scanner.java:2128)
at java.util.Scanner.nextInt(Scanner.java:2087)
at Program.getInput(Program.java:47)
at Program.startGame(Program.java:24)
at Program.main(Program.java:62)
As you can see, once the inputs are depleted and the stream is closed, we get this error.
I hope this explains your problem and sheds some light on the WHY.
here is answer, I try to do it and I found in main sc.close(). After comment line all work nice! :
#I_code Is this the actual code you are using? It works fine for me. That error is thrown when the the System.in is closed. Are you using sc.close() somewhere that you didn't show in the code?
– #Ivar Mar 15 '19 at 10:10
Good morning you need to initialize the input variable outside the for like this:
int input;
for (int i = 1; i <= 10; i++) {
input = sc.nextInt();
if (input > random_num)
Try this and tell me
I'm trying to create a program that makes a file that randomly generates numbers and I want the program to read those numbers off of the file and analyze it. If the randomly generated number doesn't equal 0, the program should keep generating numbers, but if it does equal 0, then the program will stop. However, it seems that my program is not reading those numbers.
I tried putting the outFile.close(); and inFile.close(); in a couple different places to see if that would fix anything, but it seems that didn't work out. I tried tracing my code with pen and paper, but I couldn't find anything wrong. Perhaps it could be my placement of outFile.close(); and inFile.close();, but I couldn't find anything wrong with it.
import java.util.*;
import java.io.*;
public class squirrel {
public static void main(String[] args) throws IOException{
Scanner in = new Scanner(System.in);
PrintWriter outFile = new PrintWriter(new File("squirrel.txt"));
Scanner inFile = new Scanner(new File("squirrel.txt"));
Random rand = new Random();
int squirrelNum;
int foxSquirrel = 0;
int squirrelsSeen = 0;
int trials = 0;
System.out.println("Welcome to the Fox Squirrel Simulator\n");
System.out.println("How many trials should be simulated?");
System.out.println("Enter a value greater than 1000: ");
trials = in.nextInt();
while(trials <= 1000)
{
System.out.println("Please try again. Enter a value greater than 1000: ");
trials = in.nextInt();
}
for(int i = 0; i <= trials; i ++)
{
squirrelNum = rand.nextInt(10);
outFile.println(squirrelNum);
while(inFile.hasNextInt())
{
int token = inFile.nextInt();
while(token != 0)
{
squirrelsSeen ++;
}
if(token == 0)
{
foxSquirrel ++;
squirrelsSeen ++;
}
outFile.close();
}
System.out.println("squirrelsSeen: " + squirrelsSeen);
System.out.println("foxSquirrel: " + foxSquirrel);
}
inFile.close();
System.out.println("\nsimulating trials now... one moment please...\n");
System.out.println("The results!");
System.out.println("The average number of squirrels until spotting a Fox Squirrel at the city park is: " + (((double)foxSquirrel / squirrelsSeen) * 100));
}
}
And here is how it is done using Scanner.
File file = new File("squirrel.txt");
try {
Scanner sc = new Scanner(file);
while (sc.hasNextLine()) {
int i = sc.nextInt();
System.out.println(i);
}
sc.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
And it is like you said. You put the .close() inside your while loop in your code. Try putting it outside.
new PrintWriter(new File("squirrel.txt")) immediately erases the file. From the documentation:
If the file exists then it will be truncated to zero size; otherwise, a new file will be created.
It is not possible to read and write the same file simultaneously. (Actually there are some cases were it’s possible, but they don’t apply here.)
Do not create your PrintWriter until you have finished reading from the file and have called inFile.close(). Or, write to a different file, then when you’re done, rename it to match the original file.
I just wanted to say first that I'm a beginner so I apologize for my (really) horrible code.
I'm creating a program where you input an int and print out the square root using a do while loop. And when you input "0" the program will stop.
How do you stop it?
public static void main(String[] args)
{
Scanner InputNum = new Scanner(System.in);
DecimalFormat formatTenths = new DecimalFormat("0.0");
do {
System.out.println("Please enter an integer.");
int sqroot = InputNum.nextInt();
double Finalsqroot = Math.sqrt(sqroot);
System.out.println("Your Square Root is: " + (formatTenths.format(Finalsqroot)));
} while (sqroot==0);
System.out.println("Closing...");
InputNum.close();
}
}
You need to test if the value entered was 0 (I would test less than or equal to zero, because the square root of a negative number is imaginary). If so, break the loop. Like,
int sqroot = InputNum.nextInt();
if (sqroot <= 0) {
break;
}
try this
public static void main(String[] args) {
Scanner InputNum = new Scanner(System.in);
DecimalFormat formatTenths = new DecimalFormat("0.0");
int sqroot = 0;
do {
System.out.println("Please enter an integer.");
sqroot = InputNum.nextInt();
double Finalsqroot = Math.sqrt(sqroot);
System.out.println("Your Square Root is: " + (formatTenths.format(Finalsqroot)));
} while (sqroot != 0);
System.out.println("Closing...");
InputNum.close();
}
I just initialize sqroot outside of your while and change == to !=
This academic exercise may demand use of a do/while loop, but if you're not constrained to using it, a for loop would also work:
public static void main(String[] args)
{
Scanner InputNum = new Scanner(System.in);
DecimalFormat formatTenths = new DecimalFormat("0.0");
System.out.println("Please enter an integer.");
for(int sqroot = InputNum.nextInt(); sqroot > 0; sqroot = InputNum.nextInt()) {
double Finalsqroot = Math.sqrt(sqroot);
System.out.println("Your Square Root is: " + (formatTenths.format(Finalsqroot)));
}
System.out.println("Closing...");
InputNum.close();
}
Your program as presented in the question has an intrinsic flaw: you ask for input and then immediately try and do something with it (calc the square root) without determining if it is suitable to use.
Switching to a for loop is one way this can be overcome, because it encourages a program flow of "ask for input", "check if input is acceptable", "use input", "repeat"
If you're constrained to using a do/while loop then you still need to follow this flow, which Elliott Frish addresses in his answer, recommending you add in the "check if input is acceptable" part as a dual purpose test of whether the input is <= 0.. Such values are not acceptable for a square root op, and you also want to end the program when you encounter them, so the test can be used to achieve both goals
Side trivia, for loops can be used pretty much exclusively:
for(;;) //same as while(true)
for(;test;) //same as while(test)
for(bool do = true; do; do = test) //same as do..while(test)
..though using while or do is probably more readable than using a for loop for the same job
Note, your while(sqroot==0) is a bug.. you don't want to continue looping while the user entered 0, you want to continue looping while they DIDN'T enter a 0...
I am using Java eclipse and I would like to have the user input the filename to retrieve a list of scores from the file. My goal is to take the average of those numbers. What line of code do I need just to get the user to input a file name and for the program to take those numbers so that I can compute with them? Currently I can have the user input scores, But I need to get the numbers from the file instead. I have visited numerous resources on this site. Here are a few:
BufferedReader, Error finding file, Getting a list from a file
package Average;
/**An average of scores*/
import java.util.Scanner;
public class Average2 {
public static void main(String[] args) {
int grade = 0;
int students = 0;
float total = 0;
double average = 0;
Scanner input = new Scanner(System.in);
System.out.println("Enter number of students: ");
students = input.nextInt();
if (students <= 10) {
System.out.println("Enter the grades of the students: ");
for(int i = 0; i < students; i++) {
do {
grade = input.nextInt();
} while(grade < 0 || grade > 100);
total += grade;
}
average = (total/students);
int median = ((82+84)/2);
System.out.println("The average is " + average);
System.out.println("The mean is " + median);
}
}
}
Update since above post!
package trials;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class trials2 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// Create new Scanner object to read from the keyboard
Scanner in = new Scanner(System.in);
// Grab the name of the file
System.out.println("Enter filename: ");
String fileName = in.next();
// Access the file
Scanner fileToRead = new Scanner(new File(fileName));
// While there is still stuff in the file...
double sum = 0;
while (fileToRead.hasNext()) {
if (fileToRead.hasNextDouble()) {
sum += fileToRead.nextDouble();
} else {
fileToRead.next();
}
}
{
fileToRead.close();
}
System.out.println(sum);
}
}
The results I get from this:
Enter filename:
esp.txt <--entered by me
501.0
Given that you want to find the average of numbers in a file, you could do something like this:
// Create new Scanner object to read from the keyboard
Scanner in = new Scanner(System.in);
// Grab the name of the file
System.out.println("Enter filename: ");
String fileName = in.next();
// Access the file
Scanner fileToRead = new Scanner(new File(fileName));
// Initialize our relevant counters
double sum = 0.0;
int numStudents = 0;
// While there is still stuff in the file...
while (fileToRead.hasNext()) {
// Is this next line consisting of just a number?
if (fileToRead.hasNextDouble()) {
// If it is, accumulate
sum += fileToRead.nextDouble();
numStudents++;
}
else { // Else, just skip to the next line
fileToRead.next();
}
}
// Close the file when finished
fileToRead.close();
// Print the average:
System.out.println("The average mark is: " + (sum / numStudents));
This code will create a new Scanner object that will read input from your keyboard. Once it does that, you type in the file name, and it gets access to this file by opening another Scanner object. After that, we initialize some counters to help us calculate the average. These are sum, which will add up all of the marks we encounter and numStudents, which keeps track of how many students there are in the file.
The while loop will keep looping through each line of this file until it reaches the end. What is important is that you check to see whether or not the line you are reading in next consists of a single number (double). If it is, then add this to our sum. If it isn't, skip to the next line.
Once you're finished, close the file, then display the average by taking the sum and dividing by the total number of students we have encountered when reading the numbers in the file.
Just took a look at your profile and your profile message. You have a long road ahead of you. Good luck!
Look at the Java tutorial on Scanning: http://docs.oracle.com/javase/tutorial/essential/io/scanning.html, particularly the ScanSum example. It shows how to scan double values from a text file and add them. You should be able to modify this example for your project.
Scanner userInput = new Scanner(System.in);
System.out.println("ENter filename");
String fileName = userInput.next();
Scanner fileScan = new Scanner(new File(fileName));
then use scanner methods to process lines or string tokens you are interested in.