Як уникнути знака% (відсотків) у printf C?


274

Як уникнути знака% при використанні printfв C?

printf("hello\%"); /* not like this */

Відповіді:


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 (" привіт %% ");" правильно. Але я не думаю, що це втеча. використовувати printf ("привіт \ 045");
Лай Цзяншань

1
@Pablo Santa Cruz: цей спосіб "втечі" %специфічний для printf, правда?
Лазер

10
Це особливий випадок дуже поширеного правила в рятувальних системах, щоб отримати буквальний символ втечі, ви використовуєте <escape символ> <символ втечі>.
dmckee --- кошеня колишнього модератора

12
Лай Цзяншань, це не вийде. \045- це втеча з часу компіляції, що є частиною мови, і перетвориться %при компіляції. printf- це функція часу виконання, тому вона має справу з байтами рядка, а не з вихідним кодом C, і у нього є власні послідовності евакуації, які є частинами функції . Коротше кажучи, 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 лінійну функцію однією. Не хвилюйтеся, я сильно бив себе по голові, як заслужив.
Graeme Perrow

Щоправда, але не забувайте, що 99% часу, коли ви отримуєте рядок формату, ви отримуєте аргументи у вигляді va_list, тому вам потрібно використовувати vprintf. Таким чином, я технічно правильний;)
Пробіг

2
Так набагато простіше робити ставки (с). Якщо
Вільям Перселл

1
ставить додає новий рядок. Це часто небажана поведінка.
Пробіг

33

Якщо в рядку немає форматів, ви можете використовувати puts(або fputs):

puts("hello%");

якщо в рядку є формат:

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

Як зазначається в коментарях, putsдодає a \nдо результату і fputsне робить.


4
Варто згадати також fputs (), оскільки воно прямо відповідає взагалі fprintf ().
Тім Пост

1
put також додає новий рядок [навіть якщо у вас вже є]. Якщо ви цього хочете, чудово. Інакше ...
Пробіг

@Sinan Ünür: дякую, що нагадали про мене puts. Я ніколи не думав putsнадрукувати струни і стрибав прямо на printf. Більше не.
Лазер


7

Nitpick:
Ви дійсно не уникаєте %рядка, що визначає формат для printf()(та scanf()) сімейства функцій.

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

У рядку дійсно є два '%'символи (на відміну від бігових символів: "a\bc"це рядок з 3 ненульовими символами; "a%%b"це рядок з 4 ненульовими символами)


2
технічно вона все ще "рятується"; персонажам, які потребують особливих
знань,



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.