简体   繁体   English

C fgets语义错误

[英]C fgets semantic error

I'm new in the C world, and I've a problem with fgets() function. 我是C语言世界中的新手,并且fgets()函数存在问题。 I googled almost 2 hours my error, and found different solutions but no one worked. 我用Google搜索了将近2个小时的错误,发现了不同的解决方案,但没有人能解决。

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. 问题是:每次我运行此代码时,正在运行的服务器在写出“给我您的地址”后都跳过fgets() ,并执行以下功能。

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. 是的,仍然跳过了我的部分...我也尝试使用fflush(stdin)来确保一切都清楚了,但没有用。

 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. 在这些namecity有两个char变量,而不是以null terminated字符串。 Thus , using here - 因此,使用此处-

strcpy(kivansag.name,&name);

leads to UB . 导致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. 因此,由于下一个fgets也不会被跳过。

And then do as you were doing . 然后照常做。

char is just a single character, you can't use it to read a string with the %s format in scanf . char只是一个字符,您不能使用它来读取scanf具有%s格式的字符串。 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()

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. 在scanf之后,请参阅fgets不起作用,以了解程序为何跳​​过fgets及其修复方法。

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. 函数scanf()始终将NUL字节附加到输入的字符串中。

there is only one byte defined in char name . char name只定义了一个字节。

There is no limit put on the "%s" so the user can/will always overrun that one byte buffer. “%s”没有限制,因此用户可以/将始终超出该一个字节的缓冲区。

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 以下对fgets()的调用将看到换行符,并立即返回,除了换行符和NUL字节外,什么都没有放入输入缓冲区

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: 可能会或可能不会找到嵌入的换行符,并用NUL字节覆盖它:建议:

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. 甚至有“更巧妙”的方法来替换字符串中的换行符,但是这种方法很容易理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM