Search code examples
cfgetsgetchar

fgets is getting skipped


I have little program where I want to ask for an option and then for a filename.

  //Some code before
   printf("######################\n");
   printf("# 1. Register a file #\n");
   printf("# 2. Get global list #\n");
   printf("# 3. Download a file #\n");
   printf("# 4. Quit / Exit     #\n");
   printf("######################\n");
   printf("Enter decision: ");
      fflush(stdin);
   action = getchar();
   action -= '0';
   sprintf(input, "[%d]--", action);
   switch (action)
   {
    case 1:
     printf("Enter file name: ");
        fflush(stdin);
     fgets(input+strlen(input), LINE_LEN, stdin);
     input[strlen(input)] = (input[strlen(input)] == '\n') ? 0 : input[strlen(input)];
     if(write(sock, input, sizeof(input)) == -1) perror("Clienthandler Write 3");
    break;
//some code after

The problem is that my fgets is getting skipped, even in gdb, gdb shows after the fgets for inspect input the value "\n\000]--" when action = 1

This is the console output:

######################
# 1. Register a file #
# 2. Get global list #
# 3. Download a file #
# 4. Quit / Exit     #
######################
Enter decision: 1
Enter file name: ######################
# 1. Register a file #
# 2. Get global list #
# 3. Download a file #
# 4. Quit / Exit     #
######################
Enter decision: ^C

Solution

  • fget() is not getting skipped but reads the left over new-line from the previous input using getchar().

    It is all about complete error checking and sane logging:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    
    #define LINE_LEN (1024)
    
    
    int main(void)
    {
      int action = 0;
      char input[LINE_LEN] = {0};
      size_t len = 0;
    
      printf("enter decision: ");
      {
        int c = fgetc(stdin); /* equivalent to getchar() */
        if (EOF == c)
        {
          putc('\n');
    
          if (ferror(stdin))
          {
            perror("fgetc(stdin) failed");
          }
          else
          {
            fprintf(stderr, "read EOF, aborting ...\n");
          }
    
          exit(EXIT_FAILURE);
        }
    
        action = c;
      }
    
      /* read left over from previous input: */
      {
        int c = fgetc(stdin);
        if (EOF == c)
        {
          putc('\n');
    
          if (ferror(stdin))
          {
            perror("fgetc(stdin) failed");
            exit(EXIT_FAILURE);
          }
        }
        else if ('\n' != c)
        {
          fprintf(stderr, "read unexpected input (%d), aborting ...\n", c);
          exit(EXIT_FAILURE);
        }
      }
    
      len = strlen(input);
      if (LINE_LEN <= len + 1) 
      {
        fprintf(stderr, "input buffer full, aborting ...\n");
        exit(EXIT_FAILURE);
      }
    
      switch(action - '0')
      {
        case 1:
          printf("enter file name: ");
          if (NULL == fgets(input + len, LINE_LEN - len, stdin))
          {
            putc('\n');
    
            if (ferror(stdin))
            {
              perror("fgets() failed");
            }
            else
            {
              fprintf(stderr, "missing input, aborting ...\n");
            }
    
            exit(EXIT_FAILURE);
          }
    
          (input + len)[strcspn(input + len, "\n")] = '\0'; /* cut off new-line, if any. */
    
          printf("read file name '%s'\n", input + len);
    
          break;
    
        default:
          fprintf(stderr, "unknown action (%d), aborting ...\n", action);
          exit(EXIT_FAILURE);
    
          break;
      }
    }