c - 在C中同时读取和写入文件

标签 c file-handling fgets fgetpos

应该在文件中每两行交换一次,直到只剩下一行或所有行都用完。我不想在这样做时使用另一个文件。

这是我的代码:

#include <stdio.h>

int main() {
    FILE *fp = fopen("this.txt", "r+");
    int i = 0;
    char line1[100], line2[100];
    fpos_t pos;
    fgetpos(fp, &pos);

    //to get the total line count
    while (!feof(fp)) {
        fgets(line1, 100, fp);
        i++;
    }

    i /= 2;  //no. of times to run the loop
    rewind(fp);

    while (i-- > 0) {  //trying to use !feof(fp) condition to break the loop results in an infinite loop
        fgets(line1, 100, fp);
        fgets(line2, 100, fp);

        fsetpos(fp, &pos);

        fputs(line2, fp);
        fputs(line1, fp);

        fgetpos(fp, &pos);
    }

    fclose(fp);
    return 0;
}

this.txt中的内容:

aaa
b
cc
ddd
ee  
ffff
gg
hhhh
i
jj

程序运行后的内容

b
aaa
ddd
cc
ddd
c
c

c


i
jj

我什至尝试使用 fseek 代替 fgetpos 只是为了得到相同的错误结果。

据我所知,在第二个 while 循环运行两次 (即前四行已被处理) 之后,光标正确地位于第 17 个字节,它应该是 (调用 ftell(fp)) 甚至第 4 行之后的文件内容都没有改变,并且由于某种原因 fgets 是第三次循环时调用,读入数组line1和line2的内容分别为“c\n”和“ddd\n”。

再一次,我不想使用另一个文件来完成此操作,我只需要弄清楚屏幕背后到底出了什么问题

如有任何线索,我们将不胜感激。谢谢你。

最佳答案

您的代码中存在多个问题:

  • 您不检查 fopen() 是否成功,存在未定义行为的风险。

  • 确定总行数的循环不正确。
    在此处了解原因:Why is “while ( !feof (file) )” always wrong?

  • 您实际上不需要计算总行数。

  • 您应该调用 fflush() 将内容写回文件,然后再从写回读更改。

C 标准对以更新模式打开的文件指定了此限制:

7.21.5.3 The fopen function

[...] output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.

这解释了为什么仅在以相反顺序写入行后读取文件位置会导致问题。调用 fflush() 应该可以解决这个问题。

这是更正后的版本:

#include <stdio.h>

int main(void) {
    FILE *fp;
    char line1[100], line2[100];
    fpos_t pos;

    fp = fopen("this.txt", "r+");
    if (fp == NULL) {
        fprintf(stderr, "cannot open this.txt\n");
        return 1;
    }

    while (fgetpos(fp, &pos) == 0 &&
           fgets(line1, sizeof line1, fp) != NULL &&
           fgets(line2, sizeof line2, fp) != NULL) {

        fsetpos(fp, &pos);
        fputs(line2, fp);
        fputs(line1, fp);
        fflush(fp);    
    }

    fclose(fp);
    return 0;
}

关于c - 在C中同时读取和写入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42046611/

相关文章:

c - 我想打破存储在数组中 '\n' 字符处的字符串?

c - 带有二维数组参数的c中的函数调用和函数原型(prototype)

检查数组的长度

c - 在 C 中修剪字符串

c++ - 如何查看c++程序生成的.dat文件?

c - fgets 如何处理 Enter 键按下?

c++ - 在 C/C++ 中的特定地址边界上对齐内存是否仍能提高 x86 性能?

php - 我们如何从文件中获取文本(逐字)到 PHP 中的二维数组中?

c++ - 理解以下 C++ 代码时遇到问题。 (寻求)

c - fgets() 无法正常工作