Checking a string for invalid characters - java

I am trying to write a program that takes a string as input.
This string must be an equation with only brackets, operations or digit.
The code I posted below is what I came up with, but when I run it, anything I enter is apparently an invalid string. Can someone please tell what I did wrong?
System.out.println("Enter a string");
String str = s.nextLine(); //s is a Scanner object
int n = str.length();
for(int i = 0; i < n; i++) {
if( !Character.isDigit(str.charAt(i)) || str.charAt(i) != '+'
|| str.charAt(i) != '-' || str.charAt(i) != '*'
|| str.charAt(i) != '/' || str.charAt(i) != '('
|| str.charAt(i) != ')' || str.charAt(i) != '['
|| str.charAt(i) != ']' || str.charAt(i) != '{'
|| str.charAt(i) != '}') {
System.out.println("invalid string, try again: ");
str = s.nextLine();
}
...}

As suggested in the comments, switch || for &&:
if( !Character.isDigit(str.charAt(i)) && str.charAt(i) != '+'
&& str.charAt(i) != '-' && str.charAt(i) != '*'
&& str.charAt(i) != '/' && str.charAt(i) != '('
&& str.charAt(i) != ')' && str.charAt(i) != '['
&& str.charAt(i) != ']' && str.charAt(i) != '{'
&& str.charAt(i) != '}') {
System.out.println("invalid string, try again: ");
str = s.nextLine();
}
Or, to make your code easier to understand:
final String validChars = "0123456789+-*/()[]{}";
for(int i = 0; i < n; i++) {
if(!validChars.contains(str.charAt(i))) {
System.out.println("invalid string, try again: ");
str = s.nextLine();
// potential bug here - i and n are not being reset
}
}
Note: You have a bug where you don't reset the i index or the n length when reading a new line from the scanner in the case where your previous line contained an invalid character (see comment in code above).

if you dont want change all of your code you can that :
System.out.println("Enter a string");
String str = s.nextLine(); // s is a Scanner object
int n = str.length();
if (n > 0) {
for (int i = 0; i < n; i++) {
if (!(Character.isDigit(str.charAt(i)) || str.charAt(i) == '+' || str.charAt(i) == '-'
|| str.charAt(i) == '*' || str.charAt(i) == '/' || str.charAt(i) == '(' || str.charAt(i) == ')'
|| str.charAt(i) == '[' || str.charAt(i) == ']' || str.charAt(i) == '{'
|| str.charAt(i) == '}')) {
System.out.println("invalid string, try again: ");
str = s.nextLine();
n = str.length();
i = -1;//reset i for the new line ( set at -1 for the next i++ of the next loop )
}
}
} else {
System.out.println("empty string ");
}

package hello;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class Characts {
#Test
public void testSwitch () {
assertTrue(isValid("123+321*"));
assertFalse(isValid("A123+321*"));
assertTrue(isValid("123+321*\n")); // don't forget returns and line feeds
}
private boolean isValid(String str) {
for (int i = 0 ; i < str.length(); i++) {
char s = str.charAt(i);
if (Character.isDigit(s)) {
continue;
} else {
switch (s) {
case '+' :
case '-' :
case '*' :
case '/' :
case '(' :
case ')' :
case '[' :
case ']' :
case '{' :
case '}' :
continue;
}
return false;
}
}
return true;
}
}

Related

Why is this counting the number of words incorrectly?

