permutations and combinations

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 6 Exercise 10
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Exercise 10

/*
input:
12
3
c
*/

#include "std_lib_facilities.h"

int factorial(int _n) {
int fact = 1;
while (1 < _n){
fact *= _n;
--_n;
if (fact < 1) {
error("factorial overflow");
}
}
return fact;
}

int permutations(int _a, int _b) {
if (_a < _b || _a < 1 || _b < 1) {
}
return factorial(_a) / factorial(_a - _b);
}

int combinations(int _a, int _b)
{
return permutations(_a, _b) / factorial(_b);
}

int main()
try
{
int a;
int b;
string aCheck;
string bCheck;
bool permCheck = false;
bool combCheck = false;

cout << "Enter two integer values for permutation and combination: \n";
cout << "Enter value for a\n";

if (cin >> a) {}
else{
cin.clear();
cin >> aCheck;
error("Wrong value for a: ", aCheck);
}

cout << "Enter value for b\n";
if (cin >> b) {}
else {
cin.clear();
cin >> aCheck;
error("Wrong value for b: ", aCheck);
}
if (b > a) {
error("Value b must be smaller than a, b: ", b);
}

cout << "a = " << a << "\n";
cout << "b = " << b << "\n";

cout << "Enter 'p' for permutations, 'c' for combinations or 'b' for both:\n";
if (answer == 'p') {
permCheck = true;
}
else if (answer == 'c') {
combCheck = true;
}
else if (answer == 'b') {
permCheck = true;
combCheck = true;
}
else {
}

if (permCheck) {
cout << "Permutation: " << permutations(a, b) << "\n";
}
if(combCheck){
cout << "Combination: " << combinations(a, b) << "\n";
}

keep_window_open(".");
}

catch (runtime_error e) {
cout << e.what() << "\n";
keep_window_open(".");
}
catch (...) {
cout << "Extiting" << "\n";
keep_window_open(".");
}
```

Output:

```Enter two integer values for permutation and combination:
Enter value for a
12
Enter value for b
3
a = 12
b = 3
Enter 'p' for permutations, 'c' for combinations or 'b' for both:
c
Combination: 220
Please enter . to exit
```

compose digits to integers

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 6 Exercise 9
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Exercise 9

//input: 1234x

#include "std_lib_facilities.h"

class Token {
public:
char intChar;
Token(char iCh)
:intChar(iCh) { }
};

class Token_stream {
public:
Token_stream();
Token get();
void putback(Token t);
private:
bool full;
Token buffer;
};

Token_stream::Token_stream()
:full(false), buffer(0)
{
}

void Token_stream::putback(Token t)
{
if (full) error("putback() into a full buffer");
buffer = t;
full = true;
}

Token Token_stream::get()
{
if (full) {
full = false;
return buffer;
}

char iCh;
cin >> iCh;

switch (iCh) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'x':
{
//cin.putback(iCh);
}
default:
}
}

Token_stream ts;

int main()
try
{
cout << "Enter 1-4 integer values\n";
vector<int> intFromChar;
int intAdded = 0;
bool check = true;

while (check) {
if (intFromChar.size() < 4) {
Token t = ts.get();
if (t.intChar == 'x') break; // 'x' for quit
intFromChar.push_back(t.intChar - '0');
}
else{
check = false;
}
}

cout << "Num size: " << intFromChar.size() << "\n";

for (int i = 0; i < intFromChar.size(); i++) {
int result = pow(10, intFromChar.size() - i) / 10;
intFromChar[i] = intFromChar[i] * result;
}

for (int i = 0; i < intFromChar.size(); i++) {
}

if (intFromChar.size() == 1) {
cout << intAdded << " is "
<< intFromChar[0] << " ones\n";
}

if (intFromChar.size() == 2) {
cout << intAdded << " is "
<< intFromChar[0] << " tens and "
<< intFromChar[1] << " ones\n";
}

if (intFromChar.size() == 3) {
cout << intAdded << " is "
<< intFromChar[0] << " hundreds and "
<< intFromChar[1] << " tens and "
<< intFromChar[2] << " ones\n";
}

if (intFromChar.size() == 4) {
cout << intAdded << " is "
<< intFromChar[0] << " thousands and "
<< intFromChar[1] << " hundreds and "
<< intFromChar[2] << " tens and "
<< intFromChar[3] << " ones\n";
}

keep_window_open(".");
}

catch (runtime_error e) {
cout << e.what() << "\n";
keep_window_open(".");
}
catch (...) {
cout << "Extiting" << "\n";
keep_window_open(".");
}
```
```Output:
Enter 1-4 integer values
1234x
Num size: 4
1234 is 1000 thousands and 200 hundreds and 30 tens and 4 ones
Please enter . to exit
```

