2022-11-10C控制語句:分支和跳轉(zhuǎn)

C的條件運算符

switch語句

break、 continue和goto語句

使用C的字符I/O函數(shù): getchar()和putchar()

ctype.h頭文件提供的字符分析函數(shù)系列

while循環(huán)的測試條件利用scanf()的返回值來結(jié)束循環(huán)抵栈, 因為scanf()在讀到非數(shù)字字符時會返回0佛玄。 temperature的類型是float而不是int, 這樣程序既可以接受-2.5這樣的值惠赫, 也可以接受8這樣的值目锭。

該程序示例把計算后的百分比強(qiáng)制轉(zhuǎn)換為 float類型和泌。 其實村缸, 也不必使用強(qiáng)制類型轉(zhuǎn)換, 因為在表達(dá)式100.0 * cold_days /all_days中武氓, 將首先對表達(dá)式100.0 * cold_days求值梯皿, 由于C的自動轉(zhuǎn)換類型規(guī)則, 乘積會被強(qiáng)制轉(zhuǎn)換成浮點數(shù)县恕。

使用強(qiáng)制類型轉(zhuǎn)換可以明確表達(dá)轉(zhuǎn)換類型的意圖东羹, 保護(hù)程序免受不同版本編譯器的影響。 if語句被稱為分支語句(branching statement) 或選擇語句(selection statement) 忠烛, 因為它相當(dāng)于一個交叉點属提, 程序要在兩條分支中選擇一條執(zhí)行。

if else語句

簡單形式的if語句可以讓程序選擇執(zhí)行一條語句, 或者跳過這條語句冤议。C還提供了if else形式斟薇, 可以在兩條語句之間作選擇。

if (all_days != 0)

printf("%d days total: %.1f%% were below freezing.\n",

all_days, 100.0 * (float) cold_days / all_days);

if (all_days == 0)

printf("No data entered!\n");

如果程序發(fā)現(xiàn)all_days不等于0恕酸, 那么它應(yīng)該知道另一種情況一定是all_days等于0堪滨。

if (all_days!= 0)

printf("%d days total: %.1f%% were below freezing.\n",

all_days, 100.0 * (float) cold_days / all_days);

else

printf("No data entered!\n");

如果if語句的測試表達(dá)式為真, 就打印溫度數(shù)據(jù)蕊温; 如果為假袱箱, 就打印警告消息。

if else語句的通用形式是:

if ( expression )

statement1

else

statement2

如果expression為真(非0) 义矛, 則執(zhí)行statement1发笔; 如果expression為假或0, 則執(zhí)行else后面的statement2凉翻。 statement1和statement2可以是一條簡單語句或復(fù)合語句了讨。

if語句用于選擇是否執(zhí)行一個行為, 而else if語句用于在兩個行為之間選擇噪矛。

if語句和if else語句

另一個示例: 介紹getchar()和putchar()

getchar()函數(shù)不帶任何參數(shù)量蕊, 它從輸入隊列中返回下一個字符。

ch = getchar();

該語句與下面的語句效果相同:

scanf("%c", &ch);

putchar()函數(shù)打印它的參數(shù)艇挨。

putchar(ch);

該語句與下面的語句效果相同:

printf("%c", ch);

由于這些函數(shù)只處理字符, 所以它們比更通用的scanf()和printf()函數(shù)更快韭赘、 更簡潔缩滨。 而且, 注意 getchar()和 putchar()不需要轉(zhuǎn)換說明泉瞻, 因為它們只處理字符脉漏。 這兩個函數(shù)通常定義在 stdio.h頭文件中

ctype.h系列的字符函數(shù)

C 有一系列專門處理字符的函數(shù), ctype.h頭文件包含了這些函數(shù)的原型袖牙。 這些函數(shù)接受一個字符作為參數(shù)侧巨, 如果該字符屬于某特殊的類別, 就返回一個非零值(真) 鞭达; 否則司忱, 返回0(假) 。如果isalpha()函數(shù)的參數(shù)是一個字母畴蹭, 則返回一個非零值坦仍。

