Logic operators in if statments - c++

So i am writing a calculator as an exercise in c++, were you first select operators +, -, * or / by inputting a, s, m or d. The calculator works fine, except for a filter i set up to respond with an error if the user inputs something other than a, s, m or d. The filter is an if statement:
if(Opperator=='a'||'s'||'m'||'d')
{
//some code
}
else
{
//"Operatorfault"
cout <<"opperatorfeil";
}
Even though the "operator" has other char values than those the if statement is suppose to execute, the code within the if statement is still executed. The whole code is below. The outputs and variables are in Norwegian, but i have tried to translate in the comments.
#include <iostream>
using namespace std;
//The calculator function
int Kalkulator(int IN1, int IN2, char Opperator)
{
int Svar;
//Detects witch operator the user choose, and preforms the assigned operation
if(Opperator=='a')
{
Svar=IN1+IN2;
}
if(Opperator=='s')
{
Svar=IN1-IN2;
}
if(Opperator=='m')
{
Svar=IN1*IN2;
}
if(Opperator=='d')
{
Svar=IN1/IN2;
}
//Returns the answer
return Svar;
}
int main()
{
//Input a, s, m or d for addition, subtraction, multiplication or division, respectively
cout <<"Skriv \"a\" for addisjon, \"s\" for subtraksjon, \"m\" for multipliksjon, og \"d\" for divisjon";
cout <<endl;
cout <<endl;
char Opperator;
cin >>Opperator;
cout <<endl;
//Checks if the input is valid
if(Opperator=='a'||'s'||'m'||'d')
{
cout <<"Skriv inn det første tallet du vil gjøre opperasjonen på, trykk derreter enter, og skriv inn det andre";
cout <<endl;
cout <<endl;
int IN1;
int IN2;
cin >>IN1;
cin >>IN2;
cout <<endl;
//"The answer is"
cout << "Svaret er: ";
//Calls the calculator function, and inputs the values it has gathered, then prints the answer
cout <<Kalkulator(IN1, IN2, Opperator);
}
else
{
//"Operatorfault"
cout <<"opperatorfeil";
}
return 0;
}

The error is in your if statement. In C++, when you are comparing the same variable to multiple values, for example if opperator is a, m, s, d, you need to restate the variable for each comparison.
if( Opperator=='a' || Opperator=='s' || Opperator=='m' || Opperator=='d' )
Instead of your current if statement.
Also, as a tip, a switch statement is much better in these cases, you can simply state
int ans;
switch (customerPackage) {
case 'a':
ans = int1 + int2;
case 's':
ans = int1 - int2;
case 'd':
ans = int1 * int2;
case 'm':
ans = int1 / int2;
default:
string ans;
ans = "invalid input";
}
cout <<ans;

This is wrong:
if(Opperator=='a'||'s'||'m'||'d')
you can NOT test for equality (or inequality) like this. The code executes as the equivalent of
if (Operator == (result of boolean ORs))
You have to test for equality individually:
if ((op == 'a') || (op == 's') || etc...)

Why not just break it out like so,
if (Opperator == 'a' ||
Opperator == 's' ||
Opperator == 'm' ||
Opperator == 'd')
{
// Good values
}
else
{
// Bad values
}

if(Opperator=='a'||'s'||'m'||'d')
It checks whether Opperator is equal to 'a', if not then 's' always returns true and so all logic becomes true.
You can use if statement:
if (Opperator == 'a' || Opperator == 's' || Opperator == 'm' || Opperator == 'd') {
// my calc works well
} else {
// again my calc works well
}
OR you can use switch:
switch(Opperator) {
case 'a':
case 's':
case 'm':
case 'd': // do normal operation here
break;
default: // error handle
break;
}