public static void words(String text) {
int numWords = 1;
for (int charNum = 0; charNum < text.length(); charNum++) {
char letter = text.charAt(charNum);
if(charNum + 1 < text.length()) {
char nextLetter = text.charAt(charNum + 1);
if(letter == '.' || letter == ':' || letter == ';' || letter == '?' || letter == '!'|| letter == ' ' || letter == '\n' || letter == '\t') {
if(nextLetter != '.' || nextLetter != ':' || nextLetter != ';' || nextLetter != '?' || nextLetter != '!'|| nextLetter != ' ' || nextLetter != '\n' || nextLetter != '\t')
numWords += 1;
}
}
}
System.out.println("Number of words: " + numWords);
}
The String "Is this_one_long_word or several??? What do you think?? Too much" should print 10 words and "!This uses periods.as.word.delimiters and can be tricky." should print 10 words.
This is the description: A word is sequence of one or more characters delimited by white space or by a sentence terminators (period, colon, semicolon, question mark, exclamation point), whether or not it is an actual English word. White space is defined as a space, tab ( '\t'), a new line character ('\n'), and the end of the String itself. Again this gives some results that may not make sense. For example the text "I_don't_like_to_use_SPACES-EVER!" has a single word: I_don't_like_to_use_SPACES-EVER.
The following line is always true:
if(nextLetter != '.' || nextLetter != ':' || nextLetter != ';' || nextLetter != '?' || nextLetter != '!'|| nextLetter != ' ' || nextLetter != '\n' || nextLetter != '\t')
Change it to:
if(nextLetter != '.' && nextLetter != ':' && nextLetter != ';' && nextLetter != '?' && nextLetter != '!'&& nextLetter != ' ' && nextLetter != '\n' && nextLetter != '\t')
Starting your count to int numwords = 1; will give you an incorrect count. Start at 0.
Your second input is starting with ! which is adding a word to the count.
You have to check if the character after a terminator is a letter or not to avoid this behavior:
public static void words(String text) {
int numWords = 0;
final String wordTerminators = ".:;?! \n\t";
for (int charNum = 0; charNum < text.length() - 1; charNum++) {
char letter = text.charAt(charNum);
char nextLetter = text.charAt(charNum + 1);
if (wordTerminators.contains(letter + "")) {
if (!wordTerminators.contains(nextLetter + "") && !(nextLetter+"").matches("[A-Za-z]"))
numWords += 1;
}
}
System.out.println("Number of words: " + numWords);
}
Here is a cleaner version of my solution:
public static void words(String text) {
int numWords = 0;
String[] splitted = text.split("[.:;?! \\n\\t]+");
for (String word : splitted) {
if (word.length() > 0)
numWords++;
}
System.out.println("Number of words: " + numWords);
}
Both methods outputs are:
Number of words: 10
Number of words: 10
You have invalid conditions in last if (most nested one) - you need to make sure that next character (called nextLetter in your code) is none of the characters you check but you use OR instead of AND conditions there so it's always true (because character cannot be two different characters at the same time).
So you can change this if to:
if(nextLetter != '.' && nextLetter != ':' && nextLetter != ';' && nextLetter != '?' && nextLetter != '!'&& nextLetter != ' ' && nextLetter != '\n' && nextLetter != '\t')
and it will count the words correctly. Make sure that you count also the first word because currently if you start with numWords set to zero, it will print 9 for your example instead of 10 - because first word is not counted. So you should count it as well.
Btw. Your code could be significantly simplified in several ways, you can also use alternative approaches like split function (from String).

How can I make a loop keep going after the first condition returns true

