選擇結構程式設計

EricsT發表於2024-10-20

在順序結構中,各語句都是按自上而下的順序執行的,執行完上一個語句就自動執行下一個語句,是無條件的,不必做任何判斷。這是最簡單的程式結構。實際上,在很多情況下,需要根據某個條件是否滿足來決定是否執行指定的操作任務,或者從給定的兩種或多種操作選擇其一。這就是選擇結構要解決的問題。

選擇結構和條件判斷

由於程式處理問題的需要,在大多數程式中都會包含選擇結構,需要在進行下一操作之前先進行條件判斷。

C語言有兩種選擇語句:

  1. if語句:用來實現兩個分支的選擇結構
  2. switch語句:用來實現多分支的選擇結構

例:題目要求解得 ax2+bc+c=0 方程的根。由鍵盤輸入 a, b, c 假設 a, b, c的值任意,並不保證 b2-4ac>=0。需要在程式中進行判別,如果 b2-4ac>=0,就計算並輸出方程的兩個實根,如果 b2-4ac<0,就輸入“方程無實根”的資訊。


//題目要求解得 ax^2 + bc + c = 0 方程的根。
//由鍵盤輸入 a, b, c 假設 a, b, c的值任意,並不保證 b^2 - 4ac >= 0。
//需要在程式中進行判別,如果 b2 - 4ac >= 0,就計算並輸出方程的兩個實根,
//如果 b2 - 4ac<0,就輸入“方程無實根”的資訊。

#include <stdio.h>
#include <math.h>

int main(void)
{
	double a, b, c;
	scanf("%lf %lf %lf", &a, &b, &c);

	double dis = b * b - 4 * a * c;
	if (dis < 0)
	{
		printf("方程無實根\n");
		return -1;
	}

	double p = 0 - b / (2 * a);
	double q = sqrt(dis) / (2 * a);

	double x1 = p + q;
	double x2 = p - q;
	
	printf("x1 = %lf\nx2 = %lf\n", x1, x2);

	return 0;
}

在VS編譯器內會報C4996錯誤,解決見下文:(下同)

C4996 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. - EricsT - 部落格園 (cnblogs.com)

執行結果:

結果一:走無實根分支選擇結構程式設計  結果二:走有根分支選擇結構程式設計

用 if 語句實現選擇結構

用 if 語句處理選擇結構舉例

例:輸入兩個實數,按代數值由小到大的順序輸出這兩個數


//例:輸入兩個實數,按代數值由小到大的順序輸出這兩個數

#include <stdio.h>

int main()
{
	double a, b;
	scanf("%lf %lf", &a, &b);

	if (a > b)
		printf("%lf %lf\n", b, a);
	else
		printf("%lf %lf\n", a, b);

	return 0;
}

執行結果:

分支1:選擇結構程式設計  分支2:選擇結構程式設計

例:輸入3個數 a,b,c 要求由小到大順序輸出


//例:輸入3個數 a,b,c 要求由小到大順序輸出

#include <stdio.h>

int main()
{
	double a, b, c;
	scanf("%lf %lf %lf", &a, &b, &c);

	if (a > b)
	{
		double temp = a;
		a = b;
		b = temp;
	}//a < b

	if (a > c)
	{
		double temp = a;
		a = c;
		c = temp;
	}//a < c

	if (b > c)
	{
		double temp = b;
		b = c;
		c = temp;
	}//b < c

	printf("%lf %lf %lf\n", a, b, c);

	return 0;
}

執行結果:

選擇結構程式設計

if 語句的一般形式

if 語句的一般形式:

if (表示式) 語句1
[else 語句2]

表示式可以是關係表示式、邏輯表示式,甚至是數值表示式。

所謂的關係表示式就是兩個數值進行比較的式子。

在 if 語句的一般形式中,方括號內的部分(即 else 子句)為可選的,即可以有,也可以沒有

語句1和語句2可以是一個簡單的語句,也可以是一個複合語句,還可以是另一個 if 語句(即在一個 if 語句中又包括另一個或多個內嵌的 if 語句)

if 語句常用的3種形式:

if (表示式)    語句1
if (表示式)
    語句1
else
    語句2
if (表示式)    語句1
else if (表示式2)    語句2
else if (表示式3)    語句3
            .         .
            .         .
            .         .
else if (表示式m)    語句m
else                 語句n

整個 if 語句可以寫在一行上也可以寫在多行上

if 語句無論是寫在一行上還是寫在多行上,都是屬於一個整體,屬於同一個語句。

else 子句是不能作為語句單獨使用的,必須是 if 語句的一部分,與 if 語句配對使用

內嵌語句也可以是一個 if 語句

在 if 語句中要對給定的條件進行檢查,判定所給定的條件是否成立。判斷的結果是一個邏輯值“是”或“否”

關係運算子和關係表示式

