In my opinion, the best solution to your stated problem would be to replace break
with return 1;
, so that it exits the function. If you #include <stdlib.h>
, then you can also use return EXIT_FAILURE;
instead, which is easier to read.
However, in cases in which you do not want to exit the function (for example because you want the rest of the function to be executed), then I would recommend that you restructure your loop to an infinite loop with explicit break
statements for all possible cases in which the loop should end. That way, you can move the if
...else
inside the loop:
for (;;) //infinite loop, equivalent to while(true)
{
if ( height <= 0 )
{
if ( velocity >= -2.0 )
{
printf( "You landed successfully.\n" );
}
else
{
printf( "Failed! You crashed!\n" );
}
break;
}
if ( throttle >= 0 && throttle <= 100 )
{
[...]
}
else
{
printf( "Please choose a number between 0 and 100!\n" );
break;
}
}
However, I do not think that your stated problem is your actual problem. When the user enters invalid input, you probably do not want to exit the function (or even the entire program). Instead, it would make more sense to reprompt the user for valid input, when the input is invalid. In order to determine whether the input is invalid or not, you should not only check whether throttle
is in the desired range, but also whether the user entered an integer in the first place (i.e. make sure that the user didn't enter something that could not be converted to an integer).
For the reasons stated in this answer of mine to another question, I do not recommend that you use scanf
for line-based user input. For determining whether the user entered a valid integer, it is usually better to use the function fgets
to read exactly one line of user input as a string, and then to attempt to convert the string to an integer using the function strtol
. These two function calls can be combined into a single function, which automatically reprompts the user if he did not enter a valid integer. In my linked answer, I created such a function called get_int_from_user
.
After making the changes mentioned above, your code would look like this:
for (;;) //infinite loop, equivalent to while(true)
{
printf( "T: %d H: %.1f V: %.1f F: %.1f\n", time, height, velocity, fuel );
if ( height <= 0 )
{
if ( velocity >= -2.0 )
{
printf( "You landed successfully.\n" );
}
else
{
printf( "Failed! You crashed!\n" );
}
break;
}
//repeat until user entered a valid integer in the
//range 0 - 100
for (;;)
{
throttle = get_int_from_user( "Enter throttle (0-100): " );
if ( throttle < 0 || throttle > 100 )
{
printf( "Please choose a number between 0 and 100!\n" );
continue;
}
//input is ok
break;
}
//do physics calculations (copied from the question)
height = heightTemp + velocityTemp - (throttle * K-G) / 2;
velocity = velocityTemp + (throttle * K-G);
fuel = fuelTemp - throttle;
time = time + 1;
heightTemp = height;
velocityTemp = velocity;
fuelTemp = fuel;
}
Here is the full code of a test 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 );
int main( void )
{
int time = 0, throttle;
double height = 100.0, velocity = -5.0;
for (;;) //infinite loop, equivalent to while(true)
{
printf( "T: %d H: %.1f V: %.1f\n", time, height, velocity );
if ( height <= 0 )
{
if ( velocity >= -2.0 )
{
printf( "You landed successfully.\n" );
}
else
{
printf( "Failed! You crashed!\n" );
}
break;
}
//repeat until user entered a valid integer in the
//range 0 - 100
for (;;)
{
throttle = get_int_from_user( "Enter throttle (0-100): " );
if ( throttle < 0 || throttle > 100 )
{
printf( "Please choose a number between 0 and 100!\n" );
continue;
}
//input is ok
break;
}
//do physics calculations
velocity += throttle / 100.0;
velocity -= 0.5; //gravity
height += velocity;
time++;
}
}
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;
}
}
Since the physics calculations that you posted do not compile, I have added my own (simple) physics calculations.
This program has the following output:
T: 0 H: 100.0 V: -5.0
Enter throttle (0-100): hh7
Error converting string to number!
Enter throttle (0-100): test
Error converting string to number!
Enter throttle (0-100): 6abc
Unexpected input encountered!
Enter throttle (0-100): 200
Please choose a number between 0 and 100!
Enter throttle (0-100): -30
Please choose a number between 0 and 100!
Enter throttle (0-100): 5
T: 1 H: 94.5 V: -5.5
Enter throttle (0-100): 10
T: 2 H: 88.7 V: -5.9
Enter throttle (0-100): 15
T: 3 H: 82.5 V: -6.2
Enter throttle (0-100): 20
T: 4 H: 76.0 V: -6.5
Enter throttle (0-100): 25
T: 5 H: 69.2 V: -6.8
Enter throttle (0-100): 35
T: 6 H: 62.4 V: -6.9
Enter throttle (0-100): 45
T: 7 H: 55.4 V: -7.0
Enter throttle (0-100): 55
T: 8 H: 48.5 V: -6.9
Enter throttle (0-100): 65
T: 9 H: 41.8 V: -6.8
Enter throttle (0-100): 80
T: 10 H: 35.3 V: -6.5
Enter throttle (0-100): 100
T: 11 H: 29.3 V: -6.0
Enter throttle (0-100): 100
T: 12 H: 23.9 V: -5.5
Enter throttle (0-100): 100
T: 13 H: 18.9 V: -5.0
Enter throttle (0-100): 100
T: 14 H: 14.5 V: -4.5
Enter throttle (0-100): 100
T: 15 H: 10.6 V: -4.0
Enter throttle (0-100): 100
T: 16 H: 7.1 V: -3.5
Enter throttle (0-100): 100
T: 17 H: 4.2 V: -3.0
Enter throttle (0-100): 100
T: 18 H: 1.7 V: -2.5
Enter throttle (0-100): 100
T: 19 H: -0.2 V: -2.0
You landed successfully.