Clarification on std::cin - c++

This is taken right from The "C++ Programming Language" by Bjarne Stroustrup. I would just like some clarification on how he accumulating the digits into the variable (int number_value). Please don't rip on the code, I didn't write it (Complete code from chapter 6 at bottom of post).
Specifically as the parser is calling the lexer, how is the lexer building up a number by using cin. I believe the answer is in these eight lines, but I would like an explanation of how it works.
if( isalpha( ch ) ) {
(*input).putback( ch );
(*input) >> string_value;
return curr_tok=NAME;
} else {
error( "bad token " );
return curr_tok=PRINT;
}
It appears to me that the first time get_token( ) is called, it puts the full expression_list into cin or whatever input stream input points to (inside get_token( )).
(*input) >> ch;
I know ch is declared as a char, but what happens if you type 123.4+5.432; (assuming input is cin) cin now contains the "string" 123.4+5.432 contained in its stream. Then we move to the switch statement in the lexer (get_token( )). I am assuming: :
ch == 1?
at this point? Next inside the switch statement, we would "fall through" to the '.' case. Here we place '1' back into the stream and write it out to number_value?
(*input).putback( ch );
(*input) >> number_value;
Now number_value = 1, and we return to the parser. Since we found a NUMBER it calls get_token( ) again. And cin operator<< is called again. Wouldn't the next call to (*input)>> number_value place 2 into number value overwriting the 1 (assuming that the input is still 123.4+5.432)? What happens here. I guess I need a better understanding of how streams work. If someone could take the time, and give a brief explanation and point me to a good resource I would greatly appreciated.
Thank you,
Matthew Hoggan
For those that don't have the book, the code is:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sstream>
#include <map>
#include <cctype>
std::istream *input;
double number_value;
int no_of_errors;
std::string string_value;
std::map<std::string,double> table;
enum Token_value {
NAME, NUMBER, END,
PLUS='+', MINUS='-', MUL='*', DIV='/',
PRINT=';', ASSIGN='=', LP='(', RP=')'
};
Token_value curr_tok=PRINT;
double expr( bool );
double term( bool );
double prim( bool );
Token_value get_token( );
double error( std::string s ) {
no_of_errors++;
std::cerr << "error: " << s << std::endl;
return 1.0;
}
Token_value get_token( ) {
char ch = 0;
(*input) >> ch;
switch( ch ) {
case 0: {
return curr_tok=END;
}
case ';':
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
case '=': {
return curr_tok = static_cast<Token_value>( ch );
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.': {
(*input).putback( ch );
(*input) >> number_value;
return curr_tok=NUMBER;
}
default: {
if( isalpha( ch ) ) {
(*input).putback( ch );
(*input) >> string_value;
return curr_tok=NAME;
} else {
error( "bad token " );
return curr_tok=PRINT;
}
}
}
}
int main( int argc, char *argv[ ] ) {
switch( argc ) {
case 1: {
input = &std::cin;
break;
}
case 2: {
input = new std::istringstream( argv[1] );
break;
}
default: {
error(" To many arguments" );
return 1;
}
}
table["pi"] = 3.1415926535897932385;
table["e"] = 2.7182818284590452354;
while( (*input) ) {
get_token( );
if( curr_tok == END ) {
break;
}
if( curr_tok == PRINT ) {
continue;
}
std::cout << expr( false ) << std::endl;
}
if( input != &std::cin ) {
delete input;
}
return 0;
}
double expr( bool get ) {
double left = term( get );
for( ; ; ) {
switch( curr_tok ) {
case PLUS: {
left += term( true );
break;
}
case MINUS: {
left -= term( true );
break;
}
default: {
return left;
}
}
}
}
double term( bool get ) {
double left = prim( get );
for( ; ; ) {
switch( curr_tok ) {
case MUL: {
left *= prim( true );
break;
}
case DIV: {
if( double d = prim( true ) ) {
left /= d;
break;
}
else {
return error( "divide by 0" );
}
}
default: {
return left;
}
}
}
}
double prim( bool get ) {
if( get ) {
get_token( );
}
switch( curr_tok ) {
case NUMBER: {
double v = number_value;
get_token( );
return v;
}
case NAME: {
double &v = table[string_value];
if( get_token( ) == ASSIGN ) {
v = expr( true );
return v;
}
}
case MINUS: {
return -prim( true );
}
case LP: {
double e = expr( true );
if( curr_tok != RP ) {
return error( "')' expected" );
}
get_token( );
return e;
}
default: {
return error( "primary expected" );
}
}
}

