Thread: flushing stdin

  1. #1
    Registered User
    Join Date
    Apr 2006
    Posts
    31

    flushing stdin

    In the faq, there is a section saying that it is unsafe to fflush(stdin) (it doesn't work correctly anyway). I'm having a problem with a function and an infinate loop with switch statement where the stream has not been cleared and outputs unwanted printf data instead of pausing to read scanf. Here's a snippet:
    This is the call to the function in question from main:
    Code:
     case '4': getroom3: {
                                                      printf("Check occupant into what room? 1 - 10: ");
                                                      scanf("%d", &roomnum);
                                                      if (roomnum < 1 || roomnum > 10) {
                                                              printf("1 - 10 only!");
                                                              goto getroom3;
                                                      }
                                              }
                                              if ((addguest(roomnum)) < 0)
                                                      printf("The room is occupied\n");
                                              else
                                                      printf("The guest was added\n");
                                              break;
    This is just the call in a switch statement.
    Here is the definition to addguest:
    Code:
    #include "hotel.h"
    #include <unistd.h>
    #include <sys/types.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    
    int fd;
    char buf[NLINES];
    
    void fillbuf();
    
    int
    addguest(int roomnum)
    {
            off_t offset;
            ssize_t nread;
            int i;
    
            offset = (roomnum - 1) * NLINES;
    
            if (lseek(fd, offset, SEEK_SET) < 0)
                    perror("problem with lseek in addguest: line 24\n");
    
            if ( (nread = read(fd, buf, sizeof(buf))) < 0)
                    perror("problem with read in addguest: line 27\n");
    
            for (i = 0; i < nread; ++i) {
                    if (isalpha(buf[i]))
                            return -1;
            }
    
            fillbuf();
    
            if (lseek(fd, offset, SEEK_SET) < 0)
                    perror("problem with lseek in addguest: line 24\n");
            if (write(fd, buf, sizeof(buf)) < 0)
                    perror("problem with write in addguest function: line 36\n");
    
        return 1;
    }
    
    void
    fillbuf()
    {
        char *lname, *fname;
        int i;
    
        lname = malloc(22);
        fname = malloc(18);
    
        memset(lname, ' ', sizeof(lname));
        memset(fname, ' ', sizeof(fname));
        memset(buf, ' ', sizeof(buf));
    
        lastname: {
            fflush(stdin);           /* [red]had this as fflus(NULL) but didn't work[/red] */
            printf("Enter last name. Do not exceed 19 chars: ");
            fgets(lname, (sizeof(lname) - 3), stdin);
        }
    
        /* check for newline */
    
        for (i = 0; i < sizeof(lname); ++i) {
            if (isalpha(lname[i]))
                continue;
            else if (lname[i] == '\0')
                break;
            else if (lname[i] == '\n') {
                lname[i] = '\0';
                break;
            } else {
                printf("There was an error in your input, try again:\n");
                goto lastname;
            }
        }
       memcpy(buf, lname, strlen(lname));
    
        /* tac on ", " to lname */
    
        buf[strlen(buf)] = ',';
        buf[strlen(buf) + 1] = ' ';
        buf[strlen(buf) + 2] = '\0';
    
    
        firstname: {
            fflush(stdin);           /*[red]again tried fflush(NULL) per man page on fflush[/red]*/
            printf("Enter first name. Do not exceed 17 chars: ");
            fgets(fname, (sizeof(fname) - 1), stdin);
        }
    
        /* check for newline again */
    
        for (i = 0; i < sizeof(fname); ++i) {
            if (isalpha(fname[i]))
                continue;
            else if (lname[i] == '\0')
                break;
            else if (lname[i] == '\n') {
                lname[i] = '\0';
                break;
            } else {
                printf("There was an error in your input, try again:\n");
        /*      goto firstname; */
            }
        }
    
        strncat(buf, fname, strlen(fname));
    
        return;
    }
    Here's a trial run:
    1: Print a list of the rooms:
    2: Retrieve an occupier:
    3: Free a room
    4: Add a guest:
    5: Find a free room
    Enter a number 1 - 5: 4
    Check occupant into what room? 1 - 10: 1
    Enter last name. Do not exceed 19 chars: There was an error in your input, try again:
    There was an error in your input, try again:
    There was an error in your input, try again:
    There was an error in your input, try again:
    Enter first name. Do not exceed 17 chars: There was an error in your input, try again:
    There was an error in your input, try again:
    There was an error in your input, try again:
    There was an error in your input, try again:
    The guest was added
    1: Print a list of the rooms:
    2: Retrieve an occupier:
    3: Free a room
    4: Add a guest:
    5: Find a free room
    Enter a number 1 - 5:
    ----------------------------
    Maybe writing the data to /dev/null would help? How would I do that if that would be a solution?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > memset(lname, ' ', sizeof(lname));
    sizeof() on a pointer does NOT tell you how much memory you're pointing at.

    > fgets(fname, (sizeof(fname) - 1), stdin);
    Ditto.

    And in several other places as well.


    > fflush(stdin);
    If you use fgets() for EVERY bit of input, then the need to flush input pretty much goes away.

    char buff[BUFSIZ];
    fgets( buff, BUFSIZ, stdin );
    Then validate buff in whatever way you choose, and copy the data to it's final destination.

    > /* tac on ", " to lname */
    Use strcat then!

    > buf[strlen(buf)] = ',';
    Oops, I just overwrote the \0, I really hope the next character is a \0 as well otherwise the following strlen() is lost.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Flushing buffer
    By $l4xklynx in forum C Programming
    Replies: 6
    Last Post: 03-04-2009, 10:07 PM
  2. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  3. flushing stdin
    By crash88 in forum C Programming
    Replies: 2
    Last Post: 06-29-2006, 08:55 PM
  4. flushing stdin
    By crash88 in forum C Programming
    Replies: 2
    Last Post: 06-29-2006, 02:23 PM
  5. stdin question
    By oomen3 in forum C Programming
    Replies: 6
    Last Post: 02-19-2003, 02:52 PM