Saturday, 28 April 2018

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

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

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


Chapter 8 // Exercise 10



10. Write a function maxv() that returns the largest element of a vector argument.


#include "stdafx.h"
#include "std_lib_facilities.h"

double maxv(const vector<double>& v)
{
 //if vector only has 1 value return that
 if (v.size() == 1)
  return v[0];

 //make first value in vector max value
 double largest = v[0];

 //go through every value, if the next value is bigger
 //than the last, make that the new max value
 for (int i = 0; i < v.size(); ++i)
 {
  if (largest < v[i])
   largest = v[i];
 }

 return largest;
}

int main()
{
 vector<double> numbers = { 1000, 6, -12, 700, 56, 89, -900, 1 };

 double max = maxv(numbers);

 cout << max << endl;

 keep_window_open();

 return 0;
}

At first I tried to use the max_element() function however it didn't seem to like working with vectors, so I used the template code to draft this function. It was a lot simpler than I initially thought. Since Bjarne didn't specify a data type I went with double however you can easily change the data type yourself.

Wednesday, 25 April 2018

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

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

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


Chapter 8 // Exercise 9



9. Write a function that given two vector<double>s price and weight computes a value (an "index") that is the sum of all price[i]*weight[i]. Make sure to have weight.size()==price.size().


#include "stdafx.h"
#include "std_lib_facilities.h"

//read numbers into weight
vector<double> getAmount(string label)
{
 vector<double> v_amount;
 int howMany;
 double amount;

 cout << "How many items are there for " << label << ": ";
 cin >> howMany;
 for (int i = 0; i < howMany; ++i)
 {
  cout << ">>";
  cin >> amount;
  v_amount.push_back(amount);
  cout << endl;
 }
 
 return v_amount;
}

//multiply weight by price if vectors are same size
double getSum(const vector<double>& price, const vector<double>& weight)
{
 double sum = 0;

 if (price.size() == weight.size())
 {
  for (int i = 0; i < price.size(); ++i)
  {
   sum += price[i] * weight[i];
  }
 }
 else
  cout << "Sorry those vectors are not the same size.\n";

 cout << "\nSum: " << sum << endl;

 return sum;
}


int main()
{
 vector<double> weight = getAmount("weight");
 vector<double> price = getAmount("price");

 double sum = getSum(price, weight);

 keep_window_open();

 return 0;
}

Saturday, 21 April 2018

Chapter 8 // Exercise 7, 8 - Principles & Practice Using C++

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

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


Chapter 8 // Exercise 7



7. Read five names into a vector<string> name, then prompt the user for the ages of the people names and store the ages in a vector<double> age. Then print out the five (name[i],age[i]) pairs. Sort the names (sort(name.begin(), name.end())) and print out the (name[i], age[i]) pairs. The tricky part here is to get the age vector in the correct order to match the sorted name vector. Hint: Before sorting name, take a copy and use that to make a copy of age in the right order after sorting name.


#include "stdafx.h"
#include "std_lib_facilities.h"
//print vectors to the screen
void print(const vector<double>& ages, const vector<string>& names)
{
 for (int i = 0; i < ages.size(); ++i)
 {
  cout << names[i] << ": " << ages[i] << endl;
 }

 cout << "--------------------------------" << endl;
}

//read five names into a vector string
vector<string> getNames(vector<string>& v)
{
 string name;

 for (int i = 0; i < 5; ++i)
 {
  cout << "Name Please: ";
  cin >> name;
  v.push_back(name);
  cout << endl;
 }

 return v;
}

//read 5 ages for names
vector<double> getAges(const vector<string>& name, vector<double>& v_age)
{
 double age;

 for (int i = 0; i < name.size(); ++i)
 {
  cout << "Age for " << name[i] << ": ";
  cin >> age;
  v_age.push_back(age);
  cout << endl;
 }

 return v_age;
}

//compare copy of name vector to new to sort ages correctly
void sortNames(vector<string> name_copy, vector<string>& name, vector<double> age_copy, vector<double>& age)
{
 sort(name.begin(), name.end());  //sort actual names

 //go through each member of sorted name
 for (int i = 0; i < name.size(); ++i)
 {
  //go through each member of original copy name
  for (int j = 0; j < name.size(); ++j)
  {
   //if sorted name matches original
   if (name[i] == name_copy[j])
   {
    //assign original age to new position to match sorted vector
    age[i] = age_copy[j];
   }
  }
 }
}


