2016-02-26 61 views
1

我有以下的(很簡單)控制檯,做基礎圓計算的計算器:爲什麼當它不應該出現這個異常?

using System; 

namespace Circle 
{ 
    class Program 
    { 
     /* Compute the area of a cricle given its radius. */ 
     public static double Area(double radius) 
     { 
      return Math.Pow(radius, 2) * Math.PI; 
     } 

     /* Compute the circumference of a circle given is radius. */ 
     public static double Circumference(double radius) 
     { 
      return radius * 2 * Math.PI; 
     } 

     /* Compute the diameter of a circle given its radius. */ 
     public static double Diameter(double radius) 
     { 
      return radius * 2; 
     } 

     /* Report the result. */ 
     public static string Result(double radius, double area, double circumference, double diameter) 
     { 
      return "- A circle whose radius is " + radius + " has the following properties: " 
        + "\n- Area: " + area.ToString("0.##") + "\n- Circumference: " + circumference.ToString("0.##") 
        + "\n- Diameter: " + diameter.ToString("0.##"); 
     } 

     static void Main(string[] args) 
     { 
      double radius = 0; 
      char choice; 
      while (true) 
      { 
      Calculate: 
       { 
        // 1. Get the radius from the user. 
        Console.Write("- Enter the radius of the circle: "); 
        try 
        { // verify the input is of numerical type 
         radius = Convert.ToDouble(Console.ReadLine()); 
         if (radius <= 0) // check for negative values 
         { 
          Console.WriteLine(" [Error] Radius must be a positive value!"); 
          Console.WriteLine(); 
          continue; // restart from the next iteration without executing the rest of the statements 
         } // end if 
        } 
        catch (FormatException e) 
        { 
         Console.WriteLine(" [Error] " + e.Message); 
         Console.WriteLine(); // skip a line 
         continue; // restart from the next iteration without executing the rest of the statements 
        } // end catch 
       } 
       // 2. Calculate the area, circumference, and diameter of the circle. 
       double area = Area(radius); 
       double circumference = Circumference(radius); 
       double diameter = Diameter(radius); 
       // 3. Display the results. 
       Console.WriteLine(Result(radius, area, circumference, diameter)); 
      // 4. Ask the user whether to quit. 
      Ask: 
       { 
        Console.Write("- Do you wish to make another calculation [Y or N]? "); 
        choice = Convert.ToChar(Console.Read()); 
       } 
       if (choice.Equals('Y') || choice.Equals('y')) 
       { 
        goto Calculate; // return to the beginning of the Calculate block. 
       } 
       else if (choice.Equals('N') || choice.Equals('n')) 
       { 
        break; // exit 
       } 
       else { 
        Console.WriteLine("Invalid choice! Press Y to continue or N to exit."); 
        goto Ask; // return to the beginning of the Ask block. 
       } 
      } // end while 
      Console.WriteLine("Thank you for using me. Have a nice day!"); 
      Console.WriteLine(); 
     } // end Main 
    } 
} 

計算後,程序會詢問他們是否願意再拍計算的用戶。如果用戶輸入Y,程序將提示他們再次輸入半徑。如果用戶輸入N,則程序終止。

