Stack Matching Output Error - java

I was wondering if I could get some assistance, I'm having issues with this created class the output is incorrect. Any help would be appreciated:
import java.util.*;
public class Comparison {
public static void main(String[] args) {
Stack<Character> stack = new Stack<>();
System.out.print("Please enter arithmetic expression: For example, the expression {25 + (3 – 6) * 8}");
Scanner input = new Scanner(System.in);
{
String capture = input.next();
for (int i = 0; i < capture.length(); i++) {
char p = capture.charAt(i);
if (p == '(' || p == '{' || p == '[' || p == ')' || p == '}' || p == ']') {
stack.push(p);
}
char r = stack.peek();
if (p == '{' && r == '}' || p == '(' && r == ')' || p == '[' && r == ']') {
stack.pop();
System.out.print("Arithmetic Expression: has matched symbols. ");
} else {
System.out.print("Arithmetic Expression: has mismatched symbols. ");
}
}
}
}
}
Output:
Please enter arithmetic expression: For example, the expression {25 + (3 – 6) * 8}
{25 + (3 – 6) * 8}
Arithmetic Expression: has mismatched symbols. Arithmetic Expression: has mismatched symbols. Arithmetic Expression: has mismatched symbols. BUILD SUCCESSFUL (total time: 6 seconds)
Expected Output:
The expected output should be only the symbols in this case the output should read Arithmetic Expression: has matched symbols: (), {} as the code is popping once a match is found. The numeric values are of no concern. But If there are no matches - Arithmetic Expression: has mismatched symbols. (Then symbols).

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).

input character inside a while loop with validation

System.out.print("Enter the operator (+ - X /): ");
operator = input.next();
char c=operator.charAt(0);
while (c != '+' && c != '-' && c != '*' && c != '/'){
System.out.println("Operator doesn't match. Try again.");
System.out.print("Enter the operator (+ - X /): ");
input.next().charAt(0);
}
Here, I want an input character value from keyboard which will be only symbols just (+ - * /) inside a while loop. if the sign is not match the while loop will be running.
Here, the while loop is working but the character is not checked. So, while loop continuously works with-
System.out.println("Operator doesn't match. Try again.");
System.out.print("Enter the operator (+ - X /): ");
In the last line of your while loop, you are retrieving an user input, but not storing it anywhere. You should do like that:
c = input.next().charAt(0);
If you want to do something fancy, you could also try using the do-while loop, like below:
char c;
do {
System.out.println("Enter a operator (+ - * /):");
c = input.next().charAt(0);
} while(c != '+' && c != '-' && c != '*' && c != '/');

Infix to Postfix

