The short answer is you really shouldn't, but it is doable if the search and replace strings are exactly the same length -- but you cannot make any mistakes in the number of characters you write -- or you will corrupt the file.
In your code, if the strlen isn't the same, you need to return or otherwise handle the error, not just output that fact.
You already have f open as "r+" with the file-position-indicator at the beginning, strstr will tell you if you have found the word to replace, then all you need to do is set the file-positon-indicator to the location of the pointer returned by strstr and write the replacement characters over the search term, and repeat for the remainder of the line.
Keeping the offset for the file position indicater straight will need careful attention. After your read, the indicator will be one past the last character read by fgets, so you will need to backup by where - write - strlen(write) in your code. (note: the offset is intended to be negative)
You can use fseek to rewind and reset the file-position-indicator, but you are probably better served using fgetpos to save the current indicator position and fsetpos to restore it, while calling fseek only once to position to indicator for the replacement.
Putting it altogether in a short example, and using buf, find and replace, instead of write and where, you could do something like the following:
#include <stdio.h>
#include <string.h>
#define MAXC 1024
int main (int argc, char **argv) {
char buf[MAXC], *find, *replace; /* read buf, find, replace pointers */
size_t findlen; /* length of find string */
FILE *f = NULL; /* file pointer */
if (argc < 4 ) { /* validate sufficient arguments given */
fprintf (stderr, "error: insufficient input, "
"usage: %s file find repl\n", argv[0]);
return 1;
}
find = argv[2]; /* set find, replace & length */
replace = argv[3];
findlen = strlen (find);
if (findlen != strlen (argv[3])) { /* validate length the same */
fprintf (stderr, "error find/replace lengths differ.\n");
return 1;
}
if (!(f = fopen (argv[1], "r+"))) { /* validate file open for reading+ */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (fgets (buf, MAXC, f)) { /* read each line into buf */
char *findp = buf; /* find pointer to search buf */
/*
* buf length and search term split at end validation omitted.
*/
while ((findp = strstr (findp, find))) { /* while find found */
fpos_t pos; /* object to hold current file position */
/* compute characters to backup (negative) */
long backup = (long)(findp - buf) - strlen(buf);
fgetpos (f, &pos); /* save the current position */
fseek (f, backup, SEEK_CUR); /* backup */
for (char *p = replace; *p; p++)
fputc (*p, f); /* overwrite char-by-char */
fsetpos (f, &pos); /* reset file position */
findp += findlen; /* advance beyond current find */
}
}
if (fclose (f) == EOF) /* validate close after write */
perror ("fclose(f)");
return 0;
}
Example Input File
$ cat dat/dogfleas.txt
my dog has fleas
other dogs run away
my dog is an ichy dog
Example Use and Resulting File
$ ./bin/file_replace_in_place dat/dogfleas.txt dog cat
$ cat dat/dogfleas.txt
my cat has fleas
other cats run away
my cat is an ichy cat
(no pun in shell command intended)
mmapthe file.fseek