目录
- C语言快速入门
- C语言快速入门 - Hello World 详解
- C语言快速入门 - 变量
- C语言快速入门 - 简单运算符
- C语言快速入门 - 控制语句
什么是控制语句
回顾我们之前的程序,你会发现,我们的程序一直都是从上到下,一行接着一行执行的,并不能根据我们的意愿改变执行顺序,但是控制语句却有着这个功能。本文,就将介绍控制语句。
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
是什么意思吧。这其实是两个词的组合,go
和to
,所以他的意思就是去一个地方,所以我们在程序中就可以运用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判断多种情况)。
这个程序里,只要我们输入内的数字,就可以输出它,并让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
的条件之后,他就会一直往下执行,把之后的case
和default
全部执行掉。总感觉每个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
语句是先判断一边条件再去执行循环体的。这就是他们区别,根据不同的编程场合,应合理运用。
for
现在有一个很简单的问题:
输入一个数字,求的和。
测试样例:
输入
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 ([执行循环体之前的表达式,一般用于循环中要用到的变量的初始化];[逻辑表达式];[循环体尾部的表达式])
{
// 循环体
}
说了那么多,估计大家都晕了还是看张图比较明白:这样就直观多了。
那么我们再来看看之前那个例子用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语言快速入门 - 函数》。