分支语句和循环语句 C语言是结构化的程序设计语言有顺序结构,选择结构,循环结构 三种结构
分支语句
循环语句
goto语句
什么是语句?
C语言中由一个分号隔开的句子,就是一个语句
1 2 3 4 5 int main () { ; return 0 ; }
if语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 语法结构: if (表达式) 语句; if (表达式) 语句1 ; else (表达式) 语句2 ; if (表达式) 语句1 ; else if (表达式) 语句2 ; else (表达式) 语句3 ;
1 2 3 4 5 6 7 8 9 10 11 12 int main () { int age = 10 ; if (age>=18 ) printf ("成年\n" ); else printf ("未成年\n" ); return 0 ; }
再来一个例子,看看会暑促和什么
1 2 3 4 5 6 7 8 9 10 int main () { int age = 60 ; if (age < 18 ) printf ("少年n" ); else if (18 <= age < 26 ) printf ("青年\n" ); return 0 ; }
结果输出是青年
,那么为什么呢?因为这个写法是错误 的
来看一下else if
的表达式,已经设定age
的值为60
,因此18<=age
为真,变成1
,接着又是<26
这个表达式,1<26
为真,所以输出else if
的语句,所以输出的是青年
,而不为空
正确的写法应该是
1 2 3 4 5 6 7 8 9 10 int main () { int age = 60 ; if (age < 18 ) printf ("少年n" ); else if (age >= 18 && age < 26 ) printf ("青年\n" ); return 0 ; }
因此if语句的操作逻辑是:如果表达式的结果为真,则语句执行
1 2 3 4 5 6 7 8 9 10 11 int main () { int a = 0 ; int b =2 ; if (a == 1 ) if (b == 2 ) printf ("hehe\n" ); else printf ("haha\n" ); return 0 ; }
结果是不打印,那么是为什么呢?
乍一看以为第一个if
和else
对上,表达式不成立,直接看else
,应该是haha
啊,但是else是与它最近的if配对 的,第一个if不成立,导致它管理的语句也不会执行,因此不会进行打印
当你遇到这种写代码的人,就可以拉出去枪毙 了
优化后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int main () { int a = 0 ; int b =2 ; if (a == 1 ) { if (b == 2 ) { printf ("hehe\n" ); } else { printf ("haha\n" );、 } } return 0 ; }
所以代码风格 很重要
来点小练习
判断一个数是不是奇数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int main () { int num = 15 ; if ( num %2 ==1 ) { printf ("奇数\n" ); } else { printf ("偶数\n" ); } return 0 ; }
输出1-100之间的奇数 1 2 3 4 5 6 7 8 9 10 int main () { int i = 0 ; for ( i = 1 ; i <= 100 ; i++) { if ( i % 2 == 1 ) printf ("%d " , i); } return 0 ; }
1 2 3 4 5 6 7 8 9 int main () { int i = 0 ; for ( i = 1 ; i <= 100 ; i+=2 ) { printf ("%d " , i); } return 0 ; }
switch语句 switch
语句也是一种分支语句,常常用于多分支的情况
但是语句项是什么呢
来个例子感受一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 int main () { 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 ; } return 0 ; }
如果是1-5工作日,67休息日呢?就可以这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int main () { int day = 0 ; scanf ("%d" , &day); switch (day) { case 1 : case 2 : case 3 : case 4 : case 5 : printf ("工作日\n" ); break ; case 6 : case 7 : printf ("休息日\n" ); break ; } return 0 ; }
break语句 实际效果是把语句列表划分为不同的部分
但是上述的例子输入别的值时没有反馈,应该怎么办呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int main () { int day = 0 ; scanf ("%d" , &day); switch (day) { case 1 : case 2 : case 3 : case 4 : case 5 : printf ("工作日\n" ); break ; case 6 : case 7 : printf ("休息日\n" ); break ; default : printf ("输入错误\n" ); break ; } return 0 ; }
循环语句 while循环 与if语句十分相似
1 2 3 4 5 6 int main () { if (1 ) printf ("hehe\n" ); return 0 ; }
while的用法呢
1 2 3 4 5 6 int main () { while (1 ) printf ("hehe\n" ); return 0 ; }
很好你现在进入了无限死循环
试着用while语句打印出1-10的数字 1 2 3 4 5 6 7 8 9 10 int main () { int i - 1 ; while (i <= 10 ) { printf ("%d " , i); i++; } return 0 ; }
在while循环
中,break
只要被触发 就会永久的终止循环
1 2 3 4 5 6 7 8 9 10 11 12 13 int main () { int i - 1 ; while (i <= 10 ) { if (i == 5 ) break ; printf ("%d " , i); i++; } return 0 ; }
结果是 1 2 3 4
那么我想让代码继续跑下去呢?那首先想到的肯定是continue
,那写一个试试看
1 2 3 4 5 6 7 8 9 10 11 12 13 int main () { int i - 1 ; while (i <= 10 ) { if (i == 5 ) continue ; printf ("%d " , i); i++; } return 0 ; }
结果很奇怪,只有1 2 3 4 并且后面的光标还在闪烁,说明程序还在运行,也就是进入了死循环
因为在while循环
中,continue
的作用是跳过本次循环continue
后边的代码 ,直接去判断部分,看是否进行下一次循环
来看一下别的代码
1 2 3 4 5 6 7 int main () { int ch = 0 ; while ((ch = getchar()) != EOF) putchar (ch); return 0 ; }
先来分析一下
getchar()
当putchar()
被执行时的过程
1 2 3 4 5 6 7 8 int main () { int ch = getchar(); putchar (ch); return 0 ; }
输入一个大写的A就会输出一个大写的A
已经知道了putchar()
输出错误时会返回EOF
(end of file
-文件的结束标志)
那么回到原语句
跑起来之后,就可以一直输入一个字符,输出一个相同的字符,如果想要停止的话可以输入ctrl + z
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int main () { char password[20 ] = {0 }; printf ("请输入密码:>" ); scanf ("%s" ,password); printf ("请确认密码(Y/N):>" ); int ch = getchar(); if (ch == 'y' ) { printf ("确认成功\n" ); } else { printf ("确认失败\n" ); } return 0 ; }
但是运行之后发现,还没确认就接着确认失败是为什么呢?
因为不管getchat还是scanf都是输入函数,他们都需要去中间的缓冲区读取数据,而我们通过键盘来给缓冲区以信息而我们输入一个密码后需要回车进行确认。因此缓冲区的数据是xxxxx\n,而scanf拿走的只有xxxxx,剩下的\n就会在缓冲区等待,而getchar就会直接进行读取\n,因此就会直接显示结果。所以这就为我们修改代码提供了思路。我们应该进行清理缓冲区。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int main () { char password[20 ] = {0 }; printf ("请输入密码:>" ); scanf ("%s" ,password); printf ("请确认密码(Y/N):>" ); getchar(); int ch = getchar(); if (ch == 'y' ) { printf ("确认成功\n" ); } else { printf ("确认失败\n" ); } return 0 ; }
这样刚才的问题就解决了,但是当我输入密码的时候是xxxxx xxxxx,它又变成了刚才的样子又是为什么呢?
因为此时的缓冲区是xxxxx xxxxx\n,而scanf之拿走了空格之前的字符,剩下的字符就又被剩下了,因此现在就需要使用while循环不团的清理缓存区剩下的字符,直到把\n也清理完
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 int main () { char password[20 ] = {0 }; printf ("请输入密码:>" ); scanf ("%s" ,password); printf ("请确认密码(Y/N):>" ); int tmp = 0 ; while ((tmp = getchar()) != '\n' ) { ; } int ch = getchar(); if (ch == 'y' ) { printf ("确认成功\n" ); } else { printf ("确认失败\n" ); } return 0 ; }
试着用getchat来只进行打印数字
1 2 3 4 5 6 7 8 9 10 11 12 int main () { int ch = 0 ; while ((ch=getchar()) != EOF) { if (ch < '0' || ch > '9' ) continue ; putchar (ch); } return 0 ; }
for循环 进入for循环之前再看一遍之前打印1~10的代码
1 2 3 4 5 6 7 8 9 10 int main () { int i = 1 ; while (i <= 10 ) { printf ("%d " , i); i++; } return 0 ; }
会发现影响这个代码的地方有三个地方,分别是初始化,判断部分,调整部分。但是由于后期会在这三者中间加入越来越多的代码,后期会变得很难调整,而for循环就可以解决这个痛点
语法结构
1 2 for (表达式1 ; 表达式2 ; 表达式3 ;) 循环语法;
1 2 3 4 5 6 7 8 9 int main () { int i = 0 ; for (i=1 ;i<=10 ;i++) { printf ("%d" , i); } return 0 ; }
该代码与上方效果一致
if
中的continue
是会从调整再次开始的
例如
1 2 3 4 5 6 7 8 9 10 11 12 int main () { int i = 0 ; for (i=1 ;i<=10 ;i++) { if (i==5 ) continue ; printf ("%d" , i); } return 0 ; }
这里就不会出现像是while语句会出现的死循环,而是从调整再次开始
结果就是
同时建议for语句的循环控制变量的取值采取“前闭后开区间”写法
1 2 3 4 5 6 7 8 9 10 int main () { int arr[10 ] = {0 }; int i = 0 ; for (i = 0 ; i < 10 ; i++) { printf ("%d" , arr[i]); } return 0 ; }
for循环的三个部分都可以被省略
1 2 3 4 5 6 7 8 9 int main () { for (;;) { printf ("hehe\n" ); } return 0 ; }
来判断一下下列循环会循环几次
1 2 3 4 5 6 7 8 int main(){ int i = 0 ; int k = 0 ; for (i = 0 .k =0 ; k=0 ; i++,k++) k++; return 0 ; }
do while()循环
do语句的语法:
执行流程
1 2 3 4 5 6 7 8 9 10 11 int main () { int i = 1 ; do { printf ("%d " ,i); i++; }while (i<=10 ); return 0 ; }
先执行再进行判断!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int main () { int i = 1 ; do { if (i==5 ) { break ; } printf ("%d " ,i); i++; }while (i<=10 ); return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int main () { int i = 1 ; do { if (i==5 ) { continue ; } printf ("%d " ,i); i++; }while (i<=10 ); return 0 ; }
练习
n的阶乘
1 2 3 4 5 6 7 8 9 10 11 12 #include <stdio.h> int main () { int n,i; int sum =1 ; for (i=1 ;i<=n;i++) { sum = sum *i; } printf ("%d\n" ,sum); return 0 ; }
计算1!+2!+3!+4!+…+10!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <stdio.h> int main () { int i =0 ; int n =0 ; int ret = 1 ; int sum =0 ; for (n=1 ;n<=3 ;n++) { ret *=n; sum +=ret; } printf ("%d\n" ,sum); return 0 ; }
在一个有序数组中查找具体的某个数字n(二分查找)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <stdio.h> int main () { int arr[]={1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; int k =7 ; int sz=sizeof (arr)/sizeof (arr[0 ]); int left =0 ; int right = sz-1 ; while (left<=right) { int mid = (left+right)/2 ; if (arr[mid]<k) { left = mid+1 ; } else if (arr[mid]>k) { right = mid-1 ; } else { printf ("找到了,下标是:%d\n" ,mid); break ; } } if (left>right) { printf ("没找到\n" ); } return 0 ; }
编写代码,演示多个字符从两端移动,向中间汇聚