我在过去的3个小时里一直在尝试并且坚持到一点。 我想在使用C的文件中的每一行之后添加一些内容。
这是我的代码
int main(){
FILE *fp;
char c;
int p;
fp = fopen("example1.txt","r+");
if (fp == 0) {
perror("No File");
exit(-1);
}
while ( (c = fgetc(fp)) != EOF) {
if (c != '\n')
printf("%c",c);
else {
//Going back two points is for '\n'
fseek(fp,-2,SEEK_CUR);
fprintf(fp,"=2\n");
}
}
fclose(fp);
return 0;
}
输入文件:
1+1
1+1
1+1
期望的输出:
1+1=2
1+1=2
1+1=2
实际输出:
1+1=2
=2
=2
=2
=2
=2
执行进入无限循环..
答案 0 :(得分:0)
假设您在文件中有一行文字。
1+1
如果你按字节顺序查看内容,你会看到:
+---+---+---+----+
| 1 | + | 1 | \n |
+---+---+---+----+
当您遇到'\n'
时,您会返回两个字符并将"=2\n"
打印到该文件。之后,文件的内容将是:
+---+---+---+----+
| 1 | = | 2 | \n |
+---+---+---+----+
对fprintf
的调用不会改变您读取数据的位置。因此,读取位置位于文件的第二个字符'='
。
整个过程重复进行。文件的内容仍然是
+---+---+---+----+
| 1 | = | 2 | \n |
+---+---+---+----+
输出继续
=2
在第一行之后。
读取和写入同一个文件充满了太多陷阱。如果你将它们分开会更好。
答案 1 :(得分:0)
我遇到了同样的问题。我让它部分工作。在理想的位置,我用ftell来获得当前的位置。我从初始文件大小中减去它并存储在remainingSize变量中。使用fread我将这个位置后的字符放入缓冲区。然后我在当前位置写了所需的输出。然后我将缓冲区中的数据写回文件。这适用于小数据,但我的代码中有一个我无法解决的错误,导致ftell返回超出范围的值。
可以解释为
如果数据是
+---+---+---+----+
| 1 | + | 1 | \n |
+---+---+---+----+
+---+---+---+----+
| 3 | * | 5 | \n |
+---+---+---+----+
假设文件大小为'x' 你到了1点之后。 通过ftell,你可以获得当前的位置'y' 你必须读'x' - 'y'字符并将它们放入缓冲区 您可以在当前位置写入所需的输出,然后将缓冲区的内容写回文件
+---+---+---+----+
| 1 | + | 1 | = | 2
+---+---+---+----+
Buf =
+---+---+---+----+
| \n | 3 | * | 5 |\n
+---+---+---+----+
我认为这种解决方案效率低下,因为它涉及许多读写操作,可能无法处理大文件。
答案 2 :(得分:0)
除第一行外,您必须重写整个文件。在任意大的文件中任意长行,试图在现有文件中就地执行该操作实际上非常困难。
因此,编写新文件要容易得多。
像这样的东西(完全没有任何错误检查):
// open files
FILE *in = fopen( "infile.txt", "r" );
FILE *out = fopen( "infile.txt.tmp", "w+" );
// getline() variables
char *line = NULL;
size_t len = 0UL;
ssize_t result;
// buffer for output line
// (hope it's long enough...)
char buffer[ 1024 ];
for ( ;; )
{
// getline() makes this so much easier...
result = getline( &line, &len, in );
if ( result == -1 )
{
break;
}
// strip newline
char *p = strchr( line, '\n' );
if ( p != NULL )
{
*p = '\0';
}
// append "=2" to each line
snprintf( buffer, sizeof( buffer), "%s%s\n", line, "=2" );
fputs( buffer, out );
}
fclose( in );
fclose( out );
// assume POSIX rename is available
rename( "infile.txt.tmp", "infile.txt" );
逐行读取文件,将新数据附加到每行的末尾,将新行写入新文件,然后完成rename()
新文件到旧文件名。
通常情况下,我会在行之间添加空格以提高可读性,但额外的行会导致代码上出现滚动条,使其更少可读。