Sunday, 10 June 2018

Chapter 9 // Exercise 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 9 // Exercise 6



Add operators for Book class. Have the == operator check whether the ISBN numbers are the same for two books. Have the != also compare the ISBN numbers. Have << print out the title, author, and ISBN on separate lines.

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

class Book
{
public:
 Book();
 ~Book();

 string getISBN() const { return m_isbn; }
 string getTitle() const { return m_title; }
 string getAuthor() const { return m_author; }
 int    getDate() const { return m_date; }
 bool   getStatus() const { return m_checkedOut; }

 void setISBN(string num1, string num2, string num3, string char1);
 void setTitle(string title) { m_title = title; }
 void setAuthor(string author) { m_author = author; }
 void setDate(string year);

 void checkBookOut() { m_checkedOut = true; };
 void checkBookIn() { m_checkedOut = false; };

private:
 //m_ prefix to denote member variable
 string m_isbn, m_title, m_author;
 int m_date;
 bool m_checkedOut;
};

//--OVERLOAD OPERATORS--//

//compare ISBN numbers
bool operator==(const Book& a, const Book& b)
{
 return a.getISBN() == b.getISBN();
}

bool operator!=(const Book& a, const Book& b)
{
 return a.getISBN() != b.getISBN();
}

//print out book
ostream& operator<<(ostream& os, const Book& book)
{
 return os << "Title: "      << book.getTitle()  << endl
     << "Author: "     << book.getAuthor() << endl
           << "Copyright: "  << book.getDate()   << endl
           << "ISBN: "       << book.getISBN()   << endl
           << "Checked out:" << book.getStatus() << endl
           << endl;
}


//constructor
Book::Book()
{
 m_isbn = m_title = m_author = "";
 m_date = 0;
 m_checkedOut = false;
}

//deconstructor
Book::~Book() {}

//set the ISBN
void Book::setISBN(string num1, string num2, string num3, string char1)
{
 size_t check;
 //check first number
 check = num1.find_first_not_of("0123456789");
 while (check != string::npos)
 {
  cout << "Not a valid ISBN number, try again: ";
  cin >> num1;
  check = num1.find_first_not_of("0123456789");
 }

 //check second number
 check = num2.find_first_not_of("0123456789");
 while (check != string::npos)
 {
  cout << "Not a valid ISBN number, try again: ";
  cin >> num2;
  check = num2.find_first_not_of("0123456789");
 }

 //check third number
 check = num3.find_first_not_of("0123456789");
 while (check != string::npos)
 {
  cout << "Not a valid ISBN number, try again: ";
  cin >> num3;
  check = num3.find_first_not_of("0123456789");
 }

 //check last character
 check = char1.find_first_not_of("0123456789ABCDEFGHIJKLMNOPQRSTUVWXY");
 while (check != string::npos)
 {
  cout << "Not a valid ISBN digit or letter, try again: ";
  cin >> char1;
  check = char1.find_first_not_of("0123456789ABCDEFGHIJKLMNOPQRSTUVWXY");
 }

 //set isbn
 m_isbn = "";
 m_isbn.append(num1);
 m_isbn.append("-");
 m_isbn.append(num2);
 m_isbn.append("-");
 m_isbn.append(num3);
 m_isbn.append("-");
 m_isbn.append(char1);
}

//set and check the year of copyright
void Book::setDate(string year)
{
 size_t check;
 check = year.find_first_not_of("0123456789");
 while (check != string::npos || year.size() != 4)
 {
  cout << "Not a valid year try again: ";
  cin >> year;
  check = year.find_first_not_of("0123456789");
 }

 m_date = stoi(year);
}

int main()
{
 Book lotr;
 lotr.setTitle("Lord Of The Rings");
 lotr.setAuthor("J.R.R Tolkien");
 lotr.setDate("1954");
 lotr.setISBN("1111", "1111", "1111", "J");
 cout << lotr;

 lotr.setISBN("123", "0", "4444", "6");
 lotr.checkBookOut();
 cout << lotr;

 keep_window_open();

 return 0;
}

I changed the get functions to const on this version to prevent errors when using const versions of Book in the operators. Also, instead of using an if statement to print out specific statements in relation to a book being printed out, it just prints out 0 or 1 now. Other than that, not much was changed in this version.

Friday, 8 June 2018

Chapter 9 // Exercise 5 - 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 9 // Exercise 5



This exercise and the next few require you to design and implement a Book class, such as you can imagine as part of software for a library. Class Book should have members for the ISBN, title, author, and copyright date. Also store data on whether or not the book is checked out. Create functions for returning those data values. Create functions for checking a book in and out. Do simple validation of data entered into a Book; for example, accept ISBNs only if the form n-n-n-x where n is an integer and x is a digit or letter. Store an ISBN as a string.


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

