问题描述
#include <stdio.h>
#include <string.h>
void find_track(char *search_for);
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"
};
int main() {
char *to_search_str;
printf("Search for: ");
fgets(to_search_str,80,stdin);
find_track(to_search_str);
return 0;
}
void find_track(char *search_for) {
int i;
for (i=0; i<5; i++) {
if (strstr(tracks[i],search_for)) {
printf("Track %d: '%s'\n",i,tracks[i]);
}
}
}
该程序应该在tracks
多维数组中的每个字符串中搜索一个字符串,但是strstr()
中的find_track
函数始终返回null,无论输入如何(即使输入(如果我们从tracks
多维数组输入一个字符串的子字符串)。我不知道为什么会这样?
编辑: 校正后
#include <stdio.h>
#include <string.h>
void find_track(char *search_for);
char tracks[][80] = {
"I left my heart in Harvard Med School","The girl from Iwo Jima"
};
int main() {
char to_search_str[80];
printf("Search for: ");
fgets(to_search_str,stdin);
to_search_str[strlen(to_search_str)-1] = '\0';
find_track(to_search_str);
return 0;
}
void find_track(char *search_for) {
int i;
for (i=0; i<5; i++) {
if (strstr(tracks[i],tracks[i]);
}
}
}
解决方法
最有可能是通过fgets()
输入的问题。
-
您正在读取一个未初始化的指针
to_search_str
,该指针未指向有效的内存位置。在这种情况下,您可以简单地将其更改为一个数组,例如char to_search_str[80] = {0};
并完成它。 -
您需要修剪存储在输入缓冲区中的尾随换行符。
从man page,(强调我的)
fgets()
从流中读取最多小于大小的字符,并将其存储到s指向的缓冲区中。在EOF
或换行符之后停止读取。 如果读取换行符,则将其存储在缓冲区中。在缓冲区中的最后一个字符之后存储终止空字节('\0'
)。
to_search_str[strcspn(to_search_str,"\n")] = 0;
是完成此任务的快速方法,但是this other answer
您没有分配to_search_str
指针,而是将char *
指针传递给fgets
作为目标缓冲区。由于它实际上未初始化,因此会导致未定义的行为,通常会导致程序崩溃。
您只需要静态或动态分配它即可。
最简单的解决方案在于仅在堆栈中定义一个静态数组:
#include <string.h>
#define LEN 80
int main() {
char to_search_str[LEN];
printf("Search for: ");
fgets(to_search_str,LEN,stdin);
/* Remove trailing newline from the string to search */
to_search_str[strcspn(to_search_str,"\n")] = 0;
find_track(to_search_str);
return 0;
}
数组的大小为80,因为您将此数字用作fgets
中的 size 参数。请注意,对于常数80使用#define
,可以更轻松地对其进行更改。
堆中的动态分配涉及使用malloc()
函数(一旦不再需要该数组,则使用free()
):
#include <string.h>
#define LEN 80
int main() {
char * to_search_str = malloc(LEN);
printf("Search for: ");
fgets(to_search_str,"\n")] = 0;
find_track(to_search_str);
free(to_search_str);
return 0;
}
注意:由于fgets
在输出缓冲区中保留尾随换行符\ n,因此我们必须将其删除。我使用了here中所述的巧妙的 oneliner 解决方案。
char *to_search_str;
是未初始化的指针,对其进行写入将导致未定义的行为。例如,您必须分配内存或使用数组char to_search_str[100];
。
也不要忘记fgets
还将换行符读入缓冲区,您必须将其删除。
此代码段位于主页面
char *to_search_str;
printf("Search for: ");
fgets(to_search_str,80,stdin);
调用未定义的行为,因为指针to_search_str
尚未初始化且值不确定。
看来你至少是故意的
char to_search_str[80];
printf("Search for: ");
fgets(to_search_str,stdin);
函数fgets
可以将换行符'\n'
附加到输入的字符串中。
例如,您需要通过以下方式将其删除
to_search_str[ strcspn( to_search_str,"\n" ) ] = '\0';
函数find_track
至少应声明为
void find_track( const char *search_for);
当函数定义依赖于全局变量时,这是一个坏主意。
同样,查找相关字符串的方法也不是很好。例如,用户可以输入仅包含一个字符'a'
的字符串。在这种情况下,所有记录都将满足条件。您应该检查搜索的字符串是否在数组的字符串中形成一个单词(由空格分隔的字符序列)。