I am trying to make the user input a string, which can both contain spaces or not. So in that, I'm using NextLine();
However, i'm trying to search a text file with that string, therefore i'm using next() to store each string it goes through with the scanner, I tried using NextLine() but it would take the whole line, I just need the words before a comma.
so far here's my code
System.out.print("Cool, now give me your Airport Name: ");
String AirportName = kb.nextLine();
AirportName = AirportName + ",";
while (myFile.hasNextLine()) {
ATA = myFile.next();
city = myFile.next();
country = myFile.next();
myFile.nextLine();
// System.out.println(city);
if (city.equalsIgnoreCase(AirportName)) {
result++;
System.out.println("The IATA code for "+AirportName.substring(0, AirportName.length()-1) + " is: " +ATA.substring(0, ATA.length()-1));
break;
}
}
The code works when the user inputs a word with no spaces, but when they input two words, the condition isn't met.
the text file just includes a number of Airports, their IATA, city, and country. Here's a sample:
ADL, Adelaide, Australia
IXE, Mangalore, India
BOM, Mumbai, India
PPP, Proserpine Queensland, Australia
By default, next() searches for first whitespace as a delimiter. You can change this behaviour like this:
Scanner s = new Scanner(input);
s.useDelimiter("\\s*,\\s*");
By this, s.next() will match commas as delimiters for your input (preceeded or followed by zero or more whitespaces)
Check out the String#split method.
Here's an example:
String test = "ADL, Adelaide, Australia\n"
+ "IXE, Mangalore, India\n"
+ "BOM, Mumbai, India\n"
+ "PPP, Proserpine Queensland, Australia\n";
Scanner scan = new Scanner(test);
String strings[] = null;
while(scan.hasNextLine()) {
// ",\\s" matches one comma followed by one white space ", "
strings = scan.nextLine().split(",\\s");
for(String tmp: strings) {
System.out.println(tmp);
}
}
Output:
ADL
Adelaide
Australia
IXE
Mangalore
India
BOM
Mumbai
India
PPP
Proserpine Queensland
Australia
Related
I read a txt with data in the following format: Name Address Hobbies
Example(Bob Smith ABC Street Swimming)
and Assigned it into String z
Then I used z.split to separate each field using " " as the delimiter(space) but it separated Bob Smith into two different strings while it should be as one field, same with the address. Is there a method I can use to get it in the particular format I want?
P.S Apologies if I explained it vaguely, English isn't my first language.
String z;
try {
BufferedReader br = new BufferedReader(new FileReader("desc.txt"));
z = br.readLine();
} catch(IOException io) {
io.printStackTrace();
}
String[] temp = z.split(" ");
If the format of name and address parts is fixed to consist of two parts, you could just join them:
String z = ""; // z must be initialized
// use try-with-resources to ensure the reader is closed properly
try (BufferedReader br = new BufferedReader(new FileReader("desc.txt"))) {
z = br.readLine();
} catch(IOException io) {
io.printStackTrace();
}
String[] temp = z.split(" ");
String name = String.join(" ", temp[0], temp[1]);
String address = String.join(" ", temp[2], temp[3]);
String hobby = temp[4];
Another option could be to create a format string as a regular expression and use it to parse the input line using named groups (?<group_name>capturing text):
// use named groups to define parts of the line
Pattern format = Pattern.compile("(?<name>\\w+\\s\\w+)\\s(?<address>\\w+\\s\\w+)\\s(?<hobby>\\w+)");
Matcher match = format.matcher(z);
if (match.matches()) {
String name = match.group("name");
String address = match.group("address");
String hobby = match.group("hobby");
System.out.printf("Input line matched: name=%s address=%s hobby=%s%n", name, address, hobby);
} else {
System.out.println("Input line not matching: " + z);
}
I can think of three solutions.
In order from best to worst:
Different delimiter
Enforce the format to always have two names, two address parts and one hobby
Have a dictionary with names and hobbies, check each word to determine which type it is and then group them together as needed.
(The 3rd option is not meant as a serious alternative.)
As others have mentioned, using spaces as both field delimiter and inside fields is problematic. You could use a regex pattern to split the line (paste (\w+ \w+) (\w+ \w+) (.+) in Regex101 for an explanation):
Pattern pattern = Pattern.compile("(\\w+ \\w+) (\\w+ \\w+) (.+)");
Matcher matcher = pattern.matcher("Bob Smith ABC Street Bowling Fishing Rollerblading");
System.out.println("matcher.matches() = " + matcher.matches());
for (int i = 0; i <= matcher.groupCount(); i++) {
System.out.println("matcher.group(" + i + ") = " + matcher.group(i));
}
This would give the following output:
matcher.matches() = true
matcher.group(0) = Bob Smith ABC Street Bowling Fishing Rollerblading
matcher.group(1) = Bob Smith
matcher.group(2) = ABC Street
matcher.group(3) = Bowling Fishing Rollerblading
However this only works for this exact format. If you get a line with three name parts for example:
John B Smith ABC Street Swimming
This will get split into John B as the name, Smith ABC as the address and Street Swimming as hobbies.
So either make 100% sure your input will always match this format or use a different delimiter.
The split() method majorly works on the 2 things:
Delimiter and
The String Object
Sometimes on limit too.
Whatever limit you will provide, the split() method will do its work according to that.
It doesn't understand whether the left substring is a name or not, same as for the right substring.
Have a look at this code snippet:
String assets = "Gold:Stocks:Fixed Income:Commodity:Interest Rates";
String[] splits = assets.split(":");
System.out.println("splits.size: " + splits.length);
for(String asset: splits){
System.out.println(assets);
}
OutPut
splits.size: 5
Gold
Stocks
Fixed Income // with space
Commodity
Interest Rates // with space
The output came with spaces because I provided the ; as a delimiter.
This probably helped you to get your answer.
Find Detailed Information on Split():
Top 5 Use cases of Split()
Java Docs : Split()
It depends on the data you're dealing with. Will the name always consist of a first and last name? Then you can simply combine the first two elements from the resulting array into a new string.
Otherwise, you might have to find a different way to separate out the different pieces within the txt file. Possibly a comma? Some character that you know won't ever be used in your normal data.
Assuming that every line follows the format
Bob Smith ABC Street Swimming
ie, name surname.... this code can manually manipulate the data for you:
String[] temp = z.split(" ");
String[] temp2 = new String[temp.length - 1];
temp2[0] = temp[0] + " " + temp[1];
for (int i = 2; i < temp.length; i++) {
temp2[i] = temp2[i];
}
temp = temp2;
I am working through a piece of self study, Essentially I am to ask the User for a string input such as "John, Doe" IF the string doesnt have a comma, I am to display an error, and prompt the user until the string does indeed have a comma (Fixed.). Once this is achieved I need to parse the string from the comma, and any combination of comma that can occur (i.e. John, doe or John , doe or John ,doe) then using the Scanner class I need to grab John doe, and split them up to be separately printed later.
So far I know how to use the scanner class to grab certain amounts of string up to a whitespace, however what I want is to grab the "," but I haven't found a way to do this yet, I figured using the .next(pattern) of the scanner class would be what I need, as the way it was written should do exactly that. however im getting an exception InputMismatchException doing so.
Here is the code im working with:
while (!userInput.contains(",")) {
System.out.print("Enter a string seperated by a comma: ");
userInput = scnr.nextLine();
if (!userInput.contains(",")) {
System.out.println("Error, no comma present");
}
else {
String string1;
String string2;
Scanner inSS = new Scanner(userInput);
String commaHold;
commaHold = inSS. //FIXME this is where the problem is
string1 = inSS.next();
string2 = inSS.next();
System.out.println(string1 + " " + string2);
}
}
This can be achieved simply by splitting and checking that the result is an array of two Strings
String input = scnr.nextLine();
String [] names = input.split (",");
while (names.length != 2) {
System.out.println ("Enter with one comma");
input = scnr.nextLine();
names = input.split (",");
}
// now you can use names[0] and names[1]
edit
As you can see the code for inputting the data is duplicated and so could be refactored
This question already has answers here:
Remove all occurrences of char from string
(13 answers)
Closed 5 years ago.
I was wondering how to ignore spaces in Java. This program allows you to enter your first, middle and surname which then outputs your initials. I'm now trying to make it ignore any white spaces. Thanks in advance!
String fullName;
char firstName;
char secondName;
char surname;
int space1;
int space2;
System.out.println("Please enter your first name, your second name and your surname: ");
fullName = kybd.nextLine();
firstName = fullName.charAt(0);
space1 = fullName.indexOf(" ");
secondName = fullName.charAt(space1 + 1);
space2 = fullName.lastIndexOf(" ");
surname = fullName.charAt(space2 + 1);
System.out.println("Initials: " + firstName + secondName + surname);
Explanation
You can implicitly ignore them by just removing them from your input text.
Therefore replace all occurrences with "" (empty text):
fullName = fullName.replaceAll(" ", "");
After that call fullName won't contain a whitespace anymore.
However you'll then get a problem with your logic as you split on whitespaces.
Solution
An alternative could be to first trim the text (removing leading and trailing whitespaces). Then do your split and after that you can remove all other whitespaces:
fullName = kybd.nextLine();
// Remove leading and trailing whitespaces
fullName = fullName.trim();
// Bounds
firstSpace = fullName.indexOf(" ");
lastSpace = fullName.lastIndexOf(" ");
// Extract names
String fullFirstName = fullName.substring(0, firstSpace);
String fullSecondName = fullName.substring(firstSpace + 1, lastSpace);
String fullSurname = fullName.substring(lastSpace + 1);
// Trim everything
fullFirstName = fullFirstName.trim(); // Not needed
fullSecondName = fullSecondName.trim();
fullSurname = fullSurname.trim();
// Get initials
firstName = fullFirstName.charAt(0);
secondName = fullSecondName.charAt(0);
surname = fullSurname.charAt(0);
Example
Let's take a look at an example input (_ stands for whitespace):
__John___Richard_Doe_____
We will first trim fullName and thus get:
John___Richard_Doe
Now we identify the first and the last whitespace and split on them:
First name: John
Second name: ___Richard
Surname: _Doe
Last we also trim everything and get:
First name: John
Second name: Richard
Surname: Doe
With charAt(0) we access the initials:
First name: J
Second name: R
Surname: D
More dynamic
Another more dynamic approach would be to merge all successive whitespaces into a single whitespace. Therefore you would need to traverse the text from left to right and start recording once you see a whitespace, end recording if visiting a non-whitespace character, then replace that section by a single whitespace.
Our example then is:
_John_Richard_Doe_
And after an additional trim you can use your regular approach again:
John_Richard_Doe
Or you can use split(" ") and then reject every empty String:
Iterator<String> elements = Pattern.compile(" ").splitAsStream(fullName)
.filter(e -> !e.isEmpty()) // Reject empty elements
.collect(Collectors.toList()) // Collect to list
.iterator() // Iterator
firstName = elements.next().charAt(0);
secondName = elements.next().charAt(0);
surname = elements.next().charAt(0);
Using the example again the Stream first consists of
"", "", "John", "", "", "Richard", "Doe", "", "", "", "", ""
after the filtering it's
"John", "Richard", "Doe"
Minus Sign
As you said you also want
Richard Jack Smith-Adams
output RJS-A, you can simply split on - after splitting on the whitespace.
Pattern spacePatt = Pattern.compile(" ");
Pattern minusPatt = Pattern.compile("-");
String result = spacePatt.splitAsStream(fullName) // Split on " "
.filter(e -> !e.isEmpty()) // Reject empty elements
.map(minusPatt::splitAsStream) // Split on "-"
.map(stream ->
stream.map(e -> e.substring(0, 1))) // Get initials
.map(stream ->
stream.collect(Collectors.joining("-"))) // Add "-"
.collect(Collectors.joining("")); // Concatenate
Which outputs RJS-A.
This approach is a bit more complicated as we need to maintain the information of the sub-streams, we can't just flatMap everything together, otherwise we wouldn't know where to add the - again. So in the middle part we are indeed operating on Stream<Stream<String>> objects.
I think what you're after here is the split method in String
Which you could use like this:
String fullName = "John Alexander Macdonald";
String[] split = fullName.split(" "); // ["John", "Alexander", "Macdonald"]
The other thing you might want is the trim method which removes spaces from the front and the back of a string.
String withSpaces = " a b c ";
String trimmed = withSpace.trim(); // "a b c"
I've made the code so it asks the user various questions, and if the input.trim().isEmpty() a message will be given to the user and will ask the user to input again. So if the user just writes blank spaces, message given. If the user gives a few blank spaces and some characters, it will accept.
Problem right now is that I want to capitalize the first letter of the Word, but it doesn't really work. Say if the user's input start with a letter then that will be capitalized. But if there's whitespace it wont capitalize at all.
So if input is:
katka
Output is:
katka
Another example:
katka
Output is:
Katka
Code is:
String askWork = input.nextLine();
String workplace = askWork.trim().substring(0,1).toUpperCase()
+ askWork.substring(1);
while (askWork.trim().isEmpty()){
String askWork = input.nextLine();
String workplace = askWork.trim().substring(0,1).toUpperCase()
+ askWork.substring(1);
}
I've tried different approaches but no success.
The problem is because of whitespace as all the indices you refer while converting to uppercase are not accurate.
So first trim() the String so you can clear all leading and trailing whitespace and then capitalize it.
better check empty string and all whitespace to avoid exception.
String askWork = input.nextLine().trim();
String capitalized = askWork.substring(0, 1).toUpperCase() + askWork.substring(1)
The trim() method on String will clear all leading and trailing whitespace. The trimmed String must become your new String so that all indices you refer to after that are accurate. You will no longer need the replaceAll("\\s",""). You also need logic to test for empty input. You use the isEmpty() method on String for that. I've written a toy main() that keeps asking for a word and then capitalizes and prints it once it gets one. It will test for blank input, input with no characters, etc.
public static void main(String[] args) throws Exception {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String askWork = "";
while (askWork.isEmpty()) {
System.out.println("Enter a word:");
askWork = input.readLine().trim();
}
String workPlace = askWork.substring(0,1).toUpperCase() + askWork.substring(1);
System.out.println(workPlace);
}
Try trimming your input to remove the whitespace, before attempting to capitalize it.
String askWork = input.nextLine().trim();
String capitalized = askWork.substring(0, 1).toUpperCase() + askWork.substring(1)
However, if the input is only whitespace, this will result in an IndexOutOfBoundsException because after trim() is called askWork is set to the empty string ("") and you then try to access the first character of the empty (length 0) string.
String askWork = input.nextLine().trim();
if(askWork.isEmpty()) {
// Display error
JOptionPane.showMessageDialog(null, "Bad!");
else {
String capitalized = askWork.substring(0, 1).toUpperCase() + askWork.substring(1)
JOptionPane.showMessageDialog(null, "It worked! -- " + capitalized);
}
You will need to trim the input before you start manipulating its contents:
String askWork = input.nextLine().trim();
String workplace = askWork.substring(0,1).toUpperCase() + askWork.substring(1);
Another solution without substrings:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String askWork = input.nextLine().trim();
while (askWork.isEmpty())
askWork = input.nextLine().trim();
char[] workChars = askWork.toCharArray();
workChars[0] = workChars[0].toUpperCase();
String workplace = String.valueOf(workChars);
// Work with workplace
input.close();
}
I have a string that a user inputs their name in [Last, First Middle] format and I need to change it to [First Middle Last] format.
I've defined the last name as LFM.substring(0, commaSpace) . commaSpace being the name for the ", " in the input of the LFM (Last, First Middle) user input.
Then I needed to define firstMiddle . My question to you is, how could I define the end of the string LFM so I can have firstMiddle be LFM.substring(commaSpace, (end of string) ); ? That way I can just print firstMiddle + last .
ALL OF MY CURRENT CODE:
(IT'S REALLY MESSY, SORRY)
System.out.println();
System.out.println("This program will separate and convert a name in [Last, First, Middle] format to [First Middle Last].");
System.out.println();
System.out.print("Please enter a name in [Last, First Middle] format. ");
Scanner userInput = new Scanner(System.in);
String lineSeparator = System.getProperty("line.separator");
String LFM, first, middle, last, firstMiddle;
int commaSpace, end, lastLength;
userInput.useDelimiter(lineSeparator);
LFM = userInput.nextLine();
commaSpace = LFM.indexOf(",");
last = LFM.substring(0, commaSpace);
lastLength = last.length();
firstMiddle = LFM.substring(commaSpace, //?);
first = LFM.substring(commaSpace + firstMiddle.length());
System.out.println(firstMiddle + (" ") + last);
Use replaceAll or replaceFirst functions since it accepts regex as first argument.
string.replaceAll("^(\\w+),\\s*(\\w+)\\s+(\\w+)$", "$2 $3 $1");
DEMO