流程控制基本概念
- 預設情況下程式運作後,系統會按書寫順序從上至下依次執行程式中的每一行代碼。但是這并不能滿足我們所有的開發需求, 為了友善我們控制程式的運作流程,C語言提供3種流程控制結構,不同的流程控制結構可以實作不同的運作流程。
- 這3種流程結構分别是順序結構、選擇結構、循環結構
- 順序結構:
- 按書寫順序從上至下依次執行
-
08-C語言流程控制選擇結構循環結構
- 選擇結構
- 對給定的條件進行判斷,再根據判斷結果來決定執行代碼
-
08-C語言流程控制選擇結構循環結構 -
08-C語言流程控制選擇結構循環結構
- 循環結構
- 在給定條件成立的情況下,反複執行某一段代碼
-
08-C語言流程控制選擇結構循環結構 -
08-C語言流程控制選擇結構循環結構
- C語言中提供了兩大選擇結構, 分别是if和switch
選擇結構if
- if第一種形式
- 表示如果表達式為真,執行語句塊1,否則不執行
if(表達式) {
語句塊1;
}
後續語句;
if(age >= 18) {
printf("開網卡\n");
}
printf("買煙\n");
- if第二種形式
- 如果表達式為真,則執行語句塊1,否則執行語句塊2
- else不能脫離if單獨使用
if(表達式){
語句塊1;
}else{
語句塊2;
}
後續語句;
if(age > 18){
printf("開網卡\n");
}else{
printf("喊家長來開\n");
}
printf("買煙\n");
- if第三種形式
- 如果"表達式1"為真,則執行"語句塊1",否則判斷"表達式2",如果為真執行"語句塊2",否則再判斷"表達式3",如果真執行"語句塊3", 當表達式1、2、3都不滿足,會執行最後一個else語句
- 衆多大括号中,隻有一個大括号中的内容會被執行
- 隻有前面所有添加都不滿足, 才會執行else大括号中的内容
if(表達式1) {
語句塊1;
}else if(表達式2){
語句塊2;
}else if(表達式3){
語句塊3;
}else{
語句塊4;
}
後續語句;
if(age>40){
printf("給房卡");
}else if(age>25){
printf("給名片");
}else if(age>18){
printf("給網卡");
}else{
printf("給好人卡");
}
printf("買煙\n");
- if嵌套
- if中可以繼續嵌套if, else中也可以繼續嵌套if
if(表達式1){
語句塊1;
if(表達式2){
語句塊2;
}
}else{
if(表達式3){
語句塊3;
}else{
語句塊4;
}
}
- if注意點
- 任何數值都有真假性
#include <stdio.h>
int main(){
if(0){
printf("執行了if");
}else{
printf("執行了else"); // 被執行
}
}
-
- 當if else後面隻有一條語句時, if else後面的大括号可以省略
// 極其不推薦寫法
int age = 17;
if (age >= 18)
printf("開網卡\n");
else
printf("喊家長來開\n");
-
- 當if else後面的大括号被省略時, else會自動和距離最近的一個if比對
#include <stdio.h>
int main(){
if(0)
if(1)
printf("A\n");
else // 和if(1)比對
printf("B\n");
else // 和if(0)比對, 因為if(1)已經被比對過了
if (1)
printf("C\n"); // 輸出C
else // 和if(1)比對
printf("D\n");
}
-
- 如果if else省略了大括号, 那麼後面不能定義變量
#include <stdio.h>
int main(){
if(1)
int number = 10; // 系統會報錯
printf("number = %i\n", number);
}
#include <stdio.h>
int main(){
if(0){
int number = 10;
}else
int value = 20; // 系統會報錯
printf("value = %i\n", value);
}
-
- C語言中分号(;)也是一條語句, 稱之為空語句
// 因為if(10 > 2)後面有一個分号, 是以系統會認為if省略了大括号
// if省略大括号時隻能管控緊随其後的那條語句, 是以隻能管控分号
if(10 > 2);
{
printf("10 > 2");
}
// 輸出結果: 10 > 2
-
- 但凡遇到比較一個變量等于或者不等于某一個常量的時候,把常量寫在前面
#include <stdio.h>
int main(){
int a = 8;
// if(a = 10){// 錯誤寫法, 但不會報錯
if (10 == a){
printf("a的值是10\n");
}else{
printf("a的值不是10\n");
}
}
- if練習
- 從鍵盤輸入一個整數,判斷其是否是偶數,如果是偶數就輸出YES,否則輸出NO;
- 接收使用者輸入的1~7的整數,根據使用者輸入的整數,輸出對應的星期幾
- 接收使用者輸入的一個整數month代表月份,根據月份輸出對應的季節
- 接收使用者輸入的兩個整數,判斷大小後輸出較大的那個數
- 接收使用者輸入的三個整數,判斷大小後輸出較大的那個數
- 接收使用者輸入的三個整數,排序後輸出
- 實作石頭剪刀布
剪刀石頭布遊戲:
1)定義遊戲規則
剪刀 幹掉 布
石頭 幹掉 剪刀
布 幹掉石頭
2)顯示玩家開始猜拳
3)接收玩家輸入的内容
4)讓電腦随機産生一種拳
5)判斷比較
(1)玩家赢的情況(顯示玩家赢了)
(2)電腦赢的情況(顯示電腦赢了)
(3)平局(顯示平局)
-
08-C語言流程控制選擇結構循環結構 -
08-C語言流程控制選擇結構循環結構 -
08-C語言流程控制選擇結構循環結構
選擇結構switch
- 由于 if else if 還是不夠簡潔,是以switch 就應運而生了,他跟 if else if 互為補充關系。switch 提供了點的多路選擇
- 格式:
switch(表達式){
case 常量表達式1:
語句1;
break;
case 常量表達式2:
語句2;
break;
case 常量表達式n:
語句n;
break;
default:
語句n+1;
break;
}
- 語義:
- 計算"表達式"的值, 逐個與其後的"常量表達式"值相比較,當"表達式"的值與某個"常量表達式"的值相等時, 即執行其後的語句, 然後跳出switch語句
- 如果"表達式"的值與所有case後的"常量表達式"均不相同時,則執行default後的語句
- 示例:
#include <stdio.h>
int main() {
int num = 3;
switch(num){
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注意點
- switch條件表達式的類型必須是整型, 或者可以被提升為整型的值(char、short)
#include <stdio.h>
int main() {
switch(1.1){ // 報錯
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
default:
printf("回火星去\n");
break;
}
}
-
- case的值隻能是常量, 并且還必須是整型, 或者可以被提升為整型的值(char、short)
#include <stdio.h>
int main() {
int num = 3;
switch(1){
case 1:
printf("星期一\n");
break;
case 'a':
printf("星期二\n");
break;
case num: // 報錯
printf("星期三\n");
break;
case 4.0: // 報錯
printf("星期四\n");
break;
default:
printf("回火星去\n");
break;
}
}
-
- case後面常量表達式的值不能相同
#include <stdio.h>
int main() {
switch(1){
case 1: // 報錯
printf("星期一\n");
break;
case 1: // 報錯
printf("星期一\n");
break;
default:
printf("回火星去\n");
break;
}
}
-
- case後面要想定義變量,必須給case加上大括号
#include <stdio.h>
int main() {
switch(1){
case 1:{
int num = 10;
printf("num = %i\n", num);
printf("星期一\n");
break;
}
case 2:
printf("星期一\n");
break;
default:
printf("回火星去\n");
break;
}
}
-
- switch中隻要任意一個case比對, 其它所有的case和default都會失效. 是以如果case和default後面沒有break就會出現穿透問題
#include <stdio.h>
int main() {
int num = 2;
switch(num){
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n"); // 被輸出
case 3:
printf("星期三\n"); // 被輸出
default:
printf("回火星去\n"); // 被輸出
break;
}
}
-
- switch中default可以省略
#include <stdio.h>
int main() {
switch(1){
case 1:
printf("星期一\n");
break;
case 2:
printf("星期一\n");
break;
}
}
-
- switch中default的位置不一定要寫到最後, 無論放到哪都會等到所有case都不比對才會執行(穿透問題除外)
#include <stdio.h>
int main() {
switch(3){
case 1:
printf("星期一\n");
break;
default:
printf("Other,,,\n");
break;
case 2:
printf("星期一\n");
break;
}
}
- if和Switch轉換
- 看上去if和switch都可以實作同樣的功能, 那麼在企業開發中我們什麼時候使用if, 什麼時候使用switch呢?
- if else if 針對于範圍的多路選擇
- switch 是針對點的多路選擇
- 判斷使用者輸入的資料是否大于100
#include <stdio.h>
int main() {
int a = -1;
scanf("%d", &a);
if(a > 100){
printf("使用者輸入的資料大于100");
}else{
printf("使用者輸入的資料不大于100");
}
}
#include <stdio.h>
int main() {
int a = -1;
scanf("%d", &a);
// 挺(T)萌(M)的(D)搞不定啊
switch (a) {
case 101:
case 102:
case 103:
case 104:
case 105:
printf("大于\n");
break;
default:
printf("不大于\n");
break;
}
}
- 練習
- 實作分數等級判定
要求使用者輸入一個分數,根據輸入的分數輸出對應的等級
A 90~100 99/10 = 9 90/10= 9 98/10 = 9 100/10 = 10
B 80~89 89/10 = 8
C 70~79
D 60~69
E 0~59
-
- 實作+ - * / 簡單電腦
- C語言中提供了三大循環結構, 分别是while、dowhile和for
- 循環結構是程式中一種很重要的結構。
- 其特點是,在給定條件成立時,反複執行某程式段, 直到條件不成立為止。
- 給定的條件稱為"循環條件",反複執行的程式段稱為"循環體"
-
08-C語言流程控制選擇結構循環結構
循環結構while
while ( 循環控制條件 ) {
循環體中的語句;
能夠讓循環結束的語句;
....
}
- 構成循環結構的幾個條件
- 循環控制條件
- 循環退出的主要依據,來控制循環到底什麼時候退出
- 循環體
- 循環的過程中重複執行的代碼段
- 能夠讓循環結束的語句(遞增、遞減、真、假等)
- 能夠讓循環條件為假的依據,否則退出循環
- 循環控制條件
int count = 0;
while (count < 3) { // 循環控制條件
printf("發射子彈~哔哔哔哔\n"); // 需要反複執行的語句
count++; // 能夠讓循環結束的語句
}
- while循環執行流程
- 首先會判定"循環控制條件"是否為真, 如果為假直接跳到循環語句後面
- 如果"循環控制條件"為真, 執行一次循環體, 然後再次判斷"循環控制條件"是否為真, 為真繼續執行循環體,為假跳出循環
- 重複以上操作, 直到"循環控制條件"為假為止
#include <stdio.h>
int main(){
int count = 4;
// 1.判斷循環控制條件是否為真,此時為假是以跳過循環語句
while (count < 3) {
printf("發射子彈~哔哔哔哔\n");
count++;
}
// 2.執行循環語句後面的代碼, 列印"循環執行完畢"
printf("循環執行完畢\n");
}
#include <stdio.h>
int main(){
int count = 0;
// 1.判斷循環控制條件是否為真,此時0 < 3為真
// 4.再次判斷循環控制條件是否為真,此時1 < 3為真
// 7.再次判斷循環控制條件是否為真,此時2 < 3為真
// 10.再次判斷循環控制條件是否為真,此時3 < 3為假, 跳過循環語句
while (count < 3) {
// 2.執行循環體中的代碼, 列印"發子彈"
// 5.執行循環體中的代碼, 列印"發子彈"
// 8.執行循環體中的代碼, 列印"發子彈"
printf("發射子彈~哔哔哔哔\n");
// 3.執行"能夠讓循環結束的語句" count = 1
// 6.執行"能夠讓循環結束的語句" count = 2
// 9.執行"能夠讓循環結束的語句" count = 3
count++;
}
// 11.執行循環語句後面的代碼, 列印"循環執行完畢"
printf("循環執行完畢\n");
}
- while循環注意點
#include <stdio.h>
int main(){
while (1) { // 死循環
printf("發射子彈~哔哔哔哔\n");
// 沒有能夠讓循環結束的語句
}
}
-
- 當while後面隻有一條語句時,while後面的大括号可以省略
#include <stdio.h>
int main(){
while (1) // 死循環
printf("發射子彈~哔哔哔哔\n");
// 沒有能夠讓循環結束的語句
}
-
- 如果while省略了大括号, 那麼後面不能定義變量
#include <stdio.h>
int main(){
while (1) // 死循環
int num = 10; // 報錯
// 沒有能夠讓循環結束的語句
}
#include <stdio.h>
int main(){
int count = 0;
while (count < 3);{ // 死循環
printf("發射子彈~哔哔哔哔\n");
count++;
}
}
-
- 最簡單的死循環
// 死循環一般在作業系統級别的應用程式會比較多, 日常開發中很少用
while (1);
- while練習
- 計算1 + 2 + 3 + ...n的和
- 擷取1~100之間 7的倍數的個數
循環結構do while
do {
循環體中的語句;
能夠讓循環結束的語句;
....
} while (循環控制條件 );
- 示例
int count = 0;
do {
printf("發射子彈~哔哔哔哔\n");
count++;
}while(count < 10);
- do-while循環執行流程
- 首先不管while中的條件是否成立, 都會執行一次"循環體"
- 執行完一次循環體,接着再次判斷while中的條件是否為真, 為真繼續執行循環體,為假跳出循環
- 應用場景
- 密碼校驗
#include<stdio.h>
int main()
{
int num = -1;
do{
printf("請輸入密碼,驗證您的身份\n");
scanf("%d", &num);
}while(123456 != num);
printf("主人,您終于回來了\n");
}
- while和dowhile應用場景
- 絕大多數情況下while和dowhile可以互換, 是以能用while就用while
- 無論如何都需要先執行一次循環體的情況, 才使用dowhile
- do while 曾一度提議廢除,但是他在輸入性檢查方面還是有點用的
循環結構for
for(初始化表達式;循環條件表達式;循環後的操作表達式) {
循環體中的語句;
}
for(int i = 0; i < 10; i++){
printf("發射子彈~哔哔哔哔\n");
}
-
for循環執行流程
+首先執行"初始化表達式",而且在整個循環過程中,隻會執行一次初始化表達式
- 接着判斷"循環條件表達式"是否為真,為真執行循環體中的語句
- 循環體執行完畢後,接下來會執行"循環後的操作表達式",然後再次判斷條件是否為真,為真繼續執行循環體,為假跳出循環
- 重複上述過程,直到條件不成立就結束for循環
- for循環注意點:
- 和while一模一樣
-
for(;;);
- for和while應用場景
- while能做的for都能做, 是以企業開發中能用for就用for, 因為for更為靈活
- 而且對比while來說for更節約記憶體空間
int count = 0; // 初始化表達式
while (count < 10) { // 條件表達式
printf("發射子彈~哔哔哔哔 %i\n", count);
count++; // 循環後增量表達式
}
// 如果初始化表達式的值, 需要在循環之後使用, 那麼就用while
printf("count = %i\n", count);
// 注意: 在for循環初始化表達式中定義的變量, 隻能在for循環後面的{}中通路
// 是以: 如果初始化表達式的值, 不需要在循環之後使用, 那麼就用for
// 因為如果初始化表達式的值, 在循環之後就不需要使用了 , 那麼用while會導緻性能問題
for (int count = 0; count < 10; count++) {
printf("發射子彈~哔哔哔哔 %i\n", count);
}
// printf("count = %i\n", count);
// 如果需要使用初始化表達式的值, 也可以将初始化表達式寫到外面
int count = 0;
for (; count < 10; count++) {
printf("發射子彈~哔哔哔哔\n", count);
}
printf("count = %i\n", count);
四大跳轉
- C語言中提供了四大跳轉語句, 分别是return、break、continue、goto
- break:
- 立即跳出switch語句或循環
- 應用場景:
- switch
-
08-C語言流程控制選擇結構循環結構 -
08-C語言流程控制選擇結構循環結構 -
- 列印 10 的所有加法組和
- break注意點:
- break離開應用範圍,存在是沒有意義的
if(1) {
break; // 會報錯
}
-
- 在多層循環中,一個break語句隻向外跳一層
while(1) {
while(2) {
break;// 隻對while2有效, 不會影響while1
}
printf("while1循環體\n");
}
-
- break下面不可以有語句,因為執行不到
while(2){
break;
printf("打我啊!");// 執行不到
}
- continue
- 結束本輪循環,進入下一輪循環
-
-
08-C語言流程控制選擇結構循環結構 - continue注意點:
- continue離開應用範圍,存在是沒有意義的
if(1) {
continue; // 會報錯
}
- goto
- 這是一個不太值得探讨的話題,goto 會破壞結構化程式設計流程,它将使程式層次不清,且不易讀,是以慎用
- goto 語句,僅能在本函數内實作跳轉,不能實作跨函數跳轉(短跳轉)。但是他在跳出多重循環的時候效率還是蠻高的
-
08-C語言流程控制選擇結構循環結構
#include <stdio.h>
int main(){
int num = 0;
// loop:是定義的标記
loop:if(num < 10){
printf("num = %d\n", num);
num++;
// goto loop代表跳轉到标記的位置
goto loop;
}
}
#include <stdio.h>
int main(){
while (1) {
while(2){
goto lnj;
}
}
lnj:printf("跳過了所有循環");
}
- return
- 結束目前函數,将結果傳回給調用者
- 不着急, 放一放,學到函數我們再回頭來看它
循環的嵌套
- 循環結構的循環體中存在其他的循環結構,我們稱之為循環嵌套
- 注意: 一般循環嵌套不超過三層
- 外循環執行的次數 * 内循環執行的次數就是内循環總共執行的次數
while(條件表達式) {
while循環結構 or dowhile循環結構 or for循環結構
}
for(初始化表達式;循環條件表達式;循環後的操作表達式) {
while循環結構 or dowhile循環結構 or for循環結構
}
do {
while循環結構 or dowhile循環結構 or for循環結構
} while (循環控制條件 );
- 循環優化
- 在多重循環中,如果有可能,應當将最長的循環放在最内層,最短的循環放在最外層,以減少 CPU 跨切循環層的次數
for (row=0; row<100; row++) {
// 低效率:長循環在最外層
for ( col=0; col<5; col++ ) {
sum = sum + a[row][col];
}
}
for (col=0; col<5; col++ ) {
// 高效率:長循環在最内層
for (row=0; row<100; row++) {
sum = sum + a[row][col];
}
}
-
- 列印好友清單
好友清單1
好友1
好友2
好友清單2
好友1
好友2
好友清單3
好友1
好友2
for (int i = 0; i < 4; i++) {
printf("好友清單%d\n", i+1);
for (int j = 0; j < 4; j++) {
printf(" 角色%d\n", j);
}
}
圖形列印
- 一重循環解決線性的問題,而二重循環和三重循環就可以解決平面和立體的問題了
- 列印矩形
****
****
****
// 3行4列
// 外循環控制行數
for (int i = 0; i < 3; i++) {
// 内循環控制列數
for (int j = 0; j < 4; j++) {
printf("*");
}
printf("\n");
}
- 列印三角形
- 尖尖朝上,改變内循環的條件表達式,讓内循環的條件表達式随着外循環的i值變化
- 尖尖朝下,改變内循環的初始化表達式,讓内循環的初始化表達式随着外循環的i值變化
*
**
***
****
*****
/*
最多列印5行
最多列印5列
每一行和每一列關系是什麼? 列數<=行數
*/
for(int i = 0; i< 5; i++) {
for(int j = 0; j <= i; j++) {
printf("*");
}
printf("\n");
}
*****
****
***
**
*
for(int i = 0; i< 5; i++) {
for(int j = i; j < 5; j++) {
printf("*");
}
printf("\n");
}
-
- 列印特殊三角形
1
12
123
for (int i = 0; i < 3; i++) {
for (int j = 0; j <= i; j++) {
printf("%d", j+1);
}
printf("\n");
}
1
22
333
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= i; j++) {
printf("%d", i);
}
printf("\n");
}
--*
-***
*****
for (int i = 0; i <= 5; i++) {
for (int j = 0; j < 5 - i; j++) {
printf("-");
}
for (int m = 0; m < 2*i+1; m++) {
printf("*");
}
printf("\n");
}
-
- 列印99乘法表
1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
printf("%d * %d = %d \t", j, i, (j * i));
}
printf("\n");
}