2016-09-01 7 views
0

私の教授は、ユーザーの身長と体重をとり、bmiを計算するプログラムを作成するよう依頼しました。私はもう少しそれを取って、いくつかの "入力検証"ロジックを追加しました。これは、誰かが体重を「猫」と入力すると、「猫」が有効な体重ではないことを知らせることを意味します。C#でスコープ外の変数を参照する方法

class MainClass 
{ 
    public static void Main() 
    { 
     float userWeight; 
     float userHeight;   
     bool weight = true; 
     Console.Write ("Weight: "); 
     while (weight) 
     {    
      var inputWeight = (Console.ReadLine()); 
      if (!float.TryParse (inputWeight, out userWeight)) { 
       Console.WriteLine ("Invalid input"); 
       Console.Write ("Please try again: "); 
      } 
      else 
      { 
       weight = false; 
      } 
     } 
     bool height = true; 
     Console.Write ("Height: "); 
     while (height) 
     { 
      var inputHeight = (Console.ReadLine()); 
      if (!float.TryParse (inputHeight, out userHeight)) { 
       Console.WriteLine ("Invalid input"); 
       Console.Write ("Please try again: "); 
      } 
      else 
      { 
       height = false; 
      } 
     } 
     float bmiHeight = userHeight * userHeight; // error for userHeight 
     float bmi = userWeight/bmiHeight * 703; // error for userWeight 
     Console.WriteLine ("You BMI is " + bmi); 
    }   
} 

エラーは「未割り当てのローカル変数の使用」です。私は、ユーザー変数をIFステートメント内に割り当てていること、そしてそれらがそのIFステートメントの終わりまでしか持続しないことを知っています。

私の質問は、ifステートメントに変数を代入し、そのステートメントの外でその変数の新しい値を参照する方法です。

それは退屈そうなので確かに、私は、巣にそれらすべてを持っていない....

答えて

0

ここで問題となるのは、変数userHeightuserWeightが初期化していないためにガベージ値を保持している可能性があるということです。

あなたは有効なデフォルトでそれらを初期化しようとすることができます

float userHeight = DEFAULT_HEIGHT; 
float userWeight = DEFAULT_WEIGHT; 
+1

実際にコードを見ると、これは誤った記述です。この特定のケースで価値を初期化するための良い提案は、同じ目的を別のコードで表現するより良い方法があるので必要ではありません。 –

+0

しかし、コードに基づいて変数は最終的には初期化されますが、コンパイラはそれを実現するほどスマートではありません。そして、そういうコードを書く良い方法があるのは事実です。 – Lincoln

+0

私のuserWeightとuserHeight変数を0に設定しました!ありがとう! – Killzone

0
public void heightAndWeight() 
    { 
     double height = getValue("What is your height in inches?",36,80); 
     double weight = getValue("What is your weight in kilograms?",45,135); 
     if (height > 0 && weight > 0) 
     { 
      Console.WriteLine("your BMI is " + (height * weight).ToString("N2")); 
     } 
    } 
    private double getValue(string question,int lowRange,int highRange) { 
     double ret = 0; 
     while(ret==0){ 
      Console.WriteLine(question); 
      string retStr = Console.ReadLine(); 
      if(double.TryParse(retStr,out ret)) 
      { 
       if(ret<lowRange||ret>highRange){ 
        Console.WriteLine("You must enter a value between "+lowRange.ToString()+" and "+highRange.ToString()+". Please try again."); 
        ret=0; 
       }else{ 
        return ret; 
       } 
      }else{ 
       Console.WriteLine("Invalid entry. Please try again"); 
      } 
     } 
     return ret; 
    } 
+0

いいリファクタリング。また、特別な「割り当てられていない」値として0を使用することはお勧めしません。問題の元のコードは、別のブール変数でそれを表現するより良い方法を持っていました。単一の変数を保持し、値を保持しない場合は、null値を使用できます。 –

+0

余分な変数は必要ありません。値が有効な場合は 'while(true)'と 'return'を使用してください。 – Hamawi

0

Do ... while(condition)は、あなたのケースのために、より適しており、また、その値を確認するために、コンパイラが実際に割り当てられていることができます:

var isHeightValid = false; 
    do 
    { 
     var inputHeight = (Console.ReadLine()); 
     if (!float.TryParse (inputHeight, out userHeight)) { 
      Console.WriteLine ("Invalid input"); 
      Console.Write ("Please try again: "); 
     } 
     else 
     { 
      isHeightValid = false; 
     } 
    } 
    while (!isHeightValid); 

理由:コンパイラは、一般的なケースのためにwhile(condition)の最初の反復が常に実行されることを把握するのに十分なスマートではないので、それはwhile内のコードが実行されないことがあり、したがって、変数は、割当されないことを前提としています。はい、具体的なケースでは、最初の繰り返しが実行されたことを実際に検出することは可能ですが、これはコンパイラにルールを追加するのに十分なケースではないようです。

do ... while一方、少なくとも1回の反復が行われることを保証するので、コンパイラの観点から変数代入(out経由)が常に発生します。

0

あなたには、いくつかの、例えば、負の値を持つ変数を初期化したくないのはなぜ。あなたのコードは、有効な値がユーザによって挿入されるまで終了しません。

0

リクエストを実行するとローカルスコープの目的が無効になります。それは正当な理由で行うことはできません。変数をローカルに宣言することは、より広い範囲にノイズを掛けないことです。あなたの場合、それはノイズではありません、userWidthとuserHeight変数は、あなたがそこで使うので、メインスコープで意味を持ちます。したがって、メソッド内で適切に初期化するか、またはifの中で宣言し、それらを使用するコードをifセクションに移動します。後者は、いくつかの二重コードを持っていることを意味するでしょう、あなたはBMIの計算を別の方法に移すことによってそれを修正することができ、両方のifセクション内から変数を引数として渡してBMIを取り戻します。

計算と出力文を同じメソッドに入れるのは良いことではありません。しかしそれは別の話です。

関連する問題