[英]How to properly using EOF?
我对EOF有疑问。
首先,我正在编写一个简单的程序来处理/打印用户的输入。
但是,程序也会在输出中复制EOF。
例如,我的操作系统是Window,当我按顺序输入(Enter - > cntrl + z - > Enter)时,我的EOF正常工作。 如果我输入“Hello”+ Enter + EOF组合键,输出将在复制的用户输入结尾处打印出奇怪的字母('?')。
我怎么能摆脱'?' 在输出的最后,为什么会发生?
#include <stdio.h>
void copy(char to[], char from[]);
main()
{
int i;
int c;
char origin[10];
char copied[10];
for(i = 0; (c = getchar()) != EOF; ++i)
{
origin[i] = c;
}
copy(copied, origin);
for(i = 0; i < 10; i++)
putchar(copied[i]);
}
void copy(char to[], char from[])
{
int i;
i = 0;
while((to[i] = from[i]) != '\0')
i++;
}
你忘了NUL终止origin
。 因此,您在复制期间调用未定义的行为。 使用以下代码来获取输入:
for(i = 0; i < 9 && (c = getchar()) != EOF; ++i) /* `i < 9` to prevent array overruns */
{
origin[i] = c;
}
origin[i] = '\0'; /* NUL-terminate your string */
同时将打印代码更改为:
for(i = 0; copied[i] != '\0'; i++) /* Print until a NUL-terminator */
putchar(copied[i]);
问题根本与EOF
无关,您的代码中存在多个问题,导致潜在的未定义行为和不必要的副作用:
origin
数组的末尾之外。 这是未定义行为的第一种情况。 origin
是未初始化的,因此其内容是不确定的。 在从stdin
读取的字节之后,不存储空终止符。 copy
函数中,您依赖空终止符来停止复制循环,但由于没有存储复制循环,因此在复制从stdin
读取的所有字节后,您将访问未初始化的内容。 null终止符测试与while((to[i] = from[i]) != '\\0')
的赋值相结合。 访问未初始化的数据具有未定义的行为。 此外,您继续从origin
读取,直到找到空终止符,如果最终读取超出数组末尾,则会导致进一步的未定义行为,当写入超出copied
数组末尾时更是如此。 copied
数组的所有10个元素。 origin
可能在最后包含空字节,从而防止了copy
函数中的未定义行为。 输出循环仍然会输出有趣的字符,因为您不会在null终止符处停止,而是将其打印到stdout
,并在您在此之后copied
结束时读取未初始化的内容时再次具有未定义的行为。 main
原型是int main(void)
。 您使用的语法没有返回类型,在70年代和80年代很常见,但现在已经过时,不应再使用了。 这是一个更正版本:
#include <stdio.h>
void copy(char to[], char from[]);
int main(void) {
int i;
int c;
char origin[10];
char copied[10];
for (i = 0; i < 10 - 1 && (c = getchar()) != EOF; i++) {
origin[i] = c;
}
origin[i] = '\0';
copy(copied, origin);
for (i = 0; copied[i] != '\0'; i++) {
putchar(copied[i]);
}
return 0;
}
void copy(char to[], char from[]) {
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
i++;
}
您无条件地输出阵列的所有10个成员。
您可以通过在字母末尾附加经常使用的'\\0'
来输出。
有了
origin[i] = '\0';
读完后。
最后输出直到那个标记,而不是一切
for(i = 0; copied[i]!='\0'; i++)
这样可以保证阵列足够大以保持输入(包括添加的'\\0'
)。 但是,您应该对此进行保护,例如,通过对任何循环使用双重条件,检查是否允许访问beyound允许的最高数组索引。
您正在使用IDE(可能是CodeBlocks),它在后续IO操作之间使用页面缓冲区,这就是您实际获得输出的原因。
接下来,您将强制在输出for循环中打印数组的所有十个元素,这是错误的编码实践。
这个简单的代码片段可以帮到你
scanf("%10[^\n]s",input);
用它来读取文件./youpro <file_name_where_to_fetch_input中的输入
感谢David C. Rankin在评论中提到错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.