class Book
{
public:
 Book();
 ~Book();

 string getISBN()   { return m_isbn; }
 string getTitle()  { return m_title; }
 string getAuthor() { return m_author; }
 int    getDate()   { return m_date; }
 bool   getStatus() { return m_checkedOut; }

 void setISBN(string num1, string num2, string num3, string char1);
 void setTitle(string title) { m_title = title; }
 void setAuthor(string author) { m_author = author; }
 void setDate(string year);
 
 void checkBookOut() { m_checkedOut = true; };
 void checkBookIn() { m_checkedOut = false; };

 void printStats();

private:
 //m_ prefix to denote member variable
 string m_isbn, m_title, m_author;
 int m_date;
 bool m_checkedOut;
};

//constructor
Book::Book()
{
 m_isbn = m_title = m_author = "";
 m_date = 0;
 m_checkedOut = false;
}

//deconstructor
Book::~Book() {}

//set the ISBN
void Book::setISBN(string num1, string num2, string num3, string char1)
{
 size_t check;
 //check first number
 check = num1.find_first_not_of("0123456789");
 while (check != string::npos)
 {
  cout << "Not a valid ISBN number, try again: ";
  cin >> num1;
  check = num1.find_first_not_of("0123456789");
 }

 //check second number
 check = num2.find_first_not_of("0123456789");
 while (check != string::npos)
 {
  cout << "Not a valid ISBN number, try again: ";
  cin >> num2;
  check = num2.find_first_not_of("0123456789");
 }

 //check third number
 check = num3.find_first_not_of("0123456789");
 while (check != string::npos)
 {
  cout << "Not a valid ISBN number, try again: ";
  cin >> num3;
  check = num3.find_first_not_of("0123456789");
 }

 //check last character
 check = char1.find_first_not_of("0123456789ABCDEFGHIJKLMNOPQRSTUVWXY");
 while (check != string::npos)
 {
  cout << "Not a valid ISBN digit or letter, try again: ";
  cin >> char1;
  check = char1.find_first_not_of("0123456789ABCDEFGHIJKLMNOPQRSTUVWXY");
 }

 //set isbn
 m_isbn = "";
 m_isbn.append(num1);
 m_isbn.append("-");
 m_isbn.append(num2);
 m_isbn.append("-");
 m_isbn.append(num3);
 m_isbn.append("-");
 m_isbn.append(char1);
}

//set and check the year of copyright
void Book::setDate(string year)
{
 size_t check;
 check = year.find_first_not_of("0123456789");
 while (check != string::npos || year.size() != 4)
 {
  cout << "Not a valid year try again: ";
  cin >> year;
  check = year.find_first_not_of("0123456789");
 }

 m_date = stoi(year);
}

//print book details
void Book::printStats()
{
 cout << "Title: " << m_title << endl;
 cout << "Author: " << m_author << endl;
 cout << "Copyright: " << m_date << endl;
 cout << "ISBN: " << m_isbn << endl;
 if (m_checkedOut)
  cout << "Checked out: Yes" << endl;
 else
  cout << "Checked out: No" << endl;

 cout << endl;
}


int main()
{
 Book lotr;
 lotr.setTitle("Lord Of The Rings");
 lotr.setAuthor("J.R.R Tolkien");
 lotr.setDate("1954");
 lotr.setISBN("1111", "1111", "1111", "J");
 lotr.printStats();

 lotr.setISBN("123", "0", "4444", "6");
 lotr.checkBookOut();
 lotr.printStats();

 keep_window_open();

 return 0;
}


This was quite a confusing task as many assumptions had to be made. First, what kind of copyright date should be set? Generally the day and month are optional, so I decided to only accept the year of copyright. Second, how many integers could be allowed for the ISBN format? I'm not sure if he meant only 1 number or however many. For example 1-1-1-H, or 11111-45676543-4-7. I decided to go with the latter.

The hardest part was the check for the ISBN, however whilst searching how to solve turning a string into an int, I came across a method of std::string called 'find_first_not_of' which handily takes in a string of letters that you want included and then returns the position of the first letter not wanted. This made checking the ISBN parts easy, as the while is set to check if there is a position or not. If there is one, then an undesired character was entered, if there is no position then there were no unwanted characters. A very handy method.

Tuesday, 5 June 2018

Chapter 9 // Exercise 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 9 // Exercise 4


Look at the headache-inducing last example of section 8.4. Indent it properly and explain the meaning of each construct. Note that the example does do anything meaningful; it is pure obfuscation.

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

