You could add a prototype declaration of main
immediately after the #include
directives:
int main( void );
However, although it is legal to call main
recursively in C, this is generally not recommended. The more you do this, the more the stack will grow, and this could lead to a stack overflow if you do this thousands or millions of times.
A better option would be for the content of your main
function to run in an infinite loop and for you to add an additional input option to exit the program:
int main( void )
{
for (;;) //infinite loop
{
printf(
"ADVANCED CALCULATOR VERSION 0.2\n"
"CALCULATOR OPTIONS ARE:\n"
"1. ADDITION\n"
"2. SUBTRACTION\n"
"3. MULTIPLICATION\n"
"4. DIVISION\n"
"5. ADVANCED OPERATIONS\n"
"6. QUIT\n"
"PLEASE SELECT YOUR OPTION.\n"
);
if ( scanf( "%d", &option ) != 1 )
{
printf( "Invalid input!\n" );
exit( EXIT_FAILURE );
}
switch ( option )
{
case 1:
case 2:
case 3:
case 4:
printf( "FIRST NUMBER?\n" );
if ( scanf( "%d", &integer1 ) != 1 )
{
printf( "Invalid input!\n" );
exit( EXIT_FAILURE );
}
printf( "SECOND NUMBER?\n" );
if ( scanf( "%d", &integer2 ) != 1 )
{
printf( "Invalid input!\n" );
exit( EXIT_FAILURE );
}
switch ( option )
{
case 1:
addition();
break;
case 2:
subtraction();
break;
case 3:
multiplication();
break;
case 4:
division();
break;
}
break;
case 5:
printf( "Not yet implemented!\n" );
break;
case 6:
printf( "Quitting program as requested.\n" );
exit( EXIT_SUCCESS );
default:
printf( "Invalid input!\n" );
}
}
}
Now, you can remove the calls to main
in all of your functions.
Note that in the code above, I have also replaced your if
...else if
chain with a nested switch
statement to prevent code duplication. I have also added a bit of input validation.
You will have to add #include <stdlib.h>
in order to use the function exit
.
It is also worth noting that using global variables is generally considered bad programming practice. I have rewritten your entire program to use function arguments and local variables instead:
#include <stdio.h>
#include <stdlib.h>
void addition ( int left, int right )
{
printf( "The result is %d.\n", left + right );
}
void subtraction ( int left, int right )
{
printf( "The result is %d.\n", left - right );
}
void multiplication ( int left, int right )
{
printf( "The result is %d.\n", left * right );
}
void division ( int left, int right )
{
printf( "The result is %d.\n", left / right );
}
int main( void )
{
for (;;) //infinite loop
{
int option;
int left, right;
printf(
"ADVANCED CALCULATOR VERSION 0.2\n"
"CALCULATOR OPTIONS ARE:\n"
"1. ADDITION\n"
"2. SUBTRACTION\n"
"3. MULTIPLICATION\n"
"4. DIVISION\n"
"5. ADVANCED OPERATIONS\n"
"6. QUIT\n"
"PLEASE SELECT YOUR OPTION.\n"
);
if ( scanf( "%d", &option ) != 1 )
{
printf( "Invalid input!\n" );
exit( EXIT_FAILURE );
}
switch ( option )
{
case 1:
case 2:
case 3:
case 4:
printf( "FIRST NUMBER?\n" );
if ( scanf( "%d", &left ) != 1 )
{
printf( "Invalid input!\n" );
exit( EXIT_FAILURE );
}
printf( "SECOND NUMBER?\n" );
if ( scanf( "%d", &right ) != 1 )
{
printf( "Invalid input!\n" );
exit( EXIT_FAILURE );
}
switch ( option )
{
case 1:
addition( left, right );
break;
case 2:
subtraction( left, right );
break;
case 3:
multiplication( left, right );
break;
case 4:
division( left, right );
break;
}
break;
case 5:
printf( "Not yet implemented!\n" );
break;
case 6:
printf( "Quitting program as requested.\n" );
exit( EXIT_SUCCESS );
default:
printf( "Invalid input!\n" );
}
}
}
Another issue is that scanf
is generally not recommended for user input. When used with user input, it often behaves in a non-intuitive manner, such as
- not always reading a whole line of input at a time, and
- accepting input as such "6abc" as valid input for the number
6
.
Here is a demonstration of these two issues using a program compiled with the code posted above:
Demonstration of first issue:
ADVANCED CALCULATOR VERSION 0.2
CALCULATOR OPTIONS ARE:
1. ADDITION
2. SUBTRACTION
3. MULTIPLICATION
4. DIVISION
5. ADVANCED OPERATIONS
6. QUIT
PLEASE SELECT YOUR OPTION.
1
FIRST NUMBER?
30 50
SECOND NUMBER?
The result is 80.
Demonstration of second issue:
ADVANCED CALCULATOR VERSION 0.2
CALCULATOR OPTIONS ARE:
1. ADDITION
2. SUBTRACTION
3. MULTIPLICATION
4. DIVISION
5. ADVANCED OPERATIONS
6. QUIT
PLEASE SELECT YOUR OPTION.
1
FIRST NUMBER?
5
SECOND NUMBER?
6abc
The result is 11.
It would be better if the input were rejected in both cases.
For this reason, instead of using scanf
, I recommend using the function fgets
to always read an entire line of input. After reading the input as a string, it can be converted to an integer using the function strtol
, and the rest of the string can be checked for input that does not belong there (such as "abc"
when the user enters "6abc"
). Instead of calling both of these functions every time you to read an integer from input, it would probably be better to create your own function which combines both function calls. Also, it would be good if that function would automatically reprompt the user for input, if the user input is invalid. In the second code snippet of this answer of mine to another question, I have created such a function, which I call get_int_from_user
.
If I replace all calls to scanf
with calls to the function get_int_from_user
, then the program will have the following behavior instead:
ADVANCED CALCULATOR VERSION 0.2
CALCULATOR OPTIONS ARE:
1. ADDITION
2. SUBTRACTION
3. MULTIPLICATION
4. DIVISION
5. ADVANCED OPERATIONS
6. QUIT
PLEASE SELECT YOUR OPTION.
1
FIRST NUMBER?
30 50
Unexpected input encountered!
FIRST NUMBER?
30
SECOND NUMBER?
50
The result is 80.
ADVANCED CALCULATOR VERSION 0.2
CALCULATOR OPTIONS ARE:
1. ADDITION
2. SUBTRACTION
3. MULTIPLICATION
4. DIVISION
5. ADVANCED OPERATIONS
6. QUIT
PLEASE SELECT YOUR OPTION.
1
FIRST NUMBER?
5
SECOND NUMBER?
6abc
Unexpected input encountered!
SECOND NUMBER?
6
The result is 11.
As you can see, the program no longer has the issues mentioned above.
Here is the full code of the program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
int get_int_from_user( const char *prompt );
void addition ( int left, int right )
{
printf( "The result is %d.\n", left + right );
}
void subtraction ( int left, int right )
{
printf( "The result is %d.\n", left - right );
}
void multiplication ( int left, int right )
{
printf( "The result is %d.\n", left * right );
}
void division ( int left, int right )
{
printf( "The result is %d.\n", left / right );
}
int main( void )
{
for (;;) //infinite loop
{
int option;
int left, right;
printf(
"ADVANCED CALCULATOR VERSION 0.2\n"
"CALCULATOR OPTIONS ARE:\n"
"1. ADDITION\n"
"2. SUBTRACTION\n"
"3. MULTIPLICATION\n"
"4. DIVISION\n"
"5. ADVANCED OPERATIONS\n"
"6. QUIT\n"
);
option = get_int_from_user( "PLEASE SELECT YOUR OPTION.\n" );
switch ( option )
{
case 1:
case 2:
case 3:
case 4:
left = get_int_from_user( "FIRST NUMBER?\n" );
right = get_int_from_user( "SECOND NUMBER?\n" );
switch ( option )
{
case 1:
addition( left, right );
break;
case 2:
subtraction( left, right );
break;
case 3:
multiplication( left, right );
break;
case 4:
division( left, right );
break;
}
break;
case 5:
printf( "Not yet implemented!\n" );
break;
case 6:
printf( "Quitting program as requested.\n" );
exit( EXIT_SUCCESS );
default:
printf( "Invalid input!\n" );
}
}
}
int get_int_from_user( const char *prompt )
{
//loop forever until user enters a valid number
for (;;)
{
char buffer[1024], *p;
long l;
//prompt user for input
fputs( prompt, stdout );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "Unrecoverable input error!\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "Line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "Unrecoverable error reading from input!\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//attempt to convert string to number
errno = 0;
l = strtol( buffer, &p, 10 );
if ( p == buffer )
{
printf( "Error converting string to number!\n" );
continue;
}
//make sure that number is representable as an "int"
if ( errno == ERANGE || l < INT_MIN || l > INT_MAX )
{
printf( "Number out of range error!\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfj23jlj" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return l;
continue_outer_loop:
continue;
}
}