Simple Calculator Help (C++) - c++

I wrote a very simple calculator program in C++ and it works fine! But can someone explain how I can modify this code such that it will be able to add more than 2 numbers at once?
So instead of doing 2 + 2 for example, I want users to be able to do 2 + 2 + 2. But every time I try, it just adds the first two "2"s and gives 4, no matter how many + 2 you type after it.
Here is the code:
#include <iostream>
using namespace std;
// input function
void Input (float &x, float &y);
float a=1.0, b=1.0, result;
char operation;
int main ()
{
cout << "A simple calculator \n\n";
cin >> a >> operation >> b;
Input (a,b);
cout << result << endl;
system ("pause");
return 0;
}
void Input (float &x, float &y)
{
a = x;
b = y;
switch (operation)
{
case '+':
result = x + y;
break;
case '-':
result = x - y;
break;
case '*':
result = x * y;
break;
case '/':
result = x / y;
break;
default:
cout << "Improper operation. Please input a correct calculation operation: \n";
cin >> a >> operation >> b;
Input (a, b);
}
}
Thanks guys!

Your code is thought so you are asking the input for three elements: 2 numbers and their operator (represented as a character).
Let's say you are taking just one shot. If you want to use more operators and numbers you have to develop a simple parser which should continue acquiring input until a end token is found, probably end of line in your case.
To do this I would change your approach concerning data acquisition and calculation. You have to simple options:
Perform your calculations online: That is, to keep a partial result and update it after each input.
Gather all your input in a data structure representing it and then perform all the calculations.
For example, if you decide to implement the first option, this incomplete code may help you:
float Input (float &x, float &y, char operation)
{
float result;
switch (operation)
{
case '+':
result = x + y;
break;
case '-':
result = x - y;
break;
case '*':
result = x * y;
break;
case '/':
result = x / y;
break;
default:
cout << "Improper operation. Please input a correct calculation operation: \n";
}
return result;
}
...
...
string input;
if(!getline( cin, input ) ) return; //Try to read one line.
istringstream lin( input );
float partial = 0.0;
float a;
char op;
while(lin >> op >> a) partial = Input(partial, a, op);
//At this point, partial should contain your final result

Note: I have not tested cases. Like division by zero. etc
float operate(float a, char operand, float b)
{
float result=0.0;
switch(operand)
{
case '+':
result = (a+b);
break;
case '*':
result = (a*b);
break;
case '/':
result = (a/b);
break;
default:
cout<<"Unknown operand"<<endl;
break;
}
return result;
}
int main()
{
float result=0.0;
char operand;
float a,b;
cout<<"enter a number followed by an operation, followed by a number"<<endl;
while(cin>>a>>operand>>b)
result+=operate(a,operand,b);
cout<<result;
return 0;
}