You must test each char for equality:
if(Opperator=='a'||Opperator=='s'||Opperator=='m'||Opperator=='d') {
...execute
} else {
...execute something else
}
If you want to be fancy you can use algorithm::anyOf().
#include <algorithm>
const std::vector<char> validValues{'a','s','m','d'};
if(any_of(validValues.begin(),
validValues.end(),
[&](const char &x) { return x == Opperator; }) {
// good values
} else {
// bad values
}

Related

Inputting 30-something and -Ex42 with an output of 30 and Ex42

I can't understand how I would do this.
The input will be:
3
13894
30-something
-Ex42
and the output needs to be:
13894
30
Ex42
The main assignment is to make a function that converts a duodecimal number into the decimal format. I have figured that part out and don't need help with it. I've basically cut out all the code surrounding the duodecimal conversion and just included the stuff I can't figure out.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int to_decimal(const string& str);
int main () {
string str; // Initializes string str for input
cin.ignore (256, '\n'); //ignores the 3 from the input
while (getline(cin, str)) {
//runs str through to_decimal and outputs
cout << to_decimal(str) << endl;
}
}
int to_decimal(const string& str) {
int f = 0;
string localString; // Initialize local string variable
//sets local string to the same as inputted string
localString = str; //used for local string erasing
//This is the idea I have been working on and I cant figure it out
for (unsigned x = 0; x < localString.length(); x++) {
f = localString.at(x);
if (isdigit(f)) {
} else if (f == 'E'){
} else if (f == 'e') {
} else if (f == 'X') {
} else if (f == 'x') {
} else if (f == '-') {
} else if (f == ' ') {
} else {
f = localString.length() - x;
localString.erase(x, f);
break;
}
}
}
I am a bit confused. You say that you need to convert duodecimal numbers to decimal, however in your sample output only the line that has Ex is converted, yet 30-something stays 30, as if it is not converted - and 30 in duodecimal is 36 in decimal. Same for the number 13894.
Assuming that you really want to convert all of the lines from duodecimal to decimal, you can base your solution on the standard library function std::stoi() which can convert a string from most number bases up to 36. It requires that the digits bigger than 9 are encoded using the letters in alphabetic order - A to Z. So you need to simply convert all you x to a and all you e to b. Example:
int to_decimal(const string& str) {
bool foundDigit = false;
std::string transformedString;
for (auto c : str) {
if (std::isdigit(c) || c == 'E' || c =='e' || c == 'X' || c == 'x') {
foundDigit = true;
// If needed, convert the character.
if (c == 'E' || c == 'e') {
c = 'b';
} else if (c == 'X' || c == 'x') {
c = 'a';
}
transformedString += c;
} else if (foundDigit) {
// Skip everything to the end of the line, if we've already found some digits
break;
}
}
return std::stoi(transformedString, 0, 12);
}
If you just want to extract the characters and then do the conversion yourself, then you can do something like this:
#include <iostream>
#include <string>
#include <sstream>
bool isNumber(const char c)
{
switch (c) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
case 'e':
case 'E':
case 'x':
case 'X':
case '-':
return true;
default:
return false;
}
}
std::string getNumber(std::istream& in)
{
std::stringstream s;
for (char c;in.get(c);)
{
if (isNumber(c)) {
s << c;
break;
}
}
for (char c;in.get(c);)
{
if (!isNumber(c))
break;
s << c;
}
return s.str();
}
int main()
{
std::string bla = "3\n13894\n 30-something\n-Ex42\n";
std::stringstream klaf{ bla };
for (std::string s;(s = getNumber(klaf)) != "";) //<- use a local stringstream as input to test
//for (std::string s;(s = getNumber(std::cin)) != "";) //<- use std::cin for input
{
std::cout << s << '\n';
}
}
This outputs:
3
13894
30-
e
-Ex42
So, not exactly what you were after, but it should at least get you a starting point to improve from. For example, you may want to remove - from isNumber and then change to logic in getNumber to only accept it as the first character in a new number.

Infix to Postfix notation not respecting second set of parentheses

