【问题标题】:Read and write from file in C langage [closed]用C语言读写文件[关闭]
【发布时间】:2017-04-07 20:15:33
【问题描述】:

请有人可以为我解释为什么这个程序不起作用? 我正在尝试使用r+ 从文件中读取和写入。文件test.txt 存在,写入正确执行。但是,读取不起作用。

int main() {

    FILE* fichier = NULL;
    int age, TAILLE_MAX=10;
    char chaine[TAILLE_MAX];

    fichier = fopen("test.txt", "r+");
    if (fichier != NULL)
    {

        printf("give your age ? ");
        scanf("%d", &age);
        fprintf(fichier, "Hello you have %d year old", age);

        while (fgets(chaine, TAILLE_MAX, fichier) != NULL)
        {
            printf("%s", chaine); //does not print
        }fclose(fichier);
    }

    return 0;
}

不起作用我的意思是它不显示任何东西!即使文件包含一些你有...岁的句子。没有错误。只是程序不打印文件的内容

【问题讨论】:

  • 尝试从文件读取时出现任何错误? “阅读不起作用”是什么意思?
  • “不起作用”不是问题描述。见minimal reproducible example
  • 它是正常退出,还是出现错误消息/崩溃?
  • 尝试在 while 循环之前执行 fseek(fichier, 0, SEEK_SET);。它有什么改变吗?
  • @Mehdi fseek 将光标设置为您要在文件中读取或写入的位置。由于您已写入文件,因此您的光标在您写入的内容之后。通过执行fseek,您将光标设置回文件的开头,以读取您刚刚写的内容。

标签: c file fgets


【解决方案1】:

您正在同时写入和读取文件, 这不是好的做法, 但是您的代码不起作用的原因是因为缓冲。 fprintf(fichier, "Hello you have %d year old", age); 可能在您的 fclose(fichier) 声明发生之前不会发生。 我将这两个语句添加到您的代码中,见下文。 同样,一旦您执行fprintf,您的文件指针fichier 不在文件末尾,这是您尝试做的下一件事的错误位置,即读取您刚刚写的age 数字,所以您有以某种方式将文件指针fichier 移回 - 我刚刚使用了rewind,如果test.txt 是一个新创建的文件,它将起作用。否则,您将需要某种方法将文件指针 fichier 向后移动,以便阅读您刚刚写的内容。

int main() {

FILE* fichier = NULL;
int age, TAILLE_MAX=10;
char chaine[TAILLE_MAX];

fichier = fopen("test.txt", "r+");
if (fichier != NULL)
{

    printf("give your age ? ");
    scanf("%d", &age);
    fprintf(fichier, "Hello you have %d year old", age);

    fflush( fichier );  /* force  write to FILE */
    rewind( fichier );  /* rewind FILE pointer to beginning */

    while (fgets(chaine, TAILLE_MAX, fichier) != NULL)
    {
        printf("%s", chaine); //does not print
    }
}
fclose(fichier);
return 0;
}

在您的原始代码中,声明

while (fgets(chaine, TAILLE_MAX, fichier) != NULL)

无法读取任何内容并返回 NULL,因此printf("%s", chaine); 不会发生。这是因为输出缓冲和 fprintf() 语句在您认为应该发生的时候没有发生。

这个输出缓冲是正常的,如果你想在那个确切的时刻发生printf,那么你需要使用fflush() 阅读此处了解更多信息:Why does printf not flush after the call unless a newline is in the format string?

【讨论】:

  • 如果您使用相同的FILE*,则无需刷新。倒带时,fgets() 将使用未刷新的输出缓冲区。
  • 很好,如果他使用fseek 而不是rewind 会一样。我最初用fflush写它来说明正在发生的主要问题,然后在使用简单的fflush之后意识到文件指针位置的第二个问题。
  • 是的,是一样的。所有stdio 函数共享缓冲区。
【解决方案2】:

问题是您在写入文件句柄后尝试从文件句柄中读取。

fichier 就像编辑器中的光标,它在文件中只有一个位置。当您使用r+ 打开文件时,fichier 位于文件的开头。当您打印到fichier 时,它会覆盖文件开头的任何内容。然后,当您尝试读取时,它会从打印中断的位置开始读取。

例如,如果我以 test.txt 开头,其中包含一些文本,具体来说将超过将被打印出来的内容。

$ cat test.txt
First line
Second line
Third line

然后我运行程序。

$ ./test
give your age ? 41
rd line

注意它打印了rd line,因为那是它写Hello you have 41 year old之后剩下的东西。

$ cat test.txt
Hello you have 41 year oldrd line

我不确定您要完成什么,但您可能需要 fseek 将光标移动到正确的位置。


作为旁注,将整个程序包装在 if (fichier != NULL) 中很尴尬。如果文件没有打开,你没有错误消息,它会悄悄地神秘地什么都不做。相反,检查错误,显示信息性消息,然后退出程序。

#include <string.h>
#include <errno.h>
#include <stdlib.h>

char file[] = "test.txt";
FILE *fichier = fopen(file, "r+");
if (fichier == NULL) {
    fprintf(stderr, "Could not open '%s' for r+: %s\n", file, strerror(errno));
    exit(1);
}

这被称为early exit,它使代码变得非常简单。通过立即处理错误,代码可以跟随happy path,而无需总是嵌套在条件中。

【讨论】:

    猜你喜欢
    • 2013-05-23
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    • 2022-01-21
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多