Java Loop question about !scanner.nextLine() as condition - java

I'm learning to code Java with mooc at the moment and am doing an assignment where you take user input (and do stuff with it). The program/loop ends if user inputs nothing and enters.
So this is the right answer which I did correctly:
while (true) {
String sentence = scanner.nextLine();
if (sentence.equals("")) {
break;
}
}
However before this I also tried something like:
while (!scanner.nextLine().equals("")) { // ...
Why does that method not work? I don't see anything wrong with it.
(Below is the whole code if needed)
import java.util.Scanner;
public class AVClub {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (!scanner.nextLine().equals("")) {
String sentence = scanner.nextLine();
String[] array = splitter(sentence);
for (int i = 0; i < array.length; i++) {
if (array[i].contains("av")) {
System.out.println(array[i]);
}
}
}
}
public static String[] splitter(String sentence) {
String[] array = sentence.split(" ");
return array;
}
}

Try using scanner.hasNext() to see if there is anything else that you can read in. Instead of your splitter method, you can use StringTokenizer which will tokenize the String by spaces.
The reason your code does not work is because you are calling Scanner.nextLine() twice. Even though your code:
while (!scanner.nextLine().equals(""))
is a condition check, it reads it in and moves on. Think about it like this: The Scanner is like a book reader. When you call Scanner.nextLine(), the book reader moves to that line and reads it. When you called it again, it read an empty line. For example, if I input this:
Your reader will read in the "I like pie" and check to see that it is not a "". When it is done, and you get your sentence variable, you called the method again, which reads in the NEXT line, which is not there. So your code fails to work.

Related

I have specified the size of the array using user input but my for loop is taking input only size-1 time

I have specified the size of the array using user input but my for loop is taking input only size-1 time.
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int time=sc.nextInt();
String input[]=new String[time];
for(int i=0;i<time;i++)
{
input[i]=sc.nextLine();
}
for(int i=0;i<time;i++)
{
int len=input[i].length();
if(len>4)
{
System.out.println(input[i].charAt(0)+ Integer.toString(len-2)+input[i].charAt(len-1));
}
else
System.out.println(input[i]);
}
}
}
i changed my code and it is working fine
changed
int time=sc.nextInt();
with
int time=Integer.parseInt(sc.nextLine());
but i don't know the reason behind this . Please can anyone explain me
The Scanner.nextInt() method scans the next token of the input as an int, not the line. For example, if you give an int input and then hit enter, then it takes only the int, not the carriage return.
If you give a sample input like this:
2 xyz //hit enter and give the next input
abc
You'll see the nextInt() will take the 2 as input from that line and the upcoming first iteration for Scanner.nextLine() will consider the xyz as first input and in the next iteration, as we gave abc, it will be considered as the second. All these time you're code was working, but you couldn't see as it was taking the empty string as the first input due to the carriage return from the previous line.
However, The Scanner.nextLine() takes the whole line as input, along with the carriage return and then parses the int to the integer, so, you get the next lines for the string input for your array.
Hope that makes everything clear.
The problem is with the nextLine() method used in the first for loop. Because the method advances the scanner to the next line and returns the input that was skipped, it kind of "eats" one of your loop iterations and it ends up allowing you to input time - 1 elements into the array instead of time amount of elements. If you just use sc.next() instead, the program works perfectly fine, so you don't need to use
int time=Integer.parseInt(sc.nextLine());
as it may be a bit more complicated (in my opinion) than just replacing nextLine() with next(). Here is the code:
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int time = sc.nextInt();
String input[] = new String[time];
for(int i = 0;i < time;i++)
{
input[i] = sc.next();
}
for(int i = 0;i < time;i++)
{
int len = input[i].length();
if(len > 4)
{
System.out.println(input[i].charAt(0) + Integer.toString(len - 2) + input[i].charAt(len - 1));
}
else
System.out.println(input[i]);
}
sc.close();
}
}

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.

Code after while loop never executes

