美文网首页
C语言快速入门 - 控制语句

C语言快速入门 - 控制语句

作者: Void_Caller | 来源:发表于2019-08-20 10:42 被阅读0次

    目录

    什么是控制语句

    回顾我们之前的程序,你会发现,我们的程序一直都是从上到下,一行接着一行执行的,并不能根据我们的意愿改变执行顺序,但是控制语句却有着这个功能。本文,就将介绍控制语句

    if...else

    我们把if翻译成中文,那他的意思便是如果,也就是根据我们的条件来执行相应的语句。

    例子:

    #include <stdio.h>
    
    int main()
    {
        int a = 0;
        scanf("%d",&a);
        if (a != 0)
        {
            printf("You get something!\n");
        } else {
            printf("nothing!\n");
        }
        return 0;
    }
    

    之前,大家在学运算符的时候学到过==的运算符,所以在这里这个整个语句的意思就是:假如a的值不是0,那么我们就输出You get something!

    那么下面那个else又是什么意思呢?把它翻译成中文,那就是其他的意思,也就是说:假如a的值10,那么我们就输出nothing!

    所以if的格式就是这样的:

    if ([逻辑表达式])
    {
        // 逻辑表达式为 真 的时候做的一些事
    } else {
        // 逻辑表达式为 假 的时候做的一些事
    }
    

    if后面括号里跟的是一个逻辑表达式,根据上一节我们对它的理解来说(忘了就看一下),除了0是以外,其他任何一个数字都是,也就是说,只要这个逻辑表达式不等于0,那它就会执行下面大括号里的值。

    所以我们就可以这样来简写:

    if (a)
    {
        printf("You get something!\n");
    } else {
        printf("nothing!\n");
    }
    

    这样的效果是一样的。

    其实,我们还能再简写。

    我们观察一下main函数,你会发现它也有一个大括号,我们写的东西都在这个里面,其实if的大括号也是这样的作用,他就是把一堆要执行的语句囊括在其中的。但是我们这个例子就只有一句话,而不是一大堆,所以其实我们可以把它去掉,就像下面这样:

    if (a) printf("You get something!\n");
    else printf("nothing!\n");
    

    当然,else也不是必要的。所以下面那么写也是可以的:

    if (a) printf("You get something!\n");
    

    或者:

    if (a)
    {
        printf("You get something!\n");
    }
    

    其实,组合起来也是有的:

    if (a == 1)
    {
        printf("a = 1\n");
    } else
    {
        if (a == 2) printf("a = 2\n");
    } 
    

    也可以外面:

    if (a == 1)
    {
        printf("a = 1\n");
    } else if (a == 2)
    {
        printf("a = 2\n");
    } 
    

    反正挺自由的。

    最后,我们再来谈谈这个大括号。

    作用域

    大括号也不能直接叫它大括号吧,它也有名字的,那就是我们的标题——作用域

    我们还是先来看一段例子:

    #include <stdio.h>
    
    int main()
    {
        int a = 0;
        scanf("%d",&a);
        if (a)
        {
            int b = 1;
            printf("a = %d, b = %d\n", a, b);
        } else {
            int b = 2;
            printf("a = %d, b = %d\n", a, b);
        }
        // printf("%d", b); // 这句话错误!!
        return 0;
    }
    

    我们可以观察到,每个大括号里都定义了一个名叫b的变量,照道理来说是不能定义名字一样的变量的,但是这边为啥又可以了呢?
    原因就在于,他们是属于不同的作用域的,他们之间没有联系的。所以,上面的b归上面,下面的归下面。

    那a为什么能用呢?因为a所在的这个作用域是属于main函数的整个作用域的,自作用域可以使用父作用域里定义的变量。但是父作用域用不了子作用域里的变量,也就是例子中最后一句话错误的原因。

    这个概念和数学里的集合有点像,理解起来也不是很复杂的。

    goto

    我们先翻译一下goto是什么意思吧。这其实是两个词的组合,goto,所以他的意思就是去一个地方,所以我们在程序中就可以运用goto来进行跳转从一个语句跳转到另一个语句,而不是规规矩矩按顺序从上到下执行。

    但是具体跳转到哪里呢?跳转总要有目的地吧,这里就有与一个叫标签的概念了。

    我们先来看一段例子。

    #include <stdio.h>
    
    int main()
    {
        printf("Hello Control!\n");
        int i = 0;
    mLabel:
        printf("Times: %d.\n", i);
        i ++;
        if (i < 5) goto mLabel;
        return 0;
    }
    
    • mLabel就是那个标签,一个标签由一个标签名和一个:组成,其命名规则和变量命名规则一样。

    • 当程序从上到下运行时,遇到标签之后并不会做什么,而是跳过它,继续执行下面的语句。

    • 当程序执行的时候遇到了goto,那就会跳转到goto后面的标签所在的位置,然后继续执行标签下面的语句们,也就是例子中的printf("Times: %d.\n", i);

    测试下这个程序:

    输出

    Hello Control!
    Times: 0.
    Times: 1.
    Times: 2.
    Times: 3.
    Times: 4.

    switch...case

    我们设想一下,假如说一个变量有很多种可能性,而你的被要求把这么多种可能性都判断一遍,那么我们可以用if语句来实现:

    #include <stdio.h>
    
    int main()
    {
        int a = 0;
        scanf("%d",&a);
        if (a == 1)
        {
            printf("%d\n", a);
            a = 2;
        } else if (a == 2)
        {
            printf("%d\n", a);
            a = 3;
        } else if (a == 3)
        {
            printf("%d\n", a);
            a = 4;
        } else if (a == 4)
        {
            printf("%d\n", a);
            a = 5;
        } else if (a == 5)
        {
            printf("%d\n", a);
            a = 6;
        } else if (a == 6)
        {
            printf("%d\n", a);
            a = 7;
        } else if (a == 7)
        {
            printf("%d\n", a);
            a = 8;
        }
        return 0;
    }
    

    这样,就可以针对不同的情况来实现不同的功能了(上文例子的这个功能其实完全可以不用这么实现,但是我是为了更直观的展示使用if判断多种情况)。

    这个程序里,只要我们输入[1,7]内的数字,就可以输出它,并让a的值等于输入值+1。

    这里我还将展示一种错误的写法:

    #include <stdio.h>
    
    int main()
    {
        int a = 0;
        scanf("%d",&a);
        if (a == 1)
        {
            printf("%d\n", a);
            a = 2;
        }
        if (a == 2)
        {
            printf("%d\n", a);
            a = 3;
        }
        if (a == 3)
        {
            printf("%d\n", a);
            a = 4;
        }
        if (a == 4)
        {
            printf("%d\n", a);
            a = 5;
        }
        if (a == 5)
        {
            printf("%d\n", a);
            a = 6;
        }
        if (a == 6)
        {
            printf("%d\n", a);
            a = 7;
        }
        if (a == 7)
        {
            printf("%d\n", a);
            a = 8;
        }
        return 0;
    }
    

    注意观察,这边我把所有的else都去掉了,由于程序是按顺序执行下去的,所以,如果我们如果输了一个1,那它会把后面所有的234567全都输出出来的,和我们要的功能就相背了。

    但不管怎么说,如果你写对了,这代码也太麻烦了吧,所以switch...case语句应运而生!

    现在我们就把这个正确的例子改写为switch...case版本吧:

    #include <stdio.h>
    
    int main()
    {
        int a = 0;
        scanf("%d",&a);
        switch (a) {
            case 1:
                printf("%d\n", a);
                a = 2;
                break;
            case 2:
                printf("%d\n", a);
                a = 3;
                break;
            case 3:
                printf("%d\n", a);
                a = 4;
                break;
            case 4:
                printf("%d\n", a);
                a = 5;
                break;
            case 5:
                printf("%d\n", a);
                a = 6;
                break;
            case 6:
                printf("%d\n", a);
                a = 7;
                break;
            case 7:
                printf("%d\n", a);
                a = 8;
                break;
            default:
                break;
        }
        return 0;
    }
    

    虽然说也挺长的,但是,这样写会更严谨些。

    接下来我们就来说一下这个的格式吧。

    switch ([待判断的变量])
    {
        case [值]:
            // 当[待判断的变量] = [值]的时候做的一些事
            break; // 跳出switch语句
        default:
            // 当[待判断的变量]的值不符合上面的任何一个情况时做的一些事
    }
    
    • 最上面的switch后面的括号里填的是一个待判断的变量
    • switch下面的是一对大括号,里面写的就是可能的情况。
    • case的意思就是情况,所以在case后面写的就是待判断的变量可能的值,在这个值后面再紧跟一个:用来指示这个情况要执行的代码都在后面。
    • default的意思是默认,也就是如果这个变量实际的值不满足上面的任何一个情况时,将会执行的代码。
    • break这个语句将会跳出switch语句,具体是什么意思呢,我们先来看下不加break的情况:
    #include <stdio.h>
    
    int main()
    {
        int a;
        scanf("%d", &a);
        switch (a) {
            case 0:
                printf("0");
            case 1:
                printf("1");
            case 2:
                printf("2");
            case 3:
                printf("3");
            case 4:
                printf("4");
            default:
                printf("de\n");
                break;
        }
        return 0;
    }
    

    测试下这个程序:

    输入

    0

    输出

    01234de

    输入

    2

    输出

    234de

    输入

    10

    输出

    de

    观察规律,我们发现,一旦满足这个case的条件之后,他就会一直往下执行,把之后的casedefault全部执行掉。总感觉每个case咋这么像goto的标签哈,处理方式和长相(都有:)都这么像所以说,还是加一个break来跳出switch语句,以免搞出些奇怪的东西。

    循环

    循环,其实也就是反复执行一段一样的代码罢了。在前面,我其实已经用goto实现了一个类似循环的结构了:

    #include <stdio.h>
    
    int main()
    {
        printf("Hello Control!\n");
        int i = 0;
    mLabel:
        printf("Times: %d.\n", i);
        i ++;
        if (i < 5) goto mLabel;
        return 0;
    }
    

    其中的

    printf("Times: %d.\n", i);
    i ++;
    

    被我们重复地执行了5次,这其实就是我们称的循环体,也就是要反复执行的那部分代码。

    但是这样goto来goto去的实现循环,总觉得有点麻烦,还容易出错,所以用专门的循环语句会更好。

    在C语言中,总共有3种循环语句,下面我将我给大家一一介绍。

    while

    while语句是一中比较简单的语句,格式如下:

    while ([逻辑表达式])
    {
        // 循环体
    }
    

    只要[逻辑表达式]的值为(再回顾一下,只要[逻辑表达式]的值不是0,它就是只有值是0的时候,才为),那就不停的执行循环体里的代码。

    那么我们先看下一个简单的数字复读机的例子吧:

    #include <stdio.h>
    
    int main()
    {
        int num;
        scanf("%d", &num);
        while (num != -1)
        {
            printf("%d\n", num);
            scanf("%d", &num);
        }
        return 0;
    }
    

    观察代码,只要num的值不为-1,那就一直输入数字,并输出这个数字。这样,我们就完成了这个数字复读机了。

    当然,我们还可以这么写:

    #include <stdio.h>
    
    int main()
    {
        int num;
        while (1)
        {
            scanf("%d", &num);
            if (num == -1) break;
            printf("%d\n", num);
            
        }
        return 0;
    }
    

    switch...case语句中,我们学过了break语句,它是用于跳出switch语句的,同样的,break语句同样适用于循环语句。在这个例子中,当读入当数字等于-1的时候,我们就用break语句跳出循环,并且break之后的语句都将不会被执行

    同时,在这个例子中,假如没有这个break,那这个程序将会一直被执行下去,一直到你强制把它关闭为止,因为你在上面的while后面的值为1,也就是真,那么这样的结构就是死循环

    while (1)
    {
        // 需要反复执行的代码
    }
    

    上面的这个就是一个死循环,除了break语句以外都不能使这个循环结束。

    do...while

    do...while和while循环十分相似,只是有一点点不相同,那就是执行顺序。

    由于程序是从上到下执行的,所以,while语句它是先执行那个条件判断语句的。

    #include <stdio.h>
    
    int main()
    {
        int num;
        scanf("%d", &num);
        while (num != -1)
        {
            printf("%d\n", num);
            scanf("%d", &num);
        }
        return 0;
    }
    

    这是之前的那个程序,那么程序从上到下依次执行的是int num;定义变量,然后再是scanf("%d", &num);读入数据,并赋值给num。接下去便是我们的循环,他先碰到的是while括号里的内容,也就是num != 1,于是它先做一遍判断,如果num不等于-1的时候,那就执行循环体里的东西,反之便跳过大括号,执行下面的return 0;去了。

    但是这边写了两个scanf("%d", &num);,略显麻烦,所以do...while正是来解决这个问题的。

    格式:

    do
    {
        // 循环体
    } while ([逻辑表达式]);
    

    将刚刚那个程序修改成do...while的格式就是这样的:

    #include <stdio.h>
    
    int main()
    {
        int num;
        do
        {
            scanf("%d", &num);
            printf("%d\n", num);
        } while (num != -1);
        return 0;
    }
    

    当然,在功能上与之前的那个程序还是有一点差别的,不知道大家有没有看出来。

    唯一的区别就是,我这个程序他在输入-1的时候也会复读出-1。

    do...while语句它是先执行完循环体里的内容,再去判断while后面跟的条件的。而while语句是先判断一边条件再去执行循环体的。这就是他们区别,根据不同的编程场合,应合理运用。

    这张GIF可以看出他们的不同,布尔值其实就是一种只有真/假两个状态的值

    for

    现在有一个很简单的问题:

    输入一个数字n,求1 + 2 + 3 + ... + n的和。

    测试样例:
    输入

    10

    输出

    55

    输入

    100

    输出

    5050

    我们可以尝试先用while语句实现下:

    #include <stdio.h>
    
    int main()
    {
        int n;
        scanf("%d",&n);
        int i = 1;
        int sum = 0;
        while (i <= n) {
            sum += i;
            i ++;
        }
        printf("%d\n",sum);
        return 0;
    }
    

    我们要先定一个变量i,用于代表当前加到的数字,变量sum则用于记录总和。
    接下来就是判断,只要i ≤ n就对sum进行累加。而i ++;则是让要加的数字+1。

    其实对于这种要循环制定次数的循环结构,那么我们则可以使用for循环来达到我们的目的。

    先来看下格式:

    for ([执行循环体之前的表达式,一般用于循环中要用到的变量的初始化];[逻辑表达式];[循环体尾部的表达式])
    {
        // 循环体
    }
    
    说了那么多,估计大家都晕了还是看张图比较明白: 生动的ppt动画。。。

    这样就直观多了。

    那么我们再来看看之前那个例子用for循环实现是怎么样的:

    #include <stdio.h>
    
    int main()
    {
        int n;
        scanf("%d", &n);
        int sum = 0;
        for (int i = 1;i <= n;i ++)
        {
            sum += i;
        }
        printf("%d\n", sum);
        return 0;
    }
    

    其中,int i = 1与之前定义的变量一样,是用来记录当前要加的数,i <= n和之前的while后面的逻辑表达式作用一样,i ++也和之前的没区别,也就是在循环尾部对要加的数字进行自加。

    但是这样写有一个好处是,程序更容易阅读,并且变量i也只能在for下面的那个作用域起作用,离开了这个作用域这边定义的变量i就无法再次使用了。

    if语句一样,for循环也是可以简写的(while也行),只要作用域里只有一句话,那就可以使用简写,也就是行语句

    上面的那个for语句可以写成下面的这个形式:

    for (int i = 1;i <= n;i ++) sum += i;
    

    break 和 continue

    之前在讲switch语句的时候提到过break的用法,然后在while里也简单提过,现在我就来详细地说明一下。

    在switch里面我们讲过,break是跳出整个switch语句对作用域,也就是说不再往后执行下去,而在while和for里面也是这样的。break语句可用于各种循环语句以及switch语句,就是跳出循环语句,使作用域内之后的语句不再起作用,然后继续执行循环体后面的语句。

    continue也十分类似,它也会使它后面的语句失效,并跳转,但是跳转的位置和break不同,break跳转到循环体末尾,而continue则是跳转到整个循环的最前面,并再判断一遍那个条件,之后继续执行循环体里面的语句。

    还是图比较明了

    简单的例子:

    #include <stdio.h>
    
    int main()
    {
        int i = 0;
        while (i < 3)
        {
            i ++;
            if (i == 2) continue;
            printf("%d\n",i);
        }
        return 0;
    }
    

    输出

    1
    3

    利用continue就把2给避开了,但3还是能正常输出。

    但是假如用break,那么3就不会被输出了:

    #include <stdio.h>
    
    int main()
    {
        int i = 0;
        while (i < 3)
        {
            i ++;
            if (i == 2) break;
            printf("%d\n",i);
        }
        return 0;
    }
    

    输出

    1

    当i = 2的时候,循环就被退出了。

    结语

    到这里,大家已经掌握了基本的编程技巧了,可以适当的做一些编程题练练手了。这里我推荐个网站可以练习一些基础编程题:PTA注册个账号就能开始练习了,这样就可以巩固一些编程知识了。同时也欢迎大家阅读下一篇文章《C语言快速入门 - 函数》。

    相关文章

      网友评论

          本文标题:C语言快速入门 - 控制语句

          本文链接:https://www.haomeiwen.com/subject/rfhbjctx.html