決策敘述 - if-else-if 與 switch

除了巢狀結構,另外還有一種多重判斷式,也就是在 if-else 的程式敘述當中的 else 後面還可以加上一個 if ,進行下一層的邏輯判斷,此種形式的 if-else 與上述的巢狀敘述不太相同,每個判斷式屬於同一個執行層級,結構如下:
if(Expression ) 
{
    if 程式區塊 … 
}
else if(Expression )
{
    else 程式區塊 …
}
如你所見, else 後面緊接著一個 if 敘述,其中包含了特定的判斷式,只有當這個判斷式成立,也就是回傳 true 的時候,才會執行其中的 else 區塊,而非如同上述的 if-else ,當 if 不成立時無條件執行 else 。
class Program
{
    static void Main(string[] args)
    {
        const int intMaxSpeed = 100;
        const int intMinSpeed = 60;
        int intSpeed = 0;

        Console.WriteLine("請輸入目前車速?");
        intSpeed = int.Parse(Console.ReadLine());

        if (intSpeed > intMaxSpeed)
        {
            Console.WriteLine("請注意,目前車速過快!!");
        }
        else if (intSpeed > intMinSpeed)
        {            
             Console.WriteLine("目前車速適中,請保持車速!!"); 
        }
        else if (intSpeed < intMinSpeed)
        {
            Console.WriteLine("請注意,目前車速過慢!!"); 
        }
        Console.ReadLine();
    }
}
其中接受使用者輸入任意數字,儲存至 intSpeed 變數,並且利用兩組 else if 進行不同狀況的判斷。

另外,如果 if 或是 else 程式碼區塊的敘述只有一行,就可以將大括弧省略,語法如下:
if(Expression ) 
    if 程式區塊 … 
else if(Expression )
    else 程式區塊 …
單行的 if-else 敘述比較簡潔,而敘述區塊通常會進行縮排以方便閱讀。

如同巢狀 if 判斷式,其中可以加入更多的 else-if 結構,以提供更複雜的判斷邏輯,如果你覺得這樣的結構太過繁雜,可以利用 switch 敘述句實作相同的功能。

switch 敘述句

switch 是另一個經常用來控制程式執行流程的敘述句,這種敘述句允許你從多個條件式中,尋找符合的條件值,並且執行其中對應的相關程式碼,語法表示式如下:
switch(express)
{
     case constant-expression1
       區塊敘述句  …
      break ; 

     case constant-expression2
       區塊敘述句  …
       break ; 

     [default : statement]
 }
switch關鍵字後面緊接著由括弧圍繞起來的條件表示式,接下來大括弧裏的程式碼區塊由數個case子句所組成,每個case關鍵字後面緊接著 witch 件式可能的結果值,其中如果符合條件值, case 下面的程式碼區塊則被執行, case 區塊中的 break 敘述,負責跳出switch 敘述。

當所有的 case 敘述均不符合時,最後的 default 區塊敘述被執行,你可以選擇使用 default 敘述,或是直接跳出整個 switch 敘述區塊。default 同樣可以加上一個 break 敘述,不過這種作法並非絕對必要,它只是可以讓你的程式碼維持一致的語法。考慮以下的列表:

分數等級變數
90AintLevelA
80BintLevelB
70CintLevelC
60DintLevelD
50不級格intLevelE

使用 switch 敘述,判斷使用者輸入的資料,輸出對應的成績等級。
class Program
{  
 static void Main(string[] args)
 { 
  const int intLevelA = 90 ; 
  const int intLevelB = 80 ; 
  const int intLevelC = 70 ; 
  const int intLevelD = 60 ; 
  const int intLevelN = 50 ; 
  int intStuLevel = 0; 

  Console.WriteLine("請輸入學生成績 : 90,80,70,60,50") ;
  intStuLevel = int.Parse(Console.ReadLine()); 

  switch (intStuLevel)
  {
   case intLevelA : 
    Console.WriteLine("成績等級 : A" ) ; 
    break ; 
   case intLevelB : 
    Console.WriteLine("成績等級 : B" ) ; 
    break ; 
   case intLevelC : 
    Console.WriteLine("成績等級 : C" ) ; 
    break ; 
   case intLevelD : 
    Console.WriteLine("成績等級 : D" ) ; 
    break ; 
   case intLevelN : 
    Console.WriteLine("成績等級 : 不級格 " ) ; 
    break ; 
   default : 
    Console.WriteLine
     ("請輸入符合設定的成績值 : 90,80,70,60,50" ) ; 
    break ; 
  } 
  Console.ReadLine();
      }
}
首先建立上表列舉的五個常數值,並且定義一個變數 intStuLevel ,儲存使用者於主控台輸入的成績值。

switch 判斷區塊以 intStuLevel 變數為判斷值,配置於 switch 關鍵字後面的括弧裏。

接著以表列五個等級代表常數比對條件,根據比對結果,於主控台輸出成績的等級,其中每個 case 裏的程式碼區塊,都必須使用關鍵字 break 作結尾,以確保比對成功時跳出 switch 敘述句,否則的話,接下來的 case 會持續執行直到 switch 結束。

