Evaluating a single char in an if statement: C++ - c++

I am having some troubles with my if loop.
First off I have I assigned char sign.
void evaluate_ps(istream& input)
{
char sign;
input >> sign;
cout << sign << endl;
check(sign);
}
That prints / so my sign has the value '/'
Then I go to my void check(char operation) function
void check(char operation)
{
if(operation != '-' || operation != '+' ||
operation != '*' || operation != '/')
{
return false;
}
else return true;
}
and it's returning false... WHY!!!! I can't seem to figure this out.
Thanks everyone.

This happens because you are using the || (OR) operator. When operation is / the check operation != '-' returns true. Since || is short circuited, the entire expression returns true.
Change it to && (AND):
if (operation != '-' && operation != '+' &&
operation != '*' && operation != '/')
Another way to write this is:
if (!(operation == '-' || operation == '+' ||
operation == '*' || operation == '/'))

You probably meant all your || to be &&:
if(operation != '-' && operation != '+' &&
operation != '*' && operation != '/')
Otherwise, it will always enter the if-statement since a character will always not equal one of 4 different things.

The if statement is responding to the / not equaling one of the other values
Think about "or" even in a general sense
if blue is not green or is not red or is not blue say nope
you would need to do something like the following:
if (operation != '+' && operation != '-' && operation != '/' && operation != '*') {
return false;
}
return true;
this way its like this
if blue is not green and is not red and is not blue say nope

Related

while loop runs even if condition isnt true

i am trying to make a calculator using c++, im trying to implement error handling, so if the user enters a non arithmetic operator, it will tell the user to please enter an operator, using a while loop. the problem is, even when the user enters an operator on the first run through, the while loop still executes.
I have tried not putting a space between while, and the perinthesis, also, i tried not using a variable, and just putting all the conditionals to trigger the loop.
string getop()
{
string op;
int check = 1;
cout << "Enter an operator (+ - / *): ";
cin >> op;
if ((op != "+") || (op != "-") || (op != "/") || (op != "*"))
{
check = 0;
}
while (check == 0) // while the input is not a valid operator
{
cout << "Invalid operator, please enter a valid operator: ";
cin >> op;
if ((op == "+") || (op == "-") || (op == "/") || (op == "*"))
check = 1;
}
return op;
}
the problem is, even when the user enters an operator on the first run through, the while loop still executes.
Try:
(op != "+") && (op != "-") && (op != "/") && (op != "*")
Operator || is or operator (alternative, one or another is enough). You want operator &&, which forces all conditions to be true together.
You have a logic error:
if ((op != "+") || (op != "-") || (op != "/") || (op != "*"))
this will always yield true no matter what op is.
You want:
if ((op != "+") && (op != "-") && (op != "/") && (op != "*"))
A very good practise is to name your logical events. Also, AND chaining negations is rather unintuitive (and also unreadable). So an even better alternative would be:
bool is_valid = (op == "+") || (op == "-") || (op == "/") || (op == "*");
if (!is_valid)
check = 0;
You also shouldn't use namespace std; - you can read here why.
You want to use AND (&&), not OR (||):
if ((op != "+") && (op != "-") && (op != "/") && (op != "*"))
{
check = 0;
}
Your problem is right here:
if ((op != "+") || (op != "-") || (op != "/") || (op != "*"))
{
check = 0;
}
Suppose op is assigned a value of "+", that would mean that these conditions all evaluate to true: op != "-", op != "/", op != "*".
Since you are using the OR (||) operator, check will be assigned a value of 0 if any of those conditions are true. In fact, one of those four conditions will always be true no matter what value op has.
You should use AND (&&) instead so that check is assigned 0 when all of the conditions are true:
if ((op != "+") && (op != "-") && (op != "/") && (op != "*"))
{
check = 0;
}
when you have a chain of assertions joined by &&, normally the negation consists in negate all the assertions and change all the && operators by || or viceversa.
You changed all the asserrtions, negating them, but you forgot to change the || by &&.
Look for Demorgan's theorem in Google.

infix postfix conversion c++, can't seem to get the right answer

