我的程序的一些背景知识。我要求用户输入两种不同颜色的水晶坐标。这将保存在一个结构中,然后写入文件,稍后由程序读回(函数尚未写入)。
我看过论坛和博客,但我似乎只找到与字符数组相关的结果,而我使用的是int数组。
我的代码正常工作,直到将数据写入文件。 (这是代码片段)
char fname[20];
FILE *fp;
int loop;
struct coord{
int x;
int y;
};
for(loop=0;loop<3;loop++){
printf("Enter MAGENTA X coordinate: \n");
scanf("%2d",&mg[loop].x);
printf("Enter MAGENTA Y coordinate: \n");
scanf("%2d",&mg[loop].y);
printf("\n\n");
}
for(loop=0;loop<3;loop++){
printf("Enter YELLOW X coordinate: \n");
scanf("%2d",&ylw[loop].x);
printf("Enter YELLOW Y coordinate: \n");
scanf("%2d",&ylw[loop].y);
printf("\n\n");
}
clrscr();
printf("\nDetail entered:");
printf("\n\n\tMagenta\t\tYellow\n");
for(loop=0;loop<3;loop++){
printf("\tx %d,%d y\tx %d,%d y\n",mg[loop].x,mg[loop].y,ylw[loop].x,mg[loop].y);
}
printf("\n\nPlease save your data. Enter file name: ");
gets(fname);
fp=fopen(fname,"w");
for(loop=0;loop<3;loop++){
fprintf(fp,"%d,%d ",mg[loop].x,mg[loop].y);
fprintf(fp,"%d,%d ",ylw[loop].x,ylw[loop].y);
}
fclose(fp);
提前谢谢。
答案 0 :(得分:0)
将数据写入文件的方式没有任何问题(除了您应该检查fopen
的返回值之外。)
您的问题来自stdin
的数据输入。首先,您使用scanf
读取一堆坐标。 scanf
不是基于行的格式;它像任何其他白色空间一样对待新行字符。
然后你使用gets
,你真的不应该 - 使用fgets
代替,因为它允许你指定一个最大缓冲区大小,这样你就不会溢出20的缓冲区。 / p>
好吧,假设您使用fgets
,这是一种基于行的格式。混合scanf
和fgets
时必须小心,因为它们的工作方式不同。此外,控制台的输入通常会被缓冲,直到下一个换行符全部刷新为止,这会在屏幕上看到的内容与程序处理输入之间产生差异。
假设您使用scanf
读取两个数字,然后使用fgets
读取文件名。您的输入如下所示:
1 2 \n 5 1 \n d a t a . t x t
a a b b b c
读取第一个数字后,输入标记位于换行符之前的数字之后。在使用scanf
读取numbners之前,"%d"
会跳过空格,因此读入第二个数字,但同样,输入在换行符之前停止。然后你读了fgets
的一行,并读到下一行的所有内容,这一切都没有。实际的文件名将由下一个扫描函数读取,但没有,所以它被丢弃。
(那就是你的str != NULL is coming from: it's an assertion that has failed within
fopen`。这是编译器所做的事情。当你运行程序时,它已经被编译了。运行时库对编译时无法知道的条件进行错误检查。)
(更糟糕的是:fgets
,与gets
不同,在读取字符串后保留换行符。你应该删除那个以及可能的其他前导和尾随空格。否则你最终会文件名中包含换行符,这并不好笑。)
无论如何,你怎么能解决这个问题?使用尾随空格将scanf
格式从"%d"
更改为"%d "
。 “空间”具有scanf
的含义:读取任何数量的空白区域。
或者,您可以坚持scanf
并使用scanf("%19s ", filename)
阅读您的电子名称。这样做的好处是可以读取一个没有任何空格的字符串。
据报道,您已经通过在读取文件名之前调用fflush(stdin)
来解决此问题。 fflush
对输入流的行为取决于实现,并且不受标准保证。如果它适合你,请保留它。