分支和循环
1.if语句
1.1if语句的语法形式如下:
if(表达式) 语句
表达式成立(为真)语句执行;表达式不成立(为假)语句不执行。
在C语言中,0为假,非0为真。
//instance #include <stdio.h> int main(){ int num = 0; scanf("%d",&num); if(num%2 == 1){ printf("%d 是奇数\n",num); } return 0; }
1.2 else
如果一个数不是奇数,那就是偶数,当需要清楚判断数的奇偶需要引入if…else…语句,语法形式如下:
if() 语句1 else 语句2
//两个例子助于理解 //数的奇偶判断 #include <stdio.h> int main() { int num = 0; scanf("%d", &num); if(num % 2 == 1) printf("%d 是奇数\n", num); else printf("%d 是偶数\n", num); return 0; } //判断人是否成年 #include <stdio.h> int main() { int age = 0; scanf("%d", &age); if(age>=18) printf("成年\n"); else printf("未成年\n"); return 0; }
1.3 分支中包含多条语句
默认if和else语句中默认都只控制一条语句。
举个例子简单理解
if(今天学习了) printf("又进步了一点点"); printf("日拱一卒,积少成多!"); //if语句只能控制第一个输出语句,即使你今天没有学习,也会输出“日拱一卒,积少成多!”
如果想自由设置if和else的控制语句,需要应用“{}”。将所对应的控制语句全装进去就可以了。
1.4 嵌套if
在if-else语句中,else可以与另一个if语句连用,构成多重判断。
//要求输入一个整数,判断输入的数是零、正数还是负数,代码实现如下: #include <stdio.h> int main() { int num = 0; scanf("%d", &num); if(num == 0) printf("输⼊的数字是0\n"); else if(num > 0) //这⾥的if 相当于嵌套在else语句中,形成了嵌套结构 printf("输⼊的数字是正数\n"); else printf("输⼊的数字是负数\n"); return 0; } //新问题:输入一个整数,若为整数则判断其奇偶并输出;不是整数则输出为“非正数” #include <stdio.h> int main() { int num = 0; scanf("%d", &num); if(num>0) { if(num%2 == 0) printf("偶数\n"); else printf("奇数\n"); } else { printf("⾮正数\n"); } return 0; }
1.5 悬空else问题
如果有多个if和else,牢记一个原则——else总是跟最近的if匹配。当我们读代码时,不要根据对齐的问题来进行条件判断。举例理解:
{ int a = 0; int b = 2; if(a == 1) if(b == 2) printf("hehe\n"); else printf("haha\n"); } 上下两代码块效果相同 { int a = 0; int b = 2; if(a == 1) { if(b == 2) printf("hehe\n"); else printf("haha\n"); } }
2.关系操作符
C语言用于比较的表达式,称为“关系表达式”,里面使用的运算符就称为“关系运算符”,共6个:
【> ,大于运算符】、【< ,小于运算符】、【>= ,大于等于运算符】、【<= ,小于等于运算符】、【== ,相等运算符】、【!= ,不相等运算符】
关系表达式的返回值通常为0或1,表示真假(0假,非0真)
关系表达式常用于if或while结构。
【注意!!!在运用相等运算符“==”时,常常会出现使用了“=”的错误,这样就将比较变为了赋值,将判断的功能给抹掉了,会直接进行判断为真的操作。两种解决办法:1、认真敲代码,仔细检查;2、更为保准的方法是将数字放在运算符左侧,变量放在右侧,这样即使粗心犯了这种错误,编译器会及时报错,原理是“=”左边只能是变量╰( ̄ω ̄o)】
【另一个需要避免的错误就是:多个关系运算符不宜连用】
i<j<k; 在此语句中,比较的顺序是从左到右,即(i<j)<k,当第一个比较完后,就变成了0<k或1<k的判断,这样难以保证j是区间(i,k)中的数,有违我们的本意
当需要进行上述情况的多重比较时,得使用逻辑操作符(下面呢)
3.条件操作符
条件操作符也叫三目操作符,需要结束3个操作数的,形式如下:
exp1 ? exp2 : exp3
条件操作符的计算逻辑是:exp1为真则exp2进行计算,结果是整个表达式的结果;exp1为假则exp3进行计算,结果是整个表达式的值。(1真算2,1假算3)
//instance 正常使用if-else语句 { scanf("%d", &a); if (a > 5) b = 3; else b = -3; printf("%d\n", b); } 用条件操作符改写 { scanf("%d", &a); b = a>5 ? 3:-3; printf("%d\n", b); }
4.逻辑运算符:&&、||、!
逻辑运算符提供了判断功能,用于构建更复杂的表达式,有三个运算符。
-
!:逻辑取反运算符;
-
&&:逻辑与运算符,并且的意思(两边同时为真整个表达式才为真)
双目操作符,使用方式a&&b
-
||:逻辑或运算符,或的意思(两边有一个为真整个表达式就为真)
双目操作符,使用方式a||b
逻辑运算符最经典的应用问题:闰年判断
输入一个年份year,判断year是不是闰年。
首先明确闰年的判断规则:
-
能被4整除并且不能被100整数是闰年;
-
能被400整除是闰年。
代码实现:
#include<stdio.h> int main(){ int year; scanf("%d",&year); if(year%4==0&&year%100!=0) printf("%d是闰年\n",year); else if(year%400==0)//也可以将这两句判断改为条件运算符模式if((year%4==0 && year%100!=0) || (year%400==0)) printf("%d是闰年\n",year); else printf("%d不是闰年\n",year); return 0; }
【短路问题】
C语言逻辑运算符的一个特点——总是先对左侧表达式求值,再对右侧表达式求值,顺序固定。
如果左边的表达式满足逻辑运算符的条件时,就不再对右边的表达式求值。这种情况称为短路。
像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算的运算称为短路求值。
//instance #include <stdio.h> int main() { int i = 0,a=0,b=2,c =3,d=4; i = a++ && ++b && d++; printf("i = %d\n a = %d\n b = %d\n c = %d\nd = %d\n",i, a, b, c, d); return 0; }//结果输出为i=0 a=1 b=2 c=3 b=4 #include <stdio.h> int main() { int i = 0,a=0,b=2,c =3,d=4; i = a++||++b||d++; printf("i=%d\n a = %d\n b = %d\n c = %d\nd = %d\n",i, a, b, c, d); return 0; }//结果输出为i=1 a=1 b=3 c=3 b=4
5.switch语句
switch语句也是C语言中用来实现分支结构的语句(另一个是if语句)
应用情况:用于判断条件有多个结果的情况。它把多重的else-if改成更易用、可读性更好的形式。
switch(expression){ case value1:statement case value2:statement default:statement }
简述含义:根据表达式expression不同的值,执行相应的case分支,找不到对应的值,执行default分支。
注:
-
switch后的expression必须是整型表达式;
-
case后的值必须是整形常量表达式。
代码注意:case和后面的数字之间必须有空格。
【每一个case语句中的代码执行完成后,需要加上break,才能跳出这个switch语句】
当我们switch语句进入的case语句中无break,代码则会继续往下执行,包括其他case中的代码,直到遇见break语句或者switch语句结束。【break语句很重要,它保证了分支效果能够得到真正地实现!】
switch语句中的case语句和default语句没有顺序要求,随便设置先后,一般将default放在最后处理。
//instance #include <stdio.h> 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; }
6.while循环语句
C语言中有三种循环语句,while是其中一种。
while(表达式) 语句;
while的执行流程:首先执行判断表达式,表达式值为0(假),循环之间结束;表达式值不为0(真),则执行循环语句,语句执行完后再继续判断,否则进行下一次判断。
//instance #include <stdio.h> int main() { int i = 1; while(i<=10) { printf("%d ", i); i = i+1; } return 0; }//输出数字1~10
7.for循环
7.1 语法形式
for(表达式1;表达式2;表达式3) 语句;//多个语句使用大括号包上,同if用法
-
表达式1用于循环变量的初始化;
-
表达式2用于循环结束条件的判断;
-
表达式3用于循环变量的调整。
7.2 for循环的执行过程
首先执行表达式1初始化循环变量,接下来执行表达式2的判断部分,表达式2 的结果如果==0(即超过临界条件),则循环结束;表达式2的结果如果!=0则执行循环语句,循环语句执行完后,再去执行表达式3,调整循环变量,然后再去表达式2继续执行,判断是否再次循环。
7.3 for循环实践
//打印1~10 #include<stdio.h> int main(){ int i=0; for(i=1;i<=10;i++) { printf("%d\n",i); } return 0; }
7.4 while循环和for循环的对比
for和while在实现循环过程中都有初始化、判断、变量调整这三部分,但是for循环的三个部分非常集中,便于代码维护,而代码较多时,while循环的三个部分较为分散,所以从形式上讲,for循环更具优越性。
//instance,计算1~100之间3的倍数之和 #include <stdio.h> int main(){ int i = 0; int sum = 0; for(i=1; i<=100; i++) { if(i % 3 == 0) sum += i; } printf("%d\n", sum); return 0; } //优化 #include <stdio.h> int main(){ int i = 0; int sum = 0; for(i=3; i<=100; i+=3)//减少冗余的循环过程 { sum += i; } printf("%d\n", sum); return 0; }
8.do-while循环
8.1语法形式
do 语句; while(表达式)
while和for这两种循环都是先进行判断,满足条件进入循环,执行循环语句;
而do-while循环则是先进行循环体,执行循环语句,然后再执行while后的判断表达式,表达式为真,进行下一次循环,否则不再进行循环。
8.2 do-while循环的执行流程
在do while循环中先执行图上的“语句”,执行完语句,再去执行“判断表达式”,判断表达式结果是!=0,则继续循环,执行循环语句;否则循环结束。
【所以在do while语句循环体至少执行一次】
8.3 do while循环实例
//打印1~10 #include <stdio.h> int main(){ int i = 1; do { printf("%d\n", i); i = i + 1; }while(i<=10); return 0; } //计算输入数是几位数 #include<stdio.h> int main(){ int t=0; scanf("%d",&t); int n=0; do { n++; t/=10; }while(t); printf("输入数是%d位数",n); return 0; }
9.break和continue语句
在循环执行过程中,某些状况发送时,需要提前终止循环,在C语言中提供了break和continue两个关键字。
-
break的作用时用于永久的终止循环,只要break被执行,直接跳出循环,继续往后执行;
-
continue作用是跳过本次循环中continue后面的代码,在for循环和while循环中有所差异。
9.1 while循环中的break和continue的举例
#include <stdio.h> int main(){ int i = 1; while(i<=10) { if(i == 5) break;//当i等于5后,执⾏break,循环终⽌ printf("%d", i);//等于5后这句当然不执行^.^ i = i+1; } return 0; }//只输出“1 2 3 4” //当我们将上面的break语句换位continue语句 #include <stdio.h> int main(){ int i = 1; while(i<=10) { if(i == 5) continue; printf("%d", i); i = i+1; } return 0; }//千万不要认为此时会输出除了5以外的1~10,因为continue会跳过“i=i+1”这个代码,所以程序陷入死循环。
9.2 for循环中的break和continue的举例
#include <stdio.h> int main() { int i = 1; for(i=1; i<=10; i++) { if(i == 5) break; printf("%d ", i); } return 0; }//效果同while循环 #include <stdio.h> int main() { int i = 1; for(i=1; i<=10; i++) { if(i == 5) continue;//这⾥continue跳过了后边的打印,来到了i++的调整部分 printf("%d ", i); } return 0; }//此时会正常打印除了5以外的1~10
【for循环中continue并不会耽误变量调整的进行】
9.3 do while循环中的break和continue的举例
//效果和while一致 #include <stdio.h> int main() { int i = 1; do { if(i == 5) break; printf("%d ", i); i = i + 1; }while(i<=10); return 0; } #include <stdio.h> int main() { int i = 1; do { if(i == 5) continue; printf("%d ", i); i = i + 1; }while(i<=10); return 0; }
10.循环的嵌套
//instance //打印100~200中的素数(判定条件:除了1和其本身,再无其他因数) #include <stdio.h> int main() { int i = 0; //循环产⽣100~200的数字 for(i=100; i<=200; i++) { //判断i是否为素数 //循环产⽣2~i-1之间的数字 int j = 0; int flag = 1;//假设i是素数 for(j=2; j<i; j++) { if(i % j == 0) { flag = 0; break; } } if(flag == 1) printf("%d ", i); } return 0; }
11.goto语句
C语言中提供了goto语句和跳转标号,goto语句可以实现在同一个函数内跳转到设置好的标号处。
#include <stdio.h> int main() { printf("1\n"); goto next; printf("2\n"); next: printf("跳过了2的打印\n"); return 0; }
-
goto语句使用不当会导致函数内部随意乱转,打乱程序的执行流程,建议少使;
-
但goto语句在多层循环的代码中,如果想快速跳出就使用它(就决定是你了!goto语句)。
【break语句跳出的是单层循环体】