【问题标题】:C while loop extra iterationC while循环额外迭代
【发布时间】:2015-07-31 06:52:12
【问题描述】:

我正在尝试对 scanf 函数进行输入验证。我已经修复了输入以忽略空格(“%c....”)。

谁能看到我做错了什么?

#include <stdio.h>
#include <stdlib.h>

int main() {

  char c1, c2, c3;
  int k, done = 0;
  float x;
  double y;

  do {
    printf("\n%s\n%s\n%s\n%s", "Input the following: three characters,", " an int,", " a float,", " and a double: \n");
    if(scanf(" %c%c%c%d%f%lf", &c1, &c2, &c3, &k, &x, &y) == 6){
      printf("\nHere is the data that you typed in: \n");
      printf("%3c%3c%3c%5d%17e%17e\n\n", c1, c2, c3, k, x, y);
      done = 1;
    } else {
      printf("Invalid input!");
    }
  } while (done != 0);

  return EXIT_SUCCESS;
}

【问题讨论】:

  • 额外迭代是什么意思?
  • 在某些情况下,您也可以使用while (true) { .. break; } 构造来避免“停止变量”,例如这种情况。
  • 如果您需要至少一次迭代,请使用 do...while 循环。
  • 当问“有什么问题”时,你应该说为什么你认为有问题;包括错误/警告消息(如果有),以及程序是否运行;然后是你给它的输入、预期输出和实际输出。
  • 抱歉大家没有进一步解释(当我问这个问题时,我在底部添加了一个解释,但由于某种原因它被删除了)。代码的目的是循环直到提供正确的输入。然而,即使我给了它正确的输入,结果也会显示出来,程序会再次循环。

标签: c while-loop iteration


【解决方案1】:

首先变量done 没有被初始化并且有一个不确定的值

int k, done;
//...
while(done != 1){

你必须像这样初始化它

int k, done = 0;

但是最好写一个更合适的循环。那是使用 do-while 循环而不是 while 循环。例如

int done = 0;
//...

do
{
    printf("\n%s\n%s\n%s\n%s", "Input the following: three characters,", " an int,", " a float,", " and a double: \n");
    if(scanf(" %c%c%c%d%f%lf", &c1, &c2, &c3, &k, &x, &y) == 6){
      printf("\nHere is the data that you typed in: \n");
      printf("%3c%3c%3c%5d%17e%17e\n\n", c1, c2, c3, k, x, y);
      done = 1;
    } else {
      printf("Invalid input!");
    }
} while ( done != 1 );

其次,在 scanf 调用中,您应该为格式说明符 %c 指定 balnks

例如

    if(scanf(" %c %c %c%d%f%lf", &c1, &c2, &c3, &k, &x, &y) == 6){

【讨论】:

  • 感谢您的回复。我决定采纳你的建议并使用 Do-While 循环。 (至于 %c 修复,我是根据其他答案的建议完成的,我可以在网上找到一个。)但是,这并不能解决循环执行额外时间的潜在问题。是否有可能我的 if 验证语句是错误的? (一旦我输入了正确的值类型,它就会输出,然后再次循环回到函数中)
  • @Ashley Rowland do-while 循环中的条件应该是 while (done != 1)。 ;
【解决方案2】:

您忘记初始化变量。至少 done 应该被初始化为不是 1 的东西。

【讨论】:

    【解决方案3】:

    您忘记读取并丢弃无效输入行的其余部分。添加 e。 g.

            scanf("%*[^\n]%*c");
    

    else 块中。

    【讨论】:

    • 一般来说这个模式实际上是行不通的,因为%[如果匹配零个字符就会失败并停止读取,所以在这种情况下换行符会留在缓冲区中。但是,由于 OP 总是通过丢弃空格开始读取下一行,因此在这种情况下它将起作用。一般情况可由scanf("%*[^\n]"); scanf("%*c");处理
    • 这似乎类似于忽略空格。如果我错了,请纠正我(我是 C 新手),但你不能将 scanf 函数更改为 scanf ("%c") 以便扫描仪知道忽略空格吗? (我不确定这是否是您的评论的意思)
    • 他的意思是我的建议不会丢弃输入缓冲区中留下的唯一\n(这是正确的,但您的格式字符串不会发生)。这两种模式的目的主要不是忽略空格,而是忽略(丢弃)从您的scanf() 停止点开始留在缓冲区中的其余无效输入。考虑输入行abcd1 2 3 - 您的程序的scanf() 在c1 中读取a,在c2 中读取b,在c3 中读取c,然后因为d 无法转换为整数而停止,返回3 并离开@ 987654333@ 在缓冲区中;在循环的下一次循环中,它在 c1 中读取 d