What I'm trying to do here is have a user input a sentence or some type of string, then have the scanner search through the string to determine if there is an "e" or "E" in there. If the scanner finds either one of those it will replace them with "xyz." If they are not present then it should return "All is good!" The code I have thus far is:
public class Example {
String userInput;
Scanner in = new Scanner(System.in);
System.out.println("Please write a sentence.");
userInput = in.nextLine();
System.out.println(userInput.replace("e","xyz"));
System.out.println(userInput.replace("E","xyz"));
in.close();
}
As I think you can tell this really just prints the same line twice, once removing a lower case e and the other removing a capital E. I was looking for a way to combine the two replacements and then have it replace and print if it finds an e or just print "All is good!" if there are no "e"s.
This isn't related to Scanner at all really. Trivial approach:
String replaced = userInput.replace("e","xyz").replace("E","xyz");
String out = replaced.equals(userInput) ? "All is good!" : replaced;
System.out.println(out);
Or use replaceAll:
Pattern eE = Pattern.compile("[eE]");
String replaced = eE.matcher(userInput).replaceAll("xyz");
You're going to want to look into Pattern and its associate Matcher. This can give you precisely what you want.
While String#replaceAll gives you what you want, it's not entirely semantic; you can certainly replace all of the "e"s with "xyz" and then compare them to see if there was no change, but using Matcher gives you a bit more obvious control over the logic.
We first need to compile a regex, then build a matcher from the compiled regex. If we find a match, we can then replace the strings; otherwise, we can print out our value.
String userInput;
Scanner in = new Scanner(System.in);
System.out.println("Please write a sentence.");
userInput = in.nextLine();
Pattern pattern = Pattern.compile("[eE]");
Matcher matcher = pattern.matcher(userInput);
if(matcher.find()) {
System.out.println(matcher.replaceAll("xyz"));
} else {
System.out.println("All is good!");
}
System.out.println(userInput.replaceAll("[eE]","xyz"));
Also, don't close the System.in stream. It's not desirable to close that out in case some other part of your application wants to make use of it, or if you want to make use of it later.
Java strings are immutable, so you can't just call replace on userInput and expect it to be modified in place. You need to save the result of the function call.
Related
I guys, i'm trying to create an interactive constructor that take name and surname of the users as input in a scanner...all works, but for design now i want to accept only letters in name and surname, i've tryed with Pattern and Matcher, but the costructor still set number as name or surname (it tell me that is an invalid input but still set it in the User)
public User(){
System.out.println("insert name and surname");
System.out.println("Name: ");
Scanner input = new Scanner(System.in);
Pattern p = Pattern.compile("a,z - A,Z");
name = input.nextLine();
Matcher m = p.matcher(name);
if(m.matches()) {
this.setName(name);
}else{
System.out.println("invalid input");
}
System.out.println("SURNAME:");
surname= input.nextLine();
this.setSurname(surname);
p.matcher(surname);
System.out.println(Welcome);
System.out.println("--------------------------");
}
There's a lot of things going on here that aren't quite right. You are on your own for the stuff other than the regex-issue but consider the other points noted below.
the constructor should not be interactive - collect inputs and pass them to the constructor
your regex pattern is wrong so it will not match the inputs you actually want
you are reading the name into the name variable and then testing it - this is why it reports bad input but still stores it
you have no error recovery for handling bad input
write methods to do thing like build a user or get user input rather than trying to do everything in one place. Limit responsibilities and it is easier to write, debug, and maintain.
Regex
As written, your pattern will probably only match itself because the pattern is not well-defined. I think what you are trying to do with your regex is "^[a-zA-Z]+$".
The ^ starts the match at the beginning of the String and the $ ends the match at the end of the String. Together it means the input must be an exact match to the pattern (i.e. no extraneous characters).
The [a-zA-Z] defines a character class of alphabet characters.
The + indicates one or more characters of the preceding character class match.
Note that String has a convenience method for pattern-matching so you can do something like
String regex = "^[a-zA-Z]+$";
String input = ...
if (input.matches(regex)) { ...
Regarding how to create an instance of the User. Write methods to do things and let the constructor simply construct the object.
// Constructor is simple - just assign parameter arguments to members
public User(String name, String surname) {
this.name = name;
this.surname = surname;
}
// a method for constructing a User - get the user input and invoke constructor
public User buildUser(Scanner in) {
// define the regex in a constant so its not repeated
String name = promptForString("Enter name", NAME_REGEX, in);
String surname = promptForString("Enter surname", in);
return new User(name, surname);
}
// get the input, check against regex, return it if valid
public String promptForString(String prompt, String regex, Scanner in) {
for (;;) {
String input = in.readLine();
if (!input.matches(regex)) {
System.out.println("Invalid input - try again");
continue;
}
return input;
}
}
First I'd say such complex logic shouldn't be used in a constructor. Use it in our main method or any other dedicated method and construct the object from the processed results:
...
Scanner scanner = new Scanner(System.in);
Pattern p = Pattern.compile(???);
User user = new User();
String name = scanner.nextLine().trim()
if( p.matcher(name).matches() )
{
user.setName(name);
}
...
Now let's talk about why you code is probably not working correctly and that's because of Regex. The regex expression you use maybe does not what you think. With external third-party tools like Regexr you can see what your expressions do.
In your case you only want to allow character but not numbers. This can be done with the Regex [A-Za-z] Now we'd check if the string is a single letter... However names rarely consist of a single character so we've to add a quantifier operator to the regex. Now let's assume a name can range between 0 and infinite letters. In such a case the correct quantifier would be + (at least 1) which leads to our final result: Pattern p = Pattern.compile("[A-Za-z]+")
Code I used for testing:
String val = "";
Pattern pattern = Pattern.compile( "^[A-Za-z]+$" );
try ( Scanner scanner = new Scanner( System.in ) )
{
String input = scanner.nextLine().trim();
Matcher m = pattern.matcher( input );
if(m.matches())
val = input;
}
System.out.println("Value: " + val);
Im trying to separate each word in the sentence using StringTokenizer class. It works fine for me. But I found another solution to my case using Scanner class.I applied same regular expression in both ways but got different result. I would like to know the reason for different out put I got but with same expression.
Here is my code :
String sentence = "I have some problems with this section!"
+ " But I love to learn.";
StringTokenizer st = new StringTokenizer(sentence, "[! ]");
System.out.println("========Using StringTokenizer=========");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
Scanner s = new Scanner(sentence);
s.useDelimiter("[! ]");
System.out.println("========Using Delimiter=========");
while (s.hasNext()) {
System.out.println(s.next());
}
Out-put form StringTokenizer:
========Using StringTokenizer=========
I
have
some
problems
with
this
section
But
I
love
to
learn.
Out-put using Scanner class :
========Using Delimiter=========
I
have
some
problems
with
this
section
But
I
love
to
learn.
It is because Scanner may match an empty String, while StringTokonizer will not. In this case in the part "section! But" Scanner matches the whitespace after the ! symbol, whereas StringTokenizer does not.
Scanner includes empty matches while StringTokenizer does not.
StringTokenizer can't properly parse delimited files with meaningful indexed columns/fields like /etc/passwd or CSVs for this reason because it will not return all of the columns/fields while Scanner will.
I understand splitting a string in Java is something like this:
String[] result = userCalcInput.split("[-+*/]");
But i want to split say the following expressions.
2+2
222*2
2/2+6
120+9/4+22
29*2+9
I want the user to be able to enter anything such as the above or their own choice as a string and then i can split this on the operator and push into the different lists. code so far below:
List<Integer> numberList = new ArrayList<Integer>();
List<String> operatorList = new ArrayList<String>();
Scanner userInputNoOne = new Scanner( System.in );
System.out.println("Enter your calculation: ");
userCalcInput = userInputNoOne.next();
String[] result = userCalcInput.split("[-+*/]");
if(userCalcInput = int){
//code here
}
else if (userCalcInput = NaN){
//code here
}
System.out.println(result);
I understand this wont work but just wanted to see if right idea and how to properly implement it.
thanks
I understand you are quite new to Java.
You could use regular expressions.
Regular expressions allow you to find specific patterns in a string, in that case you want to look for numbers and operators, which are defined separately in a 'regex' : \d for a digit and \W for a non-word character, such as an arithmetic operator.
You should try using the Pattern and Matcher classes
Firstly, I'm very beginner, but I like to think I mildly understand things.
I'm trying to write a method that will store the user's input into a string. It works just fine, except if the user puts in a space. Then the string stops storing.
public static String READSTRING() {
Scanner phrase = new Scanner(System.in);
String text = phrase.next();
return text;
}
I think the problem is that phrase.next() stops scanning once it detects a space, but I would like to store that space in the string and continue storing the phrase. Does this require some sort of loop to keep storing it?
Use .nextLine() instead of .next().
.nextLine() will take your input until a newline character has been found (when you press enter, a newline character is added). This essentially allows you to get one line of input.
From the Javadoc, this is what we have:
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
Either you can use phrase.nextLine() as suggested by others, or you can use Scanner#useDelimiter("\\n").
Try phrase.nextLine();. If I recall correctly, Scanner automatically uses spaces as delimiters.
Try
pharse.NextLine();
and you got do an array for limited words
String Stringname = {"word","word2"};
Random f = new Random(6);
Stringname = f.nextInt();
and you can convert an integer to string
int intvalue = 6697;
String Stringname = integer.ToString(intvalue);
I have a string in what is the best way to put the things in between $ inside a list in java?
String temp = $abc$and$xyz$;
how can i get all the variables within $ sign as a list in java
[abc, xyz]
i can do using stringtokenizer but want to avoid using it if possible.
thx
Maybe you could think about calling String.split(String regex) ...
The pattern is simple enough that String.split should work here, but in the more general case, one alternative for StringTokenizer is the much more powerful java.util.Scanner.
String text = "$abc$and$xyz$";
Scanner sc = new Scanner(text);
while (sc.findInLine("\\$([^$]*)\\$") != null) {
System.out.println(sc.match().group(1));
} // abc, xyz
The pattern to find is:
\$([^$]*)\$
\_____/ i.e. literal $, a sequence of anything but $ (captured in group 1)
1 and another literal $
The […] is a character class. Something like [aeiou] matches one of any of the lowercase vowels. [^…] is a negated character class. [^aeiou] matches one of anything but the lowercase vowels.
(…) is used for grouping. (pattern) is a capturing group and creates a backreference.
The backslash preceding the $ (outside of character class definition) is used to escape the $, which has a special meaning as the end of line anchor. That backslash is doubled in a String literal: "\\" is a String of length one containing a backslash).
This is not a typical usage of Scanner (usually the delimiter pattern is set, and tokens are extracted using next), but it does show how'd you use findInLine to find an arbitrary pattern (ignoring delimiters), and then using match() to access the MatchResult, from which you can get individual group captures.
You can also use this Pattern in a Matcher find() loop directly.
Matcher m = Pattern.compile("\\$([^$]*)\\$").matcher(text);
while (m.find()) {
System.out.println(m.group(1));
} // abc, xyz
Related questions
Validating input using java.util.Scanner
Scanner vs. StringTokenizer vs. String.Split
Just try this one:temp.split("\\$");
I would go for a regex myself, like Riduidel said.
This special case is, however, simple enough that you can just treat the String as a character sequence, and iterate over it char by char, and detect the $ sign. And so grab the strings yourself.
On a side node, I would try to go for different demarkation characters, to make it more readable to humans. Use $ as start-of-sequence and something else as end-of-sequence for instance. Or something like I think the Bash shell uses: ${some_value}. As said, the computer doesn't care but you debugging your string just might :)
As for an appropriate regex, something like (\\$.*\\$)* or so should do. Though I'm no expert on regexes (see http://www.regular-expressions.info for nice info on regexes).
Basically I'd ditto Khotyn as the easiest solution. I see you post on his answer that you don't want zero-length tokens at beginning and end.
That brings up the question: What happens if the string does not begin and end with $'s? Is that an error, or are they optional?
If it's an error, then just start with:
if (!text.startsWith("$") || !text.endsWith("$"))
return "Missing $'s"; // or whatever you do on error
If that passes, fall into the split.
If the $'s are optional, I'd just strip them out before splitting. i.e.:
if (text.startsWith("$"))
text=text.substring(1);
if (text.endsWith("$"))
text=text.substring(0,text.length()-1);
Then do the split.
Sure, you could make more sophisticated regex's or use StringTokenizer or no doubt come up with dozens of other complicated solutions. But why bother? When there's a simple solution, use it.
PS There's also the question of what result you want to see if there are two $'s in a row, e.g. "$foo$$bar$". Should that give ["foo","bar"], or ["foo","","bar"] ? Khotyn's split will give the second result, with zero-length strings. If you want the first result, you should split("\$+").
If you want a simple split function then use Apache Commons Lang which has StringUtils.split. The java one uses a regex which can be overkill/confusing.
You can do it in simple manner writing your own code.
Just use the following code and it will do the job for you
import java.util.ArrayList;
import java.util.List;
public class MyStringTokenizer {
/**
* #param args
*/
public static void main(String[] args) {
List <String> result = getTokenizedStringsList("$abc$efg$hij$");
for(String token : result)
{
System.out.println(token);
}
}
private static List<String> getTokenizedStringsList(String string) {
List <String> tokenList = new ArrayList <String> ();
char [] in = string.toCharArray();
StringBuilder myBuilder = null;
int stringLength = in.length;
int start = -1;
int end = -1;
{
for(int i=0; i<stringLength;)
{
myBuilder = new StringBuilder();
while(i<stringLength && in[i] != '$')
i++;
i++;
while((i)<stringLength && in[i] != '$')
{
myBuilder.append(in[i]);
i++;
}
tokenList.add(myBuilder.toString());
}
}
return tokenList;
}
}
You can use
String temp = $abc$and$xyz$;
String array[]=temp.split(Pattern.quote("$"));
List<String> list=new ArrayList<String>();
for(int i=0;i<array.length;i++){
list.add(array[i]);
}
Now the list has what you want.