Lab #3 FAQ

(Frequently Asked Questions)

Updated: Sunday, July 20, at 8:15 pm

Here are some tidbits that might help some of you who are having trouble starting the assignment. I've noticed that some students are asking questions similar to these:

******************************
Q: How should I prompt the user for an expression?
A: You should use the handout as a guide. I give a few sample runs so that there is no confusion as to what the program should prompt for and display. There is a single prompt, then the user types in a single line, and then the program prints a single line of output. Don't prompt the user for each individual input (i.e. DON'T prompt for the first number, then prompt for the first operator, then prompt for the second number, etc.) The user should naturally type in an expression that alternates between numbers and operators:

number operator number operator number

That's what the samples show: 5 * 2 / 4. Remember, you can have zero or more spaces between the numbers and the operators. Both of these will work:
  5*2/4
  5      * 2  /           4 
*****************************
Q: What if the user types an operator other than +, -, *, or /
A: You need to detect that. We learned how to catch errors like this using the else part of the if statement, or the default part of the switch statement. You should print out an error message similar to the message you display when dividing by 0. As with divide by zero, for easier of implementation you can assume the result of a nonsense operator is zero:
  5 $ 2 * 3
This would result in 0 because 5 $ 2 is invalid, and we say invalid results are 0, so 0 * 3 is 0. Some of you are implementing a function to verify the expression, in which case you won't have this problem because you are detecting illegal expression *before* trying to evaluate them. This is the recommended approach.


****************************
Q: How do I know if the user is going to input an integer or a float?
A: You don't, so you must assume they will enter floats. This is a safe assumption because it is legal to assign an integer to a float, but it is NOT legal to assign a float to an integer. Your program should use floats only.


****************************
Q: If the user types in an illegal expression, do I have to re-prompt them for a valid one?
A: No. If the input is illegal, either invalid operators or division by 0, you just need to detect that, print an appropriate error message, and quit. Don't try to "recover" from the invalid input. You haven't learned enough yet to do so.


****************************
Q: If the user enters integers, should I display them in printResults() using decimal places?
A: No, in this assignment, you shouldn't use cout.setf(ios::fixed) or cout.setf(ios::showpoint). To be safe, you should just use setprecision(5) with no setw() calls. You'll see why when you test your program. If you don't see why, you haven't tested your program enough. A couple of examples could be:
  Enter an expression in the form: num op num op num (ex. 5 * 3 - 8)
  8.3456  -  5  +  1.0001
  The expression 8.3456 - 5 + 1.0001 evaluates to 4.3457

  Enter an expression in the form: num op num op num (ex. 5 * 3 - 8)
  4.25 * 4 + 7
  The expression 4.25 * 4 + 7 evaluates to 24
****************************
Q: Do I have to write a function to verify the expression? Do I have to write a function to evaluate simpler expressions?
A: No. But you will be writing about 3 times as much if you don't. When it comes to functions, it seems that the hardest part for students is the concept of reference parameters. In this assignment, the only function that requires reference parameters is the getData() function (or whatever you are calling the function that prompts the user for input and returns it) Don't write a function to replace the built in operators; write a function to evaluate what the user inputs. Here is how the function would be described in English:
  float evaluateSimpleExpression(float operand1, char operator, float operand2)
  {
     float result;

     find out what the operator is
     if it is '+' then
        result = the sum of the two operands
     else if it is '-' then 
        result = the difference of the two operands
     else if it is '*' then
        result = the product of the two operands
     else if it is '/'
        result = operand1 divided by operand2
     else
        print error message "invalid operator"

     return the result;
  }


*****************************
Q: Why doesn't the compiler accept my expression?
A: Because it's not an expression.

Several people have been trying to do this same thing:

You prompt the user for 5 pieces of information, namely, 2 operators and 3 operands. So far, everything is fine. Then, when you try to evaluate the expression, the compiler gives weird messages. I'll try to describe what you as the programmer are trying to do.
Let's say you prompt the user for the input and assign the inputs to:
  operand1, operator1, operand2, operator2, operand3
Most people are doing this, which is correct. Next, you try to do something like this:
  result = operand1 operator1 operand2 operator2 operand3;
