Есть ли «нулевой» код printf, который ничего не печатает, используемый для пропуска параметра?

Если я хочу, чтобы программа имела несколько форматов вывода текста, я мог бы сделать что-то вроде этого:

const char *fmtDefault = "%u x %s ($%.2f each)\n";
const char *fmtMultiLine = "Qty: %3u\nItem: %s\nPrice per item: $%.2f\n\n";
const char *fmtCSV = "%u,%s,%.2f\n";

const char *fmt;
switch (which_format) {
    case 1: fmt = fmtMultiLine; break;
    case 2: fmt = fmtCSV; break;
    default: fmt = fmtDefault;
}

printf(fmt, quantity, item_description, price);

Поскольку цена указана последней, я также мог бы добавить цену, в которой цены не указаны:

const char *fmtNoPrices = "%u x %s\n";

Но что, если я хочу вместо этого опустить количество? Если бы я сделал это:

const char *fmtNoQuantity = "The price of %s is $%.2f each.\n";

тогда произойдет неопределенное поведение (скорее всего, segfault), а не то, что я хочу. Это потому, что он будет обрабатывать первый параметр как указатель на строку, даже если на самом деле это int без знака. Это беззнаковое целое, скорее всего, будет указывать на что-то иное, чем действительные строковые данные, или (гораздо более вероятно, особенно если вы не покупаете сотни миллионов одного и того же элемента) неверное расположение в памяти, что приведет к ошибке сегментации. >

Я хочу знать, есть ли код, который я могу где-то поместить (%Z в этом примере), чтобы он пропустил это параметр, как это:

const char *fmtNoQuantity = "%ZThe price of %s is $%.2f each.";
7 голосов | спросил flarn2006 23 Mayam13 2013, 10:03:23

2 ответа


0

Для значений %s существует «нулевой» код printf (): %.0s

Вы можете найти общее решение через:

Когда это возможно, переставьте так, чтобы значения non-%s были последними, а затем указывайте строку формата.

Мое любимое занятие - три отдельных вызова printf (), по одному для каждого значения в своем собственном формате. Если значение не требуется, просто укажите строку формата без спецификаторов.

const char * Format1q   = "";
const char * Format1id  = "The price of %s";
const char * Format1p   = " is $%.2f each.\n";
...
printf(Format1q,  quantity); 
printf(Format1id, item_description);
printf(Format1p,  price);

Странные решения:

Для других значений того же размера вы можете попробовать Неопределенное поведение, используя также %.0s. (работал с некоторыми образцами в gcc 4.5.3, кто знает в других компиляторах или в будущем.)

Для других значений, которые имеют размер N x того же размера, что и размер указателя, вы можете попытаться использовать неопределенное поведение, используя %.0s N раз. (работал с некоторыми образцами в gcc 4.5.3, кто знает в других компиляторах или в будущем.)

ответил chux 27 Mayam13 2013, 07:27:38
0

Я на самом деле понял это сам, когда искал что-то для своего вопроса. Можно добавить номер параметра, после которого $ к коду формата, после %. Так было бы так:

const char *fmtNoQuantity = "The price of %2$s is $%3$.2f each.";

То есть строка будет использовать 2-й параметр, а переменная будет использовать 3-й параметр. Однако обратите внимание, что это расширение POSIX, а не стандартная функция языка C.

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


typedef enum {fmtDefault, fmtMultiLine, fmtCSV, fmtNoPrices, fmtNoQuantity} fmt_id;

void print_record(fmt_id fmt, unsigned int qty, const char *item, float price)
{
    switch (fmt) {
    case fmtMultiLine:
        printf("Qty: %3u\n", qty);
        printf("Item: %s\n", item);
        printf("Price per item: $%.2f\n\n", price);
        break;
    case fmtCSV:
        printf("%u,%s,%.2f\n", qty, item, price);
        break;
    case fmtNoPrices:
        printf("%u x %s\n", qty, item);
        break;
    case fmtNoQuantity:
        printf("The price of %s is $%.2f each.\n", item, price);
        break;
    default:
        printf("%u x %s ($%.2f each)\n", qty, item, price);
        break;
    }
}
ответил chux 27 Mayam13 2013, 07:27:38

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132