Scanf 'максимальная ширина поля' включает пробелы? - PullRequest
2 голосов
/ 09 апреля 2019

Предположим, у нас есть

int n;
sscanf(" 42", "%2d", &n);

Должно ли n быть 4 (пробел учитывается как "% 2d") или 42 (пробел игнорируется, заставляя scanf читать 3 символа)?

реализация ideone читает 3 символа

Ответы [ 3 ]

4 голосов
/ 09 апреля 2019

Спецификация POSIX для sscanf() довольно ясно об обработке:

Формат представляет собой строку символов, состоящую из нуля или более директив. Каждая директива состоит из одного из следующих: один или несколько символов пробела (<space>, <tab>, <newline>, <vertical-tab> или <form-feed>); обычный символ (ни '%', ни символ пробела); или спецификация преобразования. Каждая спецификация преобразования вводится символом '%' [CX] ⌦ или последовательностью символов "% n $", ⌫ после чего в последовательности появляется следующее:

...

Директива, которая является спецификацией преобразования, определяет набор соответствующих входных последовательностей, как описано ниже для каждого символа преобразования. Спецификация преобразования должна быть выполнена в следующих шагах.

Входные пробельные символы (как указано isspace) должны быть пропущены, если спецификация преобразования не включает спецификатор преобразования [, c, C или n.

Элемент должен быть прочитан из ввода, если спецификация преобразования не включает спецификатор преобразования n. Элемент ввода должен быть определен как самая длинная последовательность входных байтов (вплоть до любой заданной максимальной ширины поля, которая может измеряться в символах или байтах в зависимости от спецификатора преобразования), которая является начальной подпоследовательностью совпадающей последовательности. Первый байт, если он есть, после элемента ввода должен оставаться непрочитанным. Если длина элемента ввода равна 0, выполнение спецификации преобразования завершится сбоем; это условие является ошибкой сопоставления, если только конец файла, ошибка кодирования или ошибка чтения не предотвратили ввод из потока, и в этом случае это сбой ввода.

Если пробел пропущен согласно спецификации преобразования (%…), он не учитывается как часть ширины поля; пропуск происходит раньше, чем подсчитывает.

Эквивалентная спецификация в C11 §7.21.6.2 Функция fscanf очень похожа (но, конечно, не включает в себя разметку «расширение C»).

3 голосов
/ 09 апреля 2019

Scanf 'максимальная ширина поля' включает пробелы?

Да для [ и c.
Нет для других спецификаторов.
"%n" делаетне применяется.

fscanf() (C11dr §7.21.6.2 7-9)

7 ... Спецификация преобразования выполняется на следующих этапах :

8 Вводимые пробельные символы (как указано в функции isspace): пропуск , если в спецификации не указан спецификатор [, c или n.

9 Элемент ввода считывается из потока, ... Элемент ввода определяется как самая длинная последовательность символов ввода, которая не превышает ни одно из указанных полей ширина и ....

ширина применяется после лидирующего ввода символов пробела.


Далее, как я прочитал спецификацию, если преобразование завершится неудачно,введенные пробельные символы остаются занятыми.

1 голос
/ 09 апреля 2019

со страницы руководства BSD:

В дополнение к этим флагам может быть необязательная максимальная ширина поля, выражается в виде десятичного целого числа между% и конверсией. Если нет ширины учитывая, используется значение по умолчанию «бесконечность» (с одним исключением, ниже); иначе самое большее это число байтов сканируется при обработке преобразования. В случае преобразования lc, ls и l [ширина поля задает максимальное число многобайтовые символы, которые будут сканироваться. Перед началом конверсии большинство конверсий пропускают пробелы; этот пробел не засчитывается против поля ширина.

Справочная страница Linux имеет

Необязательное десятичное целое число, которое определяет максимальную ширину поля. чтение символов останавливается либо при достижении этого максимума, либо при несовпадении персонаж найден, в зависимости от того, что произойдет первым. Большинство конверсий отбрасывают начальные символы пробела (исключения отмечены ниже), и они отбрасываются символы не учитываются при максимальной ширине поля. Строковые входные преобразования хранят завершающий нулевой байт ('\ 0'), чтобы отметить конец ввода; максимальная ширина поля не включает этот терминатор.

оба указывают, что пробел не учитывается при ширине поля.

...