控制语句 用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成, C 语言有九种控制语句。 可分成以下三类: 1. 条件判断语句也叫分支语句: if 语句、 switch 语句; 2. 循环执行语句: do while 语句、 while 语句、 for 语句; 3. 转向语句: break 语句、 goto 语句、 continue 语句、 return 语句。
2.分支语句(选择结构)
2.1.if语句·if语句
·switch语句
1.单分支if语句
if ( 表达式 ) 语句 ;2.双分支if语句
if ( 表达式 ) 语句 1 ; else 语句 2 ;3.多分支if语句
if ( 表达式 1 ) 语句 1 ; else if ( 表达式 2 ) 语句 2 ; else 语句 3 ;代码1:
#includeint main() { int age=0; scanf("%d",&age); if(age>=18) printf("成年n"); return 0; }
代码2:
#includeint main() { int age=0; scanf("%d",&age); if(age>=18) printf("成年n"); else printf("未成年n"); return 0; }
代码3:
#include1.c语言中规定:0就是假,非0就是真。 2. if(age>=18 && age<=40) 与 if(18<=age<=40)是不同的,写代码时应该用第一种格式,第二种语法没有错,但不是你想要的逻辑(此时编译器这么翻译:假设age是10,编译器会先进行18<=10为0然后0<=40为真) 3. 如果条件成立,要执行多条语句,则应该使用代码块。如下代码:int main() { int age=0; scanf("%d",&age); if(age<18) printf("少年n"); else if(age>=18 && age<25) printf("青年n"); else if(age>=25 && age<60) printf("壮年n"); else if(age>=60 && age<90) printf("老年n"); else printf("老寿星n"); return 0; }
#include2.1.1.悬空elseint main() { int age=0; scanf("%d",&age); if(age>=18) { printf("成年n"); printf("可以谈恋爱n"); } else printf("未成年n"); return 0; }
代码1:
#includeint main() { int a = 0; int b = 2; if(a == 1) if(b == 2) printf("hehen"); else printf("hahan"); return 0; }
运行结果1:无输出
代码2:
#includeint main() { int a = 0; int b = 2; if(a == 1) { if(b == 2) { printf("hehen"); } } else { printf("hahan"); } return 0; }
运行结果2:
注:
1.else总是和离得最近的if相匹配。
2.第一个代码的风格不好,使用{ }可以使阅读效果更好。
2.1.2.if书写形式的对比代码1:
if (condition) {
return x;
}
return y;
代码2:
if(condition) {
return x; }
else
{
return y;
}
注:两段代码意思相同,都是条件成立返回x,不成立返回y。但是代码1是不好的代码,可读性差。
代码3:int num = 1;
if(num == 5)
{
printf("hehen");
}
代码4:
int num = 1;
if(5 == num)
{
printf("hehen");
}
注:代码4更好,因为假如你疏忽将==写成了=,则代码1不会报错,而代码2因为给一个常量赋值,系统会报错。
2.1.3练习1. 判断一个数是否为奇数 2. 输出 1-100 之间的奇数2.2.switch语句 switch 语句也是一种分支语句,常常用于多分支的情况。 语句结构:
switch ( 表达式 ) { case 表达式1 : 语句1 ; case 表达式2 : 语句2 ; }2.2.1.在switch语句中的break
代码1:
#include代码2:int main() { int day = 0; 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; } return 0; }
#include注: 1.在 switch 语句中,我们没办法直接实现分支,搭配 break 使用才能实现真正的分支。 2.若不加break,编译器会从符合条件的case开始往后所有case对应语句依次执行,直到遇见break。(总结里会详细说明) 3.语句中switch后面括号内可以是整型常量、整型常量表达式、字符常量、字符型常量表达式或enum类型。 4.case后面可以是整型常量、整型常量表达式、字符常量、字符型常量表达式。 2.2.2.default子句//switch代码演示 int main() { int day = 0; switch(day) { case 1: case 2: case 3: case 4: case 5: printf("weekdayn"); break; case 6: case 7: printf("weekendn"); break; } return 0; }
#includeint main() { int day = 0; 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("输入错误,请输入1~7的数字n"); break; } return 0; }
注:
1.default:默认前面的case都不能匹配的情况下,那就走default的语句。
2.default一般是放在最后,放在前面也可以。
3.不需要default时,default可以不用删除(在每个 switch 语句中都放一条default子句是个好习惯),把default中的语句删除即可(default要是在前面default中的break要加上,要是在末尾,break可删除)
2.2.3.练习#include答案: 2.2.4.总结int main() { int n = 1; int m = 2; switch (n) { case 1: m++; case 2: n++; case 3: switch (n) {//switch允许嵌套使用 case 1: n++; case 2: m++; n++; break; } case 4: m++; break; default: break; } printf("m = %d, n = %dn", m, n); return 0; }
switch语句运行原理:
从前往后case后的表达式与switch后表达式匹配:(两种情况)
1. 匹配上了:从匹配上的case语句往后所有语句依次执行(包括default后的语句)(不再与后面的case匹配),直到遇见break。
2.未匹配上: 找default,从default语句往后所有语句依次执行,直到遇见break。
1.语句中switch后面括号内可以是整型常量、整型常量表达式、字符常量、字符型常量表达式或enum类型。
2.case后面可以是整型常量、整型常量表达式、字符常量、字符型常量表达式。
3.若default放在最后,匹配后不再执行其他分支,因此可不加break。若放在前面,则需要加break。
4.default不是必须的,若没有default,如果所有case匹配失败,那么什么都不执行。
3.循环语句
·while ·for ·do while3.1.while循环 3.1.1.语法 while语句语法结构:
while ( 表达式 ) { 循环语句 ; }while语句执行流程: 代码:
#include3.1.2.while语句中的break和continue 1.break介绍 代码:int main() { int i = 1; //初始化 while(i<=10) //判断 { printf("%d ", i); i++; //调整部分 } return 0; }
#include运行结果: 总结: 在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。 所以:while中的break是用于永久终止循环的。 2.continue介绍 代码:int main() { int i = 1; while(i<=10) { if(5==i) break; printf("%d ", i); i++; } return 0; }
#includeint main() { int i = 1; while(i<=10) { if(5==i) continue; printf("%d ", i); i++; } return 0; }
运行结果:死循环
总结: continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行, 而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。 3.1.3.几个重要代码范例代码范例1:
#define _CRT_SECURE_NO_WARNINGS 1 #includeint main() { int ch = getchar(); printf("%cn", ch); putchar(ch); return 0; }
注:
1.getchar函数
上图stdin意思是标准输入,意思就是键盘。函数作用就是可以利用getchar函数从键盘获取一个字符。
2.getchar函数返回字符的类型一般是整型。getchar取得是一个字符,但字符的存储值(代表这个字符的值)是一个ASCII值,ASCII值是一个整数,因此可以用整型来接收。当getchar读取失败的时候,返回EOF,如下图,其实EOF就是-1,而-1是一个整型,因此getchar最好用整型来接收。若用char接受,当getchar读取失败时,char只有一个字节无法接受4个字节的-1值
3.putchar函数
上图stdout的意思是标准输出,意思就是屏幕。函数作用就是可以利用putchar函数在屏幕上输出一个字符。
4.getchar函数和putchar函数只是针对字符的输入和输出。scanf函数和printf函数比这两个函数功能要全。
代码范例2:#includeint main() { int ch = 0; while ((ch = getchar()) != EOF) { putchar(ch); } return 0; }
运行结果2:
注:
1.若要让这个代码运行停下来,使用ctrl+z,ctrl+z意思就是获取一个EOF,代码中EOF!=EOF逻辑为假,代码结束。
2.这里要注意括号,(ch = getchar()) != EOF 与 ch = getchar() != EOF表达的逻辑是不一样的,前面是将输入值赋值给ch再与EOF进行比较,后面代码是将输入值先与EOF进行比较,再将比较的结果赋值给ch。
3.这里的代码适当的修改是可以用来清理缓冲区的,如下面代码范例3所示。
代码范例3:
注:
1.上图第1个代码无法达到预期的目的,此时输入abcdef还没有进入确认密码阶段,系统就已经输出确认失败了。事实上scanf函数和getchar函数不是从键盘上拿取数据的,而是从输入缓冲区拿取数据,scanf和getchar的工作原理是它去看输入缓冲区有没有东西,若有东西,函数就拿走了,若 输入缓冲区什么都没有,他就会等待你输入。代码1中,你输入abcdef还需要按回车,敲回车的话相当于加了一个n,scanf读取拿走了abcdef给了input变量,此时缓冲区还有个n,getchar再获取信息读取了缓冲区的n赋值给ch,n不等于Y,因此直接输出了确认失败。
2.上图第2个代码在第一个代码代码的基础上加了一个getchar,此时getchar的作用是从缓冲区拿走一个字符,现在getchar把多余的n取走,便可达到预期目的。但是scanf(%s,...)读取字符串的时候,遇到空格就结束了,因此发生了代码2的错误,此时scanf拿走了abcdef并结束了,后面的getchar拿走了输入缓冲区后面的一个字符h,再后面的getchar拿走了e赋值给ch并与Y比较,逻辑为0,输出确认失败。
3.如上图第3个代码所示,把getchar换成一个while循环语句,便可将缓冲区里的所有字符(包括n)全部拿走,此时再输入一个值就赋值给了ch进行判断,达到预期目的。
4.如上图第一个代码中输入函数括号内所示,数组名本来就是地址,因此数组名是不需要取地址的。
代码范例4:
#includeint main() { int ch = 0; while ((ch = getchar()) != EOF) { if (ch < ‘0’ || ch > ‘9’) continue; putchar(ch); } return 0; }
注:这个代码的作用是:只打印数字字符,跳过其他字符的。
3.2.for循环 3.2.1.语法for语句语法结构:
for ( 表达式 1 ; 表达式 2 ; 表达式 3 ) { 循环语句 ; } 表达式 1: 表达式 1 为 初始化部分 ,用于初始化循环变量的。 表达式 2: 表达式 2 为 条件判断部分 ,用于判断循环时候终止。 表达式 3: 表达式 3 为 调整部分 ,用于循环条件的调整for语句执行流程: 代码:
#include3.2.2.for语句中的break和continue 1.break介绍 代码:int main() { int i = 0; for(i=1; i<=10; i++) { printf("%d ", i); } return 0; }
#includeint main() { int i = 0; for(i=1; i<=10; i++) { if(i == 5) break; printf("%d ",i); } return 0; }
运行结果:
总结: 在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。 所以:for循环中的break是用于永久终止循环的(与while相同) 2.continue介绍 代码:#includeint main() { int i = 0; for(i=1; i<=10; i++) { if(i == 5) continue; printf("%d ",i); } return 0; }
运行结果:
总结:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行, 而是直接跳转到for语句的调整部分,再进行下一次循环的入口判断。(与while不同) 3.2.3.for语句的循环控制变量1.不可在for 循环体内修改循环变量,防止 for 循环失去控制。(见如下代码)
代码:
运行结果:死循环
2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。(见如下代码)
注:这样写不好,代码的可读性不高,建议写成前闭后开区间。
3.2.4.一些for循环的变种1. for循环的变种一
代码:
#include运行结果: 注: 1.for的初始化,判断,调整三个部分在语法层次上是都可以省略的。 2.中间的判断部分如果省略,意味着判断恒为真,就构成了死循环。 3.如果条件允许,不建议省略for循环的三个表达式。(如下两图进行对比),第一个代码打印9个hehe而第二个代码因为从i=1第二轮循环开始j已经是3了内循环不再执行,因此只打印i=0第一轮循环的3个hehe。 2. for循环的变种二int main() { for(;;) { printf("hehen"); }
int x, y;
for (x = 0, y = 0; x<2 && y<5; ++x, y++)
{
printf("hehen");
}
return 0;
注:for循环也可以用两个变量来进行控制。
3.2.5.练习请问循环要循环多少次?
#includeint main() { int i = 0; int k = 0; for(i =0,k=0; k=0; i++,k++) k++; return 0; }
答案:0次(for循环条件判断部分为k=0,其结果是0为假,不进入循环)
3.3.do while循环do while语句循环至少执行一次,使用的场景有限,所以不是经常使用。
3.3.1.语法do while语句语法结构:
do 循环语句 ; while ( 表达式 );do while语句执行流程:
代码:
#include3.3.2.do while循环中的break和continue 1.break介绍 代码:int main() { int i = 1; do { printf("%dn", i); i++; } while(i<=10); return 0; }
运行结果:
总结: 在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。 所以:do while循环中的break是用于永久终止循环的(与while、for相同) 2.continue介绍 代码:运行结果:死循环
总结:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分再从do进行下一次循环的入口。() 3.3.3.do语句的特点 循环至少执行一次,使用的场景有限,所以不是经常使用。#include3.4.练习int main() { int i = 10; do { printf("%dn", i); }while(i<10); return 0; }
1. 计算 n 的阶乘。 2. 计算 1!+2!+3!+……+10! 3. 在一个有序数组中查找具体的某个数字 n 。(讲解二分查找) 4. 编写代码,演示多个字符从两端移动,向中间汇聚。 5. 编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成,如果三次均输入错误,则退出程序。
练习1参考代码:
练习2参考代码:
错误代码:
普通正确代码:
优化的正确代码:
练习3参考代码:
普通正确代码:(在1~10中找到7所在的位置)
优化正确代码:(二分查找、折半查找)(在1~10中找到7所在的位置)
练习4参考代码:
注:
1.sleep():睡眠函数,其单位是毫秒,使用sleep需要windows.h的头文件。
2.system():用来执行系统命令。
3.cls:系统命令,其功能是清理屏幕(清空屏幕)。



