《 Head First C》一书中的演示中的strstr()和fgets()的问题

问题描述 投票:0回答:1
char tracks[][80] = {
    "I left my heart in Harvard Med School",
    "Newark, Newark - a wonderful town", 
    "Dancing with a Dork",
    "From here to maternity",
    "The girl from Iwo Jima",
};

void find_track(char search_for[]) {
    int i;

    for (i = 0; i < 5; i++) {
        char *pointer = strstr(tracks[i], search_for);
        printf("P:%s\n", pointer);
    } 
}

int main() {

    char search_for[80]; 
    printf("Search for: "); 
    fgets(search_for, 80, stdin); 
    // scanf("%79s", search_for);
    find_track(search_for);


    return 0;
}

这是使用strstr()和fgets()的示例。但是,当我运行它时,它无法返回匹配的指针,它始终为null。

Search for: wonderful
P:(null)
P:(null)
P:(null)
P:(null)
P:(null)

并且我尝试了一些不同的表达式:1.我将search_for数组的容量从80减少到10:

char search_for[10];

有效!

Search for: wonderful
P:(null)
P:wonderful town
P:(null)
P:(null)
P:(null)

2.I用scanf()替换了功能fgets()。

scanf("%79s", search_for);

也可以使用!

Search for: wonderful
P:(null)
P:wonderful town
P:(null)
P:(null)
P:(null)

因此,我对此感到困惑,谁能告诉我这种现象的深层原因?

c fgets stdio linefeed
1个回答
1
投票

这是因为fgets最多读取80-1 = 79个字符的长度(它留下1个字符,将成为空终止),但是在您将换行符\n字符附加到stdin之后,它将停止读取输入“精彩”,然后按Enter。但是它将\n字符复制到缓冲区中,因此输入字符串实际上是"wonderful\n\0",由于换行,它与您拥有的数据不匹配。

现在,当您恰好声明缓冲区大小为10时,fgets没有空间存储\n,但是null终止了字符串-这就是为什么它偶然起作用的原因。

scanf另一方面却将\n留在stdin中而不读取它,因此这就是scanf也起作用的原因。但是,fgets是更好,更安全的功能,因此您应该继续使用它。

快速解决方案是执行类似的操作:

fgets(search_for, 80, stdin); 
search_for[strlen(search_for)-1] = '\0';
find_track(search_for);

这将使用空终止符覆盖\n。在fgets之后,您在内存中有"wonderful\n\0",然后search_for[strlen(search_for)-1] = '\0';将其更改为"wonderful\0\0"

注意,对于正确的程序,还应该添加错误处理:

if(fgets(search_for, 80, stdin) != NULL)
{
  search_for[strlen(search_for)-1] = '\0';
  find_track(search_for);
}
© www.soinside.com 2019 - 2024. All rights reserved.