The 'trick' is caused by the differing behaviour of the following three lines:
char ch; std::cin >> ch;
std::string string_value; std::cin >> string_value;
double number_value; std::cin >> number_value;
The first just gets a single character, the second and third get multiple characters to build a variable of the correct type.
Strings overload the global operator>> function to provide a version for strings, and this version uses whitespace as the delimiter (if you need to input spaces with your string, you should look into getline).
The double version uses the istream& operator>> (double& val); member function and will read characters only while they make sense in forming a double value.
So, let's say you enter abc. The code cin >> ch will populate ch with the character 'a', removing it from the input stream. You will then detect this with isapha in the default case since it matches none of the other cases.
At that point, you push that character 'a' back on to the input stream so you can re-read it, and execute cin >> string_value which gets the entire string abc, not a single character.
Similarly, if you entered 3.14159, it would be caught by the case '3' check, the character would be pushed back on to the input stream, and cin >> number_value would then get the whole value.

Now number_value = 1, and we return to the parser.
No. (*input) >> number_value; reads-in the whole double, i.e., 123.4 since number_value is of type double. Other than this, you are right.

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.

c++ The evaluation of expression. How to exit the while loop?

I use stack to evaluate an expression.
The most important function is below:
double Expression_Eval()
{
SeqStack<char,100> OPTR;
SeqStack<double,100> OPND;
OPTR.Push('#');
char ch;
ch=getchar();
while (ch!='#' || OPTR.GetTop()!='#')
{
if (!InOPTR(ch))
{
int n=ch-'0';
double num=(double)n;
OPND.Push(num);
ch=getchar();
}
else
{
char pre_op=OPTR.GetTop();
switch (Precede(pre_op, ch))
{
case '<': OPTR.Push(ch);
ch=getchar();
break;
case '=': OPTR.Pop();
ch=getchar();
break;
case '>': double b=OPND.Pop();
double a=OPND.Pop();
pre_op=OPTR.Pop();
OPND.Push(Operate(a, pre_op, b));
ch=getchar();
break;
}
}
}
return OPND.GetTop();
}
Then, when I input 8/(5-3)#, it will not print the result.
I think the loop termination condition ch!='#' || OPTR.GetTop()!='#' is wrong.
When I press Enter, getchar() get the last char is CR but not #.
But, I don't know how to revise it to make my program work.
The other part of my program is below:
#include<iostream>
using namespace std;
template<typename DataType,int StackSize>
class SeqStack
{
private:
DataType data[StackSize];
int top;
public:
SeqStack()
{ top=-1; }
~SeqStack() {}
void Push(DataType x)
{
if(top == StackSize-1)
throw "error";
data[++top]=x;
}
DataType Pop()
{
if(top == -1)
throw "error";
DataType x=data[top--];
return x;
}
DataType GetTop()
{
if(top != -1)
return data[top];
else
cout<<"error";
}
};
bool InOPTR(char ch)
{
if( (ch>='(' && ch<='+') || ch=='-' || ch=='/' )
{
return true;
}else{
return false;
}
}
char Precede(char op1, char op2)
{
char pri[7][7]={ {'>','>','<','<','<','>','>'}
, {'>','>','<','<','<','>','>'}
, {'>','>','>','>','<','>','>'}
, {'>','>','>','>','<','>','>'}
, {'<','<','<','<','<','=','#'}
, {'>','>','>','>','#','>','>'}
, {'<','<','<','<','<','#','='} };
int m,n;
switch(op1)
{
case '+': m=0;break;
case '-': m=1;break;
case '*': m=2;break;
case '/': m=3;break;
case '(': m=4;break;
case ')': m=5;break;
case '#': m=6;break;
}
switch(op2)
{
case '+': n=0;break;
case '-': n=1;break;
case '*': n=2;break;
case '/': n=3;break;
case '(': n=4;break;
case ')': n=5;break;
case '#': n=6;break;
}
return pri[m][n];
}
double Operate(double a, char op, double b)
{
double result;
switch(op)
{
case '+': result=a+b; break;
case '-': result=a-b; break;
case '*': result=a*b; break;
case '/': result=a/b; break;
}
return result;
}
int main()
{
double r=Expression_Eval();
cout<<r<<endl;
return 0;
}
Problem seem to be that '#' is considered a number, but it should be considered an operation:
Use:
bool InOPTR(char ch) {
if ((ch >= '(' && ch <= '+') || ch == '-' || ch == '/' || ch=='#'){
return true;
}
else {
return false;
}
}
Note that '#' is ASCII 64 which is not covered in the ranage '(' to '+' [40-43]
Hope this helps.
You need to consume carriage return or newline character after getchar(); which comes into play when you press enter button.
One trick is as below.
ch=getchar();
getchar(); //this getchar to consume CR.
since you have used ch = getchar() many times you have to use above solution at many places.
Better solution to this problem will be to enter string instead of entering single character using getchar()...
Hope you got what I am trying to say...

