Why does my while loop needs this line of code to run? - java

I just completed an application which prompts the user for a text File input IO but I have something to clarify as the final part, While loop I actually managed to refer it to a tutorial on google. In this loop, there is a if-else statement and for the else part I don't understand why is it necessary.
Here's my code:
import java.io.*;
import java.util.*;
class FileReadingExercise2 {
public static void main(String[] args) {
Scanner userInput = new Scanner(System.in);
Scanner fileInput = null;
do {
try {
System.out.println("Please enter the name of a file or type QUIT to finish");
String a = userInput.nextLine();
if (a.equals("QUIT")) { // if user inputs QUIT then stop application
System.exit(0);
}
fileInput = new Scanner(new File(a)); // the file contains text and integers
} catch (FileNotFoundException e) {
System.out.println("Error - File not found");
}
} while (fileInput == null);
int sum = 0;
while (fileInput.hasNext()) // continues loop as long as there is a next token
{
if (fileInput.hasNextInt()) // if there is an int on the next token
{
sum += fileInput.nextInt(); // then adds the int to the sum
} else {
fileInput.next(); // else go to the next token
}
}
System.out.println(sum);
fileInput.close();
}
}
As you can see, as long as the fileInput Scanner has a next token to look up to then operate the if else statement. If fileInput has a next Int then adds it up to the sum variable. So from what I think is that this will be sufficient. Once fileInput has no more token to read, it shall get out of the while loop isn't it? Why does it has still go onto the next token? I'm confused. Please advise thanks! ;)

Why does it has still go onto the next token?
That is because when nextInt() is executed it will consume the int number within the file but within it, it has a newLine character that needs to be consume and that is when next is executed to consume that newLine after the int number.
sample file content:
1
what actually in there is 1 character and newline \n character

In this loop, there is a if-else statement and for the else part I don't understand
why is it necessary.
fileInput.hasNexInt() method returns true if int value found and than it performs adding operation. if next value is not int type than else part will perform where fileInput.next() will return next value(pointer will points after that value), performs nothing means escaping next value(which can be any type except int-type). Again if condition will check for int.

Related

Why does one println statement change the entire output of my code?

Problem
I am currently creating a program to read a file and find a couple of variables. I am running into this problem where changing one println changes the entire output of my code. I have never run into this before and am not sure if this is an eclipse error or my error?
My Code
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class FileAnalyzer {
public static void main(String args[]) throws IOException {
Scanner input = new Scanner(System.in);
String fileName;
int words = 0, letters = 0, blanks = 0, digits = 0, miscChars = 0, lines = 0;
System.out.print("Please enter the file path of a .txt file: ");
fileName = input.nextLine();
File text = new File(fileName);
//System.out.println(text.exists());
Scanner word = new Scanner(text);
while(word.hasNext()) {
//System.out.println(word.next());
words++;
}
word.close();
Scanner letter = new Scanner(text);
while(letter.hasNext()) {
String currentWord = letter.next().toLowerCase();
for(int i = 0; i < currentWord.length(); i++) {
if(Character.isLetter(currentWord.charAt(i))) {
letters++;
}
}
}
letter.close();
Scanner blank = new Scanner(text);
while(blank.hasNextLine()) {
String currentWord = blank.nextLine();
for(int j = 0; j < currentWord.length(); j++) {
if (currentWord.charAt(j) == ' ') {
blanks++;
}
}
}
blank.close();
System.out.println("Words: " + words);
System.out.println("Letters: " + letters);
System.out.println("Blanks: " + blanks);
}
}
However
Simply changingSystem.out.println(word.next()) in the first Scanner instance changes the entire output. If i leave it in I get the three print statements at the bottom and what I am looking for. If I remove it since I do not want each word printed in the file it shows as nothing in the console. Not Sure why one print statement within a while statement changes the entire output.The only reason it was there in the first place was to make sure the scanner was taking input the way I had wanted.
Not Sure why one print statement within a while statement changes the entire output
Because when the statement is present, you're consuming a token from the scanner. When it's commented out, you're not. It's not the printing that consumes the token, it's the call to next().
With it commented out, your loop is:
while (word.hasNext()) {
words++;
}
hasNext() doesn't modify the state of the scanner, so that will just loop forever if it goes into the loop body at all.
If you want to have a line you can comment out or not, change the code to:
while (word.hasNext()) {
String next = word.next(); // Consume the word
System.out.println(next); // Comment this out if you want to
words++;
}
By using System.out.println(word.next()); you are cycling through the elements in a collection due to the next() method. So invoking next() directly will allow you to move through the iteration.
When commenting out //System.out.println(word.next());, then word.hasNext() will cause you to loop forever(provided there is a word) as you will not be able to move to the next token.
The below snippet will help you achieve your desired result
while(word.hasNext()){
word.next();
words++;
}
Not sure why you would want to go thru the text three times. But if you really have to, I would close the first scanner before opening the next.

Why won't this print any integers?

