Jump to content

сканирование

scanf , сокращение от scan formatted, — это C стандартной библиотеки функция , которая считывает и анализирует текст со стандартного ввода .

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

Подобные функции с другими именами появились раньше C, например: readf в Алголе 68 .

Строки входного формата дополняют строки выходного формата (см. printf ), которые обеспечивают форматированный вывод ( шаблоны ).

Майка Леска , Портативная библиотека ввода/вывода включающая scanfофициально стал частью Unix в версии 7 . [1]

Использование

[ редактировать ]

The scanf Функция считывает ввод чисел и других типов данных со стандартного ввода .

Следующий код C считывает переменное количество неформатированных десятичных целых чисел из стандартного ввода и выводит каждое из них в отдельных строках:

#include <stdio.h>
int main(void)
{
    int n;
    while (scanf("%d", &n) == 1)
        printf("%d\n", n);
    return 0;
}

Для ввода:

456 123 789 456 12
456 1
      2378

Результат:

456
123
789
456
12
456
1
2378

Чтобы распечатать слово:

#include <stdio.h>
int main(void)
{
    char word[20];
    if (scanf("%19s", word) == 1)
        puts(word);
    return 0;
}

Независимо от того, какой тип данных программист хочет прочитать, аргументы (например, &n выше) должны быть указателями, указывающими на память. В противном случае функция не будет работать правильно, поскольку она будет пытаться перезаписать неправильные разделы памяти, вместо того, чтобы указывать на ячейку памяти переменной, для которой вы пытаетесь получить входные данные.

В последнем примере оператор адреса ( &) не используется в качестве аргумента: поскольку word имя массива это char, как таковой он (во всех контекстах, в которых его результатом является адрес) эквивалентен указателю на первый элемент массива. Хотя выражение &word будет иметь численное значение одного и того же значения, семантически оно имеет совершенно другое значение, поскольку обозначает адрес всего массива, а не его элемента. Этот факт необходимо иметь в виду при назначении scanf вывод в строки.

Как scanf предназначен только для чтения со стандартного ввода, многие языки программирования с интерфейсами , такие как PHP , имеют производные, такие как sscanf и fscanf но не scanf сам.

Спецификации строки формата

[ редактировать ]

форматирования Заполнители в scanf более или менее такие же, как и в printf, его обратная функция. Как и в printf, расширение POSIX n$ определяется. [2]

В строке формата редко встречаются константы (т. е. символы, не являющиеся заполнителями форматирования ), главным образом потому, что программа обычно не предназначена для чтения известных данных, хотя scanf принимает их, если это явно указано. Исключением является один или несколько символов пробелов , которые отбрасывают все символы пробелов во входных данных. [2]

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

  • %a : сканирование числа с плавающей запятой в шестнадцатеричном формате.
  • %d : Сканировать целое число как десятичное число со знаком.
  • %i : Сканировать целое число как число со знаком. Похоже на: %d, но интерпретирует число как шестнадцатеричное , если ему предшествует 0x и восьмеричный, если ему предшествует 0. Например, строка 031 будет читаться как 31, используя %dи 25 с использованием %i. Флаг h в %hi указывает на преобразование в short и hh преобразование в char.
  • %u : Сканировать десятичные числа unsigned int (Обратите внимание, что в стандарте C99 знак минус входного значения является необязательным, поэтому, если считывается знак минус, ошибок не возникает, и результатом будет дополнение до двух отрицательного числа, вероятно, очень большое значение. См. strtoul(). [ не удалось пройти проверку ] ) Соответственно, %hu сканирует в поисках unsigned short и %hhu для unsigned char.
  • %f : сканирование числа с плавающей запятой в обычном представлении ( с фиксированной запятой ).
  • %g, %G : сканирование числа с плавающей запятой в обычном или экспоненциальном представлении. %g использует строчные буквы и %G использует верхний регистр.
  • %x, %X : Сканировать целое число как беззнаковое шестнадцатеричное число.
  • %o : Сканировать целое число как восьмеричное .
  • %s : Сканировать строку символов . Сканирование завершается на пробеле . длины . В конце строки сохраняется нулевой символ. Это означает, что предоставленный буфер должен быть как минимум на один символ длиннее указанной входной
  • %c : Сканировать символ (char). не Нулевой символ добавляется.
  • пробел : любые пробельные символы запускают сканирование на наличие нуля или более пробельных символов. Количество и тип пробельных символов не обязательно должны совпадать в любом направлении.
  • %lf : Сканировать как двойное число с плавающей запятой. Формат «Float» со спецификатором «long».
  • %Lf : Сканировать как длинное двойное число с плавающей запятой. «Float» форматирует спецификатор «long long».
  • %n : Ничего не ожидается. Количество символов, использованных на данный момент от ввода, сохраняется через указатель next, который должен быть указателем на int. Это не преобразование и не увеличивает счетчик, возвращаемый функцией.