bulls and cows [guess 4 characters]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 6 Exercise 8
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Exercise 8

#include "std_lib_facilities.h"

vector<char> randomCharGen(int _seed, int _num) {
vector <char> chosen;
int counter = 0;
vector <char> alphabet = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z' };

srand(_seed);
while (chosen.size() < _num) {
char temp = alphabet[rand() % alphabet.size()];
if (chosen.size() == 0) {
chosen.push_back(temp);
}
else{
for (int j = 0; j < chosen.size(); j++) {
if (temp == chosen[j]) {
counter++;
}
}
if (counter == 0) {
chosen.push_back(temp);
}
else {
counter = 0;
}
}
}
return chosen;
}

int main()
try
{
vector <char> randomChars;
vector <char> charGuess;
char charGuessTemp;
int charGuessCheck;

int bulls = 0;
int cows = 0;

int charNums = 4;
int seed;
string seedCheck;

while (randomChars.size() < charNums) {
cout << "Enter seed value between 0 and 100\n";
if (cin >> seed && seed <= 100 && seed >= 0) {}
else {
cin.clear();
cin >> seedCheck;
error("Seed value is wrong: ", seedCheck);
}
randomChars = randomCharGen(seed, charNums);

for (int i = 0; i < randomChars.size(); i++) {
cout << randomChars[i] << "\n";
}

while (bulls != charNums) {
bulls = 0;
cows = 0;

cout << "Enter 4 different letters\n";
if (cin) {
while (charGuess.size() < charNums) {
if (cin >> charGuessTemp) {
charGuess.push_back(charGuessTemp);
}
else {
cin.clear();
cin >> charGuessCheck;
error("Entered wrong guess", charGuessCheck);
}
}
}

//COMPARING GUESS AND RANDOM LETTERS
for (int i = 0; i < charNums; i++) {
for (int j = 0; j < charNums; j++) {
if (charGuess[i] == randomChars[j] && i == j) {
bulls++;
}
else if (charGuess[i] == randomChars[j] && i != j) {
cows++;
}
}
}
cout << "Bulls: " << bulls << " Cows: " << cows << "\n";
charGuess.clear();
}

cout << "You win!\n";
cout << "Play again? Type y for yes and n for no: ";

}
else if (answer == "y") {
randomChars.clear();
bulls = 0;
}
}
keep_window_open(".");
}

catch (runtime_error e) {
cout << e.what() << "\n";
keep_window_open(".");
}
catch (...) {
cout << "Extiting" << "\n";
keep_window_open(".");
}
```
```Output:
Enter sentece to be checked or x to exit:
birds fly and fish swim.
OK!
x for exit or continue:
C++ rules.
OK!
x for exit or continue:
x
Please enter . to exit
```

grammar for bitwise logical expressions

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 6 Exercise 7
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Exercise 7

#include "std_lib_facilities.h"

/*
Binary And:
Exclusive Or
And "&" Or

Binary Exclusive Or:
Or
Exclusive Or "^" Or

Binary Or:
Unary
Or "|" Unary

Prefix Unary:
Primary
Unary "!" Primary
Unary "~" Primary

Primary:
Number
"("Expression")"

Number:
integer
*/
```

sentence check

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 6 Exercise 6
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Exercise 6

