модуль Scanf
scanf для Ruby
Описание
scanf — это реализация функции C scanf(3), изменённая по мере необходимости для совместимости с Ruby.
Предоставленные методы — String#scanf, IO#scanf и Kernel#scanf. Kernel#scanf — это оболочка вокруг STDIN.scanf. IO#scanf может использоваться с любым IO потоком, включая дескрипторы файлов и сокеты. scanf можно вызывать как с блоком, так и без него.
Scanf сканирует строку или поток ввода в соответствии с форматом, описанным ниже в Разделах преобразований, и возвращает массив соответствий между форматом и вводом. Формат определяется строкой и похож (но не идентичен) форматам, используемым в Kernel#printf и Kernel#sprintf.
Формат может содержать спецификаторы преобразования, которые сообщают scanf, в какой форме (тип) должно быть преобразовано каждое сопоставленное подстрока (например, десятичное целое число, число с плавающей точкой, строка-литераль и т. д.). Сопоставления и преобразования выполняются слева направо, а сами преобразования возвращаются как массив.
Строка формата также может содержать символы, отличные от указанных в спецификаторах преобразования. Пробелы (пробелы, табуляции или символы новой строки) в строке формата соответствуют любому количеству пробелов, включая отсутствие пробелов, во входных данных. Всё остальное соответствует только себе.
Сканирование прекращается, и scanf возвращает значение, когда любой символ ввода не соответствует спецификациям в строке формата, когда входные данные исчерпаны или когда все элементы в строке формата были сопоставлены. Все найденные соответствия до точки остановки возвращаются в массиве возврата (или передаются в блок, если был передан блок).
Базовое использование
require 'scanf'
# String#scanf and IO#scanf take a single argument, the format string
array = a_string.scanf("%d%s")
array = an_io.scanf("%d%s")
# Kernel#scanf reads from STDIN
array = scanf("%d%s")
Использование с блоком
При вызове с блоком scanf продолжает сканировать входные данные, циклически возвращаясь к началу строки формата, и передаёт новый массив преобразований в блок каждый раз, когда строка формата соответствует (включая частичные соответствия, но не включая полные неудачи). Фактическое возвращаемое значение scanf при вызове с блоком — это массив, содержащий результаты всех вызовов блока.
str = "123 abc 456 def 789 ghi"
str.scanf("%d%s") { |num,str| [ num * 2, str.upcase ] }
# => [[246, "ABC"], [912, "DEF"], [1578, "GHI"]]
Преобразования
Единственный аргумент scanf — строка формата, которая обычно включает один или несколько спецификаторов преобразования. Спецификаторы преобразования начинаются с символа процента ('%') и содержат информацию о том, что scanf должен сканировать дальше (строку, десятичное число, одиночный символ и т. д.).
Может быть указана необязательная максимальная ширина поля, выраженная как десятичное целое число, между символом '%' и преобразованием. Если ширина не задана, используется значение по умолчанию «бесконечность» (за исключением спецификатора %c; см. ниже). В противном случае, при заданной ширине поля n для данного преобразования, при обработке этого преобразования сканируется не более n символов. Перед началом преобразования большинство преобразований пропускают пробелы во входной строке; эти пробелы не учитываются при подсчёте ширины поля.
Доступны следующие преобразования.
- %
-
Сопоставляет литеральную `%'. То есть `%%' в строке формата сопоставляется с одним символом ввода `%'. Преобразование не выполняется, и полученный `%' не включается в возвращаемый массив.
- d
-
Сопоставляет необязательно знаковое целое десятичное число.
- u
-
То же, что и d.
- i
-
Сопоставляет необязательно знаковое целое число. Целое число считывается в 16-ричной системе счисления, если оно начинается с `0x' или `0X', в 8-ричной системе счисления, если оно начинается с `0', и в 10-ричной системе счисления в противном случае. Признаются только символы, соответствующие выбранной системе счисления.
- o
-
Сопоставляет необязательно знаковое целое число в 8-ричной системе.
- x, X
-
Сопоставляет необязательно знаковое целое число в 16-ричной системе счисления.
- a, e, f, g, A, E, F, G
-
Сопоставляет необязательно знаковое число с плавающей точкой.
- s
-
Сопоставляет последовательность символов без пробелов. Строка ввода завершается пробелом или максимальной шириной поля, в зависимости от того, что встречается раньше.
- c
-
Сопоставляет один символ или последовательность из n символов, если указана ширина поля n. Обычное пропускание начальных пробелов подавляется. Чтобы сначала пропустить пробелы, используйте явный пробел в формате.
- [
-
Сопоставляет непустую последовательность символов из заданного набора допустимых символов. Обычное пропускание начальных пробелов подавляется. Это вложенное выражение интерпретируется точно так же, как класс символов в регулярном выражении Ruby. (Фактически, оно помещается как есть в регулярное выражение.) Сопоставление со строкой ввода заканчивается появлением символа, отсутствующего в (или, с символом подчёркивания, присутствующего в) наборе, или когда заканчивается ширина поля — в зависимости от того, что произойдёт раньше.
Подавление присваивания
Для требования, чтобы определённое соответствие имело место, но не включало результат в возвращаемый массив, используйте флаг подавления присваивания, который является звездочкой ('*'), сразу после начального '%' спецификатора формата (непосредственно перед шириной поля, если она указана).
Сравнение scanf для Ruby и scanf в C
scanf для Ruby основан на функции C scanf(3), но с модификациями, в основном обусловленными различиями между языками.
Нереализованные флаги и спецификаторы
-
Единственный реализованный флаг в scanf для Ruby — '
*' (пропустить следующее преобразование). Многие флаги, доступные в C-версиях scanf(3), связаны с типом предстоящих аргументов указателей и бессмысленны в Ruby. -
Спецификатор
n(сохранение количества потреблённых символов до сих пор в следующем указателе) не реализован. -
Спецификатор
p(сопоставление значения указателя) не реализован.
Изменённые спецификаторы
- o, u, x, X
-
В scanf для Ruby все эти спецификаторы сканируют необязательно знаковое целое число, а не беззнаковое целое число, как их аналоги в C.
Возвращаемые значения
scanf для Ruby возвращает массив успешных преобразований, тогда как scanf(3) возвращает число успешно выполненных преобразований. (См. ниже подробности о возвращаемых значениях scanf для Ruby.)
Возвращаемые значения
Без блока scanf возвращает массив, содержащий все найденные преобразования. Если преобразования не найдены, scanf вернёт пустой массив. Неуспешное соответствие никогда не игнорируется, а, наоборот, всегда сигнализирует об окончании операции сканирования. Если первое неуспешное соответствие происходит после того, как уже имели место одно или несколько успешных соответствий, возвращаемый массив будет содержать результаты этих успешных соответствий.
При работе с блоком scanf возвращает массив-«отображение» преобразований из блока — то есть массив, отражающий, что сделал блок с каждым результатом, переданным из итеративной операции scanf. (См. «Использование с блоком» выше.)
Текущие ограничения и ошибки
При использовании IO#scanf в Windows, убедитесь, что вы открываете файлы в двоичном режиме:
File.open("filename", "rb")
чтобы scanf мог корректно отслеживать символы.
Поддержка классов символов достаточно полная (поскольку она в значительной степени опирается на обработку классов символов в регулярных выражениях Ruby), но пользователям рекомендуется проявлять осторожность при использовании более сложных и/или экзотических выражений классов символов, так как их тестирование не было исчерпывающим.
Лицензия и авторские права
- Авторские права
-
© 2002-2003 David Alan Black
- Лицензия
-
Распространяется на тех же лицензионных условиях, что и сам Ruby
Отказ от гарантий
Данное программное обеспечение предоставляется «как есть» и без каких-либо явных или подразумеваемых гарантий, включая, но не ограничиваясь, подразумеваемыми гарантиями товарной пригодности и пригодности для определённой цели.
Авторы и благодарности
scanf был разработан в качестве основной деятельности на Austin Ruby Codefest (Остин, Техас, август 2002).
- Главный автор
-
David Alan Black (dblack@superlink.net)
- Соавтор
-
Hal Fulton (hal9000@hypermetrics.com)
- Участники проекта
-
Nolan Darilek, Jason Johnston
Благодарим Хэла Фалтона за организацию Codefest.
Благодарим Matz за предложения по проектированию класса.
Благодарим Гавина Синклера за отзывы по документации.
Текст некоторых частей этого документа, особенно разделов «Описание» и «Преобразования» выше, был адаптирован из документации Linux Programmer's Manual manpage для scanf(3), от 01 ноября 1995 года.
Ошибки и сообщения об ошибках
scanf для Ruby основан на некотором альянсе реализаций C scanf и документации, а не на едином каноническом описании. Предложения по функциям и поведению, которые появляются в других реализациях scanf и были бы уместны в Ruby, приветствуются, как и сообщения о подозрительном поведении и/или ошибках. (Обратитесь к разделу «Авторы и благодарности» выше, для получения адресов электронной почты.)
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.