You are on page 1of 7

ECE 209 Program 1: rcalc

Fall 2022
Due Friday, Sep 23 @ 11:59pm

This programming assignment must be completed individually. Do not share your


code with or receive code from any other student. Evidence of copying or other
unauthorized collaboration will be investigated as a potential academic integrity
violation. The minimum penalty for cheating on a programming assignment is a
grade of 0 on the assignment. If you are tempted to copy because you're running late,
or don’t know what you’re doing, you will be better off missing the assignment and
taking a zero. Providing your code to someone is cheating, just as much as copying
someone else's work.
DO NOT copy code from the Internet, or use programs found online or in textbooks
as a "starting point" for your code. Your job is to design and write this program from
scratch, on your own. Evidence of using external code from any source will be
investigated as a potential academic integrity violation.

This program performs simple arithmetic (addition and subtraction) with Roman numerals. The user
enters an expression containing multiple Roman numerals and operators (+, -); the program computes
the expression and prints the result in decimal and then as a Roman numeral.
The learning objectives of the program are:
• Write a complete C program.
• Use loops and conditional statements.
• Use printf and scanf to perform I/O.

Background
In elementary school, you likely learned about the scheme used by ancient Romans to write down
numbers. This notation, typically known as Roman numerals, involves the use of letters to represent
fixed quantities. For example, ‘X’ means 10. Instead of a weighted positional system of digits, numbers
are built from repetitions of the letter symbols. Each time the symbol appears, it adds the corresponding
amount to the number: ‘XX’ means 20 (two 10’s), and ‘XXX’ means 30.
Letters and their corresponding values are shown in this table:

I V X L C D M

1 5 10 50 100 500 1000

To interpret a Roman numeral – that is, to convert it to a decimal integer – we primarily use an additive
rule: Each time we encounter a letter, we add its value to the number. We can process the letters in either
direction, but it will be easier for programming if we always go from left to right:
MMCVII = M (1000) + M (1000) + C (100) + V (5) + I (1) + I (1) = 2107.
1
However, there is also a subtractive rule: If a letter precedes another letter with higher value, it is
subtracted, rather than added. This lets us write ‘IX’ for 9 instead of ‘VIIII’. While this could be used as
a general rule, typical practice restricts the rule to the following cases:
IV = 4
IX = 9
XL = 40
XC = 90
CD = 400
CM = 900
Here's an example that includes the subtractive rule:
DCCXLIX = D (500) + C (100) + C (100) + X (-10) + L (50) + I (-1) + X (10) = 749
Note: When we encounter I, X, or C, we won’t know if it should be added or subtracted until we see the
following letter. Instead of viewing this as subtraction, an alternative interpretation would be something
like: “V is worth 5, unless it is preceded by I, in which case it is worth 3.” Interpreting V=3 in this case
allows us to always use addition, and IV = 1 + 3 = 4. From a programming perspective, it allows us to
use the previous letter to decide an action, rather than the next letter, which can simplify our logic.
The Roman notation was used for centuries throughout Europe, before it was widely replaced by the
Arabic system that we are familiar with. There were many other numbering systems used in different
parts of the world and at different times: Egyptian, Greek, Hebrew, Mayan, etc. We learn the Roman
scheme as kids because it uses the Latin alphabet, rather than other special symbols. Roman numerals
still pop up in various contexts today: numbers on a clock dial, names of Super Bowls, some dates in US
copyright law, etc. You can find a lot more interesting information about Roman numerals and other
numbering schemes on Wikipedia:
https://en.wikipedia.org/wiki/Roman_numerals

Problem Description
This program will implement a very simple Roman numeral calculator that will only perform addition
and subtraction. When the program is run, it will only handle one calculation, as follows:
1. User types an expression containing Roman numerals, spaces, plus (+), and minus (-), ending
with a linefeed.
2. The program will print the result of the calculation, first as a decimal integer and then (on the
next line) as a Roman numeral.
3. Program ends.
The program is not expected to check for erroneous input, so the user input must follow these rules. Any
violation of the rules will lead to undefined behavior.
• Roman numerals must be written using only capital letters with no spaces, and no character other
than I, V, X, L, C, D, and M may be used.
• There may be zero or more spaces between a numeral and an operator, and there may be zero or
more spaces after the last numeral.
• Every operator (+, -) must have two operands: a number before and after the operator.
• The result will be calculated from left to right. No parentheses are allowed to group operations.

2
• The entire expression must be typed before hitting the Enter/Return key. It’s fine if the input
wraps to the next line on the screen, but the Enter/Return key indicates the end of the expression
to the program.
The user is allowed to enter weird, unconventional numerals. The subtractive rule will only be applied in
the specific cases listed above: IV, IX, XL, XC, CD, and CM. In all other cases, the additive rule will be
followed. Here are some examples of numerals that are not allowed by the generally accepted rules,
along with how they will be interpreted by this program.

