roman integer class 1.0

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 10 Exercise 6
Using std_lib_facilities.h by Bjarne Stroustrup.

My project includes the following files:
p377_6_romanIntMain.cpp my main cpp file
p377_6_romanIntClass.h my roman integer class header file

p377_6_romanIntMain.cpp my main cpp file

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 10 Exercise 6

#include "p377_6_romanIntClass.h"

int main()
try
{
	Roman_int r;
	r.set_values();
	//cout << r;

	keep_window_open();
}
catch (runtime_error e) {
	cout << e.what() << endl;
	keep_window_open();
}
catch (...) {
	cout << "Exiting" << endl;
	keep_window_open();
}

p377_6_romanIntClass.h my roman integer class header file

#pragma once
//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 10 Exercise 6

#include "std_lib_facilities.h"

vector<char> roman_chars = {
	'N', 'I', 'V', 'X', 'L', 'C', 'D', 'M'
};

int roman_char_value(char ch) {
	switch (ch) {
	case 'N':
		return 0;
	case 'I':
		return 1;
	case 'V':
		return 5;
	case 'X':
		return 10;
	case 'L':
		return 50;
	case 'C':
		return 100;
	case 'D':
		return 500;
	case 'M':
		return 1000;
	default:
		return -1;
	}
}

class Roman_int {
private:
	string roman_string;
	int roman_int;
public:

	Roman_int() {};
	Roman_int(string& _roman_string);

	void set_values();
	string get_string() { return roman_string; }
	int get_int() { return roman_int; }
};

ostream& operator<<(ostream& os, Roman_int _roman_int) {
	os << "Roman_int conversion:\n"
		<< _roman_int.get_string()
		<< " equals " << _roman_int.get_int() << endl;
	return os;
}

Roman_int::Roman_int(string& _roman_string) {
	roman_string = _roman_string;
}

bool read_roman_string(string& _value) {
	string _value_temp;
	if (cin >> _value_temp) {
		_value = _value_temp;
		return true;
	}
	else {
		return false;
	}
}

bool check_char_validity(string& _value) {
	if (_value.size() == 1) {
		cout << "Checking validity of roman char... ";
	}
	else {
		cout << "Checking validity of roman chars... ";
	}

	int size = int(_value.size());
	vector<int> invalid_index;

	for (int i = 0; i < size; i++) {
		int check = 0;
		for (int j = 0; j < roman_chars.size(); j++) {
			if (roman_chars[j] == _value[i]) {
				check++;
			}
		}
		if (check == 0) {
			invalid_index.push_back(i);
		}
	}

	if (invalid_index.size() != 0) {
		cout << "Invalid char: ";
		for (int i = 0; i < invalid_index.size(); i++) {
			cout << _value[invalid_index[i]] << " ";
		}
		cout << endl;
		return false;
	}
	else {
		if (_value.size() == 1) {
			cout << "Valid roman char." << endl;
			return true;
		}
		else {
			cout << "Valid roman chars." << endl;
			return true;
		}
	}
}

bool check_char_count(string& _value) {
	cout << "Checking number of roman chars... ";

	int size = _value.size();
	vector<int> counter(roman_chars.size(), 0);

	for (int i = 0; i < size; i++) {
		for (int j = 0; j < roman_chars.size(); j++) {
			if (_value[i] == roman_chars[j]) {
				counter[j]++;
			}
		}
	}

	int check = 0;
	for (int i = 0; i < roman_chars.size(); i++) {
		if (counter[i] > 1 && (roman_chars[i] == 'V' || roman_chars[i] == 'L' || roman_chars[i] == 'D')) {
			cout << "Invalid number of " << roman_chars[i] << "." << endl;
			check++;
		}
		else if (counter[i] > 3 && (roman_chars[i] == 'I' || roman_chars[i] == 'X' || roman_chars[i] == 'C' || roman_chars[i] == 'M')) {
			cout << "Invalid number of " << roman_chars[i] << "." << endl;
			check++;
		}
	}
	if (check == 0) {
		if (_value.size() == 1) {
			cout << "It is a single char." << endl;
		}
		else {
			cout << "Valid number of chars." << endl;
		}
		return true;
	}
	else {
		return false;
	}
}

void deconpose_roman_string(string& _value, int& _digit) {
	cout << "Decomposing roman string... ";

	int resulting_val = 0;
	int size = _value.size();
	int check = 0;

	//fill vector
	vector<int> value_ints;
	for (int i = 0; i < size; i++) {
		value_ints.push_back(roman_char_value(_value[i]));
	}

	/*
	I placed before V or X indicates one less, so four is IV (one less than five) and nine is IX (one less than ten)
	X placed before L or C indicates ten less, so forty is XL (ten less than fifty) and ninety is XC (ten less than a hundred)
	C placed before D or M indicates a hundred less, so four hundred is CD (a hundred less than five hundred) and nine hundred is CM (a hundred less than a thousand)
	*/

	if (size == 1) {
		resulting_val = value_ints[0];
	}
	else {
		for (int i = 0; i < size; i++) {
			if (_value[i] == 'I' && (_value[i + 1] == 'V' || _value[i + 1] == 'X')) {
				if (i == 0 && size == 2) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else if ((value_ints[i + 1] - value_ints[i]) < resulting_val){
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else {
					cout << "Number not existing." << endl;
					check = 1;
				}
			}
			else if (_value[i] == 'X' && (_value[i + 1] == 'L' || _value[i + 1] == 'C')) {
				if (i == 0 && size == 2) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else if ((value_ints[i + 1] - value_ints[i]) < resulting_val) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else {
					cout << "Number not existing." << endl;
					check = 1;
				}
			}
			else if (_value[i] == 'C' && (_value[i + 1] == 'D' || _value[i + 1] == 'M')) {
				if (i == 0 && size == 2) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else if ((value_ints[i + 1] - value_ints[i]) < resulting_val) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else {
					cout << "Number not existing." << endl;
					check = 1;
				}
			}
			else {
				resulting_val += value_ints[i];
			}
		}
	}

	if (check == 0) {
		cout << "resulting value = " << resulting_val << endl;
		_digit = resulting_val;
	}
}

void Roman_int::set_values() {
	//while (true) {
		cout << "Enter roman string or char:" << endl;
		//read roman string from user
		if (read_roman_string(roman_string)) {
			if (roman_string == "p") {
				//break;
			}
			//check if valid roman chars
			//check if valid count of chars
			else if (check_char_validity(roman_string) && check_char_count(roman_string)) {
				//decompose roman string
				deconpose_roman_string(roman_string, roman_int);
				cout << "Roman_int conversion:\n"
					<< get_string()
					<< " equals " << get_int() << endl;
			}
		}
	//}
}
Output:
Enter roman string or char:
IV
Checking validity of roman chars... Valid roman chars.
Checking number of roman chars... Valid number of chars.
Decomposing roman string... resulting value = 4
Roman_int conversion:
IV equals 4
Please enter a character to exit

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.