Модуль Scanf
frozen_string_literal: false 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
-
Соответствует целому числу со знаком (опционально). Целое число считывается в шестнадцатеричной системе, если оно начинается с `0x' или `0X', в восьмеричной системе, если оно начинается с `0', и в десятичной системе в противном случае. Признаются только символы, соответствующие основанию.
- o
-
Соответствует целому числу в восьмеричной системе со знаком (опционально).
- x, X
-
Соответствует целому числу в шестнадцатеричной системе со знаком (опционально).
- 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.
Спасибо Мацу за предложения по проектированию класса.
Спасибо Гавину Синклеру за отзывы по документации.
Текст некоторых частей этого документа, особенно разделов «Описание» и «Преобразования», выше, был адаптирован из справки Linux Programmer's Manual для scanf(3), от 01.11.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.