strstr函数和c中的多维数组

问题描述

#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]);
        }
    }
}

输出

enter image description here

解决方法

最有可能是通过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'的字符串。在这种情况下,所有记录都将满足条件。您应该检查搜索的字符串是否在数组的字符串中形成一个单词(由空格分隔的字符序列)。