CCVD 100 + 100 + 5 + 500 = 705

IXII 9 + 1 + 1 = 11

DDD 500 + 500 + 500 = 1500

IC 1 + 100 = 101

In other words, this program will not try to detect or prevent improperly-formatted Roman numerals as
input. The output of this program, however, will follow the generally accepted rules, as discussed in the
program specification below.
We will assume that the people using Roman numerals were not familiar with the concept of negative
numbers. Therefore, any calculation that results in a negative value will be interpreted as zero, even if it
comes in the middle of an expression. For example:
I - II = 0
V + II - X + CC = 200 (because (V + II) - X goes negative and yields zero, before CC is added)

Program Specification
First, the program must prompt the user to enter an expression. The prompt must look exactly as
follows, with a linefeed immediately after the colon:
Enter an expression using Roman numerals:
The program then reads from standard input, one character at a time. Your program does not need to
check for incorrect or badly-formatted input data. All of the tests used to grade your program will have
legal input, as described above.
There is no limit to the number of characters in a numeral, or the number of operations in an expression.
If your program imposes a limit, you will lose points, even if that limit is sufficient for all of the tests.
Print the result as a decimal integer, followed by a linefeed.
Print the result as a Roman numeral, followed by a linefeed. The output Roman numeral must follow the
following rules:
• Letters must appear in decreasing value order (from largest to smallest), except when the
subtractive rule is used.
• The letters D, L, and V must only appear (at most) once.
• The letters I, X, and C must not appear more than three times in a row. M may appear as many
times as needed.
• The following limits are placed on the subtractive rule:
3
o I can only be subtracted from V and X.
o X can only be subtracted from L and C.
o C can only be subtracted from D and M.
• No spaces are allowed, and the output number must end with a linefeed.

Implementation
DO NOT try to read the entire line as a string. DO NOT try to read an entire Roman numeral as a
string. You must read one character at a time. Why? We haven’t covered strings in class, and it’s not
necessary. If we find code that uses strings for this program, we will be very suspicious that you (a)
copied code from somewhere else or (b) received inappropriate help from a more experienced
programmer. This will be taken as evidence of cheating and will be further evaluated. (If you have
programmed before and know how to use strings, don’t do it. It’s not needed for this program and it
does not make the program substantially easier.)
As you read a character, determine whether it is a letter, a space, an operator, or a linefeed. This will
determine what you do with the character and what action you should take. You might need to save the
character, or you might need to perform a computation, or both.
• When the character is I, V, X, L, C, D, or M, it is part of a numeral. You should be accumulating
the value of the current numeral into a variable. In most cases, you will simply add the value of
this letter to that variable. In the case of I, X, or C, you will also want to remember this character
to handle the subtractive rule when the next letter is read.
• Note (repeated from above): When we encounter I, X, or C, we won’t know if it should be added
or subtracted until we see the following letter. Instead of viewing this as subtraction, an
alternative interpretation would be something like: “V is worth 5, unless it is preceded by I, in
which case it is worth 3.” Interpreting V=3 in this case allows us to always use addition, and IV
= 1 + 3 = 4. From a programming perspective, it allows us to use the previous letter to decide an
action, rather than the next letter, which can simplify our logic.
• When the character is space, it may mean that you have reached the end of a numeral. If there is
a calculation (add, subtract) that needs to be done, this is the time to do it. However, it may be
the space that comes after an operator and before the next numeral. It may also be an extra space,
because any number of spaces can come between numerals and operators.
• When the character is plus (+) or minus (-), it means that another numeral is coming. When that
numeral ends, the desired operation must be performed. Therefore, you must remember that you
have seen an operator in order to perform the operation at the right time.
• When the input character is a linefeed, that means the expression is complete. It’s perfectly legal
for the expression to contain no operators. If the user enters a single Roman numeral followed by
linefeed, then the program will simply print the value of that Roman numeral. (This will be
useful for testing whether your code that reads and interprets the Roman numeral is correct.)
Do not use an array in your program. We have not covered arrays, and there is no reason to store a large
number of characters or numbers.
There is no limit to the number of characters in a numeral, or the number of operations in an expression.
If your program limits either of these in some way, points will be deducted. Do not use the zyBook tests
to determine a limit; we may test your code with inputs that are not shown in the tests.

