Is there a "zero" printf code that doesn't print anything used to skip a parameter?

If I want the program to have several text output formats, I could do something like this:

const char *fmtDefault = "%ux %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); 

Since the price is listed last, I can also add one that does not list prices:

 const char *fmtNoPrices = "%ux %s\n"; 

But what if I want to give up quantity instead? If I did this:

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

then undefined behavior (most likely segfault) will happen, and not what I want. This is because it will treat the first parameter as a pointer to a string, even if it is actually an unsigned int. This unsigned int is likely to indicate something different from the actual string data or (which is much more likely, especially if you are not buying hundreds of millions of the same element), an invalid memory location, which will lead to a segmentation error.

I want to know if there is code that I can post somewhere ( %Z in this example) to let it skip this parameter, for example:

 const char *fmtNoQuantity = "%ZThe price of %s is $%.2f each."; 
+6
source share
2 answers

For values %s there is a โ€œnullโ€ code printf (): %.0s .

You can get a general solution through:

If possible, reinstall the non-%s values โ€‹โ€‹to be the last, and then specify the format string.

My favorite for you is the presence of 3 separate calls to printf (), one for each value, using its own format. When a value is not required, just put the format string without specifications.

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

Strange decisions:

For other values โ€‹โ€‹of the same size, you can try Undefined Behavior, using also %.0s . (worked with some samples in gcc 4.5.3, who knows in other compilers or in the future.)

For other values โ€‹โ€‹that are N x the same size as the size of the pointer, you can try Undefined Behavior, using also %.0s N times. (worked with some samples in gcc 4.5.3, who knows in other compilers or in the future.)

+4
source

I really thought about it on my own, looking at the question. You can add the parameter number, and then $ to the format, after % . So it would be like this:

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

That is, the string will use the second parameter, and the float will use the third parameter. Note, however, that this is a POSIX extension, not a standard C function.

The best way would probably be to define a custom print function. Something like that:

 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("%ux %s\n", qty, item); break; case fmtNoQuantity: printf("The price of %s is $%.2f each.\n", item, price); break; default: printf("%ux %s ($%.2f each)\n", qty, item, price); break; } } 
+1
source

Source: https://habr.com/ru/post/945655/


All Articles