【问题标题】:Check if words of an array exist in a txt file in C检查C语言的txt文件中是否存在数组的单词
【发布时间】:2026-01-27 22:15:01
【问题描述】:

我有一个单词数组:

const char *words[3]={cat,dog,snake,bee};

还有一个像这样的txt文件:

apple tree day night story bee oil lemons get fight 234 meow woof safari  
jazz stuff what is dog fight street snake garden glass house bee question                 
foot head 29191 43493 == 

(我们不知道这个文件有多少行)

我想检查整个文件,每次找到数组中的一个单词来打印该单词并打印找到它的行。

我在比较时遇到了问题。我的想法是将文件的每个单词保存到一个数组中,并将每个单词与单词数组的单词进行比较。但我不能那样做。我有这个:

FILE *f;
const char *arr;
f=fopen("test.txt","r");
while(fscanf(f,"%s",arr)!EOF)

我真的不知道在这里写什么,以便将文件分成单词。

请善待我,我只是想学习。

【问题讨论】:

  • 使用strstr(),很简单
  • 我究竟如何使用 strstr() ?我的意思是在打开我的文件并在上面使用 fscanf 之后?
  • system( "grep ..." )... (鸭子和奔跑...嘿,这是狂欢节...)

标签: c arrays string file pointers


【解决方案1】:

你提供的sn-ps代码有几个问题:

const char *words[3]={cat,dog,snake,bee};

在这里,您声明了一个包含 3 个元素的数组,但您有 4 个初始化器。而且你忘了把单词放在引号之间。

这里你使用fscanf读入arr,但是你没有分配内存,arr没有初始化,你可能打算写char arr[200],200是最大字长。

FILE *f;
const char *arr;
f=fopen("test.txt","r");
while(fscanf(f,"%s",arr)!EOF)

您希望以此为基础,但仍有改进空间:

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

const char *words[] = { "cat", "dog", "snake", "bee" };

int main()
{
  char line[200];   // maximum line size is 200
  size_t len = 0;

  FILE *f;
  f = fopen("test.txt", "r");

  if (f == NULL)
  {
    printf("Can't open file\n");
    return 1;
  }

  int line_no = 0;
  while (fgets(line, sizeof line, f))
  {
    ++line_no;

    // (sizeof words)/sizeof *words is the the number of words in the words array
    for (int i = 0; i < (sizeof words)/sizeof *words; i++) 
    {
      if (strstr(line, words[i]) != NULL)
      {
        printf("found %s in line %d\n", words[i], line_no);
      }
    }
  }

  fclose(f);
}

【讨论】:

  • @SergeBallesta 这只是一个基础,但是是的,还有改进的余地
  • for (int i = 0; i &lt; (sizeof words)/sizeof *words; i++) 比较有符号整数和无符号整数。应该是for (size_t i = 0; i &lt; (sizeof words)/sizeof *words; i++)
【解决方案2】:

您正在使用fscanf() 从文件中读取单词,这不是最好的方法。您应该使用getline(3)fgets(3) 来读取文件的每一行。

另外,这一行:

const char *words[3]={cat,dog,snake,bee}; 

需要能够容纳 4 个 char* 指针,而不是 3 个。您还需要在这些字符串文字中包含引号。这是另一种方法:

const char *words[] = {"cat", "dog", "snake", "bee"};

然后要获取这个数组的大小,只需使用sizeof(x) / sizeof(x[0])

此外,在此代码段中:

FILE *f;
const char *arr;
f=fopen("test.txt","r");
while(fscanf(f,"%s",arr)!EOF)

您在未初始化的指针上使用fscanf(),这会导致很多问题。如果您希望使用指针,您可能需要使用malloc(3) 在堆上动态分配arr。如果您不想这样做,只需声明一个 VLA,例如 char arr[200]。此外,fscanf() 返回扫描的项目数,因此必须将 fscanf(f,"%s",arr)!=EOF 替换为 fscanf(f,"%s",arr)==1,以确保一次读取一个单词。

注意:您还应该检查FILE *f 是否正确打开,因为它可能会在错误时返回NULL

我在比较时遇到了问题。我的想法是将文件的每个单词保存到一个数组中,并将每个单词与单词数组的单词进行比较。

正如其他人提到的使用strstr(3),另一种可能的选择是使用strtok(3) 解析行中的每个单词,然后使用strcmp(3)words[i] 与从文件中解析的单词进行比较。如果将来words[] 变得更大,我建议使用二分搜索而不是线性搜索来比较单词。这会将您的搜索时间从 O(n) 缩短到 O(logn)

这是我之前写的一些(修改过的)代码,它做了类似的事情:

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

#define ARRAYSIZE(x) (sizeof x / sizeof x[0])

int main(void) {
    const char *words[] = {"cat", "dog", "snake", "bee"};
    FILE *fptr;
    char *line = NULL, *word = NULL;
    const char *delim = " \n";
    size_t len = 0, lineno = 0;
    ssize_t read;

    fptr = fopen("somewords.txt", "r");
    if (fptr == NULL) {
        fprintf(stderr, "Error reading file\n");
        exit(EXIT_FAILURE);
    }

    while ((read = getline(&line, &len, fptr)) != -1) {
        lineno++;
        word = strtok(line, delim);
        while (word != NULL) {
            for (size_t i = 0; i < ARRAYSIZE(words); i++) {
                if (strcmp(word, words[i]) == 0) {
                    printf("Found matched word: %s, Line number: %zu\n", word, lineno);
                }
            }
            word = strtok(NULL, delim);
        }
    }

    free(line);

    fclose(fptr);

    return 0;
}

【讨论】:

    【解决方案3】:

    使用 getline 和 strstr

    char *line = NULL;
    size_t len = 0;
    ssize_t read;
    
    int line_no = 0;
    while ((read = getline(&line, &len, f)) != -1) 
    {
        ++line_no;
        for (int i = 0; i < 3; i++) {
            if (strstr(line, words[i]) != null) 
            {
                // if matched
            }
        }
    }
    

    【讨论】:

    • 这给了我一个细分:(
    • 你必须改变:words[3] --> words[4]
    • 当心,strstr 将搜索子字符串而不是单词。例如如果会在“manager”中找到“age”,而它不是同一个词...