在C語言中,比較符(或稱比較運算子)稱為關係運算子。

所謂“關係運算”就是“比較運算”,將兩個數值進行比較,判斷其比較的結果是否符合給定的條件。

關係運算子及其優先次序

C語言提供6種關係運算子

  1. < 小於
  2. <= 小於或等於
  3. > 大於
  4. >= 大於或等於
  5. == 等於
  6. != 不等於

前四種關係運算子的優先順序相同,後兩種也相同,前四種優先順序高於後兩種

關係運算子的優先順序低於算術運算子

關係運算子的優先順序高於賦值運算子

關係表示式

用關係運算子將兩個數值或數值表示式連線起來的式子,稱為關係表示式

邏輯運算子和邏輯表示式

用邏輯運算子將關係表示式或其他邏輯量連線起來的式子就是邏輯表示式

邏輯運算子及其優先次序

有3種邏輯運算子,與(AND)或(OR)非(NOT)

在 BASIC 和 Pascal 等語言中可以在程式中直接用 AND,OR,NOT作為邏輯運算子,在 C 語言中不能再程式中直接使用 AND,OR,NOT 作為邏輯運算子,而是用其他符號代替

C 邏輯運算子及其含義
運算子 含義 舉例 說明
&& 邏輯與 a && b 如果 a 和 b 都是真,則結果為真,否則為假
|| 邏輯或 a || b 如果a 和 b 有一個以上為真,則結果為真,二者都為假,則結果為假
! 邏輯非 !a 如果 a 為真,則 !a 為假,如果 a 為真,則 !a 為假

“&&”和“||”是雙目運算子,要求有兩個運算物件(運算元)“!”是一目(元)運算子,只要求有一個運算物件

邏輯運算的真值表
a b !a !b a && b a || b

非(!)的優先順序高於與(&&),與(&&)的優先順序高於或(||)

邏輯運算子中的“&&”和“||”的優先順序低於關係運算子,而“!”的優先順序高於算術運算子

邏輯表示式

邏輯表示式應該是一個邏輯量“真”或“假”

C語言編譯系統在表示邏輯運算結果時,以數值“1”代表“真”,以數值“0”代表“假”,但在判斷一個量是否為“真”時,以0代表“假”,以非0代表“真”。即將一個非零的數值認作為“真”

由系統給出的邏輯運算結果不是0技術1,不可能是其他數值。

在邏輯表示式中作為參加邏輯運算的運算物件可以是 0(“假”)或任何非0的數值(按“真”對待)

邏輯運算子兩側的運算物件不但可以是0和1,或者是0和非0整數,也可以是字元型、浮點型、列舉型或指標型的純量型資料。系統最終以0和非0來判定它們屬於“真”或“假”

邏輯運算的真值表
a b !a !b a && b a || b
非0 非0 0 0 1 1
非0 0 0 1 0 1
0 非0 1 0 0 1
0 0 1 1 0 0

在邏輯表示式的求解中,並不是所有的邏輯運算子都被執行,只是在必須執行下一個邏輯運算子才能求出表示式的解時,才執行該運算子

邏輯型變數

是C99所增加的一種資料型別。

可以將關係運算和邏輯運算的結果存到一個邏輯型變數裡面,以便分析和運算。

定義邏輯變數用型別符_Bool

在標頭檔案 stdbool.h 中,將 bool 定義為 _Bool 的同義詞,同時定義了兩個符號常量 true 和 false ,true 代表 1,false 代表 0,用它們分表代表真和假

邏輯變數 bool 和 true 和 false 原本是C++中使用的,現在 C 把它們吸收進 C 新標準,以增加程式的可讀性。但是目前使用的有些 C 編譯系統並未實現此功能。

條件運算子和條件表示式

條件運算子是由兩個符號(“?”和“:”)組成,必須一起使用。要求有3個操作物件,稱為三目(元)運算子,它是C語言中唯一的一個三目運算子

條件表示式的一般形式:表示式1 ? 表示式2 : 表示式3

條件運算子的執行順序:

  • 先求解“表示式1”
    • 若為真則執行“表示式2”此時“表示式2”的值作為整個條件表示式的值
    • 若為假則執行“表示式3”此時“表示式3”的值作為整個條件表示式的值

條件運算子的優先順序高於賦值運算子

條件運算子的優先順序比關係運算子和算術運算子都低

例:輸入一個字元,判別它是否是大寫字母,如果是,將它轉換為小寫字母;如果不是,不轉換,然後輸出最後得到的字元。


//例:輸入一個字元,判別它是否是大寫字母,如果是,將它轉換為小寫字母;如果不是,不轉換,然後輸出最後得到的字元。

#include <stdio.h>

int main(void)
{
	char ch;

	scanf("%c", &ch);

	((ch <= 'Z') && (ch >= 'A')) ? (ch = ch + 32) : (ch = ch);

	printf("ch = %c\n", ch);

	return 0;
}

