Strstr返回NULL

时间:2016-05-26 01:49:25

标签: c arrays string strstr

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

例如:

./stream_search word_list.txt < paragraph.txt

目标:打印出包含word_list.txt中单词的paragraph.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;
}

1 个答案:

答案 0 :(得分:1)

您在代码中遇到两个问题,其中任何一个都会阻止它按预期工作。

  1. 您不会从要搜索的单词的末尾(或“用户输入”)中删除换行符,因此只有在输入结尾处出现该单词时才会找到该单词。
  2. 使用错误顺序的参数调用函数strstr()。调用需要符合strstr(haystack, needle)的顺序,而不是代码中使用的strstr(needle, haystack)顺序。换句话说,通话需要strstr(user_input, words)而不是strstr(words, user_input)
  3. 您有一个未使用的功能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()的所有实现都不会优雅地处理空指针;他们有权发生崩溃,如果他们这样做,IMO会更好。但是,我没有修复这个代码 - (un)幸运的是,我正在使用的系统有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
    $