?個人主頁:?Anmia.
??所屬專欄:?C Language??操作環(huán)境:?Visual Studio 2019 版本
?
目錄
?1.什么是循環(huán)結(jié)構(gòu)?
2.while循環(huán)
while流程圖
while語句中的break和continue
break?
continue
?3.for循環(huán)
for流程圖
for循環(huán)中的break和continue
break
continue?
for語句的循環(huán)控制變量
一些for循環(huán)的變種
do...while()循環(huán)
do...while()循環(huán)流程圖
do...while對比while,for有什么特殊?
do while循環(huán)中的break和continue
break?
continue?
練習(xí)
練習(xí)1
練習(xí)2
?練習(xí)3
練習(xí)4
練習(xí)5
練習(xí)6
后言???????
?1.什么是循環(huán)結(jié)構(gòu)?
用順序結(jié)構(gòu)和選擇結(jié)構(gòu)可以解決簡單的,不重復(fù)的問題,但在日常生活中或者是在應(yīng)用程序中,許多問題是需要反復(fù)處理執(zhí)行的。
- 問題1:分別統(tǒng)計全班50個學(xué)生的平均成績。
- 問題2:求30個整數(shù)的和。
要處理以上問題,最原始的方法是分別編寫若干個相同或者相似的語句或者程序段來進行處理,這種方法工作量大,程序長,重復(fù),難以閱讀和維護。
循環(huán)結(jié)構(gòu)又稱為重復(fù)結(jié)構(gòu),利用循環(huán)結(jié)構(gòu)可以方便的處理這種需要重復(fù)處理的問題。大多數(shù)應(yīng)用程序都是包含循環(huán)結(jié)構(gòu)。
C語言給我們提供了三種循環(huán)語句:
- while
- do...while
- for
2.while循環(huán)
我們已經(jīng)掌握了,if語句:
if(條件) ??語句;
當(dāng)條件滿足的情況下,if語句后的語句執(zhí)行,否則不執(zhí)行。
但是這個語句只會執(zhí)行一次。
由于我們發(fā)現(xiàn)生活中很多的實際的例子是:同一件事情我們需要完成很多次。
那我們怎么做呢?
C語言中給我們引入了: while 語句,可以實現(xiàn)循環(huán)。while(表達式) 循環(huán)語句;
while流程圖
?
比如我們實現(xiàn):
在屏幕上打印1-10的數(shù)字。#include <stdio.h> int main() { int i = 1; while(i<=10) { printf("%d ", i); i = i+1; } return 0; }
以 i 作為是否執(zhí)行while循環(huán)的條件,我們此時i =1 滿足 i<=10 這個循環(huán)條件,所以加入whilex循環(huán)。先打印1,然后i+1變成2,2再和循環(huán)條件i<=10進行判斷,滿足則繼續(xù)執(zhí)行循環(huán)體,直到i=11不滿足i<=10,退出循環(huán)體,結(jié)束循環(huán)。運行結(jié)果如下
上面的代碼已經(jīng)幫我了解了 while 語句的基本語法,那我們再了解一下:
?
while語句中的break和continue
break?
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
if(i == 5)
break;
printf("%d ", i);
i = i+1;
}
return 0;
}
這里的輸出結(jié)果是什么?
答案如圖。
看運行結(jié)果不難看出,在i 加到5時,在進行if循環(huán)判斷時,if條件成立,執(zhí)行break語句。直接跳出了當(dāng)前的while循環(huán),不再執(zhí)行后面的循環(huán)語句。
通過之前學(xué)習(xí)的switch中的break,似乎效果一致,即跳出當(dāng)前的循環(huán)語句/switch語句。
- 總結(jié):
- break在while循環(huán)中的作用:
- 其實在循環(huán)中只要遇到break,就停止后期的所有的循環(huán),直接終止循環(huán)。
- 所以:while中的break是用于永久終止循環(huán)的。
?
continue
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
?? i = i+1;
if(i == 5)
continue;
printf("%d ", i);
}
return 0;
}
這段代碼的運行結(jié)果又是什么呢?
答案如圖。
看運行結(jié)果不難看出,進入循環(huán)i先+1后打印,所以沒有打印1。當(dāng)i+1=5時進入if中的語句,執(zhí)行continue,我們發(fā)現(xiàn)沒打印5,但是打印了后面的6 7 8 9?10 11。
- 沒打印5的原因:因為continue是結(jié)束本次循環(huán)后面的語句,因此在Continue執(zhí)行后,后面的printf被跳過了,直接跳回到i=i+1,繼續(xù)循環(huán)往復(fù)。
- 打印了11的原因:因為i=10仍然是滿足條件i<=10后還會執(zhí)行循環(huán)體。
- 總結(jié):
- continue在while循環(huán)中的作用就是:
- continue是用于終止本次循環(huán)的,也就是本次循環(huán)中continue后邊的代碼不會再執(zhí)行,
- 而是直接跳轉(zhuǎn)到while語句的判斷部分。進行下一次循環(huán)的入口判斷。
下面再看兩段代碼,分別是什么意思?
#include <stdio.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
??? putchar(ch);
return 0;
}
getchar() ?- 獲取(輸入)一個字符
getchar 讀取字符成功時,返回字符的ASCLL碼值
讀取失敗時 或者 遇到文件末尾時就返回EOF?windows環(huán)境Ctrl + z getchar返回 EOF
詳細見:
【C語言】EOF搭配while循環(huán)來控制scanf輸入的次數(shù)_Anmia.的博客-CSDN博客
#include <stdio.h>
int main()
{
?? char ch = '\0';
while ((ch = getchar()) != EOF)
{
?? if (ch < ‘0’ || ch > ‘9’)
???? continue;
?? putchar(ch);
}
return 0;
}
這個代碼的作用是:只打印數(shù)字字符,跳過其他字符的。
?3.for循環(huán)
我們已經(jīng)知道了while循環(huán),但是我們?yōu)槭裁催€要一個for循環(huán)呢?
首先來看看for循環(huán)的語法:for(表達式1; 表達式2; 表達式3) 循環(huán)語句;
- 表達式1:為初始化部分,用于初始化循環(huán)變量的。
- 表達式2:為條件判斷部分,用于判斷循環(huán)時候終止。
- 表達式3:為調(diào)整部分,用于循環(huán)條件的調(diào)整。
例子1:
使用for循環(huán) 在屏幕上打印1-10的數(shù)字。
#include <stdio.h>
int main()
{
int i = 0;
//for(i=1/*初始化*/; i<=10/*判斷部分*/; i++/*調(diào)整部分*/)
for(i=1; i<=10; i++)
{
printf("%d ", i);
}
return 0;
}
?
for流程圖
現(xiàn)在我們對比一下for循環(huán)和while循環(huán)。
//實現(xiàn)相同的功能,使用while
int i = 0;
i=1;//初始化部分
while(i<=10)//判斷部分
{
printf("hehe\n");
i = i+1;//調(diào)整部分
}
//實現(xiàn)相同的功能,使用for
for(i=1; i<=10; i++)
{
printf("hehe\n");
}
可以發(fā)現(xiàn)在while循環(huán)中依然存在循環(huán)的三個必須條件,但是由于風(fēng)格的問題使得三個部分很可能偏離較
遠,這樣
查找修改就不夠集中和方便。所以,for循環(huán)的風(fēng)格更勝一籌;for循環(huán)使用的頻率也最高。
for循環(huán)中的break和continue
break
我們發(fā)現(xiàn)在for循環(huán)中也可以出現(xiàn)break和continue,他們的意義和在while循環(huán)中是一樣的。
但是還是有些差異:
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
break;
printf("%d ",i);
}
return 0;
}
continue?
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
continue;
printf("%d ",i);
}
return 0;
}
通過和while的代碼對比,相信不難區(qū)分它們的寫法
for語句的循環(huán)控制變量
建議:
1. 不可在for 循環(huán)體內(nèi)修改循環(huán)變量,防止 for 循環(huán)失去控制。
2. 建議for語句的循環(huán)控制變量的取值采用“前閉后開區(qū)間”寫法。
int i = 0;
//前閉后開的寫法
for(i=0; i<10; i++)
{}
//兩邊都是閉區(qū)間
for(i=0; i<=9; i++)
{}
一些for循環(huán)的變種
#include <stdio.h>
int main()
{
for (;;)
{
printf("hehe\n");
}
}
for循環(huán)中的初始化部分,判斷部分,調(diào)整部分是可以省略的,但是不建議初學(xué)時省略,容易導(dǎo)致問題。?
這里打印多少個hehe?
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
printf("hehe\n");
}
}
return 0;
}
答案是100個,這種形式是for的嵌套。
代碼邏輯:
i=0--> i<10成立進入外層for --> j=0 --> j<10成立進入內(nèi)層for -->打印hehe\n --> j++后 j=2? ? ? ?--> j<10成立繼續(xù)循環(huán)........直到 j=10,j<10不成立跳出內(nèi)層for---> i++后i=2 --> i<10成立再次進入外層for......直到i=10,j<10不成立跳出外層for,for嵌套結(jié)束。
- 簡單點看
無非就是滿足for循環(huán)條件就進入循環(huán),只是外層for循環(huán)體中又有一個內(nèi)層for而已。
如果省略掉初始化部分,這里打印多少個hehe?
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;
for (; i < 10; i++)
{
for (; j < 10; j++)
{
printf("hehe\n");
}
}
return 0;
}
?
答案是10個,對比上一題,為什么少打印了那么多?主要問題出現(xiàn)在內(nèi)層初始化部分被省略了,當(dāng)j++第一次到j(luò)=10內(nèi)層條件不滿足,跳出內(nèi)層循環(huán)到i++,i=2時i<10是滿足的,會執(zhí)行外層for的循環(huán)體,可是問題就是j之前已經(jīng)++到10了,內(nèi)層for有沒有初始化部分,會直接檢查條件部分是否滿足,但j此時是10了,就j<10這個條件就不滿足了,因此不會再執(zhí)行內(nèi)層for循環(huán)。
使用多余一個變量控制循環(huán)
int x, y;
??for (x = 0, y = 0; x<2 && y<5; ++x, y++)
?{
????printf("hehe\n");
?}
例題1:
請問下面循環(huán)要循環(huán)多少次?
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for (i = 0, k = 0; k = 0; i++, k++)
{
k++;
}
return 0;
}
答案是0次,代碼中存在一個錯誤的循環(huán)條件,導(dǎo)致循環(huán)無法正常終止。在循環(huán)條件?
k = 0
?中,應(yīng)該使用相等運算符?==
?而不是賦值運算符?=。
do...while()循環(huán)
- 語法如下:
do { 循環(huán)語句; }while(表達式);
do...while()循環(huán)流程圖
do...while對比while,for有什么特殊?
循環(huán)至少執(zhí)行一次,使用的場景有限,所以不是經(jīng)常使用。以下是代碼案例。
#include <stdio.h>
int main()
{
int i = 10;
do
{
printf("%d\n", i);
}while(i<10);
return 0;
}
do while循環(huán)中的break和continue
break?
#include <stdio.h>
int main()
{
int i = 10;
do
{
if (5 == i)
break;
printf("%d\n", i);
} while (i < 10);
return 0;
}
以上代碼,單看i=10肯定是不滿足i<10這個循環(huán)條件的,但由于do...while循環(huán)的特性,它不論循環(huán)條件是否成立,都會先執(zhí)行一次循環(huán)體再進行判斷。所以上面代碼結(jié)果是只輸出了10。
continue?
那這段代碼的結(jié)果呢?
#include <stdio.h>
int main()
{
int i = 10;
do
{
if (5 == i)
continue;
printf("%d\n", i);
} while (i < 10);
return 0;
}
答案也是只輸出一個10,原因同上。
練習(xí)
練習(xí)1
計算 n的階乘。
#include <stdio.h>
int main() {
int n;
unsigned long long factorial = 1;
printf("請輸入一個非負整數(shù):");
scanf("%d", &n);
if (n < 0)
{
printf("輸入的數(shù)必須是非負整數(shù)。\n");
}
else
{
for (int i = 1; i <= n; i++) {
factorial *= i;
}
printf("%d 的階乘是 %llu\n", n, factorial);
}
return 0;
}
練習(xí)2
計算n的階乘和。
#include <stdio.h> int main() { int n; unsigned long long factorialSum = 0; printf("請輸入一個非負整數(shù):"); scanf("%d", &n); if (n < 0) { printf("輸入的數(shù)必須是非負整數(shù)。\n"); } else { for (int i = 1; i <= n; ++i) { unsigned long long factorial = 1; for (int j = 1; j <= i; ++j) { factorial *= j; } factorialSum += factorial; } printf("從1到%d的階乘和是 %llu\n", n, factorialSum); } return 0; }
這段代碼首先要求用戶輸入一個非負整數(shù),并將其存儲在變量?
n
?中。然后,使用兩個嵌套的?for
?循環(huán)來計算從 1 到?n
?的所有整數(shù)的階乘,并將每個階乘的結(jié)果累加到?factorialSum
?變量中。最后,使用?printf
?函數(shù)將結(jié)果輸出到屏幕上。
?練習(xí)3
用二分查找在一個有序數(shù)組中查找具體的某個數(shù)字n
int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int sz = sizeof(arr) / sizeof(arr[0]); int left = 0;//左下標(biāo) int right = sz - 1;//右下標(biāo) int num = 0; int flag = 0; scanf("%d", &num); while (left <= right) { int mid = (left + right) / 2;//(左下標(biāo)+右下標(biāo))/2 if (arr[mid] < num) { left = mid + 1; } else if (arr[mid] > num) { right = mid - 1; } else { printf("找到了,數(shù)字%d的下標(biāo)是:%d\n", num, mid); flag = 1; break; } } if (flag == 0) { printf("沒找到!"); } return 0; }
這段代碼使用二分查找算法在給定的有序數(shù)組中查找一個特定的數(shù)字。
首先,定義一個整型數(shù)組?
arr
,并初始化為?{1,2,3,4,5,6,7,8,9,10}
。然后,計算數(shù)組的大小?sz
,即數(shù)組中元素的個數(shù)。接下來,定義兩個變量?
left
?和?right
?分別表示數(shù)組的左下標(biāo)和右下標(biāo)。初始時,left
?設(shè)為 0,right
?設(shè)為?sz - 1
。然后,通過用戶輸入獲取一個數(shù)字?
num
。接下來,使用一個循環(huán)來執(zhí)行二分查找。循環(huán)條件是?
left <= right
,即左下標(biāo)小于等于右下標(biāo)。在每次循環(huán)中,計算中間下標(biāo)?mid
,即?(left + right) / 2
。然后,根據(jù)中間元素的值與目標(biāo)數(shù)字?
num
?的大小關(guān)系,更新左下標(biāo)和右下標(biāo)。如果中間元素小于?num
,則將左下標(biāo)?left
?更新為?mid + 1
;如果中間元素大于?num
,則將右下標(biāo)?right
?更新為?mid - 1
。如果中間元素等于?
num
,則找到了目標(biāo)數(shù)字,輸出找到的消息,并將標(biāo)志變量?flag
?設(shè)為 1,然后使用?break
?語句跳出循環(huán)。如果循環(huán)結(jié)束后?
flag
?仍為 0,表示未找到目標(biāo)數(shù)字,輸出未找到的消息。最后,返回 0 表示程序執(zhí)行完畢。
這段代碼適用于在有序數(shù)組中查找特定數(shù)字的場景。如果數(shù)組是無序的,二分查找算法將不適用,需要使用其他查找算法。
練習(xí)4
?編寫代碼,演示多個字符從兩端移動,向中間匯聚
#include <string.h> #include <windows.h> int main() { char arr1[] = "Hello World!!!"; char arr2[] = "**************"; int left = 0;//左下標(biāo) int right = strlen(arr2) - 1;//右下標(biāo)//-1是因為數(shù)組下標(biāo)從0開始 while (left <= right) { arr2[left] = arr1[left]; arr2[right] = arr1[right]; printf("%s\n", arr2); Sleep(1000);//等待一秒 system("cls");//清空屏幕 left++; right--; } printf("%s\n", arr2); printf("%d\n", strlen(arr2)); return 0; }
這段代碼使用兩個字符數(shù)組?
arr1
?和?arr2
?來模擬一個動態(tài)變化的字符串效果。首先,定義一個字符數(shù)組?
arr1
?并初始化為 "Hello World!!!",定義另一個字符數(shù)組?arr2
?并初始化為 "**************",長度與?arr1
?相同。接下來,定義兩個變量?
left
?和?right
?分別表示?arr2
?的左下標(biāo)和右下標(biāo)。初始時,left
?設(shè)為 0,right
?設(shè)為?strlen(arr2) - 1
,其中?strlen(arr2)
?函數(shù)用于獲取?arr2
?的長度。然后,使用一個循環(huán)來依次將?
arr1
?中的字符賦值給?arr2
?對應(yīng)位置的字符,并在每次循環(huán)中輸出?arr2
?的內(nèi)容。為了實現(xiàn)動態(tài)效果,使用?Sleep
?函數(shù)暫停一秒鐘,然后使用?system("cls")
?函數(shù)清空屏幕。循環(huán)結(jié)束后,輸出最終的?
arr2
?的內(nèi)容和長度。最后,返回 0 表示程序執(zhí)行完畢。
這段代碼的目的是實現(xiàn)一個字符動畫效果,將?
arr1
?中的字符逐漸替換?arr2
?中的字符,并在每次替換后輸出?arr2
?的內(nèi)容。通過循環(huán)中的延時和清空屏幕操作,實現(xiàn)了字符動態(tài)變化的效果。
練習(xí)5
編寫代碼實現(xiàn),模擬用戶登錄情景,并且只能登錄三次。(只允許輸入三次密碼,如果密碼正確則提示登錄成功,如果三次均輸入錯誤,則退出程序。
#include <string.h> #include <windows.h> int main() { int i; char password[20] = { 0 }; for (i = 0; i < 3; i++) { printf("請輸入密碼:>"); scanf("%s", password); if (strcmp(password, "123456") == 0) { printf("密碼正確!\n"); break; } else { printf("密碼錯誤!\n"); Sleep(1000); system("cls"); } } if (i == 3) { printf("三次輸入錯誤,登錄失?。?); } return 0; }
這段代碼實現(xiàn)了一個簡單的密碼驗證功能。
首先,定義一個整型變量?
i
,用于記錄密碼輸入的次數(shù)。然后,定義一個字符數(shù)組?
password
,長度為 20,并初始化為全零。接下來,使用一個?
for
?循環(huán),循環(huán)次數(shù)為 3,表示最多允許輸入密碼三次。在每次循環(huán)中,使用?
printf
?函數(shù)提示用戶輸入密碼,并使用?scanf
?函數(shù)獲取用戶輸入的密碼,并將其存儲在?password
?數(shù)組中然后,使用?
strcmp
?函數(shù)將用戶輸入的密碼與預(yù)設(shè)的密碼 "123456" 進行比較。如果兩個密碼相等,即返回值為 0,表示密碼正確,輸出密碼正確的消息,并使用?break
?語句跳出循環(huán)。如果密碼不正確,則輸出密碼錯誤的消息,使用?
Sleep
?函數(shù)暫停一秒鐘,然后使用?system("cls")
?函數(shù)清空屏幕,以便下一次輸入密碼。循環(huán)結(jié)束后,判斷變量?
i
?的值是否等于 3。如果等于 3,表示密碼輸入錯誤的次數(shù)已達到上限,輸出登錄失敗的消息。最后,返回 0 表示程序執(zhí)行完畢。
這段代碼的目的是實現(xiàn)一個簡單的密碼驗證功能。用戶可以最多輸入三次密碼,如果密碼輸入正確,則輸出密碼正確的消息并登錄成功;如果密碼輸入錯誤,則輸出密碼錯誤的消息,并在每次錯誤后暫停一秒鐘并清空屏幕,以便重新輸入密碼。如果連續(xù)三次輸入都錯誤,則輸出登錄失敗的消息。
練習(xí)6
猜數(shù)字游戲?qū)崿F(xiàn)
#include <stdlib.h>//rand 和 srand需要
#include <time.h> //time需要
void menu()
{
printf("********************\n");
printf("**** 1. play ****\n");
printf("**** 0. exit ****\n");
printf("********************\n");
}
void game()
{
//1. 生成1-100隨機數(shù)
//rand函數(shù),生成的是偽隨機數(shù),范圍是0-RAND_MAX(32767);
//rand函數(shù)需要用srand函數(shù)來設(shè)置隨機數(shù)生成器
int ret = rand() % 100 + 1;//%100-->(0~99) +1 -->(1~100)
//2. 猜數(shù)字
int guess = 0;
while (1)
{
printf("請猜數(shù)字:>");
scanf("%d", &guess);
if (guess < ret)
{
printf("猜小了!\n");
}
else if(guess > ret)
{
printf("猜大了!\n");
}
else
{
printf("猜對了!\n");
break;
}
}
}
int main()
{
srand((unsigned int)time(NULL));//unsigned int 是因為srand函數(shù)的參數(shù)需要,所以要強制類型轉(zhuǎn)化
//NULL是因為time函數(shù)參數(shù)需要一個指針變量,所以我們可以用空指針代替。
int input = 0;
do
{
menu();
printf("請輸入:>");
scanf("%d", &input);
switch (input)
{
case 1:game();
break;
case 0:printf("退出游戲\n");
break;
default:printf("輸入錯誤,請重新輸入!\n");
break;
}
} while (input);
return 0;
}
這段代碼實現(xiàn)了一個猜數(shù)字游戲。游戲開始時,會顯示一個菜單,讓玩家選擇是否開始游戲或退出游戲。
在?
game()
?函數(shù)中,首先使用?rand()
?函數(shù)生成一個 1 到 100 之間的隨機數(shù),并將其賦值給變量?ret
。然后,使用一個?
while
?循環(huán),讓玩家不斷輸入猜測的數(shù)字,直到猜對為止。在每次循環(huán)中,玩家輸入猜測的數(shù)字,并與隨機數(shù)?
ret
?進行比較。如果猜測的數(shù)字小于?
ret
,則輸出 "猜小了"。如果猜測的數(shù)字大于?
ret
,則輸出 "猜大了"。如果猜測的數(shù)字等于?
ret
,則輸出 "猜對了",并使用?break
?語句跳出循環(huán)。在?
main()
?函數(shù)中,使用?srand()
?函數(shù)設(shè)置隨機數(shù)生成器的種子,以確保每次運行程序時生成的隨機數(shù)不同。然后,使用一個?
do-while
?循環(huán),顯示菜單并根據(jù)玩家的選擇執(zhí)行相應(yīng)的操作。如果玩家輸入的是 1,則調(diào)用?game()
?函數(shù)開始游戲;如果玩家輸入的是 0,則輸出 "退出游戲" 并結(jié)束循環(huán);如果玩家輸入的是其他數(shù)字,則輸出 "輸入錯誤,請重新輸入"。循環(huán)條件是?
input
,當(dāng)玩家輸入 0 時,循環(huán)結(jié)束。最后,返回 0 表示程序執(zhí)行完畢。
這段代碼的目的是實現(xiàn)一個簡單的猜數(shù)字游戲。玩家根據(jù)提示輸入猜測的數(shù)字,通過與隨機生成的數(shù)字進行比較,判斷猜測的數(shù)字是大了、小了還是猜對了,并給出相應(yīng)的提示。玩家可以選擇繼續(xù)游戲或退出游戲。文章來源:http://www.zghlxwxcb.cn/news/detail-686628.html
后言
本篇較為詳細的將了循環(huán)語句中的重點,以及6道測試題檢測學(xué)習(xí)情況,對后面學(xué)習(xí)可以起到一定的理解幫助。希望可以得到支持,后面會持續(xù)輸出各項詳解。文章來源地址http://www.zghlxwxcb.cn/news/detail-686628.html
到了這里,關(guān)于【C語言】循環(huán)語句詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!