C 语言分支与循环五例

C 语言分支与循环的基本语法并不难,已经有大量文章进行归纳总结,我这里就不再赘述。而我在学习分支与循环的过程中,发现一些重要的细节问题。特别是对于已经习惯了其他编程语言的同学,初次接触 C 语言,如果不注意区别,就特别容易出现这些问题。这里通过五个案例,来记录一下。

案例一

关键词:if 语句,条件,等于比较运算符,赋值表达式

#include <stdio.h>

int main()
{
    int x = 0;
    scanf("%d", &x);
    if (x = 5)	// error
    {
        printf("haha\n");
    }

    return 0;
}

注意这是一个错误案例。

程序本来的目的是:让用户输入一个整数,如果等于 5,则打印输出 “haha”。但是,在 if 语句的条件中,本来应该是 x == 5,结果写成了 x = 5,错将等于比较运算符 == 写成了赋值运算符 =。这就导致:无论用户输入什么,变量 x 都会被赋值为 5,然后整个赋值表达式返回值为 5 作为 if 语句的条件。由于条件非 0,被判定为“真”,条件语句中的代码块会固定被执行。

这里的错误不仅仅来源于错将等于比较运算符 == 写成了赋值运算符 =,同样也要注意到在 C 语言中“赋值”不仅仅是语句,还是一个“表达式”,是有返回值的。对于习惯了一些其他编程语言的人,在那里赋值仅仅是语句,不会有返回值,初次遇到 C 语言的这个特性,可能会出现这样的问题。

案例二

关键词:switch 语句,break 语句

#include <stdio.h>

int main()
{
    int day = 0;
    printf("Enter the day of a week: ");
    scanf("%d", &day);
    switch (day)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        printf("It is a weekday.\n");
    case 6:
    case 7:
        printf("It is weekend.\n");
    default:
        printf("invalid input\n");
    }

    return 0;
}

​注意这是一个错误案例。

程序本来的目的是:让用户输入一周的第几天,然后通过这个数字来判断这是周内还是周末;如果输入数字超过 7,则认为是不合理的输入。但照上面这样写,实际执行的结果却是:

Enter the day of a week: 5
It is a weekday.
It is weekend.  
invalid input

程序实现使用 switch 分支语句。本来只需要打印输出 “It is a weekday.”,结果把后面其他分支所有的代码都执行了。

这里需要注意的是,switch 语句中的 case <value>: 仅仅是一个标签,只代表如果匹配到这个值,程序会标签处开始执行。因此,如果我们想匹配时只执行这一小部分代码,需要在这个分支的结尾处加上 break 语句,用来跳出整个 switch 语句。位于最后的分支理论上是可以不用加 break 语句的。但在习惯上,为了减少思考成本,统一在所有分支下加上 break 语句,所以最后的 default 标签下,也加了 break 语句。最后正确的代码如下:

#include <stdio.h>

int main()
{
    int day = 0;
    printf("Enter the day of a week: ");
    scanf("%d", &day);
    switch (day)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        printf("It is a weekday.\n");
        break;
    case 6:
    case 7:
        printf("It is weekend.\n");
        break;
    default:
        printf("invalid input\n");
        break;
    }

    return 0;
}

案例三

关键词:for 循环,无限循环

#include <stdio.h>

int main()
{
    for (int i = 0; i < 10; ++i)
    {
        if (i = 5)	// error
        {
            printf("5\n");
        }
    }

    return 0;
}

注意这是一个错误案例。

程序本来的目的是:从数字 0 读到数字 9,如果读到数字 5,就打印输出 5。但是,这里犯了与案例一相同的一个错误,把 if 语句条件中的等于比较运算表达式 i == 5 错写成了赋值表达式 i = 5。所以条件必然成立,固定输出 5。同时,由于变量 i 被赋值为 5,循环体结束后 i 自增 1 值变成 6,必然满足下次继续进入循环的条件。于是,这里的 for 循环变成了无限循环。

这个案例本身没有什么实际意义,主要就是要说明 C 语言与其他语言在 for 循环上的区别。以 Python 为例,Python 的 for 循环要求指定一个可遍历的对象,该对象没有一个元素,循环就执行一次。由于可遍历对象中元素的个数是固定的,所以循环的次数几乎就是固定可预见的。Python 的 for 循环,语法和其意图是一致的。但是在 C 语言中,for 循环的本意是想实现指定次数的循环,但是 for 循环的语法却不会自动满足这一点。C 语言的 for 循环,在语法上本质仍然是 while 循环,它没有指定循环次数,而是指定了循环结束条件。只是在 while 循环上增加了一点点便利而已。

因此,在 C 语言中,我们需要格外留意 for 循环是否得到了正确的执行,是否达到了我们指定循环次数的目的。

案例四

关键词:do while 语句

#include <stdio.h>

// input:   an integer
// output:  number of digits of the intger
// 0 shoude be counted as having 1 digit
int main()
{
    int n = 0;
    int len = 0;
    scanf("%d", &n);
    do
    {
        ++len;
        n /= 10;
    } while (n);
    printf("%d\n", len);
    
    return 0;
}

这是一个正确的案例,可放心运行。

相比 while 语句和 for 语句,do while 语句的使用的频率会少很多。这里给出的是一个比较适用 do while 语句的场合。程序的目的是:用户输入一个整数,输出这个整数的位数;对于输入的 0,也需要输出位数为 1。

案例五

关键词:continue 语句,while 循环,for 循环

在本案例中,我们对比 continue 语句在 while 循环和在 for 循环中的表现。首先我们先看 continue 语句使用在 while 循环中的一个案例:

#include <stdio.h>

int main()
{
    int i = 1;
    while (i <= 10)
    {
        if (i == 5)
        {
            continue;
        }
        printf("%d\n", i);
        ++i;
    }

    return 0;
}

注意这是一个错误案例。

变量 i 等于 1、2、3、4 时,程序运行正常,通过四次循环,分别打印输 1、2、3、4。然后,出当变量 i 等于 5 时,会执行 continue 语句。continue 语句会跳过循环体中剩余的代码,后面的 ++i 没有得到执行,变量 i 保持值为 5。在下次进入循环时,由于 i 值为 5,又会继续执行 continue 语句。于是,程序进入无限循环。

对比 continue 语句在 for 循环中:

#include <stdio.h>

int main()
{
    for (int i = 1; i <= 10; ++i)
    {
        if (i == 5)
        {
            continue;
        }
        printf("%d\n", i);
    }

    return 0;
}

同样在变量 i 等于 5 时,会执行 continue 语句,跳过循环体中的剩余代码。但是,对于 for 循环,在执行下一次循环之前,会先执行 for 语句头部中的 ++i,这个不会被跳过。变量 i 会自增,值变为 6,这样就保证程序继续执行。程序最后运行的结果是,依次打印输出 1-10,但跳过 5 没有被输出。

前面的案例四,我们说明在 C 语言中,for 循环与 while 循环的本质是相同的。而在本案例中,我们也看到 for 循环在语法上也提供了一些特性,让我们能够更容易确保循环变量的调整得到执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值