1

在以下代码中, fprintf 没有打印到文件中,并且 printf 显示错误的输出:

#include<stdio.h>

 void main()
{  
    FILE *fp;  
    int d,w,t;
    fp = fopen("file.txt","r+");//already created file having value 10
    fscanf(fp,"%d",&d); 
    printf("%d",d);//print value 10
    t=ftell(fp);
    fseek(fp,t,SEEK_END);
    fprintf(fp,"%d",1000); // printing 1000 to the file
    fscanf(fp,"%d",&w);
    printf("%d",w); // this printf is still printing wrong value 12803
    fclose(fp);
    getch();
}
4

2 回答 2

1
#include<stdio.h>

 void main()

这是错误的;它应该是int main(void)。如果你有一本书告诉你使用void main(),它的作者对 C 不是很了解;得到一本更好的书。

{
    FILE *fp;
    int d,w,t;
    fp = fopen("file.txt","r+");//already created file having value 10

您需要检查fopen调用是否成功,如果失败则可能终止程序。

    fscanf(fp,"%d",&d);
    printf("%d",d);//print value 10

假设到目前为止一切顺利,这将打印10 没有换行符。如果您的程序有效,它的输出将是101000. 将“%d”更改为“%d\n”。

    t=ftell(fp);

t是文件中的当前位置,应该就在 之后10,所以它是从开始的 2 个字节。

    fseek(fp,t,SEEK_END);

现在您将文件指针重新定位到文件结尾之前的2 个字节。这没有任何意义。您最终相对于“10”的位置取决于其他内容file.txt(换行符?CR-LF?)

您可以保存返回的值ftell()并在稍后调用 时使用它fseek,但这只有在第三个参数是 时才有意义 SEEK_SET。所以你可能想要:

t = ftell(fp);
fseek(fp, t, SEEK_SET);

这不会改变你在文件中的位置,但它确实允许你从你一直在写入的文件中读取。

哦,并且ftell使用fseek价值观long,而不是int. 如果文件不是太大,您的程序(带有这些修复程序)可能会工作,但您确实应该声明tlong变量。

我还建议使用 , 和 之类的名称,d并使您的代码更难阅读。使用更长的描述性名称。想想你以外的其他人试图阅读和理解你的代码——或者你在一个月后阅读自己的代码,那时你已经忘记了代码是什么。wtd

通过这些更改,您当前的位置在file.txt should now be just after the10`。

    fprintf(fp,"%d",1000); // printing 1000 to the file

1000现在您在 之后立即打印10,所以现在文件包含101000,并且您当前的位置您写的最后一个字符之后。

    fscanf(fp,"%d",&w);

在这里,您尝试在写入文件后立即从文件中读取。但是你在文件的末尾,所以没有什么可读的。由于您没有检查fscanf(这会告诉您失败)的结果,所以没有w改变,

    printf("%d",w); // this printf is still printing wrong value 12803

同样,添加换行符会使输出更易于阅读。

    fclose(fp);
    getch();

getch()是一个特定于 Windows(和特定于 MSDOS)的函数,它在终止程序之前等待用户输入。如果你坚持使用它,如果我没记错的话,你需要#include <windows.h>. 如果编译器没有抱怨缺少getch.

}

概括:

如果你想读取和写入同一个打开的文件,你可以这样做——但是你需要调用一些定位函数,比如fseek 在读取和写入之间,或者在写入和读取之间。

您应该检查所有库调用返回的值。例如,如果file.txt不存在,您的程序会悄悄地忽略错误并继续尝试读取和写入文件,但结果未定义。(通常忽略printf 调用的结果,因为如果打印到标准输出失败,您无能为力,但无论如何查看结果是有启发性的。)

编写您的printf调用,以便输出可读。\n在每个输出行的末尾打印换行符 ( )。

阅读您使用的每个功能的文档。

让你的编译器警告你有问题的结构。请参阅编译器的文档以了解如何执行此操作。

于 2013-08-12T15:50:13.937 回答
0

fseek()您需要在同一文件中的读取和写入之间执行(或类似)。这不是所有实现中的严格要求,但它是可移植性所必需的。


编辑

好的,您的新版本具有:

t=ftell(fp);
fseek(fp,t,SEEK_END);

这在某些情况下可能有意义,但可能不是这个。我想你的意思是:

fseek(fp, 0, SEEK_CUR);

它相对于当前位置进行搜索,实际上没有移动到任何地方。

但是你没有得到的原因w==1000是在这两行之间:

fprintf(fp,"%d",1000); // printing 1000 to the file
fscanf(fp,"%d",&w);

您无需在此处搜索即可从写作过渡到阅读。w 如果不使用 seek 重新断言您想要的位置,您将无法完全确定您将尝试从文件中的哪个位置读取。

尝试:

t = ftell(fp);
fprintf(fp,"%d",1000); // printing 1000 to the file
fseek(fp, t, SEEK_SET);
fscanf(fp,"%d",&w);

顺便说一句,这段代码还有很多其他危险;就像那样,fprintf不会打印任何终止字符,因此在您写入的位置之后可能会有尾随数字(来自之前对其他值的写入,或其他),它们会附加到读入的值中w

于 2013-08-11T12:56:22.523 回答