Java Scanner while loop - java

I'm trying to take in a string input which consists of multiple lines of numbers separated by ',' and ';' .
Example:
1,2;3,4;5,6;
9,8;7,6;
0,1;
;
Code:
ArrayList<Integer> alist = new ArrayList<>();
String delims = ";|\\,";
int i = 0;
Scanner input = new Scanner(System.in);
input.useDelimiter(delims);
while (input.hasNext()) {
alist.add(i, input.nextInt());
System.out.print(i + ' ');
System.out.print(alist.get(i) + '\n');
i++;
}
System.out.print('x');
When I run this in eclipse:
1,2;3,4;5,6; ( <= what i typed in console)
321133123413351436153716 ( <= output)
I'd expect something more like:
0 1
1 2
2 3
3 4
4 5
5 6
x
Why am I getting this sort of output?

One problem is that System.in is basically an infinite stream: hasNext will always return true unless the user enters a special command that closes it.
So you need to have the user enter something that tells you they are done. For example:
while(input.hasNext()) {
System.out.print("Enter an integer or 'end' to finish: ");
String next = input.next();
if("end".equalsIgnoreCase(next)) {
break;
}
int theInt = Integer.parseInt(next);
...
For your program, you might have the input you are trying to parse end with a special character like 1,2;3,4;5,6;end or 1,2;3,4;5,6;# that you check for.
And on these lines:
System.out.print(i + ' ');
System.out.print(alist.get(i) + '\n');
It looks like you are trying to perform String concatenation but since char is a numerical type, it performs addition instead. That is why you get the crazy output. So you need to use String instead of char:
System.out.print(i + " ");
System.out.print(alist.get(i) + "\n");
Or just:
System.out.println(i + " " + alist.get(i));
Edit for comment.
You could, for example, pull the input using nextLine from a Scanner with a default delimiter, then create a second Scanner to scan the line:
Scanner sysIn = new Scanner(System.in);
while(sysIn.hasNextLine()) {
String nextLine = sysIn.nextLine();
if(nextLine.isEmpty()) {
break;
}
Scanner lineIn = new Scanner(nextLine);
lineIn.useDelimiter(";|\\,");
while(lineIn.hasNextInt()) {
int nextInt = lineIn.nextInt();
...
}
}

Since Radiodef has already answered your actual problem(" instead of '), here are a few pointers I think could be helpful for you(This is more of a comment than an answer, but too long for an actual comment):
When you use Scanner, try to match the hasNextX function call to the nextX call. I.e. in your case, use hasNextInt and nextInt. This makes it much less likely that you will get an exception on unexpected input, while also making it easy to end input by just typing another delimiter.
Scanners useDelimiter call returns the Scanner, so it can be chained, as part of the initialisation of the Scanner. I.e. you can just write:
Scanner input = new Scanner(System.in).useDelimiter(";|\\,");
When you add to the end of an ArrayList, you don't need to(and usually should not) specify the index.
int i = 0, i++ is the textbook example of a for loop. Just because your test statement doesn't involve i does not mean you should not use a for loop.
Your code, with the above points addressed becomes as follows:
ArrayList<Integer> alist = new ArrayList<>();
Scanner input = new Scanner(System.in).useDelimiter(";|\\,");
for (int i = 0; input.hasNextInt(); i++) {
alist.add(input.nextInt());
System.out.println(i + " " + alist.get(i));
}
System.out.println('x');
Edit: Just had to mention one of my favorite delimiters for Scanner, since it is so suitable here:
Scanner input = new Scanner(System.in).useDelimiter("\\D");
This will make a Scanner over just numbers, splitting on anything that is not a number. Combined with hasNextInt it also ends input on the first blank line when reading from terminal input.

Related

Getting multiple inputs from user with char and integers Java

I'm trying to allow the user to put in multiple inputs from the user that contain a char and integers.
Something like this as input: A 26 16 34 9
and output each int added to an array.
I was thinking I could have the first input as a character and then read the rest as a string which then I separate and put into an array.
I'm not new to coding but new to java. I've been doing c++ so the syntax is a bit different.
This is what I have so far, I haven't set up my array yet for the integers.
import java.util.Scanner;
public class Program0 {
public static void main(String[] args) {
int firstNumber;
Scanner reader = new Scanner(System.in);
System.out.println("'A' to enter a number. 'Q' to quit");
int n = reader.nextInt();
if (n=='A') {
//if array is full System.out.println("The list is full!");
//else
System.out.println("Integer " + " " + "has been added to the list");
}
else if (n=='Q') {
System.out.println("List of integers: ");
System.out.println("Average of all integers in the list: ");
}
else{
System.out.println("Invalid Action");
}
reader.close();
}
}
Could you specify better how should your input be given? From your question, if I understand well, the user simply type "A" followed by a list of numbers separated by a space. So I would simply read the next line, split it in words (separated by a space) and check if the first word is the letter "A". Here it goes:
import java.util.Scanner;
public class Program0 {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("'A' to enter a number. 'Q' to quit");
String line = reader.nextLine();
String[] words = line.split(" ");
if (words.length > 0 && words[0].equals("A")) {
//if array is full System.out.println("The list is full!");
// => I don't understand this part
//else
for(int i = 1; i<words.length; i++){
int integer = Integer.parseInt(words[i]);
System.out.println("Integer " + integer + " has been added to the list");
//do your stuff here
}
}
else if (words.length > 0 && words[0].equals("Q")) {
System.out.println("List of integers: ");
System.out.println("Average of all integers in the list: ");
}
else{
System.out.println("Invalid Action");
}
reader.close();
}
}
Note that in your solution, you read the next int from your scanner and then try to compare it with the character 'A'. This will not work because A is not an int. If you really want to get the first character from your scanner, you could do:
String line = reader.nextLine();
if(line.length() > 0){
char firstChar = line.charAt(0);
//do your stuff here
}
A character is not an int. You cannot read an int to expect something like 'A'. You can read a String and take its first character though. Scanner doesn't offer a convenient method to read the next String and expect it to be only one-character long. You'd need to handle that yourself.
But considering you don't know in advance how many numbers there will be to read, your solution to read the entire line and interpret it entirely, is the better one. That means you can't use nextInt() nor nextDouble() nor next() nor nextWhateverElse().
You need nextLine(), and it will give you the entire line as a String.
Then you can split() the result, and check if the first is one-char-long. Then you can parse all the others as int.
I don't immediately recall how to write this in Java – it's been a bit of a while – but what I'd do is to first separate the string by spaces, then attempt to do ParseInt on each piece.
If the string isn't a valid integer, this method will throw an exception, which you can catch. So:
If you make it to the next statement, an exception didn't happen, so the value is an integer.
If, instead, you find yourself in the exception-handler (having caught [only ...] the expected kind of exception, the value is a string.
Of course, don't "catch" any exception-type other than the NumberFormatException that you're expecting.
By the way, it is perfectly routine to use exceptions in this way. Let Java's runtime engine be the authority as to whether it's an integer or not.

How to check if the next 3 input is an int by using Scanner.hasNextInt() and loop only in java

How can I check if the next three input user is giving is an int value,
like let's say there is three variables,
var1
var2
var3
And I am taking input as,
Scanner sc = new Scanner (System.in);
var1 = sc.nextInt();
var2 = sc.nextInt();
var3 = sc.nextInt();
Now if I want to use while(sc.hasNextInt()) to determine if the next input is an int or not then it will only check if the next input for var1 is int or not and won't check for the other to variables, var2, var3. One thing can be done by using while loop with if (condition). For example,
Scanner sc = new Scanner (System.in);
while (sc.hasNextInt()) {
var1 = sc.nextInt();
if (sc.hasNextInt()) {
var2 = sc.nextInt();
if (sc.hasNextInt()) {
var3 = sc.nextInt();
}
}
}
But this looks lengthy and needs a lot to write. For similar issue I have seen for Language C there is a method for scanf() which can do the trick. For example,
while(scanf("%d %d %d", &var1, &var2 & var3) == 3) {
// Statements here
}
So my question is there any such features available in java's Scanner.hasNextInt or Scanner.hasNext("regex").
I have also tried sc.hasNext("[0-9]* [0-9]* [0-9]*") but didn't worked actually.
Thank you in advance.
hasNext(regex) tests only single token. Problem is that default delimiter is one-or-more-whitespaces so number number number can't be single token (delimiter - space - can't be part of it). So sc.hasNext("[0-9]* [0-9]* [0-9]*") each time will end up testing only single number. BTW in your pattern * should probably be + since each number should have at least one digit.
To let spaces be part of token we need to remove them from delimiter pattern. In other words we need to replace delimiter pattern with one which represents only line separators like \R (more info). This way if user will write data in one line (will use enter only after third number) that line would be seen as single token and can be tested by regex.
Later you will need to set delimiter back to one-or-more-whitespaces (\s+) because nextInt also works based on single token, so without it we would end up with trying to parse string like "1 2 3".
Scanner sc = new Scanner(System.in);
sc.useDelimiter("\\R");
System.out.print("Write 3 numbers (sepate them with space): ");
while(!sc.hasNext("\\d+ \\d+ \\d+")){
String line = sc.nextLine();//IMPORTANT! Consume incorrect values
System.out.println("This are not 3 numbers: "+line);
System.out.print("Try again: ");
}
//here we are sure that there are 3 numbers
sc.useDelimiter("\\s+");//nextInt can't properly parse "num num num", we need to set whitespaces as delimiter
int var1 = sc.nextInt();
int var2 = sc.nextInt();
int var3 = sc.nextInt();
System.out.println("var1=" + var1);
System.out.println("var2=" + var2);
System.out.println("var3=" + var3);
Possible problem with this solution is fact that \d+ will let user provide number of any length, which may be out of int range. If you want to accept only int take a look at Regex for a valid 32-bit signed integer. You can also use nextLong instead, since long has larger range, but still it has max value. To accept any integer, regardless of its length you can use nextBigInteger().
I tried with nextLine method and usage of Pattern. Regex is matching with 3 numbers which is separeted with space. So it can be like this i think ;
Scanner scanner = new Scanner(System.in);
Pattern p = Pattern.compile("[0-9]+\\s[0-9]+\\s[0-9]+$");
while(!p.matcher(scanner.nextLine()).find()){
System.out.println("Please write a 3 numbers which is separete with space");
}
System.out.println("Yes i got 3 numbers!");
I hope this helps you.

Is there a function in Java that allows you to transform a string to an Int considering the string has chars you want to ignore?

I'm doing a project for a Uni course where I need to read an input of an int followed by a '+' in the form of (for example) "2+".
However when using nextInt() it throws an InputMismatchException
What are the workarounds for this as I only want to store the int, but the "user", inputs an int followed by the char '+'?
I've already tried a lot of stuff including parseInt and valueOf but none seemed to work.
Should I just do it manually and analyze char by char?
Thanks in advance for your help.
Edit: just to clear it up. All the user will input is and Int followed by a + after. The theme of the project is to do something in the theme of a Netflix program. This parameter will be used as the age rating for a movie. However, I don't want to store the entire string in the movie as it would make things harder to check if a user is eligible or not to watch a certain movie.
UPDATE: Managed to make the substring into parseInt to work
String x = in.nextLine();
x = x.substring(0, x.length()-1);
int i = Integer.parseInt(x);
Thanks for your help :)
Try out Scanner#useDelimiter():
try(Scanner sc=new Scanner(System.in)){
sc.useDelimiter("\\D"); /* use non-digit as separator */
while(sc.hasNextInt()){
System.out.println(sc.nextInt());
}
}
Input: 2+33-599
Output:
2
33
599
OR with your current code x = x.substring(0, x.length()-1); to make it more precise try instead: x = x.replaceAll("\\D","");
Yes you should manually do it. The methods that are there will throw a parse exception. Also do you want to remove all non digit characters or just plus signs? For example if someone inputs "2 plus 5 equals 7" do you want to get 257 or throw an error? You should define strict rules.
You can do something like: Integer.parseInt(stringValue.replaceAll("[^\d]","")); to remove all characters that are no digits.
Hard way is the only way!
from my Git repo line 290.
Also useful Javadoc RegEx
It takes in an input String and extracts all numbers from it then you tokenize the string with .replaceAll() and read the tokens.
int inputLimit = 1;
Scanner scan = new Scanner(System.in);
try{
userInput = scan.nextLine();
tokens = userInput.replaceAll("[^0-9]", "");
//get integers from String input
if(!tokens.equals("")){
for(int i = 0; i < tokens.length() && i < inputLimit; ++i){
String token = "" + tokens.charAt(i);
int index = Integer.parseInt(token);
if(0 == index){
return;
}
cardIndexes.add(index);
}
}else{
System.out.println("Please enter integers 0 to 9.");
System.out.print(">");
}
Possible solutions already have been given, Here is one more.
Scanner sc = new Scanner(System.in);
String numberWithPlusSign = sc.next();
String onlyNumber = numberWithPlusSign.substring(0, numberWithPlusSign.indexOf('+'));
int number = Integer.parseInt(onlyNumber);

Java Scanner not behaving correctly?

I have the following Code Snippet in my project:
public void addText(String s){
Scanner scan;
int newInt = Integer.parseInt(s.substring(s.indexOf('\t') + 1 + 1));
//find insertion point
String temp = "";
scan = new Scanner(text);
int prev = 0;
while(scan.hasNextInt() && newInt > scan.nextInt()){
temp += text.substring(prev, text.indexOf('\n')) + "\r\n";
prev = text.indexOf('\n') + 1;
}
text = temp + s + "\r\n" + text.substring(prev);
}
The goal of this is to insert a string into an existing string and keep it in a somewhat "numerical order".
The String s is a formatted string that looks like "CityName\t\tSomeNumber". That code for newInt works (confirmed by debugging). What doesn't work is the while loop. Even when text has data in it, the scan.hasNextInt() fails.
For example, assume text = "Charlestown\t\t9",s = "Downville\t\t15". newInt gets assigned 15. The while loop should iterate once and end, since 15 > 9 (were organizing cities in ascending order of these numbers). But for some reason the Scanner returns false every time on the scan.hasNextInt()part of the condition statement.
Any suggestions?
The Javadoc for hasNextInt says
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.
Which means that if your next token is "Charlestown", this will return false. You're going to have to read the name of the town from your scanner before you check hasNextInt().

Keep doing stuff until empty line entered

I cant get this to work for some reason. I have an app that reads transactions, when an empty line in entered it needs to print out some stuff.
int transationCount = 0;
while(sc.hasNext())
{
String trans = sc.next();
String mode = trans.substring(0, 1);
Double amount = Double.valueOf(trans.substring(1));
if(mode.equals("C"))
{
c.charge(amount);
ps.println(c.getBalance());
transationCount = transationCount + 1;
}
else if(mode.equals("P"))
{
c.pay(amount);
ps.println(c.getBalance());
transationCount = transationCount + 1;
}
}
ps.println(c.getBalance());
ps.println(transationCount);
I tried
while(sc.hasNext() && !(sc.next().equals("")))
doesnt work. I also tried adding inside the while loop
else if (!(trans.equals("")) {break;}
By default, an empty line will be ignored by the scanner as it is not a valid token.
You could manually check if the line is empty:
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
while(true) {
String line = sc.nextLine();
if (line.isEmpty()) {
System.out.println("Empty line entered");
} else {
System.out.println("received line: " + line);
String[] tokens = line.split("\\s+");
System.out.println("tokens: " + Arrays.toString(tokens));
}
}
}
Your Scanner is using the default delimiter (a whitespace) to tokenize the input.
This means that tokens are words, regardless of the lines they are in.
some
word
only returns two tokens, exactly as
some word
What you really need is to get lines separately, in order to tell which line is empty, and which line contain something. In order to do that, use new line as a separator:
Scanner.useDelimiter("\\n");
Or you might as well use BufferedReader, see BufferedReader.readLine()
Please note that two words on the same line will now be contained in the same trans string. You can use the String.split method to get each word separately.
So then how would I escape the while loop if an empty line is entered? Is there another way? – Infodayne
you can use label over/above your while loop, and break it when emptyLine is encountered
or alternatively you can use
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
while(! line.isEmpty()){
}
line.isEmpty() returns true when line is empty,So condition to enter while loop will become false as now inside while loop we have(! (true)) which equals to (false) therefore while loop will not execute.

Categories