Monday 26 December 2016

Chapter 6 // Exercise 9 - Principles & Practice Using C++

Chapter 6 // Exercise 9

Write a program that reads digits and composes them into integers. For example 123 is read as the characters 1, 2 and 3. The program should output "123 is 1 hundred and 2 tens and 3 ones". The number should be output as an int value. Handle numbers with one, two, three or four digits.

Hint: To get the integer value 5 from the character '5' subtract '0', that is '5'-'0'==5.


#include "stdafx.h"
#include <vector>
#include <string>
void pause();
void getNumbers();
void printNumbers();
using namespace std;
vector <int> digits;
char er = 'n'; //for error checking

int main()
{
 //get the numbers and convert them to an int from string
 getNumbers();

 //print the numbers out
 printNumbers();


 //ask for letter to quit the program
 pause();

 return 0;
}


void getNumbers()
{
 er = 'n';
 cout << "Please enter a number with up to 4 digits: ";
 string x;
 cin >> x; 

 //error checking
 for (int i = 0; i < x.size(); ++i)
 {
  for (char n = 'a'; n < 'z'; ++n)
  {
   while (x[i] == n)
   {
    er = 'y';
    cout << "That is not a number. Sorry.\n";
    return;
   }  
  }

  int num = x[i] - '0'; //converts letter to int
  digits.push_back(num); //pushes back into int vector
 }
}

void printNumbers()
{
 //continue to get input while er is equal to y
 while (er == 'y')
  getNumbers();

 for (int i = 0; i < digits.size(); ++i)
  cout << digits[i];

 cout << " is ";

 if (digits.size() == 4)
 {
  if (digits[0] == 1)
   cout << digits[0] << " thousand and ";
  else
   cout << digits[0] << " thousands and ";

  if (digits[1] == 1)
   cout << digits[1] << " hundred and ";
  else
   cout << digits[1] << " hundreds and ";

  if (digits[2] == 1)
   cout << digits[2] << " ten and ";
  else
   cout << digits[2] << " tens and ";

  cout << digits[3] << " ones.\n";
 }


 if (digits.size() == 3)
 {
  if (digits[0] == 1)
   cout << digits[0] << " hundred and ";
  else
   cout << digits[0] << " hundreds and ";

  if (digits[1] == 1)
   cout << digits[1] << " ten and ";
  else
   cout << digits[1] << " tens and ";

  cout << digits[2] << " ones.\n";
 }


 if (digits.size() == 2)
 {
  if (digits[0] == 1)
   cout << digits[0] << " ten and ";
  else
   cout << digits[0] << " tens and ";
  cout << digits[1] << " ones.\n";
 }

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

}

void pause()
{
 cout << "\n\nPlease enter a letter: ";
 char key;
 cin >> key;
}


I'm sure there must be a much easier way to print the digits grammatically however I decided to just do this by brute force because this small program doesn't really take up any memory by doing it this way, nor does it slow it down. 

At first when I read this question I was like "what on earth does he want me to do now?" I didn't know if he wanted us to write into a char but then a char can't hold more than single character, so I thought about a vector of chars and pushing them back but that would require at least 5 different chars to push back. So I went with a string and I actually learnt something very useful today.

So string has similar functions as vector, I knew that I could get the size of it by using .size after the variable to return how many characters had been inputted. However on a whim I decided to see what would happen if I took away '0' from the character within the string, as suggested by Bjarne in the book. And it worked, it returned a number which I applied to a interger called num and then pushed that into a vector so printNumbers() had them all in one place.

Also, as a little extra this includes error checking. This doesn't allow any letters and will only allow numbers. I did this by comparing whatever the current character of x was to the alphabet using a for loop. For example, if the string x was equal to k then k would be compared to each letter of the alphabet and if it was equal to one then it returns to main and executes the next function. However the char 'er' has been set to 'y' so it will keep calling getNumbers() until er is equal to 'n'. It took me a while to get this error check working, so I'm pretty proud it does.

Sunday 27 November 2016

Little Hiatus & Blog Update

This blog is currently on a small hiatus as I focus on university work. I am currently half way through chapter 7 but my assignments are top priority.

I just handed in my first which was Maths & Physics for game play which focused on parabolic trajectories and IK Chains and have a programming one and another maths due by Christmas. Whilst doing my assignments it has made me think about the future of this blog and would love eventually to put up tutorials on maths for games programming and c++ tutorials. 

