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.