/*
input:
birds fly and fish swim.
C++ rules.
x
*/

#include "std_lib_facilities.h"

//word vector setup
vector<string> nouns;
vector<string> verbs;
vector<string> conjunctions;

//initialize word vectors
void init(){
nouns.push_back("birds");
nouns.push_back("fish");
nouns.push_back("C++");

verbs.push_back("rules");
verbs.push_back("fly");
verbs.push_back("swim");

conjunctions.push_back("and");
conjunctions.push_back("or");
conjunctions.push_back("but");
}

bool isNounString(string w) {
for (int i = 0; i < nouns.size(); i++) {
if (w == nouns[i]) {
return true;
}
}
return false;
}

bool isVerbString(string w) {
for (int i = 0; i < verbs.size(); i++) {
if (w == verbs[i]) {
return true;
}
}
return false;
}

bool isConjunctionString(string w) {
for (int i = 0; i < conjunctions.size(); i++) {
if (w == conjunctions[i]) {
return true;
}
}
return false;
}

bool sentences() {
string w;
cin >> w;
if (!isNounString(w)) {
return false;
}

string w1;
cin >> w1;
if (!isVerbString(w1)) {
if (w1[w1.size() - 1] == '.') {
return true;
}
else {
return false;
}
}

string w2;
cin >> w2;
if (!isConjunctionString(w2)) {
return false;
}
return sentences();
}

int main()
try
{
init();
cout << "Enter sentece to be checked or x to exit:\n";

while (true) {
char exit;
if (cin >> exit && exit == 'x') {
break;
}
else {
cin.putback(exit);
bool check = sentences();
if (check) {
cout << "OK!\n";
cout << "x for exit or continue:" << endl;
}
else {
cout << "Not OK!\n";
cout << "Try again:\n";
}
}

}

/*
while (cin) {

}
*/

keep_window_open(".");
}

catch (runtime_error e) {
cout << e.what() << "\n";
keep_window_open(".");
}
catch (...) {
cout << "Exiting!\n";
keep_window_open(".");
}
```
```Output:
Enter sentece to be checked or x to exit:
birds fly and fish swim.
OK!
x for exit or continue:
C++ rules.
OK!
x for exit or continue:
x
Please enter . to exit
```

using a simple class

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 6 Exercise 4
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Exercise 4

#include "std_lib_facilities.h"

class nameValue {
public:
nameValue(string n, int a) : name(n), age(a) { }
string name;
int age;
};

int main()
try
{
vector<nameValue> nameAndAge;

string nameTemp;
int ageTemp;

bool check = true;

while (check == true) {
cout << "Enter name and age pairs to be collected, or 'noname' and '0' to end the entry.\n";
if (cin >> nameTemp >> ageTemp) {
if (nameTemp == "noname" && ageTemp == 0) {
check = false;
}
else {
for (int i = 0; i < nameAndAge.size(); i++) {
if (nameAndAge[i].name == nameTemp) {
error("This name already exists ", nameTemp);
}
}
nameAndAge.push_back(nameValue(nameTemp, ageTemp));
}
}
else {
}
}

for (int i = 0; i < nameAndAge.size(); i++) {
cout << "Name: " << nameAndAge[i].name << " Score: " << nameAndAge[i].age << "\n";
}

keep_window_open(".");
}

catch (runtime_error e) {
cout << e.what() << "\n";
keep_window_open(".");
}
catch (...) {
cout << "Exiting \n";
keep_window_open(".");
}

/*class Name_value {	// much like Token from 6.3.3
public:
Name_value(string n, int s): name(n), score(s) { }
string name;
int score;
};

int main()
try
{
vector<Name_value> pairs;

string n;
int v;

while (cin>>n>>v && n!="NoName") {	// read string int pair
for (int i=0; i<pairs.size(); ++i)
if (n==pairs[i].name) error("duplicate: ",n); // chek for duplicate
pairs.push_back(Name_value(n,v));
}

for (int i=0; i<pairs.size(); ++i)
cout << '(' << pairs[i].name << ',' << pairs[i].score << ")\n";

keep_window_open("~");	// For some Windows(tm) setups
}*/
```