but it doesn't work. What you are thinking is that the program is going to substitute the inputted values for the variable names. For example, let's say the user typed:
  5 * 2 - 3
when you prompted for input. This would assign 5, '*', 2, '-', 3 to operand1, operator1, operand2, operator2, operand3, respectively. Now, you are expecting the program to substitute these into the statement:
  result = operand1 operator1 operand2 operator2 operand3;
which should end up like:
  result = 5 * 2 - 3;
But that's not what happens. This is a common mistake for beginning programmers. The problem is that you are expecting the program to "rewrite" the C++ code that you wrote.

What you must do is write all of the code required. You must write the code that will do multiplication, division, addition, and subtraction, because you don't know what the user is going to input. Once you have written all of the necessary code, it doesn't matter what operators the user inputs; you can handle them all.

The first task of your program, and it's also the whole point of the program, is to detect which of the four operations to invoke: * / + -

Once you figure that out (by using if statements or switch statements) you can then execute code in your program to perform these operations. For example, lets say the program only wanted a simple expression: 1 operator and 2 operands, to do the calculation (assuming you've already prompted the user and got the input) you would do something like this:
 float result;
	
 if (operator == '*') 
    result = operand1 * operand2;
 else if (operator == '/')
    result = operand1 / operand2;
 else if (operator == '+')
    result = operand1 + operand2;
  else if (operator == '-')
    result = operand1 - operand2;
This would assign the correct value to result. You can't just "plug in" the characters that the user typed in:
  result = operand1 operator operand2;
and expect this expression to be replaced by (for example the user typed 5 * 4):
  result = 5 * 4;
This is where some students are getting hung up.

You MUST use a method like the one I've shown above to

1. detect which character (operator) was typed in by the user
2. perform the operation that corresponds to the operator typed in

The assignment is slightly harder than this because you are asked to evaluate an expression with 2 operators and 3 operands. So in addition to what I've shown, you must decide which operator of the two has higher precedence and perform that operation first. You would perform that operation like I showed above. Then, you would perform the second operation based on what the other operator is.

*****************************
Q: Why can't the computer evaluate the expression directly?
A: Because it's not an expression.

What is not built-in to the C++ language, is the ability to take a string of characters (for example, 5 - 2 / 4) typed by the user, and have the computer evaluate it. The computer can evaluate:
 
  result = 5 - 2 / 4
directly, without any intervention from your program. The issue is that the user is typing characters (numbers and symbols) from the keyboard that are assigned to variables via the cin statement. What you need to do is figure out how to get the computer to evaluate the expression that was entered by the user.
The problem is that the 'expression' entered by the user is not an expression to the computer. An expression to the computer consists of constants, variables, and operators. The expression you get from the user consists *only* of variables. To be exact, 3 variables contain numbers (floats) and 2 variables contain characters (chars). There are no operators. The definition of an expression (simplified for this example) is:
  variable operator variable;
where operator is either *, +, -, or /. Don't confuse this with what the user typed in. Sure, the user typed * at the prompt, but what you have is NOT an operator, it's a variable. Exactly, it's a variable of type char. So, although it looks like an operator, it's not. Treating it as an operator is sort of like doing this in your code:
  result = 5 '-' 2 '/' 4
because literal characters are enclosed in single quotes. To the computer, this is illegal. You must substitute an expression that the computer can evaluate for the string of characters type in by the user.
That's why you are doing this: (using a C++ expression in place of the user's 'expression')
 float result;
        
 if (operator == '*') 
    result = operand1 * operand2;     // valid expression
 else if (operator == '/')
    result = operand1 / operand2;     // valid expression
   .
   .
   .
These are valid C++ expressions:
  5 * 4;
  operand1 + 4;
  4 - operand2;
  operand1 * operand2;
  operand2 - operand1 * operand3;
These are NOT C++ expressions:
  5 '*' 4
  operand1 '+' 4
  4 '-' operand2
  operand1 '*' operand2
  operand1 operator1 operand2 operator2 operand3

They are NOT valid because there are no operators. There are literal characters that look like operators, and there are variables that contain characters that look like operators.

