0

The program is supposed to read data from stdin to a text file, and then perform a find and replace on the file, with the condition that the new word is longer than the old one. It compiles fine without any errors or warnings, but the issue is that fread is not working, it seems to return a 0 so the while loop isn't starting. The print file function is just there to be able to check the contents of the file, it's not part of the final code.

#include <stdio.h> #include <stdlib.h> #include <string.h> #define BUFFER_SIZE 1000 #define OLD_WORD_SIZE 24 #define NEW_WORD_SIZE 64 void write_to_file(const char *s); void replace_word(const char *s, const char *old, const char *new); void print_file(const char *s); int main(void){ const char file_name[] = "text.txt"; int c; char old_word[OLD_WORD_SIZE]; char new_word[NEW_WORD_SIZE]; while((c = getchar()) != EOF){ switch(c){ case 'w': getchar(); write_to_file(file_name); break; case 'r': getchar(); puts("Enter the word you want to replace"); fgets(old_word, sizeof(old_word), stdin); old_word[strlen(old_word) - 1] = '\0'; puts("Enter the new word"); fgets(new_word, sizeof(new_word), stdin); new_word[strlen(new_word) - 1] = '\0'; if(strlen(old_word) >= strlen(new_word)){ printf("Error: can't replace \"%s\" with \"%s\":\n\"%s\" is too small\n", old_word, new_word, new_word); break; } replace_word(file_name, old_word, new_word); getchar(); break; case 'p': print_file(file_name); getchar(); getchar(); break; default: printf("Invalid command:%i\n", c); break; } } return 0; } void write_to_file(const char *s){ FILE *out_file; if((out_file = fopen(s, "w")) == NULL){ perror(s); exit(EXIT_FAILURE); } int c; while((c = getchar()) != EOF){ fputc(c, out_file); } fclose(out_file); } void print_file(const char *s){ FILE *in_file; if((in_file = fopen(s, "r")) == NULL){ perror(s); exit(EXIT_FAILURE); } int c; while((c = fgetc(in_file)) != EOF){ printf("%c", c); } fclose(in_file); } void replace_word(const char *s, const char *old_word, const char *new_word){ char *buffer = malloc(BUFFER_SIZE); FILE *original_file; FILE *copy; if((original_file = fopen(s, "r")) == NULL){ perror(s); exit(EXIT_FAILURE); } if((copy = fopen("copy.txt", "w")) == NULL){ perror("text"); exit(EXIT_FAILURE); } int old_word_len = strlen(old_word); int new_word_len = strlen(new_word); char *src; char *dst; char *tmp; while(fread(&buffer, BUFFER_SIZE, 1, original_file) == 1){ if((tmp = strstr(buffer, old_word))){ buffer = realloc(buffer, BUFFER_SIZE + new_word_len - old_word_len + 1); src = tmp + old_word_len; dst = tmp + new_word_len; memmove(dst, src, BUFFER_SIZE - strlen(src)); memcpy(tmp, new_word, new_word_len); fwrite(&buffer, BUFFER_SIZE + new_word_len - old_word_len + 1, 1, copy); } else{ fwrite(&buffer, BUFFER_SIZE, 1, copy); } fseek(original_file, -old_word_len, SEEK_CUR); } } 

The code is incomplete, it's only missing a small segment, I don't move the modified version back to the original file.

Why is fread returning a zero? Are there any other mistakes in the code?

I realise I should free buffer at the end.

7
  • Don't use fread on a text file. Read line by line with fgets. Otherwise the fread might break a word you want to detect. Commented May 13, 2017 at 19:52
  • @WeatherVane fgets wouldn't work here because it'll stop on the first '\n`. I need to read a specific number of bytes. Commented May 13, 2017 at 19:53
  • You try to read 1 item of size BUFFER_SIZE, you perhaps want fread(buffer, 1, BUFFER_SIZE, original_file), i.e. read (at most) BUFFER_SIZE items of size 1. Commented May 13, 2017 at 19:54
  • So your word search spans two text lines? As in "fi\nnd" Commented May 13, 2017 at 19:55
  • Why fseek(original_file, -9, SEEK_CUR);? What is that supposed to do? Commented May 13, 2017 at 19:55

2 Answers 2

1

You want to swap the second and third arguments to fread().

The way you have it, it will only return 1 if it can read BUFFER_SIZE bytes.

 n = fread(buffer, 1, BUFFER_SIZE, original_file); if (n == BUFFER_SIZE) /* buffer full, needs to read more */; if (n > 0) /* read n bytes */; 

Even better as suggested in comments is to use fgets().

Sign up to request clarification or add additional context in comments.

Comments

0

You should not use &buffer there. Since buffer already is a char pointer, pass buffer as a first argument to fread and fwrite.

2 Comments

I tried that but it still returns 0.
Then start looking at errno, strerror and/or perror.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.