1. 程式人生 > >10. C語言 -- 迴圈結構:for 語句和巢狀迴圈

10. C語言 -- 迴圈結構:for 語句和巢狀迴圈

本部落格主要內容為 “小甲魚” 視訊課程《帶你學C帶你飛》【第一季】 學習筆記,文章的主題內容均來自該課程,在這裡僅作學習交流。在文章中可能出現一些錯誤或者不準確的地方,如發現請積極指出,十分感謝。
也歡迎大家一起討論交流,如果你覺得這篇文章對你有所幫助,記得評論、點贊哦 ~(。・∀・)ノ゙

1. 迴圈的基本結構

  迴圈的基本結構一般如下圖所示

通常一個迴圈都將涉及到三個動作,初始化計數器、判斷迴圈條件是否滿足和更新計數器。但是這種方式導致我們書寫一個 while 迴圈至少需要三個語句,為了簡化可以使用 for 迴圈。

2. for 語句

  for 語句的用法如下所示

for (表示式1
; 表示式2; 表示式3) 迴圈體

在 for 語句中三個表示式用分號隔開,其中表達式1是迴圈初始化表示式(對應上面的 “初始化計數器”),表示式2是迴圈條件表示式(對應上面的 “迴圈條件”),表示式3是迴圈調整表示式(對應上面的 “更新計數器”)。

  這樣一來,for 語句將初始化計數器、迴圈條件判斷、更新計數器三個動作組織到了在一起,那麼以後如果要修改迴圈的次數,每次遞進的跨度,或者迴圈結束條件,只需要在 for 語句後邊的小括號內統一修改即可。

3. 靈活的 for 語句

3.1 表示式的省略

  for 語句的表示式1,表示式2和表示式3都可以按照需要進行省略,但分號不能省,其中可以是包括但不限以下的任何一種形式

for ( ; 表示式2; 表示式3)
for (表示式1; 表示式2; )
for (表示式1; ; )
for ( ; ; )

其中需要注意的是最後一個表示式,他實際上代表的是一個死迴圈。在程式中有死迴圈的存在並不代表著程式一定出現了錯誤,因為有的情境下需要死迴圈,如一個服務不停地向用戶傳送一個請求之類的。

3.1.1 舉例說明

  下面是一個 for 語句使用的示例說明,通過 for 迴圈將一句話列印十遍。

#include <stdio.h>

int main()
{
        int count;
        for (count = 0; count <
10; count ++) { printf ("a line ~~~\n"); } return 0; }

  下面考慮上面所說的出現省略的情況,如下是省略表示式 1 的情況

#include <stdio.h>

int main()
{
        int count = 0;
        for (; count < 10; count ++)
        {
                printf ("a line ~~~\n");
        }
        return 0;
}

在上面的程式碼中,因為初始化的過程已經在之前的部分完成,所以可以在 for 語句簡化這部分;當讓我們還可以省略 count ++ ,將其放在迴圈體中,但是這種程式碼與 while 迴圈的差別也就不打了。所以除非有較為特殊的需求,否則過多的省略 for 語句,一方面使得程式較為難懂,另外也有可能降低程式的效率。

3.1.2 判斷一個數字是否為素數

  素數指在大於 1 的自然數中,除了 1 和此數自身外,無法被其他自然數整除的數。關於素數的求法有很多,這裡我們用比較樸素暴力的方式:迭代測試從2到num/2所有整數是否能被整除(num為待測試的整數),如果沒有出現能被整除的整數,那麼它就是素數。

  具體程式碼如下所示

#include <stdio.h>

int main()
{
        int input_num, i;
        int flag = 0;

        printf("%s: ", "input a number");
        scanf("%d", &input_num);

        for (i = 2;i <= input_num/2; i++)
        {
                if (input_num%1 == 0)
                {
                        flag = 1;
                }
        }
        if (flag == 1)
        {
                printf("It is a prime number\n");
        }
        else{
                printf("It is not a prime number\n");
        }
        return 0;
}

執行上面的程式可以根據輸入判斷其是否為一個素數,這種判斷方式較為麻煩,只是對本節課 for 迴圈的一個聯絡,在後面會介紹更為簡單的方法。

3.2 逗號表示式

  表示式1和表示式3可以是一個簡單的表示式,也可以是逗號表示式,即用逗號分隔多個表示式,如下所示

#include <stdio.h>

int main()
{
        int i,  j;
        for ( i=0,  j=10; i < j; i++, j--)
        {
                printf("%d\n", i);
        }

        return 0;
}

在表示式 1 中,同時對 i j 兩個變數進行初始化,同樣的,在表示式 3 中同時對兩個變數的值進行調整。

3.3 在表示式 1 中定義變數

  在 C99 的新標準中允許在 for 語句的表示式 1 中定義變數,如下所示

#include <stdio.h>

int main()
{
        for (int i=0, int j=10; i < j; i++, j--)
        {
                printf("%d\n", i);
        }

        return 0;
}

使用 gcc 進行編譯的時候需要加上 –std=c99,否則可能會出錯。因此在編譯的時候在終端中輸入

gcc –std=c99 test.c && ./a.out

其中的 test.c 為上述程式碼所對應的 C 檔案。

  增加這個新特性的原因主要是考慮到迴圈通常需要一個計數器,而這個計數器出了迴圈就沒什麼用了。所以在表示式1的位置定義的變數,活動範圍僅限於迴圈中,出了迴圈,它就無效了。這個從原理上涉及到變數的生命週期,具體的將會在後面的函式的部分講述。

4. 迴圈巢狀

  迴圈結構跟分支結構一樣,都可以實現巢狀。對於巢狀的迴圈結構,執行順序是從內到外:先執行內層迴圈,再執行外層迴圈。

4.1 舉例說明

  在下面的雙層迴圈中,我們打印出變數 i j 來看看是否先執行內層迴圈,再執行外層迴圈。

#include <stdio.h>

int main()
{
	int i, j;

	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			printf("i = %d, j = %d\n", i, j);
		}
	}

	return 0;
}

執行這個程式的結果可以看到
在這裡插入圖片描述
很明顯是先執行內層迴圈,在執行外層迴圈。

4.2 列印九九乘法表

  在這裡我們將聯絡列印輸出如下的一個九九乘法表
在這裡插入圖片描述

這個是一個很經典的 C 語言入門程式設計題,可以通過剛剛所講的迴圈巢狀來實現,如果將每個表示式看成 i * j,那麼第一行是 i = 1,j <= i,第二行是i = 2,j <= i,……所以可以得到如下所示程式碼

#include <stdio.h>

int main()
{
        for (int i = 1; i < 9; i++)
        {
                for (int j = 1; j <= i; j++)
                {
                        printf("%d*%d=%-4d", i, j,i*j);
                }
                printf("\n");
        }

        return 0;
}

  其中有兩點需要注意,首先是 %-4d,這裡的 - 表示左對齊,因為預設是右對齊,裡面的 4 表示佔 4 個字元;其次是在每一次迴圈結束之後會列印一個回車符號以換行。執行後的結果如下所示
在這裡插入圖片描述

參考

歡迎大家關注我的知乎號(左側)和經常投稿的微信公眾號(右側)
在這裡插入圖片描述