i wrote a little parser a few weeks ago, you can study my code and maybe (hopefully) you find something usefull.
its not c++, but c, so your compiler should be able to compile it.
the parser parses any statements that could be built by following rules:
<expression> ::= <term>
| <term> "+" <term>
| <term> "-" <term>
<term> ::= <factor>
| <factor> "*" <factor>
| <factor> "/" <factor>
<factor> ::= <number>
| "(" <expression> ")"
<number> ::= ["-"] ["0" .. "9"]*
here is the code, it is pretty much self explaining because it follows the rules defined above:
#include <stdio.h>
#include <stdlib.h>
char next;
void getNext(){
next=getchar();
}
int getNum(){ //get a number
int num=0;
if((next<'0')||(next>'9')){
printf("error: expected number; found %c",next);
exit(-1);
}
while((next>='0')&&(next<='9')){
num*=10;
num+=(next-'0');
getNext();
}
return num;
}
int add(int x){
return x+term();
}
int sub(int x){
return x-term();
}
int multiply(int x){
return x*factor();
}
int divide(int x){
return x/factor();
}
int factor(){
int f=0;
if(next=='('){
getNext();
f=expression();
if(next=')')
getNext();
else{
printf("error \")\" expected; found %c",next);
exit(-1);
}
}else{
f=getNum();
}
return f;
}
int term(){
int val;
val=factor();
while((next=='*')||(next=='/')){
char c=next;
getNext();
switch(c){
case '*': val=multiply(val); break;
case '/': val=divide(val); break;
default: printf("error: (*, /) expected; found %c",next);
exit(-1);
}
}
return val;
}
int expression(){
int sign=1;
int val;
if(next=='-'){
sign=-1;
getNext();
}
val=term()*sign;
while((next=='+')||(next=='-')){
char c=next;
getNext();
switch(c){
case '+': val=add(val); break;
case '-': val=sub(val); break;
default: printf("error: (+, -) expected; found %c",next);
exit(-1);
}
}
return val;
}
int main(void) {
getNext();
printf("%d\n", expression());
return 0;
}
example:
$ gcc main.c -o calc
$ ./calc
1+2+3
6
$ ./calc
(1+2+3)/2
3
$ ./calc
3*(1+2)
9
$ ./calc
-10+20
10
$

Related

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.

how to convert returned ascii arithmetic symbols, so it can be used with operands