int main()
{
 //get names
 vector<string> names;
 getNames(names);

 //get ages
 vector<double> ages;
 getAges(names, ages);

 //print original vectors
 print(ages, names);

 //sort the vectors using copies to compare
 sortNames(names, names, ages, ages);

 //print vectors again to see changes
 print(ages, names);

 keep_window_open();

 return 0;
}


Chapter 8 // Exercise 8


8. Then, do that exercise again but allowing an arbitrary number of names.

The only part of this I changed was the function to get the names:

//read five names into a vector string
vector<string> getNames(vector<string>& v)
{
 string name;

 cout << "Press 'q' to stop entering names" << endl;

 while(name != "q")
 {
  cout << "Name Please: ";
  cin >> name;
  if (name == "q")
   break;
  v.push_back(name);
  cout << endl;
 }

 return v;
}

Wednesday, 18 April 2018

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

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

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


Chapter 8 // Exercise 5



5. Write two functions that reverse he order of elements in a vector<int>. For example 1,3,5,7,9 becomes 9,7,5,3,1. The first reverse function should produce a new vector with the reversed sequence, leaving its original vector unchanged. The other reverse function should reverse the elements of its vector without using any other vectors (hint: swap).


#include "stdafx.h"
#include "std_lib_facilities.h"

//prints a given vector to the screen with a label
void print(string& label, const vector<int>& v)
{
 cout << label << ": " << endl;

 for (int i = 0; i < v.size(); ++i)
 {
  //if incrementor is divisible by 10, start a new line to print
  cout << v[i] << '\t';
  if (i % 10 == 0 && i != 0)
   cout << '\n';
 }

 cout << '\n';
}

//calculates fibonnaci sequence for a given amount of numbers
void fibonnaci(int first, int second, vector<int>& v, int howMany)
{
 //is vector empty?
 if (v.size() == 0)
 {
  v.push_back(first);
  v.push_back(second);

  int temp;

  //pushback numbers from sequence depending on how many we want
  //start with 3rd number
  for (int i = 1; i < howMany; ++i)
  {
   temp = v[i] + v[i - 1];
   v.push_back(temp);
  }
 }
 else
  cout << "Sorry that vector is not empty.\n";
}

//swap vectors elements creating new vector leaving original unchanged
vector<int> swap1(const vector<int>& originalV)
{
 vector<int> newV;
 for (int i = originalV.size() - 1; i >= 0; --i)
 {
  newV.push_back(originalV[i]);
 }

 return newV;
}

//swap vectors elements using swap
void swap2(vector<int>& originalV)
{
 for (int i = 0; i < originalV.size()/2; ++i)
 {
  swap(originalV[i], originalV[originalV.size() - (i + 1)]);
 }
}

int main()
{
 vector<int> fibonacciNumbers;
 vector<int> newFibonacci;

 //populate vector with sequence
 fibonnaci(1, 2, fibonacciNumbers, 10);

 //swap creating a copy and assigning to new vector
 newFibonacci = swap1(fibonacciNumbers); 

 //print the vectors
 string label = "Fibonacci Numbers";
 print(label, fibonacciNumbers);
 label = "New Fibonacci";
 print(label, newFibonacci);

 //print the original vector
 label = "Fibonacci Numbers";
 print(label, fibonacciNumbers);

 //swap using swap function and no other vectors
 swap2(fibonacciNumbers);

 //print the original vector which has now been modified
 label = "Swapped Fibonocci Numbers";
 print(label, fibonacciNumbers);

 keep_window_open();

 return 0;
}