calculator 1.3 [adding factorial]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 6 Exercise 3
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Exercise 3

#include "std_lib_facilities.h" //ERROR: "#include "../std_lib_facilities.h", instead #include "std_lib_facilities.h"

//------------------------------------------------------------------------------

class Token { //ERROR 1/5: "lass Token{", missing c for class
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) { }
};

//------------------------------------------------------------------------------

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

//------------------------------------------------------------------------------

// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream()
:full(false), buffer(0)    // no Token in buffer
{
}

//------------------------------------------------------------------------------

// The putback() member function puts its argument back into the Token_stream's buffer:
void Token_stream::putback(Token t)
{
if (full) error("putback() into a full buffer");
buffer = t;       // copy t to buffer
full = true;      // buffer is now full
}

//------------------------------------------------------------------------------

Token Token_stream::get() //ERROR 2/5: "Token get()", instead 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
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': //ERROR 1/3: "case'8':", missing
{
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"
}
default:
}
}

//------------------------------------------------------------------------------

Token_stream ts;        // provides get() and putback()

//------------------------------------------------------------------------------

double expression();    // declaration so that primary() can call expression()

//------------------------------------------------------------------------------

// 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 != ')') error("')' expected )"); //ERROR 3/5: "if (t.kind != ')') error("')' expected)", missing );
return d;
}

case '{':     // handle '(' expression ')'
{
double d = expression();
t = ts.get();
if (t.kind != '}') error("'}' expected }"); //ERROR 3/5: "if (t.kind != ')') error("')' expected)", missing );
return d;
}

case '8':            // we use '8' to represent a number
return t.value;  // return the number's value

default:
error("primary expected");
}
}

//------------------------------------------------------------------------------

// deal with !
double factorial()
{
double left = primary();
Token t = ts.get();        // get the next token from token stream

while (true) {
switch (t.kind) {
case '!':
{
int leftVal = left;
for (int i = 1; i < leftVal; i++) {
left *= i;
}
t = ts.get();
break;
}
default:
ts.putback(t);     // put t back into the token stream
return left;
}
}
}

//------------------------------------------------------------------------------

// deal with *, /, and %
double term()
{
double left = factorial();
Token t = ts.get();        // get the next token from token stream

while (true) {
switch (t.kind) {
case '*':
{
left *= factorial();
t = ts.get();
break;
}
case '/':
{
double d = factorial();
if (d == 0) error("divide by zero");
left /= d;
t = ts.get();
break;
}
default:
ts.putback(t);     // put t back into the token stream
return left;
}
}
}

//------------------------------------------------------------------------------

// deal with + and -
double expression()
{
double left = term();      // read and evaluate a Term //ERROR 4/5: "double left = term(;" mssing )
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; //ERROR 2/3: "break;", missing
case '-':
left -= term();    // evaluate Term and subtract //ERROR 3/3: "left += term();" plus instead of minus
t = ts.get();
break;
default:
ts.putback(t);     // put t back into the token stream
return left;       // finally: no more + or -: return the answer
}
}
}

//------------------------------------------------------------------------------

