日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言再学习 -- 循环语句

發布時間:2025/3/15 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言再学习 -- 循环语句 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C語言有三種循環結構:while、for和do while。下面依次講解

一、while循環

1、while介紹

while(邏輯表達式) //布爾值為1 真
{
反復執行的語句
}? ? ? ? ? ? ? ? ? ? ? ? ? ??

只要邏輯表達式結果為真就反復不停執行大括號里的語句,直到邏輯表達式結果為假循環結束
只要把邏輯表達式寫成1則循環成為死循環,while(1)
while循環里可以使用break和continue;

break 關鍵字很重要,表示終止本層循環?,F在這個例子只有一層循環,當代碼執行到break 時,循環便終止。
如果把 break 換成 continue 會是什么樣子呢? continue 表示終止本次(本輪) 循環。當代碼執行到 continue 時,本輪循環終止,進入下一輪循環。while( 1)也有寫成 while(true) 或者 while(1==1) 或者 while((bool) 1)等形式的,效果一樣。


還需注意:任何非零值都是真.比如,while (-1) == while (true)

2、while復合語句

復合語句是使用花括號組織起來的兩個或更過的語句,它也被稱為一個代碼塊。

例如:

/*程序1*/

index = 0; while (index++ < 10)sam = 10 *index +2; printf ("sam = %d\n", sam); /*程序2*/

index = 0; while (index++ < 10) {sam = 10 *index +2;printf ("sam = %d\n", sam); } 說明:在沒有花括號的情況下,while循環語句的范圍是從while到下一個分號。

3、技巧

A、假如你想要跳過輸入直到第一個不為空格或者數字的字符,你可以使用這樣的循環:

while (scanf ("%d", &num) == 1) {....}

只要scanf()輸入一個整數,它就返回1,循環就會繼續。

B、while ((ch = getchar ()) != '\n') {....}

只要輸入不為換行符'\n',它就返回1,循環就會繼續。

C、while循環內只執行一次的語句

int i = 0;

while (1)?

{

if (0 == i)

{只執行一次該語句};

i == 1;

}

4、空語句

while ((ch = getchar ()) != EOF && ch != '\n') ; while語句之后的單獨一個分號稱為空語句,它就是應用于目前這個場合,也就是語法要求這個地方出現一條語句但又無需執行任何任務的時候,這個分號獨占一行,這是為了防止讀者錯誤地以為接下來的語句也是循環的一部分。

二、do while循環

1、do while介紹

do{
} ?while(為真的邏輯);

do while為退出條件循環,判斷條件在執行循環之后進行檢查,這樣就可以保證循環體中的語句至少被執行一次。

2、do while復合語句

例如:

do scanf ("%d", &num); while (num != 20); /*注意while后面有分號 ;*/

3、do while的常規用法

