【问题标题】:C-language strstr segmentation faultC语言strstr分段错误
【发布时间】:2013-01-27 01:36:01
【问题描述】:

我是初学者,tracks.c:

#include <stdio.h>
#include <string.h>

char tracks[][5] = {
    "one",
    "two",
    "three",
    "four",
    "five",
    "six",
};

void track_search(char search_for[]) {

    int i;
    puts(search_for);
    puts(strstr(tracks[0], search_for));

    /*
    for (i = 0; i < 6; i++) {
        if (strstr(tracks[i], search_for)) {
            printf("tracks %i: %s\n", i,tracks[i]);
        } else {
            puts("Nothing found");
        }
    }
    */
}

int main() {

    char search_for[5];

    printf("enter your word: ");
    fgets(search_for, 5, stdin);
    track_search(search_for);

    return 0;
}

$ gcc track.c && ./a.out

输入你的话:上

分段错误

但如果我使用 puts(strstr(tracks[0], "on"));而不是 puts(strstr(tracks[0], search_for)); 可以用酒,有人知道哪里错了吗?

【问题讨论】:

  • 您未阅读的 fgets 文档显示“换行符使 fgets 停止读取,但该函数将其视为有效字符并包含在复制到 str 的字符串中。”和“在复制到 str 的字符后自动附加终止空字符。” ...这两个都是重要的信息。

标签: c pointers segmentation-fault strstr


【解决方案1】:

这是因为fgets 读取了换行符,所以"on\n""one" 中找不到,因此strstr 返回NULL,如果传递给puts,则会导致分段错误。

您可能希望在读取输入后首先删除换行符和其他空格,例如将第一次出现的换行符/空格设置为 0,例如

char *p;
if(p = strchr(search_for, '\n')) *p = 0;
if(p = strchr(search_for, ' ')) *p = 0;

(同样char[5]"three" 来说是不够的,因为你需要额外的地方来放置空终止符。)

【讨论】:

    【解决方案2】:

    这有几个问题。

    首先,你的常量数组没有正确声明。

    char tracks[][5] = {
        "one",
        "two",
        "three",
        "four",
        "five",
        "six",
    };
    

    这表示“声明一个任意长度的数组char[5]。仔细观察该数组内容非常,并认为这些字符串的长度实际上是它的字符数加一对于零终结符。有什么突然出现在你身上?也许是"three"这个词?那将是5+1,或者六个字符宽,而不是五个。

    试试这个:

    const char *tracks[] = 
    {
        "one",
        "two",
        "three",
        "four",
        "five",
        "six"
    };
    

    并且还像这样修改你的 for 循环:

    for (i = 0; i < sizeof(tracks)/sizeof(tracks[0]); ++i) 
    {
        if (strstr(tracks[i], search_for))
            printf("track[%d]: %s\n", i, tracks[i]);
    }
    

    注意:为了我自己的理智,我从循环中删除了多余的“未找到任何东西”。

    最后,获取的字符串可能会在末尾添加一个行尾 ('\n'),如果是这样,您应该检查并将其设为空。我会显着延长输入缓冲区的大小,然后将 endl 修剪掉(如果存在):

    int main()
    {
        char search_for[64] = {0};
    
        printf("enter your word: ");
        if (fgets(search_for, sizeof(search_for), stdin))
        {
            size_t len = strlen(search_for);
            if (len && search_for[len-1] == '\n')
                search_for[len-1] = 0;
            track_search(search_for);
        }
        else
        {
            perror("fgets failed.");
            return EXIT_FAILURE;
        }
    
        return EXIT_SUCCESS;
    }
    

    【讨论】:

      【解决方案3】:

      您必须考虑两件事:

      如果单词不在列表中,strstr() 返回一个 NULL 指针,你不能将它传递给 puts(),例如这样做

       char *found = strstr(tracks[0], search_for);
      if (found)
          puts(found);
      else
          puts("The word '%s' was not found\n",search_for);
      

      一旦你这样做了,你就会意识到 fgets 也会读取你输入的换行符。因此,如果您输入四个并按回车键,您将搜索“four\n”所以您应该删除那个 \n 字符,例如做

      char *p;
      if ((p = strrchr(search_for, '\n')) != NULL) {
         *p = 0;
      }
      

      使用 fgets 读取输入后。

      【讨论】:

        猜你喜欢
        • 2021-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-01
        • 2020-10-20
        • 1970-01-01
        相关资源
        最近更新 更多