鍍金池/ 教程/ C/ 練習(xí)11:While循環(huán)和布爾表達(dá)式
練習(xí)9:數(shù)組和字符串
練習(xí)6:變量類型
練習(xí)3:格式化輸出
練習(xí)4:Valgrind 介紹
練習(xí)28:Makefile 進(jìn)階
練習(xí)14:編寫(xiě)并使用函數(shù)
練習(xí)21:高級(jí)數(shù)據(jù)類型和控制結(jié)構(gòu)
練習(xí)20:Zed的強(qiáng)大的調(diào)試宏
練習(xí)18:函數(shù)指針
練習(xí)0:準(zhǔn)備
練習(xí)15:指針,可怕的指針
練習(xí)27:創(chuàng)造性和防御性編程
練習(xí)22:棧、作用域和全局
練習(xí)10:字符串?dāng)?shù)組和循環(huán)
練習(xí)8:大小和數(shù)組
練習(xí)16:結(jié)構(gòu)體和指向它們的指針
練習(xí)7:更多變量和一些算術(shù)
練習(xí)23:認(rèn)識(shí)達(dá)夫設(shè)備
練習(xí)12:If,Else If,Else
練習(xí)2:用Make來(lái)代替Python
練習(xí)1:?jiǎn)⒂镁幾g器
練習(xí)11:While循環(huán)和布爾表達(dá)式
練習(xí)5:一個(gè)C程序的結(jié)構(gòu)
練習(xí)24:輸入輸出和文件
練習(xí)25:變參函數(shù)
練習(xí)13:Switch語(yǔ)句
練習(xí)19:一個(gè)簡(jiǎn)單的對(duì)象系統(tǒng)
練習(xí)26:編寫(xiě)第一個(gè)真正的程序
導(dǎo)言:C的笛卡爾之夢(mèng)
練習(xí)17:堆和棧的內(nèi)存分配

練習(xí)11:While循環(huán)和布爾表達(dá)式

你已經(jīng)初步了解C是如何處理循環(huán)的,但是你可能不是很清楚布爾表達(dá)式i < argc是什么。在學(xué)習(xí)while循環(huán)之前,讓我先來(lái)對(duì)布爾表達(dá)式做一些解釋。

在C語(yǔ)言中,實(shí)際上沒(méi)有真正的“布爾”類型,而是用一個(gè)整數(shù)來(lái)代替,0代表false,其它值代表true。上一個(gè)練習(xí)中表達(dá)式i < argc實(shí)際上值為1或者0,并不像Python是顯式的Ture或者False。這是C語(yǔ)言更接近計(jì)算機(jī)工作方式的另一個(gè)例子,因?yàn)橛?jì)算機(jī)只把值當(dāng)成數(shù)字。

現(xiàn)在用while循環(huán)來(lái)實(shí)現(xiàn)和上一個(gè)練習(xí)相同的函數(shù)。這會(huì)讓你兩種循環(huán),看看兩種循環(huán)是什么關(guān)系。

#include <stdio.h>

int main(int argc, char *argv[])
{
    // go through each string in argv

    int i = 0;
    while(i < argc) {
        printf("arg %d: %s\n", i, argv[i]);
        i++;
    }

    // let's make our own array of strings
    char *states[] = {
        "California", "Oregon",
        "Washington", "Texas"
    };

    int num_states = 4;
    i = 0;  // watch for this
    while(i < num_states) {
        printf("state %d: %s\n", i, states[i]);
        i++;
    }

    return 0;
}

你可以看到while循環(huán)的語(yǔ)法更加簡(jiǎn)單:

while(TEST) {
    CODE;
}

只要TESTtrue(非0),就會(huì)一直運(yùn)行CODE中的代碼。這意味著如果要達(dá)到和for循環(huán)同樣的效果,我們需要自己寫(xiě)初始化語(yǔ)句,以及自己來(lái)增加i。

你會(huì)看到什么

輸出基本相同,所以我做了一點(diǎn)修改,你可以看到它運(yùn)行的另一種方式。

$ make ex11
cc -Wall -g    ex11.c   -o ex11
$ ./ex11
arg 0: ./ex11
state 0: California
state 1: Oregon
state 2: Washington
state 3: Texas
$
$ ./ex11 test it
arg 0: ./ex11
arg 1: test
arg 2: it
state 0: California
state 1: Oregon
state 2: Washington
state 3: Texas
$

如何使它崩潰

在你自己的代碼中,應(yīng)有限選擇for循環(huán)而不是while循環(huán),因?yàn)?code>for循環(huán)不容易崩潰。下面是幾點(diǎn)普遍的原因:

  • 忘記初始化int i,使循環(huán)發(fā)生錯(cuò)誤。
  • 忘記初始化第二個(gè)循環(huán)的i,于是i還保留著第一個(gè)循環(huán)結(jié)束時(shí)的值。你的第二個(gè)循環(huán)可能執(zhí)行也可能不會(huì)執(zhí)行。
  • 忘記在最后執(zhí)行i++自增,你會(huì)得到一個(gè)“死循環(huán)”,它是在你開(kāi)始編程的第一個(gè)或前兩個(gè)十年中,最可怕的問(wèn)題之一。

附加題

  • 讓這些循環(huán)倒序執(zhí)行,通過(guò)使用i--argc開(kāi)始遞減直到0。你可能需要做一些算數(shù)操作讓數(shù)組的下標(biāo)正常工作。
  • 使用while循環(huán)將argv中的值復(fù)制到states
  • 讓這個(gè)復(fù)制循環(huán)不會(huì)執(zhí)行失敗,即使argv之中有很多元素也不會(huì)全部放進(jìn)states。
  • 研究你是否真正復(fù)制了這些字符串。答案可能會(huì)讓你感到意外和困惑。