我编写了一个程序,该程序将从其源文件读取并输出其内容。我的目的主要是学习如何使用I / O流和“ FILE”类型。我在Linux Ubuntu 14.04上的纯文本文档中编写了该程序,并使用终端来编译和运行该程序。这是终端从编译到完成的内容:
joseph@ubuntu:~/Desktop$ gcc test.c
joseph@ubuntu:~/Desktop$ ./a.out
File Opened
#include<stdio.h>
#define fileLocation ("/home/joseph/Desktop/test.c")
#define MAXREAD 1000
int main(void)
{
char fileContents[MAXREAD];
int i;
FILE *tf;
tf = fopen(fileLocation, "r");
printf("File Opened\n");
for(i=0;fileContents[i] != EOF; i++)
{
fileContents[i] = fgetc(tf);
printf("%c", fileContents[i]);
}
fclose(tf);
printf("\nFile Closed\n");
return 0;
}
************************************************************
File Closed
*符号实际上是Unicode(0 + FFFD:替换字符),但我似乎无法键入。
我的问题是,为什么它不以最后一个大括号结束程序,而是打印一堆替换字符?
循环中的顺序不正确。在存储和打印字符值之前,应先检查EOF 。您还应该确保不超出数组边界。
int main(void)
{
char fileContents[MAXREAD];
int i, c;
FILE *tf = fopen(fileLocation, "r");
if (tf == NULL)
{
perror(fileLocation);
return EXIT_FAILURE;
}
printf("File Opened\n");
for (i=0; i < MAXREAD && (c = fgetc(tf)) != EOF; ++i)
{
fileContents[i] = c;
fputc(fileContents[i], stdout);
}
fclose(tf);
printf("\nFile Closed\n");
return 0;
}
您的代码版本包括在中打印错误存储的EOF char
(这本身就是另一个问题,但是可以通过不首先存储来避免)。但这远没有结束您的困境。您继续进行for循环的条件逻辑是错误的。实际上,由于您从未进行初始化fileContents[]
,因此实际上会调用未定义的行为。每次迭代时,您都在检查尚未写入或尚未初始化的数组插槽。继续阅读如何/为什么。
为什么要继续打印?
fileContents[i] != EOF
在每次循环迭代之前对控制表达式进行求值。增量表达式在每次迭代之后但在对控制条件进行下一次评估之前i++
执行。从标准:
该声明
for ( clause-1 ; expression-2 ; expression-3 ) statement
其行为如下:表达式
expression-2
是在每次执行循环主体之前求值的控制表达式。expression-3
每次执行循环主体后,该表达式都将被评估为void表达式。如果clause-1
是声明,则它声明的所有标识符的范围是声明的其余部分和整个循环,包括其他两个表达式;在第一次对控制表达式求值之前按执行顺序达到它。如果clause-1
是表达式,则在对控制表达式进行第一次评估之前将其评估为空表达式。
坦白地说,您fileContents[i]
从未保存过的EOF不会被检查,因为i
在下一次评估之前会增加。从上面的描述中可以理解。这就是简单循环的原因:
for (i=0; i<N; ++i)
dostuff;
与退出i < N
是假的。除非有不可预见的修改dostuff
,否则循环将以终止i = N
。
同样,评估在增量步骤之后完成,因此在您的情况下:
for(i=0; fileContents[i] != EOF; i++)
fileContents[i] != EOF
每次进入循环主体之前都要对控制表达式进行求值。增量表达式发生在循环体之后,但在下一个对control-expression的求值之前。在循环体内,您将存储EOF
在以当前值索引的插槽中i
。然后,主体完成,i
增加,然后您才检查没有写入任何内容的插槽(尚未)。这种情况一直持续到某个点,如果您(不幸)EOF
在新近更新的i
索引中发现了一个等效值。这样您就终止了(但很可能在那之前很久就崩溃了)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句