I am trying to write a method that will take a string, convert any letters to an int, and return all the converted ints to main, replacing the letters . I have if statements that convert all the letters to numbers, but I am having trouble making it work with a loop to convert all the letters instead of stopping after the first one. Any help would be appreciated, thanks in advance.
public class PhoneNumberChecker
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
// Get the phone number
System.out.print("Phone number to convert: ");
String phoneNumber = input.nextLine();
// Process each character in the phone number for display
for (int i = 0; i < phoneNumber.length(); ++i)
{
// Get the character
char ch = phoneNumber.charAt(i);
if (Character.isLetter(ch))
ch = (Character.toUpperCase(ch));
else
System.out.print(ch);
}
System.out.println(getNumber(phoneNumber));
input.close();
// end method
}
public static String getNumber(String phoneNumber)
{
for (int i = 0; i < phoneNumber.length(); ++i)
{
char ch = phoneNumber.charAt(i);
ch = Character.toUpperCase(ch);
if (ch == 'A' || ch == 'B' || ch == 'C')
return "2";
else if
(ch == 'D' || ch == 'E' || ch == 'F')
return "3";
else if
(ch == 'G' || ch == 'H' || ch == 'I')
return "4";
else if
(ch == 'J' || ch == 'K' || ch == 'L')
return "5";
else if
(ch == 'M' || ch == 'N' || ch == 'O')
return "6";
else if
(ch == 'P' || ch == 'Q' || ch == 'R' || ch == 'S')
return "7";
else if
(ch == 'T' || ch == 'U' || ch == 'V')
return "8";
else if
(ch == 'W' || ch == 'X' || ch == 'Y' || ch == 'Z')
return "9";
}
return "";
}
}
You want to append the string results to a string that will continue to grow as you iterate over the given phone number.
Create a String variable before your loop, then simply append to that string instead of returning the strings. Then once you're done iterating the phone number you can return the String.
public static String getNumber(String phoneNumber){
String convertedNum = "";
for (int i = 0; i < phoneNumber.length(); ++i)
char ch = phoneNumber.charAt(i);
ch = Character.toUpperCase(ch);
if (ch == 'A' || ch == 'B' || ch == 'C')
convertedNum = convertedNum + "2"; //append to the string
else if(ch == 'D' || ch == 'E' || ch == 'F')
convertedNum = convertedNum + "3";
...
return convertedNum; //then return it at the end
}
You return from the method after the first character was handled. Let's modify your method:
public static String getNumber(String phoneNumber, int i)
{
//for (int i = 0; i < phoneNumber.length(); ++i)
{
char ch = phoneNumber.charAt(i);
ch = Character.toUpperCase(ch);
if (ch == 'A' || ch == 'B' || ch == 'C')
return "2";
else if
(ch == 'D' || ch == 'E' || ch == 'F')
return "3";
else if
(ch == 'G' || ch == 'H' || ch == 'I')
return "4";
else if
(ch == 'J' || ch == 'K' || ch == 'L')
return "5";
else if
(ch == 'M' || ch == 'N' || ch == 'O')
return "6";
else if
(ch == 'P' || ch == 'Q' || ch == 'R' || ch == 'S')
return "7";
else if
(ch == 'T' || ch == 'U' || ch == 'V')
return "8";
else if
(ch == 'W' || ch == 'X' || ch == 'Y' || ch == 'Z')
return "9";
}
return "";
}
Note, that it has an int parameter and the cycle was commented out. Now, let's process a String:
public static function parseString(String input) {
String output = "";
for (int i = 0; i < input.length; i++) {
output += getNumber(input, i);
}
return output;
}
Note, that this is very simple to understand. The thing which makes it simple is the fact that a method is doing a single thing. getNumber gets a number from a String at a given index. parseString parses the String in the way your code suggested. Of course you can modify the initial String if that is the purpose, using setChar, but then the getNumber method should return the char representation of the digits.
As an alternative you could use String.relaceAll instead of checking each char in a nested if-else. Example:
public static String getNumber(String phoneNumber){
String result = phoneNumber.toUpperCase()
.replaceAll("[A-C]", "2")
.replaceAll("[D-F]", "3")
.replaceAll("[G-I]", "4")
.replaceAll("[J-L]", "5")
.replaceAll("[M-O]", "6")
.replaceAll("[P-S]", "7")
.replaceAll("[T-V]", "8")
.replaceAll("[X-Z]", "9");
return result;
}
I would suggest you to use StringBuilder as compared to String as it is preferable performance wise compared to String. The reason is String is immutable. So inside the loop the String object will be created again and again. Whereas StringBuilder is mutable so it is declared only once and then can be operated on by it's reference. You can use it as shown below:
public static String getNumber(String phoneNumber){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < phoneNumber.length(); ++i){
char ch = phoneNumber.charAt(i);
ch = Character.toUpperCase(ch);
if (ch == 'A' || ch == 'B' || ch == 'C')
sb.append("2");
else if(ch == 'D' || ch == 'E' || ch == 'F')
sb.append("2");
else if(ch == 'G' || ch == 'H' || ch == 'I')
sb.append("3");
else if(ch == 'J' || ch == 'K' || ch == 'L')
sb.append("4");
else if(ch == 'M' || ch == 'N' || ch == 'O')
sb.append("5");
}
return sb.toString();
}
You can read about performance of String vs StringBuilder here. Pay attention to switch from concatination(+) to Builder.

how i print vowels and what they are?

