October 10, 2012

Unsnarl the ifs

money::money(const string &code, double amt)
	:country(code), amount(amt)	//initialize money
{
	if( (code == "USD") || (code == "EUR") || (code == "KWR") || (code == "GBP")) {
		if (amt >= 0)
			usd = toUSD (code, amt);
		else{
			cerr <<"ERROR: Money must be positive number." << endl;
			exit(EXIT_FAILURE);
		}
	}
	else {
		cerr << "ERROR: Wrong Currency. Choose one of the following : USD, KWR, EUR, GBP." << endl; 
		exit(EXIT_FAILURE);
	}
}

No reason to flush an unbuffered stream such as cerr. I corrected the error message about “positive”.

money::money(const string &code, double amt)
	: country(code), amount(amt)
{
	if (code != "USD" && code != "EUR" && code != "KWR" && code != "GBP") {
		cerr << "ERROR: Wrong Currency.  Choose one of the following: USD, KWR, EUR, GBP.\n"; 
		exit(EXIT_FAILURE);
	}

	if (amt < 0) {
		cerr << "ERROR: Money " << amt << can't be negative.\n";
		exit(EXIT_FAILURE);
	}

	usd = toUSD(code, amt);
}

The same thing

double money::toUSD(const string & code, double inputamount) {

	double converted;

	if( (code == "USD") || (code == "EUR") || (code == "KWR") || (code == "GBP")) {
		if (inputamount >= 0) {
			if (code == "KWR")
				converted = 0.000898473*inputamount;
			else if (code == "GBP")
				converted = 1.61321*inputamount;
			else if (code == "EUR")
				converted = 1.29178*inputamount;
			else
				converted = inputamount;
			return converted;
		}
		else{
			cerr <<"ERROR: Money must be positive number." << endl;
			exit(EXIT_FAILURE);
		}
	}
	else {
		cerr << "ERROR: Wrong Currency. Choose one of the following : USD, KWR, EUR, GBP." << endl;
		exit(EXIT_FAILURE);
	}
}
double money::toUSD(const string& code, double inputamount) {
	if (inputamount < 0) {
		cerr <<"ERROR: Money " << inputamount << "can't be negative.\n";
		exit(EXIT_FAILURE);
	}

	if (code == "KWR") {
		return 0.000898473 * inputamount;
	}

	if (code == "GBP") {
		return 1.61321 * inputamount;
	}

	if (code == "EUR") {
		return = 1.29178 * inputamount;
	}

	if (code == "USD") {
		return = inputamount;
	}

	cerr << "ERROR: Wrong Currency.  Choose one of the following: USD, KWR, EUR, GBP.\n";
	exit(EXIT_FAILURE);
}

Use an array of structures.

double money::toUSD(const string& code, double inputamount) {
	struct currency {
		string name;
		double factor;
	};

	static const currency a[] = {
		{"KWR", 0.000898473},
		{"EUR", 1.29178},
		["GBP", 1.61321},
		{"USD", 1.0}
	};
	static const size_t n = sizeof a / sizeof a[0];

	if (inputamount < 0) {
		cerr <<"ERROR: Money " << inputamount << "can't be negative.\n";
		exit(EXIT_FAILURE);
	}

	for (const currency *p = a; p < a + n; ++p) {
		if (p->name == code) {
			return p->factor * inputamount;
		}
	}

	cerr << "ERROR: Wrong Currency.  Choose one of the following: USD, KWR, EUR, GBP.\n";
	exit(EXIT_FAILURE);
}

Use a C++ map.

See Chapter 8, p. 787.

double money::toUSD(const string& code, double inputamount) {
	typedef map<string, double> map_t;
	typedef map_t::value_type pair_t;

	static const pair_t a[] = {
		pair_t("KWR", 0.000898473)
		pair_t("EUR", 1.29178)
		pair_t("GBP", 1.61321)
		pair_t("USD", 1.0)
	};
	static const size_t n = sizeof a / sizeof a[0];

	static map_t m(a, a + n);
	
	if (inputamount < 0) {
		cerr <<"ERROR: Money " << inputamount << "can't be negative.\n";
		exit(EXIT_FAILURE);
	}

	const map_t::const_iterator it = m.find(code);
	if (it == m.end()) { 
		cerr << "ERROR: Wrong Currency.  Choose one of the following: USD, KWR, EUR, GBP.\n";
		exit(EXIT_FAILURE);
	}

	return it->second * inputamount;
}