As someone who has been programming for just under a year, I'd like to keep the topics on this blog simple, especially for beginner programmers. I've found that newbies asking questions in places like stackoverflow or cplusplus are met with patronizing answers from 'experts' whose answers are way too technical for their level of understanding. 

For example, someone had posted a question on an exercise from chapter 5 of P&P on stackoverflow (I was searching for an answer myself and I was stumped) and one user replied with "just use maps". Another user then had to point out that maps aren't introduced till a much later chapter (I'm currently still trying to wrap my head around classes). I guess what I'm trying to say is, I want this site to be a place where newcomers to C++ can learn the basics without the fear of experienced programmers thinking they're stupid. 
     We all learn at different paces and in different ways. I still use system("pause") every now and then despite what every single user on stackoverflow says. I only ever use windows and it works for what I want. Would I use it in a professional program? Of course not, but that doesn't mean I'm idiot for using it. You have to learn to walk before you can run. That's why Bjarne provides you with a header file with functions such as keep_window_open(). That function works in exactly the same way as system("pause") but for the first few chapters I had no idea how it worked, I only knew that it kept the console window open (as visual studio has a habit of closing the console window when the program has finished executing). Now I understand how it works and how to create a function which does the same thing. 

I am in no way an expert, I'm still learning, and have a lot to learn, but this blog was created because I could not find any help on Principles & Practice. There are a few blog posts and Bjarne himself has answered a few questions but there doesn't seem to be anyone who actually goes through their answers and how they got them. Therefore I hope that someone else finds this blog somewhat useful, if not I'm pretty proud of how far I've progressed so far. But enough rambling, thank you to those who are dropping by and if you have any questions I will try to answer as best I can.

Thursday 29 September 2016

Chapter 6 // Exercise 8 - Principles & Practice Using C++

In all these exercises I am using Visual Studio Community 2015 and the header file "std_lib_facilities.h" which can be found here:


http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


My version is spelt differently so adjust the code accordingly if copying and pasting.


Chapter 6 // Exercise 8

Redo the "Bulls & Cows" game from exercise 12 in Chapter 5 to use four letters rather than four digits.



#include "stdafx.h"
#include "std_lib_facilities_new_version.h"
using namespace std;

void getSeed();
void printRules();
void startGame();
void getLetters();
void compareLetters();
char assignLoop();
vector<char> fourLetters{ 0,0,0,0 };
vector<char> guess{ 0,0,0,0 };

int main()
try
{
char loop = 'y';

while (loop == 'y')
{
//get number for seed  & assign letters to fourLetters
getSeed();

//print rules of game
printRules();

//begin the game and keep going till user decides to quit
startGame();

//ask if you want to play again
loop = assignLoop();
}

keep_window_open();

return 0;
}


catch (exception& e)
{
cerr << "Error: " << e.what() << '\n';
keep_window_open();
return 1;
}

//produces random number which corralates to ASCII lower case alphabet
char getRandLetter()
{
char randNum = (rand()%(122 - 97 + 1)) + 97; // produces random number between 97 and 122
return randNum;
}

//get seed for rand num and assign letters to comp's four letters
void getSeed()
{
cout << "Please enter a number(any number):\n";
int n;
cin >> n;

srand(n);
for (int i = 0; i < fourLetters.size(); ++i)
{
fourLetters[i] = getRandLetter();
}

sort(fourLetters); //to compare if any are the same

for (int i = 1; i < fourLetters.size(); ++i)
{
while (fourLetters[i] == fourLetters[i - 1])
{
fourLetters[i] = getRandLetter();
}
}

}



void printRules()
{
cout << "//RULES//";
cout << "\nLets Play Bulls & Cows.\n";
cout << "Guess the 4 letters.\n";
cout << "If a letter is right in the right position you will get a bull.\n";
cout << "If the letter is right in the wrong position you will get a cow.\n";
cout << "\nGuess a letter a-z. Each letter must be different and lower case. \n\n";
}

void startGame()
{
while (guess != fourLetters)
{
//get user letters
getLetters();
//compare user and random letters for bulls & cows
compareLetters();
}
}