Reading numbers with getChar() in C++

I'd like to make a function reading integers from stdin in the fastest way possible. To be more specific I've got a very long sequence of ints separated with spaces finished with EOF on which I've got to make some operations. I used cin but since this function is quite robust in its possibilites I'd like to make something smaller, more specific, and thus, faster and more efficient. I've read that the fastes way of reading stdin is getChar() function. I've already found some implementations of this problem in C, but chars there are just another form of integers and in C++ they're not. My idea is to make a function of type bool
bool myIntRead( int *num);
which would basically read chars of an integer until a 'space sign' and somehow put these chars back into an int number. The bool type would be used to inform that the stdin is empty.
int main() {
int num;
while (myIntRead(&num) ) {
myIntRead(&num)
//some operations on num
}
}
I'm fully aware that this sort of dealing with input is much more complex and more difficult but I'd really like to find out a solution to this problem. I will really appreaciate some help from You Guys in finding out an implementation of this concept.
Best regards!
If you only want to deal with ASCII input and you're sure that input will be provided to you in the expected format (ie. digits 0-9 followed b space) then all you have to do is read each character and then:
Determine if it's a space or a digit
If it's a space, start reading a new number
If it's a digit append digit to current number
The following illustrates that. But it doesn't handle any overflow and there is no stop condition..
int c;
int current_number;
std::vector<int> numbers;
do {
c = getchar();
if(c == 0x20) // it's a space
{
numbers.push_back(current_number); // add the current number to the list of numbers
current_number = 0; // reset the current_number variable back to 0
}else if(c >= 0x30 && c <= 0x39) // it's a digit
{
current_number = current_number * 10 + (c - 0x30); // add next digit..
// you may want to deal with overflow here (ie. if number of digits > MAX_DIGITS or similar)
}
} while (TRUE); // there should be a stop condition here..
the following code reads 1000000 (one million) numbers in 61ms (normal PC some years old). The file has the size of 3.8MB.
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
template< typename T, typename Out >
struct IntReader_type
{
IntReader_type( Out out ) : out_( out ) {}
template< typename E, typename Traits >
friend std::basic_istream< E, Traits >& operator>>( std::basic_istream< E, Traits >& in, IntReader_type rdr )
{
std::basic_istream< E, Traits >::sentry ok( in );
if( ok )
{
std::ios_base::iostate state = std::ios_base::goodbit;
try
{
const std::ctype< E >& ct = std::use_facet< std::ctype< E > >( in.getloc() );
while( state == std::ios_base::goodbit )
{
T result = T(0);
for( Traits::int_type m = in.rdbuf()->sgetc(); ; m = in.rdbuf()->snextc() )
{
if( Traits::eq_int_type( m, Traits::eof() ) )
{
state |= std::ios_base::eofbit; // EOF is not an error
break;
}
const E c = Traits::to_char_type( m );
if( ct.is( std::ctype_base::space, c ) )
break;
if( ct.is( std::ctype_base::digit, c ) )
{
(result *= 10) += T(c - E('0'));
}
else
{
state |= std::ios_base::failbit; // not a digit
break;
}
}
*(rdr.out_)++ = result; // store the number
// skip white space character
for( Traits::int_type m = in.rdbuf()->sgetc(); ; m = in.rdbuf()->snextc() )
{
if( Traits::eq_int_type( m, Traits::eof() ) )
{
state |= std::ios_base::eofbit;
break;
}
if( !ct.is( std::ctype_base::space, Traits::to_char_type( m ) ) )
break;
}
}
}
catch( ... )
{
state |= std::ios_base::badbit;
if( in.exceptions() & std::ios_base::badbit )
throw;
}
in.setstate( state );
}
return in;
}
private:
Out out_;
};
template< typename T, typename Out >
IntReader_type< T, Out > read_ints( Out out )
{
return IntReader_type< T, Out >( out );
}
call the Integer-reader in this way:
vector< int > numbers;
if( cin >> read_ints< int >( back_inserter(numbers) ) )
{ // read is done without error
be careful - in this version only unsigned numbers can be read and there is no check of integer overflow.
ok, so c = getchar();
You have to store in in an array for it to be processable.
If c contains one digit, multiply c[0] * 1.
If c contains two digits, multiply c[1] * 1 + c[0] * 10.
If c contains three digits, multiply c[2] * 1 + c[1] * 10 + c[0] * 100.
If c contains four digits, multiply c[3] * 1 + c[2] * 10 + c[1] * 100 + c[0] * 1000, etc etc.
The code for input looks like this:
while(digitInput!=13)
{
if (kbhit())
{
digitInput=getch();
if (digitInput==27) exit(0);
if ((digitInput>47) && (digitInput<59))
{
digitArray[digit]=(unsigned char)digitInput-48;
digit++;
printf("%d",digitInput-48);
}
if (digitInput==13) { digitn=digitArray[0]; break; }
}
}
switch(digit)
{
case 0:
case 1:
digitn=digitArray[0]*1 ;
break;
case 2:
digitn= digitArray[1]*1 +digitArray[0]*10 ;
break;
case 3:
digitn= digitArray[2]*1+digitArray[1]*10 +digitArray[0]*100 ;
break;
case 4:
digitn=digitArray[3]*1+digitArray[2]*10+digitArray[1]*100+digitArray[0]*1000 ;
break;
}
The complete app in code.
#include <iostream.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
int digit=0,digitInput=0;
int digitArray[10]={0},digitn;
int numberOfInputDigits=4;
/*********************************
* *
********************************/
void getIntKey(void)
{
digitArray[0]=0;
digitArray[1]=0;
digit=0;
digitInput=0;
while(digitInput!=13)
{
if (kbhit())
{
digitInput=getch();
if (digitInput==27) exit(0);
if ((digitInput>47) && (digitInput<59))
{
digitArray[digit]=(unsigned char)digitInput-48;
digit++;
printf("%d",digitInput-48);
}
if (digitInput==13) { digitn=digitArray[0]; break; }
}
}
switch(digit)
{
case 0:
case 1:
digitn=digitArray[0]*1 ;
break;
case 2:
digitn= digitArray[1]*1 +digitArray[0]*10 ;
break;
case 3:
digitn= digitArray[2]*1+digitArray[1]*10 +digitArray[0]*100 ;
break;
case 4:
digitn=digitArray[3]*1+digitArray[2]*10+digitArray[1]*100+digitArray[0]*1000 ;
break;
case 5:
digitn=digitArray[4]*1+digitArray[3]*10+digitArray[2]*100+digitArray[1]*1000+digitArray[0]*10000 ;
break;
case 6:
digitn=digitArray[5]*1+digitArray[4]*10+digitArray[3]*100+digitArray[2]*1000+digitArray[1]*10000
+digitArray[0]*100000;
break;
case 7:
digitn=digitArray[6]*1+digitArray[5]*10+digitArray[4]*100+digitArray[3]*1000+digitArray[2]*10000
+digitArray[1]*100000 +digitArray[0]*1000000;
break;
case 8:
digitn=digitArray[7]*1+digitArray[6]*10+digitArray[5]*100+digitArray[4]*1000+digitArray[3]*10000
+digitArray[2]*100000 +digitArray[1]*1000000+digitArray[0]*10000000;
break;
case 9:
digitn=digitArray[8]*1+digitArray[7]*10+digitArray[6]*100+digitArray[5]*1000+digitArray[4]*10000
+digitArray[3]*100000 +digitArray[2]*1000000+digitArray[1]*10000000 +digitArray[0]*100000000;
break;
}
// if (digitInput!=13) digitn=digitArray[3]*1+digitArray[2]*10+digitArray[1]*100+digitArray[0]*1000 ;
printf("\n%i\n\n",digitn);
}
/*********************************
* *
********************************/
int main()
{
system("color 1F"); //Blue background
printf("Digits Into decimal numbers \n ");
printf("Max Input is %d Digits \n ",numberOfInputDigits);
printf("\nInput Digit >");
getIntKey();
printf("\nThe input was digitArray[7]=%d \n",digitArray[7]);
printf("digitArray[6]=%d \n",digitArray[6]);
printf("digitArray[5]=%d \n",digitArray[5]);
printf("digitArray[4]=%d \n",digitArray[4]);
printf("digitArray[3]=%d \n",digitArray[3]);
printf("digitArray[2]=%d \n",digitArray[2]);
printf("digitArray[1]=%d \n",digitArray[1]);
printf("digitArray[0]=%d \n",digitArray[0]);
printf("\n%i\n\n",digitn);
return 0;
}

c++ Bracket Validator with Stacks

I'm trying to write a program that will validate a user input consisting of brackets for proper nesting using a stack. I am trying to do this without the use of STL containers or recursion. I have somewhat hit a road block and I'm looking for a little nudge in the right direction. I think I am kind of close, but I feel like I may be oversimplifying it (I'm in the process of learning through self teaching)
Here is what I have so far:
#include <iostream>
#include <string>
#include "ArrayStack.h"
using namespace std;
bool test(char *argg);
int main()
{
string input;
int size = 50;
cout << "enter here: ";
getline(cin, input);
for (int i = 0; i < size; i++)
test(input[i]);
}
bool test(char *argg)
{
ArrayStack S;
char D;
while ( *argg ) {
switch( *argg ) {
case '[': case '{': case '(':
S.push( *argg );
break;
case ']':
if( S.isEmpty() )
return false;
D = S.pop();
if( D!='[' )
return false;
break;
case '}':
if( S.isEmpty() )
return false;
D = S.pop();
if( D!='{' )
return false;
break;
case ')':
if( S.isEmpty() )
return false;
D = S.pop();
if( D!='(' )
return false;
break;
default:
return false;
}// end switch
argg++;
}// end while
return S.isEmpty(); // return true if reach here with empty stack
}
Thanks for any assistance in advance
If anything, you're overcomplicating it
char inverse(char c){
if(c==']') return '[';
if(c=='}') return '{';
if(c==')') return '(';
return c;
}
int stillvalid(char c, ArrayStack &stack){
if(strchr("[{(", c))
stack.push(c);
else if(strchr("]})", c))
if(stack.isEmpty() || inverse(c) != stack.pop())
return 0;
return 1;
}
int main(){
int c;
ArrayStack stack;
while((c=getchar())!=EOF){
if(!stillvalid((char)c, stack)){
printf("bad\n");
exit(0);
}
}
printf("good\n");
return 0;
}
Should be all you need.
Trace through your code by hand with the input myfunc(42);
Observe what happens, character by character. That should point you your errors.

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();
}
}