For this exercise I decided to build upon the previous ones instead of writing numbers to pushback into random vectors. The first swap, swap1() works by taking a const reference to the original vector (so it doesn't change it) and applies those values to a new vector. The for loop starts at the end of the original vector and pushes back a number into the new one until it gets to the first value. It then returns the new vector as value.

Chapter 8 // Exercise 


6. Write versions of the functions from exercise 5, but with a vector<string>.


#include "stdafx.h"
#include "std_lib_facilities.h"

//prints a given string vector to the screen with a label
void print(string& label, const vector<string>& v)
{
 cout << label << ": " << endl;

 for (int i = 0; i < v.size(); ++i)
 {
  //if incrementor is divisible by 10, start a new line to print
  cout << v[i] << '\t';
  if (i % 10 == 0 && i != 0)
   cout << '\n';
 }

 cout << '\n';
}

//swap string vectors using another vector
vector<string> swapString1(const vector<string>& originalV)
{
 vector<string> newV;
 for (int i = originalV.size() - 1; i >= 0; --i)
 {
  newV.push_back(originalV[i]);
 }

 return newV;
}

void swapString2(vector<string>& originalV)
{
 for (int i = 0; i < originalV.size() / 2; ++i)
 {
  swap(originalV[i], originalV[originalV.size() - (i + 1)]);
 }
}

int main()
{
 vector<string> myString = { "hello", "world", "this", "is", "a", "blog", "post" };
 vector<string> newString;

 //swap creating a copy
 newString = swapString1(myString);

 //print the vectors
 string label = "My String";
 print(label, myString);
 label = "New String";
 print(label, newString);

 //swap without creating a copy
 label = "My String";
 print(label, myString);

 swapString2(myString);

 label = "My String";
 print(label, myString);

 keep_window_open();

 return 0;
}

Sunday, 15 April 2018

Chapter 8 // Exercise 3, 4 - Principles & Practice Using C++

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

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


Chapter 8 // Exercise 3



3. Create a vector of Fibonacci numbers and print them using the function from exercise 2. To create the vector, write a function, fibonacci(x,y,v,n), where integers x and y are ints, v is an empty vector<int>, and n is the number of elements to put into v; v[0] will be x and v[1] will be y. A Fibonacci number is one that is part of a sequence where each element is the sum of the previous ones. For example, starting with 1 and 2, we get 1,2,3,4,8,13,21,....Your fibonacci() function should make such a sequence starting with its x and y arguments.

For this one I changed the name of few things to make them more descriptive. I also decided to not make the ints references and instead allow the user to pass numbers directly as arguments. The vector is just passed by reference in fibonacci() due to the need to modify it.

#include "stdafx.h"
#include "std_lib_facilities.h"

//prints a given vector to the screen with a label
void print(string& label, const vector<int>& v)
{
 cout << label << ": " << endl;

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

 cout << '\n';
}

//calculates fibonnaci sequence for a given amount of numbers
void fibonnaci(int first, int second, vector<int>& v, int howMany)
{
 //is vector empty?
 if (v.size() == 0)
 {
  v.push_back(first);
  v.push_back(second);

  int temp;

  //pushback numbers from sequence depending on how many we want
  //start with 3rd number
  for (int i = 1; i < howMany; ++i)
  {
   temp = v[i] + v[i - 1];
   v.push_back(temp);
  }
 }
 else
  cout << "Sorry that vector is not empty.\n";
}

int main()
{
 vector<int> fibonacciNumbers;

 //populate vector with sequence
 fibonnaci(1, 2, fibonacciNumbers, 10);

 //print the vector
 string label = "Fibonacci Numbers";
 print(label, fibonacciNumbers);

 keep_window_open();

 return 0;
}

Chapter 8 // Exercise 4
4. An int can hold integers only up to a maximum number. Find approximation of that maximum number by using fibonacci().
#include "stdafx.h"
#include "std_lib_facilities.h"

//prints a given vector to the screen with a label
void print(string& label, const vector<int>& v)
{
 cout << label << ": " << endl;

 for (int i = 0; i < v.size(); ++i)
 {
  //if incrementor is divisible by 10, start a new line to print
  cout << v[i] << '\t';
  if (i % 10 == 0 && i != 0)
   cout << '\n';
 }

 cout << '\n';
}

//calculates fibonnaci sequence for a given amount of numbers
void fibonnaci(int first, int second, vector<int>& v, int howMany)
{
 //is vector empty?
 if (v.size() == 0)
 {
  v.push_back(first);
  v.push_back(second);

  int temp;

  //pushback numbers from sequence depending on how many we want
  //start with 3rd number
  for (int i = 1; i < howMany; ++i)
  {
   temp = v[i] + v[i - 1];
   v.push_back(temp);
  }
 }
 else
  cout << "Sorry that vector is not empty.\n";
}

int main()
{
 vector<int> fibonacciNumbers;

 //populate vector with sequence
 fibonnaci(1, 2, fibonacciNumbers, 10);

 //print the vector
 string label = "Fibonacci Numbers";
 print(label, fibonacciNumbers);

 //after printing 100 numbers this is highest number it can go to
 int number = 1836311903;
 cout << '\n' << number;

 keep_window_open();

 return 0;
}
Here I added a couple of lines in print to print numbers in rows of 10. When told to find 100 numbers the number before everything goes weird is 1836311903. 

Wednesday, 11 April 2018

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

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

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


Chapter 8 // Exercise 2



2. Write a function print() that prints a vector of ints to cout. Give it two arguments: a string for 'labeling' the output and a vector.

Not quite sure what he means when he wants us to 'label' the output. Does he mean a note that says "these numbers are from this vector"? That's how I've interpreted it anyway. For the print() function we pass a string reference to avoid copying data and since we are just printing the contents of a vector there is no need to modify it so it is passed via const reference. For this exercise I added a little in main just to show the function working.

#include "stdafx.h"
#include "std_lib_facilities.h"

//prints a given vector to the screen with a label
void print(string& label, const vector<int>& v)
{
 cout << label << ": " << endl;

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

 cout << '\n';
}

int main()
{
 vector<int> numberVector = { 1,2,3,4,5,6,7,8,9,10 };
 string label = "Vector of Numbers";

 print(label, numberVector);

 keep_window_open();

 return 0;
}

Sunday, 8 April 2018

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

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

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


Chapter 8 // Exercise 1



1. Modify the calculator program from Chapter 7 to make the input stream an explicit parameter (as shown in section 8.5.8), rather than simple using cin. Also give the Token_stream constructor (section 7.8.2) an istream& parameter so that when we figure out how to make out own istream (e.g., attached to files), we can use the calculator for those. Hint: Don't try to copy an istream.

// pandp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "std_lib_facilities.h"
#include <windows .h>

//user defined type to hold name-value pair for use in calculator
struct Token {
 char kind;
 double value;
 string name;
 Token(char ch) :kind(ch), value(0) { }
 Token(char ch, double val) :kind(ch), value(val) { }
 Token(char ch, string n) :kind(ch), name(n) { }
};

//user-defined type that handles retrieving items from input
class Token_stream {
 bool full;
 Token buffer;
public:
 Token_stream() :full(0), buffer(0) { } //default constructor
 Token_stream(istream&);     //constructor for istream

 Token get();
 void unget(Token t) { buffer = t; full = true; }

 void ignore(char);
};

double expression(Token_stream& ts);  //forward declaration
void calculate(Token_stream& ts);
void showHelp();

const char let = 'L';
const char quit = 'Q';
const char print = '\n';
const char number = '8';
const char name = 'a';
const char squareR = 's';
const char findPow = 'p';
const char isConst = 'C';
const char help = 'h';

const string declKey = "let";
const string quitKey = "quit";
const string sqrtKey = "sqrt";
const string powKey = "pow";
const string constKey = "const";
const string printKey = "'\n'";


//evaluate each char in the stream and determine what it is 
Token Token_stream::get()
{
 if (full) //check if we have already have a token ready
 {
  full = false;
  return buffer;
 }

 char ch;
 cin.get(ch);        //does not skip whitespace
 while (isspace(ch))       //if ch is whitespace
 {
  if (ch == '\n')       //if ch == newline 
   return Token(print);    //print result

  cin.get(ch);       //if not newline get next ch in stream
 }

 switch (ch)
 {
 case '(': case ')': case '+': case '-':
 case '*': case '/': case '%':
 case '=': case ',':
  return Token(ch);     //let each char represent itself
 case '.':
 case '0': case '1': case '2': case '3':
 case '4': case '5': case '6': case '7':
 case '8': case '9':
 {
  cin.unget();      //put digit back into the input stream
  double val;
  cin >> val;       //read a floating-point number
  return Token{ number, val };  //return number or . with a value, put back into buffer
 }

 //allow user defined variables if user types #
 case '#':
  return Token(let);

  //if user presses h or H return to execute help function
 case 'h': case 'H':
  return Token(help);

 default:
  //do this if ch is a letter
  if (isalpha(ch) || ch == '_')
  {
   string s;
   s += ch;

   //while there are still chars in cin, read them into s
   while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_'))
    s += ch;
   cin.unget();

   //if string is equal to other commands defined below, return them
   if (s == declKey)
    return Token(let);
   if (s == constKey)
    return Token(isConst);
   if (s == quitKey)
    return Token(quit);
   if (s == sqrtKey)
    return Token(squareR);
   if (s == powKey)
    return Token(findPow);

   return Token(name, s);
  }

  //if the char does not fit any of these paramenters return an error message
  error("Bad token");
 }
}

//discard characters up to and including a c
//c represents the kind of token
void Token_stream::ignore(char c)
{
 //first look in the buffer
 if (full && c == buffer.kind)
 {
  full = false;
  return;
 }

 full = false;

 //now search input
 char ch;
 while (cin >> ch)
  if (ch == c) return;
}

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

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

struct Variable
{
 string name;
 double value;
 bool isConst;
 Variable(string n, double v, bool ic) :name(n), value(v), isConst(ic) { }
};

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

class Symbol_table {
 vector<Variable> var_table;
public:
 double get(string s);
 void set(string s, double d);
 bool is_declared(string s);
 double define(string var, double val, bool isConst);
 double declare(Token_stream& ts);
};

//return the value of the Variable named s
double Symbol_table::get(string s)
{
 for (int i = 0; i < Symbol_table::var_table.size(); ++i)
 {
  if (Symbol_table::var_table[i].name == s)
  {
   return Symbol_table::var_table[i].value;
  }
 }
 error("get: undefined name ", s);
}

//set the Variable named s to d
void Symbol_table::set(string s, double d)
{
 for (int i = 0; i < Symbol_table::var_table.size(); ++i)
 {
  //allow redefinitions as long as variable isn't const
  if (Symbol_table::var_table[i].name == s && Symbol_table::var_table[i].isConst == false)
  {
   Symbol_table::var_table[i].value = d;
   return;
  }
 }
 error("set: undefined name ", s);
}

//is variable already declared?
bool Symbol_table::is_declared(string s)
{
 for (int i = 0; i < Symbol_table::var_table.size(); ++i)
 {
  if (Symbol_table::var_table[i].name == s && Symbol_table::var_table[i].isConst == true)
   error("Cannot reassign const variable");
  else if (Symbol_table::var_table[i].name == s && Symbol_table::var_table[i].isConst == false)
   return true;
 }

 return false;
}

//allow programmers to add (var,val) to variable vector
double Symbol_table::define(string var, double val, bool isConst)
{
 if (is_declared(var))
  error(var, " declared twice");

 var_table.push_back(Variable(var, val, isConst));

 return val;
}

//check for name definition errors
double Symbol_table::declare(Token_stream& ts)
{
 Token t = ts.get();

 //is const the next word in the stream?
 bool isC;
 if (t.kind == isConst)
 {
  isC = true;
  t = ts.get();  //get the the next word in the stream for the name
 }
 else
  isC = false;

 if (t.kind != name)
  error("name expected in declaration;");

 string name = t.name;

 //if name has already been declared ask if they want to change it
 if (Symbol_table::is_declared(name))
 {
  cout << name + ", declared twice. Would you like to reassign? (No need to print with ';') y/n > ";
  cin.clear();
  cin.ignore(10000, '\n'); //clear the buffer
  string ans;
  getline(cin, ans);
  if (ans == "n")
   error(name, ", will not be reassigned; ");
  if (ans == "y")
  {
   cout << "(No need to print with ';') Please enter new value: ";
   int val;
   cin >> val;
   Symbol_table::set(name, val);

   double d = val;   //return value to print to reset calculator
   return d;
  }

 }

 Token t2 = ts.get();
 if (t2.kind != '=')
  error("= missing in declaration of ", name);

 double d = expression(ts);
 Symbol_table::var_table.push_back(Variable(name, d, isC));

 return d;
}

//-----------------------------------------------------------------------------------------------------//
Symbol_table symbols;
//-----------------------------------------------------------------------------------------------------//

//check tokenstream for 'your char here'
Token checkForChar(Token t, char ch)
{
 if (t.kind != ch)
 {
  //convert ch to string for error message
  string chstring = "";
  chstring += ch;
  error("'" + chstring + "' expected");
 }

 return t;
}

//solve characters received from ts.get()
double primary(Token_stream& ts)
{
 //get character from stream
 Token t = ts.get();
 switch (t.kind)
 {
  //solve "(expression)"
 case '(':
 {
  double d = expression(ts);
  t = ts.get();
  checkForChar(t, ')');
  return d;
 }

 //solve "-primary"
 case '-':
  return -primary(ts);

  //solve "number"
 case number:
  return t.value;

  //solve "name"
 case name:
  return symbols.get(t.name);

  //solve "sqrt(expression)"
 case squareR:
 {
  //get next char after 'sqrt' if not '(' then error   
  t = ts.get();
  checkForChar(t, '(');

  //if expression is less than 0 print an error
  double d = expression(ts);
  if (d < 0)
   error("Cannot squareroot negative integers");

  //get next char after expression, if not ')' then error
  t = ts.get();
  checkForChar(t, ')');

  // return square root of the expression taken from the tokenstream
  return sqrt(d);
 }

 //solve "pow(expression, expression)"
 case findPow:
 {
  //get next char after 'pow' if not '(' then error   
  t = ts.get();
  checkForChar(t, '(');

  //get the expression after '('
  double d = expression(ts);

  //get next char after 'expression' if not ',' then error   
  t = ts.get();
  checkForChar(t, ',');

  //get the expression after ','
  double i = expression(ts);

  //get next char after expression, if not ')' then error
  t = ts.get();
  checkForChar(t, ')');

  // return expression using pow() from 
  return pow(d, i);
 }

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

//solves for primary, *, / and %
double term(Token_stream& ts)
{
 double left = primary(ts);
 while (true)
 {
  Token t = ts.get();
  switch (t.kind)
  {
  case '*':
   left *= primary(ts);
   break;
  case '/':
  {
   double d = primary(ts);
   if (d == 0)
    error("divide by zero");
   left /= d;
   break;
  }
  case '%':
  {
   double d = primary(ts);
   if (d == 0)
    error("%:divide by zero");
   left = fmod(left, d);
   break;
  }
  default:
   ts.unget(t);
   return left;
  }
 }
}

//solves for terms and + -
double expression(Token_stream& ts)
{
 double left = term(ts);
 while (true)
 {
  Token t = ts.get();

  switch (t.kind)
  {
  case '+':
   left += term(ts);
   break;
  case '-':
   left -= term(ts);
   break;
  default:
   ts.unget(t);
   return left;
  }
 }
}

double statement(Token_stream& ts)
{
 Token t = ts.get();
 switch (t.kind)
 {
 case let:
  return symbols.declare(ts);
 default:
  ts.unget(t);
  return expression(ts);
 }
}

void clean_up_mess()
{
 cout << "\nRestarting Calculator .";
 Sleep(400);
 cout << ".";
 Sleep(400);
 cout << ".";
 Sleep(400);
 cout << ".";
 Sleep(400);
 cout << ".\n\n";
 cin.clear();
 cin.ignore(10000, '\n'); //clear the buffer 
}

const string prompt = "> ";
const string result = "= ";

void calculate(Token_stream& ts)
{
 while (true) try
 {
  cout << prompt;
  Token t = ts.get();

  while (t.kind == print)
   t = ts.get();       //first discard all 'prints'

             //if user types h or H show help, then clear the stream and get new values
  if (t.kind == help)
  {
   showHelp();
   cout << prompt;
   t = ts.get();
  }

  if (t.kind == quit)
   return;

  ts.unget(t);

  cout << result << statement(ts) << endl;
 }
 catch (runtime_error& e)
 {
  cerr << e.what() << endl;
  clean_up_mess();
 }
}

int main()

try {
 symbols.define("pi", 3.1415926535, true);
 symbols.define("e", 2.7182818284, true);
 symbols.define("k", 1000, false);

 Token_stream ts;

 calculate(ts);
 return 0;
}

catch (exception& e) {
 cerr << "exception: " << e.what() << endl;
 char c;
 while (cin >> c && c != ';');
 return 1;
}

catch (...) {
 cerr << "exception\n";
 char c;
 while (cin >> c && c != ';');
 return 2;
}

void showHelp()
{
 cout << "-----------------------HOW TO USE THE CALCULATOR------------------------\n";
 cout << "------------------------------------------------------------------------\n";
 cout << "1. To exit the program type 'quit' and press enter.\n";
 cout << "2. To show results, press enter.\n";
 cout << "3. To create your own keyword, type 'let yourWord = value'\n";
 cout << "   You can let a keyword be a const by typing 'const' before 'let'\n";
 cout << "4. To find the squareroot, type 'sqrt' followed by your number.\n";
 cout << "5. To find a number to a power of, type 'pow(number,number)'\n";
 cout << "------------------------------------------------------------------------\n\n";

 cin.clear();
 cin.ignore(10000, '\n'); //clear the buffer for new values
}

Wednesday, 4 April 2018

Chapter 8 // Drill 3 - Principles & Practice Using C++

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

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


Chapter 8 // Drill 3



3. Write a program using a single file containing three namespaces X, Y, and Z so that the following main() works correctly:

int main()
{
X::var = 7;
X::print(); //print X's var

using namespace Y;
var = 9;
print(); //print Y's var

{
using Z::var;
using Z::print;
var = 11;
print(); //print Z's var
}

print(); //print Y's var
X::print(); //print X's var

}

Each namespace needs to define a variable called var and a function called print() that outputs the appropriate var using cout.


#include "std_lib_facilities.h"

namespace X {
 double var;

 void print()
 {
  cout << "X: " << var << endl;
 }
}

namespace Y {
 double var;

 void print()
 {
  cout << "Y: " << var << endl;
 }
}

namespace Z {
 double var;

 void print()
 {
  cout << "Z: " << var << endl;
 }
}

int main()
{
 X::var = 7;
 X::print();  //print X's var

 using namespace Y;
 var = 9;
 print();  //print Y's var

 {
  using Z::var;
  using Z::print;
  var = 11;
  print(); //print Z's var
 }

 print();  //print Y's var
 X::print();  //print X's var

 keep_window_open();

 return 0;
}

Sunday, 1 April 2018

Chapter 8 // Drill 2 - Principles & Practice Using C++

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

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


Chapter 8 // Drill 2



2. Write three functions swap_v(int, int), swap_r(int&, int&), and swap_cr(const int&, const int&). Each should have the body
{int temp; temp = a, a = b; b = temp}

where a and b are the names of the arguments. Try calling each functions like this:
int x = 7;
int y = 9;
swap_?(x, y);
swap_?(7, 9);
const int cx = 7;
const int cy = 9;
swap_?(cx, cy);
swap_?(7.7, 9.9);
double dx = 7.7;
double dy = 9.9;
swap_?(dx, dy);
swap_?(7.7, 9.9);

Which functions and calls compiled and why?
After each swap that compiled, print the value of the arguments after the call to see it they were actually swapped. If you are surprised by the result, consult section 8.6.

First of all the program won't compile because you cannot change a const value so the third function needs to have a different body. This can be done by creating a second temp variable, assigning b to it and then sending temp and temp2 to one of the previous functions to be swapped.

Also, when sending numbers to the functions they will not be printed as functions can only return 1 value so the print was added to end of each calling function instead apart from the const function as that calls one that already has a print command.

Also on the functions that send numbers you cannot use pass-by-reference because that requires an object to be passed not a value. Also the double values will be truncated as all three functions use ints.

For this exercise I modified the previous drill to accomadate this one, so the program is split into three seperate files; my.h, my.cpp and use.cpp which contains main();

//my.h
#pragma once
//my.h
#include "std_lib_facilities.h"

//declarations
void swap_v(int, int);
void swap_r(int&, int&);
void swap_cr(const int&, const int&);

void keepWindowOpen();


//my.cpp
//my.cpp

#include "my.h"


//swap two integers using pass-by-value
void swap_v(int a, int b)
{
 int temp;
 temp = a;
 a = b;
 b = temp;

 cout << a << '\t' << b << endl;

 return;
}

//swap two integers using pass-by-reference
void swap_r(int& a, int& b)
{
 int temp;
 temp = a;
 a = b;
 b = temp;

 cout << a << '\t' << b << endl;

 return;
}

//swap two integers using pass-by-const-reference
void swap_cr(const int& a, const int& b)
{
 int temp;
 int temp2;

 temp = a;
 temp2 = b;

 swap_r(temp, temp2);

 return;
}

//function to keep the window open
void keepWindowOpen()
{
 char c;
 cout << "\nPress any key to quit: ";
 cin >> c;
}


//use.cpp
/use.cpp

#include "my.h"

int main()
{
 //variables to swap
 int x = 7;
 int y = 9;

 swap_r(x, y);
 swap_cr(7, 9);

 //const variables to swap
 const int cx = 7;
 const int cy = 9;

 swap_v(cx, cy);
 swap_cr(7.7, 9.9);

 //double variables to swap
 double dx = 7.7;
 double dy = 9.9;

 swap_v(dx, dy);
 swap_cr(7.7, 9.9);

 //keep window open until any key press
 keepWindowOpen();
}