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

2019-08-20  本文已影响0人  Void_Caller

目录

什么是控制语句

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

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;
}

测试下这个程序:

输出

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:
        // 当[待判断的变量]的值不符合上面的任何一个情况时做的一些事
}
#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语言快速入门 - 函数》。

上一篇下一篇

猜你喜欢

热点阅读