Search code examples
cstringstdinfgets

How do I use multiple fgets without them interfering with each other?


Here's the basic skeleton of my code:

int getSentence(SearchResults* input){
    printf("Enter sentence:");
    fgets(input->sentence, 100, stdin);

    printf("Enter message ID:");
    fgets(input->messageID, 20, stdin);
    
    return 1;
}

As is, this has a couple of problems. One is that when I print the string later, they have a newline character at the end, which I don't want. The other is that if I enter more than the 100 or 20 characters, it will overflow those characters into the next fgets call.

I've found "solutions" online, but they all either introduce new problems, or are recommended against using. Most of what I found is summarized in this SO post: How to properly flush stdin in fgets loop.

  1. fflush works for the second problem, but is apparently "problematic".
  2. I came up with *(strstr(input->sentence, "\n")) = '\0'; for the first issue, but it doesn't help with the second
  3. while ((getchar()) != '\n')(and variations) is a commonly recommended solution for both problems, but it introduces a new issue: my next input requires two enters before the program will continue running. I tried adding fputc('\n', stdin); after the while loop and it solves all three problems, but only when the input exceeds the character limit. If I write a sentence less than 100 chars, I have to hit enter twice for the program to continue.
  4. setbuf(stdin, NULL) is one of the solutions given, but one of the comments says "mucking around with setbuf is even worse [than fflush]"

Solution

  • Here's what I'm using to solve my issue, thanks to Steve Summit and Andreas Wenzel for their comments.

    int getSentence(SearchResults* input){
        printf("Enter sentence:");
        fgets(input->sentence, 100, stdin);
        int temp = strcspn(input->sentence, "\n");
        if(temp < 100 - 1) input->sentence[temp] = '\0';
        else while ((temp = getchar()) != '\n' && temp != EOF);
    
        printf("Enter message ID:");
        fgets(input->messageID, 20, stdin);
        temp = strcspn(input->messageID, "\n");
        if(temp < 20 - 1) input->messageID[temp] = '\0';
        else while ((temp = getchar()) != '\n' && temp != EOF);
    
        return 1;
    }
    

    EDIT: For anyone else who has the same issue as me, see comments below for additional problems you may need to account for if you use this solution, such as fgets returning NULL.