Получение пользовательского ввода из оператора do while

Я здесь в полной растерянности ... Логика, кажется, настроена правильно, но "ответ" в операторе while говорит, что он не существует в текущем контексте. Я искал здесь и, похоже, нашел ту же проблему в этом контексте. Проблема заключается в преобразовании в метод?

    do
        {
            Console.WriteLine("enter a number between 1 and 5");
            int x = Convert.ToInt32(Console.ReadLine());

            Random r = new Random();
            int rr = r.Next(1, 5);
            Console.WriteLine("Do you want to continue?  Please select yes or no.");
            string response = Convert.ToString(Console.ReadLine());
        } while (response == "yes");

person Jordan Olivas    schedule 31.12.2016    source источник
comment
Вы объявили response внутри цикла, так что именно там он и существует. Обычно новый уровень отступа создает новую область видимости блока. Вы также, вероятно, захотите создать один случайный экземпляр для всего цикла, а не для каждой итерации   -  person Ňɏssa Pøngjǣrdenlarp    schedule 31.12.2016
comment
Если вы определяете response внутри цикла, то как он должен проверять его вне его? Вы должны определить string response перед циклом   -  person UnholySheep    schedule 31.12.2016
comment
Ответ действительно не виден за пределами области действия {}, объявите его перед выполнением   -  person Oleg Bogdanov    schedule 31.12.2016
comment
Вам также следует прочитать Как спросить и взять тур ... только потому, что вы еще не   -  person Ňɏssa Pøngjǣrdenlarp    schedule 31.12.2016
comment
Nitpick: Console.ReadLine уже дает string результат. Преобразовывать в строку не нужно.   -  person Hans Kesting    schedule 31.12.2016
comment
также максимальный параметр для Random.Next(min, max) является эксклюзивным, поэтому код будет генерировать только значение от 1 до 4   -  person Ňɏssa Pøngjǣrdenlarp    schedule 31.12.2016


Ответы (3)


Переменные, объявленные в одной области (обычно это набор фигурных скобок { ... }), недоступны за пределами этой области. Вы объявили response внутри цикла. Вам нужно объявить response вне цикла.

Вы также хотите удалить пробелы из строки перед ее сравнением, используя _ 4_. В противном случае в конце будет символ новой строки (\n), что приведет к сбою сравнения.

string response;

do {
    //...

    response = Console.ReadLine().Trim();
} while (response == "yes");
person Jonathon Reinhart    schedule 31.12.2016

Ваша переменная ответа не находится в контексте цикла. Просто переместите объявление переменной за пределы цикла, как показано ниже:

        string response = String.Empty;

        do
        {
            Console.WriteLine("enter a number between 1 and 5");
            int x = Convert.ToInt32(Console.ReadLine());

            Random r = new Random();
            int rr = r.Next(1, 5);
            Console.WriteLine("Do you want to continue?  Please select yes or no.");
            response = Convert.ToString(Console.ReadLine());
        } while (response == "yes");
person Thomas Fitzgerald    schedule 31.12.2016
comment
Нет необходимости создавать новый рандом для каждой итерации; это плохая привычка. Нет необходимости в Convert.ToString. - person Ňɏssa Pøngjǣrdenlarp; 31.12.2016
comment
@Plutonix - вы правы, но локальные переменные, используемые только внутри фигурных скобок, должны быть объявлены внутри фигурных скобок, чтобы ограничить область действия. Компилятор достаточно умен, чтобы сделать это максимально эффективным. - person Joe; 31.12.2016
comment
Компилятор не собирается перемещать создание Random за пределы цикла. Здесь буквально сотни вопросов, когда OP получает одно и то же число снова и снова, потому что они создают новый в цикле. Кроме того, r.Next(1, 5) также не будет генерировать число от 1 до 5. - person Ňɏssa Pøngjǣrdenlarp; 31.12.2016
comment
@Joe Компилятор обнаружит попытку использования неинициализированной локальной переменной. Здесь некорректно инициализировать переменную, потому что ее начальное значение никогда не будет использоваться. Некоторые инструменты, такие как ReSharper, могут даже автоматически предлагать вам удалить инициализацию. Кто-то однажды сказал: «Эй, вам следует инициализировать локальные переменные», и люди превратили это в жесткое правило, а не в общий совет ... точно так же, как omg никогда не используют фанатиков goto. - person Jonathon Reinhart; 01.01.2017

Может помочь немного инкапсулировать это. Как насчет:

static void Main(string[] args)
    {
        Random rand = new Random();
        do
        {
            Write("enter a number between 1 and 5");
            string response = Console.ReadLine();
            int x = 5;
            if (Validate(response, "1-5")) int.TryParse(response, out x);                
            Write(rand.Next(0,x));
            Write("Do you want to continue?  Please select yes or no.");                
        } while (Validate(Console.ReadLine().ToLower(), "yes"));
    }
    static void Write(string s) => Console.WriteLine(s);
    static bool Validate(string s, string Pattern) => Regex.Match(s, Pattern).Success; 
person David Cardinale    schedule 31.12.2016
comment
Создание нового объекта Random каждый раз, когда вам нужно случайное число, неверно. - person Jonathon Reinhart; 01.01.2017
comment
Надеюсь, вы проголосовали против всех остальных, поскольку я работаю только с кодом, который они предоставили. Я все равно исправлю это, даже если это не влияет на время обработки или память, поскольку GC должен собирать это, поскольку он выпадает из области видимости каждый вызов и система простаивает в ожидании ответа пользователя и по мере необходимости ... - person David Cardinale; 02.01.2017
comment
Я действительно считаю, что вы ошибаетесь, хотя я считаю, что выполнил вашу рекомендацию. Следуя правильному ООП, было бы лучше инкапсулировать рандомизацию в метод, как это сделал я. Цикл должен быть как можно более чистым, поскольку его цель - сбор пользовательского ввода, обработка ввода должна выполняться где-то еще. Совершенно нормально создавать новый Random для каждого вызова метода, но не внутри самого цикла, так как это помешает сборщику мусора, поскольку ссылки никогда не будут выпущены. Однако в своем собственном методе они будут выпускаться с каждым вызовом и возвращаемым значением. - person David Cardinale; 02.01.2017
comment
Я надеюсь, что вы намереваетесь ответить или отозвать свой голос против, поскольку этот код работает нормально, и я считаю, что его предыдущая форма была более правильной, чем та, которую вы рекомендовали. - person David Cardinale; 02.01.2017
comment
См. Этот комментарий выше: stackoverflow.com/questions/41410716/ - person Jonathon Reinhart; 02.01.2017
comment
Опять же, вы не совсем ошибаетесь, но это не замкнутый цикл. Это утверждение MSDN по этому поводу: инициализация двух генераторов случайных чисел в тесном цикле или в быстрой последовательности создает два генератора случайных чисел, которые могут создавать идентичные последовательности случайных чисел. В большинстве случаев это не входит в намерения разработчика и может привести к проблемам с производительностью, поскольку создание экземпляра и инициализация генератора случайных чисел - относительно дорогостоящий процесс. msdn.microsoft.com/en -us / library / - person David Cardinale; 02.01.2017