//just ew
struct X
{
 //strangely returns 1 no matter what
 void f(int x)
 {
  struct Y
  {
   int f() { return 1; }
   int m;
  };

  int m;
  m = x; 
  Y m2;
  return f(m2.f());
 }

 int m;
 //if m, return 3 if not return whatever is in m + 2
 void g(int m)
 {
  if (m)
   f(m + 2);
  else
  {
   g(m + 2);
  }
 }

 X() {} //default constructor for X struct
 void m3() {} //define and declare m3, basically does nothing
 void main()
 {
  X a;
  a.f(2);  //return 1
 }

};

This code is so confusing that even though it doesn't do anything it still made me question myself. 

Sunday, 3 June 2018

Chapter 9 // Exercise 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 9 // Exercise 3



Replace Name_pair::print() with a (global) operator <<  and define  ==  and !=  for Name_pairs.

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

class Name_pairs
{
private:
 vector<string> name;
 vector<double> age;
public:
 void read_names(int iterator);  //read in a series of names
 void read_ages();     //read in age for name
 void sortNP();      //sort the vectors alphabetically by name
 vector<string> getNames() { return name; }
 vector<double> getAges() { return age; }
};

ostream& operator<<(ostream& os, Name_pairs& n) //print the vectors
{
 cout << endl;
 for (int i = 0; i < n.getNames().size(); ++i)
  os << "Name: " << n.getNames()[i] << "     Age: " << n.getAges()[i] << endl;
 return os;
}
//equals
bool operator==(Name_pairs& a, Name_pairs& b)
{
 return a.getNames() == b.getNames() &&
  a.getAges() == b.getAges();
}

//not equals
bool operator!=(Name_pairs& a, Name_pairs& b)
{
 return !(a == b);
}
void Name_pairs::read_names(int iterator)
{
 string names;
 for (int i = 0; i < iterator; ++i)
 {
  cout << "Name: ";
  cin >> names;
  name.push_back(names);
  cout << endl;
 }
}

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

void Name_pairs::sortNP()
{
 vector<string> name_copy = name;
 vector<double> age_copy = 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()
{
 cout << "How many names to read in? > ";
 int howMany;
 cin >> howMany;

 Name_pairs namePair;

 //read in names
 namePair.read_names(howMany);

 //read in ages
 namePair.read_ages();

 //print
 cout << namePair;

 //sort namePair alphabetically
 namePair.sortNP();

 //print
 cout << namePair;

 keep_window_open();

 return 0;
}


The most challenging part of this was getting the ostream operator to work properly. At the moment he's only shown examples for having it outside of the class but I'm pretty sure there is a way to have it inside the class as a member.

Also, he didn't particularly specify what type of == and != he wanted. Was to compare the name_pair in general or to compare specific days? I did it generally, however it could be improved to compare specific days and ages.

Friday, 1 June 2018

Chapter 9 // 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 9 // Exercise 1


Design and implement a Name_pairs class holding (name, age) pairs where name is a string and age is a double. Represent that as a vector<string>  (called name) and a vector<double> (called age) member. Provide an input operation read_names() that reads a series of names. Provide a read_ages() operation that prompts the user for an age for each name. Provide a print() operation that prints out the (name[i], age[i]) pairs (one per line) in the order determined by the name vector. Provide a sort() operation that sorts the name vector in alphabetical order and reorganises the age vector to match. Implement all "operations" as member functions.

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

class Name_pairs
{
private:
 vector<string> name;
 vector<double> age;
public:
 void read_names(int iterator); //read in a series of names
 void read_ages();  //read in age for name
 void print();   //print out vectors
 void sortNP();   //sort the vectors alphabetically by name
};

void Name_pairs::read_names(int iterator)
{
 string names;
 for (int i = 0; i < iterator; ++i)
 {
  cout << "Name: ";
  cin >> names;
  name.push_back(names);
  cout << endl;
 }
}

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

void Name_pairs::print()
{
 cout << endl;
 for (int i = 0; i < name.size(); ++i)
  cout << "Name: " << name[i] << "     Age: " << age[i] << endl;
}

void Name_pairs::sortNP()
{
 vector<string> name_copy = name;
 vector<double> age_copy = 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()
{
 cout << "How many names to read in? > ";
 int howMany;
 cin >> howMany;

 Name_pairs namePair;

 //read in names
 namePair.read_names(howMany);

 //read in ages
 namePair.read_ages();

 //print
 namePair.print();

 //sort namePair alphabetically
 namePair.sortNP();

 //print
 namePair.print();

 keep_window_open();

 return 0;
}

This was basically chapter 8 exercise 7 but in a class form, so I just reused some of the functions from that and stuck it into a class.