1
#define len 100

char sourceString[len];
char command;

int main(void)
{
    while (1)
    {   
        printf("\nEnter source: ");
        fgets(sourceString, len, stdin); // this gets skipped on second loop.

        printf("\nEnter command: ");
        scanf(" %c", command) 

        switch (command)
        {
        case 'A':
            printf("%s", sourceString);
            break;

        case 'B':
            printf("filler");
            break;

        default:
            break;
        }
    }

    return 0;
}

Whether im using fgets or scanf the string always gets skipped on the second loop. I tried adding a space to the second scanf " %c" but it still skips the string input, yes im trying to read a line and then a character.

eryet
  • 19
  • 2
  • `fgets` is consuming the newline character, so your `scanf` is definitely not needed (if not harmful - as it is used incorrectly). It is not even clear what you are trying to do here. Read a line and then a character? Or what? – Eugene Sh. Mar 20 '20 at 19:21
  • " It is not even clear what you are trying to do here. Read a line and then a character?" yes thats what im trying to do. – eryet Mar 20 '20 at 19:25
  • Well, mixing input methods is a bad idea in general. Use `fgetc` instead of `scanf`. – Eugene Sh. Mar 20 '20 at 19:25
  • Use `fgets()` for both and just derefernce the array holding `command` to get the first character -- ensures a complete line is read. – David C. Rankin Mar 20 '20 at 19:29

4 Answers4

1

After the call of scanf insert the following calls

    scanf( "%*[^\n]" );
    scanf( "%*c" );

to remove the new line character '\n' from the input buffer.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Here are the steps that explain the observed behavior:

  • printf("\nEnter source: "); : the prompt is printed.
  • fgets(sourceString, len, stdin); an input line is read, you should test the return value to ensure fgets() succeeded.
  • printf("\nEnter command: "); a line is skipped and a new prompt is output.
  • scanf(" %c", command) any initial white space is skipped (including pending newlines) and a single character is read. Note however that the user must type enter for this character to be made available to the program because the terminal is most likely in cooked mode, ie: line buffered. Also note that you must pass the address of charvariable command or undefined behavior will ensue.
  • the switch selects what gets done and the loop skips to the next iteration
  • printf("\nEnter source: "); : the prompt is printed.
  • fgets(sourceString, len, stdin); fgets() returns immediately with an empty line because the newline typed above is still pending in the input buffer. This is the problem.

You can fix this behavior by discarding the rest of the pending line after the character is read with:

scanf("%*[^\n]");   // read any characters except newline
scanf("%*1[\n]");   // read at most 1 newline character

You must use 2 separate calls to scanf() because the first conversion would fail if there are no characters before the newline.

#incude <stdio.h>

#define LEN 100

int main(void) {
    char sourceString[LEN];
    char command;

    for (;;) {
        printf("\nEnter source: ");
        if (!fgets(sourceString, len, stdin))
            break;

        printf("\nEnter command: ");
        /* read a single non blank character and discard the rest of the line */
        if (scanf(" %c%*[^\n]", &command) != 1)
            break;

        /* discard the pending newline if any */
        scanf("%*1[\n]");  // of just getchar()

        switch (command) {
          case 'A':
            printf("%s", sourceString);
            break;

          case 'B':
            printf("filler");
            break;

          default:
            break;
        }
    }
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
0

Use fgets() for both and just derefernce the array holding command to get the first character -- ensures a complete line is read.

Your problem is scanf() is leaving the '\n' in your input stream which on your next iteration is taken by fgets() (since fgets() reads up to and including the next '\n' in the input stream). This makes it appear like fgets() was skipped -- it wasn't it just read the '\n' left by scanf().

#define len 100

int main(void)
{
    char sourceString[len];    /* don't use global variables */
    char command[len];

    while (1)
    {   
        printf ("\nEnter source: ");
        fgets (sourceString, len, stdin); // this no longer skipped in loop.

        printf("\nEnter command: ");
        fgets (command, len, stdin); 

        switch (*command)
        {
        case 'A':
            printf("%s", sourceString);
            break;

        case 'B':
            printf("filler");
            break;

        default:
            break;
        }
    }

    return 0;
}

(note: you must always check the return of EVERY input function call -- that is left to you. See Henry Spencer's 10 Commandments for C Programmers - No. 6 "Ye be warned...")

Let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

The problem is that the fgets() function in the second loop captures '\n', which is when you press enter after you type input to the scanf() of the first loop. There is a solution to overcome this problem which is to add a getchar() function after scanf() so that it captures the '\n' instead of the fgets() of the second loop and the following loops. Here is a sample program :

while (1)
{
    printf("\nEnter source: ");
    fgets(sourceString, len, stdin); 

    printf("\nEnter command: ");
    scanf(" %c", &command);
    getchar();

    /* Rest of the program would follow */

}
notopython
  • 55
  • 5
  • Fails if more than 1-character typed for `command` (e.g. `"Apples"`, or a slip of a finger reaching for `'A'`, e.g. `"Aq"`) You can do `for (int c = getchar(); c != '\n' && c != EOF; c = getchar()) {}` – David C. Rankin Mar 20 '20 at 19:49
  • Also should test for `fgets()` null return value. – chqrlie Mar 20 '20 at 19:51
  • @DavidC.Rankin Well that's true, but if the scanf() should take one character only I think it will work fine. – notopython Mar 20 '20 at 20:34
  • Yes, that is the whole problem -- `scanf()` will take 1-character only. So, if more than 1-character is accidentally typed, all other characters remains in the input-buffer unread just wating to bite you on your next attempting input. That's why the loop to empty the input stream up to the next `'\n'` is recommended. – David C. Rankin Mar 20 '20 at 21:26