字符映射函數(shù)不會修改原始的參數(shù), 這些函數(shù)只會返回已修改的值叨襟。

多重選著else if

在程序中也可以用else if擴(kuò)展if else結(jié)構(gòu)模擬這種情況繁扎。

用符號常量表示不同的費率和費率分界點, 以便把常量統(tǒng)一放在一處。

該程序由一個ifelse語句組成梳玫, else部分包含另一個if else語句爹梁, 該if else語句的else部分又包含另一個if else語句。 第2個if else語句嵌套在第 1個if else語句中提澎, 第3個if else語句嵌套在第2個if else語句中姚垃。

整個if else語句被視為一條語句, 因此不必把嵌套的if else語句用花括號括起來虱朵。

else與if配對

if (number > 6)

if (number < 12)

printf("You're close!\n");

else

printf("Sorry, you lose a turn!\n");

else與第2個if匹配莉炉。 也就是說, 輸入的數(shù)字和匹配的響應(yīng)如下:

數(shù)字 響應(yīng)

5 None

10 You’re close!

15 Sorry, you lose a turn!

如果沒有花括號碴犬, else與離它最近的if匹配絮宁, 除非最近的if被花括號括起來。

要縮進(jìn)“語句”服协, “語句”可以是一條簡單語句或復(fù)合語句绍昂。

多層嵌套的if語句

從一系列選項中選擇一個執(zhí)行。 有時偿荷, 選擇一個特定選項后又引出其他選擇窘游, 這種情況可以使用另一種嵌套if。

這種形式的嵌套if應(yīng)用在下面的程序中跳纳。 給定一個整數(shù)忍饰, 顯示所有能整除它的約數(shù)。 如果沒有約數(shù)寺庄, 則報告該數(shù)是一個素數(shù)艾蓝。

要總體設(shè)計一下程序。 為方便起見斗塘, 程序應(yīng)該使用一個循環(huán)讓用戶能連續(xù)輸入待測試的數(shù)赢织。 這樣, 測試一個新的數(shù)字時不必每次都要重新運行程序馍盟。

提示用戶輸入數(shù)字

當(dāng)scanf()返回值為1

分析該數(shù)并報告結(jié)果

提示用戶繼續(xù)輸入

回憶一下在測試條件中使用scanf()于置, 把讀取數(shù)字和判斷測試條件確定是否結(jié)束循環(huán)合并在一起。

設(shè)計如何找出約數(shù)贞岭。

for (div = 2; div < num; div++)

if (num % div == 0)

printf("%d is divisible by %d\n", num, div);

該循環(huán)檢查2~num之間的所有數(shù)字八毯, 測試它們是否能被num整除。

必須測試的數(shù)只要到num的平方根就可以了曹步, 不用到num宪彩。

不使用平方根而用這樣的測試條件, 有兩個原因讲婚。 其一尿孔, 整數(shù)乘法比求平方根快。 其二, 我們還沒有正式介紹平方根函數(shù)活合。

for (div = 2; (div * div) <= num; div++)

{?

if(num % div == 0)

{?

if(div * div != num)

printf("%d is divisible by %d and %d.\n",num, div, num / div);

else

printf("%d is divisible by %d.\n", num, div);

}

}

if else語句作為一條單獨的語句雏婶, 不必使用花括號。 外層if也是一條單獨的語句白指, 也不必使用花括號留晚。 但是, 當(dāng)語句太長時告嘲, 使用花括號能提高代碼的可讀性错维, 而且還可防止今后在if循環(huán)中添加其他語句時忘記加花括號。

