Home > front end >  How to get user to input number between 1-10 only
How to get user to input number between 1-10 only

Time:12-24

I'm writing a code that I want to make sure the User only inputs an integer between 1-10 and stores that value in a 2D array. I'm trying to use pointers to do complete this task.

#include <stdio.h>

int main()
{
    //Declaration of a 2D array
    int movie_Scores [8][5];
    //Declaration of a pointer variable which points to the address of the 1st element
    int *p;
    p=&movie_Scores;
    //Array of pointers to strings and initializtion
    char movie_Names[][100] =      {"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<5; i  )
    {
        printf("Judge %d, rate each movie from 1-10:\n\n", i 1);
        for(int j=0;j<8;j  )
        {
            printf("\n%s\t:", movie_Names[j]);
            scanf("%d", (p i (j*5)));

            while(*(p i (j*5))<1 || *(p i (j*5))>10)
            {
                printf("Enter number between 1-10:\n");
                printf("\n%s\t:", movie_Names[j]);
                scanf("%d", (p i (j*5)));
            }
        }
    }
}

Currently my code takes the input and directly stores it into the array without checking if the value entered is between 1-10.

CodePudding user response:

Input functions do not test for valid range. (In fact, that is a known failing of scanf. See here and here for the eyes-glaze-over reasons.) You need to test the value after you get it.

int value;
if (!scanf( "%d", &value )) fooey();
if ((value < 1) or (value > 10)) fooey();

Getting input in C is actually a rather obnoxious thing to do. You can write yourself a helper function to put all the messy stuff in one spot, then you can use it elsewhere.

Also, use better variable names, and don’t introduce gratuitous variables.

for(int judge_number=0; judge_number<5; judge_number  )
{
    printf("Judge %d, rate each movie from 1-10:\n", judge_number 1);
    for(int movie_number=0; movie_number<8; movie_number  )
    {
        int rating;
        for (;;)
        {
            printf("%s\t:", movie_Names[movie_number]);
            scanf("%d", &rating);
            if ((rating >= 1) and (rating <= 10)) break;
            printf("Rating must be an integer in 1 to 10.\n");
        }
        movie_Scores[movie_number][judge_number] = rating;
    }
}

EDIT: BTW, I would be remiss if I didn’t mention today’s magic numbers 5 and 8.

You should not use magic numbers. Instead, provide a named value somewhere.

#define NUMBER_OF_MOVIES 8
#define NUMBER_OF_JUDGES 5

Then you can use those identifiers anywhere you need them:

int movie_Scores [NUMBER_OF_MOVIES][NUMBER_OF_JUDGES];

And:

for (int judge_number=0;  judge_number<NUMBER_OF_JUDGES;  judge_number  )

Et cetera.

CodePudding user response:

First, I'd write a function that reads an int and checks it against an input, returning 1 if an acceptable int was read, and 0 if one was not.

int read_int_from_range(int *n, int start, int end) {
    int r = scanf("%d", n);

    return r == 1 && *n >= start && *n <= end;
}

Now, you can call this and check it and use that to loop until you get "valid" input in another function if you want, or simply exit with an error message if that's the desired behavior.

CodePudding user response:

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.

CodePudding user response:

As far as I know, the only option is to simply use scanf. If the number is less than 1 or more than 10, you can print something like "Please enter a number from 1 to 10. and use scanf again until you get a number between 1 and 10.

  •  Tags:  
  • c
  • Related