Having trouble getting the correct outcome of
Infix: (A+B)/(C-D) Postfix: AB+CD-/
I keep getting Postfix: AB+C/D-
I do know that the issue is coming from it not being able to pop the last operators from the stack before pushing '(' This is why I added the if statement in the first else if condition. That also doesn't work. What is it exactly that I am doing wrong? Is there another way into tackling this problem?
#include <iostream>
#include <stack>
#include <sstream>
#include <string>
using namespace std;
int precedence(char x) {
int op;
if (x == '(' || x==')')
op = 1;
else if (x == '^')
op = 2;
else if (x == '*')
op = 3;
else if ( x == '/')
op = 4;
else if (x == '+')
op = 5;
else if (x == '-')
op = 6;
return op;
}
int main()
{
string getInfix;
cout << "Infix: ";
getline(cin, getInfix);
stack<char> opStack;
stringstream showInfix;
for (unsigned i = 0; i < getInfix.length(); i++)
{
if (getInfix[i] == '+' || getInfix[i] == '-' || getInfix[i] == '*' || getInfix[i] == '/' || getInfix[i] == '^')
{
while (!opStack.empty() && precedence(opStack.top() <= precedence(getInfix[i]))
{
showInfix << opStack.top();
opStack.pop();
}
opStack.push(getInfix[i]);
}
else if (getInfix[i] == '(')
{
opStack.push(getInfix[i]);
opStack.pop();
if (getInfix[i]=='(' && !opStack.empty())
{
opStack.push(getInfix[i]);
opStack.pop();
}
}
else if (getInfix [i]==')')
{
showInfix << opStack.top();
opStack.pop();
}
else
{
showInfix << getInfix[i];
}
}
while (!opStack.empty())
{
showInfix << opStack.top();
opStack.pop();
}
cout << "Postfix: "<<""<<showInfix.str() << endl;
cin.ignore ( numeric_limits< streamsize >:: max(),'\n');
return 0;
}
You didn't set op
const int precedence(const char x) noexcept(true) {
switch (x) {
case '(': case ')':
return 1;
case '^':
return 2;
case '*':
return 3;
case '/':
return 4;
case '+':
return 5;
case '-':
return 6;
}
return -1;
}
It returns -1 but I'll let you figure that part out.
It doesn't answer the question.
I just stopped after I saw you could be reading garbage values.
The problem comes from this line (!opStack.empty() && precedence(opStack.top() <=precedence(getInfix[i]))
You are popping the last operator you found without checking if you are in a parenthesis statement or not. You need to take parentheses characters into account before adding an operator to the output string.
Not related to your problem but some advices :
indent your code, simplifies visibility and trust me, saves you (and us) time.
Do not push and then pop for (or ) characters, this is just like ignoring them.
You are missing a ) on this line I imagine it's a copy/paste problem : while (!opStack.empty() && precedence(opStack.top() <=precedence(getInfix[i]))
You do realize you test precedence for ( and ) but you are never actually calling that method with that type of character?

How to resolve this runtime-error occurring in Simple Calculator Program - B. Stroustrup's PPP's, Ch. 7?

I'm learning C++ using B. Stroustrup's PPP, 1st edition. I was testing this simple calculator after completing Q9. from the Ch.7 exercises by giving random inputs to the calculator.
I'm using Visual Studio 2013 and this is the complete code of the calculator I'm using -
// This program is an simple calculator
/*
----------------------------------------------------------------------------------------
>>> Grammar used in this program to handle expressions and features <<<
Calculator:
Statement
Quit
Print
Help
Calculator Statement
Print:
";"
Quit:
"q"
Statement:
Declaration
Assignment
Expression
Declaration:
"let" Name "=" Expression
"const" Name "=" Expression
Assignment:
"set" Name "=" Expression
Name:
string-literal-starting-with-alphabet-or-underscore-and-contains-only-alphabets-underscores-&-numbers
Expression:
Term
Expression "+" Term
Expression "-" Term
Term:
Primary
Term "*" Primary
Term "/" Primary
Term "%" Primary
Primary:
Number
Name
"(" Expression ")"
"+" Primary
"-" Primary
"pow(" Primary "," Primary ")"
"sqrt(" Primary ")"
Number:
floating-point-literal
Input comes from cin through Token_stream called ts, in the form of Tokens.
*/
#include "std_lib_facilities.h"
struct Token {
char kind; // kind of Token
double value; // for numbers: value of Token
string name; // for variables: name of variables
Token(char ch) :kind(ch), value(0) { }
Token(char ch, double val) :kind(ch), value(val) { }
Token(char ch, string var) :kind(ch), name(var) { }
};
class Token_stream {
public:
Token_stream() :full(0), buffer(0) { }
Token get(); // get Tokens from Token_stream
void unget(Token t) { buffer = t; full = true; } // putback Token into Token_stream
void ignore(char c); // ignore characters till c is found, including c
private:
bool full; // buffer status
Token buffer; // buffer to store single Token
};
// Token.kind symbolic constants
const char let = '#'; // for variale-declaration
const char set = '#'; // for assignment
const char constant = '!'; // for constant-declaration
const char quit = 'Q'; // quit application
const char print = ';'; // print expression-output
const char number = '8'; // for number
const char name = 'a'; // for variable-name
const char sqroot = 'R'; // square root
const char power = 'P'; // power/order
//const char variabletype = 'v'; // variable type in Variable
//const char constanttype = 'c'; // constant type in Variable
const char help = 'h'; // help - instructions/examples/features
const string declkey = "let"; // declaration keyword, like let x = 2; to declare a new variable x
const string assignkey = "set"; // assignment keyword, like set x = 3; where x is a declared variable
const string quit1key = "quit"; // quit keyword 1
const string quit2key = "exit"; // quit keyword 2
const string quit3key = "q"; // quit keyword 3
const string powerkey = "pow"; // for using power function
const string sqrtkey = "sqrt"; // for using square root function
const string constkey = "const";// for declaring a symbolic constant, not a variable
const string help1key = "H"; // help keyword 1
const string help2key = "h"; // help keyword 2
const string help3key = "help"; // help keyword 3
const string help4key = "HELP"; // help keyword 4
const string help5key = "Help"; // help keyword 5
Token Token_stream::get()
{
if (full) { full = false; return buffer; }
char ch;
cin.get(ch);
switch (ch) {
case '(':
case ')':
case '+':
case '-':
case '*':
case '/':
case '%':
case print:
//case quit:
//case let:
case '=': // during variable/constant-initialization, assignment
case ',': // pow(x , i);
return Token(ch);
case '.':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{ cin.unget();
double val;
cin >> val;
return Token(number, val);
}
default:
if (isalpha(ch) || ch == '_') { // check for alphabet
string s;
s += ch;
while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) s += ch; // store only alphabets, numbers & underscores
cin.unget();
if (s == declkey) return Token(let); // is current statement a variable-declaration?
if (s == constkey) return Token(constant); // is current statement a constant-declaration?
if (s == assignkey) return Token(set); // is current statement an assignment?
if (s == quit1key || s == quit2key || s == quit3key) return Token(quit); // user wants to quit?
if (s == help1key || s == help2key || s == help3key || s == help4key || s == help5key) return Token(help); // user needs help?
if (s == sqrtkey) return Token(sqroot); // square root of expression
if (s == powerkey) return Token(power); // pow(x,i) = x^i = x*x*...*x (i times)
return Token(name, s); // it's a variable name then
}
else if (isspace(ch)){
if (ch == '\n')
return Token(print);
else
return get();
}
error("Bad token");
}
}
void Token_stream::ignore(char c) // ignore all characters till & including c
{
if (full && c == buffer.kind) {
full = false;
return;
}
full = false;
char ch;
while (cin.get(ch))
if (ch == c) return;
}
struct Variable {
string name;
double value;
char type;
Variable(string n, double v, char c) :name(n), value(v), type(c) { }
};
class Table {
public:
double get(string s);
void set(string s, double d);
double declare(string s, double val, char type);
bool is_declared(string s);
private:
vector<Variable> var_table;
};
Table symbol_table;
double Table::get(string s) // get value of declared variable with name s
{
for (int i = 0; i < var_table.size(); ++i)
if (var_table[i].name == s) return var_table[i].value;
error("get: undefined name ", s);
}
void Table::set(string s, double d) // set value of declared variable with name s to d
{
for (int i = 0; i <= var_table.size(); ++i)
if (var_table[i].name == s) {
if (var_table[i].type == constant)
error("set: can't change the value of a constant");
var_table[i].value = d;
return;
}
error("set: undefined name ", s);
}
bool Table::is_declared(string s) // check if a variable with name s is declared
{
for (int i = 0; i < var_table.size(); ++i)
if (var_table[i].name == s) return true;
return false;
}
double Table::declare(string s, double d, char type)
{
if (is_declared(s))
error("declare: variable already exists ", s);
var_table.push_back(Variable(s, d, type));
return d;
}
Token_stream ts;
double expression();
double primary() // Primary:
{
Token t = ts.get();
switch (t.kind) {
case '(': // "(" Expression ")"
{
double d = expression();
t = ts.get();
if (t.kind != ')') error("primary: '(' expected");
return d;
}
case '-': // "-" Primary
return -primary();
case '+': // "+" Primary
return primary();
case number: // floating-point-number
return t.value;
case name: // value of variable with name t.name
return symbol_table.get(t.name);
case sqroot: // sqrt(x) or "sqrt" Primary
{
double d = primary();
if (d < 0) error("negative square root");
return sqrt(d);
}
case power:
{
t = ts.get(); // check for '('
if (t.kind != '(')
error("power_primary: '(' expected");
double d1 = expression();
t = ts.get();
if (t.kind != ',')
error("power_primary: ',' expected");
double d2 = expression();
t = ts.get();
if (t.kind != ')')
error("power_primary: ')' expected");
int i = narrow_cast<int>(d2);
//if (d2 - int(d2) > 0)
// error("power_primary: 2nd argument invalid, must be an integer");
//if (d1 == 0 && d2 == 0)
// error("power_primary: pow(0,0) is undefined");
return pow(d1, i);
}
default:
error("primary expected");
}
}
double term() // Term:
{
double left = primary(); // Primary
while (true) {
Token t = ts.get();
switch (t.kind) {
case '*': // Term "*" Primary
left *= primary();
break;
case '/': // Term "/" Primary
{
double d = primary();
if (d == 0) error("divide by zero");
left /= d;
break;
}
case '%': // Term "%" Primary
{
double d = primary();
int i1 = narrow_cast<int>(left);
int i2 = narrow_cast<int>(d);
if (i2 == 0)
error("term: modulo by zero");
left = i1%i2;
break;
}
default: // return term-value
ts.unget(t);
return left;
}
}
}
double expression() // Expression:
{
double left = term(); // Term
while (true) {
Token t = ts.get();
switch (t.kind) {
case '+': // Expression "+" Term
left += term();
break;
case '-': // Expression "-" Term
left -= term();
break;
default: // return expression-value
ts.unget(t);
return left;
}
}
}
double declaration() // assuming "let" has been found
{
Token t = ts.get();
char type;
type = t.kind;
t = ts.get();
if (t.kind != name) error("declaration: name expected in declaration"); // check if the Token read is a name
string name = t.name;
Token t2 = ts.get();
if (t2.kind != '=') error("declaration: '=' missing in declaration of ", name); // expecting a '=' after variable name
double d = expression(); // everything right so far, get the initial value of the variable
return symbol_table.declare(name, d, type); // store new variable/constant in vector names
}
double assignment() // assuming "set" has been found
{
Token t = ts.get();
if (t.kind != name) // check if the Token read is a name
error("assignment: name expected in declaration");
string var = t.name;
if (!symbol_table.is_declared(var)) // check if the variable is declared or not
error("assignment: can't assign value to an undeclared variable");
t = ts.get(); // check for '='
if (t.kind != '=')
error("assignment: '=' expected in declaration of ", var);
double newval = expression(); // get new value of variable var
symbol_table.set(var, newval); // set new value
return newval;
}
double statement()
{
Token t = ts.get();
switch (t.kind) {
case let: // is it a variable-declaration?
case constant: // is it a constant-declaration?
ts.unget(t);
return declaration();
case set: // or an assignment?
return assignment();
default: // or an expression?
ts.unget(t);
return expression();
}
}
void clean_up_mess()
{
ts.ignore(print); // ignore characters till and including 'print' character
}
const string prompt_str = "> ";
const string result_str = "= ";
void calculate()
{
// Welcome message
cout << " This program is a basic calculator\n"
<< " To know more use - 'help'\n"
<< " To quit use - 'quit' or 'exit'\n\n";
while (true)
try {
cout << prompt_str;
Token t = ts.get(); // get a token
while (t.kind == print) t = ts.get(); // eat all 'print' tokens
if (t.kind == quit) return; // 'quit' token?
else if (t.kind == help){
// Instructions to use calculator
cout << "\n INSTRUCTIONS TO USE -\n"
<< "\t1. Operations supported: +, -, *, /, % (last one for integers only), sqrt(x), pow(x,y) (y is an integer).\n"
<< "\t2. Use expressions like 1+2/3*4-5, followed by " << print << " to terminate expression.\n"
<< "\t3. Use square brackets or parenthesis or both in expressions as usual, for example, (1-2)*{(3-4)/2}.\n";
// Features
cout << "\n FEATURES -\n"
<< "\t1. Evaluate multiple expressions at once. Enter more than one expressions in a line and see them get evaluated at once.\n"
<< "\t2. Use variables for easy calculation. Declare them like this, \"let x = 6;\" or write any expression in place of '6'.\n"
<< "\t3. Assign new values to already declared variables like this, \"set x = 3;\"\n"
<< "\t4. Use constants like 'pi' & 'e' in statements instead of remembering their values.\n"
<< "\t5. Declare your own constants like this, \"const pi = 3.1415\"\n"
<< "\t6. Ask for help anytime, use \"Help\" or \"help\" or \"HELP\" or \"h\" or \"H\"\n"
<< "\t7. Want to quit, just type \"quit\" or \"exit\"\n"
<< "\n";
//continue;
}
else{
ts.unget(t); // some other token was read, so unread it, put it back in Token_stream
cout << result_str << statement() << endl; // read 'statement' from the input stream, and evaluate it, and print its result
}
}
catch (runtime_error& e) {
cerr << e.what() << endl;
clean_up_mess();
}
catch (...){
cerr << "Oops, unknown exception" << endl;
clean_up_mess();
}
}
int main()
{
try {
// pre-defined symbolic constants
symbol_table.declare("k", 1000, constant); // k = 1000 like pi = 3.1415926535(not defined here)
calculate();
char c;
while (cin.get(c) && c != print && c != '\n');
cout << "\n\n You've now exited the program.\n"
<< " Enter x to close this window.\n\n ";
while (cin >> c && c == 'x')
break;
return 0;
}
catch (exception& e) {
cerr << "exception: " << e.what() << endl;
char c;
while (cin >> c && c != print);
return 1;
}
catch (...) {
cerr << "Oops: Unknown exception\n";
char c;
while (cin >> c && c != print);
return 2;
}
}
But I've found that the program gives this error
whenever I provide it input of the form "some_real_number_here e string_starting_with_alphabet", without any whitespace, with last string being optional and it happens with e only and not with any other alphabet (hopefully because I haven't tried each & every combination of numbers & alphabets).
What is this error? How to resolve this?
Here is the library std_lib_facilities.h .
If you're testing the program too, then at the end of every input/expression to the program, have ; for letting the program clean_up_mess() easily.
Hopefully, this is the file mentioned in the error window, isctype.c.
For example -
Input: 2e; or 4easdf123; Output: The above mentioned error
Other weird outputs -
Input: 2e12; Output: 2e+12
Input: 3e1; Output: 30
Edit: It might be the case (discussed in comments) that Token_stream::get() function when trying to read a floating-point number like 2e+11, gives error because of expecting a number whenever >> sees something like this - "number e anything" (without whitespace) and when it finds an alphabet in anything instead of an integer, it throws an exception.

Two Stack Algorithm in C++

novice coder here and I've been asking around how I should go about creating a two stack algorithm for calculating simple expressions (Dijkstra's Two Stack Algorithm) in C++. A quick refresher for anybody that need it:
Two Stack Algorithm:
Value - Push onto value stack
Operator - Push onto operator stack
Left Parenthesis - Ignore
Right Parenthesis - Pop two values from value stack and one value from operator stack and push the result
It appears that using istringstream, which was recommended to me, should allow me to separate the user inputted expression into basic, doubles, and non-doubles. This should allow me to populate my vals and ops stack respectively, however upon debugging, I realized that my vals stack ended up empty at the end (causing a segmentation fault)
I've got no idea what I'm doing wrong, and any help would be appreciated! Keep in mind I am relatively new to coding and my syntax is probably horrible, therefore any type of criticism is welcome.
For reference an input of:
( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )
Should output:
101
Thus far my code looks like this:
stack<string> ops;
stack<double> vals;
string input;
getline(cin, input);
istringstream scanner(input);
while(true){
double num;
scanner >> num;
if(scanner.fail() && scanner.eof()) break;
else if(!scanner.fail()) vals.push(num);
else{
scanner.clear();
string token;
scanner >> token;
if(token == "(") ;
else if(token == "+") ops.push(token);
else if(token == "*") ops.push(token);
/*Add more operations here (Log, sin, cos...)*/
else if(token == ")"){
string op = ops.top();
ops.pop();
if(op == "+"){
double a, b;
a = vals.top();
vals.pop();
b = vals.top();
vals.pop();
vals.push(a+b);
}
else if(op == "*"){
double a, b;
a = vals.top();
vals.pop();
b = vals.top();
vals.pop();
vals.push(a*b);
}
/*Add more operations here*/
}
}
return vals.top();
}
Thank you for your help!
Turns out the problem was with this:
scanner >> num;
if (scanner.fail() && scanner.eof()) break;
else if (!scanner.fail()) vals.push(num);
Changing it to the following fixed the problem:
if (scanner >> num) vals.push(num);
if (scanner.fail() && scanner.eof()) break;
else {
// ...
}
And putting the return statement below the loop also helped.
Live example
Not a straightforward answer to what you asked, but I reworked your example with out the use of stringstreams, which might be confusing to you. You can use the following code as an alternative:
#include <iostream>
#include <string>
#include <stack>
#include <ctype.h>
double parseExpression(std::string const &expr)
{
std::stack<char> ops;
std::stack<double> vals;
std::string num;
for (auto c : expr) {
if (c == '+' || c == '*') {
if(!num.empty()) vals.push(std::stod(num));
num.clear();
ops.push(c);
} else if (c == ')') {
if (!num.empty()) vals.push(std::stod(num));
num.clear();
char op = ops.top();
ops.pop();
switch (op) {
case '+': {
double tmp = vals.top();
vals.pop();
tmp += vals.top();
vals.pop();
vals.push(tmp);
} break;
case '*': {
double tmp = vals.top();
vals.pop();
tmp *= vals.top();
vals.pop();
vals.push(tmp);
} break;
};
num.clear();
} else if(isdigit(c) || c == '.') {
num.push_back(c);
} else if (isspace(c)) {
if (!num.empty()) vals.push(std::stod(num));
num.clear();
} else if(c != '(') {
throw std::runtime_error("Unknown character in expression!");
}
}
return vals.top();
}
int main()
{
std::string expr("( 1.00 + ( ( 2.000000 + 3.00 ) * ( 4.00 * 5.00 ) ) )");
std::cout << expr << " = " << parseExpression(expr) << std::endl;
return 0;
}
HTH

