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)
因此,我对此感到困惑,谁能告诉我这种现象的深层原因?
这是因为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);
}