Check multiple files with "strstr" and "fopen" in C

Viewed 175

Today I decided to learn to code for the first time in my life. I decided to learn C. I have created a small program that checks a txt file for a specific value. If it finds that value then it will tell you that that specific value has been found.

What I would like to do is that I can put multiple files go through this program. I want this program to be able to scan all files in a folder for a specific string and display what files contain that string (basically a file index)

I just started today and I'm 15 years old so I don't know if my assumptions are correct on how this can be done and I'm sorry if it may sound stupid but I have been thinking of maybe creating a thread for every directory I put into this program and each thread individually runs that code on the single file and then it displays all the directories in which the string can be found.

I have been looking into threading but I don't quite understand it. Here's the working code for one file at a time. Does anyone know how to make this work as I want it?

#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;
}
1 Answers

This line,

p = strstr(searchforthis, fp);

is wrong. strstr() is defined as, char *strstr(const char *haystack, const char *needle), no file pointers in it.

Forget about gets(), its prone to overflow, reference, Why is the gets function so dangerous that it should not be used?.

Your scanf("%s",...) is equally dangerous to using gets() as you don't limit the character to be read. Instead, you could re-format it as,

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

Also check the return value of scanf() , in case an input error occurs, final code should look like this,

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

It is even better, if you use fgets() for this, though keep in mind that fgets() will also save the newline character in the buffer, you are going to have to strip it manually.

To actually perform checks on the file, you have to read the file line by line, by using a function like, fgets() or fscanf(), or POSIX getline() and then use strstr() on each line to determine if you have a match or not, something like this should work,

  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 is used to determine whether or not searchforthis exists in the file.

Side note, if the line contains more than 499 characters, you will need a larger buffer, or a different function, consider getline() for that case, or even a custom one reading character by character.

If you want to do this for multiple files, you have to place the whole process in a loop. For example,

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