CMSC 313 Project 2


Assigned Wednesday Sept 21, 2011
Program Due Sunday Oct 2, 2011
Points 70
Update 23 Sep The original description of the commands in the command file inadvertently included a terminating semicolon. This was a typo. There are no semicolons in the command file. The command file section has been updated.

The Objective

The objective of this assignment is to become familiar using structs, writing and using functions and function prototypes, formatting ouput and reading input from a text file in a C application. Program design, creating a library of related functions, guarding header files, separate compilation, code reuse and makefiles are also important aspects of this project.

The Task

Two of the basic units of elementary arithmetic are fractions and mixed numbers. In this project you will implement a structure to represent a fraction and a structure to represent a mixed number. Your program will read commands from a text file and perform the arithmetic operations specified.

Note that while a correct implementation of fractions and mixed numbers is important, correct program design to achieve maximum abstraction and code reuse, creating and implementing an appropriate library of fraction functions, using guarded header file(s), proper use of "static" and creating a makefile are equally important in this project. Your project grade will be equally divided between functionality and these coding/design concepts.

How does your program work?

  1. Your program prompts the user for the name of the command file to process.
  2. Your program reads the command file and executes each command until end-of-file is reached. All commands must be echoed to the screen. See sample output below.

The command file

Each command in the command file will be on a separate line. Command arguments are separated by whitespace. All command names will be in upper-case as shown below. All command arguments will be valid. In this description, n1 is the numerator of the first fraction operand, d1 is the denominator of the first fraction operand, n2 is the numerator of the second fraction operand and d2 is the denominator of the second fraction operand.
  1. ADD n1 d1 n2 d2 -- Add the two fractions specified by the arguments then print the result in the format
    (n1 / d1) + (n2 / d2) = x / y where x / y is their sum.
  2. SUBTRACT n1 d1 n2 d2 -- sbtract the two fractions specified by the arguments then print the result in the format
    (n1 / d1) - (n2 / d2) = x / y where x / y is their difference..
  3. MULTIPLY n1 d1 n2 d2 -- multiply the two fractions specified by the arguments then print the result in the format
    (n1 / d1) * (n2 / d2) = x / y where x / y is their product.
  4. DIVIDE n1 d1 n2 d2 -- divide the two fractions specified by the arguments then print the result in the format
    (n1 / d1) / (n2 / d2) = x / y where x / y is their quotient.

