Beginner: Do while loop issue - java

Ello, got a minor issue that I haven't got a clue on what's going wrong... Snippet of the code:
do{
String third = JOptionPane.showInputDialog(null, "Please enter Year ["+day+"/"+month+"/YY?]");
year = Integer.parseInt (third);
validChoice = validYear(year);
}while(!validChoice);
do{
String goUS = JOptionPane.showInputDialog(null, "Do you want to switch the format to US? [Y/N]");
goUS = goUS.toUpperCase();
char conversion = goUS.charAt(0);
validChoice = validOption(conversion);
switch(conversion){
case 'Y':
if(year < 10)
{
date.append(month).append("/").append(day).append("/" + "200").append(year);
}else{
date.append(month).append("/").append(day).append("/" + "20").append(year);
}
JOptionPane.showMessageDialog(null, date);
break;
case 'N':
if(year < 10)
{
date.append(day).append("/").append(month).append("/" + "200").append(year);
}else{
date.append(day).append("/").append(month).append("/" + "20").append(year);
}
JOptionPane.showMessageDialog(null, date);
break;
default:
JOptionPane.showMessageDialog(null, "Invalid answer! Use Y/N", "Error", JOptionPane.ERROR_MESSAGE);
}}while(!validChoice);
//// METHODS:
public static boolean validYear (int year){
boolean isValid = true;
if(year < 1 || year > 99)
{
isValid = false;
}
return isValid;
}
public static boolean validOption (char conversion){
boolean isValid = true;
if(conversion != 'y' || conversion != 'n')
{
isValid = false;
}
return isValid;
}
The first part, with regards to the year, and with it's associated method, it loops fine if the input is wrong.
The second part, 'goUS', the method's remotely the same thing, checking the char if it's y/n - it works fine with regards to the check and all, but after hitting OK with the correct display of the date, it starts the goUS loop again, and the answers start to concatenate itself from the previous display, and so on. I want the app to just end after displaying the date.
Any help pointing out my flaw would be greatly appreciated.

Well, your validOption checks for lower case characters, but you pass it upper case characters.
The most flexible solution would be to normalise the case before comparing to expected values, such as
public static boolean validOption (char conversion) {
conversion = Character.toLowerCase(conversion)
return conversion == 'y' || conversion == 'n';
}

It seems the problem is because of case of input character, you are checking with lower-case in validOption and checking with upper-case in the main method. I believe your input is upper case, and validOption returns false.
Change validOption to:
public static boolean validOption (char conversion) {
return conversion == 'Y' || conversion == 'N';
}
or even use java.lang.Character toLower or toUpper methods.

Your validOption() does not work correctly. The working of the rest of the loop is independent of that, but the termination depends on the correct return value.
You check lower case characters there, but uppercase elsewhere. You change the checked character to uppercase just before the validity check. Change the characters to uppercase in validOption() too.

Related

Java - Use ternary operator on char input to get boolean

