2016-09-01 5 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

Проблема в том, что существует вероятность того, что ваши переменные userHeight и userWeight все еще держат значение мусора, так как вы их не инициализировали.

Вы можете попробовать инициализировать их по умолчанию действительным:

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

Это ложное утверждение, если вы действительно посмотрите на код. Хотя хорошее предложение инициализировать ценность в этом конкретном случае, нет необходимости, поскольку есть лучшие способы выразить одно и то же намерение с помощью другого кода. –

+0

Yup верно, что на основе кода переменные будут в конечном итоге инициализированы, но компилятор недостаточно умен, чтобы понять это. И да, верно, что есть лучшие способы написания такого кода. – 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 в качестве специального значения «не назначено». У исходного кода в вопросе был лучший способ выразить это с помощью отдельной переменной Boolean. Вы можете использовать значение с нулевым значением, если хотите сохранить одну переменную для хранения значения и «no value yet». –

+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 не может работать, и, следовательно, переменные не будут Assigner. Да, в вашем конкретном случае на самом деле можно обнаружить, что первая итерация выполняется, но, скорее всего, это недостаточно распространенный случай для добавления правила в компилятор.

do ... while с другой стороны гарантирует, что происходит хотя бы одна итерация и, следовательно, назначение переменной (через параметр out) всегда будет происходить с точки зрения компилятора.

0

Почему вы не хотите инициализировать переменные с некоторыми, например, отрицательное значение; Ваш код не достигнет конца до тех пор, пока пользователь не установит действительные значения

0

Выполнение вашего запроса приведет к поражению цели локального масштаба. Это нельзя сделать по уважительной причине. Точка объявления переменной локально - это не помешать более широкой области шума. В вашем случае это не шум, переменные userWidth и userHeight имеют смысл в основной области, потому что вы используете их там. Таким образом, вы либо инициализируете их должным образом в методе, либо объявляете их внутри if и перемещаете код, который их использует в секцию if. Последнее означало бы, что у вас есть двойной код, вы можете это исправить, переместив вычисление BMI в отдельный метод и вызовите это из обоих разделов, передав переменные в качестве аргументов и вернув BMI.

Неплохо было бы поместить вычисление и выходной оператор в тот же метод. Но это уже другая история.

Смежные вопросы