Hints, Notes and Requirements

    Other Requirements

  1. You must use a struct to model a fraction.
  2. You must use a struct to model a mixed number.
  3. The numerators and denominators in the file may be negative. If both are negative, treat them both as positive. If only one of them is negative, treat the numerator as negative and the denominator as positive (being consistent makes your code easier).
  4. The numerator of a fraction may be zero (except for the DIVIDE command).
  5. The denominator of a fraction may be one. We guarantee that denominators are not zero.
  6. The results of all operations must be output in lowest terms (i.e. "reduced").
    If the result of an operation is zero, print zero; do not print a fraction.
    If the result of an operation is an improper fraction, output both the improper fraction in lowest terms and the equivalent mixed number.
  7. Mixed numbers must be output in the simplest form possible. If the the improper fraction is equivalent to an integer, print the integer; do not print the fraction. If the improper fraction is negative, print the whole number as negative.
    For example
    The improper fraction 7/3 would be printed as 2 1/3
    The improper fraction 6/3 would be printed as 2
    The improper fraction -7/3 would be printed as -2 1/3
  8. Your code must be separated into multiple .c files as follows. Appropriate .h files are also required. You are free to choose any names for your files.
    1. main( ) and helper functions specific to this project may be in the same .c file
    2. Since fraction-oriented functions are reusable, they must be placed in a separate .c file and their prototypes placed in an appropriately named .h file.
    3. Since mixed numbers are closely related to fractions their functions may be in the same file. You may choose to make a separate library for mixed numbers if you wish.
  9. You must submit a makefile that creates an executable named Project2 just by typing make at the Unix prompt. The compiler flags in our makefile must include -Wall.
  10. Proper use of static, typedef and #define required. Do not abuse the use of static to create variables with file scope in order to avoid passing arguments to functions.
  11. Hints

  12. If you think about how you would implement a fraction class and a mixed number class in Java/OOP, the "methods" of the fraction and mixed number classes become the fraction and mixed number"library" that go into a separate .c file.
  13. Use incremental development.
    1. Implement the basic fraction functions first and unit test them.
    2. Write the primary processing part of main to handle just one command. Create a simple command file to test this code in main and the polynomial/term functions.
    3. Add more commands and functions.
    4. Rinse and repeat.
    5. Worry about the mixed numbers last.
  14. Several small fraction functions are better than a few large ones (think "code reuse"). Our implementation of this project resulted in more than 10 library functions almost all of which were less than 10 lines of code and some with as few as a single line. One or more application specific helper functions are also possible.
  15. gdb is your friend. Use it.
  16. Visit blackboard discussion board regularly. Create and share your own command files via blackboard.
  17. Struct assignment is your friend.
  18. Structs are passed to functions by value and may be used as function return types.
  19. You cannot use a string in a switch statement.
  20. Adding fractions does not require finding a common denominator. Use the general rule (a / b) + (c / d) = (a * d + c * b) / (b * d) and then simplify to lowest terms.
  21. Notes

  22. We guarantee that the command file will be well-formed and that all data in the command file will be valid.
  23. Your code in main will be ugly and repetitive. Sorry, there's no good way to avoid it.
  24. Changing a fraction to lowest terms requires finding the greatest common divisor (gcd) of the numerator and denominator. Pseudo code for Eucid's gcd algorithm using the subtraction method is given below. It assumes that a and b are non-negative and that b is not zero.
    function gcd(a, b)
        if a is zero, return b;
        while b is not zero
            if a > b
               subtract b from a
               subtract a from b
        return a;
    end function

Sample output

linux1[384]% Project2
Command File Name: cmds.txt

ADD: 1, 2, 3, 4
(1/2) + (3/4) = 5/4
As mixed number: 1 1/4

MULTIPLY 2, 3, 4, 5
(2/3) * (4/5) = 8/15

ADD: 0, 2, 6, 10
(0) + (6/10) = 3/5

SUBTRACT 1, 2, 1, 4
(1/2) - (1/4) = 1/4

SUBTRACT 1, 2, 1, 2
(1/2) - (1/2) = 0

DIVIDE 1, 3, 4, 5
(1/3) / (4/5) = 5/12

ADD: -3, 6, -4, 12
(-3/6) + (-4/12) = -5/6


Project Grading

The project grade will be broken approximately evenly between functionality and coding as described below.
  1. Functionality (35 points)
    Note that your functionality score will be zero if your code does not compile or create an executable.
    1. Basic cases - This might be a command file that performs each operation but uses fractions with the same denominator, or does not result in mixed numbers or simpilification to lowest terms.
    2. More complex cases - This might be a command file with commands whose numerators and/or denominators are negative, whose numerator is zero, whose result requires simplifying to lowest terms, whose result is an improper fraction, etc.
    3. Atypical cases - This might be an empty file, or a file that cannot be opened.
    4. Stress cases - This might be operations that use fractions with very large or very small numerators or denominators.
  2. Code (35 points)
    1. Compilation Requirements - All .c files must compile without errors or warnings.
      Your makefile must compile all .c files and create an executable named Project2.
    2. Coding Requirements - we expect that you adhere to the project requirements listed above with regard to the use of #define, const variables, structs, typedefs, and static. We expect that your code produces all required output in the required format.
    3. Design - we expect that your code shows sufficient decompostion into appropriate functions used to create a fraction and mixed number library in a separate .c file. An appropriate header file should also be created.
    4. Style - we expect that your code adheres to the course coding standards, particularly with respect to function and file comments and to naming conventions.

Submitting the Program

You can submit your project using the submit command.

submit cs313 Proj2 <list of .c and .h files> makefile

See this page for a description of other project submission related commands. To verify that your project was submitted, you can execute the following command at the Unix prompt. It will show all files that you submitted in a format similar to the Unix 'ls' command.

submitls cs313 Proj2