1

The purpose of the code is to see how the strings are stored (whether it ends with \n or \0).

void print(char*);

int main(void) {

    //fscanf block
    char *ss;
    ss = malloc(sizeof(char)*100);
    printf("String for fscanf: ");
    fscanf(stdin, "%s", ss);
    printf("For fscanf:\n");
    print(ss);

    //fgets block
    char *gs;
    gs = malloc(sizeof(char)*100);
    printf("String for fgets: ");
    fgets(gs, 10, stdin);
    printf("For fgets:\n");
    print(gs);

    free(ss);
    free(gs); 
}

void print(char* str) {
    int done = 0;
    for (int i=0; i<100; i++){
        if (done == 3) {
            break;
        }
        if (str[i] == '\0') {
            printf("Zero: %d\n", i);
            done++;
        }
        if (str[i] == '\n') {
            printf("Return: %d\n", i);
            done++;
        }
    }
}

However for some reason, when I put the fscanf block first, it won't stop and req for the fgets string, it just jumps over and outputs:

String for fscanf: Hello
For fscanf:
Zero: 5
Zero: 6
String for fgets: For fgets:
Return: 0
Zero: 1

But when I put the fgets block first it works fine:

String for fgets: Hello
For fgets:
Return: 5
Zero: 6
String for fscanf: Hello 
For fscanf:
Zero: 5
Zero: 6

Why does this occur?

dng
  • 1,275
  • 1
  • 8
  • 10

2 Answers2

3

scanf and fscanf have so many caveats they get their own page in the C FAQ. Your particular problem of mixing fscanf and fgets is covered by 12.18a.

In short, you typed Hello\n. fscanf(stdin, "%s", ss) is reading the string Hello, but not the newline. That's still on stdin. fgets then reads the newline and stops. When debugging these sorts of things, it's good to put quotes around the debugging output so you can see these things. printf("'%s'", gs);

In general, don't mix fscanf and fgets. Stick to one or the other. Generally avoid scanf and fscanf to read and parse lines, lumping reading and parsing together causes lots of problems. Instead, use fgets to read the whole line and sscanf to parse it.

Schwern
  • 153,029
  • 25
  • 195
  • 336
1

It's not working as expected because when you do fscanf(stdin, "%s", ss); and when you presses ENTER, it will leave ENTER into second buffer. Note that ENTER is a valid character. Hence it will read the \n for second input and it will not wait for fgets(gs, 10, stdin);. for this you need to clear the stdin buffer after this

fscanf(stdin, "%s", ss);

One way of getting it done is use getchar(). for e.g

//fscanf block

  getchar();/* help to clear the stdin buffer */

//fgets block

Also read here why one shouldn't use scanf() & what should be used instead of scanf() http://c-faq.com/stdio/scanfprobs.html

Achal
  • 11,821
  • 2
  • 15
  • 37