so I've working on an assignment converting infix format to postfix format using a stack for the operators, for the digits of the infix notation, the code worked fine, but for the operators, it doesn't work, because the stack is initially empty when I start it, so it can't go into the while loop, but I don't know how to fix this logical error.
void calculator::convertInputIntoPostfix(){
stack S;
for(int i=0;i<mInfixInput.length();i++){
if(mInfixInput[i]>='0' && mInfixInput[i]<='9'){
mPostfixOutput+=mInfixInput[i];
}
else if(isOperator(mInfixInput[i])){
while
(!S.isEmpty()
&&hasHigherPrecedenceThan(S.top(),mInfixInput[i])==true){
mPostfixOutput += S.top();
S.pop();
}
S.push(mInfixInput[i]);
}
}
while(!S.isEmpty()){
mPostfixOutput += S.top();
S.pop();
}
}
bool calculator::isOperator(int c) const
{
return ((c == '+') ||
(c == '-') ||
(c == '*') ||
(c == '/') ||
(c == '^'));
}
bool calculator::hasHigherPrecedenceThan(int aLHS, int aRHS) const
{
if ((aRHS == '+' || aRHS == '-') &&
(aLHS == '*' || aLHS == '/' || aLHS == '^')) {
return true;
}
if ((aRHS == '+' || aRHS == '-' || aRHS == '*' || aRHS == '/') &&
(aLHS == '^')) {
return true;
}
if (aLHS == '^' && aRHS == '^') {
return true;
}
return false;
}
The cases not given above(like () spaces and commas) can be ignored, and the infix is taken by input in the main. the stack is a linked list stack. with the value being an integer.
the outputs for 2+3*3*3(desired answer:233*3*+) I've been getting is 2333**+, as it is not even entering the while loop I've written, it is just storing the values into the stack and at the end outputing it.
2333**+ might be unexpected, but it isn't actually wrong, just wrongly associative.
The way you're computing precedence, you're telling the algorithm that the case where aRHS == '*' && aLHS == '*' is false, i.e. that the operator isn't left-associative. It is. Ditto for all other cases where the operators are equal, except ^, which you are wrongly making left-associative when it is right-associative.
It is customary to use a table rather than an if-else chain when determining predence in this algorithm, and to test for >=, not >, in terms of precedence.
The version of the Dijkstra Shunting-yard algorithm given in Wikipedia has this instead of your condition:
while ((there is a function at the top of the operator stack)
or (there is an operator at the top of the operator stack with greater precedence)
or (the operator at the top of the operator stack has equal precedence and is left associative))
and (the operator at the top of the operator stack is not a left bracket):
pop operators from the operator stack onto the output queue.

converting infix to postfix (assignment operator included) using c++

I was trying to convert to an infix expression to postfix in c++. I have done coding with simple operators /,*,+,- but I am confused about the logic for assignment operator(=). I know it must be given the lowest precedence but for input like A=B=4 or A=(B=2)*2, how can I decide the precedence. My code is written below. (without implementation for assignment operator).
#include <iostream>
#include <stack>
#include <string>
using namespace std;
// Simply determine if character is one of the four standard operators.
bool isOperator(char character) {
if (character == '+' || character == '-' || character == '*' || character == '/' || character=='=') {
return true;
}
return false;
}
// If the character is not an operator or a parenthesis, then it is assumed to be an operand.
bool isOperand(char character) {
if (!isOperator(character) && character != '(' && character != ')') {
return true;
}
return false;
}
// Compare operator precedence of main operators.
// Return 0 if equal, -1 if op2 is less than op1, and 1 if op2 is greater than op1.
int compareOperators(char op1, char op2) {
if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-')) { return -1; }
else if ((op1 == '+' || op1 == '-') && (op2 == '*' || op2 == '/')) { return 1; }
return 0;
}
int main()
{
// Empty character stack and blank postfix string.
stack<char> opStack;
string postFixString = "";
char input[100];
// Collect input
cout << "Enter an expression: ";
cin >> input;
// Get a pointer to our character array.
char *cPtr = input;
// Loop through the array (one character at a time) until we reach the end of the string.
while (*cPtr != '\0') {
// If operand, simply add it to our postfix string.
// If it is an operator, pop operators off our stack until it is empty, an open parenthesis or an operator with less than or equal precedence.
if (isOperand(*cPtr)) { postFixString += *cPtr; }
else if (isOperator(*cPtr)) {
while (!opStack.empty() && opStack.top() != '(' && compareOperators(opStack.top(), *cPtr) <= 0) {
postFixString += opStack.top();
opStack.pop();
}
opStack.push(*cPtr);
}
// Simply push all open parenthesis onto our stack
// When we reach a closing one, start popping off operators until we run into the opening parenthesis.
else if (*cPtr == '(') { opStack.push(*cPtr); }
else if (*cPtr == ')') {
while (!opStack.empty()) {
if (opStack.top() == '(') { opStack.pop(); break; }
postFixString += opStack.top();
opStack.pop();
}
}
// Advance our pointer to next character in string.
cPtr++;
}
// After the input expression has been ran through, if there is any remaining operators left on the stack
// pop them off and put them onto the postfix string.
while (!opStack.empty()) {
postFixString += opStack.top();
opStack.pop();
}
// Show the postfix string at the end.
cout << "Postfix is: " << postFixString << endl;
return 0;
}
Try giving it the same precedence as the operands, and see what you get:
// Simply determine if character is one of the four standard operators.
bool isOperator(char character) {
if (character == '+' || character == '-' || character == '*' || character == '/') {
//|| character=='='
return true;
}
return false;
}
// If the character is not an operator or a parenthesis, then it is assumed to be an operand.
bool isOperand(char character) {
//for =, treat it wth the same rules as the operands; push to output
if (character == '='){
return true;
}
if (!isOperator(character) && character != '(' && character != ')') {
return true;
}
return false;
}

C++ parenthesis matching application