string!! allow letter only for the first character of my rectangle names

I can't get the right output.. please help me..
and it should return false when I put number as the first character for the name
like this ,
Enter the name of the first rectangle: rec 1a
Invalid input. Type 'rec' following by the name or 'stop' if done.
Try again! Enter the name of the first rectangle: rec a
Enter a's bottom left x and y coords: 9 3
Enter a's length and height: 2 8
i am only allow to use these 3, not anything else..
#include <iostream>
#include <string>
#include <vector>
and my code is
bool promptread_rec(const string & prompt, const string & invalid, const string & usedname, string & input, vector<Rectangle> & list)
{
cout << prompt;
getline(cin, input);
if (input == "stop")
{
return true;
}
else if (input.substr(0,4) != "rec ")
{
cout << invalid << endl;
return false;
}
else if (input[4] == '0' || input [4] == '1' || ......)
{
cout << invalid << endl;
return false;
}
else if (list.size() > 0)
{
for (int i = 0; i < list.size(); i++)
{
if (input == list[i].getName())
{
cout << usedname;
return false;
}
}
return true;
}
else
{
return true;
}
}
is there a faster way to do it?? need to avoid all numbers e.g. 0,1,2,3,...,9
From the header cctype, you may use the function isalpha(c) on the first character of the string, like:
string a = "a1234";
assert(isalpha(a.at(0)) == true);
a = "1234";
assert(isalpha(a.at(0)) == true);
Just remember to access a.at(0) only if the string is not empty or else it will throw a std::out_of_range exception
References:
http://www.cplusplus.com/reference/cctype/isalpha/
http://www.cplusplus.com/reference/cassert/assert/
http://www.cplusplus.com/reference/string/string/at/
Since you cannot use any other headers you have to implement your own functions, which is actually simple enough for ASCII characters:
bool IsLetter(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
bool IsDigit(char c) {
return c >= '0' && c <= '9';
}
Using these two helper functions you can write a function to test if a name is valid:
bool IsValidName(const std::string &name);
I leave this for you to implement.