如何在C中以不同的行将字符串写入文件
我有一个程序,可以用另一个字替换文件中的一个字,但在新文件中,所有的行都写为一行,而不是按要求写在不同的行和段落中 我尝试在从原始文件读取的每行末尾添加如何在C中以不同的行将字符串写入文件,c,string,file,replace,word,C,String,File,Replace,Word,我有一个程序,可以用另一个字替换文件中的一个字,但在新文件中,所有的行都写为一行,而不是按要求写在不同的行和段落中 我尝试在从原始文件读取的每行末尾添加'\n',但它不起作用 这是我的代码: int main() { FILE *f1, *f2; char word[MAX], fname[MAX]; char s[MAX], replace[MAX]; char temp[] = "temp.txt", *p1, *p2; printf("Enter y
'\n'
,但它不起作用
这是我的代码:
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;
}
第一个错误是将s的地址提供给fscanf,
fscanf(f1,“%[^\n]%*c”,&s)
必须是fscanf(f1,“%[^\n]%*c”,s)
无论如何,只要用一个简单的FGET替换fscanf,一切都会好起来,不会松动\n
注意:如果你不能确定MAX不足以处理行,你必须处理一行在读取时被切割成几行的情况,并且可能是因为这个原因而在切割中被替换的单词。有几种方法可以做到这一点。第一个错误是将s的地址提供给fscanf,
fscanf(f1,“%[^\n]%*c”和&s)
必须是fscanf(f1,“%[^\n]%*c”,s)
无论如何,只要用一个简单的FGET替换fscanf,一切都会好起来,不会松动\n
注意:如果你不能确定MAX不足以处理行,你必须处理一行在读取时被切割成几行的情况,并且可能是因为这个原因而在切割中被替换的单词。有几种方法可以做到这一点。简单的原因是您没有向文件输出换行符。
fscanf
不包括s
中的换行符(因为您在[^\n]
中特别省略了它,这意味着“换行符以外的字符”)
如果只添加putc('\n',f2)
在外部的最末端,当循环时,它工作正常
或者,您可以只使用fgets
进行读取,其中包含字符串中的换行符。另一个好处是,fgets
强制您指定最大长度作为参数,而使用fscanf
防止过长的行长度要求您将长度放入格式字符串本身
(请注意,printf(“%s”,s);
对进入文件的内容没有影响,因为它输出到stdout
)原因很简单,因为您没有向文件输出换行符。fscanf
不包括s
中的换行符(因为您在[^\n]
中特别省略了它,这意味着“换行符以外的字符”)
如果只添加putc('\n',f2)
在外部的最末端,当循环时,它工作正常
或者,您可以只使用fgets
进行读取,其中包含字符串中的换行符。另一个好处是,fgets
强制您指定最大长度作为参数,而使用fscanf
防止过长的行长度要求您将长度放入格式字符串本身
(请注意,printf(“%s”,s);
对进入文件的内容没有影响,因为它输出到stdout
)出于多种原因,您应该使用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()
来读取输入文件,而不是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;
}
所以您想修改文件中的单词,但保留所有空白?然后,读写空格是很重要的。使用跳过空白的读取函数不会有多大帮助
下面是读修改循环的通用版本。修复bug并将其扩展到一个程序,包括错误处理,留给读者作为练习
while (1)
{
// Read the next character
int ch = fgetc(infile);
if (ch == EOF)
break; // read error or eof
if (isspace(ch))
{
// The character was a whitespace, so we copy it to the outputstream
int err = fputc(ch, outfile);
if (err == EOF)
break; // error
}
else
{
// The next character was not a whitespace, so we put it back in the
// inputstream for scanf to find it
ungetc(ch, instream);
char word[64]; // Just assume for simplicity that no words are longer
// than 63 character.
// Read the next string, making sure we don't read more than the buffer
// can handle. A robust program should do something useful if words are
// actually longer than 63 characters
int len = fscanf(infile, "%63s", word);
if (len == EOF)
break; // error (should not happen since there is guarantied to be
// one non-whitespace character in the stream)
char mod_word[64];
modify_word(mod_word, word);
int err = fputs(mod_word, outfile);
if (err == EOF)
break; // error
}
}
// Check for read-write errors
if (ferror(infile))
perror("Failure reading from input file");
if (ferror(outfile))
perror("Failure writing to output file");
所以您想修改文件中的单词,但保留所有空白?然后,读写空格是很重要的。使用跳过空白的读取函数不会有多大帮助
下面是读修改循环的通用版本。修复bug并将其扩展到一个程序,包括错误处理,留给读者作为练习
while (1)
{
// Read the next character
int ch = fgetc(infile);
if (ch == EOF)
break; // read error or eof
if (isspace(ch))
{
// The character was a whitespace, so we copy it to the outputstream
int err = fputc(ch, outfile);
if (err == EOF)
break; // error
}
else
{
// The next character was not a whitespace, so we put it back in the
// inputstream for scanf to find it
ungetc(ch, instream);
char word[64]; // Just assume for simplicity that no words are longer
// than 63 character.
// Read the next string, making sure we don't read more than the buffer
// can handle. A robust program should do something useful if words are
// actually longer than 63 characters
int len = fscanf(infile, "%63s", word);
if (len == EOF)
break; // error (should not happen since there is guarantied to be
// one non-whitespace character in the stream)
char mod_word[64];
modify_word(mod_word, word);
int err = fputs(mod_word, outfile);
if (err == EOF)
break; // error
}
}
// Check for read-write errors
if (ferror(infile))
perror("Failure reading from input file");
if (ferror(outfile))
perror("Failure writing to output file");
我试着用没有地址的fscanf替换它,虽然我不明白为什么,但它仍然不起作用。我也尝试过fgets版本,但更糟糕的是,现在,用fgets在一个字符串中读取所有文件并替换单词,最终的文件不完整。要删除&只允许给fscanf一个char*
而不是char**
,因为这是