Thread: Code review: Bulletproof input

  1. #1
    Open to suggestions Brighteyes's Avatar
    Join Date
    Mar 2003
    Posts
    204

    Code review: Bulletproof input

    I was fooling around with scanf and fgets and came up with this. I think both are as solid as they can get but I'm not 100% sure. Could anyone comment on any problems that they may have or how to improve on them? What I'm going for is foolproof user input.

    In the code, rc is defined as an int, buf as a char array with 11 elements, and warn looks like this
    Code:
    void warn(char *msg)
    {
        fprintf(stderr, "Warning: %s\n", msg);
    }
    Ina real program I would switch warn with die as appropriate
    Code:
    void die(char *msg)
    {
        fprintf(stderr, "Fatal error: %s\n", msg);
        exit(EXIT_FAILURE);
    }
    First is the scanf method
    Code:
    rc = scanf("%10[^\n]", buf);
    if (rc == EOF)
    {
        if (feof(stdin))
            warn("End of file reached...");
        if (ferror(stdin))
            warn("I/O error occurred...");
    }
    else if (rc < 1)
        warn("Incorrect input format or no input...");
    
    if (rc >= 0)
    {
        int n;
    
        scanf("%*[^\n]%n", &n);
        getchar();
    
        /* For debugging only */
        printf("Extraneous characters: %d\n", n);
    }
    And the fgets method
    Code:
    if (fgets(buf, sizeof (buf), stdin) != NULL)
    {
        char *newline;
    
        if (buf[0] == '\n')
            warn("No input processed...");
    
        newline = strrchr(buf, '\n');
        if (newline != NULL)
            *newline = '\0';
        else
        {
            int n;
    
            scanf("%*[^\n]%n", &n);
            getchar();
    
            /* For debugging only */
            printf("Extraneous characters: %d\n", n);
        }
    }
    else
    {
        if (feof(stdin))
            warn("End of file reached...");
        if (ferror(stdin))
            warn("I/O error occurred...");
    }
    In a real program I'd also either wrap these up in their own functions to make getting a line simpler, or at the very least wrap the error checking into their own functions
    Code:
    void garbage(FILE *in)
    {
        int n;
    
        fscanf(in, "%*[^\n]%n", &n);
        getchar();
    
        /* For debugging only */
        printf("Extraneous characters: %d\n", n);
    }
    
    void ioerror(FILE *in)
    {
        if (feof(in))
            warn("End of file reached...");
        if (ferror(in))
            warn("I/O error occurred...");
    }
    Or something like that.

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    With regard to packaging the scanf version into a function, you might need to build the format string for a variable size. The following is an adaptation of some code I found in The Practice of Programming by Brian Kernighan and Rob Pike.
    Code:
    #include <stdio.h>
    
    int foo(char *buffer, size_t size)
    {
       char fmt[20];
       sprintf(fmt, "%%%lu[^\n]", (long unsigned)(size - 1));
       return scanf(fmt, buffer);
    }
    
    int main(void)
    {
       char buf[11];
       int rc = foo(buf, sizeof(buf));
       printf("buf = \"%s\"\n", buf);
       return 0;
    }
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  2. can someone help me with these errors please code included
    By geekrockergal in forum C Programming
    Replies: 7
    Last Post: 02-10-2009, 02:20 PM
  3. Need some help with C program writing
    By The_PC_Gamer in forum C Programming
    Replies: 9
    Last Post: 02-12-2008, 09:12 PM
  4. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM