2

I have an unsigned int variable x which value is comprised between from 0 and 0xFFFFF and I would like to print it in a way more readable for the user.
If x is greater than 0xF000, print it in hexadecimal, else print it in decimal. So something like this would do it

if (x > 0xF000) 
   printf("%#x", x);
else 
   printf("%u", x)

But I would like to know if there is an handier and smarter way to handle this, like conditional formatting for output depending of their value.

Mahouk
  • 902
  • 9
  • 28
  • 4
    What you have is probably the easiest to read. I'd stop here unless given a very good reason to complicate things. – user4581301 Nov 20 '19 at 16:19
  • 2
    If your program's output is ever read by a machine, or by an uninitiated human, the changing representation could be very confusing. If you really want to do this, I strongly recommend marking the output format somehow, perhaps by prefixing the hexadecimal numbers with `0x`, which you can do either with `"0x%x"` or `"%#x"`. – Steve Summit Nov 20 '19 at 16:27
  • Besides the other problems mentioned, calling `printf` with a format which is not a single, constant string is arguably poor style. It is disrecommended by some style guides. I believe it is diagnosed by some compilers. It means that the compiler can't, in general, do any checking for mismatches between the format string and the arguments. – Steve Summit Nov 20 '19 at 16:36
  • 1
    See also [Why is printf with a single argument (without conversion specifiers) deprecated?](https://stackoverflow.com/questions/31290850) (though it's a somewhat different question). – Steve Summit Nov 20 '19 at 17:08

1 Answers1

1

Your 'conditional format' could be specified using the ternary '?' operator, as suggested in the comments:

printf((x > 0xF000) ? "%#x" : "%u", x);

However, as also suggested in the comments, this doesn't really help in terms of readability.

You can also use a string variable as the format argument, for example (in this trivial case):

char fmt[4];
if (x > 0xF000) strcpy(fmt, "%x");
else            strcpy(fmt, "%u"); // You haven't specified what type "x" is, so let's assume "unsigned".
printf(fmt, x);
Mahouk
  • 902
  • 9
  • 28
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • The second approach is not good in case you wanted to add a new-line or something else. – machine_1 Nov 20 '19 at 16:31
  • @machine_1 - Well, assuming you make `fmt` a big enough buffer, you can put whatever you want (including newlines) into it. But I'm not saying it's the *best* way - just *one* way. – Adrian Mole Nov 20 '19 at 16:33
  • Wouldn't a buffer of size `3` be sufficient in the second example? – bool3max Nov 20 '19 at 16:34
  • @AnttiHaapala Of course, one could equally well use `char* fmt` and initialise to a string-literal. – Adrian Mole Nov 20 '19 at 16:35
  • Some compilers will issue a warning if the printf format string is not a string literal. – Ian Abbott Nov 20 '19 at 16:35
  • @bool - Just my habit - always prefer to allocate a 'bit too much' rather than 'not enough'. – Adrian Mole Nov 20 '19 at 16:35
  • @Ian Well they shouldn't! From [cppreference](http://www.cplusplus.com/reference/cstdio/printf/): `int printf ( const char * format, ... );` (implicit casting of non-const to const here is OK). – Adrian Mole Nov 20 '19 at 16:37
  • @Adrian See the comment I added in the question. It's a debatable warning, but not indefensible. – Steve Summit Nov 20 '19 at 16:45
  • @Steve I can understand (and even agree with) your comment/concern. However, it should be a warning from (maybe) a *code analyser* rather than a compiler. But, it depends also on whether one is using `C++` (IMHO, justified) or `C` (IMHO, unjustified) - question is tagged with both. – Adrian Mole Nov 20 '19 at 16:49
  • @Adrian Being pedantic, the variable `x` will have the wrong type for at least one of the format strings `%d` (expects an `int`) or `%x` (expects an `unsigned int`). – Ian Abbott Nov 20 '19 at 16:55
  • @Adrian Two points (though I'm not arguing with you; I like the freedom of using variable formats myself). (1) Mismatch of `printf` arguments is bad. Having the compiler check them is good. But if the format is variable the compiler can't check. Therefore variable formats are bad. (2) Some (including, I've heard, the maintainers of gcc) believe that having separate code analyzers is lame. They're too much extra work to maintain, they're too likely to diverge from the compiler(s) in terms of the language accepted, and people might not run them. Ergo, *all* the warnings go in the compiler. – Steve Summit Nov 20 '19 at 17:06
  • See also [Why is printf with a single argument (without conversion specifiers) deprecated?](https://stackoverflow.com/questions/31290850) (though it's a somewhat different question). – Steve Summit Nov 20 '19 at 17:07
  • Ok, I am sure now C does not provide native conditional formatting. – Mahouk Nov 20 '19 at 17:42
  • @SteveSummit Yeah! But my point about C++ vs C is that C is 'supposed to be' dangerous (it's human-readable assembler code - do what you want, *caveat emptor*, &c) whereas C++ is (or has become) strongly typed. But this is philosophy, and not relevant to the OP's question. – Adrian Mole Nov 20 '19 at 20:59
  • @Mahouk If you got something out of this, then we at SO have done our job! But maybe consider taking out the `C++` tag? (There are ways in *that* language to do conditional formatting, but not in C.) – Adrian Mole Nov 20 '19 at 21:02
  • @Adrian, Really? In this case, Can you tell more about it? it would be my pleasure to know it – Mahouk Nov 21 '19 at 12:19
  • 1
    @Mahouk You should post a separate question! And be **very specific** and **explicit** in your title. There are many folks here on SO far more 'clued-up' than I am on such methods. – Adrian Mole Nov 21 '19 at 12:22
  • @Adrian, Done! https://stackoverflow.com/questions/58975980/c-printing-with-conditional-format-depending-on-the-base-of-an-int-value – Mahouk Nov 21 '19 at 13:18