Это на самом деле не имеет ничего общего с Objective-C или какао. Проблема заключается просто в использовании стандартной функции библиотеки C scanf
и обработке состояния ошибки. С справочной страницы scanf
, описывающей код возврата:
Ноль означает, что, хотя вход был доступен, преобразования не были назначены; обычно это происходит из-за недопустимого входного символа, такого как буквенный символ для преобразования `% d '.
Допустимый числовой ввод может быть проанализирован с помощью scanf
с помощью спецификатора %f
, так что он, очевидно, работает как ожидалось. Но если вы введете нечисловой символ, scanf
не сможет преобразовать его в число с плавающей точкой, а оставит текст в буфере stdin
. Поскольку код не проверяет код возврата из scanf
, а только проверяет, является ли userInput
ненулевым, цикл никогда не завершится, поскольку userInput
начинается с 0.0
и никогда не будет обновляться как scanf
не будет извлекать нечисловые символы из буфера stdin
. Вот почему ваш код работает в бесконечном цикле.
Если вы инициализировали userInput
ненулевым значением, это решит проблему одним способом, так как нецифровый ввод приведет к сбою scanf
и сработает условие while
. Но лучшим решением было бы проверить код возврата scanf
. Если оно равно нулю, напечатайте сообщение об ошибке и выполните fpurge(stdin)
, чтобы очистить недопустимый ввод перед повторным циклом, например:
int rc = scanf("%f", &userInput);
if (rc == 0)
{
NSLog(@"Invalid input, try again.");
fpurge(stdin);
}
Так что это простой C-подход к вводу и анализу. Суть в защитном кодировании заключается в том, что вы всегда должны проверять код возврата!
Как упоминает Крис, для реального приложения Cocoa вы бы хотели взглянуть на NSNumberFormatter
и тому подобное, но тогда вы бы, вероятно, брали входные данные из виджетов, а не из файловых потоков, так что код был бы совершенно другим выше.