Как избежать знака% (процентов) в printf C?


Ответы:


421

Вы можете избежать этого, отправив двойной символ '%', например так: %%

Используя ваш пример:

printf("hello%%");

Экранирующий знак «%» предназначен только для printf. Если вы делаете:

char a[5];
strcpy(a, "%%");
printf("This is a's value: %s\n", a);

Он напечатает: This is a's value: %%


8
"Е (" привет %% ");" верно. Но это не бегство, я думаю. используйте printf ("привет \ 045");
Лай Цзяншань

1
@Pablo Santa Cruz: этот метод «побега» %специфичен printf, правильно?
Lazer

10
Это особый случай очень распространенного правила в экранирующих системах, что для получения буквального escape-символа вы используете <escape-символ> <escape-символ>.
dmckee --- котенок экс-модератора

12
Лай Цзяншань, это не сработает. \045это escape-время компиляции, которое является частью языка и превратится в %при компиляции. printfэто функция времени выполнения, поэтому она имеет дело с байтами вашей строки, а не с исходным кодом на языке Си, и имеет свои собственные escape-последовательности, которые являются частью функции . Короче говоря, printfэто «язык внутри языка» и printf("This is a's value: %s\n", a);дает тот же результат, что и printf("This is a's value: \045\0163\012", a);.
Triang3l

5
Кроме того , вы можете сделать это: printf("hello%c", '%');. Однако %%лучше, потому что он не использует другой аргумент.
Triang3l

36

Как уже говорили другие, %% избежит%.

Обратите внимание, однако, что вы никогда не должны делать это:

char c[100];
char *c2;
...
printf(c); /* OR */
printf(c2);

Всякий раз, когда вам нужно напечатать строку, всегда, всегда, всегда печатайте ее, используя

printf("%s", c)

чтобы предотвратить встраивание%% в проблемы [нарушения памяти, segfault и т. д.]


Предупреждение обычно уместно, однако могут быть ситуации, в которых вы хотите сделать «это» - если вы знаете, что предоставленная вами строка будет интерпретироваться как строка формата.
пп.

2
Однажды я придумал альтернативное решение - скопировать буфер в другой буфер, а затем пройти через него, удваивая знаки%. В конце концов я натолкнулся на эту идею и заменил функцию из 20-30 строк одной строкой. Не волнуйтесь, я сильно ударил себя по голове, как я и заслуживал.
Грэм Перроу

Да, но не забывайте, что в 99% случаев, когда вы получаете строку формата, вы получаете аргументы в виде va_list, поэтому вам нужно использовать vprintf. Таким образом, я технически прав;)
Mikeage

2
Гораздо проще делать путы (с). Если
Уильям Перселл

1
ставит, добавляет новую строку. Это часто нежелательное поведение.
Mikeage

33

Если в строке нет форматов, вы можете использовать puts(или fputs):

puts("hello%");

если в строке есть формат:

printf("%.2f%%", 53.2);

Как отмечено в комментариях, putsдобавляет \nк выводу и fputsне делает.


4
Стоит также упомянуть fputs (), так как он напрямую отвечает на fprintf ().
Тим Пост

1
Put также добавляет новую строку [даже если она у вас уже есть]. Если ты этого хочешь, отлично. В противном случае ...
Mikeage

@Sinan ünür: спасибо, что напомнили мне о puts. Я никогда не думал о putsпечати строк и прыгнул прямо к printf. Уже нет.
Lazer


7

Nitpick:
Вы на самом деле не экранируете %строку, которая определяет формат для семейства функций printf()scanf()).

%, В printf()scanf()) семейства функций, начинает спецификацию преобразования. Одно из правил для спецификации преобразования гласит, что %в качестве спецификатора преобразования (сразу после того, %который запустил спецификацию преобразования) вызывается запись '%'символа без преобразования аргумента.

Строка действительно имеет 2 '%'символа внутри (в отличие от экранирующих символов: "a\bc"строка с 3 ненулевыми символами; "a%%b"строка с 4 ненулевыми символами).


2
технически, это все еще "убегает"; персонажам, которые являются особенными, нужен способ «избежать» своего особого значения и вернуться к своей «природе характера»
ShinTakezou



3

Обратная косая черта в C используется для экранирования символов в строках. Строки не будут распознавать% как специальный символ, и, следовательно, нет необходимости в экранировании. Другое дело в printf: используйте %%, чтобы напечатать один%.






1

Двойной «%» работает также в «.Format (…). Пример (с iDrawApertureMask == 87, fCornerRadMask == 0,05): csCurrentLine.Format("\%ADD%2d%C,%6.4f*\%",iDrawApertureMask,fCornerRadMask) ; дает желаемое и ожидаемое значение (содержимое строки в) csCurrentLine;»% ADD87C, 0,0500 *% "

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.