Everytime i input my sentence it prints out the outcome each time it goes through the loop. i assume i have to put the printlines outside the loop?
import java.util.*;
public class homework4{
public static void main(String[] args) {
//Scanner
Scanner keyBd = new Scanner(System.in);
System.out.println("Enter a sentence ");
String userIn = keyBd.nextLine();
int count = 0;
String empty= "";
//Code
for (int i = 0; i < userIn.length(); i++) {
char ch = userIn.charAt(i);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') {
count++;
System.out.println("There are " + count + " vowels in this string");
}
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') {
count++;
empty += ch + " ";
System.out.println("The vowels are: " + empty);
}
}
}
}
import java.util.*;
public class homework4{
public static void main(String[] args) {
//Scanner
Scanner keyBd = new Scanner(System.in);
System.out.println("Enter a sentence ");
String userIn = keyBd.nextLine();
int count = 0;
String empty= "";
//Code
for (int i = 0; i < userIn.length(); i++) {
char ch = userIn.charAt(i);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') {
count++;
empty += ch + " ";
}
}
System.out.println("There are " + count + " vowels in this string");
System.out.println("The vowels are: " + empty);
}
}
No need to check condition two times. As you are updating variables (count & empty) in loop, have to print only once after exiting from loop.
you just need to move the print statement outside and put a check condition if the count is still zero then it means there were no vowels and if count is not zero you can print it.
import java.util.Scanner;
public class homework4 {
public static void main(String[] args) {
//Scanner
Scanner keyBd = new Scanner(System.in);
System.out.println("Enter a sentence ");
String userIn = keyBd.nextLine();
int count = 0;
String empty = "";
//Code
for (int i = 0; i < userIn.length(); i++) {
char ch = userIn.charAt(i);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') {
count++;
empty += ch + " ";
}
}
if(count == 0){
System.out.println("There are no vowels in the input string");
}else {
System.out.println("There are " + count + " vowels in this string");
System.out.println("The vowels are: " + empty);
}
}
}
You don't need to test for vowels twice? (and add to count twice), only once:-
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U'){
count++;
empty += ch + " ";
}
And your print statement doesn't need to happen every time you find a vowel:-
for (int i = 0; i < userIn.length(); i++) {
// not in here
}
System.out.println("There are " + count + " vowels in this string\n" + "The vowels are: " + empty);
Additionally...
If statements are ugly here, where there are many conditions. A switch would be easier to read and more efficient:-
switch (ch){
case 'a': case 'A':
case 'e': case 'E':
case 'i': case 'I':
case 'o': case 'O':
case 'u': case 'U':
count++;
empty += ch + " ";
break;
}
Or move the whole condition into a method
public boolean isVowel(char c){
return (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U');
}
and use
if (isVowel(ch)){
//...
}

vowel counter and display the letter

public class vowel {
public static void main(String args[])
{
String sentence;
int vowels = 0, digits = 0, blanks = 0, consonants=0;
char ch;
System.out.print("Enter a String : ");
sentence = TextIO.getln();
sentence = sentence.toLowerCase();
for(int i = 0; i < sentence.length(); i ++)
{
ch = sentence.charAt(i);
if(ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
vowels ++;
else if(ch =='b'|| ch == 'c' || ch == 'd'|| ch =='f' || ch =='g' ||
ch == 'h' || ch =='j' || ch =='k'|| ch =='l' || ch =='m' ||
ch == 'n' || ch =='p' || ch =='q'|| ch =='r' || ch =='s' ||
ch == 't' || ch =='v' || ch =='w'|| ch =='x' || ch =='z' ||
ch == 'y')
consonants ++;
else if(Character.isDigit(ch))
digits ++;
else if(Character.isWhitespace(ch))
blanks ++;
}
System.out.println("Vowels : " + vowels);
System.out.println("Consonants : " +consonants);
System.out.println("Digits : " + digits);
System.out.println("Blanks : " + blanks);
}
}
This program works perfectly in counting, but I wish to add on a function display the word it count
For example, input ABBCC12:
Vowels :1
Input Vowels : A
Consonants :4
Input Consonants : BBCC
Digits :2
Input Digits :12
Can I know what to do next?
Thanks in advance
It looks as though the easiest way that would fit with your current way of working would be to keep hold of a StringBuilder for each type:
vowelsStringBuilder = new StringBuilder();
and then whenever you encounter one, you add it on:
vowelsStringBuilder.append(ch);
At the end, you can then use
String vowelsString = vowelsStringBuilder.toString();
to get the final String containing all the vowels.
In fact, if you do it like this, you don't really need to count them as you go, because you can get the number of vowels at the end with vowelsString.length().

calculate a process with operator precedence

I am trying to calculate an arithmetic expression, which is entered as a string (for example, ( 5+4*5-1/8 ), which will give the result 3). I enter an expression and convert it into an array. First; the result will start with the first element and it will change in the loop. But the problem is operator precedence. How can I use the operator presedence in a loop? Here is my code:
import java.util.Scanner;
public class HesapMakinesi {
private char value[];
private int count;
private Scanner str = new Scanner(System.in);
private String process;
HesapMakinesi() {
System.out.print("Enter the process ");
process = str.next();
//System.out.println(islem);
Initializer(process);
}
private void Initializer(String process) {
count = process.toCharArray().length;
value = new char [count];
int i;
System.arraycopy(process.toCharArray(), 0, value, 0, count);
//System.out.println(value);
if(value[0]=='-' || value[0]=='+' || value[0]=='/' || value[0]=='*' || // A process cannot start with an operator
value[count-1]=='-' || value[count-1]=='+' || value[count-1]=='/' || value[count-1]=='*') {
System.out.println("You have entered a wrong process.Please enter again!!!");
System.out.print("Enter the process: ");
process = str.next();
Initializer(process);
}
for(i=0; i<count; i++) { // A process cannot include a character except operators
if( value[i]!='+' && value[i]!='-' && value[i]!='*' && value[i]!='/' && value[i]!='(' && value[i]!=')' && !Character.isDigit(value[i]) ) {
System.out.println("You have entered a wrong process.Please enter again!!!");
System.out.print("Enter the process: ");
process = str.next();
Initializer(process);
}
}
for(i=0; i<count-1; i++) { // A process cannot have operators sequantially
if( !Character.isDigit(value[i]) && !Character.isDigit(value[i+1]) ) {
if( (value[i] == '+' && value[i+1] == '+' ) || (value[i] == '+' && value[i+1] == '-' ) || (value[i] == '+' && value[i+1] == '*' ) ||
(value[i] == '+' && value[i+1] == '/' ) ) {
System.out.println("You have entered a wrong process.Please enter again!!!");
System.out.print("Enter the process: ");
process = str.next();
Initializer(process);
}
else if( (value[i] == '-' && value[i+1] == '+' ) || (value[i] == '-' && value[i+1] == '-' ) || (value[i] == '-' && value[i+1] == '*' ) ||
(value[i] == '-' && value[i+1] == '/' ) ) {
System.out.println("You have entered a wrong process.Please enter again!!!");
System.out.print("Enter the process: ");
process = str.next();
Initializer(process);
}
else if( (value[i] == '*' && value[i+1] == '+' ) || (value[i] == '*' && value[i+1] == '-' ) || (value[i] == '*' && value[i+1] == '*' ) ||
(value[i] == '*' && value[i+1] == '/' ) ) {
System.out.println("You have entered a wrong process.Please enter again!!!");
System.out.print("Enter the process: ");
process = str.next();
Initializer(process);
}
else if( (value[i] == '/' && value[i+1] == '+' ) || (value[i] == '/' && value[i+1] == '-' ) || (value[i] == '/' && value[i+1] == '*' ) ||
(value[i] == '/' && value[i+1] == '/' ) ) {
System.out.println("You have entered a wrong process.Please enter again!!!");
System.out.print("Enter the process: ");
process = str.next();
Initializer(process);
}
}
}
//sCount();
}
/*private void Count(){
double result,temp;
int i;
for(i=0; i<count; i++) {
if( value[i]!= )
}
}*/
}
That's not how you do it. You need to parse the expression before evaluating it. I suggest you to read the Shunting-yard algorithm.
Following on from my comment... If you're dealing with a simple expression where you can only have numbers and signs +-/* then you can have a simple approach:
split your expression by lowest precedence operators first (+-) remembering the signs.
Compute each piece - as now the precedence isn't important, since everything is of the same level
sum those computed pieces taking into account the sign of the piece from step 1.
In your example, you'll end up with something like this:
(Split by +-) three pieces: (1) 5; (2) 4*5 with sign +; (3) 1/8 with sign -
Compute each of the three pieces: (1) 5; (2) 20; (3) 0.125
Sum the three pieces with their respective signs: 5+20-0.125 = 24.875

Categories

Resources