I'm making a word guessing game. The JTextField can't be empty, can't be longer or smaller than 5 and cannot contain numbers. How do I do the last part?
#Override
public void actionPerformed(ActionEvent e) {
if (text.getText().isEmpty()) {
showErrorMessage("You have to type something");
} else if (text.getText().length() != 5) {
showErrorMessage("Currently only supporting 5-letter words");
} else if (contains integer){
showErrorMessage("Words don't contain numbers!");
} else {
r.setGuess(text.getText());
}
}
Rather than explicitly checking for numbers, I would suggest whitelisting characters which are allowed. Would letters with accents be allowed, for example? Both upper and lower case? Punctuation?
Once you've worked out your requirements, I suggest you express them as a regular expression - and then check whether the text matches the regular expression.
For example:
private static final Pattern VALID_WORD = Pattern.compile("^[A-Za-z]*$");
...
if (!VALID_WORD.matcher(text.getText()).matches()) {
// Show some appropriate error message
}
Note that I haven't included length checks in there, as you're already covering those - and it may well be worth doing so in order to give more specific error messages.
You might also want to consider preventing your text box from accepting the invalid characters to start with - just reject the key presses, rather than waiting for a submission event. (You could also change the case consistently at the same time, for example.) As noted in comments, JFormattedTextField is probably a good match - see the tutorial to get started.
create a method that checks if the JTextField has a number like this:
private boolean isContainInt(JTextField field) {
Pattern pt = Pattern.compile("\\d+");
Matcher mt = pt.matcher(field.getText());
return mt.find();
}
if (!text.getText().matches("[a-zA-Z]*")) {
// something wrong
}
Related
I have to create a program in which I input 2 values simultaneously but, these values must range from 50 to 127. If the value is less than 50 or above 127 it should show an exception saying "value entered" is too low or too high. As a requirement for the program, I cannot use flow-control statements. I have not tried anything as I am lost
UPDATE: WITH THE HELP OF YOUR COMMENTS I HAVE SATISFIED THE 127 CONDITION, AND MAY BE ON THE WAY TO SATISFYING THE LOWER CONDITION WITH THE NEXT(PATTERN) METHOD. I AM CURRENTLY CONTACTING MY TEACHER AND ASKING IF SATISFYING THE 127 CONDITION IS ENOUGH. THANK YOU ALL
UPDATE 2: the 127 condition was enough!
import java.util.Scanner;
public class A1_Q1 {
public static void main(String[] args) {
// declaration of variables
double x, y, z;
int p, q;
Scanner kBoard = new Scanner(System.in);
System.out.println("Welcome to the Simple 3D-Space Program:");
System.out.println("+++++++++++++++++++++++++++++++++++++++");
System.out.print("Enter values for 'p' and 'q' simultaneously. Must be between 50 and 127:");
String input = kBoard.nextLine();
//separating first number and second number from the inputed line
String firstNum = input.substring(0, input.indexOf(" "));
String secondNum = input.substring(input.indexOf(" "), input.length());
//isolating numbers from the strings and filtering out
String numOnlyP = firstNum.replaceAll("[^0-9]", "");
String numOnlyQ = secondNum.replaceAll("[^0-9]", "");
//transforming string into integer values
p = Integer.parseInt(numOnlyP);
q = Integer.parseInt(numOnlyQ);
//to check and see if previous code was functioning correctly
System.out.println(p + " " + q);
}
}
The constraint against using flow control statements is highly artificial, but it does force you into a certain direction. For the program to behave differently for some inputs than it does for others requires flow control. If you cannot use flow control in your program then that means the needed flow control must be somewhere else. And the only "somewhere else" you are allowed to use is java.util.Scanner.
As a blooming programmer, some of the things you need to learn and have ready at all times at the tip of your brain are the powers of two, and certain ones of them especially. Among those is 27 = 128, which has special significance as one more than 127, the maximum value of an 8-bit two's complement integer, such as a Java byte (these properties are closely related). And lo and behold, the maximum value your program is supposed to accept is 127.
Read the API docs of Scanner, especially those for scanning inputs of various specific Java types. You will find some that can serve the purpose of (as a side effect) throwing an exception for inputs larger than 127. If you want to throw a custom exception instead, then you can catch the one thrown by the Scanner and throw one of your choice in its place -- provided that try / catch is not considered flow control.
Scanner could be pressed into service for an exception for violation of the lower bound, too, but that would require a very unnatural hack.
Details are left as the exercise they are intended to be.
This question is a tad disingenuous. A requirement that 50-127 is accepted, the rest is not, is not normally possible without flow control. So we need flow control, but, we're not allowed to use flow control.
Quite the dilemma.
It's a bit like an escape room. You must screw together this intricate thing, but, you don't have a screwdriver (all your pockets were emptied before entering it), so now what? Well, you look around the room. What tools do you have? Even if they are epically not suited to the job, can they be used to deliver?
So, let's look. What do we have? We have scanner.
We need to look at what you can do with those, and see if that helps, because other than Scanner you're not given much room to work.
And lo! Scanner delivers. It's a method that is almost never used with scanner, but it's there, and it'll give us a way through: The next(Pattern) method can do the job.
Quoting from the javadoc:
Returns the next token if it matches the specified pattern.
Great!
Now, I'm flabbergasted, but the docs are broken. Java is used by millions of people and the docs are taken fairly seriously, so that is mostly an indictment on how little this method is used. Nobody, apparently, noticed. The thing missing from the docs is subtle, but important: What happens if the next token in the stream does not match the specified pattern? The docs don't say. But the scanner acts the exact same way as when you call e.g. nextInt() and the next token is not an int: It throws InputMismatchException.
This means next(Pattern) is the complete package: Will pass if input 'matches the pattern' and throws if it does not, so now all we need is a pattern that matches if the input is 50-127 and fails otherwise. We can trivially do that, though we'll need to dive into Regular Expressions to do the job - as that is the 'language' for the pattern we can provide to this next method. (There is a String variant too, but it just parses your string as... a regular expression, so we can't get out of reading up on those).
Scanner s = new Scanner(System.in);
int value = s.next("[5-9][0-9]|1[0-1][0-9]|12[0-7]");
It's a rather unwieldy pattern, but it'll get the job done. This pattern says:
The input has to be one of these 3 different options (a|b|c is regexp for: either a, or b, or c)
Option 1: A 5/6/7/8/9, followed by any digit.
Option 2: A 1, followed by a 0 or a 1, followed by any digit.
Option 3: A 1, a 2, and then a 0/1/2/3/4/5/6/7.
That'll covers 50-127. If you want e.g. 00050 to be okay too, stick a 0* on the front, which regexp for 'any amount of zeroes'.
I think this exercise is quite a reach. As the answers provided so far clearly attest, no java programmer would get in their right mind to solve such a task by using the regexp pattern powers of scanner, they'd just read an int and use an if like normal. As the unwieldiness of that regexp shows, using a regex pattern to limit numeric input is not really what it is meant for. A key insight into writing readable, flexible code is to avoid doing that: Using a thing in a way that the author of the thing clearly was not at all thinking about when they wrote it is a fine way to create confusing code that runs into bugs quickly and may no longer work nearly as well in future updates of said thing. I guess it's testing if you can think creatively and read documentation, perhaps?
If you can contact the author of this question, you might want to have them read this answer too :)
I'll be filing a bug over at OpenJDK about the subtle mistake in the docs, at any rate.
Quite standard approach for such problems is to use lookup tables, something like this:
import java.util.Scanner;
public class TestProgram {
private interface Handler {
void handle(final int value);
}
private static class NullHandler implements Handler {
public void handle(final int value) { }
}
private static class TooLowHandler implements Handler {
public void handle(final int value) {
throw new IllegalArgumentException("Value " + value + " is too low");
}
}
private static class TooHighHandler implements Handler {
public void handle(final int value) {
throw new IllegalArgumentException("Value " + value + " is too high");
}
}
private static void checkLow(final int value) {
final int sign = ((value - 50) >> 31) & 1;
new Handler[]{new NullHandler(), new TooLowHandler()}[sign].handle(value);
}
private static void checkHigh(final int value) {
final int sign = ((value - 128) >> 31) & 1;
new Handler[]{new TooHighHandler(), new NullHandler()}[sign].handle(value);
}
public static void main(final String args[]) {
final Scanner scanner = new Scanner(System.in);
final int p = scanner.nextInt();
final int q = scanner.nextInt();
System.out.println(p + " " + q);
checkLow(p); checkLow(q);
checkHigh(p); checkHigh(q);
}
}
Wrote a method which takes in a String and checks to see the follow conditions:
If String is "quit", it will terminate the program.
If the String is any value other than an integer, it should return "Invalid input ".
Any negative integers and also 0 should return "Invalid input".
However, when I passed in 10, it returned as "Invalid input"?
Please advise:
public static String validate(String input) {
Pattern pattern = Pattern.compile(".*[^1-9].*");
StringBuilder results = new StringBuilder();
if (input.equals("quit")) {
System.exit(1);
} else if (!pattern.matcher(input).matches() == false) {
results.append("Invalid input ");
results.append("'");
results.append(input);
results.append("'");
}
return results.toString();
}
What's wrong with what I am doing?
You should write a pattern of what you expect instead of what you're not.
As describe what you want is always simpler that describe the rest of it.
So you expect :
Pattern acceptPattern = Pattern.compile("[1-9][0-9]*");
You may consider make you conditional expression simpler and correct by not using both ! and == false at the same time:
Which will make :
if (!acceptPattern .matcher(input).matches()) {//Invalid input code}
or
if (acceptPattern .matcher(input).matches() == false) {//Invalid input code}
note :
You write if(!A == false) => if(A == true) => if(A) but which was the inverse
It looks like you want to match one or more digits, where the first one is not a zero.
[1-9]\d*
If you want to force it to be the entire string, you can add anchors, like this:
^[1-9]\d*$
Your regex string doesn't allow for the presence of a zero (not just a lone zero).
That is, the string ".*[^1-9].*" is looking for "any number of characters, something that isn't 1-9, and any number of characters". When it finds the zero, it gives you your incorrect result.
Check out What is the regex for "Any positive integer, excluding 0" for how to change this.
Probably the most helpful solution on that page is the regex [0-9]*[1-9][0-9]* (for a valid integer). This allows for leading zeros and/or internal zeros, both of which could be present in a valid integer. In using Matcher#matches you also ensure that this regex matches the whole input, not just part of it (without the need to add in beginning and end anchors -- ^$).
Also, the line else if (!pattern.matcher(input).matches() == false) could be made a lot more clear.... maybe try else if (pattern.matcher(input).matches()) instead?
This question already has answers here:
How to determine if a String has non-alphanumeric characters?
(8 answers)
Closed 8 years ago.
Here I am using search TextField and search button in my program
searchTxt = new TextField();
searchTxt.setWidth("400px");
search = new Button("Search");
search.setImmediate(true);
search.addListener((Button.ClickListener) this);
public void buttonClick(ClickEvent event) {
final Button button = event.getButton();
if (button == search) {
String searchText = (String) searchTxt.getValue();
searchText = searchText.trim();
if (!searchText.equals(GlobalConstants.EMPTY_STRING) && searchText != null)
{
// logic
}
}
}
which logic should I use here by performance point of view?
First and foremost, you should not so much care about performance in GUI event handling code. If you'll encounter performance problems they will most probably not emerge in user input validation code.
So, when writing an application your focus should be on maintainability and readability. You'll best achieve that when you use built-in framework functionality. So, assuming that with 'check that entered text only contains alphanumeric characters' you mean 'validate that...' you can use Vaadin's validators, and more specifically the RegexpValidator. Your code would then look like
searchTxt = new TextField();
// match at least one or more alphanumeric characters
searchTxt.addValidator(new RegexpValidator("\\w+", true, "Error msg: not valid..."));
public void buttonClick(ClickEvent event) {
final Button button = event.getButton();
if (button == search) {
if (searchTxt.isValid()) {
// logic
}
}
}
With that, the logic will only be executed if the user has entered at least one alphanumeric character.
You can do it as follows:
1. Check that the length of the String is 1.
2. If so, get the character at position zero by using charAt() method of String.
3. Then use Character.isAlphabetic() or Character.isDigit() to do your validation.
Another option would be to use RegEx which would greatly reduce your lines of code but increase your learning curve.
What will be the FormatterFactory's factor value in JFormattedTextField if I only want to accept letters and spaces.
Cause I want it to accepts Names only. Like - John Doe.
I couldn't find an elegant way using a formatter. The non-elegant way is to create a MaskFormatter with the main issue that you will be limiting the number of characters allowed (although you can limit to an arbitrarily large number).
MaskFormatter mask = new MaskFormatter("*************"); // Specifies the number of characters allowed.
mask.setValidCharacters("qwertyuiopasdfghjklzxcvbnm" +
" QWERTYUIOPASDFGHJKLZXCVBNM "); // Specifies the valid characters: a-z, A-Z and space.
mask.setPlaceholderCharacter(' '); // If the input is less characters than the mask, the space character will be used to fill the rest. Then you can use the trim method in String to get rid of them.
JFormattedTextField textField = new JFormattedTextField(mask);
I feel that validating the input is a better approach than restricting characters in this case. I can add an example if you want to use this approach.
Edit: Using InputVerifier, you have to subclass it and override verify as shown below.
JTextField textField = new JTextField();
textField.setInputVerifier(new InputVerifier() {
#Override
public boolean verify(JComponent input) {
String text = ((JTextField) input).getText();
if (text.matches("[a-zA-Z ]+")) // Reads: "Any of a-z or A-Z or space one or more times (together, not each)" ---> blank field or field containing anything other than those will return false.
return true;
return false;
}
});
The text field will not yield focus (except to parent components) until requirements are met.
I am new to write regular expressions so please help.
I want to match this pattern (in Java):
"ABC",010,00,"123",0,"time","time",01,00, 10, 10,88,217," ",," "
the data I get will always be in the above format with 16 values. But the format will never change.
I am not looking for parsing as this can be parsed by java split too.
I will have large chunks of these data so want to capture the first 16 data points and match with this pattern to check if I received it correctly else ignore.
so far I have only tried this regex:
^(\".\"),.,(\".\"),.,(\".\"),(\".\"),.,.,.,.,.,.,(\".\"),.,(\".\")$
I am still in the process of building it.
I just need to match the pattern from a given pool. I take first 16data points and try to see if it matches this pattern else ignore.
Thanks!!
This should do the trick. Keep in mind that he doesn't care what order the data points occur in (ie. they could all be strings or all numbers).
(\s?("[\w\s]*"|\d*)\s?(,|$)){16}
You can try it out here.
Please find in the below code comprising comma separated evaluation for String, Number and Decimal.
public static void commaSeparatedStrings() {
String value = "'It\\'s my world', 'Hello World', 'What\\'s up', 'It\\'s just what I expected.'";
if (value.matches("'([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.]+'(((,)|(,\\s))'([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.]+')*")) {
System.out.println("Valid...");
} else {
System.out.println("Invalid...");
}
}
/**
*
*/
public static void commaSeparatedDecimals() {
String value = "-111.00, 22111.00, -1.00";
// "\\d+([,]|[,\\s]\\d+)*"
if (value.matches(
"^([-]?)\\d+\\.\\d{1,10}?(((,)|(,\\s))([-]?)\\d+\\.\\d{1,10}?)*")) {
System.out.println("Valid...");
} else {
System.out.println("Invalid...");
}
}
/**
*
*/
public static void commaSeparatedNumbers() {
String value = "-11, 22, -31";
if (value.matches("^([-]?)\\d+(((,)|(,\\s))([-]?)\\d+)*")) {
System.out.println("Valid...");
} else {
System.out.println("Invalid...");
}
}