4
The Wikipedia page (https://en.wikipedia.org/wiki/Roman_numerals) describes one method for
converting from decimal to Roman: Look at each decimal digit and replace with the corresponding letter
sequence or skip if the digit is zero. This will work in most cases, but keep in mind that the rules for this
program allow for an unlimited number of M characters: not restricted to three as it is described on that
page. So there may be more than four digits in the value, which means looking at the thousands digit
may not be sufficient.
An alternative approach is to use successive subtraction. For example, if the number is greater than
1000, print ‘M’ and subtract 1000. Do this as many times as necessary. Then consider successively
smaller cases of interest: 900, 500, 400, 100, etc.
If the result is zero, the decimal value 0 will be printed, and the output Roman numeral is simply an
empty line.
You are allowed to use functions in your program, if you wish. We will likely not cover the use of
functions before this program is due, but you may choose to learn this on your own. The use of functions
is not necessary and not particularly encouraged. Using functions for this program will only allow you to
organize your code differently; there is no clear advantage gained by using functions for this program.

Developing and Submitting the Program


You will submit this code as a zyBook lab, but you will develop the program outside of the zyBook. It
is expected that you will use CLion, but you are free to use whatever development environment that you
want.
1. In CLion, create a new project. Specify a C Executable, and use the C11 standard. Name the
project whatever you like, but I recommend something meaningful like “prog1” or “rcalc”. This
will create a directory in the place where your CLion projects are kept.
2. Now use CLion to complete the program, using the editor, compiler, and debugger to meet the
program specifications.
3. When you are ready, upload your main.c file to the zyBook assignment and submit. This will
run the tests.
If some tests fail, go back to Step 2 and work on your program some more. The input for the failed tests
will give you some idea of what’s not correct, but use the debugger to figure out what’s happening with
your implementation.
Several iterations of Steps 2 and 3 might be necessary. In fact, it’s a reasonable strategy to write a
program that only passes the first test (or some tests), then improve it to pass the next test, etc. (This
even has a fancy name: test-driven development.)
There is no limit to the number of times you can submit. Each submission will overwrite the earlier
ones, so make sure that your new code does not break tests that passed earlier.

Hints and Suggestions


• Don’t overcomplicate the program. Do not use anything that we have not covered in class. (For
example, don’t try to use pointers or string library functions.)
• Work incrementally. Get one part of the code working, and then move to the next. For example,
you might do an initial implementation that only reads a single Roman numeral and prints it as a
decimal integer. This will pass some of the earlier tests. Then extend that to print the result as a
Roman numeral; this will pass more tests. Then implement the operators. It’s ok if your program
5
fails some tests, or even if it crashes when running some tests for program features that you
haven’t implemented yet.
• For compiler errors, look at the source code statement mentioned in the error. Try to figure out
what the error is telling you. Try to fix the first error first, and then recompile. Sometimes,
fixing the first error will make all the other errors go away. (Because the compiler got confused
after the first error.)
• Use a source-level debugger to step through the program if the program behavior is not correct.
If you are using CLion on your own computer, the debugger is integrated with the editor and
compiler, so there’s no excuse for not using it.
• For general questions or clarifications, use Piazza, so that other students can see your question
and the answer. For code-specific questions, post a private message to Piazza and attach your
code as a file. (Do not copy and paste!)

Administrative Info
Updates or clarifications on Piazza:
Any corrections or clarifications to this program spec will be posted on Piazza. It is important that you
read these postings, so that your program will match the updated specification.

What to turn in:


• Submit your main.c file to the zyLab assignment in 15.1 Program 1: Roman number calculator.

Grading criteria:
20 points: Program compiles. If you’ve made some effort to actually solve the problem and the file
compiles with no errors or warnings, you will get these points. You will not get points if you
submit the “hello world” program or an empty/trivial main function.
10 points: Proper coding style, comments, and headers. No global variables. No goto. See the
Programming Assignments section on Moodle for more style guidelines. (You will not get
these points if you only submit trivial code.)
25 points: Correctly reads a single Roman numeral.
15 points: Correctly operates on two Roman numerals.
15 points: Correctly prints result as a Roman numeral.
10 points: Expressions with more than two numerals.
5 points: Correctly deals with negative values.
NOTE: The ZyBook tests will only total 70 points. The first 30 points will be assigned manually by the
grader.
NOTE: Points may be deducted for errors, even if all of the zyBook tests pass. This will be rare, but it
may happen if it is obvious to the grader that the program is written specifically to pass only these tests
and would not pass other similar tests, or if you have violated the specifications (e.g., by assuming a
limit to the number of characters to be read).

6
Do not make assumptions. Write your code to pass any test consistent with this specification. We
reserve the right to run your code on tests that were not provided ahead of time.

Appendix: Sample Runs


In the following examples, text in bold is entered by the user (or test program). NOTE: When running
tests on zyBook, the input will not appear as part of the program’s output. There must be a linefeed after
the output Roman numeral.
Example 1: Just enter one number
Enter an expressing using Roman numerals:
MDCLXXVIII
1678
MDCLXXVIII

Example 2: Simple expression


Enter an expressing using Roman numerals:
XI + IX
20
XX

Example 3: Multi-term expression


Enter an expressing using Roman numerals:
MMI + CCCXII - DLV + C
1858
MDCCCLVIII

Example 4: Zero result


Enter an expressing using Roman numerals:
X + X + X + X - XL
0

You might also like