Introduction to Programming (22C:16, 22C:106)

Project 2: Tuesday, 3/18/97

Introduction:

This is the second of the 4 programming projects that you are required to complete for this class. This project builds on Project 1 and so as a starting point you should either use your code for Project 1 or use the solution posted on the course page. The main differences between this project and Project 1 are as follows:

Later in this handout, you will read more details on the two items listed above.

The goal of this programming project is to give you some practice with the following: (a) char data type, (b) using classes other than the string class, (c) writing a program composed of several functions, (d) using functions that return objects, and (e) checking for and responding to errors in the input.

Input:

As in Project 1, the input to your program is expected to be an arithmetic expression. However, for this project, there is no guarantee that the user will type a valid arithmetic expression. The user may make all kinds of errors while entering input. For example, the user may type a strange character, or the user may type an incomplete expression (that is, the expression might end with an operator), or the user may type two operands consecutively or two operators consecutively. Here are 4 examples of input that do not constitute valid arithmetic expressions. Each example is shown in a separate line.

 
3+  8 plus 9 * 8

3 + 3 +

3 - 8 + 2 10 * 11

3 - + 2 * 11

In the above example, the first line is in error because of ``strange'' characters in the input; the second line is in error because the expression is incomplete; the third line is in error because of two operands immediately following each other; the fourth line is in error because of two operators immediately following each other.

Your program should read the input that the user types and if the input is indeed a valid arithmetic expression, your program should produce as output the value of the expression. If, on the other hand, the input is not a valid expression, then your program should produce an appropriate error message. Later in this handout, you will read more about error messages. As in Project 1, an arithmetic expression can only include non-negative integers as operands and the operators + and *. Furthermore, no parentheses are allowed in arithmetic expressions. Operators and operands in a valid expression may or may not be separated by white spaces. For example, the operator * might immediately follow the operand 89876587 as in the following example.

 
11 * 24567534*3+ 89876587*91111191111 * 1 * 8 + 8

The user will end the input by typing CTRL-D.

In Project 1, you could assume that the arithmetic expression in the input evaluates to an integer that is not too ``large''. This assumption cannot be made for Project 2! In fact, for this project the operands in an arithmetic expression may be arbitrarily large (that is, they may contain arbitrarily many digits). The immediate implication of this is that you cannot use the int or the long int data types to store the operands. Instead you will use the BigInt class.

Reading Input:

You may have realised by reading the above description that it is no longer possible to read operands as integers and operators as strings. Instead the input has to be read character by character while keeping a lookout for possible errors. In particular you will have to write two separate functions for reading input, as described below:

  1. BigInt getOperand()
    This function reads the input, character by character, attempting to ``get'' the next operand from the input. It skips leading white spaces (blanks or end-of-line characters) until it finds the first digit. It then attempts to read a sequence of contiguous digits and stops at the first non-digit character. As it reads the digits, it concatenates them to form a string of digits. This string of digits is eventually used to construct an object belonging to the BigInt class. This constructed object is then returned by the function.

    It is possible that while reading input, the function getOperand() encounters an error in the input. In this case, the function should abandon its task and return a value to the calling function that signals an error. You can read more details on error handling in the next section.

  2. char getOperator()
    This function reads the input character by character attempting to ``get'' the next operator from the input. It skips leading white spaces (blanks or end-of-line characters) until it finds '+' or '*'. The function then returns the operator found. Like the function getOperand(), this function also might encounter errors while reading the input. In such a case, the function should immediately abandon its task and return a value to the calling function that signals an error.

The two functions described above will be repeatedly called to get operands and operators from the input. Thus, instead of simply reading an operand from the input (as you might have done in the solution to Project 1) as follows:

cin >> num1;

for this project, you will use a statement such as:

num1 = getOperand();

Handling Errors:

As mentioned in the above section, the two functions getOperand and getOperator might encounter errors in the input as they are reading it. It is the responsibility of these functions to report the error back to the calling function. Examples of errors that the function getOperand() might encounter are as follows:

(a)
Missing operand: This occurs when getOperand() reads a sequence of 0 or more white spaces, but does not find anything after the white spaces! In other words, the input ends immediately after the white spaces.

(b)
Strange characters found in place of digit: This occurs when getOperand() reads a sequence of 0 or more white spaces and encounters a non-digit character immediately after the white spaces.

This is by no means a complete list of errors that getOperand() might be able to detect. For each distinct error condition that getOperand() detects, it returns an appropriate ``code'' to the calling function. The codes could be -1 for the error described in (a) above, -2 for the error described in (b) above and smaller negative numbers for other errors. Since valid operands are non-negative, any negative value returned by getOperand() will be appropriately interpreted as an error signal.

In a similar manner, the function getOperator() should return appropriate codes for the errors it encounters. For example, getOperator() could return the codes '1', '2', and so on corresponding to the different errors it encounters. Since a valid operator is '+' or '*', a value such as '1' or '2' returned by the function will be appropriately interpreted as an error signal.

A comment about the organization of your program might be appropriate here. Rather than have cout-statements for printing error messages all over your program, you should define a single function that is responsible for printing all the error messages. This function should be called repeatedly with appropriate arguments to print various error messages.

What is the BigInt class?

BigInt is a class created by the author of our textbook Owen Astrachan. The author describes it in Chapter 8 (pages 419-423). At this point we are not interested in how this class was created; we only want to use it. The purpose of this class is to allow us to use arbitrarily large integers in our programs. Recall that using int or long int data type restricts us to use integers with at most 10 digits. The BigInt class has been implemented so that the arithmetic operators that we use with int or long int variables can be used in a similar manner with objects of the BigInt class. Some examples might make this notion clearer.

  1. Consider the following code fragment:
     
    		 BigInt x;
    

    x = 100;

    In the first line above, an object called x belonging to the BigInt class is constructed. This is done by a call to the default constructor in the BigInt class. The constructed object x is automatically initialized to 0 by the default constructor. In the second line, the integer constant 100 is assigned to x.

  2. Consider the following code fragment:
     
    		 BigInt x("87942347965173");
    

    x = x*x;

    In the first line above, an object called x belonging to the BigInt class is constructed. This is done by a call to a constructor in the BigInt class that takes a string as a parameter. The object x is initialized to the integer 87942347965173 when it is constructed. The second line just demonstrates that we can use BigInt objects in assignment statements just as we would use int or long int objects.
The two files bigint.h and bigint.cc that define the BigInt class are available on the NEBULA MACAPPS file server. These are also available by following the link Code from Astrachan's book from our course page. To use the BigInt class in the CodeWarrior environment, copy the files bigint.h and bigint.cc onto your diskette. In addition, copy a file called vector.h from the file server onto your diskette. When you add the file project2.cpp that contains your program to the project, add the file bigint.cc as well.

What to turn in:

Turn in a single 3.5'' Macintosh formatted disk with a single file called project2.cpp that contains your C++ program. Make sure that there is nothing else on your diskette. If your program is on a PC formatted diskette, there is no need to reformat it for a Macintosh since Power Macintosh computers in MLH ITC can read PC formatted diskettes also. However, if you are a PC user you should make sure that your program compiles and executes within the CodeWarrior environment as well. All programs, independent of their origins, have to compile and execute within the CodeWarrior environment. Clearly label your diskette by writing your name, section number, and the project number on it. In addition turn in a printout of your program.

A final word:

Instructions and advice from Project 1 handout related to making your program more readable, still applies. This programming project is much more complicated than Project 1. Please start thinking about it right away! As always, the TAs and I will be glad to help.



Sriram Pemmaraju
Tue Feb 25 12:18:56 CST 1997