Looking to do something like in C#:
bool walkable = t.Type == TileType.Green ? true : false;
but in Java
Boolean international_F = (in.next() == 'Y') ? true : false;
The above is what I've tried so far. Wondering if it's even possible.
EDIT: I just noticed .nextChar() doesn't exist. Edited snippet to reflect that.
"nextChar": Assuming in is a Scanner, your issue is that Scanner doesn't have a nextChar() method. You could read a whole word, and then take it's first char:
char theChar = in.next().charAt(0)
boolean vs ternery: If your outputs are true/false, then you don't need an if. You can just write:
bool walkable = t.Type == TileType.Green; // C#
boolean international_F = in.next().charAt(0) == 'Y'` // Java
boolean vs Boolean: Please also note that boolean is the primitive boolean type in Java. Using Boolean will force it to be wrapped as the Boolean class.
case sensitivity: If you want to allow 'y' or 'Y', force the input to a known case first. Since charAt() returns primitive char, you need to use the static Character.toUpperCase().
Solution:
boolean isY = Character.toUpperCase(in.next().charAt(0)) == 'Y'
// - OR -
boolean isY = in.next().startsWith("Y") // not case-insensitive
Boolean international_F = "Y".equals(in.next()); // next returns a string
Boolean international_F =in.next().charAt(0) == 'Y';
You do not need a ternary operator to simply assign the result (true/false) of the evaluation of the condition. You need a ternary operator if you want to do something based on the result of the evaluation of the condition e.g.
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(System.in);
System.out.print("Do you want to continue? [Y/N]: ");
boolean yes = in.nextLine().toUpperCase().charAt(0) == 'Y';
if (yes) {
System.out.println("You have chosen to continue");
} else {
System.out.println("You have chosen to stop");
}
// Or simply
System.out.print("Do you want to continue? [Y/N]: ");
if (in.nextLine().toUpperCase().charAt(0) == 'Y') {
System.out.println("You have chosen to continue");
} else {
System.out.println("You have chosen to stop");
}
// You can use ternary operator if you want to do something based on the result
// of evaluation of the condition e.g.
System.out.print("Do you want to continue? [Y/N]: ");
String response = in.nextLine().toUpperCase().charAt(0) == 'Y' ? "Yes" : "No";
System.out.println(response);
// Without a ternary operator, you would write it as:
System.out.print("Do you want to continue? [Y/N]: ");
String res;
char ch = in.nextLine().toUpperCase().charAt(0);
if (ch == 'Y') {
res = "Yes";
} else {
res = "No";
}
System.out.println(res);
}
}
A sample run:
Do you want to continue? [Y/N]: y
You have chosen to continue
Do you want to continue? [Y/N]: n
You have chosen to stop
Do you want to continue? [Y/N]: y
Yes
Do you want to continue? [Y/N]: n
No
This is an example demonstrating what you want to do:
char a = 'a';
char b = 'b';
Boolean b1 = (a == 'a') ? true : false;
Boolean b2 = (a == b) ? true : false;
System.out.println(b1);
System.out.println(b2);
The output will be:
true
false

Make a loop with a-z input

I am a complete noob to Java, but I wish to make a program that takes an input from user, [A/a] - [C/c], [D/d] - [F/f], and so on, and then returns a value ([A/a-C/c = 1], [D/d-F/f = 2]....
If the input is not A-Z or a-z, returns a "Invalid input". (I think I can figure this one out myself).
I suppose I could make a "ToUpperCase" statement on the input, but I am not entirely sure how to do so.
I would prefer not to use any special databases.
Here is my code so far:
import java.util.Scanner;
public class TelefonTastatur {
public static void main(String[] args) {
String korrTall = "Korresponderer til tallet "; //Strings are in Norwegian, but I don't need help with those :-)
System.out.println("Dette programmet konverterer bokstav-input til korresponderende tall på et telefontastatur.");
System.out.println("Oppgi en bokstav (A-Z: "); //Asks user for A-Z input.
Scanner sc = new Scanner(System.in);
char c = sc.next().charAt(0); //Perhaps toUpperCase to lower number of switch cases?
switch (c) {
case ('A'-'C'): //Not sure how to make A-C and/or a-c. I could make an individual case for all inputs, but that would make a lot of code.
case ('a'-'c'):
System.out.print(korrTall + "2.");
break;
case (D/d - F/f):
case ():
System.out.print(korrTall + "3.");
break;
case (G/g - I/i):
case ():
System.out.print(korrTall + "4.");
break;
case (J/j - L/l):
case ():
System.out.print(korrTall + "5.");
break;
case (M/m - O/o):
case ():
System.out.print(korrTall + "6.");
break;
case (P/p - S/s):
case ():
System.out.print(korrTall + "7.");
break;
case (T/t - V/v):
case ():
System.out.print(korrTall + "8.");
break;
case (W/w - Z/z):
case ():
System.out.print(korrTall + "9.");
break;
case 'F':
case 'f':
System.out.print(korrTall + "0.");
break;
default:
System.out.println("Det du har tastet inn tilsvarer ikke noe tall på et telefontastatur.");
break;
}
}
}
If you want to read a single letter from the user you can use the readInput()provided in the code snippet.
Then, for example in your main(), you could ask for the user to input 2 letters and then you will provide him the result.
public static void main(String[] args) {
try{
char inputOne = readInput();
char inputTwo = readInput();
handle(inputOne,inputTwo);
}catch(Exception e){
System.out.println(e.getMessage());
}
}
static char readInput(){
System.out.println("Insert a character");
String input = Console.readLine();
if (input.length==0) {
char c = input.charAt(0);
if (Character.isLetter(c)) {
return c;
}
}
throw new Exception("Invalid input!");
}
static void handle(char a, char b){
// your logic to handle the input of the user
}
Your question is not clear at all but i try to help you. Next time post what u tried.
This simple code will help you, this can be improved so let's do this :D
Scanner scanner = new Scanner(System.in);
System.out.println("Insert first char");
String firstChar = scanner.next().toUpperCase();
if (firstChar.length() != 1 || (firstChar.toCharArray()[0] < 65 || firstChar.toCharArray()[0] > 90)) {
System.out.println("Please, insert one single character [a-z/A-Z]");
return;
}
System.out.println("Insert second char");
String secondChar = scanner.next().toUpperCase();
if (secondChar.length() != 1 || (secondChar.toCharArray()[0] < 65 || firstChar.toCharArray()[0] > 90)) {
System.out.println("Please, insert one single character");
return;
}
System.out.println(firstChar + " - " + secondChar + " = " + Math.abs(firstChar.toCharArray()[0] - secondChar.toCharArray()[0]));
Note that You can create methods to do repetitive action. In this simple example you can create a method that check if what you just read from keyboard is a single character.
One other improve you can do is handle when user insert something wrong.
Let's try to code :D
Bye
You're going to have to use the Scanner class to accomplish user input.
import java.util.Scanner;
Then create a variable that takes in the keyboard input.
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter a letter: ");
String text = keyboard.nextLine();
Create a method that returns a number given a character.
a-z is equal to 97-122 in Java, and A-Z is equal to 65-90.
public int toNum(String text) {
//Ensure that the text is only 1 character long.
if(text.length() > 1) return -1;
//Convert the one-character String to type char.
char letter = text.charAt(0);
//Convert char to its equivalent number value.
int rawNum = letter;
int newNum;
//Convert the number to a value 0-25.
if(rawNum >= 'a' && rawNum <= 'z') {
newNum = rawNum - 'a';
} else if(rawNum >= 'A' && rawNum <= 'Z') {
newNum = rawNum - 'A';
} else {
//None of the characters were letters A-Z.
System.out.println("Invalid input");
return -1;
}
//If {a,b,c} are 1 and {d,e,f} are 2, then {0,1,2} -> 1 and {3,4,5} -> 2
//Take the floor of the new number divided by 3.
int toReturn = Math.floor(newNum / 3.0) + 1;
return toReturn;
}
Now just call your method with the user input.
toNum(text);
You can print the returned value of the user input as well.
System.out.println(toNum(text));

Issue with or operator in Java - ||

I'm writing a password validation program and having some issues with the or statement that checks for special characters. I'm not sure what is wrong with it, the rest of the program seems to function properly, but entering a password that matches the criteria, for example, P#ndas123$%, just results in an infinite loop.
I believe that the problem is related to my big statement for the !pass.contains("") portion. If that is right, could someone help me understand why the statement is incorrect?
import java.util.Scanner;
public class DylanJacksonProg5 {
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
boolean valid;
valid = true;
do {
//Password rules declared to user
System.out.println("Password Verifier");
System.out.println("");
System.out.println("Enter a password that meets the following rules: ");
System.out.println(" Is at least 8 characters long");
System.out.println(" Contains at least 1 lower letter character");
System.out.println(" Contains at least 1 upper letter character");
System.out.println(" Contains at least 1 numeric digit");
System.out.println(" Contains at least 1 special character of the following set: !##$%^&*");
System.out.println(" Does not contain the word 'and' or the word 'the'");
//Gathering password from user
System.out.println("Enter your password: ");
String pass;
pass = user_input.next();
//Validating password to rules
if (pass.length() < 8) {
int shortlen;
shortlen = 8 - pass.length();
System.out.println("Password is too short. Please add " + shortlen + " characters");
valid = false;
} else
System.out.println("Password length is acceptable.");
//Check for character cases
boolean hasUppercase = !pass.equals(pass.toLowerCase());
boolean hasLowercase = !pass.equals(pass.toUpperCase());
if (!hasUppercase) {
System.out.println("Must have an uppercase Character");
valid = false;
}
if (!hasLowercase) {
System.out.println("Must have a lowercase Character");
valid = false;
}
if (hasUppercase) {
System.out.println("Has an upper case character");
}
if (hasLowercase) {
System.out.println("Has a lowercase Character");
}
//Check for digit
for (int i = 0; i < pass.length(); i++) {
char x = pass.charAt(i);
if (!Character.isDigit(x)) {
valid = false;
}
}
//check for special character
if (!pass.contains("!") || !pass.contains("#") || !pass.contains("#") || !pass.contains("$") ||
!pass.contains("%") || !pass.contains("^") || !pass.contains("&") || !pass.contains("*"))
{
valid = false;
System.out.println("Password requires a special character from the following: !##$%^&*");
}
// check for 'and'
if (pass.contains("and")) {
valid = false;
System.out.println("Cannot contain 'and'");
}
//check for 'the'
if (pass.contains("the")) {
valid = false;
System.out.println("Cannot contain 'the'");
}
System.out.println("");
}
while (!valid);
}
}
I'll tell you one problem straight up front.
Since you set valid to true before the validation loop, and only ever set it to false within the loop, entering an invalid password as your first attempt will result in the loop never exiting.
The setting of valid to true should be the first thing done within the loop.
On top of that, your checks each individually apply to every character in the input string, a situation which is impossible. For example, you check whether the entire string is equal to its lowercased variant, then you check whether it's also equal to its uppercased variant.
That means any string with a letter in it will be deemed invalid since xyZZy cannot be equal to both xyzzy and XYZZY at the same time.
It would be more correct to do something like (pseudo-code, and cut down to a few conditions just to show the method):
do:
hasLowercase = false
hasUpperCase = false
hasNumeric = false
isLongEnough = false
get string from user
if len(string) >= 8:
isLongEnough = true
for each character in string:
if character is lowercase:
hasLowerCase = true
if character is uppercase:
hasUpperCase = true
if character is numeric:
hasNumeric = true
isValid = hasLowerCase && hasUpperCase && hasNumeric && isLongEnough
until isValid
This checks each individual character so that any of them (rather than requiring that all of them) will mark a condition as true.
The OR operators will conflict if you don't have all of the special characters in the password, because in your condition statements, if you have "!" but not "#", it will still result in a false value.
What you can do is check for each special character separately.
Sorry for the lack of explanation, but it is your negation statements in your special character checking block. Usually using !condition works, but it didn't on this online IDE I am using. Not really sure why.
This code will work:
//check for special character
if (pass.contains("!") || pass.contains("#") || pass.contains("#") || pass.contains("$") ||
pass.contains("%") || pass.contains("^") || pass.contains("&") || pass.contains("*"))
{
valid = true;
System.out.println("Password requires a special character from the following: !##$%^&*");
}
else
{
valid = false;
}
There are multiple problems with your code, which are unrelated to each other:
You never set valid to true in the loop, which means that if you enter 1 wrong password, valid will be and always stay false, which means that no matter how many correct passwords you enter afterwards, the loop will repeat infinitely. In other words: the program will only stop if you enter a correct password at the very first attempt.
The big boolean expression is not checking whether the password contains any of the characters, it is checking whether the password contains all characters. Draw the truth table or apply DeMorgan's Laws, and you will see:
!p.c("!") || !p.c("#") || !p.c("#") || !p.c("$") || !p.c("%") || !p.c("^") || !p.c("&") || !p.c("*")
// is the same per DeMorgan's Laws as
!(p.c("!") && p.c("#") && p.c("#") && p.c("$") && p.c("%") && p.c("^") && p.c("&") && p.c("*"))
As soon as you find a single character that is not a digit, you reject the password, IOW all characters must be digits.
It should be obvious that #2 and #3 contradict each other, so it it simply impossible to enter a valid password, so even if you fix #1, it will still not be possible to exit the loop.
There are a 3 issues with your code:
valid must be set to true inside your loop before any checks are done on input:
do {
valid = true;
...
lower & upper case checks should be done differently, for example:
boolean hasUppercase = false;
boolean hasLowercase = false;
for (int i = 0; i < pass.length(); i++){
if (Character.isUpperCase(pass.charAt(i))){
hasUppercase = true;
}
if (Character.isLowerCase(pass.charAt(i))){
hasLowercase = true;
}
}
your checks for special character are incorrect, you could use below instead:
if (!(pass.contains("!") || pass.contains("#") || pass.contains("#") || pass.contains("$") || pass.contains("%") || pass.contains("^") || pass.contains("&") || pass.contains("*"))){
valid = false;
}
EDIT: actually there's another one:
4. Your check for digit also won't work, you could use below instead:
boolean isDigit = false;
for (int i = 0; i < pass.length(); i++) {
char x = pass.charAt(i);
if (Character.isDigit(x)) {
//valid = false;
isDigit = true;
break;
}
}
if (!isDigit)
valid = false;
Here's how OR operator works:
if( condition1 || condition2 || condition3 || condition4)
{
// .....your code;
}
If condition1 is true,then remaining conditions will not be checked and program will move to inside your IF block.However,if Condition1 is false,then condition2 will be checked.If this is true,then remaining conditions will not be checked,otherwise(if it is false) condition3 will be checked.and so on.However as other peoples have already mentioned there is more problem with your code than just with OR operator.
For example,for password=P#ndas123$%,it does not contain "!",so !pass.contain("!") will give true and valid will be set as false thus causing infinite loop.

How to check if a string contains a letter different then a given range in Java

I'm learning Java and I need to write a program that converts Roman numerals and traditional integers.
The code only accepts the letters MDCLXVI as Roman numerals. It does not accept any number.
This is my code:
System.out.print("Enter a roman numeral");
Scanner keyb = new Scanner(System.in);
String roman = keyb.next();
if(roman.matches(".*[0-9].*") || **something different then M, D, C, L, X, V or I**)
{
System.out.println("Wrong! Re-type.");
}
The problem that I'm trying to solve is how to write the second condition of the If.
first off all you have to check if the given Roman number is valid or not. So the method could look like the following:
public static boolean isValid(String romanNumber) {
String pattern = "[m|d|c|l|x|v|i]*";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(romanNumber);
return m.matches();
}
Then you can use this one inside your converter method. After you made this, it is necessary to convert each character inside your Roman string. So you can go ahead by creating a switch-function, which can be used inside of a for-loop.
public static int convertCharacter(String romanNumber, int position) {
char c = romanNumber.charAt(position);
switch (c) {
case 'm':
return 1000;
case 'd':
return 500;
case 'c':
return 100;
case 'l':
return 50;
case 'x':
return 10;
case 'v':
return 5;
case 'i':
return 1;
default:
return 0;
}
}
And due to fact that you are new to Java, I will show you, how the converter method could be written. This one is not the best solution, but it worked for me. Using this one, it will also be possible to convert numbers like "MCMXCIX".
I deleted the comments. So try to understand what the code does. Otherwise you won't learn from it.
public static int convertRomanNumber(String romanNumber) {
romanNumber = romanNumber.toLowerCase();
if (!isValid(romanNumber)) {
System.out.println("Invalid character detected");
System.exit(0);
}
int result = 0;
int currentNumber;
int nextNumber;
for (int i = 0; i < romanNumber.length(); i++) {
currentNumber = convertCharacter(romanNumber, i);
if (i < romanNumber.length() - 1) {
nextNumber = convertCharacter(romanNumber, i + 1);
if (nextNumber > currentNumber) {
result += currentNumber * -1;
} else {
result += currentNumber;
}
} else {
result += currentNumber;
}
}
System.out.println("Your input: " + romanNumber.toUpperCase());
return result;
}
I hope it helps you for the future.
All the best.
First I use toLowerCase() to lower case the user input, then use matches() to check whether the user input is equal to the character of M D C L X V I.
String user_input = "M";
if (user_input.toLowerCase().matches("m|d|c|l|x|v|i")){
System.out.println("Matches");
}
you can use this:
if(roman.matches(".*[0-9].*") ||
!roman.matches("[MDCLXVI]"))
this for case insensitive:
if(roman.matches(".*[0-9].*") ||
!roman.matches("(?i)[MDCLXVI]"))

Password verifier problems

I am trying to complete my programming assignment, I have to create a "Password verifier" that has 1 uppercase, 1 lowercase, 1 number, and 1 special character. If invalid, it must show "invalid" plus the rule that it has shown as false. The problem I have, is not an error message, but I always get a positive response, plus all the violated rules, plus it reads them twice. Little help here?
import java.util.Scanner;
public class PasswordVerifier {
public static void main(String[] args) {
System.out.println("Password Verifier");
System.out.println("Enter a password that meets the following rules: ");
System.out.println("-Must be at least 8 characters long" + '\n' +
"-Must contain at least 1 lower case character" + '\n' +
"-Must contain at least 1 upper case character" + '\n' +
"-Must contain at least 1 numeric digit" + '\n' +
"-Must contain at least 1 special character from the set: !##$%^&*" + '\n' +
"-Must not contain the word 'and' or the word 'end'");
String password;
String contains1 = "and";
String contains2 = "end";
String special = "!##$%^&*";
Scanner stdIn = new Scanner(System.in);
boolean digit = false; //Has at least 1 digit
boolean upper = true; //Has at least 1 upper case letter
boolean lower = true; //Has at least 1 lower case letter
boolean hasspecial = true; //Has at least 1 special character
boolean length = true; //Has at least 8 digits
boolean endand = true; //Does not contain end or and
boolean valid = false; //Is the password valid?
System.out.println("Enter password: ");
password = stdIn.nextLine();
int result;
result = password.indexOf(contains1);
if (result == -1) {
System.out.println("");
} else {
System.out.println("Must not contain the word 'and'");
}
int result2;
result2 = password.indexOf(contains2);
if (result2 == -1) {
System.out.println("");
} else {
System.out.println("Must not contain the word 'end'");
}
if (password.length() < 8) {
System.out.println("Must be at least 8 characters long.");
} else {
System.out.print("");
}
for (int i = 0; i < password.length(); i++) {
if (!(Character.isUpperCase(password.charAt(i)))) ;
{
upper = false;
valid = false;
i++;
}
if (!(Character.isLowerCase(password.charAt(i)))) ;
{
lower = false;
valid = false;
i++;
}
if (!(Character.isDigit(password.charAt(i)))) ;
{
digit = false;
valid = false;
i++;
}
if (!(password.matches(special))) ;
{
hasspecial = false;
valid = false;
}
if (upper != true) {
System.out.println("Must contain an upper case letter.");
}
if (lower != true) {
System.out.println("Must contain a lower case letter.");
}
if (digit != true) {
System.out.println("Must contain a numeric digit.");
}
if (hasspecial != true) {
System.out.println("Must contain a special character.");
}
if (valid) {
System.out.println("Valid.");
} else if (valid != true) {
System.out.println("Invalid.");
}
}
}
}
One thing. All your if lines are wrong.
You are adding a ';' after the if. That means, if the if condition is met, do nothing, then always execute the following lines.
Another thing, when you do
if (!(password.matches(special))) {
hasspecial = false;
valid = false;
}
You are asking for the password to match the string "!##$%^&(asterisk)", which it probably doesn't. So, since you are assuming that the string contains a special character, hasspecial will always be true. You want to write something like password.matches(".(asterisk)[!##$%^&*].(asterisk)) (Probably escaping some characters).
Finally, you are saying if a letter doesn't meet a condition, set the marker to false. So, if the following letter does meet the condition, the marker will still be false. You should usually approach this kind of problems by assuming that all of the conditions are false and then setting the markers to true once the condition is met.
Note: I wrote (asterisk) instead of *, becasue the text gets highlighted and I don't know how to escape it :(

Categories

Resources