Вы должны использовать fgets()
для чтения из входного файла вместо fscanf(f1,"%[^\n]%*c", &s)
по нескольким причинам:
- вы не даете
fscanf()
максимальному количеству символов для хранения в s
: любая достаточно длинная строка во входном файле вызовет неопределенное поведение. - вы читаете строку из
f1
и явно пропускаете новую строку, это объясняет, почему новая строка никогда не записывается в f2
. fscanf()
завершится с ошибкой в пустой строке, поскольку нет символов, отличных от \n
для чтения в s
, s
не изменяется и обрабатывается так же, как и в предыдущей строке (или неопределенное поведение в первой строке)), и цикл повторяется в том же месте во входном файле, фактически застрял навсегда, записывая в f2
безрезультатно ...
Вот исправленная и упрощенная версия:
#include <stdio.h>
#include <string.h>
#define MAX 100
int main() {
FILE *f1, *f2;
char word[MAX], fname[MAX];
char s[MAX], replace[MAX];
char temp[] = "temp.txt";
char *p1, *p2;
printf("Enter your input file name: ");
if (!fgets(fname, sizeof fname, stdin))
return 1;
fname[strcspn(fname, "\n")] = '\0'; /* strip the newline if present */
printf("Enter the word to search: ");
if (scanf("%99s", word) != 1)
return 1;
printf("Enter the replacement word: ");
if (scanf("%99s", replace) != 1)
return 1;
f1 = fopen(fname, "r");
if (!f1) {
fprintf(stderr, "Unable to open the input file %s\n", fname);
return 1;
}
f2 = fopen(temp, "w");
if (!f2) {
fprintf(stderr, "Unable to open temporary file %s\n", temp);
return 1;
}
while (fgets(s, sizeof s, f1)) {
p1 = s;
while ((p2 = strstr(p1, word)) != NULL) {
while (p1 < p2) {
fputc(*p1++, f2);
}
fputs(replace, f2);
p1 += strlen(word);
}
fputs(p1, f2);
}
fclose(f1);
fclose(f2);
remove(fname);
rename(temp, fname);
return 0;
}
Обратите внимание, что если входной файл имеет очень длинные строки с совпадениями, охватывающими несколько фрагментов, считанных fgets()
, эти совпадения будут пропущены программой.
Вот другой подход, чтобы избежать этой проблемы:
#include <stdio.h>
#include <string.h>
#define MAX 100
int main() {
FILE *f1, *f2;
char fname[MAX], word[MAX], replace[MAX];
char temp[] = "temp.txt";
char *p1 *p2;
int c;
printf("Enter your input file name: ");
if (!fgets(fname, sizeof fname, stdin))
return 1;
fname[strcspn(fname, "\n")] = '\0'; /* strip the newline if present */
printf("Enter the word to search: ");
if (scanf("%99s", word) != 1)
return 1;
printf("Enter the replacement word: ");
if (scanf("%99s", replace) != 1)
return 1;
f1 = fopen(fname, "r");
if (!f1) {
fprintf(stderr, "Unable to open the input file %s\n", fname);
return 1;
}
f2 = fopen(temp, "w");
if (!f2) {
fprintf(stderr, "Unable to open temporary file %s\n", temp);
return 1;
}
p2 = word;
while ((c = getc(f1)) != EOF) {
if (c != '\0' && *p2 == (char)c) {
p2++;
if (*p2 == '\0') {
fputs(replace, f2);
p2 = word;
}
} else {
for (p1 = word; p1 < p2;) {
putc(*p1++, f2);
/* find potential match for special cases: find aab in aaab */
if (!memcmp(word, p1, p2 - p1) && word[p2 - p1] == (char)c)
p2 = word + (p2 - p1) + 1;
p1 = word;
break;
}
}
if (p1 == p2) {
putc(c, f2);
}
}
}
/* flush potential partial match at end of file */
for (p1 = word; p1 < p2; p1++) {
putc(*p1, f2);
}
fclose(f1);
fclose(f2);
remove(fname);
rename(temp, fname);
return 0;
}