Obviously, my real code is more complex, but here's an example:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in).useDelimiter("\n");
String[] cmdSplit = null;
while (true) {
while (input.hasNext()) {
cmdSplit = input.next().split("\\s+");
System.out.println("stuff");
}
for (int i = 0; i < cmdSplit.length; i++) System.out.println(cmdSplit[i]);
}
}
}
In the above example, the code takes input from System.in, splits it, and should output each piece. However, for some reason, the code after the inner while loop never executes. If I replace while with if, it works. If you test it, you can see it doesn't run infinitely, because it only prints "stuff" once, showing the loop runs once. What is the issue with the while loop?
Reading from System.in is different than reading from a file or other fixed-size source of input. The input doesn't necessarily exist until you create it, and so attempts to read it need to block until the input actually arrives (i.e. you type it). Try typing another line - you'll see the stuff message again; that will allow .hasNext() to return because there is now input.
To have .hasNext() return false the input source needs to be closed. For a command line application you can do this by sending the EOF signal (Ctrl+D on Linux) which tells the process stdin has no more input. That's not generally how you want a program to work, though, so if your intent is to only read one line and then move on, you should in fact be using an if instead of a while as you've tried to do. Later if you need to read more input you'll call .hasNext() again and your program will block there until the user passes more input.
As #user7 mentions your outer while (true) combined with while(input.hasNext()) is redundant. If you want to read only once get rid of the while (true) and use if (input.hasNext()). Otherwise if you want to read forever just combine the two loops:
while (input.hasNext()) {
cmdSplit = input.next().split("\\s+");
System.out.println("stuff");
for (int i = 0; i < cmdSplit.length; i++) System.out.println(cmdSplit[i]);
} // Loop will terminate once stdin is closed, e.g. by the user sending EOF.
Yes , your code won't go to the for loop because the Scanner.hasNext() will always listen to the console for inputs.
You have to break the loop in order to come out and go to the for loop.
Scanner input = new Scanner(System.in).useDelimiter("\n");
String[] cmdSplit = null;
while (true) {
while (input.hasNext()) {
cmdSplit = input.next().split("\\s+");
System.out.println("stuff");
break;
}
for (String element : cmdSplit) {
System.out.println(element);
}
}
The reason it is printing "stuff" only one time is because the hasNext() returned false.
Let me explain what I have observed.
To get "stuff" printed indefinately the assignment has to be removed. meaning once you assigned the input the scanner does not have any more token
The java.util.Scanner.hasNext() method Returns true if this scanner has another token in its input.
This will print indefinitely
while (input.hasNext()) {
// cmdSplit = input.next().split("\\s+");
System.out.println("stuff");
}

How to take integer and remove other data types from the file java?

I do not know how to take the integer and ignore the strings from the file using scanner. This is what I have so far. I need to know how to read the file token by token. Yes, this is a homework problem. Thank you so much.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ClientMergeAndSort{
public static void main(String[] args){
int length = 13;
try{
Scanner input = new Scanner(System.in);
System.out.print("Enter the file name with extention : ");
File file = new File(input.nextLine());
input = new Scanner(file);
while (!input.hasNextInt()) {
input.next();
}
int[] arraylist = new int[length];
for(int i =0; i < length; i++){
length++;
arraylist[i] = input.nextInt();
System.out.print(arraylist[i] + " ");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Take a look at the API for what you're doing.
http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#hasNextInt()
Specifically, Scanner.hasNextInt().
"Returns true if the next token in this scanner's input can be interpreted as an int value in the default radix using the nextInt() method. The scanner does not advance past any input."
So, your code:
while (!input.hasNextInt()) {
input.next();
}
That's going to look and see if input hasNextInt().
So if the next token - one character - is an int, it's false, and skips that loop.
If the next token isn't an int, it goes into the loop... and iterates to the next character.
That's going to either:
- find the first number in the input, and stop.
- go to the end of the input, not find any numbers, and probably hits an IllegalStateException when you try to keep going.
Write down in words what you want to do here.
Use the API docs to figure out how the hell to tell the computer that. :) Get one bit at a time right; this has several different parts, and the first one doesn't work yet.
Example: just get it to read a file, and display each line first. That lets you do debugging; it lets you build one thing at a time, and once you know that thing works, you build one more part on it.
Read the file first. Then display it as you read it, so you know it works.
Then worry about if it has numbers or not.
A easy way to do this is read all the data from file in a way that you prefer (line by line for example) and if you need to take tokens, you can use split function (String.split see Java doc) or StringTokenizer for each line of String that you are reading using a loop, in order to create tokens with a specific delimiter (a space for example) so now you have the tokens and you can do something that you need with them, hope you can resolve, if you have question you can ask.
Have a nice programming.
import static java.nio.file.Files.readAllBytes;
import static java.nio.file.Paths.get;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String args[]) throws IOException {
String newStr=new String(readAllBytes(get("data.txt")));
Pattern p = Pattern.compile("-?\\d+");
Matcher m = p.matcher(newStr);
while (m.find()) {
System.out.println("- "+m.group());
}
}
}
This code fill read the file and then using the regular expression you can get only Integer values.
Note: This code works in Java 8
I Think This will work for you requirement.
Before reading the data from the file initially,try to write some content to the file by using scanner and filewriter then try to execute the below code snippet.
File file = new File(your filepath);
List<Integer> list = new ArrayList<Integer>();
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String str =null;
while(true) {
str = bufferedReader.readLine();
if(str!=null) {
System.out.println(str);
char[] chars = str.toCharArray();
String finalInt = "";
for(int i=0;i<chars.length;i++) {
if(Character.isDigit(chars[i])) {
finalInt=finalInt+chars[i];
}
}
list.add(Integer.parseInt(finalInt));
System.out.println(list.size());
System.out.println(list);
} else {
break;
}
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
The final println statement will display all the integer in your file line by line.
Thanks

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");
}

Categories

Resources