I am reading a string from stdin that's formatted as a list. I am using the information from the string to create objects.
An example input string would be formatted as follows:
1 apple, 3 bananas, 2 pears
I want to read that line a create objects as I go, but my biggest issue is properly reading the line to get the number of items, followed by them item itself while also skipping whitespace and commas.
I have tried the following:
Scanner input = new Scanner(System.in);
input.useDelimeter(",|\\s");
while(input.hasNext()){
int numItems = input.nextInt();
String item = input.next();
// create object and add to object array
}
Which works for the first iteration (1 apple) but fails on the second with a type mismatch. Can anyone suggest a fix or alternate solution?
Thanks!
,|\\s declares two separate delimiters. Those delimiters can be matched in text "apple, 3" twice:
comma after apple
space before 3
apple, 3
^^
12
so we split that text at two separate (middle) places, which means we split it into 3 tokens:
"apple",
"",
"3".
When in next iteration (after calling input.next() which consumes apple) you are calling input.nextInt() Scanner tries to parse second token as int, but since it finds empty string it is throwing exception.
One of solutions would be treating [space] or ,[space] as single delimiter. You can achieve it by making comma optional:
input.useDelimiter(",?\\s");
Demo:
Scanner input = new Scanner("1 apple, 3 bananas, 2 pears");
input.useDelimiter(",?\\s");
while(input.hasNext()){
int numItems = input.nextInt();
System.out.println(numItems);
String item = input.next();
System.out.println(item);
System.out.println("----");
}
Output:
1
apple
----
3
bananas
----
2
pears
----
You can spilt the input String using delimiter "," and get following output after using trim() method.
1 apple
3 bananas
2 pears
Here is the code:
String [] array1 = input.nextLine().split(",");
for(int i=0; i<array1.length; i++){
System.out.println(array1[i].trim());
}
Edit: You can further split the Strings inside for loop using delimiter space, to get the desired output.
Related
I want to be able to distinguish the user's input using spaces, where each string they input in one line is used for something different.
Specifically, each word they input is used in a method where I add an item to a list. The user will type 'add' followed by the item's type and age.
I have just messed around trying to figure something out but I am just lost.
if (input.equals("add")) {
scan.next(); ??
}
After the user types 'add', they then input a type and age for a vehicle that they want to add to a list. For example, 'car 7' may be typed so a new item in a list can be made, and 'car' will be its type and '7' will be its age.
To note: age is an int.
If the user enters:
car 7
all you need to do to read that line is:
String words[] = scan.nextLine().split(" ");
Now you have an array that contains the words of that line. For eg: words[0] would contain car, words[1] would contain 7, etc.
You can also read them one at a time as well as change the delimiter. Here are several examples.
String text = "The quick brown fox jumped over the lazy dog";
Scanner scan = new Scanner(text);
while (scan.hasNext()) {
System.out.print(scan.next() + " ");
}
System.out.println();
And this one changes the delimiter between words. You can specify a regular expression pattern or a simple String.
text = "The:quick,+-brown::::fox:.:jumped++over,,,,the,+,+lazy---dog";
scan = new Scanner(text);
// regular expression delimiter. Any combo of one or more of the chars.
scan.useDelimiter("[:,.;+-]+");
while (scan.hasNext()) {
System.out.print(scan.next() + " ");
}
System.out.println();
So, I have a text file that looks exactly like this:
<sgkljsd>::=<sdfasfda> <sadfasf>
<lol>::=<dgs> <pdja> <l>|<np>
<or>::hello|howdy
<sdfas>::=<saf>|<sdf> <adlp>
<needd>::=huge|massive|big|tall
So, in this text file, line 1 and 2 are not needed so I just skip over them. However, I need the words in line 3 and in line 5. My current code splits line three at the "|" so I either get "howdy" or "::hello". So is there a way to remove elements in a line? In line 3 and in line 5, I only need the words split at the "|". I want to get rid of the items in "< >".
My current code is below:
Scanner scan = new Scanner(System.in);
System.out.print("Enter a file name: ");
String fileName = scan.nextLine();
File infile = new File(fileName);
Scanner readIt = new Scanner(infile);
// removes first line of file
String junkLine1 = readIt.nextLine();
// removes second line of file
String junkLine2 = readIt.nextLine();
//gets random <word> from text file
String word = readIt.nextLine();
// breaks it into "<or>hello" and "howdy"
String[]word1 = word.split("\\|");
int rnd = r.nextInt(word1.length);
String rnd_word = (word1[rndDp]);
System.out.println(rnd_word);
So, what I wanted to do was randomly select the word in the array and randomly print out a greeting but I can't seem to figure out how to remove the unnecessary text. Thank you for any ideas on how to fix or approach this.
You can get rid of < > replacing them all with a regex:
"<needd>::=huge|massive|big|tall".replaceAll("<.+?>", "");
which returns:
::=huge|massive|big|tall
"<needd>::=huge|massive|big|tall".replaceAll("<.+?>::=", "");
which returns:
huge|massive|big|tall
or you can also split:
"<needd>::=huge|massive|big|tall".split("<.+?>|:+|\\||=");
which will return an array of String containing:
{huge, massive, big, tall}
You can try on the combinations above here: http://www.regexpal.com/
I tried doing something like what these people have done:
How to split a comma-separated string?
But when I do the following:
String UserInput = new Scanner(System.in).next();
GradesNonInt = Arrays.asList(UserInput.replaceAll("\\s","").split(","));
System.out.println(GradesNonInt.size());
When I input a string like "1,2,3" I get 3 printed. When I type "1, 2, 3" I get 1 printed. For some reason, it does not want to work when the string has spaces in it.
As one of the answers below said, entering "1, 2, 3" directly seems to work fine, but yet when taken from the Scanner(System.in).next(), it is not.
I tried following code and it printed 3 when I used "1, 2, 3" in UserInput string
String UserInput = "1, 2, 3";
List<String> GradesNonInt = Arrays.asList(UserInput.replaceAll("\\s","").split(","));
System.out.println(GradesNonInt.size());
The issue is not with split but this is happening cause Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace and that's why this behaviour is shown. Refer this link.
If you want you can change the delimiter to something else than space by using useDelimiter method of Scanner class
UPDATE
To change the delimiter to next line and to ensure the code accept spaces in the strings, you can change your code to following
String UserInput = new Scanner(System.in).useDelimiter("\n").next();
List<String> GradesNonInt = Arrays.asList(UserInput.replaceAll("\\s","").split(","));
System.out.println(GradesNonInt.size());
Problem is that Scanner#next() can return only next token (until it finds next delimiter, or end of data). So for input like 1, 2, 3, it will return 1,.
Use Scanner#nextLine() to read entire line.
Also don't create new instance of Scanner each time you want to read data from user. Create one Scanner handling System.in per application and reuse it.
I am trying to use a string splitter to display user input e.g. 1,2 coordinates to display on a console. I don't get any errors when I run my code. However, my attempt to use the splitter does not seem to work.
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a row and column number at which to shoot (e.g., 2,3): ");
String[] coordinates = scanner.nextLine().split(",");
if (coordinates.length != 2) {
System.out.println("Please enter coordinates in the correct format.");
System.out.println("\nPlayer 1 Please take your turn:");
continue;
}
System.out.println("\nEnter Mine location:");
System.out.println("\nPlease Enter x position for your Mine:");
System.in.read(byt);
str = new String(byt);
row = Integer.parseInt(str.trim());
System.out.println("\nPlease Enter y position for your Mine:");
System.in.read(byt);
str = new String(byt);
col = Integer.parseInt(str.trim());
Your use of System.in.read(...) is dangerous code and is not doing what you think it's doing:
System.in.read(byt); // *****
str = new String(byt);
row = Integer.parseInt(str.trim());
Instead use a Scanner, something that you already have, and either call getNextInt() on the Scanner, or get the line and parse it.
Also, you never use the Strings held in the coordinates array -- why get the Strings if you are ignoring them?
You ask about:
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a row and column number at which to shoot (e.g., 2,3): ");
str = scanner.nextInt().split(",");
but then see that the compiler won't allow this since you're trying to call a method on the int primitive that scanner.nextInt() returns.
My recommendation to use Scanner#nextInt() was as a replacement for you misuse of System.in.read(...). If instead you want the user to enter two numbers on one line, separated by a comma, then you're best bet is to use String.split(","), although, I think it might be better to use String.split("\\s*,\\s*") to get rid of any white space such as spaces hanging about. This way the split should work for 1,1 as well as 1, 2 and 1 , 2, and then you can parse the items held in the array via Integer.parseInt(...).
What is the main difference between next() and nextLine()?
My main goal is to read the all text using a Scanner which may be "connected" to any source (file for example).
Which one should I choose and why?
I always prefer to read input using nextLine() and then parse the string.
Using next() will only return what comes before the delimiter (defaults to whitespace). nextLine() automatically moves the scanner down after returning the current line.
A useful tool for parsing data from nextLine() would be str.split("\\s+").
String data = scanner.nextLine();
String[] pieces = data.split("\\s+");
// Parse the pieces
For more information regarding the Scanner class or String class refer to the following links.
Scanner: http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
String: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html
next() can read the input only till the space. It can't read two words separated by a space. Also, next() places the cursor in the same line after reading the input.
nextLine() reads input including space between the words (that is, it reads till the end of line \n). Once the input is read, nextLine() positions the cursor in the next line.
For reading the entire line you can use nextLine().
From JavaDoc:
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
next(): Finds and returns the next complete token from this scanner.
nextLine(): Advances this scanner past the current line and returns the input that was skipped.
So in case of "small example<eol>text" next() should return "small" and nextLine() should return "small example"
The key point is to find where the method will stop and where the cursor will be after calling the methods.
All methods will read information which does not include whitespace between the cursor position and the next default delimiters(whitespace, tab, \n--created by pressing Enter). The cursor stops before the delimiters except for nextLine(), which reads information (including whitespace created by delimiters) between the cursor position and \n, and the cursor stops behind \n.
For example, consider the following illustration:
|23_24_25_26_27\n
| -> the current cursor position
_ -> whitespace
stream -> Bold (the information got by the calling method)
See what happens when you call these methods:
nextInt()
read 23|_24_25_26_27\n
nextDouble()
read 23_24|_25_26_27\n
next()
read 23_24_25|_26_27\n
nextLine()
read 23_24_25_26_27\n|
After this, the method should be called depending on your requirement.
What I have noticed apart from next() scans only upto space where as nextLine() scans the entire line is that next waits till it gets a complete token where as nextLine() does not wait for complete token, when ever '\n' is obtained(i.e when you press enter key) the scanner cursor moves to the next line and returns the previous line skipped. It does not check for the whether you have given complete input or not, even it will take an empty string where as next() does not take empty string
public class ScannerTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int cases = sc.nextInt();
String []str = new String[cases];
for(int i=0;i<cases;i++){
str[i]=sc.next();
}
}
}
Try this program by changing the next() and nextLine() in for loop, go on pressing '\n' that is enter key without any input, you can find that using nextLine() method it terminates after pressing given number of cases where as next() doesnot terminate untill you provide and input to it for the given number of cases.
next() and nextLine() methods are associated with Scanner and is used for getting String inputs. Their differences are...
next() can read the input only till the space. It can't read two words separated by space. Also, next() places the cursor in the same line after reading the input.
nextLine() reads input including space between the words (that is, it reads till the end of line \n). Once the input is read, nextLine() positions the cursor in the next line.
import java.util.Scanner;
public class temp
{
public static void main(String arg[])
{
Scanner sc=new Scanner(System.in);
System.out.println("enter string for c");
String c=sc.next();
System.out.println("c is "+c);
System.out.println("enter string for d");
String d=sc.next();
System.out.println("d is "+d);
}
}
Output:
enter string for c
abc def
c is abc
enter string for d
d is def
If you use nextLine() instead of next() then
Output:
enter string for c
ABC DEF
c is ABC DEF
enter string for d
GHI
d is GHI
In short: if you are inputting a string array of length t, then Scanner#nextLine() expects t lines, each entry in the string array is differentiated from the other by enter key.And Scanner#next() will keep taking inputs till you press enter but stores string(word) inside the array, which is separated by whitespace.
Lets have a look at following snippet of code
Scanner in = new Scanner(System.in);
int t = in.nextInt();
String[] s = new String[t];
for (int i = 0; i < t; i++) {
s[i] = in.next();
}
when I run above snippet of code in my IDE (lets say for string length 2),it does not matter whether I enter my string as
Input as :- abcd abcd or
Input as :-
abcd
abcd
Output will be like
abcd
abcd
But if in same code we replace next() method by nextLine()
Scanner in = new Scanner(System.in);
int t = in.nextInt();
String[] s = new String[t];
for (int i = 0; i < t; i++) {
s[i] = in.nextLine();
}
Then if you enter input on prompt as -
abcd abcd
Output is :-
abcd abcd
and if you enter the input on prompt as
abcd (and if you press enter to enter next abcd in another line, the input prompt will just exit and you will get the output)
Output is:-
abcd
From javadocs
next() Returns the next token if it matches the pattern constructed from the specified string.
nextLine() Advances this scanner past the current line and returns the input that was skipped.
Which one you choose depends which suits your needs best. If it were me reading a whole file I would go for nextLine until I had all the file.
From the documentation for Scanner:
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
From the documentation for next():
A complete token is preceded and followed by input that matches the delimiter pattern.
Just for another example of Scanner.next() and nextLine() is that like below :
nextLine() does not let user type while next() makes Scanner wait and read the input.
Scanner sc = new Scanner(System.in);
do {
System.out.println("The values on dice are :");
for(int i = 0; i < n; i++) {
System.out.println(ran.nextInt(6) + 1);
}
System.out.println("Continue : yes or no");
} while(sc.next().equals("yes"));
// while(sc.nextLine().equals("yes"));
Both functions are used to move to the next Scanner token.
The difference lies in how the scanner token is generated
next() generates scanner tokens using delimiter as White Space
nextLine() generates scanner tokens using delimiter as '\n' (i.e Enter
key presses)
A scanner breaks its input into tokens using a delimiter pattern, which is by default known the Whitespaces.
Next() uses to read a single word and when it gets a white space,it stops reading and the cursor back to its original position.
NextLine() while this one reads a whole word even when it meets a whitespace.the cursor stops when it finished reading and cursor backs to the end of the line.
so u don't need to use a delimeter when you want to read a full word as a sentence.you just need to use NextLine().
public static void main(String[] args) {
// TODO code application logic here
String str;
Scanner input = new Scanner( System.in );
str=input.nextLine();
System.out.println(str);
}
I also got a problem concerning a delimiter.
the question was all about inputs of
enter your name.
enter your age.
enter your email.
enter your address.
The problem
I finished successfully with name, age, and email.
When I came up with the address of two words having a whitespace (Harnet street) I just got the first one "harnet".
The solution
I used the delimiter for my scanner and went out successful.
Example
public static void main (String args[]){
//Initialize the Scanner this way so that it delimits input using a new line character.
Scanner s = new Scanner(System.in).useDelimiter("\n");
System.out.println("Enter Your Name: ");
String name = s.next();
System.out.println("Enter Your Age: ");
int age = s.nextInt();
System.out.println("Enter Your E-mail: ");
String email = s.next();
System.out.println("Enter Your Address: ");
String address = s.next();
System.out.println("Name: "+name);
System.out.println("Age: "+age);
System.out.println("E-mail: "+email);
System.out.println("Address: "+address);
}
The basic difference is next() is used for gettting the input till the delimiter is encountered(By default it is whitespace,but you can also change it) and return the token which you have entered.The cursor then remains on the Same line.Whereas in nextLine() it scans the input till we hit enter button and return the whole thing and places the cursor in the next line.
**
Scanner sc=new Scanner(System.in);
String s[]=new String[2];
for(int i=0;i<2;i++){
s[i]=sc.next();
}
for(int j=0;j<2;j++)
{
System.out.println("The string at position "+j+ " is "+s[j]);
}
**
Try running this code by giving Input as "Hello World".The scanner reads the input till 'o' and then a delimiter occurs.so s[0] will be "Hello" and cursor will be pointing to the next position after delimiter(that is 'W' in our case),and when s[1] is read it scans the "World" and return it to s[1] as the next complete token(by definition of Scanner).If we use nextLine() instead,it will read the "Hello World" fully and also more till we hit the enter button and store it in s[0].
We may give another string also by using nextLine(). I recommend you to try using this example and more and ask for any clarification.
The difference can be very clear with the code below and its output.
public static void main(String[] args) {
List<String> arrayList = new ArrayList<>();
List<String> arrayList2 = new ArrayList<>();
Scanner input = new Scanner(System.in);
String product = input.next();
while(!product.equalsIgnoreCase("q")) {
arrayList.add(product);
product = input.next();
}
System.out.println("You wrote the following products \n");
for (String naam : arrayList) {
System.out.println(naam);
}
product = input.nextLine();
System.out.println("Enter a product");
while (!product.equalsIgnoreCase("q")) {
arrayList2.add(product);
System.out.println("Enter a product");
product = input.nextLine();
}
System.out.println();
System.out.println();
System.out.println();
System.out.println();
System.out.println("You wrote the following products \n");
for (String naam : arrayList2) {
System.out.println(naam);
}
}
Output:
Enter a product
aaa aaa
Enter a product
Enter a product
bb
Enter a product
ccc cccc ccccc
Enter a product
Enter a product
Enter a product
q
You wrote the following products
aaa
aaa
bb
ccc
cccc
ccccc
Enter a product
Enter a product
aaaa aaaa aaaa
Enter a product
bb
Enter a product
q
You wrote the following products
aaaa aaaa aaaa
bb
Quite clear that the default delimiter space is adding the products separated by space to the list when next is used, so each time space separated strings are entered on a line, they are different strings.
With nextLine, space has no significance and the whole line is one string.