Подтвердить что ты не робот

Является ли scanf "regex" поддержкой стандарта?

Поддерживает ли scanf "regex" стандарт? Я не могу найти ответ нигде.

Этот код работает в gcc, но не в Visual Studio:

scanf("%[^\n]",a);

Это ошибка Visual Studio или расширение gcc?

EDIT: похоже, что VS работает, но нужно учитывать разницу в контурах строк между Linux и Windows. (\ r\n)

4b9b3361

Ответ 1

Эта конкретная строка формата должна отлично работать в соответствующей реализации. Символ [ вводит сканирование для сопоставления непустого набора символов (с ^, означающим, что сканирование является инверсией символов). Другими словами, спецификатор формата %[^\n] должен соответствовать любому символу, который не является символом новой строки.

Из C99 7.19.6.2, слегка перефразируемый:

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

Если присутствует модификатор длины l, вход должен представлять собой последовательность многобайтовых символов, которая начинается в начальном состоянии сдвига. Каждый многобайтовый символ преобразуется в широкий символ, как если бы вызов функции mbrtowc, с состоянием преобразования, описанным объектом mbstate_t, инициализированным нулем перед преобразованием первого многобайтового символа. Соответствующим аргументом должен быть указатель на исходный элемент массива wchar_t, достаточно большой, чтобы принять последовательность и завершающий нуль-широкий символ, который будет добавлен автоматически.

Спецификатор преобразования включает в себя все последующие символы в строке формата, вплоть до подходящего правого скобки ]. Символы между скобками (список сканирования) составляют сканирование, если только символ после левой скобки не является обводным ^, и в этом случае сканирование содержит все символы, которые не отображаются в списке сканирования между округлой и правой скобками. Если спецификатор преобразования начинается с [] или [^], символ правой скобки находится в списке сканирования, а следующий следующий символ правой скобки - подходящая правая скобка, которая заканчивает спецификацию; в противном случае первый следующий символ правой скобки - это тот, который заканчивает спецификацию. Если символ - находится в списке сканирования и не является первым, а второй, где первый символ является ^, а не последним символом, поведение определяется реализацией.

Возможно, если MSVC работает некорректно, это просто один из многих примеров, когда Microsoft либо не соответствует последнему стандарту, либо думает, что они знают лучше: -)

Ответ 2

Спецификация формата "%[" для scanf() является стандартной и была с C90.

MSVC действительно поддерживает его.

Вы также можете указать ширину поля в спецификации формата, чтобы обеспечить защиту от переполнения буфера:

int main()
{
    char buf[9];

    scanf("%8[^\n]",buf);

    printf("%s\n", buf);
    printf("strlen(buf) == %u\n", strlen(buf));

    return 0;
}

Также обратите внимание, что спецификация формата "%[" не означает, что scanf() поддерживает регулярные выражения. Эта спецификация формата аналогична возможности регулярных выражений (и, без сомнения, была подвержена влиянию регулярного выражения), но она гораздо более ограничена, чем регулярные выражения.