如何知道一個數(shù)字是素數(shù)橄唬? 如果num是素數(shù)赋焕, 程序流不會進(jìn)入if語句。 要解決這個問題仰楚, 可以在外層循環(huán)把一個變量設(shè)置為某個值(如隆判, 1) , 然后在if語句中把該變量重新設(shè)置為0僧界。 循環(huán)完成后侨嘀, 檢查該變量是否是1, 如果是捂襟, 說明沒有進(jìn)入if語句咬腕, 那么該數(shù)就是素數(shù)。 這樣的變量通常稱為標(biāo)記(flag) 葬荷。

C都習(xí)慣用int作為標(biāo)記的類型郎汪, 其實新增的_Bool類型更合適。 另外闯狱, 如果在程序中包含了stdbool.h頭文件, 便可用bool代替_Bool類型抛计, 用true和false分別代替1和0哄孤。

小結(jié): 用if語句進(jìn)行選擇

關(guān)鍵字: if、 else

一般注解:

下面各形式中吹截, statement可以是一條簡單語句或復(fù)合語句瘦陈。 表達(dá)式為真說明其值是非零值。

形式1:

if (expression)

statement

如果expression為真波俄, 則執(zhí)行statement部分晨逝。

形式2:

if (expression)

statement1

else

statement2

如果expression為真, 執(zhí)行statement1部分懦铺; 否則捉貌, 執(zhí)行statement2部分。

形式3:

if (expression1)

statement1

else if (expression2)

statement2

else

statement3

如果expression1為真, 執(zhí)行statement1部分趁窃; 如果expression2為真牧挣, 執(zhí)行statement2部分; 否則醒陆, 執(zhí)行statement3部分瀑构。

if (legs == 4)

printf("It might be a horse.\n");

else if (legs > 4)

printf("It is not a horse.\n");

else /* 如果legs < 4 */

{?

legs++;

printf("Now it has one more leg.\n");

}

邏輯運算符

要編寫一個程序, 計算輸入的一行句子中除單引號和雙引號以外其他字符的數(shù)量刨摩。 這種情況下可以使用邏輯運算符寺晌, 并使用句點(.) 標(biāo)識句子的末尾。

if語句的測試條件中使用了邏輯與運算符&&澡刹。 該 if語句翻譯成文字是“如果待測試的字符不是雙引號呻征, 并且它也不是單引號,那么charcount遞增1”像屋。

邏輯運算符兩側(cè)的條件必須都為真怕犁, 整個表達(dá)式才為真。 邏輯運算符的優(yōu)先級比關(guān)系運算符低己莺, 所以不必在子表達(dá)式兩側(cè)加圓括號奏甫。

備選拼寫:iso646.h頭文件

C99標(biāo)準(zhǔn)新增了可代替邏輯運算符的拼寫, 它們被定義在ios646.h頭文件中凌受。 如果在程序中包含該頭文件阵子, 便可用and代替&&、 or代替||胜蛉、 not代替!挠进。

if (ch != '"' && ch != '\'')

charcount++;

改寫為:

if (ch != '"' and ch != '\'')

charcount++;

C一直堅持盡量保持較少的關(guān)鍵字。 參考資料V“新增C99和C11的標(biāo)準(zhǔn)ANSI C庫”列出了一些運算符的備選拼寫誊册。

優(yōu)先級

!運算符的優(yōu)先級很高领突, 比乘法運算符還高, 與遞增運算符的優(yōu)先級相同案怯, 只比圓括號的優(yōu)先級低君旦。 &&運算符的優(yōu)先級比||運算符高, 但是兩者的優(yōu)先級都比關(guān)系運算符低嘲碱, 比賦值運算符高金砍。 因此, 表達(dá)式a >b && b > c ||b > d相當(dāng)于((a > b) && (b > c)) || (b > d)麦锯。

也就是說恕稠, b介于a和c之間, 或者b大于d扶欣。

求值順序

除了兩個運算符共享一個運算對象的情況外鹅巍, C 通常不保證先對復(fù)雜表達(dá)式中哪部分求值千扶。