int main()
try
{
cout << "Welcome to our simple calculator.\n";
cout << "Please enter expressions using floating-point numbers.\n";
cout << "Currently available operators are: '(', ')', '*', '/', '+', '-' and '!'.\n";
cout << "Use '=' to get result or 'x' to quit the program.\n";

double val = 0; //ERROR 5/5: val not initialized

while (cin) {
Token t = ts.get();

if (t.kind == 'x') break; // 'x' 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;
}

//------------------------------------------------------------------------------
```
```Output:
Welcome to our simple calculator.
Please enter expressions using floating-point numbers.
Currently available operators are: '(', ')', '*', '/', '+', '-' and '!'.
Use '=' to get result or 'x' to quit the program.
13!
=
=6.22702e+09
```

calculator 1.3 [adding curly brakets]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 6 Exercise 2
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Exercise 2

//input: {4 + 3} / 3;

#include "std_lib_facilities.h" //ERROR: "#include "../std_lib_facilities.h", instead #include "std_lib_facilities.h"

//------------------------------------------------------------------------------

class Token { //ERROR 1/5: "lass Token{", missing c for class
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) { }
};

//------------------------------------------------------------------------------

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

//------------------------------------------------------------------------------

// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream()
:full(false), buffer(0)    // no Token in buffer
{
}

//------------------------------------------------------------------------------

// The putback() member function puts its argument back into the Token_stream's buffer:
void Token_stream::putback(Token t)
{
if (full) error("putback() into a full buffer");
buffer = t;       // copy t to buffer
full = true;      // buffer is now full
}

//------------------------------------------------------------------------------

Token Token_stream::get() //ERROR 2/5: "Token get()", instead 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 '/':
return Token(ch);        // let each character represent itself
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': //ERROR 1/3: "case'8':", missing
{
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"
}
default:
}
}

//------------------------------------------------------------------------------

Token_stream ts;        // provides get() and putback()

//------------------------------------------------------------------------------

double expression();    // declaration so that primary() can call expression()

//------------------------------------------------------------------------------

// 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 != ')') error("')' expected)"); //ERROR 3/5: "if (t.kind != ')') error("')' expected)", missing );
return d;
}

case '{':     // handle '(' expression ')'
{
double d = expression();
t = ts.get();
if (t.kind != '}') error("'}' expected)"); //ERROR 3/5: "if (t.kind != ')') error("')' expected)", missing );
return d;
}

case '8':            // we use '8' to represent a number
return t.value;  // return the number's value

default:
error("primary expected");
}
}

//------------------------------------------------------------------------------

// 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) error("divide by zero");
left /= d;
t = ts.get();
break;
}
default:
ts.putback(t);     // put t back into the token stream
return left;
}
}
}

//------------------------------------------------------------------------------

// deal with + and -
double expression()
{
double left = term();      // read and evaluate a Term //ERROR 4/5: "double left = term(;" mssing )
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; //ERROR 2/3: "break;", missing
case '-':
left -= term();    // evaluate Term and subtract //ERROR 3/3: "left += term();" plus instead of minus
t = ts.get();
break;
default:
ts.putback(t);     // put t back into the token stream
return left;       // finally: no more + or -: return the answer
}
}
}

//------------------------------------------------------------------------------

int main()
try
{
cout << "Welcome to our simple calculator.\n";
cout << "Please enter expressions using floating-point numbers.\n";
cout << "Currently available operators are: '(', ')', '*', '/', '+' and '-'.\n";
cout << "Use '=' to get result or 'x' to quit the program.\n";

double val = 0; //ERROR 5/5: val not initialized

while (cin) {
Token t = ts.get();

if (t.kind == 'x') break; // 'x' 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;
}

//------------------------------------------------------------------------------
```
```Output:
{4 + 3} / 3;
=2.33333
```

calculator 1.2 [bug fixes]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 6 Drill
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Drill

//
// This is example code from Chapter 6.7 "Trying the second version" of
// "Software - Principles and Practice using C++" by Bjarne Stroustrup
//

/*
This file is known as calculator02buggy.cpp

I have inserted 5 errors that should cause this not to compile
I have inserted 3 logic errors that should cause the program to give wrong results

First try to find an remove the bugs without looking in the book.
If that gets tedious, compare the code to that in the book (or posted source code)

Happy hunting!

*/

//input: (4 + 3) / 3;

#include "std_lib_facilities.h" //ERROR: "#include "../std_lib_facilities.h", instead #include "std_lib_facilities.h"

//------------------------------------------------------------------------------

class Token{ //ERROR 1/5: "lass Token{", missing c for class
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) { }
};

//------------------------------------------------------------------------------

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

//------------------------------------------------------------------------------

// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream()
:full(false), buffer(0)    // no Token in buffer
{
}