Вышеупомянутое можно использовать в сочетании с числовыми модификаторами и l, L модификаторы, обозначающие «long» и «long long» между символом процента и буквой. Между символом процента и буквами, предшествующими символу процента, также могут быть числовые значения. long модификаторы, если таковые имеются, которые определяют количество сканируемых символов. Необязательная звездочка ( *) сразу после символа процента означает, что данные, считанные этим спецификатором формата, не должны сохраняться в переменной. Для этой отброшенной переменной не следует включать аргументы в строке формата.

The ff Модификатор в printf отсутствует в scanf, что приводит к различиям между режимами ввода и вывода. ll и hh модификаторы отсутствуют в стандарте C90, но присутствуют в стандарте C99. [3]

Пример строки формата:

"%7d%s %c%lf"

Приведенная выше строка формата сканирует первые семь символов как десятичное целое число, затем читает оставшиеся как строку до тех пор, пока не будет найден пробел, новая строка или табуляция, затем потребляет пробелы до тех пор, пока не будет найден первый символ, не являющийся пробелом, затем потребляет этот символ. и, наконец, сканирует оставшиеся символы как двойные . Следовательно, надежная программа должна проверять, scanf вызов успешен и предпримите соответствующие действия. Если ввод был не в правильном формате, ошибочные данные все равно будут находиться во входном потоке и должны быть отброшены, прежде чем можно будет прочитать новый ввод. Альтернативный метод, позволяющий избежать этого, заключается в использовании fgets а затем проверьте прочитанную строку. Последний шаг можно выполнить с помощью sscanf, например.

В случае большого количества символов типа float a, e, f, g , многие реализации предпочитают сжимать большинство данных в один и тот же синтаксический анализатор. Microsoft MSVCRT делает это с помощью е, ж, ж , [4] в то время как glibc делает то же самое со всеми четырьмя. [2]

ISO C99 включает в себя inttypes.h заголовочный файл, который включает в себя ряд макросов для использования в независимых от платформы scanf кодирование. Они должны быть вне двойных кавычек, например scanf("%" SCNd64 "\n", &t);

Примеры макросов включают в себя:

Макрос Описание
СКНд32 Обычно эквивалентно I32d ( Win32/Win64 ) или д
СКНд64 Обычно эквивалентно I64d ( Win32/Win64 ), lld ( 32-битные платформы ) или ld ( 64-битные платформы )
СКНи32 Обычно эквивалентно I32i ( Win32/Win64 ) или я
SCNi64 Обычно эквивалентно I64i ( Win32/Win64 ), lli ( 32-битные платформы ) или li ( 64-битные платформы )
СКНу32 Обычно эквивалентно I32u ( Win32/Win64 ) или в
СКНу64 Обычно эквивалентно И64у ( Win32/Win64 ), llu ( 32-битные платформы ) или lu ( 64-битные платформы )
СКНx32 Обычно эквивалентно I32x ( Win32/Win64 ) или х
SCNx64 Обычно эквивалентно I64x ( Win32/Win64 ), llx ( 32-битные платформы ) или lx ( 64-битные платформы )

Уязвимости

[ редактировать ]

scanf уязвим для атак на строку формата . Следует уделить особое внимание тому, чтобы строка форматирования включала ограничения на размеры строк и массивов. В большинстве случаев размер входной строки от пользователя является произвольным и не может быть определен до scanf функция выполняется. Это означает, что %s заполнители без спецификаторов длины по своей сути небезопасны и могут быть использованы для переполнения буфера . Другая потенциальная проблема — разрешить строки динамического форматирования, например строки форматирования, хранящиеся в файлах конфигурации или других файлах, управляемых пользователем. В этом случае разрешенную входную длину размеров строк невозможно указать, если строка форматирования не проверена заранее и не применяются ограничения. С этим связаны дополнительные или несовпадающие заполнители форматирования, которые не соответствуют фактическому списку переменных аргументов . Эти заполнители могут быть частично извлечены из стека или содержать нежелательные или даже небезопасные указатели, в зависимости от конкретной реализации varargs .

См. также

[ редактировать ]
  1. ^ Макилрой, доктор медицины (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). CSTR. Лаборатории Белла. 139.
  2. ^ Jump up to: а б с scanf(3) Linux программиста Руководство – Библиотечные функции
  3. ^ Стандарт C99, §7.19.6.2 «Функция fscanf» alinea 11.
  4. ^ «Символы поля типа сканирования» . docs.microsoft.com . 26 октября 2022 г.
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 6c030a795dcadd546abef12ed19d4064__1716053940
URL1:https://arc.ask3.ru/arc/aa/6c/64/6c030a795dcadd546abef12ed19d4064.html
Заголовок, (Title) документа по адресу, URL1:
scanf - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)