Click here to Skip to main content
15,884,099 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am having a few issues, I have created a calculatir program for my students to look at to gain an understanding of procedural programming.

The issues i am having relates to the calculations not working correctly when the functions/procedures are called, same i can not get the the display results to display the answer.

Please feel free to change the code to make it work, but please add comments to it.

I have been trying to resolve for most of this evening looking at different approaches with no joy.

Thank you

C++
<pre>
#include <iostream>

double a, b;
double calResult;

char showMenu(void);
void addCal(void);
void subCal(void);
void mulCal(void);
void divCal(void);
void displayResult(void);
//void clearBuffer(void);

int main()
{
	char menu;
	

	std::cout << "Welcome to a basic C++ calculator\nEnter in two numbers you wish to perform a calculation on.\nThen select the option you which to perform\n\n";
	std::cout << "Enter first number: ";
	std::cin >> a;
	std::cout << "Enter second number: ";
	std::cin >> b;
	
	do
	{
		menu = showMenu();
		switch (menu)
		{
		case 1:
			addCal();
				
			//clearBuffer();
			break;

		case 2:
			subCal();
			//clearBuffer();
			break;

		case 3:
			mulCal();
			//clearBuffer();
			break;

		case 4:
			divCal();
			//clearBuffer();
			break;

		}
		displayResult();
		std::cout << "\n";

	}

	while (menu != 'X' && menu != 'x');
	{
		std::cout << "Thank you!\nGoodbye!";
		
	}
}

char showMenu(void)
{
	char option;

	std::cout << "Please select a calculation option.\n";
	std::cout << "1 - Addition\n";
	std::cout << "2 - Subtraction\n";
	std::cout << "3 - Multiplication\n";
	std::cout << "4 - Division\n";
	std::cout << "X - eXit\n\n";
	std::cout << "Enter choice (1,2,3,4 or X): ";
	std::cin >> option;
	return option;
}

void addCal(void)
{
	double add;

	add = a + b;
	add = calResult;
		
}

void subCal(void)
{

	double sub;

	sub = a - b;
	sub = calResult;
	

}

void mulCal(void)
{

	double mul;

	mul = a * b;
	mul = calResult;
	
}

void divCal(void)
{

	double div;

	div = a / b;
	div = calResult;
	
}

void displayResult(void)
{
	std::cout << "The anwser is: ", calResult;
	
}

/*void clearBuffer(void)
{
	while (getchar() != '\n');
}*/


What I have tried:

I have tried to output statements in each function/procedure but they do not display once the calculation is done, that is why i had to create a display function.

I have also tried to allocate the results from add, sub, mul and div to a new variable that will be used in the display result, but due to the calculations not working, it returns a value of 0.0000000 (used break to check).
Posted
Updated 28-Aug-19 6:02am
Comments
Stefan_Lang 28-Aug-19 3:45am    
When I was at university, I've found that overly complex examples are not very good when all you wish to show is one language feature or programming concept.

Try limiting code examples to at most 10-15 lines of code, otherwise your students will have a hard time finding out which parts are in fact relevant to the thing they are trying to learn. Anything beyond that detracts from the actual topic.

I am well aware that you can't compose meaningful code examples in just 10-15 lines. But that isn't necessary. You can leave the meaningful stuff to the exercises.

P.S.: I might also add that code examples are not required to actually run, although of course it's a good idea to verify that at least the segment you show to your students does what it's supposed to.

You have a few problems in this code.
In showMenu, you read the menu option as a char, The problem is that a digit as a char is written as '1'.
So your code must be changed from
C++
menu = showMenu();
switch (menu)
{
case 1:
    addCal();

    //clearBuffer();
    break;

case 2:
    subCal();
    //clearBuffer();
    break;

case 3:
    mulCal();
    //clearBuffer();
    break;

case 4:
    divCal();
    //clearBuffer();
    break;

}

to
C++
menu = showMenu();
switch (menu)
{
case '1':
    addCal();

    //clearBuffer();
    break;

case '2':
    subCal();
    //clearBuffer();
    break;

case '3':
    mulCal();
    //clearBuffer();
    break;

case '4':
    divCal();
    //clearBuffer();
    break;

}

Learning the debugger will help you to understand what your programs are doing.

Your code do not behave the way you expect, or you don't understand why !