try {
Scanner sc = new Scanner(new File("testing.txt"));
while (sc.hasNextInt()){
int i = sc.nextInt();
//timing.add(i);
System.out.println(i);
}
sc.close();
}catch (FileNotFoundException e) {
e.printStackTrace();
}
The text file does have int and strings in it. I can get it to print words from the text file, but not the numbers.
The text file includes the following:
Michael 3000 7000 Bilbo I like the number 2000 do you? No,
I like 9000
Your first value ("Michael") isn't an integer, therefore it never gets inside of the body of the loop.
Perhaps you want to change the code to loop until it reaches the end of the file, reading and printing integers, but consuming (without printing) non-integer values. So something like this:
import java.util.*;
import java.io.*;
public class Test {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(new File("test.txt"));
while (sc.hasNext()) {
if (sc.hasNextInt()) {
System.out.println(sc.nextInt());
} else {
// Just consume the next token
sc.next();
}
}
sc.close();
}
}
You never enter your while loop. Because the first input Michael is not a number.
A solution would be to take .next() and use a try-catch to parse an int out of it:
while (sc.hasNext() {
String input = sc.next();
try {
int printInt = Integer.parseInt(input);
System.out.println(printInt);
} catch () {}
The problem is that hasNextInt will return false for your initial string token ("Michael"), hence your loop will never execute any statement within.
You can parse every line and infer whether the tokens are convertible to integer types instead:
while (sc.hasNext()) {
try {
System.out.println(Integer.parseInt(sc.next()));
} catch (NumberFormatException nfe) {
// nope
}
}
Will print...
3000
7000
2000
9000
The issue is that you have a mix of words and numbers. When you call sc.hasNextInt(), it checks against "Michael", which isn't an integer, so it returns false and never executes. In this case, you can read the entire line, and split it on spaces. Then check if each word is an integer using regex. You can also check by using a try...catch block and attempting to parse an integer inside of that block.
Scanner sc = new Scanner(new File("StackTxtFiles/text.txt"));
while(sc.hasNextLine()){
String [] lineSplitArray = sc.nextLine().split(" ");
for(String wordInLine : lineSplitArray){
if(wordInLine.matches("-?\\d+(\\.\\d+)?")){
System.out.println(Integer.valueOf(wordInLine));
}
}
}
sc.close();
The problem is you are checking for an int first. There is not an int first so it will exit your while loop without doing anything:
while (sc.hasNextInt()){
Michael 3000
Michael is not an int it is a String so there is no hasNextInt() there is a hasNext() and hasNextLine()...
What you can do is:
while (sc.hasNext()){
try
{
System.out.println(Integer.parseInt(sc.next());
}catch(Exception e){}
}

Java Scanner no line found, and then Scanner closed error?

I have Java code that asks for user input and then stores this data in a string variable. The below function is part of a class called 'number' and is called in the main function.
public static void setVal(int i){
Scanner readIn = new Scanner(System.in);
//while (readIn.hasNextLine()){
str = readIn.nextLine();
numCheck = false;
if (i == 1){
while (!numCheck){
if (str.contains(" ")){
System.out.println("Please input a single item.");
str = readIn.nextLine();
}
else if (!isNumeric(str)){
System.out.println("Please input a valid number.");
str = readIn.nextLine();
}
else {
numCheck = true;
value = Double.parseDouble(str);
readIn.close();
}
}
readIn.close();
}
else if (i == 2){
while (!numCheck){
if (str.contains(" ")){
System.out.println("Please input a single item.");
str = readIn.nextLine();
}
else if (!isNumeric(str)){
System.out.println("Please input a valid number.");
str = readIn.nextLine();
}
else {
numCheck = true;
secondV = Double.parseDouble(str);
readIn.close();
}
}
readIn.close();
}
else {
System.out.println("An error has occurred.");
}
// }
readIn.close();
}
Part of the main function looks like this:
number input = new number();
for (int i = 1; i <= 2; i++){
input.setVal(i);
System.out.println("Now please input a second value for computing with the first.");
input.setVal(i);
}
I use the same function twice but handing it a different argument to distinguish assignment of the input to a different variable but when it runs a second time it throws a no line found error.
Applying some other advice you can see commented out I have added a 'hasNextLine()' check to check if the line exists before executing the code but this ends up at a 'Scanner closed' error even though I invoke a new instance of Scanner every time the function runs. I have also closed the scanner appropriately to ensure minimisation of errors.
I have no idea what's going wrong as I can create a Scanner in the main function and call '.nextLine()' as many times as requried without an error but when called again through a class method, I receive these errors.
Any help is appreciated, thanks in advance.
Scanner.close() documentation states that
If this scanner has not yet been closed then if its underlying
readable also implements the Closeable interface then the readable's
close method will be invoked. If this scanner is already closed then
invoking this method will have no effect.
On closing scanner, you are also closing System.in input stream, so when you reopen the scanner it will not find any open input stream.
Refer : java.util.NoSuchElementException - Scanner reading user input
Better pass scanner object from outside method as argument and then close it in calling method only when you are done with it.
Just to point out, is your String object str Static?
If not then you can't use it in your static method. Better you remove the static from method declaration.
You have to close the scanner when everything is done.
You have closed the scanner inout stream readIn.close(); twice.
You are closing the stream before picking line by line from the file. So you have to close it once after all the instances that use readIn is finished.

Program goes in an infinite loop

This program goes in an infinite loop in while cycle. Please, can someone tell me why?
import java.util.Scanner;
public class program {
public static void main(String[] pars) {
System.out.println("Insert something.");
Scanner read = new Scanner(System.in);
String s = "";
while(read.hasNext()) {
System.out.println(read.next());
}
System.out.println("End of program");
}
}
Read the Javadoc of Scanner#hasNext():
Returns true if this scanner has another token in its input. This method may block while waiting for input to scan. The scanner does not advance past any input.
Hence the while loop will always be executed in your case, each time waiting for input from the user. Since the Scanner is linked to System.in, the input stream will always block until the user inputs a string and hasNext() will always return true, unless the user signals the end of file (e.g. through the Ctrl+z combination on Windows). Scanner#hasNext() is more convenient when reading from files where the input size is known and the end of the file marks the end of the stream.
One way to end the loop here is to add a condition on the input:
while (read.hasNext()) {
s = read.next();
if(s.equals("quit")) {
break;
}
System.out.println(s);
}
P.S.: It is more conventional to name classes starting with an uppercase letter.
The problem is this line:
while(read.hasNext()) {
If you use System.in as a stream provided by the user, it will - if no such input is available - as #manouti says, block and wait for input. But even if you provide input, it will keep waiting. The system has no means to detect whether the user wants to provide additional input in the future.
It will only stop, if the Stream ends. This can be under two conditions:
The end of the file (in case of I/O redirection like java -jar program.jar < input.dat; or
The user marks the end of a stream, in most shells with Ctrl+D. This marks the end-of-stream.
An alternative is to provide some kind of stop directive. Something like "END". Thus:
while(read.hasNext()) {
String nx = read.next();
if(nx.equals("END")) {
break;
}
System.out.println(nx);
}
Just remove while loop
public static void main(String[] pars) {
System.out.println("Insert something.");
Scanner read = new Scanner(System.in);
String s = "";
System.out.println(read.next());
System.out.println("End of program");
}
Or if u want display certain no.of string then mention condition properly.
public static void main(String[] pars) {
System.out.println("Insert something.");
Scanner read = new Scanner(System.in);
String s = "";
int i=0;
while(i<5) {
System.out.println(read.next());
i++;
}
System.out.println("End of program");
}

Assigning a String to a String array

I am trying to assign each string a user inputs to a String array. The entire thing is in a for loop and is evaluated by the index of the array. My code is:
String skillAssign[] = new String[100];
for (int i=0; isDone == false; i++)
{
System.out.println(skillAssign[i]);
System.out.println(i);
skillAssign[i] = keyboard.nextLine();
if ((!(skillAssign[i].equalsIgnoreCase("stats"))) && (!(skillAssign[i].equalsIgnoreCase("done"))))
{
assignmentValue = keyboard.nextInt();
if (((skillAssign[i].equalsIgnoreCase("health"))) && (skillPoints - assignmentValue >=0))
{
System.out.println("Added " + assignmentValue + " points to Health!");
skillPoints = (skillPoints - assignmentValue);
newMaxHealth = (assignmentValue + newMaxHealth);
}
//code that evaluates the string located inside the skillAssign[i] for other stats
}
The first string evaluates properly, but when I go to input the second string, I get java.util.InputMisMatchException. How can I get it so it assigns a string to each index of the array inputted by the user, then evaluate it? (I think I got the evaluation part though)
I tried to limit the post to relevant code, so things like isDone are omitted, but isDone is changed to true when done is typed and keyboard is constructed with Scanner keyboard = new Scanner all other variables are set to 0 except for skillPoints
I have tested the abovementioned code, and this is what happens:
We enter the loop.
You are requested to input the first string (through keyboard.nextLine()). I inputted 'health'.
You are requested to input an integer (through keyboard.nextInt()). I inputted '40'.
We re-enter the loop.
You are requested to input an integer (through keyboard.nextInt()).
...
It seems that I'm not asked to input the second string, but instantly the integer.
I do not know why it is, but it looks like nextInt() causes the next nextLine() to be skipped.
Maybe you can replace
assignmentValue = keyboard.nextInt();
with
try {
assignmentValue = Integer.parseInt(keyboard.nextLine());
}
catch (NumberFormatException exc) {
throw new InputMismatchException(exc.getMessage());
}
EDIT
I saw a post on StackOverflow which briefly mentions why nextLine() after nextInt() is skipped.
i believe this is closer to your intention. this way the reference to your keyboard input that nextLine grabs isn't lost on each iteration, but remains preserved in a new String instance. correct?
System.out.println(i);
String getMe = keyboard.nextLine();
skillAssign[i] = new String(getMe);
System.out.println(skillAssign[i]);

Categories

Resources