最後程式碼還包含了一個 default 敘述,當使用者輸入的成績比對不到符合值,程式流程會跳到這個程式碼區段,輸出成績不符之訊息。

執行範例程式,依畫面上的指示,輸入成績分數,程式依據分類等級,輸出此分數所屬的成績等級,結果如下:
請輸入學生成績 : 90,80,70,60,50
70
成績等級 : C
若是其輸入的成績不是畫面上提示的分數,則要求輸入符合的成績值,如下式:
請輸入學生成績 : 90,80,70,60,50
33
請輸入符合設定的成績值 : 90,80,70,60,50

我們可以修改這個範例,提供進一步的判斷,當使用者輸入的成績等於 100 則跳到intLevelA 敘述句,若是輸入的值等於 0 則跳到 intLevelN 的 case 敘述句,因此將 case 相關的程式碼修改如下:
case intLevelA : 
 Console.WriteLine("成績等級 : A" ) ; 
 break ; 
case intLevelB : 
 Console.WriteLine("成績等級 : B" ) ; 
 break ; 
case intLevelC : 
 Console.WriteLine("成績等級 : C" ) ; 
 break ; 
case intLevelD : 
 Console.WriteLine("成績等級 : D" ) ; 
 break ; 
case intLevelN : 
 Console.WriteLine("成績等級 : 不及格 " ) ; 
 break ; 
case 100 : 
 goto case intLevelA ;      
case 0 : 
 goto case intLevelN ;   
default : 
 Console.WriteLine("請輸入符合設定的成績值 : 90,80,70,60,50" ) ; 
 break ;
其中使用 goto 跳躍敘述句,跳到指定的 case 敘述句裏。

底下為輸入100的執行結果:
請輸入學生成績 : 90,80,70,60,50
100
成績等級 : A

goto 並非良好的敘述句,有經驗的程式設計師會儘免避免使用這個跳躍敘述句,它非常容易破壞程式的架構,尤其不利大型程式專案的開發設計與維護。

最後談談 break 這個關鍵字,它在 case 當中不允許被省略,但是有一個例外,若是case 底下的程式區塊為空值,此時省略 break 關鍵字並不會造成任何錯誤,編譯器會越過此 case 判斷式,直接執行下一個 case 區塊內容,如果程式邏輯當中有一個以上的case 狀況執行相同的程式區塊,可以透過此種作法達到目的。
class Program
{
    static void Main(string[] args)
    {
        const int intLevelA = 90;
        const int intLevelB = 80;
        const int intLevelC = 70;
        const int intLevelD = 60;
        const int intLevelN = 50;
        int intStuLevel = 0;

        Console.WriteLine("請輸入學生成績: 90,80,70,60,50");
        intStuLevel = int.Parse(Console.ReadLine());

        switch (intStuLevel)
        {
            case 100: 
            case intLevelA:
                Console.WriteLine("成績等級: A");
                break;
            case intLevelB:
                Console.WriteLine("成績等級: B");
                break;
            case intLevelC:
                Console.WriteLine("成績等級: C");
                break;
            case intLevelD:
                Console.WriteLine("成績等級: D");
                break;
            case 0:
            case intLevelN:
                Console.WriteLine("成績等級: 不及格");
                break;
            default:
                Console.WriteLine("請輸入符合設定的成績值: ,80,70,60,50");
                break;
        }
        Console.ReadLine();
    }
}
相較於上一個範例,新增的 case 沒有內容區塊,因此當 switch 的 intStuLevel 等於 100 時會執行一開始的 case intLevelA 區塊,同樣的最後的 case 0 亦是無內容區塊,因此會執行 case intLevelN 的內容區塊。

測試調整後的結果,輸入100,switch執行其中等級A的case區塊。
請輸入學生成績 : 90,80,70,60,50
100
成績等級 : A
省略 break 能夠將數個 case 合併成相同的程式區塊,毋需在每個 case 區塊裏重複撰寫相同的程式碼。

除了整數之外,其他的整數型別亦能當作表示式使用,其中包含了 char 字元型別,你可以利用字元作為判斷條件,底下修改上述的範例,進行實作示範。
class Program
{
    static void Main(string[] args)
    {
        const char charLevelA = 'A';  
        const char charLevelB = 'B';
        const char charLevelC = 'C';
        const char charLevelD = 'D';
        const char charLevelE = 'E';        

        Console.WriteLine("請輸入學生成績 : A,B,C,D,E");
        char levelChar =char.Parse( Console.ReadLine());

        switch (levelChar)
        {            
            case charLevelA:
                Console.WriteLine("成績等級 : 頂尖(A)");
                break;
            case charLevelB:
                Console.WriteLine("成績等級 : 高於平均(B)");
                break;
            case charLevelC:
                Console.WriteLine("成績等級 : 等於平均(C)");
                break;
            case charLevelD:
                Console.WriteLine("成績等級 : 不及格(C)");
                break;
            case charLevelE:
                Console.WriteLine("成績等級 : 不及格(E)");
                break;           
        }
        Console.ReadLine();
    }
}
執行結果
請輸入學生成績 : A,B,C,D,E
B
成績等級 : 高於平均(B)
這是輸入等級 B 的輸出結果,讀者可以自行執行範例,檢視各種等級的輸出結果。









沒有留言: