The problem of how to verify that the user actually entered an integer has already been answered in this question:
Validate the type of input in a do-while loop C
Therefore, the question remains how to verify that the integer that the user entered is also in the range 1
to 10
.
In order to do this, all you need is an if
statement. However, if you want the user to be automatically re-prompted for input, then you will also need a loop.
In my solution below, I use the function get_int_from_user
from my solution to the question mentioned above, with a slight modification, so that it accepts printf
-style input. This function automatically verifies that the user entered a valid integer, and if not, it automatically reprompts the user for input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#include <stdarg.h>
#define NUM_JUDGES 3
#define NUM_MOVIES 8
int get_int_from_user( const char *prompt, ... );
int main( void )
{
//Declaration of a 2D array
int movie_scores[NUM_JUDGES][NUM_MOVIES];
//Array of pointers to strings and initializtion
char *movie_names[] = {
"1. <Movie 1>",
"2. <Movie 2>",
"3. <Movie 3>",
"4. <Movie 4>",
"5. <Movie 5>",
"6. <Movie 6>",
"7. <Movie 7>",
"8. <Movie 8>"
};
for( int i = 0; i < NUM_JUDGES; i++ )
{
printf( "Judge %d, rate each movie from 1-10:\n\n", i+1 );
for( int j = 0; j < NUM_MOVIES; j++ )
{
//repeat until the input is in the range 0 to 10
for (;;)
{
int score;
score = get_int_from_user( "%s: ", movie_names[j] );
if ( 0 <= score && score <= 10 )
{
//score is good, so write it to the 2D array and
//break out of the loop
movie_scores[i][j] = score;
break;
}
printf( "Error: The score must be in the range 0 to 10!\n" );
}
}
printf( "\n" );
}
//input is complete, so now it is time to print back the data to the user
printf( "\nThe following data was entered:\n\n" );
for ( int i = 0; i < NUM_JUDGES; i++ )
{
printf( "Judge %d: ", i+1 );
for ( int j = 0; j < NUM_MOVIES; j++ )
{
printf( "%d ", movie_scores[i][j] );
}
printf( "\n" );
}
}
int get_int_from_user( const char *prompt, ... )
{
//loop forever until user enters a valid number
for (;;)
{
char buffer[1024], *p;
long l;
va_list vl;
//prompt user for input
va_start( vl, prompt );
vprintf( prompt, vl );
va_end( vl );
//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;
}
}
This program has the following behavior:
Judge 1, rate each movie from 1-10:
1. <Movie 1>: abc
Error converting string to number!
1. <Movie 1>: 4abc
Unexpected input encountered!
1. <Movie 1>: 12
Error: The score must be in the range 0 to 10!
1. <Movie 1>: 1
2. <Movie 2>: 2
3. <Movie 3>: 3
4. <Movie 4>: 4
5. <Movie 5>: 5
6. <Movie 6>: 6
7. <Movie 7>: 7
8. <Movie 8>: 8
Judge 2, rate each movie from 1-10:
1. <Movie 1>: 8
2. <Movie 2>: 7
3. <Movie 3>: 6
4. <Movie 4>: 5
5. <Movie 5>: 4
6. <Movie 6>: 3
7. <Movie 7>: 2
8. <Movie 8>: 1
Judge 3, rate each movie from 1-10:
1. <Movie 1>: 10
2. <Movie 2>: 10
3. <Movie 3>: 10
4. <Movie 4>: 10
5. <Movie 5>: 10
6. <Movie 6>: 10
7. <Movie 7>: 10
8. <Movie 8>: 10
The following data was entered:
Judge 1: 1 2 3 4 5 6 7 8
Judge 2: 8 7 6 5 4 3 2 1
Judge 3: 10 10 10 10 10 10 10 10
Note that for demonstration purposes, I have reduced NUM_JUDGES
form 5
to 3
.