C语言是一门结构化的程序设计语言。
生活中结构又分:1、顺序结构 2、选择结构 3、循环结构
生活中所有情况无非就这三种情况,可以描述生活中所有的事情。
选择结构在C语言中又叫作分支语句或选择语句。
循环结构在C语言中也叫循环语句。
分支语句:
if
switch
循环语句:
while
for
do while
什么是语句?
C语言中由一个分号 “;” 隔开的就是一条语句。
空语句:是指只有一个分号作为语句。(不需要内容,只需语句)
如:
int main(){
int a=0;——表示一个语句
;——空语句
return 0;
}
分支语句(选择结构)
面对多种选择的同时也会得到相对应的结果。
例子:如果你好好学习,校招时拿一个好offer,走上人生巅峰;如果你不学习,毕业等于失业,回家卖红薯。——这就是选择!
if语句
语句结构:
第一种
if(表达式)
语句;
这里表达式计算的结果如果为真(即非0),那这个语句就要被执行;否则,什么都不执行。
第二种
if(表达式)
语句1;
else
语句2;
这里表达式计算结果为真(即非零),那语句1就要被执行;否则,就执行语句2。
第三种(多分支)
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
这里如果表达式1成立,语句1就要被执行;另外如果表达式2成立,那就执行语句2;那如果表达式2也不成立,那就只能执行语句3。
这里,语句1、语句2、语句3只能被执行一个,且执行顺序是依次递进的。
用代码描述if语句——
int main(){
int age=10;
if(age<18) //原括号里头放的是一个判断语句
printf("未成年\n");//因age=10<18,条件成立,所以语句被执行
return 0;
}
若age=20时,那这时20<18为假,什么都不输出。(单分支if)
2、 if else的例子:
int main(){
int age=20;
if(age<18) //如果age<18则打印
printf("未成年\n");
else //否则,则打印
printf("成年\n");
return 0;
}
【注:if相当于判断,else则给出另一种可能】
3、当int age=10;时,若 if() 写成 if(18<=age<28) 时,这个表达式写法是错误的。
这个写法执行顺序为:先执行18<=age,再执行后半部分;因18<=10条件为假,为假的结果就为0,但又因0<28为真,则又可以成功被打印;所以这种写法是错误的。
正确的写法:else if(age>=18&&age<28)
例子:
int main(){
int age=100;
if(age<18)
printf("未成年\n");
else if(age>=18&&age<28) //这是并列的判断
printf("青年\n");
else if(age>=18&&age<50)
printf("壮年\n");
else if(age>=50&&age<90)
printf("老年\n");
else //最后这个else是说在前几次可能,给出最后一种可能(当然也可以省略,看是否需要)
printf("长生\n");
return 0;
}
也可换成:
if(age<18)
printf("未成年\n");
else{
if(age>=18&&age<28)
...
}
这是把if和else当成两个逻辑,else里面在当成一个逻辑
if else 语句的书写形式多样化。
在C语言中如何表示真假?
0为假,非0即为真。
if语句如果要控制多条语句,包括else语句要控制多条语句的话,都要用大括号括起来。
如:
if(age<18)
printf("未成年\n");
printf("不能谈恋爱\n");
else{
printf...
}
从语法形式来讲这是错的;这两个打印函数若未括起来,则会出现“没有匹配if的非法else”的错误。
这里的一对大括号{ }就是一个代码块。
else中悬空else问题
对比以下两个代码中形式上的区别
#include<stdio.h>
int main(){
int a=0;
int b=2;
if(a==1)
if(b==2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}
#include<stdio.h>
int main(){
int a=0;
int b=2;
if(a==1)
if(b==2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}
第一个代码中else看似与第一个if对齐;第二个代码中else看似与第二个if对齐;但其实两个代码中else都是与第二个if匹配。
第一个代码的写法会误以为if不执行,则执行else,但这是错的。
试着去vs编译器中运行这两个代码会发现输出结果都是一样的;从中可发现else的位置存在差异,但输出结果都一样。
总结得出:else和其最近的未匹配的if进行匹配。
但要注意,代码的写法不一样,容易造成阅读上的理解错误。
注意代码风格(即写法)
美观的话,可以在if之后加上代码块把if与else包住,即——
if(a==1){
if(b==2)
printf("hehe\n");
else
printf("haha\n");}
因a=0,为假,其循环并不执行。
若想让else与第一个if匹配,则——
if(a==1){
if(b==2)
printf("hehe\n");}
else
printf("haha\n");添加上一个代码块即可
if书写形式的对比
代码1:
if(condition){
return x;
}
return y;
代码2:
if(condition){
return x;
}
else{
return y;
}
这两个代码表示的意思是——条件成立返回x,否则返回y
代码1与代码2打印结果一样,区别于写法形式上的差异;相对于代码1,代码2更容易看懂。
判断:
int main(){
int num=4;
if(num=5){
printf("hehe\n");
}
return 0;
}
这个代码可以打印。(区别在于一个等号和两个等号)
【注:判断相等——“==”,“=”是赋值的意思。】
若写成
if(5=num)
则无法打印,这里意思是将num赋给5,而5是常量,无法像变量可以改变。【注:常量无法改变】
以上代码容易写错,可采用:
if(5==num)或if(num==5)
效果一样,这只是从形式上风格效果更好。
未来如果设计到一个常量与一个变量的比较相不相等,可以把常量放到左边来判断。
练习:
1、判断一个数是否为奇数
2、输出1~100之间的奇数
思路:判断奇数就用除2看余数是否为1;而输出1~100之间的奇数,就要有1~100之间的数来判断。
这时,在编程中联想到 “%” 取模与 while 循环 和 if语句。
while循环需要循环变量,而又需要判断i是奇数,则要加上if
i++——表示下一个数。
代码如下:
int main(){
int i=1;
while(i<=100){
if(i%2==1) //也可写成if(i%2!=0)指模2的结果不等于0
printf("%d ",i);
i++;
}
return 0;
}
【注:这里“%d”后加一个空格,意思是每个数都隔开,不会连在一起。】
另一种写法:
int main(){
int i=1;
while(i<=100){
printf("%d ",i);
i+=2;
}
return 0;
}
这个代码意思是从i=1开始,依次往后加上2,再打印出来。
其结果和上一个代码一样。
这是一种算法,不同的做法也是不同的算法。
注:不能写成
i+=2;
printf("%d ",i);
这种先计算后打印;这样会导致最开始的1没有打印,因此应先打印再计算。
switch语句
switch语句也是一种分支语句;常常用于多分支情况。
若想要输入1~7的数值,来判断星期几,则用输入函数scanf
int day=0;
scanf("%d ",&day);
接下来就是判断了,而这是多分支情况。
若采用:
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
if else多分支语句,则会过于繁琐。
这时,就运用到switch语句——
语法形式:
switch(整形表达式){
语句项;
}
每个语句项都是由case组成的。
case 整形常量表达式: 语句;
如:
switch(day){
case 1:
printf("星期1\n");
case 2:
....(以此往复下去)
}
case 1:表示情况1
这里意思是如果输入为1,switch(day)里day为1,则打印星期1
整形表达式结果是几,它就从case几进去。
switch判断,case作为一个入口,然后进去输出相应结果。
【注:这里指从哪里进去,但没有给出从哪出去的代码语句指令;因此,若输入3,则后面4、5、6、7的结果会相继打印。】
这里就要加上“break”语句(break——停止、终止)指跳出switch语句。
建议在每一个case语句后加上break语句。
【注:switch()语句,括号里必须是整形表达式,case后一定是要整形以及常量。如case 1;不能是case n或case 0.1这样】
若想要表达周一至周五是工作日,周六日是休息日。
除上述的方法,也可用——多个case语句对应一个break(根据逻辑需要而定)
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日\n");
break;
case 6:
case 7:
printf("休息日\n");
break;
若原本只需一个break语句的代码若改成每个case后都加上break,这样会把原来整体代码执行的逻辑打乱。(依整体而言)
建议即便是最后一个break也要写上,可为后续修改添加提供方便。
若在给定的范围输入范围之外的数,会导致超出处理范围,最后什么都没有。
C语言给出这样的解决方案——加上default: 语句
即——
default:
printf("输入错误\n"); //——贴心提示(也可以不写)
break;
用于处理非法情况。
break语句的实际效果是把语句列表划分为不同部分。
编程好习惯:在最后一个case语句的后面加上一条break语句。(之所以这么写是可以避免出现在以前的最后一个case语句后面忘了添加break语句)。
default子句
如果表达的值与所有的case标签的值都不匹配怎么办?
其实也没什么,结构就是所有的语句都被跳过而已,程序并不会终止,也不会报错;因为这种情况在C语言中并不认为适合错误。
但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办?
你可以在语句列表中增加一条default子句,把下面的标签default: 写在任何一个case标签可以出现的位置。
当switch表达式的值并不匹配所有case标签的值时,这时default子句后面的语句就会执行;所以,每个switch语句中只能出现一条default子句。
但是它可以出现在语句列表的任何位置,而且语句又会像贯穿一个个case标签一样贯穿default子句。(即包括与被包括的意思)
【注:case: 与default: 后面都是有冒号存在的。】
switch case 语句中可能出现的关键字default和break,在if语句也是可以出现的。
如:
case 1:
if(n==1)
printf("hehe\n");
不能出现continue。(因为不知道会跳到哪里去。)
编程好习惯:
在每个switch语句中都放一条default子句是个好习惯,甚至可以在后边再加上一个break。
练习:
int main(){
int n=1;
int m=2;
switch(n){
case 1:m++;
case 2:n++;
case 3:
switch(n){
case 1:n++
case 2:m++;n++;break;
}
case 4:m++;break;
default:
break;
}
printf("m=%d,n=%d\n",m,n);
return 0;
}
【注:switch1允许嵌套使用。】
打印结果为m=5,n=3
具体请自行分析。(提一点:break语句在最后)