0

The program prints all the outputs from the file I expect it to if I comment out the second line however if I re-add it the tokens reach null earlier and only 2 words from the file are printed any problems I'm missing?

printf("%s\n",texttoken);
fprintf(resultptr,"%s ",filterer(redwords,lowercase(texttoken)));

The rest of the code is below.

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

void main(){
  char *filterer(char* redwords, char* word);
  char *lowercase(char *word);
  FILE *redptr;
  FILE *textptr;
  FILE *resultptr;
  char *redwords = malloc(20);
  char *text = malloc(255);
  char *texttoken;
  char *temp;
  redptr = fopen("redfile.txt", "r");
  textptr = fopen("textfile.txt", "r");
  resultptr = fopen("result.txt", "w");
  fgets(redwords,20,redptr);
  redwords = lowercase(redwords);
  fgets(text,255,textptr);
  texttoken = strtok(text, " ");
  while(texttoken != NULL){
    printf("%s\n",texttoken);
    fprintf(resultptr,"%s ",filterer(redwords,lowercase(texttoken)));
    texttoken = strtok(NULL, " ");
  }
}

char *filterer(char *redwords, char *word){
  int match = 0;
  char *token;
  token = strtok(redwords, ",");
  while(token != NULL) {
    if(strcmp(word,token)==0){
      match = 1;
    }
    token = strtok(NULL, ",");
  }
  if(match == 1){
    int i;
    int len = strlen(word);
    char modified[len+1];
    modified[len] = NULL;
    for(i=0; i<len; i++){
      modified[i] = '*';
    }
    return modified;
  }
  return word;
}

char *lowercase(char *word){
   int i;
   for(i=0; i<=strlen(word); i++){
      if(word[i]>=65&&word[i]<=90)
         word[i]=word[i]+32;
   }
   return word;
}

Gtracks
  • 3
  • 2
  • `filterer` calls `strtok` so the internal pointer to the string that is being tokenized is reset. `strtok` can only remember one pointer at a time. You could use `strtok_r` instead if you need to work on different strings in an overlapping manner. – Retired Ninja Mar 16 '22 at 17:56
  • please look into [this](https://stackoverflow.com/questions/2799023) for further reading. – quidstone Mar 16 '22 at 18:01
  • Aside: Say the length of `word[]` is 10. `for(i=0; i<=strlen(word); i++){` calls `strlen(word)` 11 times, each time costs a walk down `word[]` of 11 steps - very inefficient. Instead use `for(i=0; word[i]; i++){` – chux - Reinstate Monica Mar 17 '22 at 00:42
  • Gtracks, what compiler are you using? – chux - Reinstate Monica Mar 17 '22 at 00:51

1 Answers1

0

At least these problems:

Return of invalid pointer

return modified; returns a pointer to a local array. Local arrays become invalid when the function closes.

char modified[len+1];
modified[len] = NULL;
for(i=0; i<len; i++){
  modified[i] = '*';
}
return modified; // Bad

Save time: Enable all warnings

Example: warning: function returns address of local variable [-Wreturn-local-addr]

Nested use of strtok()

Both this loop and filterer() call strtok(). That nested use is no good. Only one strtok() should be active at a time.

while(texttoken != NULL){
  printf("%s\n",texttoken);
  fprintf(resultptr,"%s ",filterer(redwords,lowercase(texttoken)));
  texttoken = strtok(NULL, " ");
}

Since filterer() is only looking for a ',', look to strchr() as a replacement.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256