有,但是,有兩個基本問題:

  1. 如果用戶選擇通過按Y再拍計算,該程序會提示用戶輸入一個值,而且還執行了catch塊和投例外。這示出在該示例的輸出:
  • 輸入圓的半徑:3
  • 的圓的半徑爲3具有以下性質:
  • 面積:28.27
  • 周長:18.85
  • 直徑:6
  • 你是否想再次計算[Y或N]? Y
  • 輸入圓的半徑:[錯誤]輸入字符串格式不正確。

  • 輸入圓的半徑:

  • 當用戶輸入比Y或N以外的內容的第二個問題是,該方案還示出了意外行爲,如在輸出:
    • 輸入圓的半徑:4
    • 個圓,半徑爲4具有以下特性:
    • 面積:50.27
    • 周長:25.13
    • 直徑:8
    • 你希望再拍計算[Y或N]? j選擇無效!按Y繼續或按N退出。
    • 您是否希望進行另一次計算[Y或N]?無效的選擇!按Y繼續或按N退出。
    • 您是否希望進行另一次計算[Y或N]?無效的選擇!按Y繼續或按N退出。
    • 您是否希望進行另一次計算[Y或N]?

    我似乎無法弄清楚爲什麼會發生這些事情之一。我懷疑這是我的使用gotocontinue,但我不知道。

    +0

    你真的不應該使用'goto'。這不好。 – Enigmativity

    +0

    感謝您的評論。我知道這不是最好的想法,但對於這種情況來說似乎很合理。如果您有其他建議或替代方案,請隨時通知我。 –

    +0

    功能將比goto語句更優雅的解決方案 – ohiodoug

    回答

    3

    的問題是你的Convert.ToChar(Console.Read())。它從輸入中讀取一個字符,但輸入不會從控制檯設置,直到按下Enter鍵。所以Console.Read()正確得到'Y',但輸入有一個ENTER排隊,所以你的Convert.ToDouble(Console.ReadLine())得到一個空的字符串,它試圖轉換,因此例外。

    更改Convert.ToChar(Console.Read())Convert.ToChar(Console.ReadLine())並能正常工作。

    你也應該擺脫goto s也擺脫例外誘捕 - 你應該使用double.TryParse(...)來代替。沒有更多的例外。


    我做你的代碼,您可以嘗試的重構 - 沒有goto秒且不異常處理。

    while (true) 
    { 
        while (true) 
        { 
         Console.Write("- Enter the radius of the circle: "); 
         double radius; 
         if (double.TryParse(Console.ReadLine(), out radius) && radius > 0.0) 
         { 
          double area = Area(radius); 
          double circumference = Circumference(radius); 
          double diameter = Diameter(radius); 
          Console.WriteLine(); 
          Console.WriteLine(Result(radius, area, circumference, diameter)); 
          break; 
         } 
         Console.WriteLine(" [Error] Radius must be a positive value!"); 
         Console.WriteLine(); 
        } 
        string choice = ""; 
        while (true) 
        { 
         Console.Write("- Do you wish to make another calculation [Y or N]? "); 
         choice = Console.ReadLine(); 
         if (new [] { "Y", "N", }.Contains(choice.ToUpper())) 
         { 
          break; 
         } 
         Console.WriteLine(); 
         Console.WriteLine("- Invalid choice! Press Y to continue or N to exit."); 
        } 
        if (choice.ToUpper() == "N") 
        { 
         break; 
        } 
        Console.WriteLine(); 
    } 
    Console.WriteLine(); 
    Console.WriteLine("- Thank you for using me. Have a nice day!"); 
    Console.WriteLine(); 
    
    +0

    完全修復它。我承認,我對ReadLine()和Read()之間差異的理解是基本的。毫不奇怪,我在那裏做了什麼!謝謝! –

    +0

    只是對重構版本的提示:我將它複製到我的IDE中進行測試,但它告訴我沒有'Contains'方法,因此它給了我一個錯誤。我在VS 2015中使用了C#6.0。(但是我得到了修改後程序的一般邏輯) –

    +1

    您需要引用'System.Linq',我認爲'.Contains'才能工作。 – Enigmativity

    0

    問題出在您使用Read()ReadLine()以及輸入如何從外殼發送到Console對象。

    在控制檯對象,輸入流(緩衝液)被按下[確定]之後才加載。在這一點上,Read()將返回字符串中下一封未讀的性格,但只一個字符。當後續調用ReadLine()時,它將進入緩衝區,換行符仍在等待,所以它立即返回(在本例中)一個空字符串。歡鬧隨之而來。

    整治就留給讀者做練習;)

    +0

    如果作業是指我爲自己設計的初學C#用戶的問題,那麼你就是對的。感謝您的輸入! –

    +0

    夠公平的!我記得我自己也用幾種語言做了同樣的事情。如此編輯。 –

    +0

    不用擔心。再次感謝你:) –

    相關問題