I am creating a simple CLI calculator tool as an exercise. I need to make sure n1 and n2 are numeric in order for the functions to work; consequently, I would like to make the program quit upon coming across a predetermined non-numeric value.
Can anyone give me some direction?
Additionally, if anyone can offer any general tips as to how I could have done this better, I would appreciate it. I'm just learning c++.
Thank you!
The complete code is included below.
#include <iostream>
#include <new>
using namespace std;
double factorial(double n) { return(n <= 1) ? 1 : n * factorial(n - 1); }
double add(double n1, double n2) { return(n1 + n2); }
double subtract(double n1, double n2) { return(n1 - n2); }
double multiply(double n1, double n2) { return(n1 * n2); }
double divide(double n1, double n2) { return(n1 / n2); }
int modulo(int n1, int n2) { return(n1 % n2); }
double power(double n1, double n2) {
double n = n1;
for(int i = 1 ; i < n2 ; i++) {
n *= n1;
}
return(n);
}
void print_problem(double n1, double n2, char operatr) {
cout<<n1<<flush;
if(operatr != '!') {
cout<<" "<<operatr<<" "<<n2<<flush;
} else {
cout<<operatr<<flush;
}
cout<<" = "<<flush;
}
int main(void) {
double* n1, * n2, * result = NULL;
char* operatr = NULL;
n1 = new (nothrow) double;
n2 = new (nothrow) double;
result = new (nothrow) double;
operatr = new (nothrow) char;
if(n1 == NULL || n2 == NULL || operatr == NULL || result == NULL) {
cerr<<"\nMemory allocation failure.\n"<<endl;
} else {
cout<<"\nTo use this calculator, type an expression\n\tex: 3*7 or 7! or \nThen press the return key.\nAvailable operations: (+, -, *, /, %, ^, !)\n"<<endl;
do {
cout<<"calculator>> "<<flush;
cin>>*n1;
cin>>*operatr;
if(*operatr == '!') {
print_problem(*n1, *n2, *operatr);
cout<<factorial(*n1)<<endl;
} else {
cin>>*n2;
switch(*operatr) {
case '+':
print_problem(*n1, *n2, *operatr);
cout<<add(*n1, *n2)<<endl;
break;
case '-':
print_problem(*n1, *n2, *operatr);
cout<<subtract(*n1, *n2)<<endl;
break;
case '*':
print_problem(*n1, *n2, *operatr);
cout<<multiply(*n1, *n2)<<endl;
break;
case '/':
if(*n2 > 0) {
print_problem(*n1, *n2, *operatr);
cout<<divide(*n1, *n2)<<endl;
} else {
print_problem(*n1, *n2, *operatr);
cout<<" cannot be computed."<<endl;
}
break;
case '%':
if(*n1 >= 0 && *n2 >= 1) {
print_problem(*n1, *n2, *operatr);
cout<<modulo(*n1, *n2)<<endl;
} else {
print_problem(*n1, *n2, *operatr);
cout<<" cannot be computed."<<endl;
}
break;
case '^':
print_problem(*n1, *n2, *operatr);
cout<<power(*n1, *n2)<<endl;
break;
default:
cout<<"Invalid Operator"<<endl;
}
}
} while(true);
delete n1, n2, operatr, result;
}
return(0);
}
What you want to do is read a line of input, or a string, then attempt to convert that line to your numeric form. Boost wraps this in lexical_cast, but you don't need that at all. I've answered a question similar to yours twice, here and here. Read those posts to understand what's going on.
Here's the final result:
template <typename T>
T lexical_cast(const std::string& s)
{
std::stringstream ss(s);
T result;
if ((ss >> result).fail() || !(ss >> std::ws).eof())
{
throw std::bad_cast();
}
return result;
}
Use it how I outlined in those posts:
int main(void)
{
std::string s;
std::cin >> s;
try
{
int i = lexical_cast<int>(s);
/* ... */
}
catch(...)
{
/* ... */
// conversion failed
}
}
This uses exceptions. You can make this no-throw like outlined in the links above, by catching the bad_cast exception:
template <typename T>
bool lexical_cast(const std::string& s, T& t)
{
try
{
t = lexical_cast<T>(s);
return true;
}
catch (const std::bad_cast& e)
{
return false;
}
}
int main(void)
{
std::string s;
std::cin >> s;
int i;
if (!lexical_cast(s, i))
{
std::cout << "Bad cast." << std::endl;
}
}
This is good for making Boost's lexical_cast no-throw, but if you're implementing it yourself, there's no reason to waste time throwing and catching an exception. Implement them in terms of each other, where the throwing version uses the no-throw version:
// doesn't throw, only returns true or false indicating success
template <typename T>
const bool lexical_cast(const std::string& s, T& result)
{
std::stringstream ss(s);
return (ss >> result).fail() || !(ss >> std::ws).eof();
}
// throws
template <typename T>
T lexical_cast(const std::string& s)
{
T result;
if (!lexical_cast(s, result))
{
throw std::bad_cast("bad lexical cast");
}
return result;
}
There is more trouble in your code: you're newing everything! Is there a reason for that? Consider if any part of your code throws an exception: now you jump out of main and leak everything. If you stack allocate your variables, they will be guaranteed to destruct.
No need for Boost or writing your own template or forcing yourself to use exceptions vs error codes. cin alone does everything you're asking for.
You can test if ( cin ) or if ( ! cin ) to determine success or failure. One failure (eg, a letter in numeric input) will stop cin from accepting any more input. Then call cin.clear() to clear the error and resume getting input, starting with whatever text caused the error. Also, you can request that a stream throw exceptions on conversion errors: cin.exceptions( ios::failbit ).
So, you can do this:
for (;;) try {
double lhs, rhs;
char oper;
cin.exceptions( 0 ); // handle errors with "if ( ! cin )"
cin >> lhs >> oper; // attempt to do "the normal thing"
if ( ! cin ) { // something went wrong, cin is in error mode
string command; // did user enter command instead of problem?
cin.clear(); // tell cin it's again OK to return data,
cin >> command; // get the command,
if ( command == "quit" ) break; // handle it.
else cin.setstate( ios::failbit ); // if command was invalid,
// tell cin to return to error mode
}
cin.exceptions( ios::failbit ); // now errors jump directly to "catch"
// note that enabling exceptions works retroactively
// if cin was in error mode, the above line jumps immediately to catch
if ( oper != '!' ) cin >> rhs;
// do stuff
} catch ( ios::failure & ) {
cin.clear();
cin.ignore( INT_MAX, '\n' ); // skip the rest of the line and continue
}
This is meant as a demonstration of error handling with iostreams. You can choose to use exceptions or manual testing or both.
You can use input stream object itself to perform simple validation:
What is the best way to do input validation in C++ with cin?
Another interesting approach could be to construct a parser with Boost.Spirit library, though it is an advanced technique heavily exploiting C++ metaprogramming features. If you'd like to try it, check the quick start examples
Probably a lot of C++ guys will hate me for this, but even while C++ has all these new shiny strings and I try to stay with C++ strings as long as possible to feel clean, in this case the simplest and considerably also cleanest thing is to stick with good ol' C:
if (sscanf(input, "%d", &integer) != 1) {
// failure to read number
}
// happily continue and process
Related
I want to give the expression in the form of parenthesis through CIN, like: ()). then, through push & pop operation of the stack, I want the program to print me weather the given expression is BALANCED or NOT. The program works perfectly but only one issue has been found & that is when I enter like ()(, so it tells me that this expression is IMBALANCED which is fine but when I enter like () (, so then it tell me that this expression is BALANCED which is actually not balanced.
#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
char Stack[10];
int top=-1;
void push(char ch)
{
if(top<10)
{
top++;
Stack[top] = ch;
}
else
cout<<"Stack Overflow";
}
void pop()
{
if(top > -1)
{
top--;
}
else
cout<<"Stack Underflow";
}
int show(){
cout<<"It is imbalanced.";
}
int main(int argc, char** argv)
{
int a=0,b=0;
string exp;
cout << "Write down the parenthesis:" ;
cin >> exp;
bool check = true;
for(int i=0; i<exp.length(); i++)
{
if(exp[i]== '(')
{
push(exp[i]);
}
else if(exp[i]== ')')
{
if(top == -1)
{
check = false;
break;
}
else
{
pop();
}
}
}
for(int i=0; i<exp.length(); i++)
{
if(exp[i]=='('){
++a;
}
else if (exp[i]==')')
{
b++;
}
}
if(a>b){
cout<<"\n\nGiven Combination is IMBALANCED";
return 0;
}
if(check == true)
cout<<"\n\nGiven Combination is BALANCED";
else
cout<<"\n\nGiven Combination is IMBALANCED";
return 0;
}
The main comments boil down to:
Don’t use a stack when no stack is needed.
And if you do use one, don’t limit it to an arbitrary fixed depth.
Handle errors and report malformed expressions.
Make sure you get the right input; std::getline() may be less error-prone than input tokenized using the >> operators. Just skip spaces (or whatever insignificant characters are allowed in the input).
using namespace std; is an antipattern and a bad habit.
The basic idea: Calculate the nesting depth as you iterate over the string. It must be zero, ultimately. It must not drop below zero at any point.
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string_view>
using std::size_t;
bool correctly_parenthesized(std::string_view expression) {
size_t depth{0};
for (const auto character : expression) {
switch (character) {
case '(': ++depth; break;
case ')': if (depth) { --depth; break; } else { return false; }
case ' ': break;
default: throw std::invalid_argument("invalid character");
}
}
return depth == 0;
}
int main() {
std::cout << "Write down the parentheses: ";
std::string exp;
std::getline(std::cin, exp);
try {
std::cout << (correctly_parenthesized(exp) ? "YES" : "NO") << std::endl;
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
}
#include<iostream>
#include<stdio.h>
#define MAX 20
using namespace std;
char stk[MAX];
int top=-1;
void push(char c)
{
if(top==MAX-1)
cout<<"Overflow";
else
{
stk[++top]=c;
}
}
char pop()
{
if(top==-1)
{
return '\0';
}
else
return stk[top--];
}
int priority(char ch)
{
if(ch=='(')
return 1;
if(ch=='+'||ch=='-')
return 2;
if(ch=='*'||ch=='/')
return 3;
if(ch=='^')
return 4;
}
int main()
{
char exp[35],*t,x;
cout<<"Enter expression: ";
fgets(exp,35,stdin);
t=exp;
while(*t)
{
if(isalnum(*t))
cout<<*t;
else if(*t=='(')
push(*t);
else if(*t==')')
{
while((x=pop())!='(')
cout<<x;
}
else
{
if(priority(stk[top])>=priority(*t))
cout<<pop();
push(*t);
}
t++;
}
while(top!=-1)
cout<<pop();
return 0;
}
The output for input:
a+b-(c+d/e)
is
ab+cde/+
-
I don't understand why - is on a newline.
I have just started learning c++ and I am trying to implement some programs I did in c using c++. The same code in c works fine. I think there are some holes in my basic c++ knowledge and I would like to fill them up.
std::fgets does not discard the newline in the input stream like getline would. That means exp contains "a+b-(c+d/e)\n" and not "a+b-(c+d/e)". You either need to remove the newline from exp, switch to cin.getline(), or stop your processing loop when it hits the newline.
Try to change fgets to std::cin. And use std::string instead of char*:
#include <iostream>
#include <string>
int main()
{
string exp;
cout << "Enter expression: ";
std::cin >> exp;
auto t = exp.data();
char x;
for(auto &ch: exp)
{
if(isalnum(ch))
cout << ch;
else if(ch == '(')
push(ch);
else if(ch == ')')
{
while((x = pop()) != '(')
cout << x;
}
else
{
if(priority(stk[top]) >= priority(ch))
cout << pop();
push(ch);
}
}
while(top != -1)
cout << pop();
return 0;
}
In addition to the processing of '\n' as mentioned by NathanOliver, your function priority() doesn't return a value when the user entered any other character not checked in the if statements, so the behavior might be undefined.
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
}
I'm new to C++ and working on a simple guessing game where you get 5 tries to guess a number between 1 and 100.
I'm having issues dealing with user inputs.
I've made it so that the program only accepts numbers between 1 and 100, and it ignores characters without crashing. The problem is that when I type in gibberish like 34fa1e8, the loop will run three times, using 34 the first time, 1 the second time, and 8 the last time, instead of ignoring the input like I want it to.
The code im using is here:
int check_guess() {
int guess;
do {
cin >> guess;
if (cin.fail()) {
cin.clear();
cin.ignore();
}
} while (guess < 1 || guess > 100);
return guess;
}
How can I make the program dismiss inputs like these instead of accepting them separately?
You could use getline and stol.
I've given an answer like this before; an explanation can be found here.
You can even extended the solution to check for the specified range:
template <int min, int max>
class num_get_range : public std::num_get<char>
{
public:
iter_type do_get( iter_type it, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long& v) const
{
auto& ctype = std::use_facet<std::ctype<char>>(str.getloc());
it = std::num_get<char>::do_get(it, end, str, err, v);
if (it != end && !(err & std::ios_base::failbit)
&& ctype.is(ctype.alpha, *it))
err |= std::ios_base::failbit;
else if (!(min <= v && v <= max))
err |= std::ios_base::failbit;
return it;
}
};
Now you can imbue the stream with the new locale and you need to restructure your loop to discard valid input. For example:
std::locale original_locale(std::cin.getloc());
std::cin.imbue(std::locale(original_locale, new num_get_range<1, 100>));
int check_guess()
{
int guess;
while (!(std::cin >> guess))
{
std::cin.clear();
std::cin.igore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
Use ifstream::getline to store the input in a char array. Then convert it to an integer using a function like this:
int convertToInteger(char const *s){
if ( s == NULL || *s == '\0'){
return 0;
}
int result = 0, digit = 1000;
while((*s) && (digit > 0)){
if ( *s >= '0' && *s <= '9' ){
result += digit * (*s - '0');
}else{
return 0;
}
++s;
digit /= 10;
}
return result;
}
The reason it works is because it will return 0 in case of failure and that's something your loop's condition will not accept. You also don't have to worry about negative numbers since your loop won't accept them anyways.
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