0

I'm writing a piece of code in C that iterates T times and each time takes as input the text of a little song on which it will perform some counting operation (counting the length of each word). For now I'm just testing if the input works, and it doesn't.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SONG_SIZE 501

int main(void){
    int T;
    scanf("%d", &T);
    while(T--){
        char* song = malloc(MAX_SONG_SIZE);
        if(song == NULL){
            printf("malloc failed");
            return 1;
        }
        fgets(song, MAX_SONG_SIZE, stdin);
        printf("foo\n");
        free(song);
    }
    return 0;
}

I'm using fgets() because of the spaces among the words, and dynamic memory allocation because I can't just use one array for all the songs, characters from the previous iteration would remain in the array.

But there's a problem. It skips the fgets() in the first iteration, writing only "foo" and without waiting for me to insert a string.

This is an example of how it prints with initial input "3":
3
foo
this is a test
foo
another test
foo


With substituting printf("foo\n"); with printf("<<%s>>\n", song); the output is this:

3<br>
<< <br>
>> <br>
test <br>
<<test <br>
>> <br>
another test <br>
<<another test <br>
>> <br>

How can I solve this problem? If you have ANY advice you're welcome.

Ice
  • 54
  • 1
  • 6
  • 2
    The newline after the 3 is left in the buffer waiting for the first `fgets()` to read it. You need to read up to the end of the first line, the one with the number on it, before starting the calls to `fgets()`. For example: `int c; while ((c = getchar()) != EOF && c != '\n') ;` will work OK. You should be checking the return value from `fgets()` too, in case you encounter EOF before the T lines have been read. Eventually, you'll get rid of T and simply have the computer count the lines — computers are good at counting. You could debug this with printing: `printf("<>\n", song);` would help. – Jonathan Leffler Apr 05 '15 at 00:50
  • Note that you could use a statically allocated buffer as you are passing a fixed size to `malloc` anyway. – Diego Apr 05 '15 at 00:56
  • @JonathanLeffler: I've added in the main post how it prints with your debug trick – Ice Apr 05 '15 at 01:10
  • 1
    That goes to confirm what [Alejandro Díaz](http://stackoverflow.com/users/2283078/alejandro-d%c3%adaz) said in his [answer](http://stackoverflow.com/a/29453007/15168) and what I said in my comments. The `printf()` advice will help you avoid needing to ask such questions in the future — you'd have printed the input and seen you have a newline immediately, and you'd have asked "how do I get rid of the newline after the number I've entered before I call `fgets()` in a loop", or you'd have worked out what to do without extra help. Seeing the data that is being read (with end markers) helps a lot! – Jonathan Leffler Apr 05 '15 at 01:13
  • @JonathanLeffler: Thank you very much, problem solved. – Ice Apr 05 '15 at 01:25

2 Answers2

3

There's a \n left in the input buffer, see http://c-faq.com/stdio/scanfinterlace.html

A quote from the link:

As a general rule, you shouldn't try to interlace calls to scanf with calls to gets() (or any other input routines); scanf's peculiar treatment of newlines almost always leads to trouble. Either use scanf to read everything or nothing.

Alejandro Díaz
  • 1,998
  • 13
  • 22
0

There's a \n left in the input buffer. One solution is:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SONG_SIZE 501

int main(void){
    int t;
    scanf("%d", &t);
    getchar();

    char song[MAX_SONG_SIZE];
    while(t--){
        fgets(song, MAX_SONG_SIZE * sizeof(char), stdin);
        printf("foo\n");
    }
    return 0;
}

See also: How to clear input buffer in C?

Community
  • 1
  • 1
fa11enprince
  • 122
  • 1
  • 6