I am trying to convert infix to postfix.For example :
"20 + 2 * 3 + (2*8 + 5)* 4" ->20 2 3 * + 2 8 * 5 + 4 * +
here is my code :
Stack<Character> s = new Stack<Character>();
String postfix = "";
boolean enter = true;
String infixExpr = "20 + 2 * 3 + (2*8 + 5)* 4";
for(int i = 0;i<infixExpr.length();i++){
if(Character.isDigit(infixExpr.charAt(i)) == true){
postfix = postfix + infixExpr.charAt(i);
}
if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-'){
if(s.isEmpty() == true){
s.push(infixExpr.charAt(i));
}
else{
if(s.peek() == '*' || s.peek() == '/' || s.peek() == '+' || s.peek() == '-'){
while(s.isEmpty()== false){
postfix = postfix + s.pop();
}
s.push(infixExpr.charAt(i));
}
else{
s.push(infixExpr.charAt(i));
}
}
}
if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ){
if(s.isEmpty() == true){
s.push(infixExpr.charAt(i));
}
else{
if(s.peek()== '+' || s.peek() == '-' || s.peek() == '('){
s.push(infixExpr.charAt(i));
}
else if(s.peek() == '*' || s.peek() == '/'){
while(s.isEmpty()== false){
postfix = postfix + s.pop();
}
s.push(infixExpr.charAt(i));
}
}
if(infixExpr.charAt(i) == '('){
s.push(infixExpr.charAt(i));
}
if(infixExpr.charAt(i) == ')'){
while(enter){
if(s.peek() == '('){
enter = false;
}
else{
postfix = postfix + s.pop();
}
}
}
}
}
As it is written at the top I suppose to get "20 2 3 * + 2 8 * 5 + 4 * +" but I get "2023*+28*+54" which is wrong and I revised the code many times and still I cant see the problem. It would be great if anybody could help.
Spaces
You are not putting any spaces on your postfix variable. You are only checking if the current character is one of the "interesting" characters (digits, operators), but not whether it's a space. As a result, if the current character is a space, you just skip it and you don't copy it to the postfix.
Since the only things that you put in the postfix are characters that you have checked, you end up with no spaces at all.
You can solve it like this:
Add a boolean called inNumber, set it to true at first.
Whenever you process a digit, before you add it to postfix, check if inNumber is true. If so, add a space first.
If you have just processed a digit, set inNumber to true.
If you are processing an operator, set inNumber to false.
Whenever you add any operator to the stack, add a space first.
The idea about this inNumber is that digits that all belong to the same number should not have spaces between them. But if the digit is added to postfix after we have processed an operator in the previous round, then it belongs to a new number, so there should be a space there.
So basically, your digit handling code should look like:
if(Character.isDigit(infixExpr.charAt(i)) == true){
if ( ! inNumber ) {
postfix += " ";
}
postfix = postfix + infixExpr.charAt(i);
inNumber = true;
}
And in every if that indicate an operator you should have inNumber = false.
And every place where you add an operator to postfix should look like:
postfix = postfix + " " + s.pop();
Handling parentheses
Your other problem is the handling of ().
First, you put the code that checks for ( and ) inside the if for * and /. Of course, if the character at the i position is * or /, it is not a ( or a ) so this code is never called.
So you should move the if for parentheses outside, to the same level of the if on numbers and operators.
Also, your use of enter is wrong. If you have parenthesis inside parenthesis, like ( 3 + ( 5 + 7 ) ), then at the first ) you will go back all the way to the parenthesis after the 5, which is OK. But then enter will become false and you will not process the external pair correctly. This is also true for (3 + 5 ) * ( 7 + 2 ) because you are not setting enter to true again after the beginning of the program.
Instead of using enter, you should pop what's on the stack and check if it was a (:
if(infixExpr.charAt(i) == '('){
inNumber = false;
s.push(infixExpr.charAt(i));
}
if(infixExpr.charAt(i) == ')'){
inNumber = false;
char popped;
while ( ( popped = s.pop() ) != '(' ) {
postfix = postfix + " " + popped;
}
}
Unpopped operators
Finally, you finish when you completed scanning the input. But at this point you will still have operators waiting on the stack! You have to pop them all and add to postfix. So after the loop you should have:
while ( ! s.isEmpty()) {
postfix += " " + s.pop();
}
Additional remarks:
It would be better and more clear if instead of using all those if statements, you used a switch statement.
There is no point in comparing a boolean expression to true. The proper way to write if (s.isEmpty() == true) is just if (s.isEmpty()), and instead of s.isEmpty() != true use ! s.isEmpty().
You are not doing any syntax checking. I am not sure if that's because this is homework, but in real life you should check that every ( is matched by a ), that every operator has two operands, and also handle negative numbers that may have a - in the beginning.
The issue is that you are not adding spaces. You cannot, however, simply add a space in between each number. You have to make sure the spaces are not being added in between the digits of a whole number. To solve this, I simply added a postfix += " "; after the if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-')and again after if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ). The logic behind this is that once you encounter an operator, you know that everything before the operator was the number. Now when I run the program, the output is 20 2 3 *+2 8 *+5 4. There are still a few spaces that need to be added between the operators, but I'll let you handle that.
Modified code:
if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-'){
postfix += " ";
...
if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ){
postfix += " ";
here is my code for your answer
#include<stack>
#include<iostream>
using namespace std;
bool high(char a,char b)
{
if(b==' ')
return true;
else if(a==b)
return false;
else if(a=='/')
return true;
else if(a=='*'&&b!='/')
return true;
else if(b=='/')
return false;
else if(a!='/'&&b=='*')
return false;
else if(b=='-')
return true;
else if(a=='-'&&b!='(')
return false;
else if(b=='(')
return true;
else if(a=='(')
return true;
else if(a==')')
return false;
}
main()
{
int k=0;
string s;
stack<char>s1;
s1.push(' ');
char ch;
while(cin>>ch)
{
if(ch=='(')
{
k=1;
s1.push(ch);}
else if(ch>47&&ch<58)
s.push_back(ch);
else if(high(ch,s1.top()))
s1.push(ch);
else if(!high(ch,s1.top())&&ch!=')')
{
while(!s1.empty()&&!high(ch,s1.top()))
{
s.push_back(s1.top());
s1.pop();
}
s1.push(ch);}
else if(ch==')')
{
while(!s1.empty()&&s1.top()!='(')
{
s.push_back(s1.top());
s1.pop();
}
s1.pop();
k=0;
}
}
while(!s1.empty())
{
s.push_back(s1.top());s1.pop();
}
cout<<s;
}

Validate a string contains only certain characters in java

Ok, what I am trying to do is take a user input in infix notation and translate it to postfix and then evaluate it. I have that already completed.
What I am struggling with, is for the user input I need to validate that it only contains the following: (), 0-9, +, -, *, /, %
Each character will be separated by a space, so here is a potential valid input:
( 3 + 4 ) * 5 / ( 6 - 7 )
I have created an InvalidCharacterException that I wish to throw if the user string contains anything other than those characters.
Here is what an invalid input would look like:
3 - 5 ^ 5
The ^ would be an invalid character and then I would throw new InvalidCharacterException and ask for a new input.
I will also say I have looked at a ton of regex samples, and to be honest I don't understand what they're doing.
EDIT:
Ok, this is what I ended up implementing because I don't really understand anything else. Any advice on a simpler way?
for(int i = 0; i <= infix.length(); i++){
if(infix.charAt(i) == '(' || infix.charAt(i) == ')' || infix.charAt(i) =='+'
|| infix.charAt(i) =='-' ||infix.charAt(i) == '*' ||infix.charAt(i) == '/'
||infix.charAt(i) == '%' ||infix.charAt(i) ==' ' ||infix.charAt(i) == '0'
||infix.charAt(i) == '1' || infix.charAt(i) =='2' || infix.charAt(i) =='3'
||infix.charAt(i) == '4' ||infix.charAt(i) == '5' ||infix.charAt(i) == '6'
||infix.charAt(i) == '7' || infix.charAt(i) =='8' ||infix.charAt(i) == '9'){
}else{
throw new InvalidCharacterException(infix.charAt(i));
}
}
Infix is the variable name of my user input as a StringBuffer.
You can use a Scanner to validate your string:
Scanner scanner = new Scanner(string);
String validationResult = scanner.findInLine("[^0-9()+\\-*\\/%]+");
if (validationResult != null) {
// Invalid character found.
throw new InvalidCharacterException("Invalid character: " + validationResult);
}
The findInLine method returns a String with the characters that match the regex and the regex looks for any character not valid in your validation. The findInLine only returns a non null String when there are any invalid characters in the String.
I would suggest you use a Scanner (for an example) and then loop over each character (in each token) and throw your Exception if your criteria are met (e.g. look at Character.isDigit) or just write your own method to test against acceptable characters (e.g. is char is contained in"()0123456789+-*/%").
In your code this is probably better because it does the same thing.
Btw it probably should be i < infix.length() not <=
for(int i = 0; i < infix.length(); i++){
char x = infix.charAt(i);
if(!(Character.isDigit(x) || x == '/' || x == '*' ||
x == '+'|| x== '-' || x=='%' || x == '\n'))
throw new InvalidCharacterException(x);
/* what you want to do if valid*/
}

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