//------------------------------------------------------------------------------

// The putback() member function puts its argument back into the Token_stream's buffer:
void Token_stream::putback(Token t)
{
if (full) error("putback() into a full buffer");
buffer = t;       // copy t to buffer
full = true;      // buffer is now full
}

//------------------------------------------------------------------------------

Token Token_stream::get() //ERROR 2/5: "Token get()", instead 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 '/':
return Token(ch);        // let each character represent itself
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': //ERROR 1/3: "case'8':", missing
{
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"
}
default:
}
}

//------------------------------------------------------------------------------

Token_stream ts;        // provides get() and putback()

//------------------------------------------------------------------------------

double expression();    // declaration so that primary() can call expression()

//------------------------------------------------------------------------------

// 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 != ')') error("')' expected)"); //ERROR 3/5: "if (t.kind != ')') error("')' expected)", missing );
return d;
}
case '8':            // we use '8' to represent a number
return t.value;  // return the number's value
default:
error("primary expected");
}
}

//------------------------------------------------------------------------------

// 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) error("divide by zero");
left /= d;
t = ts.get();
break;
}
default:
ts.putback(t);     // put t back into the token stream
return left;
}
}
}

//------------------------------------------------------------------------------

// deal with + and -
double expression()
{
double left = term();      // read and evaluate a Term //ERROR 4/5: "double left = term(;" mssing )
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; //ERROR 2/3: "break;", missing
case '-':
left -= term();    // evaluate Term and subtract //ERROR 3/3: "left += term();" plus instead of minus
t = ts.get();
break;
default:
ts.putback(t);     // put t back into the token stream
return left;       // finally: no more + or -: return the answer
}
}
}

//------------------------------------------------------------------------------

int main()
try
{
cout << "Welcome to our simple calculator.\n";
cout << "Please enter expressions using floating-point numbers.\n";
cout << "Currently available operators are: '(', ')', '*', '/', '+' and '-'.\n";
cout << "Use '=' to get result or 'x' to quit the program.\n";

double val = 0; //ERROR 5/5: val not initialized

while (cin) {
Token t = ts.get();

if (t.kind == 'x') break; // 'x' 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;
}

//------------------------------------------------------------------------------
```
```Output:
(4 + 3) / 3;
=2.33333
```

calculator 1.2

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Using std_lib_facilities.h by Bjarne Stroustrup.

```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 6 Try This Page 216

#include "std_lib_facilities.h"

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

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

// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream()
:full(false), buffer(0)    // no Token in buffer
{
}

// The putback() member function puts its argument back into the Token_stream's buffer:
void Token_stream::putback(Token t)
{
if (full) error("putback() into a full buffer");
buffer = t;       // copy t to buffer
full = true;      // buffer is now full
}

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 'q':    // for "quit"
case '(': case ')': case '+': case '-': case '*': case '/':
return Token{ ch };        // let each character represent itself
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': 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"
}
default:
}
}

Token_stream ts;        // provides get() and putback()
double expression();    // declaration so that primary() can call expression()

// 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 != ')') error("')' expected");
return d;
}
case '8':            // we use '8' to represent a number
return t.value;  // return the number's value
default:
error("primary expected");
}
}

// 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) error("divide by zero");
left /= d;
t = ts.get();
break;
}
default:
ts.putback(t);     // put t back into the token stream
return left;
}
}
}

// deal with + and -
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
}
}
}

int main()
try
{
/* First Version of 6.7
while (cin)
cout << "=" << expression() << '\n';
keep_window_open("~0");
*/

double val = 0;
while (cin) {
Token t = ts.get();

if (t.kind == 'q') break; // 'q' for quit
if (t.kind == ';')        // ';' for "print now"
cout << "=" << val << '\n';
else
ts.putback(t);
val = expression();
}
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
return 1;
}
catch (...) {
cerr << "Oops: unknown exception!\n";
return 2;
}
```
```Output:
4 + 6;
=10
10 - 3
;
=7
```