void getLetters()
{

vector<string>n = { "1st Letter: ", "2nd Letter: ", "3rd Letter: ", "4th Letter: " };

for (int i = 0; i < 4; ++i)
{
cout << n[i];
char letter;
cin >> letter;

if (letter < 'a' || letter > 'z')
error("You can only use lower case.\n");

guess[i] = letter;
}

cout << "Your guess: ";

for (int i = 0; i < 4; ++i)
{
cout << guess[i] << " ";
}

cout << '\n';
}

void compareLetters()
{
for (int i = 0; i < 4; ++i)
{
for (int n = 0; n < 4; ++n)
{
if (guess[i] == fourLetters[n])
{
if (i == n)
cout << "1 Bull(" << guess[i] << ")";
else
cout << "1 Cow(" << guess[i] << ")";
}
}
}
}

char assignLoop()
{
cout << "\n\nCongratz! You did it!\n";
cout << "Would you like to play again? y / n:\n";
char l;
cin >> l;
while (l != 'y' && l != 'n')
{
cout << "Invalid answer, try again. y / n:\n";
cin >> l;
}

return l;
}



This one took a while as I figured out how to perfect a few things. The original exercise had you guess a number 1 - 9, this one a letter a -z. Since int and char are interchangeable I simply changed most of the code to char however when it came to randomizing what letters you would get I had to find a new function.


The one I've got accepts a max and a min value, for us we want between 97 and 122 as these are the numbers for the characters a - z. I then just assigned one of the generated numbers to the guess vector. When looking to see if any of them were the same I realised my prior function wasn't exactly perfect and would sometimes allow the same numbers. I've corrected it on this one by sorting them first. This does give the letters some predictability by putting them in order however not all the time as if some are the same they will be changed to another generated number.



Tuesday 27 September 2016

Chapter 6 // Exercise 7 - Principles & Practice Using C++

In all these exercises I am using Visual Studio Community 2015 and the header file "std_lib_facilities.h" which can be found here:


http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


My version is spelt differently so adjust the code accordingly if copying and pasting.


Chapter 6 // Exercise 7

Write a grammar for bitwise logical expressions.  A bitwise logical expression is much like an arithmetic expression except that the operators are ! (not), ~ (complement), & (and), | (or) and ^ (exclusive or).

Each operator does its operation to each bit of its integer operands. ! and ~ are prefix unary operators.

binds tighter than a | (just as * binds tighter than +) so that x|y^z means x|(y^z) rather than (x|y)^z. The & operator binds tighter than ^ so that x^y&z means x^(y&z).

Expression:
    Third Term
    Expression "|" Third Term

Third Term:
    Second Term
    Third Term "^" Second Term

Second Term:
    First Term
    Second Term "&" First Term

First Term:
    Primary
    First Term "!" Primary
    First Term "~" Primary

Primary:
    Object   //int, char, string etc
    "(" Expression ")"


Following the example earlier in chapter 6 I think this is how it would be done although I'm not entirely sure. English was always my best subject but grammar in programming is throwing my brain for a loop.

EDIT 07/10/2019 - This was almost correct the first time I did it. However, now I understand his thought process a little better on grammars I've realised that the First Term section is incorrect. "!" and "~" are always pre-fix operators and as such it will be sufficient for First term to look like this:
Primary
"!" Primary
"~" Primary
This way, they will always affect the Primary instead of the left value. Here is an updated version on GitHub.

Friday 23 September 2016

Chapter 6 // Exercises 5, 6 - Principles & Practice Using C++

In all these exercises I am using Visual Studio Community 2015 and the header file "std_lib_facilities.h" which can be found here:


http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


My version is spelt differently so adjust the code accordingly if copying and pasting.


Chapter 6 // Exercise 5

Add the article the to the "English" grammar in 6.4.1, so that it can describe sentences such as "The birds fly but the fish swim."

I'm not sure quite what he wants us to do in this one. Make a program or just change the psuedocode? Either way the word 'the' is extremely complicated and has many different uses. It's doesn't always come before or after a verb, same with a noun and it's not a conjunction (something that joins sentences together). 

