1

I am currently wondering if there is a way to replace the format specifier %u by nothing using sprintf

My question is about the use of a ternary operator in sprintf which gonna replace %u by a value or by nothing.

Here is an example of what I am trying to do :

int main (void)
{
   char mytab[10]={'\0'};
   uint_32 i=0;

   scanf("%u",&i);

   sprintf(mytab, "\"%u"\",i>0?i:/*Here is the syntax I want to find if it exists*/);
   printf("%s\r\n",mytab);

   return 0;
}

The result of the code I am trying to get is for example "1" if the input is 1 (or "2" if the input is 2...) and "" if the input is 0.

Do you have any ideas or explantion about it ? Thanks by advance.

Joze
  • 1,285
  • 4
  • 19
  • 33
  • 4
    What's wrong with an if-statement? – Sneftel Oct 23 '13 at 12:30
  • I would say nothing but the use of ternary operator will avoid multiple sprintf line (for example if have multiple variable to test...). – Joze Oct 23 '13 at 12:32
  • 1
    No, you can't, and also your `scanf` format is wrong for that type. – interjay Oct 23 '13 at 12:34
  • It's what I thought... – Joze Oct 23 '13 at 12:36
  • @Joze - the answer you accepted doesn't deal well with multiple variables to test in one statement. Since the accepted answer only works for a single conditional format you might as well go with using a straightforward `if` statement. – Michael Burr Oct 24 '13 at 08:48

4 Answers4

3

I think you should put the ternary operator on the format-string, choosing to use either "%u", or "", depending on the value of i.

sprintf(mytab, i? "\"%u\"" : "\"\"", i);
abelenky
  • 63,815
  • 23
  • 109
  • 159
  • 1
    Nice, because "clean". However if this is about tightness: `sprintf(mytab, i ?"%"PRIu32 :"", i); printf("\"%s\"", mytab);` – alk Oct 23 '13 at 17:00
  • 1
    @abelenky: True in general, but the OP specified `i` to be unsigned. – alk Oct 23 '13 at 17:18
  • Ah... so he did. So his comparison `>0` doesn't make much sense. Good point. – abelenky Oct 23 '13 at 17:19
  • Why doesn't `>0` make sense? – Michael Burr Oct 23 '13 at 18:52
  • Another thing to keep in mind is that this will only work if the conditional format-spec is the last one. That problem can be handled if you're willing to rely on the POSIX extension of numbered argument conversion specifications (`"i? "\"%1$u\"" : "\"\""`). – Michael Burr Oct 23 '13 at 19:20
  • Comparing an UNSIGNED int > zero doesn't make sense since the value cannot be less than zero. You might as well just write `i?`. (`i>0` is legal... and it works. But to me, it implies that the other possibility is that i could be less than zero) – abelenky Oct 23 '13 at 19:20
2

Modify this statement

sprintf(mytab, "\"%u"\",i>0?i:/*Here is the syntax I want to find if it exists*/);  

This is what you need.

 (i>0)? sprintf(mytab, "%u",i) : sprintf(mytab,"%s","") ;

EDIT

AS H2CO3 suggested

You can also Use in this way.

if (i > 0)  
sprintf(mytab, "%"PRIu32, i); 
else
sprintf(mytab,"%s","");   

Also note that %u is not the appropriate format specifier for uint32_t, use "%"PRIu32

(i>0)? sprintf(mytab, "%"PRIu32,i) : sprintf(mytab,"%s","") ;  
Gangadhar
  • 10,248
  • 3
  • 31
  • 50
2

I think a simple if statement is still the cleanest option:

char mytab[10] = "\"\"";

if (n > 0) {
    snprintf(mytab, sizeof mytab, "\"%" PRIu32 "\"", n);
}
1

You might (not?) like to use this dirty trick*1 (which makes gcc yell out warnings):

char mytab[11] = ""; 
uint32_t i = 0;
int result = scanf("%"SCNu32, &i);

if (1 != result)
{
  if (-1 == result)
  {
    if (errno)
    {
      perror("scanf() failed");
    }
    else
    {
      fprintf(stderr, "EOF reached\n");
    }
  }
  else
  {
    fprintf(stderr, "invalid input\n");
  }
}

sprintf(mytab, i>0 ?"%"PRIu32 :"%s", i>0 ?i :"");
printf("%s", mytab);

*1 To mention this explicitly: "dirty" in this context is a hint that this might invoke the fabulous Undefined Behaviour. So don't do this in prodcution!


The sane apporach would be to do:

...

if (i)
{
  sprintf(mytab, "%"PRIu32, i);
}
printf("%s", mytab);

Please note that although the maximum number of digits for an unsigned 32bit number in decimal format is 10, you still need to reserve one character for the 0-terminator.

alk
  • 69,737
  • 10
  • 105
  • 255
  • Also note that `%u` is not the appropriate format specifier for `uint32_t` (I think that's what OP meant). –  Oct 23 '13 at 14:47
  • 1
    If you're going to use the `inttypes.h` format specifier macros, the one in the `scanf()` call should be `SCNu32`. – Michael Burr Oct 23 '13 at 15:15
  • 1
    `i>0 ?i :""` is invalid according to the standard because arguments 2 and 3 are `uint32_t` and `char*`. I'm not sure why both gcc and MSVC only generate a warning. Both compilers treat the type of the expression as `char*` so if you're building for a 64-bit target with 32-bit ints you'll get undefined behavior when `sprintf()` tries to format a 32-bit unsigned int value from a 64-bit pointer when `i>0`. This problem might not show up in the example, but will almost certainly show up when a more complex format is used with more arguments. It's pretty difficult to read as well. – Michael Burr Oct 23 '13 at 15:34