C 把先計算哪部分的決定權(quán)留給編譯器的設(shè)計者, 以便針對特定系統(tǒng)優(yōu)化設(shè)計昆著。 但是县貌, 對于邏輯運算符是個例外, C保證邏輯表達(dá)式的求值順序是從左往右凑懂。 &&和||運算符都是序列點煤痕, 所以程序在從一個運算對象執(zhí)行到下一個運算對象之前, 所有的副作用都會生效接谨。 而且摆碉, C 保證一旦發(fā)現(xiàn)某個元素讓整個表達(dá)式無效, 便立即停止求值脓豪。

while ((c = getchar()) != ' ' && c != '\n')

第1 個子表達(dá)式把讀取的值賦給c巷帝, 后面的子表達(dá)式會用到c的值。 如果沒有求值循序的保證扫夜, 編譯器可能在給c賦值之前先對后面的表達(dá)式求值楞泼。

if (number != 0 && 12/number == 2)

printf("The number is 5 or 6.\n");

如果number的值是0, 那么第1個子表達(dá)式為假笤闯, 且不再對關(guān)系表達(dá)式求值堕阔。 這樣避免了把0作為除數(shù)。 許多語言都沒有這種特性颗味, 知道number為0后超陆, 仍繼續(xù)檢查后面的條件。

小結(jié): 邏輯運算符和表達(dá)式

邏輯運算符:

邏輯運算符的運算對象通常是關(guān)系表達(dá)式浦马。 !運算符只需要一個運算對象时呀, 其他兩個邏輯運算符都需要兩個運算對象, 左側(cè)一個晶默, 右側(cè)一個谨娜。

當(dāng)且僅當(dāng)expression1和expression2都為真, expression1 && expression2才為真磺陡。 如果 expression1 或 expression2 為真瞧预, expression1 || expression2 為真。 如果expression為假仅政, !expression則為真, 反之亦然盆驹。

邏輯表達(dá)式的求值順序是從左往右圆丹。

范圍

&&運算符可用于測試范圍。要測試score是否在90~100的范圍內(nèi)躯喇, 可以這樣寫:

if (range >= 90 && range <= 100)

printf("Good show!\n");

由于<=運算符的求值順序是從左往右辫封, 所以編譯器把測試表達(dá)式解釋為:

(90 <= range) <= 100

子表達(dá)式90 <= range的值要么是1(為真) 硝枉, 要么是0(為假) 。 這兩個值都小于100倦微, 所以不管range的值是多少妻味, 整個表達(dá)式都恒為真。 因此欣福, 在范圍測試中要使用&&责球。

一個統(tǒng)計單詞的程序

編寫一個統(tǒng)計單詞數(shù)量的程序(即, 該程序讀取并報告單詞的數(shù)量) 拓劝。 該程序還可以計算字符數(shù)和行數(shù)雏逾。

首先, 該程序要逐個字符讀取輸入郑临, 知道何時停止讀取栖博。 然后, 該程序能識別并計算這些內(nèi)容: 字符厢洞、 行數(shù)和單詞仇让。

讀取一個字符

當(dāng)有更多輸入時

遞增字符計數(shù)

如果讀完一行, 遞增行數(shù)計數(shù)

如果讀完一個單詞躺翻, 遞增單詞計數(shù)

讀取下一個字符

輸入循環(huán)的模型:

while ((ch = getchar()) != STOP)

{?

...

}

STOP表示能標(biāo)識輸入末尾的某個值丧叽。

要查找一個單詞里是否有某個字符, 可以在程序讀入單詞的首字符時把一個標(biāo)記(名為 inword) 設(shè)置為1获枝。 也可以在此時遞增單詞計數(shù)蠢正。 然后, 只要inword為1(或true) 省店, 后續(xù)的非空白字符都不記為單詞的開始嚣崭。 下一個空白字符, 必須重置標(biāo)記為0(或false) 懦傍, 然后程序就準(zhǔn)備好讀取下一個單詞雹舀。

