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:
using std::cout;
using std::endl;
using std::cin;
6. Just a minor thing: To print a linebreak, dont't print '\n', use
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:
#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;
std::cout << "'q' - quit" << std::endl;
}
char get_command()
{
char command;
do
{
std::cin >> command;
switch (command)
{
case 'a': break;
case 'q': break;
default: 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; 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; 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:
#include <stdio.h>
void hello(char const* name)
{
printf("Hello procedural %s!\n", name);
}
int main()
{
hello("world"); return 0;
}