1

I have an array of words:

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

and a txt file like this one:

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 == 

(where we don't know how many lines this file has)

I want to check the whole file and each time I find one of the words of the array to print that word and also print the line where it was found.

I'm having trouble with the comparison. My thought was to save every word of the file into an array and compare each one with the words of the words array. But i cannot do that. I have this:

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

I don't really know what to write here so that that I separate the file into words.

Please be kind to me, I'm only trying to learn.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
frog
  • 31
  • 6

3 Answers3

2

There are several problems in the code snippets you've provided:

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

Here you declare an array of 3 elements but you have 4 initializers. And you forgot to put the words between quotes.

Here you use fscanf to read into arr, but you didn't allocate memory, arr is not initialized, you probably meant to write char arr[200], 200 being the maximum word length.

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

You want this as base, tough there is still room form improvement:

#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);
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • @SergeBallesta it's a base only, but yes there is room for improvement – Jabberwocky Feb 24 '17 at 08:56
  • 1
    `for (int i = 0; i < (sizeof words)/sizeof *words; i++)` is comparing between signed and unsigned integer. Should be `for (size_t i = 0; i < (sizeof words)/sizeof *words; i++) `. – RoadRunner Feb 24 '17 at 09:40
1

You are using fscanf() to read the words out of your file, which is not the best way to do this. You should use getline(3) or fgets(3) to read each line of your file.

Additionally, this line:

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

Needs to be able to hold 4 char* pointers, not 3. You will also need to include quotes with these string literals. This is another way to do this:

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

Then to get the size of this array, just use sizeof(x) / sizeof(x[0]).

Furthermore, in this code segment:

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

You are using fscanf() on an uninitialized pointer, which leads to many problems. If you wish to use a pointer, you may need to dynamically allocate arr on the heap with malloc(3). If you don't wish to do this, just declare a VLA, such as char arr[200]. Also fscanf() returns number of items scanned, so fscanf(f,"%s",arr)!=EOF will have to be replaced with fscanf(f,"%s",arr)==1, to ensure one word is being read at a time.

Note: You should also check if FILE *f was opened correctly, as it can return NULL on error.

I'm having trouble with the comparison. My thought was to save every word of the file into an array and compare each one with the words of the words array.

As others have mentioned to use strstr(3), another possible option is to use strtok(3) to parse each word on the line, then use strcmp(3) to compare words[i] with the word parsed from the file. If words[] becomes bigger in the future, I would suggest using binary search instead of linear search to compare the words. This will improve you search time from O(n) to O(logn).

Here is some (modified) code I wrote before which does something similar:

#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;
}
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
0

Use 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
        }
    }
}