我在尝试将strstr与以下代码结合使用时遇到问题。谁能指出我为什么第108行的strstr(记录在printf()语句中)为什么返回NULL?我使用一个文件作为命令行参数(包含三个用\ n分隔并且以null终止的单词),然后使用另一个文件作为stdin

例如:

./stream_search word_list.txt < paragraph.txt


目标:打印出段落.txt中包含word_list.txt中所有单词的所有行

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INPUTSIZE 1000
#define LINESIZE 100

/*
    Read one line of a given file f into the array buffer.
 */
char* read_line(FILE* f, char buffer[LINESIZE]) {
    //reads line until n-1 char read, \n read, \o read, or EOF reached
    fgets(buffer, LINESIZE-1, f);
    printf("line 38: read line: %s\n", buffer);
    return buffer;
}

/*
   Prints the string in array buff.
*/
void print_buff(char buff[LINESIZE]) {
   printf("print_buff: %s\n", buff);
}

/*
    Read lines from standard input and store in array p.
*/
char* get_input(char p[INPUTSIZE]) {
    fgets(p, INPUTSIZE-1, stdin);
    printf("line 76: %s\n", p);
    return p;
}

int main(int argc, char* argv[]) {

   char words[LINESIZE];
   char user_input[INPUTSIZE];

   /*
    * Prints error if program was called with
    * no command line arguments,
    * or with more than one argument.
    */
    if(argc != 2) {
        fprintf(stderr, "Usage: ./stream_search <word list file> \n");
        return 0;
    }

    //assume argv[1] is a filename to open
    FILE* file = fopen (argv[1], "r");

    //Print error if file cannot be opened
    if (file == NULL) {
        fprintf(stderr, "Unable to open word list \n");
        return 0;
    }

    read_line(file, words); //get input from file
    get_input(user_input); //get input from stdin

    printf("line 98: %s", words);
    printf("line 101: %s", user_input);

    char* a = "hello";
    char* b = "hel";

    printf("line 103: %s\n", strstr(a, b));
    printf("line 108: %s\n", strstr(words, user_input));

    fclose(file);
    return 0;
}

最佳答案

您在代码中有两个问题,这两个问题都会阻止它按预期工作。


您无需从要搜索的单词(或“用户输入”)的末尾删除换行符,因此仅当单词出现在输入末尾时才能找到该单词。
您以错误的顺序调用函数strstr()及其参数。调用需要按照strstr(haystack, needle)的顺序,而不是代码中使用的strstr(needle, haystack)的顺序。换句话说,呼叫必须是strstr(user_input, words)而不是strstr(words, user_input)


您有未使用的功能print_buff()。您有两个非常相似的函数,可以通过将文件流和缓冲区大小作为参数传递而很容易地组合为一个函数。这也将为您提供一个删除换行符的地方。请注意,如果数组为char buffer[BUFLEN];,则使用fgets(buffer, BUFLEN, fp)(通常最好使用fgets(buffer, sizeof(buffer), fp))并指定数组的完整大小是完全安全和理智的。

将这些更改放在一起可以得出:

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

#define INPUTSIZE 1000
#define LINESIZE 100

static void read_line(FILE *f, size_t bufsiz, char buffer[])
{
    fgets(buffer, bufsiz, f);
    buffer[strcspn(buffer, "\n")] = '\0';
}

int main(int argc, char *argv[])
{
    char words[LINESIZE];
    char user_input[INPUTSIZE];

    if (argc != 2)
    {
        fprintf(stderr, "Usage: ./stream_search <word list file> \n");
        return 0;
    }

    FILE *file = fopen(argv[1], "r");

    if (file == NULL)
    {
        fprintf(stderr, "Unable to open word list \n");
        return 0;
    }

    read_line(file, sizeof(words), words);
    read_line(stdin, sizeof(user_input), user_input);

    printf("line 98: %s\n", words);
    printf("line 101: %s\n", user_input);
    printf("line 108: %s\n", strstr(words, user_input));
    printf("line 109: %s\n", strstr(user_input, words));

    fclose(file);
    return 0;
}


请注意,并非printf()的所有实现都能正常处理null指针。他们有权坠毁,而IMO最好这样做。但是,我没有在代码中解决此问题-(不幸的是,不幸的是,我使用的系统有一个printf()可以打印(null),而当给出空指针以字符串形式打印时不会崩溃。

给定一个包含行words的文件hel和一个包含data的文件hello world并调用程序wm13,我得到了示例输出:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
      -Wold-style-definition -Werror wm13.c -o wm13
$ ./wm13 words < data
line 98: hel
line 101: hello world
line 108: (null)
line 109: hello world
$

关于c - Strstr返回NULL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37450275/

10-13 05:14