/*
 * EE5C Assignment #5
 * Author:  Cedric Lam
 * Date: 1-18-1998
 */

#define THOUSAND 1000
#define MILLION 1000000
#define BILLION 1000000000

#include <iostream.h>
#include <stdlib.h>
#include <ctype.h>

// These are global variables used to represent digits in words 
char *digits[10] = {"zero", "one", "two", "three", "four", "five",
		"six", "seven", "eight", "nine"};
char *digit1x[10] = {"ten", "eleven", "twelve", "thirteen", "fourteen",
		"fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
char *digitx0[10] = {"not used", "ten", "twenty", "thirty", "forty",
		"fifty", "sixty", "seventy", "eighty", "ninety"};


int isblank(char c);
void printsingle(int);
void printtens(int);
void printhundreds(int);
void num2words(int);
int get_input(int *dollarp, int *centp);
void intro(void);

/*
 * returns 1 if the character c is a ' ' or '\t', 0 otherwise 
 * We cannot use the ctype.h function isspace() since the new line
 * character is considered space by isspace(). \n is used to test
 * end of input in our case.
 */
int isblank(char c)
{
	return (c==' ' || c=='\t');
}

/* This function coverts numbers less than 1000 billion into words.
 * It uses functions: printsingle, printtens and printhundreds.
 */
void num2words(int num)
{
	int tmp = num,
		q, r;
	
	if (num == 0){
		cout << "zero ";
		return;
	}
	q = num / BILLION;
	if(q){
		if(q >= 1000){
			cout << "Error: num2words cannot handle inputs "
			     << "bigger than 1000 billion." << endl;
			return;
		}
		else {
			printhundreds(q);
			cout << " billion ";
		}
		num %= BILLION;
	}
	q = num / MILLION;
	if(q){
		printhundreds(q);
		cout << " million ";
		num %= MILLION;
	}
	q = num / THOUSAND;
	if(q){
		printhundreds(q);
		cout << " thousand ";
		num %= THOUSAND;
	}
	if(num){
		printhundreds(num);
		cout << " ";
	}
	return;
}

/*
 * This function converts any number with three digits or less into words.
 */ 
void printhundreds(int num)
{
	int  tmp = num;
	
	if(num < 10)		/* num has one and only one digit */
		printsingle(num);
	else if(num < 100)	/* num has two and only two digits */
		printtens(num);
	else if(num < 1000){	/* num has three and only three digits */
		printsingle(num / 100);
		cout << " hundred";
		if(tmp = num % 100) cout << " and ";
		if(tmp >= 10){
			printtens(num % 100);
		}
		else if(tmp)
			printsingle(num % 100);
	}
	else			/* num has more than three digits */
		cout << "Error: function printhundreds can only"
		     << " handle integers less than 1000." << endl;
}

/*
 * This function covert a single digit number into words.
 */
void printsingle(int num)
{
	if (num >= 10 || num <0){
		cout << "Error: input to function printsingle must be"
		     <<	" between 0 and 9" << endl ;
		return;
	}
	cout << digits[num];
}

/*
 * This number converts a two-digit number into words.
 */
void printtens(int num)
{
	if(num < 10 || num > 99){
		cout << "Error: input to function printtens must be"
		     <<	" between 10 and 99." << endl;
		return;
	}
	if(num < 20) {
		cout << digit1x[num%10];
		return;
	}
	cout << digitx0[num/10];
	if(num % 10){
		cout << "-";
		printsingle(num % 10);
	}
}

/*
 * This function gets the the input from the user. The function 
 * checks the format of the input. If a valid input is given,
 * the amount in dollars and cents are passed back using pointers.
 * The function returns 1 if the input is valid and 0 if an invalid
 * input is typed by the user.
 */
int get_input(int *dollarp, int *centp)
{
	char c;	/* user input character */
	int decimal_point = 0,  /* occurrance of decimal point */
	    dollar=0,  /* dollar part of input */
	    cent=0,    /* cent part of input */
	    dollar_sign = 0;  /* occurance of the dollar sign */
	
	cout << endl << "Input the value of the money you have: ";
	while(isblank(c=cin.get()));	/* skip leading spaces */
	if(c=='$'){ /* skip the leading dollar sign */
		dollar_sign = 1;
		/* skip white space after the dollar sign */
		while(isblank(c = cin.get()));
	}
	if(c=='\n') /* empty input, return */ 
		return 0;
	while(isdigit(c)){
		dollar = dollar*10 + c -'0';
		c = cin.get();
	}
	if(c=='.'){	/* found decimal point */
		decimal_point++;
		c = cin.get();
	}
	while(isdigit(c)){
		if(decimal_point <= 2){
			if(decimal_point == 1)
				cent += (c - '0')*10;
			else
				cent += c -'0';
			decimal_point++;
		}
		/* ignore all the digits following the second decimal place. */
		c = cin.get();
	}
	while(isblank(c)){
		c = cin.get();
	}
	if(c != '\n'){
		return 0;
	}
	*dollarp = dollar;
	*centp = cent;
	return 1;
}

/*
 * This function gets the y/n answer from the user.
 * If waits until a valid y/n answer is typed by the user.
 * The function returns 1 for yes and 0 for no.
 */
int yes_no(void)
{
	char c;
	int yes = -1; /* initialized to an invalid input character */
	
	do{
		while(isspace(c=cin.get())); /* skip leading blank characters */
		if(c == 'y' || c =='Y')
			yes = 1;
		else if(c == 'n' || c =='N')
			yes = 0;
		while((c=cin.get())!='\n'); /* skip rest of the line */	
	}while (yes == -1);
	return yes;
}

/*
 * This function prints the output of dollars and cents onto
 * the screen in words.
 */
void print_output(int dollar, int cent)
{
	cout << endl << "You entered ";
	num2words(dollar);
	if(dollar > 1)
		cout << "dollars and ";
	else
		cout << "dollar and ";
	num2words(cent);
	if(cent >1)
		cout << "cents.\n";
	else
		cout << "cent.\n";
}

void intro(void)
{
	cout << "================================================================"<< endl
	<< "This program gets the dollar amount of an input value and" << endl
	<< "prints out the value in words." << endl << endl
	<< "The input can be any positive real number up to 2100000000" << endl
	<< "possibly preceeded by a $ sign." << endl
	<< "The leading and trailing spaces and the space characters" << endl
	<< "between the $ symbol and the number in the input are ignored." << endl
	<< "There should be no separation between digits in the input." << endl
	<< "Digits after the second decimal places are simply ignored." << endl
	<< "Any characters other than the period, digits, the dollar symbol" << endl
	<< "and space and tab characters are illegal." << endl
	<< "The $ symbol and integer part can be omitted in the input." << endl
	<< "================================================================" << endl
	<< "Try it ... " << endl;
}


int main(void)
{
	int dollar, cent;
	
	intro();
	do{
		if(get_input( &dollar, &cent))
			print_output(dollar, cent);
		else
			cout << "Sorry, incorrect input format." << endl;
		cout << endl;
		cout << "Do you want to give another input (y/n)? ";
	} while(yes_no());

	cout << endl << "Thank you." << endl;
	
	return 0;
}
