语句定义
c语言中可分为以下五类:
- 表达式语句
- 函数调用语句
- 控制语句
- 复合语句
- 空语句
控制语句
控制语句用于控制程序的执行流程,以实现程序的各种结构方式(c语言支持三种结构:顺序结构、选择结构、循环结构),它们由特定的语句定义符组成,c语言有九种控制语句。
分类:
- 条件判断语句(分支语句):if语句,switch语句
- 循环执行语句:do while语句、while语句、for语句
- 转向语句:break语句、goto语句、continue语句、return语句
分支语句(选择结构)
人生处处充满了选择,每做一次选择就会产生不一样的结果
if语句
语法结构
单条语句可以不加{ }
//单判断
if(表达式){
语句列表;
}
//单分支
if(表达式1){
语句列表1;
}
else{
语句列表2;
}
//多分支
if(表达式1){
语句列表1;
}
if else(表达式2){
语句列表2;
}
...
else{
语句列表n;
}
匹配策略
在c语言中if 和 else是采用就近匹配的原则
#include<stdio.h>
int main(){
int a = 0;
int b = 0;
if(a == 1)
if(b == 2)
printf("happy\n");
else
printf("sad\n");
return 0;
}
由上面的例子我们可以引出,当多个if else语句出现时,难免会出现配对的问题。
而由就近匹配原则可知:最后的else应该与其上面最近的if匹配,因此该程序没有输出。
我们在写代码时,应该注重代码风格(详见:《高质量的C-C++编程》),可以树立良好的编程习惯。
书写形式
不同的书写形式会造就不一样的阅读体验,对于代码的可读性来说非常重要
//代码1
if(condition){
return x;
}
return y;
//代码2
if(condition){
return x;
}
else{
return y;
}
上述代码1和代码2两者表达的意义相同,但代码1的可读性较差,容易造成误解。
//代码3
int num = 1;
if(num == 5){
printf("happy\n");
}
//代码4
int num = 1;
if(5 == num){
printf("happy\n");
}
上述代码3和代码4两者表达的意义相同,但代码4将if语句中的判断条件左值设置为不可赋值类型,当不小心将==比较符号写成=赋值符号时,编译器会报错提醒,能更好的检查出错误。
switch语句
switch也是一种分支语句,常常用于多分支的情况
语法结构
switch(整型表达式){
case(整型常量表达式1): 语句列表1;
case(整型常量表达式2): 语句列表2;
...
case(整型常量表达式n): 语句列表n;
default: 语句列表n+1;
}
- switch()的参数类型必须为整型,不能为float等浮点型。
- case标签必须是常量表达式,如 ‘a’、66、枚举常量等。
- case标签具有唯一性,不能有两个case的值相同
- case后面可以有多条语句且不需要加{}
- case和default子句的先后顺序可以变动,而不会影响程序执行结果。因为程序会自动跳过default语句,先进行case子句的判断。(default可以省略不要)
举例说明
例如:对应数字1、2、3、4、5、6、7分别输出星期一、星期二、星期三、星期四、星期五、星期六、星期天。
int day = 0;
scanf("%d",&day);
switch(day){
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期天\n");
break;
default:
printf("输入错误\n");
}
break这个关键字在switch中扮演了重要的角色,当每次执行完case选项语句后,若不想往下继续执行,则需要用break跳出该switch语句。(case决定了它的入口,break决定了它的出口)
嵌套规则
switch语句是允许嵌套使用的,当嵌套switch使用break时只会跳出一层内部switch。
int n = 1;
int m = 2;
switch(n){
case 1: // n = 1
m++; // m = 3
case 2:
n++; // n = 2
case 3:
switch(n){
case 1:
n++;
case 2: // n = 2
m++; // m = 4
n++; // n = 3
break;
}
case 4:
m++; // m = 5
default:
break;
}
return 0;
循环语句
日常生活中我们除了会进行选择,还会重复做相同的事情,所以为了解决这类问题,我们引入了循环语句。
while循环
语法结构
while(表达式){
循环语句;
}
while语句流程图:
- break直接终结循环。
- continue跳过本次循环后面的语句,转到while语句判断部分,进行下一次循环的入口判断。
举例说明
//下面的代码都是什么意思?
//代码1
#include<stdio.h>
int main(){
int ch = 0;
while((ch = getchar()) != EOF) // EOF == -1
putchar(ch);
return 0;
}
// getchar有时也可用于清理输入缓冲区里的回车引起的\n等不需要的符号
// while((ch = getchar()) != '\n'){;}
//代码2
// 打印0~9的字符
#include<stdio.h>
int main(){
int ch = 0;
while((ch = getchar()) != EOF){
if(ch < '0' || ch > '9')
continue;
putchar(ch);
}
return 0;
}
上述程序中我们使用到了getchar()这个方法,接收键盘输入的字符,但它的返回值为int类型,也就是返回了字符的ASCII码值。
而putchar()则可以将获取的字符打印出来,它需要int型参数,返回值也为int。
查看cplusplus网站即可得到详细的介绍
for循环
for循环相对于while循环三个部分比较集中,能更好的展现循环的要素。
语法结构
for(表达式1;表达式2;表达式3){
循环语句;
}
- 表达式1:初始化部分,用于初始化循环变量的。
- 表达式2:条件判断部分,用于判断循环什么时候终止。
- 表达式3:调整部分,用于循环条件的调整。
for循环流程图:
- break的作用依然是终止循环。
- continue在跳过后面语句后,先执行表达式3,再继续进行下一轮条件判断。
控制变量
不可在for循环体内修改循环变量,防止for循环失去控制。
建议for语句的循环控制变量的取值采用“前闭后开区间”的写法。
int i = 0;
//前闭后开的写法
for(i=0; i<10; i++){ //数组循环时,10可以体现出循环的次数。
}
//两边都是闭区间
for(i=0; i<=9; i++){
}
//for的初始化,判断,调整三个部分可以省略
//但若省略判断部分,就意味着判断恒为真
for(;;){
}
//for循环可以设置多个循环变量
//笔试题
//请问下面的for循环多少次
#include<stdio.h>
int main(){
int i = 0;
int k = 0;
for(i=0,k=0; k=0; i++,k++){
k++;
}
return 0;
}
//循环0次,因为判断语句k = 0是个赋值语句,它被赋值为0,恒为假,不进入循环。
for和while循环
for循环可以替换所有的while循环,所以在后续的一些新的编程语言中,如go语言,循环语句只包含有for循环,删除了while循环。
do while循环
do
循环语句;
while(表达式);
do while 流程图
- 使用break时同样结束整个循环
- continue则回到末尾的判断部分,进行下一次循环的判断。
综合应用
计算n!相加的和
#include<stdio.h>
int main(){
int n, i;
scanf("%d",&n);
int ret = 0;
int sum = 0;
for(i=1; i<=n; i++){
ret *= i;
sum += ret;
}
printf("%d\n",sum);
return 0;
}
编写代码,演示多个字符从两端向中间汇聚
#include<stdio.h>
#include<string.h>
int main(){
char arr1[] = "Hello World!";
char arr2[] = "************";
int l = 0;
int r = strlen(arr1) - 1;
while(l<=r){
arr2[l] = arr1[l];
arr2[r] = arr2[r];
printf("%s\n",arr2);
Sleep(1000); // windows下Sleep函数参数单位为ms
system("cls");
l++;
r--;
}
printf("%S\n",arr2);
return 0;
}
其它题目详见我的c语言仓库
go to语句
c语言中提供了可以随意使用的go to语句和标记跳转的标号。
go to从理论上来说是没有必要的,实践中也很少使用。
但某些场合下还是有用的,例如:终止程序在某些深度嵌套的结构的处理过程,可以一次跳出多层循环,这种情况break就难以实现。
使用场景
for(...){
for(...){
for(...){
if(disaster){
goto error;
}
}
}
}
...
error:
if(disaster){
//处理错误情况
}
举例说明
//写一个关机程序,只要程序运行起来,电脑在一分钟内关机。
//输入:我是猪,才能取消关机。
#include<stdio.h>
#include<stdlib.h>
int main(){
char input[20] = {0};
system("shutdown -s -t 60");
again:
printf("请注意你的电脑将在一分钟内关机,请输入(我是猪)方可取消!!!\n");
scanf("%s",input);
if(strcmp(input,"我是猪") == 0){
system("shutdown -a");
printf("关机取消成功!\n");
}
else{
goto again;
}
return 0;
}