6

I can't work out what's the problem with my code. Here's my code:

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

#define N 20

typedef struct _dog {
    char dogName[N],ownerName[N];
    int dogAge;
} Dog;

int main() {
    //Dynamic array
    int size;
    printf("Number of dogs: ");
    scanf("%d", &size);
    Dog *dog = (Dog*)malloc(sizeof(Dog)*size);
    printf("\n");
    //Input
    int i;
    printf("Please provide the data: [dogName][ownerName][dogAge] :\n");
    for(i=0;i<size;i++) {
        fgets(dog[i].dogName, sizeof(dog[i].dogName), stdin);
        fgets(dog[i].ownerName, sizeof(dog[i].ownerName), stdin);
        scanf("%d", &dog[i].dogAge);
    }
    //Output
    printf("\nYou provided the following data:\n");
    for(i=0;i<size;i++) {
        printf("Dog Name: %s\nOwner Name: %s\nDog Age: %d\n", dog[i].dogName, dog[i].ownerName, dog[i].dogAge);
    }

    free(dog);
    return 0;
}

The task is pretty easy, you have to make a database but the dogs and owners can have two or more names, so that's why i try to use fget. But the output looks awful: (And the first Dog name part is usually blank)

You provided the following data:
Dog Name: 

Owner Name: Doggy 1

Dog Age: 0
Dog Name: Big Dick

Owner Name: 2

Dog Age: 0

I've read this but didn't help me.

The input I used:

Doggy 1
Big Dick
2
Doggy 2

It's ended after Doggy 2.

Community
  • 1
  • 1
2b1c
  • 75
  • 8

2 Answers2

11

You are leaving a newline from your last scanf() which is a valid input for the fgets(). Change

scanf("%d", &size);

to

scanf("%d%*c", &size);

to consume and discard the trailing newline due to the press of ENTER key after entering the number of dogs.

The same goes for the dogAge variable scanning, too, inside the lop.

Related, quoting the C11 standard, chapter §7.21.6.2, fscanf()

Trailing white space (including new-line characters) is left unread unless matched by a directive. [...]

so, the newline ('\n'), the trailing white space, is left unread in the input buffer.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Thank you for the fast reply. I've added the code at the size part but it seems I've still got a bug in my code in the loop where i use scanf. If I understand right the scanf in the loop creates a newline too? UPDATE: I've added %d%*c at the scanf in the loop, now works like a charm. :) Is there a better way to consume newlines after scanf or I have to use this all the time? – 2b1c Dec 27 '15 at 14:45
  • @SouravGhosh I downvoted it. No offense please, but I tested it and it does not work. Does it work for you? – Ely Dec 27 '15 at 14:55
  • 1
    @Elyasin I did not test the functionality, but I see no reason for this to fail. Can you share your test please? – Sourav Ghosh Dec 27 '15 at 14:57
  • Both @Elyasin and Sourav Ghosh answer is working, now i understand what was the problem. Thanks for both of you! UPDATE: I used %d%*c at both scanf in code, and works the same as getchar(); – 2b1c Dec 27 '15 at 14:57
  • 1
    Oh dear, I retested it and it works. I'm sorry, my bad :-( – Ely Dec 27 '15 at 14:59
  • Our interactions might have interleaved. In the beginning you forgot to mention the scanf in the inner loop. That's when my test failed. Now that I did it again it works after the edit it works. The answer is correct I think (y) – Ely Dec 27 '15 at 15:03
  • 1
    @Elyasin ha ha. I did not forget, I thought it was understood. However, later I thought of adding the last line too, and see, _it helps_ . :) – Sourav Ghosh Dec 27 '15 at 15:05
3

Add a getchar() after the scanf(...) calls.

As in the other answer(s) mentioned. scanf consumes the recognized characters according to format, but leaves the newline \n in stdin. With getchar you consume it and subsequent reads from stdin should not get confused.

Ely
  • 10,860
  • 4
  • 43
  • 64
  • @Elyasin If I add getchar(); after the two scanf it works too, thanks for the help. You guys rock! – 2b1c Dec 27 '15 at 14:53