c - 通过 C 中的 EOF 停止 While 循环
问题描述
我只是在学习 C,但我的基本理解遇到了问题。我试图做的是打印 X 与输入相同的次数。输入都在同一行,我现在工作得很好。
我遇到的问题是结束程序。我想要做的是在读取该行后让程序结束。
示例:输入 1 2 3
输出:
X
XX
XXX
计划结束
现在我只是永远在循环中......
任何人都可以尝试解释我在这里缺少的概念吗?我确信这可能是语法问题,但我真的想了解我的逻辑在哪里出错。
EOF 在这种情况下如何工作?
int main(void)
{
int i;
int n = 0;
while ( n != EOF ) {
scanf( "%d",&n );
if (n == EOF){
break;
}
for ( i=0; i<n; i++){
printf("X");
}
printf("\n");
}
}
解决方案
你可以做你想做的事,而不是你正在做的事情......
对于初学者,您必须始终验证scanf
. 您必须防范三种情况:
EOF
返回 - 表示在遇到任何输入之前已经到达输入的结尾(这可以由用户通过按下Ctrl+d(或Ctrl+z在 windows 1上)手动生成);返回的转换说明符数少于此数,表示匹配或输入失败(发生这种情况时,从流中提取字符会停止,您有责任在下次尝试读取之前删除任何无关字符);或者
返回等于转换说明符的数量——表示数据已转换并存储在您提供的每个变量中;
此外,您必须验证收到的输入是否在可接受的范围内。(您可能不希望输入负值。
对于您的代码,您可以简单地验证上面的 (3) 并退出 on EOF
,或者匹配或输入失败——因为您只读取 1 类数据 ( integers
) 并且可以在任何失败时退出。
但这并不能解决你的问题。解决此问题的正确方法是一次读取一行数据(使用fgets
或 POSIX getline
),然后通过重复调用解析数据行中的每个整数值,strtol
并利用其endptr
参数沿着整行工作. (关于它的正确使用有很多关于 SO 的例子)
但是,您也可以通过在读取每个字符后简单地检查下一个字符来做您想做的事情int
,getchar()
如果是'\n'
,那么您的读取已完成,否则您需要将字符放回使用并验证放回成功通过什么方式?(提示:检查返回——每个 C 库函数的返回都清楚地描述在它的关联中——使用它们stdin
ungetc
man page
:)
总而言之,您可以执行以下操作:
#include <stdio.h>
int main (void) {
int i, n;
printf ("input: ");
while (scanf ("%d", &n) == 1) { /* validate the 'return' of scanf */
if (n < 0) { /* validate n not negative */
fprintf (stderr, "error, input cannot be negative.\n");
return 1;
}
for (i = 0; i < n; i++) /* then loop that number of times */
putchar ('X'); /* don't printf 1-char, use putchar */
putchar ('\n'); /* tidy up with newline */
i = getchar(); /* read next char in stdin */
if (i == '\n') /* if end of line - break (done) */
break;
else if (ungetc (i, stdin) != i) { /* validate putting it back */
fprintf (stderr, "error: putting char back in stdin.\n");
return 1;
}
}
return 0;
}
示例使用/输出
$ ./bin/output_x
input: 1 2 3
X
XX
XXX
或者
$ ./bin/output_x
input: 7 1 1 5 1 1 1
XXXXXXX
X
X
XXXXX
X
X
X
如果您还有其他问题,请仔细查看并告诉我。
脚注
推荐阅读
- java - 为什么我的 IntelliJ IDEA 每次运行时都会显示致命错误?
- java - JavaFX 3D - 是否可以在 DrawMode.Line 中更改 Line 的宽度?
- java - 使用 Spring Boot 将 @WebInitParam 中的值外部化
- c++ - 没有非免费且没有 gpl 的 FFMPEG 编译无法正常工作
- python - 当可能发生多个相同类型的异常时如何正确处理异常
- sapui5 - ComboBox 值未显示在 XML 视图中
- php - Laravel:当值与上一个值不同时如何移动新行,刀片中的foreach
- python - 参考单维列表的python异常行为中的列表
- java - 我们可以使用“可选”在 Groovy 中进行空检查吗
- amazon-web-services - 向 EC2 自动扩展组添加容量的 AWS CloudWatch 警报一直处于警报状态