Function that prompts user for integer value and checks for valid input

前端 未结 5 1754
一个人的身影
一个人的身影 2020-12-20 09:07

I currently am stuck on a small part of an assignment I need to do. One requirement of the assignment is

\"Call a function that prompts the user for

相关标签:
5条回答
  • 2020-12-20 09:19

    My question is, how can I combine the first function with everything in the do/while loop to make one big function that I can call three times?

    Well, the function need not be big. The things to factor out are the prompt string and the variable to read - the latter can be left in the calling main() and assigned from a return value. Regarding how you would normally check the input, I recommend leaving this checking to scanf() and just test its return value.

    #include <stdio.h>
    #include <stdlib.h>
    
    int input(char *prompt)
    {   // prompts user to input integer
        // reads an integer from standard input and returns it
        int a, s;   // leave it to scanf to check the input:
        while (printf("%s", prompt), fflush(stdout), s = scanf("%d", &a), !s)
        {
            printf("INPUT ERROR!\n");
            do s = getchar(); while (s != '\n' && s != EOF);    // consume bad input
        }
        if (s == EOF) puts(""), exit(0);    // no more input
        return a;
    }
    

    In main() you can then just do

         a = input("Enter a value for a: ");
         b = input("Enter a value for b: ");
         c = input("Enter a value for c: ");
    

    (without a loop).

    0 讨论(0)
  • 2020-12-20 09:23

    I think the following code is you wanted:

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>  // for isalpha
    
    void InputAndCheck(int * pValue, const char * pName)
    {
        do
        {
            printf("Enter a value for %s: ", pName);
            scanf("%d", pValue);
            if (isalpha(*pValue))
            {
                printf("INPUT ERROR!\n");
                continue;
            }
            else
            {
                break;
            }
        } while (1);
    
        // clear the input buffer
        fflush(stdin);
        return;
    }
    
    int main()
    {
        int a, b, c;
        InputAndCheck(&a, "a");
        InputAndCheck(&b, "b");
        InputAndCheck(&c, "c");
        printf("a=%d;b=%d;c=%d;\r\n",a,b,c);
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-20 09:24

    scanf() already processes the input for you according to the format specifier (%d) so you just need to understand how scanf works and use it to check and build your function :)

    When you write scanf("%d", &a); the program expects you write an integer because of the %d specifier, and if an integer is read, the program writes it into variable a.

    But the function scanf also has a return value, ie, you can do check = scanf("%d", &a); and check will have a value of 0 or 1 in this case. This is because the return value records how many values have been successfuly read. If you entered dsfugnodg there's no number so it would return 0. If you entered 659 32 it would read the 1st value successfully and return 1.

    Your function would look something like:

    #include <stdio.h>
    
    int getAndPrint(char label)
    {
        int n = 0, val = 0;
        do {
            printf("Enter a value for %c: ", label);
            n = scanf("%d", &val);
            if (n == 0) {
                printf("Error, invalid value entered.\n");
                /* Consume whatever character leads the wrong input 
                 * to prevent an infinite loop. See: 
                 * https://stackoverflow.com/questions/1669821/scanf-skips-every-other-while-loop-in-c */
                getchar();
            }
        } while (n == 0);
        printf("%c = %d\n", label, val);
        return val;
    }
    
    int main()
    {
        int a, b, c;
        a = getAndPrint('a');
        b = getAndPrint('b');
        c = getAndPrint('c');
        printf("a=%d, b=%d, c=%d\n", a, b, c);
    }
    

    See also: Scanf skips every other while loop in C

    0 讨论(0)
  • 2020-12-20 09:25

    Function that prompts user for integer value and checks for valid input

    If users only entered valid integer text on a line-by-line basis, then code is easy:

    // Overly idealized case
    fputs(prompt, stdout);
    char buf[50];
    fgets(buf, sizeof buf, stdin);
    int i = atoi(buf);
    

    But users are good, bad and ugly and **it happens. If code wants to read a line, parse it for an in-range int, and detect a host of problems, below is code that vets many of the typical issues of bogus and hostile input.

    I especially interested in detecting overly long input as hostile and so invalid as a prudent design against hackers. As below, little reason to allow valid input for a 32-bit int with more than 20 characters. This rational deserve a deeper explanation.

    • End-of-file
    • Input stream error
    • Overflow
    • No leading numeric test
    • Trailing non-numeric text
    • Excessive long line

    First a line of input is read with fgets() and then various int validation tests applied. If fgets() did not read the whole line, the rest is then read.

    #include <limits.h>
    #include <ctype.h>
    
    // Max number of `char` to print an `int` is about log10(int_bit_width)
    // https://stackoverflow.com/a/44028031/2410359
    #define LOG10_2_N 28
    #define LOG10_2_D 93
    #define INT_DEC_TEXT (1 /*sign*/ + (CHAR_BIT*sizeof(int)-1)*LOG10_2_N/LOG10_2_D + 1)
    
    // Read a line and parse an integer
    // Return:
    //   1: Success
    //   0: Failure
    //   EOF: End-of-file or stream input error
    int my_get_int(int *i) {
      // Make room for twice the expected need. This allows for some
      // leading/trailing spaces, leading zeros, etc.
      //           int        \n  \0
      char buf[(INT_DEC_TEXT + 1 + 1) * 2];
      if (fgets(buf, sizeof buf, stdin) == NULL) {
        *i = 0;
        return EOF; // Input is either at end-of-file or a rare input error.
      }
      int success = 1;
    
      char *endptr;
      errno = 0;
      long value = strtol(buf, &endptr, 10);
    
    
      // When `int` is narrower than `long`, add these tests
    #if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
      if (value < INT_MIN) {
        value = INT_MIN;
        errno = ERANGE;
      } else if (value > INT_MAX) {
        value = INT_MAX;
        errno = ERANGE;
      }
    #endif
      *i = (int) value;
      if (errno == ERANGE) {
        success = 0;  // Overflow
      }
    
      if (buf == endptr) {
        success = 0; // No conversion
      }
    
      // Tolerate trailing white-space
      // Proper use of `is...()` obliges a `char` get converted to `unsigned char`.
      while (isspace((unsigned char ) *endptr)) {
        endptr++;
      }
    
      // Check for trailing non-white-space
      if (*endptr) {
        success = 0; // Extra junk
        while (*endptr) {  // quietly get rest of buffer
          endptr++;
        }
      }
    
      // Was the entire line read?
      // Was the null character at the buffer end and the prior wasn't \n?
      const size_t last_index = sizeof buf / sizeof buf[0] - 1;
      if (endptr == &buf[last_index] && buf[last_index - 1] != '\n') {
        // Input is hostile as it is excessively long.
        success = 0;  // Line too long
        // Consume text up to end-of-line
        int ch;
        while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
          ;
        }
      }
    
      return success;
    }
    

    Sample usage

         puts("Enter a value for a: ", stdout);
         fflush(stdout);  // Insure output is seen before input.
         int a;
         if (my_get_int(&a) == 1) {
           printf("a:%d\n", a); 
         }
    
    0 讨论(0)
  • 2020-12-20 09:36

    What you are looking for is an introduction to functions. Here is one : https://www.tutorialspoint.com/cprogramming/c_functions.htm

    This is a very important building block in programming and you should definitely learn to master that concept.

    functions will allow you to execute some code in different contexts over and over, just changing the context (the parameters).

    It is declared like this

    int add(int first, int second){
        //here we can use first and second
        printf("first: %d\n", first);
        printf("second: %d\n", second);
    
        //and eventually return a value
        return first+second;
    
    }
    

    Now when using we are reusing our previous code to excute a task which result will vary depending of the arguments we pass.

    printf("1+2 = %d\n", add(1, 2));
    -->3
    printf("2+2 = %d\n", add(2, 2));
    -->4
    

    Example solution for your task:

    //this will handle validation
    int validateInput(int input){
        if(isalpha(input)){
            printf("INPUT ERROR!\n");
            return 0;
        }
        return 1;
    }
    
    //this will prompt the user and return input only if the input is valid
    int askForCoefficient(unsigned char coefficientName){
        int valid = 0;
        int value = 0;
        while(!valid){
            printf("Enter a value for %c: ", coefficientName);
            value = scanf("%d", &value);
            valid = validateInput(value);
    
        }
    
        printf("%d\n", value);
    
        return value;
    
    }
    
    0 讨论(0)
提交回复
热议问题