如果c不是空白字符, 且inword為假

設(shè)置inword為真粗俱, 并給單詞計數(shù)

如果c是空白字符说榆, 且inword為真

設(shè)置inword為假

在讀到每個單詞的開頭時把inword設(shè)置為1(真) , 在讀到每個單詞的末尾時把inword設(shè)置為0(假) 寸认。 只有在標(biāo)記從0設(shè)置為1時签财, 遞增單詞計數(shù)。 如果能使用_Bool類型偏塞, 可以在程序中包含stdbool.h頭文件唱蒸, 把inword的類型設(shè)置為bool, 其值用true和false表示灸叼。 如果編譯器不支持這種用法神汹, 就把inword的類型設(shè)置為int庆捺, 其值用1和0表示

如果使用布爾類型的變量, 通常習(xí)慣把變量自身作為測試條件屁魏。

用if (inword)代替if (inword == true)

用if (!inword)代替if (inword == false)

可以這樣做的原因是滔以, 如果 inword為true, 則表達(dá)式 inword == true為true氓拼; 如果 inword為false你画, 則表達(dá)式inword == true為false。 所以披诗, 還不如直接用inword作為測試條件撬即。 類似地, !inword的值與表達(dá)式inword == false的值相同(非真即false呈队, 非假即true)剥槐。

該程序使用邏輯運算符把偽代碼翻譯成C代碼。如果c不是空白字符宪摧, 且inword為假翻譯成如下C代碼:

if (!isspace(c) &&!inword)

注意粒竖, !inword 與 inword == false 等價。 上面的整個測試條件比單獨判斷每個空白字符的可讀性高:

if (c != ' ' && c != '\n' && c != '\t' && !inword)

如果c不是空白字符几于, 且如果c不在單詞里”蕊苗。 如果兩個條件都滿足, 則一定是一個新單詞的開頭沿彭, 所以要遞增n_words朽砰。 如果位于單詞中, 滿足第1個條件喉刘, 但是inword為true瞧柔, 就不遞增 n_word。 當(dāng)讀到下一個空白字符時睦裳, inword 被再次設(shè)置為 false造锅。 檢查代碼, 查看一下如果單詞之間有多個空格時廉邑, 程序是否能正常運行哥蔚。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蛛蒙,隨后出現(xiàn)的幾起案子糙箍,更是在濱河造成了極大的恐慌,老刑警劉巖牵祟,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倍靡,死亡現(xiàn)場離奇詭異,居然都是意外死亡课舍,警方通過查閱死者的電腦和手機(jī)塌西,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來筝尾,“玉大人捡需,你說我怎么就攤上這事〕镆” “怎么了站辉?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長损姜。 經(jīng)常有香客問我饰剥,道長,這世上最難降的妖魔是什么摧阅? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任汰蓉,我火速辦了婚禮,結(jié)果婚禮上棒卷,老公的妹妹穿的比我還像新娘顾孽。我一直安慰自己,他們只是感情好比规,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布若厚。 她就那樣靜靜地躺著,像睡著了一般蜒什。 火紅的嫁衣襯著肌膚如雪测秸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天灾常,我揣著相機(jī)與錄音霎冯,去河邊找鬼。 笑死岗憋,一個胖子當(dāng)著我的面吹牛肃晚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仔戈,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼关串,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了监徘?” 一聲冷哼從身側(cè)響起晋修,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凰盔,沒想到半個月后墓卦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡户敬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年落剪,在試婚紗的時候發(fā)現(xiàn)自己被綠了睁本。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡忠怖,死狀恐怖呢堰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凡泣,我是刑警寧澤枉疼,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站鞋拟,受9級特大地震影響骂维,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贺纲,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一航闺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哮笆,春花似錦来颤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至项阴,卻和暖如春滑黔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背环揽。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工略荡, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人歉胶。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓汛兜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親通今。 傳聞我的和親對象是個殘疾皇子粥谬,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容