как scanf () проверяет, является ли ввод целым числом или символом? - PullRequest
5 голосов
/ 12 апреля 2011

Мне интересно, как стандартная функция библиотеки C scanf () проверяет, является ли ввод целым числом или символом, когда мы вызываем scanf ("% d", & var), когда сам символ является просто числом?Я знаю, что когда он встречает нецелое число, он помещает его обратно во входной буфер и возвращает -1, но как он узнает, что входное значение не является целым числом?

Ответы [ 7 ]

3 голосов
/ 12 апреля 2011

Вы правы в том, что каждый символ действительно представлен как 8-битное целое число. Решение простое: посмотрите на это число и посмотрите, находится ли оно в диапазоне 48–57, что является диапазоном кодов SCII для символов «0» - «9».

Начиная со строки 1315 scanf() исходного кода , мы можем увидеть это в действии. scanf() на самом деле сложнее - он также смотрит на многобайтовые символы, чтобы определить числовое значение. В строке 1740 происходит волшебство, и этот персонаж фактически превращается в число. Наконец, и, возможно, это наиболее полезно, функция strtol() выполняет цикл для выполнения этого преобразования.

3 голосов
/ 12 апреля 2011

Ввод всегда является строкой. Если scanf ожидает целое число (потому что вы передали его "%d"), оно пытается преобразовать строку в целое число для вас.

2 голосов
/ 13 июня 2011

В выражении scanf вы упоминаете% d, в котором содержится только целое число, поэтому по умолчанию оно воспринимает переменную как целое число

1 голос
/ 12 апреля 2011

По сути, функция scanf сопоставляет регулярные выражения на основе переданного вами спецификатора преобразования.Если вы укажете %d, это скажет scanf сопоставить ввод с регулярным выражением, состоящим из одного или нескольких символов от '0' до '9' (необязательно с начальным символом + или -).Затем он преобразует эту последовательность символов в эквивалентное целочисленное значение.

A очень упрощенная версия может выглядеть примерно так:

while (isdigit(c = fgetc(stream))
  val = val * 10 + valueOf(c); 
ungetc(c, stream);

где isdigit - стандартная библиотечная функция, которая возвращает true (не ноль), еслисимвольное значение представляет десятичную цифру, а valueOf - это определяемая пользователем функция, которая отображает символ, представляющий целое число ('0' - '9'), в эквивалентное целочисленное значение (0 - 9) (I 'я не знаю стандартной библиотечной функции, которая делает это для отдельных значений символов).Почему бы просто не вычесть '0' из c, чтобы получить эквивалентное целочисленное значение?В зависимости от кодировки не гарантируется, что все десятичные целочисленные символы будут расположены по порядку («Весь мир не является ASCII»);лучше всего делегировать фактическое преобразование функции, которая знает о текущей кодировке.

0 голосов
/ 12 апреля 2011

Вы неправильно поняли спецификатор формата %d. не возвращает значение ASCII введенного символа (для этого можно использовать %c); возвращает целое число, которое представляют символы. Таким образом, при вводе символа '9', %d возвращает значение 9, а не значение ASCII '9'.

(Ну, на самом деле %d фактически просматривает последовательность символов, поэтому, если ввод '9', за которым следует '0' с последующим ' ', он будет интерпретироваться как 90).

0 голосов
/ 12 апреля 2011

В основном используется цикл вроде:

while (isdigit((ch=getchar()))
    // ...
0 голосов
/ 12 апреля 2011

Он пытается проанализировать действительное десятичное целое число от начала потока, на практике необязательный + или -, а затем последовательность из одной или нескольких цифр.

...