******************************
Q: Don't you need at least one space between variables entered? How will the program work with out one?
A: For our program, using the cin statement, you don't need to worry about spaces.

You need a space *only* if all input is numerical. For example, suppose the user wants to input 3 integers:
 17, 23, and 44
The user MUST separate them with at least one space like this:
 17 23 44
If they didn't, how would you know what this means:
 172344
You wouldn't, the program would think that you entered only one number.
In our assignment, since there is a mandatory symbol (*, /, +, -) between each number, the cin statement knows where each number and symbol begins and ends, so it can handle:
 5-2*3
without any problems.

****************************** Other tips:

1. TEST, TEST, TEST your programs! I would recommend that you should have at least 20 different tests for your programs. Considering there are 16 different combinations of operators the user can input. Also, if you test using integers, using floats, and using both, you will see why you don't want to use cout.setf() at all.


2. If you look at the expression you are evaluating, you'll notice that it is really 2 expressions in one. For example, the expression
  5 * 2 / 4
requires 2 evaluations. The first evaluation is 5 * 2. This results in 10. The second evaluation is 10 / 4 which results in 2.5, and that's how the answer was arrived at.

Some of you have a function named evaluateExpression, and are trying to evaluate the entire expression at once. That's why you have so many if statements or cases in your switch statements. Although you will eventually get the correct result, this can be a complex and tedious task, especially if there was another operator and operand.

The purpose of lab #2 was to show you how you can 'break' up a bigger problem into smaller problems. You could have written the entire program in main(). However, your program would have been over 10 times larger than it was. By now, most of you recognize that our lab assignments can be broken down into 3 basic parts:
  getting data
  calculating
  printing results
In lab #3, you would be wise to break down the calculating part into 2 parts. If you don't, you will be trying to evaluate the entire expression at once. If you break the expression down into 2 evaluations (sub-expressions), you can then see that the code you use to evaluate the first sub-expression is identical to the code required to evaluate the second sub-expression.

The way to do this, without duplicating the code for each sub-expression, is to create a function to evaluate sub-expressions. Sub-expressions are very simple; they contain a single operator and two operands; a left operand and a right operand. Also, with only one operator, there is no precedence, so you can just evaluate the simple expression. This function to evaluate a simple expression would only need to be passed the single operator, and the two operands on either side of it

In the example problem:
  5 * 2 / 4
You could pass 5, '*', and 2 to this function to evaluate it. Let's say the function evaluates it and you assign the result to a variable called first_result. Now, you pass first_result, '/', and 4 to the *same* function, which will evaluate that and return the result. Maybe you assign this result to second_result.

You'll notice that in both cases you are passing a float, a char, and another float. This is the hint that you may be able to use the same function twice. The only difference really is that the operators are different. (The numbers are too, but that's more trivial). This is especially apparent when the operators may be the same:
 5 * 2 * 4
Here, you would pass:
  5, '*', 4
to the function, getting some result (the result would be 20, but you would assign that to some temporary variable). Then, you would pass:
  temp_variable, '*', 4
to the same function. The function would evaluate it just as it did the first time, but since the values of the floats are different, the result will be different. In this case the result is 80, and that's what the entire expression evaluates to.

The only decision that needs to be made in the function I'm describing is a way for it to tell if it should do:
  5 * 2,
  5 / 2,
  5 + 2, or
  5 - 2
But since that information is passed in (the operator), you can tell which operation needs to be performed.

The job of evaluateExpression should be to 'decide' what to pass first and what to pass second. In the original example, it doesn't matter because the operators have the same precedence. However, in the second example in the handout, it makes a difference. There, you would first pass:
  2, '/', 4
and then pass:
  5, '-', temp
assuming that you saved the first calculation in temp.

This method I'm describing is how I'm hoping most will do it. Otherwise, it can get a little messy and there will be a lot of duplication of code since both expressions need to be evaluated in an identical manner.


3. Ask me questions. Those of you who do are finding out that I give lots of hints. But, you must demonstrate that you have spent some time trying to solve the problem before I will give detailed directions.


Back to Outline