convert integers to Roman Numerals assignment

I'm working on an assignment for my first semester of c++ at uni. I've Been working on a program that acts as a form of Roman numeral calculator, I input Roman Numeral Characters, and the program (is suppose to) output the corresponding digits. *Not allowed to use for loops or arrays.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  Input:
02
MCCXXVI
03
LXVIIII
04
+
05
 
06
Output:
07
The First number is 1226
08
The second number is 69
09
Arithmetic operation is +
10
the sum of 1226 and 69 is MCCLXXXXV (1295)


However, when I run the program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
input:
02
MCCXXVI
03
LXVIIII
04
+
05
 
06
Output:
07
The first number is 77
08
The second number is 76
09
Arithmetic Operation is +
10
The sum of 77 and 76 is (infinite loop of I's) (153) 


I noticed that when I input MCCXXVI, it only takes the first character (I thought cin.get() was suppose to stop this?), and returns the ASCII decimal value of that, instead of the integer value that I assigned to each letter. I was wondering if anyone could tell me why this is happening, and how to fix it? Also, why i get an infinite loop, and how to fix it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
using namespace std;

const int I_Value = 1;
const int  V_Value = 5;
const int X_Value = 10;
const int L_Value = 50;
const int C_Value = 100;
const int D_Value = 500;
const int M_Value = 1000;
void PrintRomanNumeral ( int Val );
void PrintResult ( int operand1, int operand2, 
                      int result, char operation );
char RomanDigitChar ( int Val );
int RomanDigitValue( char roman_digit );
int ReadRomanNumeral ( int Total );


int main()
{
	char num1;
	char num2;
	int total;
	char MathOperator;
	cin >> num1;
	ReadRomanNumeral ( num1 );
	while ( !cin.eof() )
	{
		cin >> num2;
		ReadRomanNumeral ( num2);
		cin >> MathOperator;

		if ( MathOperator == '+' )
			total = num1 + num2;
		else if ( MathOperator == '-' )
			total = num1 - num2;
		else if ( MathOperator == '*' )
			total = num1 * num2;
		else if ( MathOperator == '/' )
			total = num1 / num2;

		PrintResult ( num1, num2, total, MathOperator);
		cin >> num1;
		ReadRomanNumeral ( num1 );
	}

   return 0;
}



//---------------------------------
//function definitions below
//---------------------------------
int ReadRomanNumeral ( int Total )
	{
		char ch;
		cin.get ( ch );
		while ( ch!= '\n' && !cin.eof() )
		{
			cin.get ( ch );
			Total += RomanDigitValue(ch);
		}
		return Total;
	}

char RomanDigitChar ( int Val )
	{
		if (Val = I_Value ) //1
			return 'I';
		else if (Val = V_Value ) //5
			return 'V';
		else if (Val = X_Value ) //10
			return 'X';
		else if (Val = L_Value ) //50
			return 'L';
		else if (Val = C_Value ) //100
			return 'C';
		else if (Val = D_Value ) //500
			return 'D';
		else if ( Val = M_Value ) //1000
			return 'M';
		
		
	}

void PrintRomanNumeral (int val)
{
	while ( val >= 0 )
	{
		if ( val <= I_Value ) //1
			cout << RomanDigitChar ( I_Value );
		else if ( val <= V_Value ) //5
			cout << RomanDigitChar ( V_Value );
		else if ( val <= X_Value )//10
			cout << RomanDigitChar ( X_Value );
		else if ( val <= L_Value ) //50
			cout << RomanDigitChar ( L_Value );
		else if ( val <= C_Value ) //100
			cout << RomanDigitChar ( C_Value );
		else if ( val <= D_Value ) //500
			cout << RomanDigitChar ( D_Value ); 
		else if ( val <= M_Value ) //1000
			cout << RomanDigitChar ( M_Value ); 
		else if ( val = 0 )
			cout << "zero";
	}
}

void PrintResult ( int operand1, int operand2, 
				  int result, char operation )
{
	cout << "The first number is " << operand1 <<endl;
	cout << "The second number is " << operand2 <<endl;
	cout << "Arithmetic operation is " << operation <<endl;
	if ( operation == '+' )
	{
		cout << "The sum of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result );
			cout << " (" << result << ")" <<endl;
	}
	else if ( operation == '-' )
	{
		cout << "The difference of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result );
			cout << " (" << result << ")" <<endl;
	}
	if ( operation == '*' )
	{
		cout << "The product of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result );
			cout << " (" << result << ")" <<endl;
	}
	if ( operation == '/' )
	{
		cout << "The quotient of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result );
			cout << " (" << result << ")" <<endl;
	}
}

int RomanDigitValue ( char roman_digit )
{
	if ( roman_digit == 'I' )
		return I_Value;
	else if ( roman_digit == 'V' )
		return V_Value;
	else if ( roman_digit == 'X' )
		return X_Value;
	else if ( roman_digit == 'L' )
		return L_Value;
	else if ( roman_digit == 'C' )
		return C_Value;
	else if ( roman_digit == 'D' )
		return D_Value;
	else if ( roman_digit == 'M' )
		return M_Value;
}


Below Code that causes infinite loop.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void PrintResult ( int operand1, int operand2, 
				  int result, char operation )
{
	cout << "The first number is " << operand1 <<endl;
	cout << "The second number is " << operand2 <<endl;
	cout << "Arithmetic operation is " << operation <<endl;
	if ( operation == '+' )
	{
		cout << "The sum of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result ); //causes infinite loop
			cout << " (" << result << ")" <<endl;
	}
	else if ( operation == '-' )
	{
		cout << "The difference of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result ); //causes infinite loop
			cout << " (" << result << ")" <<endl;
	}
	if ( operation == '*' )
	{
		cout << "The product of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result ); //causes infinite loop
			cout << " (" << result << ")" <<endl;
	}
	if ( operation == '/' )
	{
		cout << "The quotient of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result ); //causes infinite loop
			cout << " (" << result << ")" <<endl;
	}
}
there are several problems here, but I'll start with the biggest. In main() you declare char num1;
This only lets you get one character, which you then read in on line 28. This being the case, you'll never get past the first M. What you need to do is
char num1[10];  // can read in up to a 10 character Roman Numeral
std::cout << "Type the whole Roman Numeral\n";
std::cin.getline(num1,10);
std::cout << num1 << std::endl; // this is important, make sure you have the right letters here

Although, you say no arrays; are you sure you can't do it this way reading in a char array?
If not, you'll have to get the Roman Numeral characters one at a time using cin and assign each to it's own char variable such as
1
2
3
4
char a,b,c; // ...as many as you need
cin >> a;  // should prob have prompts between
cin >> b;
cin >> c; // then print each variable to make sure you have the right letters 

So this is your first problem to take care of. Get the whole number into memory so you can work with it.

Your next problem starts with the ReadRomanNumeral() call and the function itself, but you need to get the input to send the function first. Which method you use above will determine the best approach to take next.

Edit:

You're returning a value from ReadRomanNumeral, but you're not assigning it to anything. That should get you started. Sorry for all that above,but some of it will be necessary to print out the Roman Numerals at the end. I'm going to bed now. But first.
You'll need to add a few ints to your code
1
2
3
int firstTotal, secondTotal;
firstTotal =  ReadRomanNumeral(num1);  // line 29
secondTotal = ReadRomanNumeral(num2);  // line 33 

Then, use firstTotal and secondTotal in for your calculations.

Ok, that's it from me for now. Hope that pushes you along
Last edited on
Thank you for your help mgoetschius, Adding FirstTotal and secondTotal fixed my basic calculations
however, I am not allowed to use any type of array, this assignment was given before we learned anything about arrays, using an array will result in a 0.
When i input MCCXXVI, it returns the individual ASCII character values added up, instead of adding up the values that i assigned to each letter. Is their any way to input a string into ReadRomanNumeral() to fix this? Or is their another way i should be going about trying to solve this?
Are you allowed to use C++ strings? If not, it's going to be pretty tricky to evaluate something like CMXCIV (994).
Here are the guidelines i was given, sorry if its a little long.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
Write a C++ program to implement a form of a Roman numeral calculator.
We are using the purely additive form of Roman numerals.  By that, we
mean that a number is simply the sum of its digits; for example, 4 equals
IIII, in our additive notation.  This means that we are NOT using IV for 4.
Each Roman numeral must start with the digit of highest value and ends with
the digit of smallest value.  That is 9 is VIIII and NOT IIIIV.
Your program continually (in a loop) inputs 2 Roman numbers and an
arithmetic operator and prints the result of the operation as a Roman
number.  The values of the Roman digits (upper case letters only)
are as follows:

      Roman Digit            Value of Roman Digit
           I                         1
           V                         5
           X                        10
           L                        50
           C                       100
           D                       500
           M                      1000

So, the Roman number MMVIIII represents 2009.  The arithmetic operators
that your program must recognize in the input are +, -, *, and /. These
should perform the C++ integer operations of addition, subtraction,
multiplication, and division, respectively. Your program must loop, 
processing 2 Roman numbers with an operator, finishing when end of file 
is reached.

You do not have to ensure that the input is in purely additive form, 
i.e., your program does NOT have to check for this.

You can assume that only positive numbers will be entered as input and 
you don't have to check for negative numbers.

If the result is negative, you must print out a minus sign followed 
by the absolute value of the result printed as a Roman Numeral. See
the sample runs below.

If the result is zero, print the word "zero".

------------------------------------------------------------------------

The following additional requirements must be followed:
A. Your main function must implement the following pseudocode:

        read a roman numeral [Hint: use a value returning function]
        While Not at the end of file Do
           echo first number
           read second roman numeral 
           echo second number
           read operator
           echo operator
           calculate the result
           print results
           read a roman numeral
        End While

   You must use ONE function to read a roman numeral.

B. You must correctly implement and use the following functions
   in your program (-2 points off per function that is either
   not correctly implemented or correctly used):

   //---------------------------------------------------------------------
   // This function prints, to the standard output and in purely additive
   // notation, the Roman numeral corresponding to a natural number.
   // If the input value is 0, nothing is printed.
   // params: (in)
   //---------------------------------------------------------------------
   void PrintRomanNumeral ( int val )


   //---------------------------------------------------------------------
   // This function outputs the result in Roman numeral format to
   // the standard output.
   // It presumes that the operation is valid and does
   // not check for that.
   // params: (in, in, in, in)
   //---------------------------------------------------------------------
   void PrintResult ( int operand1, int operand2, 
                      int result, char operation )

   
   *NOTE* The above two functions should NOT perform any kind
   calculation.

   
   //---------------------------------------------------------------------
   // This function returns the Roman numeral digit corresponding
   // to an integer value.
   // params: (in)
   //---------------------------------------------------------------------
   char RomanDigitChar ( int val )


   //---------------------------------------------------------------------
   // This function returns the integer value of a Roman numeral digit.
   // params: (in)
   //---------------------------------------------------------------------
   int RomanDigitValue(char roman_digit)


C. Functions should be single-minded, performing a 
   focused task that can be well-named. You should
   design pseudocode for each of these functions.
   All function bodies, including the body of main,
   should be NO more than 30 lines long,
   including braces, blank lines and comments.

D. You must NOT use arrays.  You will lose ALL points if 
   you use arrays.

E. You must follow the programming ground rules.

F. You must follow the formatting of the sample I/O below.

G. You must thoroughly test your program.
 
H. Hint: use a combination of a sentinel-controlled and end of file
   loop to read in a roman numeral.  Ask in class as to what the 
   sentinel should be.  You must have ONLY one function to read in
   a Roman number.  Otherwise you will lose 3 points.

I. To get credit for the assignment, your solution must minimally
   work on Test Case # 1 below.

J. (HINT) Have a single function that reads a roman numeral
   from the standard input and returns its integer value. 
   It can use a loop that is a combination of a sentinel-controlled 
   loop and an end-of-file controlled loop. That is, you must check 
   for both the end of file and sentinel condition in the loop test 
   (which condition to check first?). You will have to read characters 
   from the standard input one at a time using cin.get() until the 
   sentinel value of '\n' is reached. As you read each character in, 
   convert it to its integer value using the appropriate function 
   listed above. Keep a running total of the sum of all the 
   (integer values) of the roman numerals that you read in and return
   this value. 

------------------------------------------------------------------------

Sample I/O
Below are two sample runs.
They do NOT cover all cases.

Input for Run 1:
MCCXXVI
LXVIIII
+
DCX
MCI
-
LXVI
CCLXI
/
MD
XXX
/
LXVIIII
XXVIIII
*

The output for Test Run 1: 

The first number is 1226
The second number is 69
Arithmetic operation is  +
The sum of 1226 and 69 is MCCLXXXXV (1295)

The first number is 610
The second number is 1101
Arithmetic operation is  -
The difference of 610 and 1101 is -CCCCLXXXXI (-491)

The first number is 66
The second number is 261
Arithmetic operation is  /
The quotient of 66 and 261 is zero (0)

The first number is 1500
The second number is 30
Arithmetic operation is  /
The quotient of 1500 and 30 is L (50)

The first number is 69
The second number is 29
Arithmetic operation is  *
The product of 69 and 29 is MMI (2001)
Wow, your professor is pretty thorough. Still doesn't mention C++ strings, but since the Roman numerals are purely additive, I guess that's not necessary.

As for your problem, I don't see why your program is adding up the ASCII values instead of the values you assigned. There are problems with your ReadRomanNumeral function which would make your Total an absolutely random number, but nothing will specifically make it the sum of the ASCII values.

Try using this and see if that solves the problem:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <cctype>

using namespace std;

int RomanDigitValue(char roman_digit)
{
    switch (roman_digit)
    {
        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;
    }
    return 0;
}

int ReadRomanNumeral()
{
    int sum = 0;
    char ch;
    cin.get(ch);
    while (ch != '\n' && !cin.eof())
    {
        ch = toupper(ch);
        sum += RomanDigitValue(ch);
        cin.get(ch);
    }
    cin.clear();
    return sum;
}
Last edited on
the above fix still returns the incorrect (random) integers
Ok, here is a minimal example (only works with V's and I's) of what I think your prof is looking for. You'll have to expand it, make it pretty, etc... Not all of the functionality your prof requested is included here, you'll have to implement it, such as getting from integer back to roman numeral.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>

int GetIntValue(char val)
{
    if(val == 'I')
        return 1;
    else if(val == 'V')
        return 5;
    // etc...
    else
        return 0;
}

int ReadRomanNumeral(char val)
{
    int total = GetIntValue(val);
    char c;
    std::cin.get(c);
    while(c != '\n')
    {
        total += GetIntValue(c);
        std::cin.get(c);
    }
    return total;
}

int main()
{
    int total1, total2;
    char num1, num2, op;
    std::cout << "First Roman numeral?\n";
    std::cin >> num1;
    total1 = ReadRomanNumeral (num1);
    std::cout << "Total1 is: " << total1 << std::endl;
    // get second number
    std::cout << "Second Roman numeral?\n";
    std::cin >> num2;
    total2 = ReadRomanNumeral (num2);
    std::cout << "Total2 is: " << total2 << std::endl;

    std::cout << "What Operator?\n";
    std::cin >> op;
    std::cout << "Operator is: " << op << std::endl;

    if(op == '+')
        std::cout << std::endl << "Total: " << total1 + total2 << std::endl;



    return 0;
}

If you need more help after working on implementing the rest of the assignment, post the changes you've made
Last edited on
I finished the assignment, thank you so much mgoetschius!
Just out of curiosity, is it possible to redo my void PrintRomanNumeral function without using for loops, and still have the function be 30 lines or less?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
const int I_Value = 1;
const int  V_Value = 5;
const int X_Value = 10;
const int L_Value = 50;
const int C_Value = 100;
const int D_Value = 500;
const int M_Value = 1000;
void PrintRomanNumeral ( int Val );
void PrintResult ( int operand1, int operand2, 
                      int result, char operation );
char RomanDigitChar ( int Val );
int RomanDigitValue( char roman_digit );
int ReadRomanNumeral (char val);
int main()
{
	int total, firstTotal, secondTotal;
	char num1, num2, mathOperator;
	cin >> num1;	firstTotal = ReadRomanNumeral (num1);
	while ( !cin.eof() )
	{
		cin >> num2;
		secondTotal = ReadRomanNumeral (num2);
		cin >> mathOperator;

		if ( mathOperator == '+' )
			total = firstTotal + secondTotal;
		else if ( mathOperator == '-' )
			total = firstTotal - secondTotal;
		else if ( mathOperator == '*' )
			total = firstTotal * secondTotal;
		else if ( mathOperator == '/' )
			total = firstTotal / secondTotal;

		PrintResult ( firstTotal, secondTotal, total, mathOperator);
		cin >> num1;
		firstTotal = ReadRomanNumeral (num1);
		
	}

   return 0;
}



//---------------------------------
//function definitions below
//---------------------------------
int ReadRomanNumeral ( char val)
	{
		int total = RomanDigitValue(val);
		char ch;
		cin.get ( ch );
		while ( ch!= '\n' && !cin.eof() )
		{
			total += RomanDigitValue(ch);
			cin.get ( ch );
		}
		return total;
	}

char RomanDigitChar ( int Val )
	{
		if (Val = I_Value ) //1
			return 'I';
		else if (Val = V_Value ) //5
			return 'V';
		else if (Val = X_Value ) //10
			return 'X';
		else if (Val = L_Value ) //50
			return 'L';
		else if (Val = C_Value ) //100
			return 'C';
		else if (Val = D_Value ) //500
			return 'D';
		else if ( Val = M_Value ) //1000
			return 'M';
		
		
	}

void PrintRomanNumeral ( int val )
{
   int newval;
   for ( int i = 1; i <= abs ( val / M_Value ); i++ )
      cout << "M";
   newval = val % M_Value;
   if ( abs ( newval / D_Value ) == 1 )
      cout << "D";
      newval = newval % D_Value;
   for ( int i = 1; i <= abs ( newval / C_Value ); i++ )
      cout << "C";
   newval = newval % C_Value;
   if ( abs ( newval / L_Value ) == 1 )
      cout << "L";
      newval = newval % L_Value;
   for ( int i = 1; i <= abs ( newval / X_Value ); i++ )
      cout << "X";
   newval = newval % X_Value;
   if ( abs ( newval / V_Value ) == 1 )
      cout << "V";
   newval = newval % V_Value;
   for ( int i = 1; i <= abs ( newval ); i++ )
      cout << "I";
}

void PrintResult ( int operand1, int operand2, 
				  int result, char operation )
{
	cout << "The first number is " << operand1 <<endl;
	cout << "The second number is " << operand2 <<endl;
	cout << "Arithmetic operation is " << operation <<endl;
	if ( operation == '+' )
	{
		cout << "The sum of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result );
			cout << " (" << result << ")" << endl << endl;
	}
	else if ( operation == '-' )
	{
		cout << "The difference of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result );
			cout << " (" << result << ")" << endl << endl;
	}
	if ( operation == '*' )
	{
		cout << "The product of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result );
			cout << " (" << result << ")" << endl << endl;
	}
	if ( operation == '/' )
	{
		cout << "The quotient of " << operand1 << " and " << operand2
			<< " is ";
		PrintRomanNumeral ( result );
			cout << " (" << result << ")" << endl << endl;
	}
}

int RomanDigitValue ( char roman_digit )
{
	if ( roman_digit == 'I' )
		return I_Value;
	else if ( roman_digit == 'V' )
		return V_Value;
	else if ( roman_digit == 'X' )
		return X_Value;
	else if ( roman_digit == 'L' )
		return L_Value;
	else if ( roman_digit == 'C' )
		return C_Value;
	else if ( roman_digit == 'D' )
		return D_Value;
	else if ( roman_digit == 'M' )
		return M_Value;
	else
		return 0;
}
Glad you have it finished. As for your question, I'm sure someone slick could come up with another solution but that isn't me I'm afraid. Every solution that occurs to me uses at least one loop. So, I must leave it to someone else to be clever. I say, If it works and it's easy to understand, let it go.
Topic archived. No new replies allowed.