C語言程序設計
chapter 3 循環結構
1. for
for( 預定義條件; 判斷條件; 條件增量 ){
循環體
}
程序執行的時候會先執行初始化條件,再判斷條件是否成立;
如果條件成立就執行 {}中的循環體,如果條件不成立就退出循環;
{}執行完后再執行條件增量;
條件增量執行完后,再判斷條件是否成立,如果成立繼續循環執行{}中的語句,直到條件不成立退出。
總結就是其執行順序為:
for( 1; 2; 4){
3
}
這里其實我們已經發現:初始條件(1)僅執行了一次,之后都是在 (2,3,4)中循環執行。
其實對於 for(1;2;4)中的 (1,2,4)三部分可以部分或者全部省略,
這樣也不會有語法上面的問題,但是 ';' 不可省略。
//預定義條件, 判斷條件,條件增量都可以不寫,如下
for( ; ; ){
// 循環體
}
但是這樣就是一個死循環(一直循環,沒有結束)
所以我們需要另外使用一個退出:break
break 是指退出當前一層循環,比如
for(int i=1; i<=10; i++){
if(i==5) break;
printf("%d ", i);
}
當 i==5 的時候,就break(退出),這樣輸出的結果就是:1 2 3 4
后面的就不會輸出了。
continue 退出本次循環,繼續下次循環
for(int i=1; i<=10; i++){
if(i==5) continue;
printf("%d ", i);
}
當 i==5 的時候,就 continue(退出本次循環,繼續下次循環),
這樣輸出的結果就是:1 2 3 4 6 7 8 9 10
會發現只有 5 沒有輸出,其余元素都輸出了。
這就是 break 和 continue 的作用和不同。
注明:細心的讀者已經發現問題了,沒錯,對於程序的寫法我並未完全按照 C 標准的格式
比如:在 C 語言中使用 for 循環的寫法應當是:
int i;
for(i=1; i<=10; i++){
//...
}
當然,如果我們使用 Dev-C++ 編譯運行程序時會默認保存為 .cpp 格式,也就是 C++ 格式,那么這時候時不會報錯的,但是一旦使用 .c 就會出現問題了,在后文中,為了節省這一點點篇幅,我還是會使用C++的寫法 for(int i=1; i<=10; i++){...}
,但是讀者應當明白這樣會導致的問題,以及如何解決。
2. for循環案例練習
【題目描述】輸入n,輸出1~n。
輸入樣例:10
輸出樣例:1 2 3 4 5 6 7 8 9 10
#include<stdio.h>
int main(){
int n; scanf("%d", &n);
for(int i=1; i<=n; i++){//循環 1-n,次數:n
printf("%d ", i);
}
return 0;
}
【題目描述】輸入n,輸出1~n的所有偶數。
#include<stdio.h>
int main(){
int n; scanf("%d", &n);
for(int i=1; i<=n; i++){
if(i%2==0) printf("%d ", i);
}
return 0;
}
#include<stdio.h>
int main(){
int n; scanf("%d", &n);
for(int i=2; i<=n; i+=2){
printf("%d ", i);
}
return 0;
}
【題目描述】輸入n,輸出1~n的所有奇數之和與偶數之和。
#include<stdio.h>
int main(){
int sum1=0, sum2=0; //初始化為0,否則會隨機化一個值
int n; scanf("%d", &n);
for(int i=1; i<=n; i++){ //1 2 3 ...
if(i%2==0) sum2=sum2+i;
else sum1=sum1+i;
}
printf("奇數和:%d 偶數和:%d", sum1, sum2);
return 0;
}
【題目描述】輸入n,以及n個人的身高值,求出其中的最大值。
#include<stdio.h>
int main() {
int n, max = -1; scanf("%d", &n);
for(int i=1; i<=n; i++) {
int a; scanf("%d", &a);
if(max<a) max=a;
}
printf("%d", max);
return 0;
}
【題目描述】斐波那契數列 Fibonacci(又稱為黃金數列)指的是這樣一個數列:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,……
請你輸出斐波那契數列的前 40 項。
#include<stdio.h>
int main(){
int i,a=1,b=1,c;
printf("第1項:%d",a);
printf("第2項:%d",b);
for(i=3; i<=40;i++){
c=a+b;
printf("第%d項:%d",i,c);
a=b;
b=c;
}
return 0;
}
3. while
while 循環分為兩種直到型循環 和 當型循環
//當型循環:先判斷滿足條件,再執行循環體
while( 循環條件 ){
循環體
}
舉例:輸出 1~n
int i=1;
while( i<=n ){
printf("%d ", i);
i++;
}
當然它的寫法有很多種,比如下面這樣的:
int i=1;
while( 1 ){ //這樣貌似好像是死循環了呢!那么怎么退出呢?
if(i>n) break;//退出當前一層循環
printf("%d ", i);
i++;
}
//直到型循環:先執行一次循環體,再判斷是否滿足條件,滿足就繼續執行,否則退出。
do{
循環體
}while(flag);
4. while循環案例練習
【題目描述】輸入n,輸出1~n。
【題目描述】輸入n,輸出1~n的所有偶數。
【題目描述】輸入n,輸出1~n的所有奇數之和與偶數之和。
【題目描述】輸入n,以及n個人的身高值,求出其中的最大值。
【題目描述】斐波那契數列 Fibonacci(又稱為黃金數列)指的是這樣一個數列:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,……
請你輸出斐波那契數列的前 40 項。
哈哈,你沒看錯,這就是上面for循環的那幾個題,只是讓你用 while 循環來實現一下。
但是我們又要思考,為什么有了 for循環,還有 while 循環呢?
其實你會發現,對於已經知道循環次數的題目,用 for 更方便一點;
但是如果不知道循環次數,但是知道結束條件,那么用 while 會更好一點。
5. 單層循環實例練習
需要給解析嗎?貌似不需要......,思考了一下,還是給一點吧!
B2057 最高的分數
解析:數據抽象為在多個數據中尋找最大值,沒說的。
#include<stdio.h>
int main(){
int n,maxn=0; scanf("%d", &n);
for(int i=1; i<=n; i++){//循環次數 n
int x; scanf("%d", &x);
if(maxn<x) maxn=x;
}
printf("%d", maxn);
return 0;
}
B2072 分蘋果
解析:主要想到如何才能最少,那不就是從小到大遞增嘛,所以對 1~n 累加即可。
#include<stdio.h>
int main(){
int n; scanf("%d", &n);
int sum=0;
for(int i=1; i<=n; i++){
sum += i;// sum = sum+i;
}
printf("%d", sum);
return 0;
}
B2060 滿足條件的數累加
解析:給了左右邊界,枚舉一下,再判斷所枚舉的數據是否滿足累加條件即可。
#include<stdio.h>
int main(){
int m,n; scanf("%d%d", &m, &n);
int sum=0;
for(int i=m; i<=n; i++){
if(i%17==0){
sum += i;
}
}
printf("%d", sum);
return 0;
}
B2055 均值
解析:就是求平均數,那么將數據累加后, ans=sum/n;
#include<stdio.h>
int main(){
int n; scanf("%d", &n);
double sum=0;
for(int i=0; i<n; i++){
double x; scanf("%lf", &x);
sum += x;
}
printf("%.4lf", sum/n);
return 0;
}
U169811 水仙花數
解析:水仙花數是一個三位數,那么枚舉 [100, 999],再按照 水仙花數的特點進行判斷是不是滿足條件即可。
#include<stdio.h>
int main(){
for(int i=100; i<1000; i++){
int a = i/100;
int b = i/10%10;
int c = i%10;
if(i==a*a*a+b*b*b+c*c*c){
printf("%d\n", i);
}
}
return 0;
}
P1151 子數整數
解析:說了是一個五位數,那么枚舉 [10000, 99999] ,並按照題目分割得到子數,最后判斷子數是不是滿足條件即可。
#include<stdio.h>
int main(){
int k,cnt=0; scanf("%d", &k);
for(int i=10000; i<=30000; i++){
int a = i/100;
int b = i/10%1000;
int c = i%1000;
if(a%k==0 && b%k==0 && c%k==0){
printf("%d\n", i); cnt=1;
}
}
if(cnt==0) printf("No\n");
return 0;
}
P1424 小魚的航程(改進版)
解析:就是將整個過程模擬一遍就行,要注意就是:周天之后是周一。
模擬過程:天數 <=n, 就一直執行:周 x 遞增,天數遞增;
如果 周 x>7,則 x=1;
如果 周 x 屬於 1~5,則小魚泳一次 ans += 250;
最后輸出結果 ans 即可。
#include<stdio.h>
int main(){
int x, n; scanf("%d%d", &x, &n);
int i=1, ans=0;
while(i<=n){
if(x>7) x=1;
if(x>=1 && x<=5) ans+=250;
i++; x++;
}
printf("%d", ans);
return 0;
}
6. 嵌套循環
所謂嵌套,就是一層套一層,類似套娃游戲;
#include<stdio.h>
int main(){
int n=5;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
printf("%d:%d \t",i,j);
}
printf("\n");
}
return 0;;
}
輸出結果:
1:1 1:2 1:3 1:4 1:5
2:1 2:2 2:3 2:4 2:5
3:1 3:2 3:3 3:4 3:5
4:1 4:2 4:3 4:4 4:5
5:1 5:2 5:3 5:4 5:5
對於雙重循環,我們一般使用外層循環 i 來控制行數,內層循環 j 來控制列數。
除了上述 for-for的嵌套,還有 for-while, while-for, ..., for-for-for, ..., 很多格式都是可以的。
本質上循環的主要目的是控制執行次數,所以我們也可以將循環次數 與 問題本身相分割,但是習慣上,還是會將循環條件作為問題中的某些因素來使用, 如 for循環時的 i ,可以用來作為數組下標,奇偶次數判斷等。
【題目描述】輸出九九乘法表,樣例如下:
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
解析:開始直接輸出矩陣形態的樣例,最后對樣例尋找行列特性,發現 i>=j 才輸出,否則不輸出。
#include<stdio.h>
int main(){
int n=9;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(i>=j) printf("%d*%d=%d\t", i,j,i*j);
}
printf("\n");
}
return 0;
}
7. 嵌套循環案例鞏固
- B2083 畫矩形
- B2101 計算矩陣邊緣元素之和
- B2100 同行列對角線的格
- P5721 【深基4.例6】數字直角三角形
- P1980 [NOIP2013 普及組] 計數問題
- P2669 [NOIP2015 普及組] 金幣
- P5725 【深基4.習8】求三角形
- P1035 [NOIP2002 普及組] 級數求和
- P5723 【深基4.例13】質數口袋
- P1307 [NOIP2011 普及組] 數字反轉
- P1423 小玉在游泳
提升鞏固解析
#include<stdio.h>
/*B2083 畫矩形
1. 題目數據有問題,要求能過樣例即可
2. 直接輸出實心80score
3. 測試發現f需要初始為0,方可ac,懷疑數據最后的f=0賦值失敗 */
int main(){
int a,b,f=0; char c;
scanf("%d%d %c%d", &a, &b, &c, &f);
for(int i=1; i<=a; i++){
for(int j=1; j<=b; j++){
if(i==1 || i==a) printf("%c", c);
else if(j==1||j==b) printf("%c", c);
else if(f==0) printf(" ");
else printf("%c",c);
}
printf("\n");
}
return 0;
}
- B2101 計算矩陣邊緣元素之和
和上一個題目一樣,設定行列的表示變量,如果是首尾行首尾列那么累加即可。
注意:這里很多同學在思考會不會重復累加的情況,其實不會的!因為我們只對每個數遍歷一次,那么要么加,要么不加,不會出現第二次選擇的機會。
#include<stdio.h>
int main(){
int m, n, sum=0; scanf("%d%d", &m, &n);
for(int i=1; i<=m; i++){
for(int j=1; j<=n; j++){
int x; scanf("%d", &x);
if(i==1||i==m || j==1 || j==n) sum+=x;
}
}
printf("%d", sum);
return 0;
}
- B2100 同行列對角線的格
讀懂題目是關鍵,實現還需要找到一些規律,這里具體規律在程序中已經體現了。
另外本題較為隱秘的一個點:空格,需要多看樣例,雖然題目也有說明,但是還是很容易犯錯。
#include<stdio.h>
int main() {
int n,x,y; scanf("%d%d%d", &n, &x, &y);
for(int j=1; j<=n; j++){
printf("(%d,%d) ", x,j);//同行
}printf("\n");
for(int i=1; i<=n; i++){
printf("(%d,%d) ", i,y);//同列
}printf("\n");
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(j-i==y-x){
printf("(%d,%d) ", i,j);//左上到右下
}
}
}printf("\n");
for(int i=n; i>=1; i--){
for(int j=1; j<=n; j++){
if(i+j==x+y){
printf("(%d,%d) ", i,j);//左下到右上
}
}
}printf("\n");
return 0;
}
- P5721 【深基4.例6】數字直角三角形
題目很簡單,主要是自己的思維邏輯,對於%02格式如果不清楚也可以通過 if(cnt<10)完成。
#include<stdio.h>
int main(){
int n,cnt=0; scanf("%d",&n);
for(int i=1; i<=n; i++){
for(int j=1; j<=n-i+1; j++){
printf("%02d", ++cnt);
}printf("\n");
}
return 0;
}
- P1980 [NOIP2013 普及組] 計數問題
如何循環提取一個數據中的某些數,但是對於原數不能改變,故而我們定義了一個臨時變量temp, 檢查一位刪除一位,排好隊一個一個來。
#include<stdio.h>
int main() {
int n,x; scanf("%d%d",&n,&x);
int cnt=0;
for(int i=1; i<=n; i++) {
int temp=i;
while(temp!=0) {
if(temp%10==x) cnt++;
temp=temp/10;
}
}
printf("%d",cnt);
return 0;
}
#include<stdio.h>
int main(){
int k; scanf("%d", &k);
int day=1,cnt=1, sum=0;//day表示天數,cnt表示每天發放金幣數量
while(day<=k){
for(int i=1; i<=cnt && day<=k; i++){
sum += cnt; day++;
}
cnt++;
}
printf("%d", sum);
return 0;
}
- P5725 【深基4.習8】求三角形
有趣的題目,充滿了暴力美學
#include<stdio.h>
int main(){
int n, cnt=0; scanf("%d", &n);
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
printf("%02d", ++cnt);
}printf("\n");
}printf("\n");
cnt=0;
for(int i=1; i<=n; i++){
for(int j=1; j<=n-i; j++) printf(" ");
for(int j=1; j<=i; j++) printf("%02d",++cnt);
printf("\n");
}
return 0;
}
- P1035 [NOIP2002 普及組] 級數求和
突然來這么簡單的題目,這是看不起誰呢?
#include<stdio.h>
int main_1(){
int k, n=0; scanf("%d", &k);
double sum=0;
while(sum<=k){
n++;
sum += 1.0/n;
}
printf("%d", n);
return 0;
}
int main(){
int k, n=0; scanf("%d", &k);
double sum=0;
while(1){
n++;
sum += 1.0/n;
if(sum>k) break;
}
printf("%d", n);
return 0;
}
#include<stdio.h>
int main(){
int l, cnt=0; scanf("%d", &l);
for(int i=2; l>i; i++){
int flag=1;//1表示 i是質數,0表示不是質數
for(int j=2; j*j<=i; j++){
if(i%j==0) {
flag=0; break;
}
}
if(flag && l>=i){
l -= i; cnt++;
printf("%d\n", i);
}
}
printf("%d\n", cnt);
return 0;
}
#include<stdio.h>
int main(){
int n; scanf("%d", &n);
if(n<0) {
printf("-");
n = -n;
}
int ans=0;
while(n){
ans = ans*10+n%10;
n /= 10;
}
printf("%d", ans);
return 0;
}
- P1423 小玉在游泳
也就是一個模擬題目,理清游戲規則,梳理流程,一步一步實現即可。
注意輸出結果為整數,如果定義為浮點數,記得強制轉換
#include<stdio.h>
int main(){
double x, cnt=0, step=2, sum=0;
scanf("%lf", &x);
while(sum<x){
sum += step;
cnt++;
step = step*0.98;
}
printf("%d", (int)cnt);
return 0;
}