執行結果:

結果1:選擇結構程式設計,結果2:選擇結構程式設計

條件表示式相當於一個不帶關鍵字 if 的 if 語句,用它處理簡單的選擇結構可使程式簡潔。

選擇結構的巢狀

在 if 語句中又包含一個或多個 if 語句稱為 if 語句的巢狀

其一般形式:選擇結構程式設計

else 總是與它上面的最近的未配對的 if 配對

例:有一個函式:x < 0 時,y = -1;x = 0 時,y = 0;x > 0 時,y = 1;編一程式,輸入一個 x 值,要求輸出相應的 y 值


//例:有一個函式:x < 0 時,y = -1;x = 0 時,y = 0;x > 0 時,y = 1;編一程式,輸入一個 x 值,要求輸出相應的 y 值

#include <stdio.h>

int main(void)
{
	double x;
	int y;

	scanf("%lf", &x);

	if (x < 0)
		y = -1;
	else
	{
		if (0 == x)
			y = 0;
		else
			y = 1;
	}

	printf("y = %d\n", y);

	return 0;
}

執行結果:

結果一:選擇結構程式設計

結果二:選擇結構程式設計

結果三:選擇結構程式設計

用 switch 語句實現多分支選擇結構

C語言提供 switch 語句直接處理多分支選擇

switch 句是多分支選擇語句

例:要求按照考試成績的等級輸出百分制分數段,A等85分以上,B等[70, 84],C等[60, 69],D等為60分以下。成績由鍵盤輸入


//例:要求按照考試成績的等級輸出百分制分數段,A等85分以上,B等[70, 84],C等[60, 69],D等為60分以下。成績由鍵盤輸入

#include <stdio.h>

int main(void)
{
	char ch;

	scanf("%c", &ch);

	switch (ch)
	{
	case 'A':
		printf("85以上\n");
		break;
	case 'B':
		printf("70到84\n");
		break;
	case 'C':
		printf("60到69\n");
		break;
	case 'D':
		printf("60以下\n");
		break;
	}

	return 0;
}

執行結果:

結果一:選擇結構程式設計  結果二:選擇結構程式設計  結果三:選擇結構程式設計  結果四:選擇結構程式設計

switch 語句的作用是根據表示式的值,使流程跳轉到不同的語句。

switch 語句的一般形式:

switch (表示式)
{
    case 常量1:    語句1
    case 常量2:    語句2
      .    .        .  
      .    .        .  
      .    .        .  
    case 常量n:    語句n
    default:       語句n+1
}

switch 後面括號內的“表示式”其值型別應該為整數型別(包括字元型)

switch 下面的花括號內是一個複合語句。這個複合語句包括若干語句,它是 switch 語句的語句體。語句體內包含多個以關鍵字 case 開頭的語句行和最多一個以 default 開頭的行。case 後面跟一個常量(或常量表示式)case 和 default 都是起標號( label 或稱標籤、標記)的作用,用來標誌一個位置。

執行 switch 語句時,先計算 switch 後面的“表示式”的值,然後將它與各 case 標號比較,如果沒有與 switch 表示式相匹配的 case 常量,流程轉去執行 default 標號後面的語句

可以沒有 default 語句,此時如果沒有與 switch 表示式相匹配的 case 常量,則不執行任何語句,流程轉到 switch 語句的下一個語句。

各個 switch 標號出現的次序不影響執行結果

每一個 case 常量必須互不相同;否則就會出現互相矛盾的現象(對 switch 表示式的同一個值,有兩種或多種執行方案)

case 標號只起標記的作用。在執行 switch 語句時,根據 switch 表示式的值找到匹配的入口標號,並不在此進行條件檢查,在執行完一個 case 標號後面的語句後,就從此標號開始執行下去,不再進行判斷。

一般情況下,在執行一個 case 子句後,應當用 break 語句使流程跳出 switch 結構,即終止 switch 語句的執行。最後一個 case 子句(今為 default 子句)中可不必加 break 語句,因為流程已經到了 switch 結構的結束處。

在 case 子句中雖然包含了一個以上執行語句,但可以不必用花括號括起來,會自動順序執行本 case 標號後面所有的語句。當然加上花括號也可以。

多個 case 標號可以共用一組執行語句

選擇結構程式綜合舉例

例:寫一程式,判斷某一年是否為閏年


//例:寫一程式,判斷某一年是否為閏年

#include <stdio.h>

int main(void)
{
	int year;

	scanf("%d", &year);

	if (((0 == (year % 4)) && (0 != (year % 100))) || (0 == (year % 400)))
		printf("%d是閏年\n", year);
	else
		printf("%d不是閏年\n", year);

	return 0;
}

執行結果:

結果一:選擇結構程式設計  結果二:選擇結構程式設計

相關文章