2012-02-06 2 views
2

Я получаю 48, когда ввод 0 в ReadLine().Console.ReadLine add 48 to int

Это ошибка?

class Program 
{ 
    static void Main(string[] args) 
    { 
     string name; 
     int age; 

     readPerson(out name, out age); 
    } 
    static void readPerson(out string name, out int age) 
    { 
     Console.Write("Enter name: "); 
     name = Console.ReadLine(); 
     Console.Write("Enter age: "); 
     age = Console.Read(); 
     Console.WriteLine("Name: {0}; Age: {1}", name, age.ToString()); 
    } 
} 

ответ

6

Согласно документации MSDN, в Console.Read метод возвращает:

Следующий персонаж входной поток или отрицательный (-1), если в настоящее время больше нет символов для чтения.

Таким образом, на самом деле то, что вы видите, это только первый символ в настоящее время на потоке (т.е. полученных символов между двумя последними Enter толчков).

Во время тестирования устройства казалось, что значения были сдвинуты на 48, потому что так получилось, что значения ASCII для символов от «0» до «9», как вы уже догадались, 48 для «0», , 49 для «1», и т.д.:

ASCII Table

поскольку вы не указали преобразование, содержание потока было «автомагический» читаются как char значений, и ваш вызов Read() отображается их ASCII десятичных эквивалентов.

Вы можете проверить это с помощью этого простого теста:

static void TestRead() 
{ 
    int current = 0; 

    Console.Write("Enter 1: "); 
    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 

    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 

    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 

    Console.Write("Enter 22: "); 
    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 

    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 

    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 

    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 
} 

Который приведет:

Output

Вы заметите, что спина к спине вызовы на Read() захватить одного символа из потока и дать вам его ASCII десятичный эквивалент. Также обратите внимание на то, как Windows добавляет последовательность возврата каретки (ASCII 13) и строки (ASCII 10) для каждого такта . Введите ключ, который ваша программа добросовестно повторяет вам.

Незначительная модификация данного метода позволило бы вести точку, что при отсутствии конкретных направлений, среда выполнения будет интерпретировать содержимое входного потока в виде символов:

static void TestReadModified() 
{ 
    int current = 0; 

    Console.Write("Enter a: "); 
    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 

    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 

    current = Console.Read(); 
    Console.WriteLine("Next char: {0}", current); 
} 

Как и ожидалось, метод выше будет возвращать значение ASCII для символа 'A':

Output for a letter

Как уже уже упоминалось, это легко исправить. Просто сообщите во время выполнения, что вы хотите, чтобы значение было интерпретировано как int. Вероятно, это также хорошая идея, по крайней мере, проверить, что введенный вход - это номер:

static void readPerson(out string name, out int age) 
{ 
    Console.Write("Enter name: "); 
    name = Console.ReadLine(); 

    Console.Write("Enter age: "); 

    // in this case, we could simply use tempAge (defaults to 0) 
    // but it's just practice to check TryParse's success flag 
    int tempAge; 
    var success = Int32.TryParse(Console.ReadLine(), out tempAge); 

    age = success ? tempAge : 0; 

    Console.WriteLine("Name: {0}; Age: {1}", name, age); 
    Console.ReadLine(); 
} 
+1

отличный ответ - я не могу представить, чтобы это было понятно. Интересно, как Read() «хранит» и выбрасывает отдельный символ в последовательности. Он также может быть перезаписан, если есть новый вход. Есть какой-то буферный механизм? Можете ли вы направить меня куда-нибудь для дальнейшего чтения? Я знаю, что это бесполезно, но мне любопытно. – KMC

+0

Существует много информации вокруг. Вот несколько быстро схваченных статей: http://stackoverflow.com/questions/1216380/what-is-a-stream и http://msdn.microsoft.com/en-us/library/system.io.stream .aspx –

9

Нет, это не ошибка.

Console.Read() возвращает код символа ASCII для любого символа. Код ASCII для цифры 0 равен 48, а для цифры 1 - 49 и т. Д. Он не добавляет число 48 произвольно, и не имеет ничего общего с параметрами out.

Вы должны прочитать в строке и брось вход в целое число соответственно:

Console.Write("Enter age: "); 
age = Convert.ToInt32(Console.ReadLine()); 

Если вам нужно использовать Read() по какой-либо причине, то, как я уже сказал в своем комментарии вы должны привести результат до char. Вам также необходимо изменить переменную из int age в char age:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string name; 
     char age; 

     readPerson(out name, out age); 
    } 
    static void readPerson(out string name, out char age) 
    { 
     Console.Write("Enter name: "); 
     name = Console.ReadLine(); 
     Console.Write("Enter age: "); 
     age = (char) Console.Read(); 
     Console.WriteLine("Name: {0}; Age: {1}", name, age.ToString()); 
    } 
} 

Имейте в виду, что Read() может читать только один символ за один раз, так что если вам нужно проанализировать возраст с более чем одной цифрой, это не будет работать, и вам намного лучше, если вместо этого использовать ReadLine().

+0

спасибо. Это сработало. Любопытно: если я использую Read вместо ReadLine, оператор снова возвращает символ ASCII. Зачем? – KMC

+0

Он всегда возвращает код символа ASCII для следующего символа во входном потоке. Нет «почему». – BoltClock

+0

Это было не «почему», я спрашивал. 'Convert.ToInt32 (Console.ReadLine())' работает, но 'Convert.ToInt32 (Console.Read())' все еще возвращает ASCII. – KMC

1

Печатаются коды ASCII для номеров. Обратите внимание, что Console.Read() считывает следующий символ из стандартного ввода и возвращает int. Итак, когда вы вводите символ 0 (не целое число 0), он возвращает код ASCII 48 и так далее. Кроме того, этот код ASCII является целым кодом для символа (скажем 0), поэтому преобразование в int этого кода является избыточным. Читаешь в возрасте как строку и преобразовать его в целое число, которое может быть сделано с Console.ReadLine, а затем с помощью int.TryParse и т.д.

+0

спасибо. См. Отредактированный ответ. – KMC

+0

@KMC - Ваше редактирование, кажется, предполагает, что вы не прочитали мой ответ. Чтение получает символ 0, а не целое число 0 при вводе. Таким образом, он возвращает 48, который является кодом ascii для него. Обратите внимание, что этот 48 сам по себе является целым числом и, следовательно, преобразование того, что 48 в int вернет только 48. Вы не конвертируете символ 0 в int, вы преобразовываете 48 в int. – manojlds

+0

Я думал, что ASCII имеет тип Char в Utf16? Не следует ли использовать char для int, чтобы неявно преобразовать код char в соответствующий int? – KMC