如何在while循环中的条件为假时打破循环?

3

我试图编写一个程序,如果我输入一个整数,程序会找出其中更大的数字并将较小的数字从中减去。我已经完成了这个部分。

问题是无限循环的部分。

我尝试使用while循环使输入两个整数不停地打印,并在至少输入一个字符时break

例如,如果我输入2 @,它就会退出。
但我找不到把break;放在代码中的正确位置,因此每当我输入一个字符时,它都会创建一个无限循环。
是否有任何方法在这段代码中添加break?我谦虚地请求建议...

以下是我无法放置 break的代码: (顺便说一下,我在while条件中使用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;
}

1
尝试使用 while (2==scanf("%d %d", &i, &j)) 语句。如果我正确理解了您的问题,它应该会有所帮助。 - Yunnosch
2个回答

3

你不能使用 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", &i, &j) != 2这部分进行更详细的解释呢?具体来说,为什么是2?这是因为true和true == 1和1 == 1 + 1 == 2吗? - Learner_15
1
就像我之前说的,scanf 函数会返回它成功读取的值的数量。如果你输入 1 2,它将读取两个整数,并返回 2(表示成功);如果你输入 1 $,它只会读取一个整数,并返回 1(表示失败);同样地,如果你输入 "& 2",它将返回 0 - Adrian Mole
2
但要注意:使用scanf函数存在许多危险!如果输入 2 0.1,它将成功读取两个整数(20),但下一次使用时会失败 - 因为.字符留在输入缓冲区中。 - Adrian Mole

3
放弃在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;
}

我会使用一个变量存储scanf()的返回值,在循环条件中使用do {...} while (...)。这样做更加优雅,避免了复制打印语句,但我保留了你的代码结构。
对于你的代码,以下是更多的评论:
  • 如注释所述,sizeof()的工作方式与您似乎认为的不同;它是静态的,不能在运行时改变,因此不能在循环条件中使用
  • while (sizeof(i)==4 || sizeof(j)==4){if (sizeof(i) == 4 || sizeof(j) == 4){/* a */} else {/* b */}中,b永远不可能被执行,因为whileif的条件完全相同
  • 检查循环内if条件的所有可能结果,你没有为i==j的情况指定结果,并且返回未初始化的值
  • 始终将所有变量初始化为一种习惯
  • 为一个良好的MRE包括包含行
根据你的要求,以下是使用do-while替代方案的建议:
#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;
}

感谢您对我的代码提出具体的评论以及提供另一种代码!此外,我想尝试一下do {...} while (...)。如果不麻烦的话,能否提供一个使用它的代码?这样我就可以检查我写的是否正确了。 - Learner_15
不用客气。结果发现它比我想象中的要简单,因为我无法避免额外的“if”来进行美化输出。我仍然更喜欢它比while循环更好一点,因为我更喜欢额外但直观的“if”而不是将输出行加倍。在我看来/经验中,输出行更容易被更改(一旦测试)。那么,你的 “do-while” 代码是否类似? - Yunnosch
1
注意,我同意@AdrianMole在另一个答案中的评论警告,这同样适用于我的回答。有关scanf陷阱的更多信息可以在这篇非常有趣的文章中找到:http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html - Yunnosch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接