8

如果我想要一个程序有多种文本输出格式,我可以这样做:

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";

然后会发生未定义的行为(很可能是段错误),而不是我想要的。这是因为它将第一个参数视为指向字符串的指针,即使它实际上是一个无符号整数。这个 unsigned int 很可能指向有效字符串数据以外的其他内容,或者(更有可能,特别是如果您不购买数亿个相同项目)无效的内存位置,从而导致分段错误。

我想知道的是是否有一个代码可以放在某处(%Z在本例中)来告诉它跳过该参数,如下所示:

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

2 回答 2

7

对于%s值,有一个“null” printf() 代码:%.0s.

您可以通过以下方式达成一般解决方案:

如果可能,重新排列以使non-%s值在最后,然后在指定格式字符串下。

我最喜欢的是有 3 个单独的 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 与指针大小相同大小的其他值,您可以尝试也使用%.0sN 次的未定义行为。(在 gcc 4.5.3 中使用了一些示例,谁知道其他编译器或未来。)

于 2013-05-27T03:27:38.037 回答
1

我实际上是在为我的问题寻找一些东西时自己想出来的。您可以在 . 之后添加参数编号,后跟$格式代码%。所以它会是这样的:

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

也就是说,字符串将使用第二个参数,而浮点数将使用第三个参数。但是请注意,这是 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;
    }
}
于 2013-05-23T06:03:23.877 回答