I want to loop back to the main function in my program but I can't simply call it again in another function due to main being undeclared in the part of the code where the other functions are, is there a way I can fix this?
#include <stdio.h>
#include <conio.h>
#include <cbm.h>
int integer1;
int integer2;
int integer3;
int option;
char choice;
void addition (){
integer3 = integer1 integer2;
printf("%d\n", integer3);
integer1 = 0;
integer2 = 0;
integer3 = 0;
main();
}
void subtraction (){
integer3 = integer1 - integer2;
printf("%d\n", integer3);
integer1 = 0;
integer2 = 0;
integer3 = 0;
main();
}
void multiplication (){
integer3 = integer1 * integer2;
printf("%d\n", integer3);
integer1 = 0;
integer2 = 0;
integer3 = 0;
main();
}
void division (){
integer3 = integer1 / integer2;
printf("%d\n", integer3);
integer1 = 0;
integer2 = 0;
integer3 = 0;
main();
}
int main()
{
printf("ADVANCED CALCULATOR VERSION 0.2\n");
printf("CALCULATOR OPTIONS ARE:\n");
printf("1. ADDITION\n");
printf("2. SUBTRACTION\n");
printf("3. MULTIPLICATION\n");
printf("4. DIVISION\n");
printf("5. ADVANCED OPERATIONS\n");
printf("PLEASE SELECT YOUR OPTION.\n");
scanf("%d", &option);
if (option == 1){
printf("FIRST NUMBER?\n");
scanf("%d", &integer1);
printf("SECOND NUMBER?\n");
scanf("%d", &integer2);
addition();
}
else if (option == 2){
printf("FIRST NUMBER?\n");
scanf("%d", &integer1);
printf("SECOND NUMBER?\n");
scanf("%d", &integer2);
subtraction();
}
else if (option == 3){
printf("FIRST NUMBER?\n");
scanf("%d", &integer1);
printf("SECOND NUMBER?\n");
scanf("%d", &integer2);
multiplication();
}
else if (option == 4){
printf("FIRST NUMBER?\n");
scanf("%d", &integer1);
printf("SECOND NUMBER?\n");
scanf("%d", &integer2);
division();
}
else {
printf("Bruh");
//exit();
}
}
I have tried to solve this issue on my own but I could not really find anything good (and possibly understand anything I found since I'm new to C). I would put the main statement first but then that would just cause the other functions to not be declared. Any advice would help, thanks!
CodePudding user response:
Use a while loop
Put a while loop in your main
int main()
{
while(true)
{
...
}
return 0;
)
and remove the calls to main()
CodePudding user response:
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;
}
}
CodePudding user response:
Kudos to you. You are obviously working very hard at this problem.
The following is offered as a less repetitious version of your code. I hope this helps make you a better programmer. This is a 'partially condensed' version of what you have written.
Notice the two comments in the following code referring to "infinite loop" that will 'restart' execution at the top of the loop.
Keep at it!
#include <stdio.h>
#include <conio.h>
#include <cbm.h>
int integer1;
int integer2;
int option;
void get2nums() {
printf( "FIRST NUMBER?\n" );
scanf( "%d", &integer1);
printf( "SECOND NUMBER?\n");
scanf( "%d", &integer2);
}
void addition() {
get2nums();
printf( "%d\n", integer1 integer2 );
}
void subtraction() {
get2nums();
printf( "%d\n", integer1 - integer2 );
}
void multiplication() {
get2nums();
printf( "%d\n", integer1 * integer2 );
}
void division() {
get2nums();
if( integer2 == 0 )
printf( "Div by 0 undefined\n" );
else
printf( "%d with %d remainder\n", integer1 / integer2, integer1 % integer2 );
}
int main() {
// for( ;; ) { // uncomment this line and below for infinite looping
printf("ADVANCED CALCULATOR VERSION 0.2\n");
printf("CALCULATOR OPTIONS ARE:\n");
printf("1. ADDITION\n");
printf("2. SUBTRACTION\n");
printf("3. MULTIPLICATION\n");
printf("4. DIVISION\n");
// printf("5. ADVANCED OPERATIONS\n"); // TODO
printf("PLEASE SELECT YOUR OPTION.\n");
scanf( "%d", &option );
if( option == 1 )
addition();
else if( option == 2 )
subtraction();
else if( option == 3 )
multiplication();
else if( option == 4 )
division();
else
printf( "Bruh" );
// } // uncomment this line for infinite looping
return 0;
}
As some rather 'undocumented but advanced' lines of code have been proposed, I offer this to the student for careful study. It contains some elements that you won't encounter until the later chapters of the textbook. But, it's been fun for an hour.
#include <stdio.h>
#include <stdlib.h>
typedef void(*func_t)(int,int);
void stdOut( char op, int res, int i1, int i2 ) {
printf( "\n%d %c %d = %d%c", i1, op, i2, res, "\n "[op=='/'] );
}
void add( int i2, int i1 ) { stdOut( ' ', i1 i2, i1, i2 ); }
void sub( int i2, int i1 ) { stdOut( '-', i1 - i2, i1, i2 ); }
void mul( int i2, int i1 ) { stdOut( '*', i1 * i2, i1, i2 ); }
void dvd( int i2, int i1 ) {
if( i2 == 0 ) { printf( "Div by 0 undefined\n" ); return; }
stdOut( '/', i1 / i2, i1, i2 );
printf( "with %d remainder\n", i1 % i2 );
}
int getInt( char *prompt ) {
char buf[64]; // sufficient
printf( "%s", prompt );
fgets( buf, sizeof buf, stdin );
return atoi( buf );
}
void get2nums( func_t f ) { f( getInt( "SECOND NUMBER: " ), getInt( "FIRST NUMBER: ") ); }
int main() {
func_t f[] = { &add, &sub, &mul, &dvd, };
printf("ADVANCED CALCULATOR VERSION 0.2");
top:
printf(
"\nCALCULATOR OPTIONS ARE:\n"
"0. Quit\n"
"1. ADDITION\n" "2. SUBTRACTION\n"
"3. MULTIPLICATION\n" "4. DIVISION\n"
// "5. ADVANCED OPERATIONS\n" // TODO
);
int opt = getInt( "PLEASE SELECT YOUR OPTION: " );
switch( opt ) {
case 0: printf( "\nBye-bye\n" ); return 0;
case 1:
case 2:
case 3:
case 4: get2nums( f[ opt - 1 ] ); break;
default:
printf( "\nBruh\n\n" );
}
goto top;
return 0;
}
Output:
ADVANCED CALCULATOR VERSION 0.2
CALCULATOR OPTIONS ARE:
0. Quit
1. ADDITION
2. SUBTRACTION
3. MULTIPLICATION
4. DIVISION
PLEASE SELECT YOUR OPTION: 3
FIRST NUMBER: 42
SECOND NUMBER: 54
42 * 54 = 2268
CALCULATOR OPTIONS ARE:
0. Quit
1. ADDITION
2. SUBTRACTION
3. MULTIPLICATION
4. DIVISION
PLEASE SELECT YOUR OPTION: 4
FIRST NUMBER: 8
SECOND NUMBER: 3
8 / 3 = 2 with 2 remainder
CALCULATOR OPTIONS ARE:
0. Quit
1. ADDITION
2. SUBTRACTION
3. MULTIPLICATION
4. DIVISION
PLEASE SELECT YOUR OPTION: 0
Bye-bye