【问题标题】:How to break a while loop when it is false to a certain condition当某个条件为假时如何打破while循环
【发布时间】:2020-01-07 06:47:27
【问题描述】:

我正在尝试编写一个程序,如果我输入一个整数,程序会找出较大的数字并减去较小的数字。这部分,我明白了。

问题是,无限循环部分。

我尝试让 type in two integers 继续使用 while 循环打印,并在至少输入一个字符时让 break 继续打印。

例如,如果我输入2 @,它会中断。

但是我找不到在代码中获取break; 的写入位置,因此每当我输入一个字符时,它都会继续创建一个无限循环。

有没有办法在这段代码中创建一个中断?我虚心求教……

以下是我无法输入break 的代码 (顺便说一句,我在sizeof(i)==4 || sizeof(j)==4中设置条件的原因是为了让它只输入一个整数,因为整数的大小是4)

int main()
{   
    int i, j;
    int result;

    while (sizeof(i)==4 || sizeof(j)==4){
        printf("type in two integers : ");
        scanf("%d %d", &i, &j);
        if (i < j) {
            result = j - i;
        }
        else if (j < i){
            result = i - j;
        }

        printf("%d\n", result);
    }

    return 0;
}

底部代码是我尝试输入break但失败的代码(它一直在创建无限循环)...

int main()
{   
    int i, j;
    int result;

    while (sizeof(i)==4 || sizeof(j)==4){
        if (sizeof(i) == 4 || sizeof(j) == 4) {
            printf("type in two integers : ");
            scanf("%d %d", &i, &j);
            if (i < j) {
                result = j - i;
            }
            else if (j < i) {
                result = i - j;
            }

            printf("%d\n", result);
        }
        else
            break;
    }

    return 0;
}

这是我摆脱sizeof并使用while(1)的代码,尽管break不起作用这一事实并没有太大变化......

int main()
{   
    int i, j;
    int result;

    while (1){
            printf("type in two integers : ");
            scanf("%d %d", &i, &j);
            if (i < j) {
                result = j - i;
            }
            else if (j < i) {
                result = i - j;
            }

            printf("%d\n", result);
    }

    return 0;
}

【问题讨论】:

  • 试试while (2==scanf("%d %d", &amp;i, &amp;j)) 。如果我正确理解您的问题,它应该会有所帮助。

标签: c while-loop integer


【解决方案1】:

您不能使用sizeof(i) 进行运行时检查!这是一个 编译时 常量,在您的情况下(32 位整数)将始终评估为 4.

为了检查是否给出了两个有效整数,您可以检查scanf 函数的返回值(它给出了成功扫描的字段数):

#include <stdio.h>

int main()
{
    int i, j;
    int result;

    while (1) {
        printf("type in two integers : ");
        if (scanf("%d %d", &i, &j) != 2) break; // Break here if we didn't get two integers
        if (i < j) {
            result = j - i;
        }
        else if (j < i) {
            result = i - j;
        }

        printf("%d\n", result);
    }

    return 0;
}

请随时要求进一步澄清和/或解释。

【讨论】:

  • 哇!非常感谢你。如果不麻烦,请您在scanf("%d %d", &amp;i, &amp;j) != 2 上解释一下。更具体地说,为什么是2?这是因为 true & true == 1 & 1 == 1 + 1 == 2?
  • 正如我所说,scanf 返回它已成功读取的 值数。如果输入1 2,它将读取两个整数,并返回2(成功);如果您输入1 $,它将只读取一个整数并返回1(失败);同样,如果您输入“& 2”,它将返回0
  • 但是注意:使用scanf函数有很多危险!如果您输入2 0.1,它将成功读取两个整数(20),但下一轮将失败 - 因为. 字符留在输入缓冲区中。
【解决方案2】:

放弃无限循环的整个概念,在 if 中使用 break。
根据scanf()的返回值为循环创建一个条件,这实际上就是它的设计目的。

#include <stdio.h>

int main()
{   
    /* always init everything */
    int i=0, j=0;
    int result=0;

    printf("type in two integers : ");
    while (2==scanf("%d %d", &i, &j))
    {
        if (i < j) {
            result = j - i;
        }
        else /* removed second if, to have a meaningful result for i==j */
        {
            result = i - j;
        }

        printf("%d\n", result);
        printf("type in two integers : ");            
    }

    return 0;
}

我可能实际上将do {...} while (...) 与存储scanf() 的返回值的变量一起用于循环条件中。由于不必复制打印,我认为它更优雅,但我让它更接近您的代码结构。

您的代码上有更多 cmets:

  • 如 cmets 中所述,sizeof() 的工作方式与您想象的不同;它是静态的,在运行时不会改变,因此不能在循环条件中使用
  • 对于while (sizeof(i)==4 || sizeof(j)==4){if (sizeof(i) == 4 || sizeof(j) == 4){/* a */} else {/* b */},b 永远无法达到,因为whileif 的条件是相同的
  • 检查循环内 if 条件的可能结果,您将留下 i==j 未定义的结果并返回未初始化的值
  • 始终将所有变量初始化为习惯
  • 对于一个好的 MRE,包括包含行

根据您的要求,这里有一个临时替代方案的建议:

#include <stdio.h>

int main()
{   
    /* always init everything */
    int i=0, j=0;
    int result=0;
    int iScanned=0;

    do 
    {
        printf("type in two integers : ");
        iScanned=scanf("%d %d", &i, &j); /* keep the return value for loop */

        if (i < j) {
            result = j - i;
        }
        else /* removed second if, to have a meaningful result for i==j */
        {
            result = i - j;
        }

        if(2==iScanned) printf("%d\n", result); /* if to avoid awkward last output */
    } while (2==iScanned);

    return 0;
}

【讨论】:

  • 感谢您在我的代码中提供特定的 cmets 以及替代代码!另外,我想试试do {...} while (...)。如果不麻烦,是否可以使用此代码?所以如果我写的对,我可以匹配?
  • 我的荣幸。事实证明它没有我想象的那么优雅,因为我无法避免额外的if 以获得漂亮的输出。我仍然喜欢它比while 替代品略好,因为我更喜欢额外但直接的if 以使输出线加倍。在我看来/经验中,输出线比逻辑更有可能被改变(一旦测试)。现在,您的do-while 代码是否相似?
  • 注意,我同意@AdrianMole 对另一个答案的评论警告,这绝对同样适用于我的。更多关于 scanf 的陷阱可以在这篇非常有趣的文章中找到:sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html
猜你喜欢
  • 2021-08-02
  • 2019-10-26
  • 2020-07-21
  • 2011-02-08
  • 2020-05-31
  • 1970-01-01
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多