我对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++;
}
答案 0 :(得分:4)
您忘记了NUL终止onClick(e, stateKey){
this.setState({[stateKey]: e.target.value});
}
。因此,您可以在复制期间调用未定义行为。使用以下代码获取输入:
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 */
答案 1 :(得分:3)
该问题根本与EOF
无关,代码中存在多个问题,导致潜在的不确定行为和不良副作用:
origin
数组末尾的字节。这是行为未定义的第一种情况。origin
未初始化,因此其内容不确定。从stdin
读取字节后,不要在其中存储空终止符。copy
函数中,您依靠空终止符停止复制循环,但是由于没有终止符存储在其中,因此在复制从stdin
读取的所有字节之后,您可以访问未初始化的内容。空终止符测试与while((to[i] = from[i]) != '\0')
中的赋值结合在一起。访问未初始化的数据具有未定义的行为。此外,您将继续从origin
进行读取,直到找到一个空终止符为止,如果最终读取结果超出了数组末尾,则会导致进一步的未定义行为,而在copied
末尾进行写入时甚至会导致更多不确定的行为。数组。copied
数组的所有10个元素。origin
偶然在末尾包含空字节,也可以防止copy
函数中未定义的行为。输出循环仍将输出有趣的字符,因为您不会在空终止符处停止,而是将其打印到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++;
}
答案 2 :(得分:1)
您将无条件输出数组的所有10个成员。
您可以通过在字母末尾附加常用的'\0'
来解决问题。
用
origin[i] = '\0';
读完后。
最后输出直到该标记,而不是所有内容
for(i = 0; copied[i]!='\0'; i++)
您可以假设数组足够大以保留输入(包括添加的'\0'
)。但是,您应该对此加以保护,例如,对任何循环使用双重条件,检查是否禁止访问最大允许的数组索引。
答案 3 :(得分:0)
您使用的是IDE(可能是CodeBlocks),该IDE在后续的IO操作之间使用页面缓冲区,这就是您真正获得输出的原因。
接下来,您将强制在循环输出中打印数组的所有十个元素,这是不好的编码习惯。
这个简单的代码片段可以帮助您
scanf("%10[^\n]s",input);
使用它来读取文件./youpro 感谢David C. Rankin在评论中提及错误。