我认为 fgets 会让我的程序比使用 fgetc 更快,但由于我对 fgets 实际工作原理了解甚少,我的最终代码有很多问题,例如在文件底部留下空行,如果有人能弄清楚如何解决这个问题我很感激
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
int main() {
FILE *file, *f;
char line[100], l[100]; // buffers to move and copy lines in the file
int count = 1, // this counts the line we're in right now
StartDelete = 6, //here the first line of the sequence that we're gonna delete
EndDelete = 10, // the line where deleting end
size = 10; // how many lines in the file
file = fopen("data.txt", "w+"); // Open the file in read-write mode
f = fopen("data.txt", "r+"); // open another handle for the file to skip the lines we wanna delete
if (file == NULL || f == NULL) {
printf("Error opening file.\n");
return 1;
}
//take user's input
for ( int i = 0; i < size; ++i ) {
printf("name %d: ", i+1);
assert( fgets( line, sizeof(line), stdin ) );
fprintf( file, "%s%s", "name: ", line );
}
rewind(file); // going back to the start of the file
//
while( count <= EndDelete ) {
count++;
fgets(l, sizeof(l), f);
}
count = 0;// reset the lines counter to zero this time because of the way fgets work
// Read each line and overwrite the file with lines that are not marked for deletion
while (fgets(line, sizeof(line), file)) { //moving to the lines in the file
count++;//the line conter grows as we move forward in lines
if (count > StartDelete) {
fseek(file, -strlen(line), SEEK_CUR);//going back to the beginning of the line again because of the mechanism of fgets
fwrite(l, sizeof(char), strlen(l), file);//overwriting
if(fgets(l, sizeof(l), f));//moving to the next line we wanna overwrite with
else break;
}
}
// Truncate the file to remove any remaining content beyond the new end of file
fseek(file, ftell(file), SEEK_SET);
ftruncate(fileno(file), ftell(file));
fclose(file);
return 0;
}
我尝试从中删除两个和三个
one
two
three
four
我最终得到了
one
four
但末尾有额外的空行
多次打开同一文件(使用或不使用不同的访问模式)是实现定义的。换句话说,不要这样做。
(但是,这并不意味着您不能同时读取和写入文件。)
这里有三个不错的选择。
此选项分为三个步骤:
对于普通人计划做的几乎任何事情,这个选项就足够了。它也非常方便,因为您现在对文件内容具有完整的字符串编辑功能。
tmpfile()
来记忆这实际上是我最喜欢的选择。临时文件通常只是一个内存对象,实际上并不存在于磁盘上。
这与选项 1 的变体非常相似,除了我们如何处理实际的磁盘文件。
这是一个非常常见的选项,但我最不喜欢。然而,对于非常大的文件来说,这是唯一真正的选择。
也就是说,不必尝试删除旧文件并重命名新文件,只需重新打开这两个文件并将新文件复制回旧文件即可。这效率较低,但克服了删除和重命名方法的一些问题。
ftell()
此解决方案不是最佳方案,因为所有开销簿记以及需要使用特定于操作系统的工具将文件截断为新大小。 (嗯...这是一篇关于此的帖子。)