How could I use arithmetic operation symbols if its assigned to variable and need to return for evaluation of simple arithmetic problems --> from the way its constructed in the code below. How? or any other suggestions welcomed thanks in advance
int arithmeticType();
int main() {
int arithmeticSymbol = arithmeticType();
int x, y;
int result = 0;
srand(time(NULL) );
printf( "Type is: %d\n", arithmeticSymbol );
//how to get result of (x + y)using arithmeticSymbol?????
printf( "The result %d %d %d", 4, arithmeticSymbol, 3 );
return 0;
}
int arithmeticType() {
int type, token;
printf("Select the type of arithmetic operation to perform:\n"
"\t1. Addition.\n\t2. Subtraction.\n\t3. Multiplication.\n\t"
"4. Mixture of all three. --> ");
scanf("%d", &type);
switch ( type ) {
case 1:
token = '+';
break;
case 2:
token = '-';
break;
case 3:
token = '*';
break;
case 4:
//get random value between 1-3
token = rand() % 3 + 1;
if ( token == 1 ) {
token = '+';
}
else if ( token == 2 ) {
token = '-';
}
else {
token = '*';
}
break;
default:
printf("Wrong input");
break;
}
return token;
}
Write a function to apply the operator. You also need to consider your types - if you just use integers, things like 3/2 may not do what you expect...
If it was me I'd probably use an enum instead of the ASCII operator code.
int getResult(int op1, int op, int op2)
{
int result = 0;
if (op== '+') {
result = op1 + op2;
}
else ...
return result;
}
You would call it like: printf( "The result of %d %c %d is: %d", 4, getOperation, 3, getResult(4, getOperation, 3) ); (note printing the operator as %d wont do what you expect and the name getOperator is very misleading.

how can i convert infix to postfix expression of multi digit operands?

I am able to convert infix to postfix and calculates with one digit but i can't convert to postfix and calculate with N digits. PLz anyone help me! Thanks!!
here is my code with single digit
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
using namespace std;
class infix2postfix
{
public:
void push(int symbol);
int pop();
void infix_to_postfix();
int priority(char symbol);
int isEmpty();
int white_space(char);
int eval_post();
};
char infix[100], postfix[100];
int stack[100];
int top;
int main()
{
infix2postfix ip;
top=-1;
cout<<"Enter infix : ";
gets(infix);
ip.infix_to_postfix();
cout<<"Postfix : "<<postfix<<endl;
cout<<"Result is : "<<ip.eval_post()<<endl;
return 1;
}
void infix2postfix :: infix_to_postfix()
{
int i,p=0;
char next;
char symbol;
for(i=0; i<strlen(infix); i++)
{
symbol=infix[i];
if(!white_space(symbol))
{
switch(symbol)
{
case '(':
push(symbol);
break;
case ')':
while((next=pop())!='(')
postfix[p++] = next;
break;
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
while( !isEmpty( ) && priority(stack[top])>= priority(symbol) )
postfix[p++]=pop();
push(symbol);
break;
default: /*if an operand comes*/
postfix[p++]=symbol;
}
}
}
while(!isEmpty( ))
postfix[p++]=pop();
postfix[p]='\0'; /*End postfix with'\0' to make it a string*/
}
/*This function returns the priority of the operator*/
int infix2postfix :: priority(char symbol)
{
switch(symbol)
{
case '(':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
case '%':
return 2;
case '^':
return 3;
default :
return 0;
}
}
void infix2postfix :: push(int symbol)
{
if(top>100)
{
cout<<"Stack overflow\n";
exit(1);
}
stack[++top]=symbol;
}
int infix2postfix :: pop()
{
if( isEmpty() )
{
cout<<"Stack underflow\n";
exit(1);
}
return (stack[top--]);
}
int infix2postfix :: isEmpty()
{
if(top==-1)
return 1;
else
return 0;
}
int infix2postfix :: white_space(char symbol)
{
if( symbol == ' ' || symbol == '\t' )
return 1;
else
return 0;
}
int infix2postfix :: eval_post()
{
int a,b,i,temp,result;
for(i=0; i<strlen(postfix); i++)
{
if(postfix[i]<='9' && postfix[i]>='0')
push(postfix[i]-'0');
else
{
a=pop();
b=pop();
switch(postfix[i])
{
case '+':
temp=b+a;
break;
case '-':
temp=b-a;
break;
case '*':
temp=b*a;
break;
case '/':
temp=b/a;
break;
case '%':
temp=b%a;
break;
case '^':
temp=pow(b,a);
}
push(temp);
}
}
result=pop();
return result;
}
My Question is: how to get the result for more than 1 digit operand?
I have tried for Single digit, but how could i get for multi-digit numbers?
You are currently pushing the digits on the stack individually, so a numeric value of 10 will be pushed on the stack two symbols: 1 and 0.
In your operator logic, you are popping one symbol from the stack per operand. Multi-digits operands will thus not work and produce completely wrong results.
There are many ways to solve this. For example, you could fuse multiple digits together into the same stack symbol while reading them in (i.e. combine the digit currently processed with the top of the stack if both are digits).
The place to do this would be inside push. Here's how to do this:
void infix2postfix :: push(int symbol)
{
if(top>100)
{
cout<<"Stack overflow\n";
exit(1);
}
if (! isEmpty() && stack[top] >= 0 && stack[top] <= 9) {
stack[top] *= 10;
stack[top] += symbol;
}
else {
stack[++top]=symbol;
}
}
This will work as long as a numeric operand fits inside the range of an int. Bigger numbers will simply overflow.
There will also be problems because numbers cannot be told apart from other stack symbols. With multi-digit numbers, you can now have symbols which have the same int value as an operator. A way to fix this is to assign negative int values to the operator symbols, and non-negative values for the numbers. This will work for your case as your grammar does not seem to have a unary minus.
This approach is also in line with what you do in eval_post, where you push the calculation result on the stack as a single integer value, regardless of how many digits might be contained.
The most powerful but complicated alternative would write a grammar and use a parser generator. I recommend GNU bison. This will completely take over generating the code for the parser, so all you have to do is to write the grammar for your expressions plus the actual infix-to-postfix transformation (which will be trivial with bison). It will also help you detect invalid input easily and provide appropriate error messages.
However, getting started with bison can be hard if you never used it before.

A recursive parser help

I'm supposed to write this c++ that take in 01 and on. for example: 01010101 but not 0,1,10,011,110. Can someone help me figure out what I need to do to fix the problem. Sorry guys the code isn't working right.I pushed ctrl+k and posted the code but everything wasn't in place.
What I was trying to do is that when some enter 1 than it prints invalid. if they enter 0 it prints invalid, if the enter 10 it prints invalid, if they enter 01 it prints valid, if the enter 0101 it prints valid. So 0 always have to come first and always follow by 1. another example: 0101010101 prints valid
Thanks Seth :). I removed the links
[From seth.arnold: I removed commented-out code and indented the code to follow some kind of logical pattern. Feel free to replace this with your code if you wish, indent each line by four spaces to properly format it.]
#include <iostream>
#include<stdlib.h> // for the exit(1) function
using namespace std;
char text[300];
char ToBeChecked;
char lexical(); //identify the characters
void SProd();
void BProd();
int main(){
cout<<"Enter some strings only 1 and 0 (max. 300 characters"<<endl;
cin>>text;
ToBeChecked = lexical(); //identify the character; find the first letter and give it to ToBeChecked
SProd();
if(ToBeChecked == '\0')
cout<<"Valid"<<endl;
else
cout<<"Invalid"<<endl;
cin.get();
return 0;
}
char lexical(){
static int index = -1; //a memory box named index with a value of -1; is static so it won't change.
//is -1 because -1 to 1 is 0; everything move on to next one
index++; //update index
return text[index]; //return the value of index
}
void SProd(){
if(ToBeChecked != '0' ) {
cout<<"Invalid"<<endl;
exit(1);
}
else{
BProd();
ToBeChecked = lexical();
}
}
void BProd(){
if(ToBeChecked != '1')
{
cout<<"Invalid"<<endl;
exit(1);
}
else
SProd();
ToBeChecked = lexical();
}
Have a look in Bjorn Stroustroup's book Programming Principles and Practice using c++ chapter 6-7.
You will have to write the grammar, you need to know how to:
Distinguish a rule from a token
Put one rule after another (sequencing)
Express alternative patterns (alternation)
Express a repeating pattern
(repetition)
Recognize the grammar rule to start
with
For example - you will have to have a token class:
class Token {
public:
char kind; // what kind of token
double value; // for numbers: a value
Token(char ch) // make a Token from a char
:kind(ch), value(0) { }
Token(char ch, double val) // make a Token from a char and a double
:kind(ch), value(val) { }
};
Then Token stream class:
class Token_stream {
public:
Token_stream(); // make a Token_stream that reads from cin
Token get(); // get a Token (get() is defined elsewhere)
void putback(Token t); // put a Token back
private:
bool full; // is there a Token in the buffer?
Token buffer; // here is where we keep a Token put back using putback()
};
Identify default constructor for Token stream:
Token_stream::Token_stream()
:full(false), buffer(0) // no Token in buffer
{
}
Then create a putback() function, you will need that to put back the character you read from the iostream if it is of interest to you, and function who specializes in extraction of that particular character will be called:
void Token_stream::putback(Token t)
{
if (full) throw std::runtime_error("putback() into a full buffer");
buffer = t; // copy t to buffer
full = true; // buffer is now full
}
Then in Token::get() you will have to make the rules what is important to you and what you want to include, omit or throw error:
Token Token_stream::get()
{
if (full) { // do we already have a Token ready?
// remove token from buffer
full=false;
return buffer;
}
char ch;
cin >> ch; // note that >> skips whitespace (space, newline, tab, etc.)
switch (ch) {
case '=': // for "print"
case 'x': // for "quit"
case '(': case ')': case '{': case '}': case '+': case '-': case '*': case '/': case '!':
return Token(ch); // let each character represent itself
break;
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '9':
{
cin.putback(ch); // put digit back into the input stream
double val;
cin >> val; // read a floating-point number
return Token('8',val); // let '8' represent "a number"
}
break;
default:
throw std::runtime_error("Bad token");
}
}
In this version of Token_stream::get() we are interested in numbers, mathematical operators and brackets. So you will have to change that case statement to get either '1' or '0', and ignore everything else, or throw, it is up to you, I don't know what is exactly you need to do.
Then create a grammar function, you will have to establish hierarchy of functions that call one another if you want or example 1 character to be processed in front of the other. But if you only need to read sequentially, you can have only 1 function. anyway, I include 3 functions that are using calculator example where you have +,-,*,/,(,),{,}. As you see this example need to identify what it is in order to call the right function before the other one, eg - multiplication before subscription.
primary() function deals with numbers and parentheses:
// deal with numbers and parentheses
double primary()
{
Token t = ts.get();
switch (t.kind) {
case '(': // handle '(' expression ')'
{
double d = expression();
t = ts.get();
if (t.kind != ')') throw std::runtime_error("')' expected");
return d;
break;
}
case '{':
{
double d = expression();
t=ts.get();
if (t.kind != '}') throw std::runtime_error("'}' expected");
return d;
break;
}
case '8': // we use '8' to represent a number
return t.value; // return the number's value
break;
default:
throw std::runtime_error("primary expected");
}
}
term() function deals with multiplication and division:
// deal with *, /, and %
double term()
{
double left = primary();
Token t = ts.get(); // get the next token from token stream
while(true) {
switch (t.kind) {
case '*':
left *= primary();
t = ts.get();
break;
case '/':
{
double d = primary();
if (d == 0) throw std::runtime_error("divide by zero");
left /= d;
t = ts.get();
break;
}
default:
ts.putback(t); // put t back into the token stream
return left;
}
}
}
expression() deals with addition and subtraction:
double expression()
{
double left = term(); // read and evaluate a Term
Token t = ts.get(); // get the next token from token stream
while(true) {
switch(t.kind) {
case '+':
left += term(); // evaluate Term and add
t = ts.get();
break;
case '-':
left -= term(); // evaluate Term and subtract
t = ts.get();
break;
default:
ts.putback(t); // put t back into the token stream
return left; // finally: no more + or -: return the answer
}
}
}
And finally our calling function:
int callDrill_01(void)
try
{
std::cout << "Welcome to simple calculator." << std::endl;
std::cout << "Please enter expressions using floating-point numbers." << std::endl;
std::cout << "The arithmetic operators available are: + - * / ( ) { } = e(x)it." << std::endl;
double val = 0;
while (cin) {
Token t = ts.get();
if (t.kind == 'x') break; // 'q' for quit
if (t.kind == '=') { // ';' for "print now"
cout << "=" << val << '\n';
}else{
ts.putback(t);
}
val = expression();
}
keep_window_open();
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
keep_window_open();
return 1;
}
catch (...) {
cerr << "Oops: unknown exception!\n";
keep_window_open();
return 2;
}
This should give you an idea of how recursive parser are created. Your head is probably spinning. I suggest you to find that book that I mentioned and read those chapters. It will help you in the future.
#include <iostream>
//#include<stdlib.h> // for the exit(1) function
using namespace std;
char text[300];
char ToBeChecked;
char lexical(); //identify the characters
void SProd();
void BProd();
int main(){
cout<<"Enter some strings (max. 300 characters"<<endl;
cin>>text;
ToBeChecked = lexical(); //identify the character; find the first letter and give it to ToBeChecked
SProd();
if(ToBeChecked == '\0')
cout<<"Valid"<<endl;
else
cout<<"Invalid"<<endl;
cin.get();
return 0;
}
char lexical(){
static int index = -1; //a memory box named index with a value of -1; is static so it won't change.
//is -1 because -1 to 1 is 0; everything move on to next one
index++; //update index
return text[index]; //return the value of index
}
void SProd(){
if(ToBeChecked != 'a' ) {
BProd();
ToBeChecked = lexical();
}
}
void BProd(){
if(ToBeChecked == 'b'){
ToBeChecked = lexical();
SProd();
}
}

validating numerical user input

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