If he just wants us to change the psuedocode so it always comes before a noun (like he's put in his example) then it would be like this:


Sentence:
The Noun Verb
Sentence Conjuction Sentence

Conjuction:
and
or
but

Noun:
birds
fish
C++

The:
the

Verb:
rules
fly 
swim

I think this would also give you "The c++ rules", which is bad grammar because c++ doesn't denote something plural or a direct object (as opposed to saying 'the rules' where rules denotes the plural of rule) But I don't think we're creating Microsoft Word just yet, so I'm going to leave this one where it is.

Chapter 6 // Exercise 6


Write a program that checks if a sentence is correct according to the "English" grammar in 6.4.1. Assume that every sentence is terminated by a full stop (.) surrounded by white space. For example, birds fly but the fish swim .  is a sentence, but birds fly but the fish swim (terminating dot missing) and birds fly but the fish swim. (no space before dot) are not. For each sentence entered, the program should simply respond "OK" or "not OK". Hint: Don't bother with tokens; just read in a string using >>.

 I honestly didn't know what to make of this so here is his answer:

Chapter 6 exercise 6

Reading through it, it uses bools and I just can't wrap my head around them. It's just like minecraft with the not gates, I understand it flips it but I just don't get the whole 'true' 'false' thing.

Overall these two exercises were just



to me.

EDIT 07/10/2019 - I have now completed these two exercises found on GitHub here. This took me a while as I started getting pedantic about how to parse the sentence. I eventually went with a very hacky way of doing things as I was starting to run out of time. Eventually, I'll go back and refactor the code again to make it a little more …elegant shall we say. I started doing it how he has done it without realising it, but it doesn't allow for all the sentence types I don't think. I do like the idea of parsing the sentence into a wordtype vector as you can create verb/noun vectors and add more words to them and when deciding what they are, use a for loop to loop through each vector. Then creating a function which checks sentence structure shouldn't be too much hassle. I say shouldn't...

Wednesday 21 September 2016

Chapter 6 // Exercise 4 - Principles & Practice Using C++

In all these exercises I am using Visual Studio Community 2015 and the header file "std_lib_facilities.h" which can be found here:


http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


My version is spelt differently so adjust the code accordingly if copying and pasting.


Chapter 6 // Exercise 4

Define a class Name_value that holds a string and a value. Rework exercise 19 in Chapter 4 to use a vector<Name_value> instead of two vectors.

#include "stdafx.h"
#include "std_lib_facilities_new_version.h"
using namespace std;

class Name_value
{
public:
string name;
int score;
};

vector<Name_value> n_s;

void getData()
{
cout << "Please enter a name, press enter, then input the score. To stop input enter 'NoName' in name and 0 in scores.\n";

Name_value data;  //variable that holds a string and int pair
char loop = 'y';

//get names and scores
while (loop == 'y')
{
cout << "Name: ";
cin >> data.name;
cout << "Score: ";
cin >> data.score;
for (int i = 0; i < n_s.size(); ++i)
{
while (n_s[i].name == data.name)
{
cout << "Sorry, that name has already been entered. Please Re-Name it: \n" << endl;
cin >> data.name;
}
}

if (data.name == "NoName" && data.score == 0)
{
loop = 'n';
}

n_s.push_back(data);  //pushes the string and int pair into the vector together
}

}

void printData()
{
cout << '\n';

//print them out
for (int x = 0; x < n_s.size() - 1; ++x)
{
cout << n_s[x].name << '\t' << n_s[x].score << '\n';
}

}

int main()
{

getData();

printData();

keep_window_open();

return 0;

}


This took some thought but didn't take me too long. The bit I tripped up on was pushing back the data into the class vector. Originally I had separate variables and was trying to push them in like this:
     n_s.name.push_back(inputname);
but obviously that wouldn't work because the compiler thought name was a function. Instead I realised I could just create a variable that held both and then push the entire variable into it's respective slots in the vector.

Monday 19 September 2016

Chapter 6 // Exercise 3 - Principles & Practice Using C++

In all these exercises I am using Visual Studio Community 2015 and the header file "std_lib_facilities.h" which can be found here:


http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


My version is spelt differently so adjust the code accordingly if copying and pasting.


Chapter 6 // Exercise 3

Add a factorial operator: use suffix ! operator to represent "factorial." For example, the expression 7! means 7*6*5*4*3*2*1. Make ! bind tighter than * and /; that is 7*8! means 7*(8!) rather than (7*8)!. begin by modifying the grammar to account for a higher-level operator. To agree with the standard mathematical definition of factorial, let 0! evaluate to 1.
Hint: The calculator functions deals with doubles, but factorial is defined only for ints, so just for x!, assign the x to an int and calculate the factorial of that int.

Sweet baby Jesus and the orphans. I read this and thought "what the hell is a factorial? Is he just making shit up now?". After some researching on factorials it's basically represented like this n(n-1). To start off I wrote a program that works out a factorial and got it working just so I understood what I was working with. Below is the program for documentation purposes:

#include "stdafx.h"
#include "std_lib_facilities_new_version.h"
using namespace std;

int getFactorial(int n)
{
if (n == 0)
n = 1;

int factorial = n;

for (int i = n - 1; i > 1; --i)
{
factorial = factorial*i;
}

return factorial;
}

int main()
{
cout << "Please enter a number to find the factorial:\n";
cout << "Press x to quit.\n";

while (cin)
{
int n;
cin >> n;

int f = getFactorial(n);

cout << n << "!" << " = " << f << endl;

cout << "Please enter a number to find the factorial:\n";
}

keep_window_open();

return 0;

}

The for loop in getFactorial() starts with i assigned -1 of whatever the number you input. So if n was 5, i will equal 4. Factorial is then assigned itself; multiplied by i. So for each iteration, i minuses 1 until it reaches 1 and multiplies with the previous answer.

So now we know how do do a factorial, it's just a matter of implementing it within the calculator program. First I added '!' to the case list in get():

Token Token_stream::get()
{
if (full)
{       // do we already have a Token ready?
// remove token from buffer
Token_stream::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':

{
cin.putback(ch);         // put digit back into the input stream
cin >> val;              // read a floating-point number
return Token('#', val);   // let '#' represent "a number"
}

default:
error("Bad token");
}

}

Then, I created a new function called int higherTerm() which is obviously higher than term. This is meant to illustrate to the computer that '!' binds tighter than '*' or '/'. This code is placed directly after primary().

int getFactorial(int n) //function that deals with factorials
{
if (n == 0)
n = 1;

int factorial = n;

for (int i = n - 1; i > 1; --i)
{
factorial = factorial*i;
}

return factorial;
}

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

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

while (true)
{
switch (t.kind)
{
case '!':
{
int ileft = left; //changing the double to an int, this will round down
left = getFactorial(ileft);
t = ts.get();
break;
}

default:
ts.putback(t);     // put t back into the token stream

return left;
}
}


}

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

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