There is an almost universal solution: Run your code on debugger step by step, inspect variables.
The debugger is here to show you what your code is doing and your task is to compare with what it should do.
There is no magic in the debugger, it don't know what your code is supposed to do, it don't find bugs, it just help you to by showing you what is going on. When the code don't do what is expected, you are close to a bug.
To see what your code is doing: Just set a breakpoint and see your code performing, the debugger allow you to execute lines 1 by 1 and to inspect variables as it execute.

Debugger - Wikipedia, the free encyclopedia[^]

Mastering Debugging in Visual Studio 2010 - A Beginner's Guide[^]
Basic Debugging with Visual Studio 2010 - YouTube[^]

1.11 — Debugging your program (stepping and breakpoints) | Learn C++[^]

The debugger is here to only show you what your code is doing and your task is to compare with what it should do.
 
Share this answer
 
Comments
Chris.Harrison2603 27-Aug-19 19:36pm    
Thank you will try that later today
Maciej Los 28-Aug-19 4:09am    
Well explained!
Patrice T 28-Aug-19 4:11am    
Thank you
Why are you using global variables rather than locals and passing them to each of the calculator functions. And each function should return its value to the caller. Thus you should have something more like:
C++
<pre>
#include <iostream>

using namespace std;   // so you don't need std:: everywhere

// lines removed for readability

int main()
{
	char menu;
    double a, b;
    double calResult;
	

	std::cout << "Welcome to a basic C++ calculator\nEnter in two numbers you wish to perform a calculation on.\nThen select the option you which to perform\n\n";
	std::cout << "Enter first number: ";
	std::cin >> a;
	std::cout << "Enter second number: ";
	std::cin >> b;
	
	do
	{
		menu = showMenu();
		switch (menu)
		{
		case '1':  // as Patrice pointed out showMenu returns a char not an int
			calResult = addCal(a, b);
				
			break;

// lines removed for readability
		}
		displayResult(calResult);
		cout << "\n";

	}

	while (menu != 'X' && menu != 'x');
	{
		cout << "Thank you!\nGoodbye!"; // don't need std:: prefix
		
	}
}

char showMenu(void)
{
// lines removed for readability
}

double addCal(double number1, double number2)
{
	double add;

	add = number1 + number2;
	return add;
		
}

void displayResult(double number)
{
	cout << "The anwser is: ", number;
	
}


To be perfectly honest, and sorry to have to say this, but I think you need to do a lot more learning yourself before trying to teach programming to students.
 
Share this answer
 
Comments
Maciej Los 28-Aug-19 4:39am    
Great answer!

BTW: My GrandMa usually said: "you learn all your life, but you die being stupid". This is not a perfect translation, but i hope it makes sense. In other words, the process of learning have to be continuos.
Richard MacCutchan 28-Aug-19 4:44am    
Thank you. I am sure that phrase sounds better in Polish, but I totally agree with the sentiment.
Maciej Los 28-Aug-19 4:51am    
:)
If you want to explain procedural programming, you should check out a good book on that topic, or Wikipedia at Procedural programming - Wikipedia[^]

Note how Wikipedia explains it by comparing it to other programming styles. Showing a single program will never be enough to explain what PP means. You have to point out the differences to other paradigms.

If this code is meant as an example to students, you should fix the following issues:
1. Do not use global variables.
a) If you have functions that require input, pass it as function argument(s). That way you can see right from your code that processing this function is dependent on these parameters.
b) Likewise, if a function calculates some result, pass it back to the caller as a return value. Again, this improves readability: assign the result of a function is implicitely clear; reading the result from some apparently unrelated global variable is not.
If you go by these rules, you should never need global variables.

2. Name your functions appropriately. Point in case, see below:

3. If you select a function name that you think is appropriate, and then end up using that function only to discover that it doesn't seem right, then you probably added functionality to that function that doesn't belong there, and maybe should be moved to a separate function.

Point in case: the function showMenu() may originally have been intended to just print the menu that the user can choose from. However, at some point you also added reading the user input. It's not much, but that part is clearly not covered by the function name, and the apparent original purpose of that function. The line menu=showMenu() is confusing, because you wouldn't expect any return from a function called show...(). Either rename it to reflect its extended functionality (e. g. getCommand()), or better, extract the part reading user input into a separate function.

4. Don't use one letter variable names. While this may be ok in some cases for small programs like these, if you are using these programs to teach, you should make sure to make the code as easily readable as you can. Renaming a to first_operand and b to second_operand may seem tedious, but then it's instantly clear what they mean and they won't detract your students from the real problem you'd like to focus on.