I have to write a function that accepts a string and returns a bool. The string passed in is a series or different parenthesis opened or closed ex.({[]}) and returns whether the 'parens' are well-balanced. This has to be implemented by adding items to a stack. I am getting the following error:
parenMatching_demo.cpp:18:12: error: no match for 'operator==' in 'c
== '('
The psudocode is:
matcher(expression)
for each character in expression
if the character is an opener
push on stack
else if the character is a closr
if stack is empty return false
if the (opener at) the top of the stack does not match the closer
return false
pop the stack
if the stack is not empty return false
return true
This is what I have.
template <typename T>
bool parenMatching(string c) {
stack<string> s;
for (int i = 0; i < s.size(); i++) {
if (c == '(' || c == '[' || c == '{' || c == '<')
s.push(c);
else if (c == ')' || c == ']' || c == '}' || c == '>') {
if (s.empty()) return false;
if (s.top() != '(' || s.top() != '[' || s.top() != '{' || s.top() != '<')
return false;
s.pop();
}
}
}
One problem is the type of the stack, it should be
stack<char> s;
Then the for loop, the condition should be
i < c.size()
The next problem is
if (c == '(' || c == '[' || c == '{' || c == '<')
does not compare the character of the string c at i, so you need
const char c2 = c[i];
if (c2 == '(' || c2 == '[' || c2 == '{' || c2 == '<')
If you need help to fix the rest, let me/us know :)
You're comparing a string with a char in your codes that check for the parentheses. You're missing a line where you get the current character you're looking at as you iterate your string - you probably want something like:
char current = c.at(i);
Additionally, you need to fix your stack type as Daniel Frey says in his answer.
edit - he's since changed his to contain this info, so that answer should have everything you need.

Stupid C++ question about if-else

I have this code:
#include <iostream>
using namespace std;
int main()
{ char c='6';
if(c == '+' || '-' || '*' || '^' || '/' || '%')
{
cout<<"good";
}
else {cout<<"bad";}
return 0;
}
I want to write "good" if the char is '+' or '-' etc, and write "bad" if the char is anything else.
But this code writes "good" always with any char.
Where is the problem? Thanks.
if(c == '+' || '-' || '*' || '^' || '/' || '%')
parses to
if( (c == '+') || ('-'!=0) || ('*'!=0 || ('^'!=0) || ('/'!=0) || ('%'!=0))
It will always evaluate to true because '-' is indeed not equal to zero. Of course it's a sort of flaw with the type-safety that a char "degrades" to a boolean and evaluates to true. (The proper type-safe solution would be simply not to compile your code unless you explicitly cast).
What you wanted to know was whether c is one of those values. There are many ways to do that. Apart from an indented if you could use a library feature:
C function strchr:
if( strchr( "+-*^/%", c ) != NULL )
switch statement
switch (c )
{
case '+': case '-': case '*': case '^': case '/': case '%':
// true logic
break;
default:
// false logic
};
regex
(overkill here but purists would like it).
std::bitset
This takes a lot of "setup" but if you have a fixed set of chars and lots of variable chars to see if it exists in the set, this is the quickest way to do it.
// one-time setup
std::bitset<256> myCharSet;
myCharSet.set('+');
myCharSet.set('-');
myCharSet.set('*');
myCharSet.set('^');
myCharSet.set('/');
myCharSet.set('%');
// subsequently
if( myCharSet.test( static_cast<unsigned char>(c) ) )
{
// true logic
}
else
{
// false logic
}
static array
Similar solution to bitset but you don't mind wasting a few bytes.
static bool charset[256] = { false };
static bool init = false;
if( !init )
{
charset['+'] = true; // etc
init = true;
}
if( charset[ static_cast<unsigned char>(c) ] )
{
// true logic
}
else
{
// false logic
}
And you could make a class that does this that initialises from a string of the characters you want to check for (plus some logic as to whether a 0 byte is true or false, if the string you pass is null-terminated).
As with bitset this is constant-time lookup.
There are other options (eg with C++ std::string class using find and std::find) but these will do for now.
Change your if to:
if(c == '+' || c == '-' || c == '*' || c == '^' || c == '/' || c == '%')
or better yet:
switch (c)
{
case '+': case '-': case '*' : case '^' : case '/' : case '%':
cout << "good\n"; break;
default: cout << "bad\n"; break;
}
it should be
if(c == '+' || c == '-' || c == '*' || c == '^' || c == '/' || c == '%')
...
otherwise the expression is always evaluating to true. Any of those characters have a value different from 0, so true for c++.
Simple answer:'-' is the ASCII (the way the computer encodes character) value of that character - which is not 0 therefore it's true (computer's logic).
Same for all the other characters. So we got:
c == '+' || true || true || true || true || true which is always true.
What you should've done:
c == '+' || c == '-' || c == '*' || c == '^' || c == '/' || c == '%'
The mistake was probably you thinking "It needs to be equal to this or that or that or that" and so on. This happened to everyone, just remember that computers don't speak English.