while (true)
{
switch (t.kind)
{
case '*':
{
left *= higherTerm();
t = ts.get();
break;
}

case '/':
{
double d = higherTerm();
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;
}
}
}



So higherTerm() now gets the primary, the function checks to see if there is a '!' after the primary, if not, passes the number on down the food chain. term() now calls to higherTerm() so it gets whatever has been left over from there.

Here is the full program:


#include "stdafx.h"

#include "std_lib_facilities_new_version.h"
using namespace std;

double val; //global variable
//------------------------------------------------------------------------------

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
Token_stream::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':

{
cin.putback(ch);         // put digit back into the input stream
cin >> val;              // read a floating-point number
return Token('#', val);   // let '#' represent "a number"
}

default:
error("Bad token");
}
}

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

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

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

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

int getFactorial(int n);

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

// 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;
break;
}

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

case '#':            // we use '#' to represent a number
{
return t.value;  // return the number's value
break;
}

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

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

int getFactorial(int n) //function that deals with factorials
{
if (n == 0)
n = 1;

int factorial = n;

for (int i = n - 1; i > 1; --i)
{
factorial = factorial*i;
}

return factorial;
}

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

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

while (true)
{
switch (t.kind)
{
case '!':
{
int ileft = left; //changing the double to an int, this will round down
left = getFactorial(ileft);
t = ts.get();
break;
}

default:
ts.putback(t);     // put t back into the token stream

return left;
}
}
}



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

while (true)
{
switch (t.kind)
{
case '*':
{
left *= higherTerm();
t = ts.get();
break;
}

case '/':
{
double d = higherTerm();
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
}
}
}

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

void printInstructions()
{
cout << "Welcome to our simple calculator!\n";
cout << "You can use + - / * and ! for factorial \n";
cout << "Press = to print the answer and x to exit.\n";
cout << "Please enter expressions using floating-point numbers:\n" << endl;
}

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

int main()
try
{
printInstructions();

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

while (t.kind == '=')
t = ts.get();

if (t.kind == 'x')
{
return 0;
}

ts.putback(t);
cout << expression() << '\n';
}
return 0;
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
keep_window_open();
return 1;
}
catch (...) {
cerr << "Oops: unknown exception!\n";
keep_window_open();
return 2;
}

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