I have program that replaces a word in a file with another one, but in the new file the lines are all written as one line, not in different lines and paragraphs as required.
I tried adding '\n'
at the end of each line I am reading from the original file, but it is not working.
This is my code:
int main() {
FILE *f1, *f2;
char word[MAX], fname[MAX];
char s[MAX], replace[MAX];
char temp[] = "temp.txt", *p1, *p2;
printf("Enter your input file name:");
fgets(fname, MAX, stdin);
fname[strlen(fname) - 1] = '\0';
scanf("%s", word);
scanf("%s", replace);
f1 = fopen(fname, "r");
if (!f1) {
printf("Unable to open the input file!!\n");
return 0;
}
f2 = fopen(temp, "w");
if (!f2) {
printf("Unable to open temporary file!!\n");
return 0;
}
while (fscanf(f1,"%[^\n]%*c", &s) != EOF) {
printf("%s",s); //I wanted to see what happens when I'm reading from the file. Previously I added at the end of string s the char '\n' but it didnt work
if (strstr(s, word)) {
p2 = s;
while (p1 = strstr(p2, word)) {
while (p2 != p1) {
fputc(*p2, f2);
p2++;
}
p1 = p1 + strlen(word);
fprintf(f2, "%s", replace);
p2 = p1;
}
while (*p2 != '\0') {
fputc(*p2, f2);
p2++;
}
} else {
fputs(s, f2);
}
}
fclose(f1);
fclose(f2);
remove(fname);
rename(temp, fname);
return 0;
}
You should use
fgets()
to read from the input file instead offscanf(f1,"%[^\n]%*c", &s)
for multiple reasons:fscanf()
to maximum number of characters to store intos
: any sufficiently long line in the input file will cause undefined behavior.f1
and explicitly skip the newline, this explains why the newline never gets written tof2
.fscanf()
will fail on an empty line because there are no characters different from\n
to read intos
,s
is unmodified and gets handled like the previous line (or undefined behavior on the first line), and the loop iterates at the same spot in the input file, effectively stuck forever writing tof2
to no avail...Here is a corrected and simplified version:
Note however that if the input file has very long lines with matches spanning multiple chunks read by
fgets()
, these matches will be missed by the program.Here is a different approach to avoid this problem:
So you want modify words in a file, but keep all whitespace as is? Then it is important to read and write the whitespace. Using read-functions that skips whitespace won't help you much.
Here is a generic version of a read-modify loop. Fixing bugs and extending it to a compete program, including error handling, is left as exercise to the reader
The simple reason is that you are not outputting a newline to the file. The
fscanf
doesn't include the newline ins
(because you specifically omit it with[^\n]
, which means "characters other than newline").If you just add
putc('\n', f2);
at the very end of the outerwhile
loop, it works fine.Alternatively, you could just read with
fgets
, which does include the newline in the string. An added benefit is thatfgets
forces you to specify the maximum length as an argument, while guarding against excessive line length withfscanf
requires you to put the length in the format string itself.(Note that the
printf("%s", s);
has no effect on what goes into the file, since it outputs tostdout
.)a first error is to give the address of s to fscanf,
fscanf(f1,"%[^\n]%*c",&s)
must befscanf(f1,"%[^\n]%*c",s)
anyway, just replace your fscanf by a simple fgets and all will be ok, you will not loose \n
P.S. if you cannot be sure MAX is not enough to handle lines you have to manage the case a line is cut in several at read, and may be the word to replace in cut because of that. There are several ways to do that.