【问题标题】:Check multiple files with "strstr" and "fopen" in C在 C 中使用“strstr”和“fopen”检查多个文件
【发布时间】:2021-10-17 14:45:07
【问题描述】:

今天我决定人生中第一次学习编码。我决定学习 C。我创建了一个小程序来检查 txt 文件中的特定值。如果它找到该值,那么它将告诉您已找到该特定值。

我想做的是我可以把多个文件通过这个程序。我希望这个程序能够扫描文件夹中的所有文件以查找特定字符串并显示哪些文件包含该字符串(基本上是文件索引)

我今天刚开始,我 15 岁,所以我不知道我的假设是否正确,如果这听起来很愚蠢,我很抱歉,但我一直在考虑也许创建一个我放入该程序的每个目录的线程,每个线程单独在单个文件上运行该代码,然后显示可以找到该字符串的所有目录。

我一直在研究线程,但我不太了解它。这是一次一个文件的工作代码。有谁知道如何按照我的意愿进行这项工作?

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

int main()
{
    //searches for this string in a txt file
    char searchforthis[200];
    
    //file name to display at output
    char ch, file_name[200];
    FILE *fp;

    //Asks for full directory of txt file (example: C:\users\...) and reads that file.
    //fp is content of file
    printf("Enter name of a file you wish to check:\n");
    gets(file_name);
    fp = fopen(file_name, "r"); // read mode

    //If there's no data inside the file it displays following error message
    if (fp == NULL)
    {
        perror("Error while opening the file.\n");
        exit(EXIT_FAILURE);
    }
    
    //asks for string (what has to be searched)
    printf("Enter what you want to search: \n");
    scanf("%s", searchforthis);

    char* p;

    // Find first occurrence of searchforthis in fp
    p = strstr(searchforthis, fp);

    // Prints the result
    if (p) {
        printf("This Value was found in following file:\n%s", file_name);

    } else
        printf("This Value has not been found.\n");

    fclose(fp);
    return 0;
}

【问题讨论】:

  • 您希望同时完成还是一次只处理一个文件?
  • 除此之外,去掉gets(),它不会为溢出提供任何安全性,你应该限制scanf()读取的字符。
  • p = strstr(searchforthis, fp); 不会编译。 strstr 在另一个字符串中搜索一个字符串。相反,您可以将文件读入缓冲区(可能一次使用fgets 循环一行),然后执行p = strstr (searchforthis, buffer);
  • 另外,如果您刚刚开始,请忘记多线程。这是以后的事情,很久以后。
  • @PaulSanders 一些编译器(至少 gccclang)实际上接受错误的 p = strstr(searchforthis, fp); 并发出警告(不兼容的指针类型)。对于这些编译器,我建议添加编译器选项-Wall -Wextra -pedantic -pedantic-errors 以使编译失败。添加-Werror 也可能有好处。

标签: c multithreading input


【解决方案1】:

这一行,

p = strstr(searchforthis, fp);

错了。 strstr() 定义为 char *strstr(const char *haystack, const char *needle),其中没有文件指针。

忘记gets(),它容易溢出,参考Why is the gets function so dangerous that it should not be used?

您的scanf("%s",...) 与使用gets() 一样危险,因为您没有限制要读取的字符。相反,您可以将其重新格式化为,

scanf("%199s", searchforthis); /* 199 characters + \0 to mark the end of the string */

还要检查scanf()的返回值,万一出现输入错误,最终代码应该是这样的,

if (scanf("%199s", searchforthis) != 1)
{
  exit(EXIT_FAILURE);
}

如果您为此使用fgets() 会更好,尽管请记住fgets() 也会将换行符保存在缓冲区中,但您将不得不手动删除它。

要实际对文件执行检查,您必须逐行读取文件,通过使用fgets()fscanf() 或POSIX getline() 之类的函数,然后在每一行上使用strstr()确定你是否有匹配,这样的事情应该可以工作,

  char *p;

  char buff[500];

  int flag = 0, lines = 1;

  while (fgets(buff, sizeof(buff), fp) != NULL)
  {

    size_t len = strlen(buff); /* get the length of the string */

    if (len > 0 && buff[len - 1] == '\n') /* check if the last character is the newline character */
    {
      buff[len - 1] = '\0'; /* place \0 in the place of \n */
    }

    p = strstr(buff, searchforthis);

    if (p != NULL)
    {
      /* match - set flag to 1 */
      flag = 1;
      break;
    }
  }

  if (flag == 0)
  {
    printf("This Value has not been found.\n");
  }
  else
  {
    printf("This Value was found in following file:\n%s", file_name);
  }

flag用于判断文件中是否存在searchforthis

旁注,如果该行包含超过 499 个字符,您将需要更大的缓冲区或不同的函数,在这种情况下考虑 getline(),甚至可以自定义一个阅读字符字符。

如果要对多个文件执行此操作,则必须将整个过程置于循环中。例如,

 for (int i = 0; i < 5; i++) /* this will execute 5 times */
{
    printf("Enter name of a file you wish to check:\n");
    ...
}

【讨论】:

  • 感谢您帮助我。我试图将您的答案应用到我的程序中,但有些东西无法正常工作。我确信缓冲区有问题。这是更新的代码link
  • @GiancarloMetitieri 你留下了你的gets() 电话并添加了scanf("%1s"...),它只会读取一个字符...This 版本应该没问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-27
  • 1970-01-01
  • 2020-06-30
相关资源
最近更新 更多