【问题标题】:Using "continue" in while loop, skips over scanf("%d", var)在 while 循环中使用“继续”,跳过 scanf("%d", var)
【发布时间】:2016-09-11 05:47:13
【问题描述】:

所以我在我的 C 程序中使用了 Visual Studio。

while 循环以提示和 scanf 开始,如果用户输入非数字响应,则循环中的 switch/case 将变为默认值。这会打印一个错误并“继续”循环。

问题在于,当循环继续到下一次迭代时,它会完全跳过“scanf”,然后无限循环默认情况。我已经搜索了几个小时,但似乎找不到解决方案。

我的目标是跳过 switch/case 之后的代码,然后回到开头。任何帮助将不胜感激。

while (userInput != 'N' && userInput != 'n') {

    printf("Enter input coefficients a, b and c: "); // prompt user input
    scanf_s("%d %d %d", &a, &b, &c); // look for and store user input

    /* ----- Break up the quadratic formula into parts -----*/

    inSqRoot = (pow(b, 2) - (4.0 * a * c)); // b^2 - 4ac
    absInSqRoot = abs((pow(b, 2) - (4.0 * a * c))); // absolute value of b^2 - 4ac
    denom = 2.0 * a; // get denomiator 2.0 * a
    negB = -1.0 * b; // take negative of b

    /*------ Determine number of roots -------*/

    if (!isdigit(a) || !isdigit(b) || !isdigit(c)) {

        rootNum = 4;

    }  // end if

    else if (a == 0 && b == 0 && c == 0) {

        rootNum = 0;
    } // end if

    else if (inSqRoot == 0) {

        rootNum = 1;
    } // end if

    else if (inSqRoot > 0) {

        rootNum = 2;
    } // end if

    else if (inSqRoot < 0) {

        rootNum = 3;

    } // end if


    /*------ Begin switch case for rootNum ------*/

    switch (rootNum) {

    case 0: // no roots

        printf("The equation has no roots.\n");
        break;

    case 1: // one root

        root1 = (-b + sqrt(inSqRoot)) / denom;

        printf("The equation has one real root.\n");
        printf("The root is: %.4g\n", root1);
        break;

    case 2: // two roots

        root1 = (-b + sqrt(inSqRoot)) / denom;
        root2 = (-b - sqrt(inSqRoot)) / denom;

        printf("The equation has two real roots.\n");
        printf("The roots are: %.4g and %.4g\n", root1, root2);
        break;

    case 3: // imaginary roots

        printf("The equation has imaginary roots.\n");
        printf("The roots are: %.1g + %.4gi and %.1g - %.4gi \n", negB / denom, sqrt(absInSqRoot) / denom, negB / denom, sqrt(absInSqRoot) / denom);
        break;

    default:
        printf("ERROR: The given values are not valid for a quadratic equation.\n");
        continue;
    }

    printf("Enter Y if you want to continue or N to stop the program: ");
    scanf_s("%*c%c", &userInput);
    printf("\n");
}

【问题讨论】:

  • continue 表示“中断当前执行并从头开始循环代码”。所以它是循环的“短路”。另一方面,break 将退出循环块。在这里你可以简单地跳过conitinue 并且你的scanf_s 将被执行。
  • 然而,在case statemets 中,break 打破了当前case 而不是外部循环
  • 好吧,如果默认情况被激活,我的目标是跳过 switch case 之后的代码。然后回到顶部,要求用户重新输入整数值。
  • scanf_s("%d %d %d", &amp;a, &amp;b, &amp;c); 导致输入被读取为整数而不是 ascii 字符。所以调用isdigit(a) 没有意义,因为a 不是ASCII 字符。例如,如果用户输入“1”,那么a 的值将是 1 而不是 31('1' 的 ascii 字符)。在这种情况下,isdigit 将在您希望它为 true 时返回 false。
  • 这听起来像是一个荒谬的问题——但如果我的预感是正确的,那么它很快就会变得有意义。你有多确定 scanf_s 没有被调用?当您陷入无限循环时,您是否会偶然看到“输入输入系数 a、b 和 c:”重复打印?

标签: c


【解决方案1】:

scanf 实际上并没有被跳过,它只是一遍又一遍地读取相同的错误输入。您可以使用 scanf 的返回值来查看读取了多少个参数。在错误输入的情况下,它将小于 3。要刷新错误输入,您可以调用这样的函数

void flushInput() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}

并在默认情况下添加对 flushInput 的调用

default:
    printf("ERROR: The given values are not valid for a quadratic equation.\n");
    flushInput();
    continue;

【讨论】:

    【解决方案2】:

    一般来说,当涉及到用户输入时,读取和验证用户输入对于编写表现良好的应用程序至关重要。用户可能会提交不“完美”的输入,您的应用程序应该对此进行检查。

    scanf() 可能不是最好的选择,因为它是一个蒸汽输入,而不是控制台输入函数,并且不符合预期的方式:

    • 对空格和换行符一视同仁
    • 只有在读取并分配了所有变量或遇到文件结束符 (Ctrl+Z) 时才会返回。

    所以我的建议是改用控制台-I/0 功能,即gets()(或其“安全”形式gets_s())。这个行为符合预期,因为它准确读取整行文本,并在按下 Enter 时返回(scanf() 甚至可以从下一行读取参数)。

    然后使用sscanf(),它类似于scanf(),但改为从缓冲区读取变量,并返回读取和分配的变量数。您可以使用 "%d %d &d %s" 作为格式字符串,以检查用户是否输入了恰好 3 个变量,不少于甚至...更多(第四个变量将是一个虚拟字符串,仅使用如果用户提交乱码输入,则使 sscanf() 返回大于 3)。

    【讨论】:

      猜你喜欢
      • 2016-06-05
      • 2012-12-10
      • 2015-07-30
      • 2010-12-12
      • 2023-04-09
      • 2014-10-27
      • 2022-01-22
      相关资源
      最近更新 更多