0

I'm new in the C world, and I’ve a problem with fgets() function. I googled almost 2 hours my error, and found different solutions but no one worked.

My class is too big for just show every parts of it, but let me show you the problematic part:

//... kivansag is a struct(!)
if(check == 1){
        char name;
        printf("Please give me your nickname!\n");
        scanf("%s", &name);
        strcpy(kivansag.name,&name);

        char city;
        printf("Please give me your city!\n");
        scanf("%s", &city);
        strcpy(kivansag.city,&city);

        char *address = malloc(100);
        printf("Please give me your address!\n");           
        fgets(address,100,stdin);

        if((strlen(address)>0) && address[strlen(address)-1] == '\n'){
            address[strlen(address)-1] = '\0';
        }

        strcpy(kivansag.address,address);
        free(address);
}//...

The problem is: Every time I run this code, the running server is skipping fgets() after it wrote out "give me your address", and do the following function.

May I get any suggestions?

UPDATED:

Now I have only this:

        printf("Please give me your address!\n");           
        fgets(kivansag.address,sizeof(kivansag.address),stdin);

        if((strlen(kivansag.address)>0) && kivansag.address[strlen(kivansag.address)-1] == '\n'){
            kivansag.address[strlen(kivansag.address)-1] = '\0';
        }

the struct seems like this:

struct Kivansag{
  //...
  char address[100];
};

And yeah, still skipping my part... I tried to use fflush(stdin) too, to make sure everything is clear, but not worked.

dsh
  • 12,037
  • 3
  • 33
  • 51
  • `char name;` is a variable with enough space for **one** character. – wildplasser Oct 16 '15 at 18:55
  • 1
    Hint: What kind of character doesn't match `scanf("%s")` (remaining in the input stream), but causes `fgets()` to return immediately? – EOF Oct 16 '15 at 19:17
  • always check (!=NULL) the returned value from malloc() to assure the operation was successful. – user3629249 Oct 17 '15 at 06:27
  • the function fflush() is only for output streams, not stdin. The C standard specifically states that `fflush(stdin)` is undefined behaviour. – user3629249 Oct 17 '15 at 06:36
  • this line: `scanf("%s", &city);` will fail because the newline left in the input stream will stop scanf() from inputting anything. Suggest reading the man page for scanf() – user3629249 Oct 17 '15 at 06:38

3 Answers3

0
 scanf("%s", &name);      //you cant use %s to take input in a char variable
 ...
 scanf("%s", &city);

In these name and city are two char variables , not null terminated strings. Thus , using here -

strcpy(kivansag.name,&name);

leads to UB .

You can declare them as arrays -

char name[20];
char city[20];
fgets(name,20,stdin);    
...
fgets(city,20,stdin); 
strcpy(kivansag.name,name);      // note address of name is not required 
/* similarly for copying city */

So due this next fgets will also not be skipped.

And then do as you were doing .

ameyCU
  • 16,489
  • 2
  • 26
  • 41
  • I tried, and didn't worked. For the last case, i commented name and city inputs, and now i only have the address part.. still skipping. – András Balázs Oct 16 '15 at 19:08
0

char is just a single character, you can't use it to read a string with the %s format in scanf. You need to provide a character array. There's no need to scan into one variable and then copy into another, you can scan directly into the structure member.

scanf("%s", kivansag.name);

You can also use fgets() directly into the variable:

fgets(kivansag.address, sizeof kivansag.address, stdin);
size_t len = strlen(kivansag.address);
if((len>0) && kivansag.address[len-1] == '\n'){
    kivansag.address[len-1] = '\0';
}

See fgets doesn't work after scanf for why your program is skipping fgets and how to fix it.

Community
  • 1
  • 1
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

these two lines are always going to produce undefined behaviour.

Undefined behaviour can result in anything, including a seg fault event

    char name;
    ....
    scanf("%s", &name);

the function scanf() always appends a NUL byte to the string that was input.

there is only one byte defined in char name.

There is no limit put on the "%s" so the user can/will always overrun that one byte buffer.

Suggest something like:

    char name[30];
    ....
    if( 1 != scanf("%29s", &name) { // handle error }

this line:

scanf("%s", &city);

left a newline in the input stream.

the following call to fgets() will see that newline, and immediately return with nothing put into the input buffer but the newline and a NUL byte

this very messy lines:

if((strlen(address)>0) && address[strlen(address)-1] == '\n'){
        address[strlen(address)-1] = '\0';
    }

may or may not find an embedded newline and overlay it with a NUL byte Suggest:

if( char* newline = strstr( address, "\n" ) )
    *newline = '\0';

There are even 'neater' ways to replace the newline in the string but this method is easy to understand.

user3629249
  • 16,402
  • 1
  • 16
  • 17