[cpp]?view plaincopy
  • //限制輸入,必須輸入0到10的數,否則重新輸入。??
  • #include"stdio.h"??
  • int?main()??
  • {??
  • ????int?num;??
  • ????do??
  • ????{??
  • ????????printf("請輸入0到10的整數:");?//先進行輸入提示??
  • ????????scanf("%d",&num);?//從鍵盤讀取一個數??
  • ????????getchar();??
  • ????}while?(num?>?10?||?num?<?0);??//如果這個數不再0~10內,也就是小于0或者大于10,重新輸入??
  • ????printf("輸入正確,輸入的數為:%d\n",?num);?//輸入正確則跳出循環并給出提示,\n表示換行??
  • }??
  • 4、do {}while(0)的用法

    參看:do while的使用 linux內核中 do{}while(0)用法分析

    linux內核和其他一些開源的代碼中,經常會遇到這樣的代碼:

    do{... }while(0)

    這樣的代碼一看就不是一個循環,do..while表面上在這里一點意義都沒有,那么為什么要這么用呢?

    實際上,do{...}while(0)的作用遠大于美化你的代碼,while(0)的好處在于在編譯的時候,編譯器基本都會為你做好優化,把這部分內容去掉,最終編譯的結果不會因為這個do while而導致運行效率上的差異。。查了些資料,總結起來這樣寫主要有以下幾點好處:

    1、輔助定義復雜的宏,避免引用的時候出錯:

    舉例來說,假設你需要定義這樣一個宏:

    #define DO_SOMETHING()\foo1();\foo2();

    這個宏的本意是,當調用DO_SOMETHING()時,函數foo1()和foo2()都會被調用。但是如果你在調用的時候這寫:

    if(a>0)DO_SOMETHING();

    因為宏在預處理的時候會直接被展開,你實際上寫的代碼是這個樣子的:

    if(a>0)foo1(); foo2();

    這就出現了問題,因為無論a是否大于0,foo2()都會被執行,導致程序出錯

    那么僅僅使用{}將foo1()和foo2()包起來行么

    我們在寫代碼的時候都習慣在語句右面加上分號,如果在宏中使用{},代碼里就相當于這樣寫了:“{...};”,展開后就是這個樣子:

    if(a>0) {foo1();foo2(); };

    注意if{};后面的";",如果if后面還有else等語句則編譯不會通過。所以,很多人才采用了do{...}while(0);

    #define DO_SOMETHING() \do{ \foo1();\foo2();\}while(0)\ ...if(a>0)DO_SOMETHING();...

    這樣,宏被展開后,才會保留初始的語義。GCC提供了Statement-Expressions用以替代do{...}while(0); 所以你也可以這樣定義宏:

    #define DO_SOMETHING() ({\foo1(); \foo2(); \ })

    http://www.spongeliu.com/?
    2、避免使用goto對程序流進行統一的控制:

    有些函數中,在函數return之前我們經常會進行一些收尾的工作,比如free掉一塊函數開始malloc的內存,goto一直都是一個比較簡便的方法:

    int foo() {somestruct* ptr = malloc(...);dosomething...;if(error){goto END;}dosomething...;if(error){goto END;}dosomething...;END:free(ptr);return 0;}

    由于goto不符合軟件工程的結構化,而且有可能使得代碼難懂,所以很多人都不倡導使用,那這個時候就可以用do{}while(0)來進行統一的管理:

    int foo() {somestruct* ptr = malloc(...);do{dosomething...;if(error){break;}dosomething...;if(error){break;}dosomething...;}while(0);free(ptr);return 0;}

    這里將函數主體使用do()while(0)包含起來,使用break來代替goto,后續的處理工作在while之后,就能夠達到同樣的效果。

    3、避免空宏引起的warning

    內核中由于不同架構的限制,很多時候會用到空宏,在編譯的時候,空宏會給出warning,為了避免這樣的warning,就可以使用do{}while(0)來定義空宏:

    #define EMPTYMICRO do{}while(0)

    4、定義一個單獨的函數塊來實現復雜的操作:

    當你的功能很復雜,變量很多你又不愿意增加一個函數的時候,使用do{}while(0);,將你的代碼寫在里面,里面可以定義變量而不用考慮變量名會同函數之前或者之后的重復。


    5、do {}while(0)的簡化

    #define st(x) do { x } while (__LINE__ == -1)

    1, __LINE__ 是個宏,它代表當前代碼在源文件的行號,它是大于0的,所以__LINE__ == -1 等同于0,化簡為:
    #define st(x) do { x } while (0)
    2,do {} while (0)通常用于宏中, 為的是避免如下情況:
    #define st(x) x
    那么我們在調用 if (0) st(a = b; b = c;) 時會被解釋成
    if(0)
    a = b;
    b = c;
    可見 if 只對a = b;起作用。

    三、for循環 1、for介紹 for(num=1; num <10; num++); 在關鍵字for之后的圓括號中包含了由兩個分號分開的三個表達式。 第一個表達式進行初始化,它在for循環開始的時候執行一次。 第二個表達式是判斷條件,在每次執行循環之前都要對它進行求值。當表達式為假時,循環結束。 第三個表達式進行改變或者稱為更新,它在每次循環結束時進行計算。
    2、for復合語句 例如: for (n = 0; n < 10; n+)printf ("%d %d\n", n, 2 * n + 1);
    3、for循環的靈活性 A、可以讓一個或多個表達式為空(但是不要遺漏分號)。只須確保在循環中包含一些能是循環最終結束的語句。
    B、順便說一句,中間的那個控制表達式為空會被認為是真,所以下面的循環會永遠執行: for (; ;) printf ("hello world\n");
    C、第一個表達式不必初始化一個變量,它也可是某種類型的printf()語句,要記住第一個表達式只在執行循環的其他部分之前被求值或執行一次。
    D、for循環可使用逗號運算符把兩個表達式鏈接為一個表達式,并保證最左邊的表達式最先計算。 例如: for (n = 2, m = 0; m < 1000; n *=2)m +=n;
    E、在for循環中使用數組,使用#define來指定數組大小 例如: #define SIZE 10 for (int n = 0; n < SIZE; n++)printf ("hello world\n");
    4、嵌套循環 A、嵌套循環是指在另一個循環之內的循環。通常使用嵌套循環來按行按列顯示數據。也就是說一個循環處理一行中的所有列,而另一個循環處理所有的行。
    B、外層for循環為外部循環,按行顯示數據;內層for循環為內部循環。按列顯示數據。 在多重循環中,如果有可能,應當將最長的循環放在最內層,最短的循環放在最外層,以減少 CPU 跨切循環層的次數。例如:
    長循環在最內層,效率高 for (col=0; col<5; col++ ) {for (row=0; row<100; row++){sum = sum + a[row][col];} }長循環在最外層,效率低 for (row=0; row<100; row++) {for ( col=0; col<5; col++ ){sum = sum + a[row][col];} }
    C、建議 for 語句的循環控制變量的取值采用“半開半閉區間”寫法。半開半閉區間寫法和閉區間寫法雖然功能是相同,但相比之下,半開半閉區間寫法寫法更加直觀。 半開半閉區間寫法:for (n = 0; n < 10; n++) {....} 閉區間寫法:for (n = 0; n <= 9; n++) {....}

    D、不能在 for 循環體內修改循環變量,防止循環失控。 for (n = 0; n < 10; n++) {…n = 8;//不可,很可能違背了你的原意… }
    E、循環要盡可能的短,要使代碼清晰,一目了然。 如果你寫的一個循環的代碼超過一顯示屏,那會讓讀代碼的人發狂的。解決的辦法由兩個:第一,重新設計這個循環,確認是否這些操作都必須放在這個循環里;第二,將這些代碼改寫成一個子函數, 循環中只調用這個子函數即可。 一般來說循環內的代碼不要超過 20行。
    F、把循環嵌套控制在 3 層以內。 國外有研究數據表明,當循環嵌套超過 3 層,程序員對循環的理解能力會極大的降低。如果你的循環嵌套超過 3 層,建議你重新設計循環或是將循環內的代碼改寫成一個字函數。
    G、擴展 1、編程實現打印一個空心的菱形和實心的菱形:
    ? ? ? ? ?*
    ? ? ? *****
    ? ?*********
    *************
    ? ?*********
    ? ? ? *****
    ? ? ? ? ?*
    #include <stdio.h> int main() {int i=0,j=0,k=0;for(i=0;i<=3;i++){for(j=0;j<=5-2*i;j++){printf(" ");}for(k=0;k<=4*i;k++){printf("*");}printf("\n");}for(i=0;i<=2;i++){for(j=0;j<=2*i+1;j++){printf(" ");}for(k=0;k<=8-4*i;k++){printf("*");}printf("\n");}return 0; }
    2、請簡述以下兩個 for 循環的優缺點
    // 第一個 for (i=0; i<N; i++) { if (condition) DoSomething(); else DoOtherthing(); } 優缺點:效率低但程序簡潔
    // 第二個 if (condition) { for (i=0; i<N; i++) DoSomething(); } else { for (i=0; i<N; i++) DoOtherthing(); }優缺點:效率高但程序不簡潔
    說明:第一個程序比第二個程序多執行了 N-1 次邏輯判斷。并且由于前者老要進行邏輯判斷,打斷了循環“流水線”作業,使得編譯器不能對循環進行優化處理,降低了效率。如果 N 非常大,最好采用第二個程序的寫法,可以提高效率。如果 N 非常小,兩者效率差別并不明顯,采用第一個程序的寫法比較好,因為程序更加簡潔。
    注意: 1、上面有提到,在多重循環中,如果有可能,應當將最長的循環放在最內層,最短的循環放在最外層,以減少 CPU 跨切循環層的次數。 ?
    2、建議 for 語句的循環控制變量的取值采用“半開半閉區間”寫法。
    int a[10];
    半開半閉區間寫法:for (n = 0; n < 10; n++)
    閉區間寫法:for (n = 0; n <= 9; n++)

    半開半閉區間寫法和閉區間寫法雖然功能是相同,但考慮到邊界計算,例如我們要在C語言中定義一個擁有 10 個元素的數組,那么 0 就是數組下標的第一個 “入界點”(指處于數組下標范圍以內的點,包括邊界點),而 10 就是數組下標中的第一個“出界點”(指不在數組下標范圍以內的點,不含邊界點)。因此寫成半開半閉區間的寫法更加直觀。

    3、不能在 for 循環體內修改循環變量,防止循環失控。for (n = 0; n < 10; n++) { … n = 8;//不可,很可能違背了你的原意 … }
    4、循環要盡可能的短,要使代碼清晰,一目了然。
    如果你寫的一個循環的代碼超過一顯示屏,那會讓讀代碼的人發狂的。解決的辦法由兩個:第一,重新設計這個循環,確認是否這些操作都必須放在這個循環里;第二,將這些代碼改寫成一個子函數, 循環中只調用這個子函數即可。 一般來說循環內的代碼不要超過 20行。

    5、把循環嵌套控制在 3 層以內。
    國外有研究數據表明,當循環嵌套超過 3 層,程序員對循環的理解能力會極大的降低。如果你的循環嵌套超過 3 層,建議你重新設計循環或是將循環內的代碼改寫成一個字函數。

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的C语言再学习 -- 循环语句的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。