4.a) Don't abbreviate! Always be aware that other people don't share your background information and may not understand any abbreviations as clearly as you do. Or at all. In code, there's no advantage for using an abbreviated variable or function name, since modern editors provide autocompletion. (and if your editor doesn't provide autocompletion, get one that does immediately!). Your functions addCal, subCal, etc. make me wonder, what does the suffix Cal mean? You're not adding calculators, are you? Anyway, if you follow my advice on item 1., you should pass the two operands as function arguments, and then it's implicitely clear what is being added or subtracted (reminding me: use 'subtract', not 'sub' - the latter is used in many different contexts and may be ambiguous).

5. Almost forgot that one: Do not use 'using namespace' ! Namespaces are used to disambiguate names and symbols from different sources. With 'using namespace' you disable that mechanism and increase the chance of conflicts. Moreover, a code line that calls a function from a different namespace is easier to understand when it's fully qualified (i. e. has the namespacee attached). Without the information of the namespace that it's orginated from, the reader needs to guess what function or symbol it is, or where to find more info.

P.S.: a reasonable alternative to 'using namespace' are using directives: replace your using statement with thie following code, and you're good:
C++
using std::cout;
using std::endl;
using std::cin;

6. Just a minor thing: To print a linebreak, dont't print '\n', use
C++
std::cout << std::endl;
The former might work almost everywhere, but the latter is guaranteed to work everywhere. Remember that on some OS's the prefered linebreak style is \r\n, not \n

Finally, a little code to show what I explained above:
C++
#include <iostream>
double add(double const first_operand, double const second_operand)
{
    return first_operand + second_operand;
}
void show_commands()
{
    std::cout << "Select option from the list below:" << std::endl;
    std::cout << "'a' - add two numbers" << std::endl;
    // expand here as neccessary
    std::cout << "'q' - quit" << std::endl;
}
char get_command()
{
    char command;
    do
    {
        std::cin >> command;
        switch (command)
        {
            case 'a': //command recognized
            break;

            case 'q': //command recognized
            break;

            default:  //command not recognized
            command = 0;
            std::cout << "Please select valid command ('q' to quit)." << std::endl;
            break;
        };
    } while (command == 0);
    return command;
}
double read_value()
{
    double value = 0.0;
    std::cout << "Please enter numeric value:" << std::endl << "> ";
    std::cin >> value;
    return value;
}
void show_result(double const result)
{
    std::cout << "The result is: " << result << std::endl;
}
void calculator()
{
    char command; // must be declared here to use it in the while() condition below
    do
    {
        show_commands();
        command = get_command();
        switch (command)
        {
            case 'a':
            {
                double first_operand = read_value();
                double second_operand = read_value();
                double result = add(first_operand, second_operand);
                show_result(result);
            }
            break;
            
            default:
            command = 0; // signal to get out of loop
            break;
        };
    } while (command != 0);
}


When you get to object oriented programming , you can formalize the above code a little more by introducing a command object that allows you to treat all those menu printing and switch case handling a little more elegantly. But that's for a different QA ;-)


P.S.: After sleeping over it, I came to the conclusion that you shouldn't use std::cout and std::cin in your example: these show how to use objects, following the object oriented paradigm. If your point is to present procedural programming, you shouldn't water down your example with bits of OO code!

Having said that, why not simplify everything and just do this:
C++
#include <stdio.h>
void hello(char const* name)
{
    printf("Hello procedural %s!\n", name);
}
int main()
{
    hello("world"); // procedural call
    return 0;
}
 
Share this answer
 
v2
Comments
Richard MacCutchan 28-Aug-19 12:11pm    
An excellent response. However, I advised the "using namespace std" as it seems sensible in a simple console application. But I take your point about possible conflicts if multiple namespaces are referenced.
Maciej Los 28-Aug-19 12:26pm    
Agree.
Stefan_Lang 29-Aug-19 3:20am    
Agreed, using namespace std is acceptable in a source file (never in a header) as long as we're talking small programs. I mentioned it only because the code is used as an example for students, and I didn't want to advertise a dubious practice.

P.S.: I just realized that using directives (e. g. using std::cout; ) are totally fine. Will add that to my solution...
Richard MacCutchan 29-Aug-19 5:49am    
Given the example code I think there are more than enough dubious practices in there already. :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900