How to test input is sane

后端 未结 6 1133
一个人的身影
一个人的身影 2020-12-11 11:38

Consider the following simple C program.

//C test

#include

int main()
{
   int a, b, c;

   printf(\"Enter two numbers to add\\n\");
   scan         


        
6条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-11 12:13

    User input is evil. Parse per:

    (optional whitespace)[decimal int][whitespace][decimal int](optional whitespace)
    

    strtol() and family have better error handling than scanf().
    Coda: Best to handle user input in a helper function. Break into 2 parts: I/O and parsing.

    #include 
    #include 
    #include 
    #include 
    #include 
    
    // return 1 (success), -1 (EOF/IOError) or 0 (conversion failure)
    int Readint(const char *prompt, int *dest, size_t n) {
      char buf[n * 21 * 2]; // big enough for `n` 64-bit int and then 2x
    
      fputs(prompt, stdout);  // do not use printf here to avoid UB
      fflush(stdout); // per @OP suggestion
      if (fgets(buf, sizeof buf, stdin) == NULL) {
        return -1;
      }
      const char *p = buf;
    
      while (n-- > 0) {
        char *endptr;
        errno = 0;
        long l = strtol(p, &endptr, 10);
        if (errno || (p == endptr) || (l < INT_MIN) || (l > INT_MAX)) {
          return 0;
        }
        *dest++ = (int) l;
        p = endptr;
      }
    
      // Trailing whitespace OK
      while (isspace((unsigned char) *p)) p++;
      // Still more text
      if (*p) return 0;
      return 1;
    }
    
    int main() {  // for testing
      int Result;
      do {
        int dest[2] = { -1 };
        Result = Readint("Enter two numbers to add\n", dest, 2);
        printf("%d %d %d\n", Result, dest[0], dest[1]);
      } while (Result >= 0);
      return 0;
    }
    

提交回复
热议问题