0

For example, if a .txt has

Hello
There.

written in it, no matter how bigger N is in fgets(str, N, file), it will only store "Hello" in str, because it stops when it finds a '\n' character.

So, how could I read the whole file if, for example, I wanted to find a specific word in it?

Jonas
  • 416
  • 4
  • 12
  • [`fgets`](https://linux.die.net/man/3/fgets) stops reading when it reaches a newline or EOF, you need to call `fgets` in a loop until EOF (or however many lines you want to read). The next line it reads will overwrite the last one read in `str`, so you'll need to save/process/do whatever with the line you just read before reading the next one. – yano Nov 16 '21 at 20:26
  • look at [this answer](https://stackoverflow.com/a/9206332/3476780) which uses `fgets` in a loop. – yano Nov 16 '21 at 20:33
  • One way would be to find the size of the file, allocate a buffer of that size+1, and `fread` the entire file into the buffer, and write the nul terminator at the index returned by `fread`. Then apply `strstr`. You might want to case-convert the entire buffer too before searching. – Weather Vane Nov 16 '21 at 20:33
  • 2
    Read the file line by line and search the word in each line read. Must be 12-15 lines of code. – Jabberwocky Nov 16 '21 at 20:39
  • Is it possible that the word you are searching for is [syllabified](https://en.wikipedia.org/wiki/Syllabification), so that part of the word is in one line and part of the word is in the next line, and that both parts are separated by a hyphen and a newline character? In that case, the solution will be more complex. – Andreas Wenzel Nov 16 '21 at 21:14
  • "it will only store "Hello" in str" --> Not quite. Code stores "Hello\n". – chux - Reinstate Monica Nov 16 '21 at 21:24
  • Jonas, given "how could I read the whole file", does your file have an expected maximum line length? If so, what is it? Does your _specific word_ every contain spaces? If the _specific word_ is "needle", does that match "Needle", or "needle123" or "_needle" or "needles"? Do words in the file have an maximum length? If the word is "bob", does that match "bobob" 0, 1 or 2 times? – chux - Reinstate Monica Nov 16 '21 at 21:26

1 Answers1

0

So, how could I read the whole file

In order to read the whole file into a memory buffer, you could use the function fread. After turning the input into a string by appending a terminating null character, you could then use the function strstr to search the input for a certain word.

Here is a program which does this and searches the input for the word targetword:

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

int main( void )
{
    FILE *fp;
    char buffer[1000];
    size_t read;

    //open input file
    fp = fopen( "input.txt", "rt" );
    if ( fp == NULL )
    {
        fprintf( stderr, "ERROR: Unable to open input file!\n" );
        exit( EXIT_FAILURE );
    }

    //read entire file into buffer
    read = fread( buffer, 1, sizeof buffer, fp );

    //verify that buffer was not too small
    if ( read == sizeof buffer )
    {
        fprintf( stderr, "ERROR: Memory buffer is too small to contain entire input!\n" );
        exit( EXIT_FAILURE );
    }

    //add terminating null character to make input a valid
    //null-terminated string
    buffer[read] = '\0';

    //search input for target word
    if ( strstr( buffer, "targetword" ) != NULL )
        printf( "Found word!\n" );
    else
        printf( "Did not find word!\n" );

    fclose( fp );
}

However, instead of reading the entire file at once (which could require a very large memory buffer), it is more common to read one line at a time in a loop, and in every loop iteration, you check whether the current line contains the word you are looking for. That way, the memory buffer only has to be large enough to store one line of input at once, instead of the entire input.

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

int main( void )
{
    FILE *fp;
    char line[100];
    bool found = false;

    //open input file
    fp = fopen( "input.txt", "rt" );
    if ( fp == NULL )
    {
        fprintf( stderr, "ERROR: Unable to open input file!\n" );
        exit( EXIT_FAILURE );
    }

    //read one line per loop iteration
    while ( fgets( line, sizeof line, fp ) != NULL )
    {
        //verify that line was not too long to fit into buffer
        if ( strchr( line, '\n' ) == NULL )
        {
            fprintf( stderr, "line too long to fit buffer!\n" );
            exit( EXIT_FAILURE );
        }

        //search for target word
        if ( strstr( line, "targetword" ) != NULL )
        {
            found = true;
            break;
        }
    }

    if ( found )
        printf( "Found word!\n" );
    else
        printf( "Did not find word!\n" );

    fclose( fp );
}

However, both solutions have several possible issues:

  1. If the target word targetword is part of another word, for example thetargetword, then it will state that it found the target word. I'm not sure if this is what you want or if you want the target word to appear by itself.

  2. If the target word is syllabified so that, for example, target-\n appears in one line and word in the next line, then the program won't be able to find the word.

  3. The search is case-sensitive, so it will only find targetword, but not Targetword or TARGETWORD.

All of these issues can be solved, if necessary, but would require additional work.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39