Ignore argument to 'printf'?

Discussion in 'C Programming' started by Arthur J. O'Dwyer, Apr 2, 2005.

  1. I have a situation where I want to use one of two different format
    strings in a 'printf' call, depending on a flag set by the user.
    One of the calls uses a field width modifier, and the other one doesn't.
    So what I have at the moment is

    if (UserFlag) {
    printf("%*d. ", clue_width, clue_number);
    }
    else {
    printf("%d.\t", clue_number);
    }

    What I'd like to have is

    const char *clue_format = (UserFlag? "%*d. ": [...something...]);
    printf(clue_format, clue_width, clue_number);

    Problem is, I don't see any way to tell 'printf' to simply discard
    its second argument. "%0.0d" doesn't work; according to the standard,
    'printf' will never truncate its output, even given a zero field width.
    So, can anyone think of what my [...something...] should be?
    Failing that, can anyone think of a method shorter and cleaner than
    the method outlined above?

    Thanks,
    -Arthur
     
    Arthur J. O'Dwyer, Apr 2, 2005
    #1
    1. Advertising

  2. In article <>,
    Arthur J. O'Dwyer <> wrote:
    > I have a situation where I want to use one of two different format
    >strings in a 'printf' call, depending on a flag set by the user.


    >Problem is, I don't see any way to tell 'printf' to simply discard
    >its second argument.


    printf() stops converting when it reaches the end of its format
    string, ignoring any argument that has not been converted.

    (It helps to remember printf()'s antecedants, in the days when
    there was no way to tell how many arguments had been given to
    a varadic call, so the only way that printf() had of knowing
    there -were- more arguments was to hit another format specifier.)
    --
    'ignorandus (Latin): "deserving not to be known"'
    -- Journal of Self-Referentialism
     
    Walter Roberson, Apr 2, 2005
    #2
    1. Advertising

  3. Arthur J. O'Dwyer

    Guest

    On Sat, 2 Apr 2005 14:09:00 -0500 (EST), "Arthur J. O'Dwyer"
    <> wrote:


    >Problem is, I don't see any way to tell 'printf' to simply discard
    >its second argument.


    printf("%d\n",1,2,3);

    prints 1 on my screen.

    The arguments that aren't matched in the formatting string, are simply
    ignored.
     
    , Apr 2, 2005
    #3
  4. On Sat, 2 Apr 2005, Arthur J. O'Dwyer wrote:
    >
    > I have a situation where I want to use one of two different format
    > strings in a 'printf' call, depending on a flag set by the user.
    > One of the calls uses a field width modifier, and the other one doesn't.
    > So what I have at the moment is
    >
    > if (UserFlag) {
    > printf("%*d. ", clue_width, clue_number);
    > }
    > else {
    > printf("%d.\t", clue_number);
    > }


    I see I've gotten two "non-answers" already. In case it wasn't
    clear, I'm looking for solutions to the setup above, not to

    if (UserFlag) {
    printf("%*d. ", a, b);
    }
    else {
    printf("%d.\t", a);
    }

    HTH,
    -Arthur
     
    Arthur J. O'Dwyer, Apr 2, 2005
    #4
  5. Arthur J. O'Dwyer

    Chris Torek Guest

    [edited slightly for vertical space]

    In articles <>
    and <>
    Arthur J. O'Dwyer <> wrote [both > and >>]:
    >>... what I have at the moment is
    >> if (UserFlag) printf("%*d. ", clue_width, clue_number);
    >> else printf("%d.\t", clue_number);


    > I see I've gotten two "non-answers" already. In case it wasn't
    >clear, I'm looking for solutions to the setup above, not to
    > if (UserFlag) printf("%*d. ", a, b);
    > else printf("%d.\t", a);


    Indeed, in this case the "ignores extra, unused arguments" feature
    of printf() is not helpful, because we need the "clue_width"
    argument to disappear.

    There are a couple of possible approaches. One, which I will
    mention just because it is horrendously ugly and nonportable but
    chances are it works on your ILP32 machine, is to misuse the "%n"
    conversion specifier and assume that sizeof(int) == sizeof(int *):

    if (UserFlag) {
    fmt = "%*d. ";
    arg1 = clue_width;
    } else {
    fmt = "%n%d.\t";
    arg1 = (int) &clue_width;
    }
    ...
    printf(fmt, arg1, clue_number);

    Of course, this potentially breaks as soon as you move to an I32LP64
    machine (where sizeof(int) is 4 but sizeof(int *) is 8). There
    are even worse hacks to work around that, in various even-more-
    machine-dependent ways, but this whole thing is a bad idea.

    So what else can we do? Well, observe that printf's output for
    "%d" and "%1d" is always 100% identical:

    printf("(plain) d: [%d] [%d] [%d]\n", 0, 1, 99);
    printf("width 1d: [%1d] [%1d] [%1d]\n", 0, 1, 99);

    The output here is always "[0] [1] [99]": specifying a minimum
    field width of 1 has no effect because %d always produces at least
    one output character. So now the answer is obvious:

    if (UserFlag) {
    fmt = "%*d. ";
    /* and use specified clue_width */
    } else {
    fmt = "%*d.\t";
    clue_width = 1;
    }
    ...
    printf(fmt, arg1, clue_number);

    (In fact, %*d with an integer value of -1 also works. Using 0
    works in my printf, but I think the Standard does not say just
    what happens in this case.)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Apr 2, 2005
    #5
  6. In article <>,
    Arthur J. O'Dwyer <> wrote:

    >On Sat, 2 Apr 2005, Arthur J. O'Dwyer wrote:
    >> if (UserFlag) {
    >> printf("%*d. ", clue_width, clue_number);
    >> }
    >> else {
    >> printf("%d.\t", clue_number);
    >> }


    > I see I've gotten two "non-answers" already.


    Sorry, I misread the "second argument" as "last argument".

    I do not have my copy of the standard here to check the
    portability of the below... I -remember- this as being part
    of the standard (not just as a local extension on the system I'm
    checking), but YMMV.

    printf( UserFlag? "%*d. " : "%2$d.\t", clue_width, clue_number );

    posp$ An optional entry, consisting of one or more decimal digits
    followed by a $ character, specifying the number of the next arg to
    access. The first arg (just after format) is numbered 1. If this
    field is not specified, the arg following the most recently used
    arg will be used.

    --
    Oh, to be a Blobel!
     
    Walter Roberson, Apr 2, 2005
    #6
  7. Walter Roberson wrote:
    >
    > I do not have my copy of the standard here to check the
    > portability of the below... I -remember- this as being part
    > of the standard (not just as a local extension on the system I'm
    > checking), but YMMV.
    >
    > printf( UserFlag? "%*d. " : "%2$d.\t", clue_width, clue_number );
    >
    > posp$ An optional entry, consisting of one or more decimal
    > digits followed by a $ character,...


    The $ character is not a member of the basic character set in C.
    [Aside: neither is @ unfortunately.]

    It may well be standardised usage, but it is not C standard usage.

    --
    Peter
     
    Peter Nilsson, Apr 3, 2005
    #7
  8. On Sat, 2 Apr 2005, Chris Torek wrote:
    > Arthur J. O'Dwyer <> wrote [both > and >>]:
    >>> ... what I have at the moment is
    >>> if (UserFlag) printf("%*d. ", clue_width, clue_number);
    >>> else printf("%d.\t", clue_number);


    > if (UserFlag) {
    > fmt = "%*d. ";
    > /* and use specified clue_width */
    > } else {
    > fmt = "%*d.\t";
    > clue_width = 1;
    > }
    > ...
    > printf(fmt, arg1, clue_number);


    ...Of course! Argh! Thank you. I hadn't been thinking of modifying
    'clue_width', but actually there's no reason not to.

    -Arthur
     
    Arthur J. O'Dwyer, Apr 3, 2005
    #8
  9. Arthur J. O'Dwyer

    Eric Sosman Guest

    Arthur J. O'Dwyer wrote:

    >
    > On Sat, 2 Apr 2005, Arthur J. O'Dwyer wrote:
    >>
    >> I have a situation where I want to use one of two different format
    >> strings in a 'printf' call, depending on a flag set by the user.
    >> One of the calls uses a field width modifier, and the other one doesn't.
    >> So what I have at the moment is
    >>
    >> if (UserFlag) {
    >> printf("%*d. ", clue_width, clue_number);
    >> }
    >> else {
    >> printf("%d.\t", clue_number);
    >> }

    >
    > I see I've gotten two "non-answers" already. [...]


    What you're using seems perfectly reasonable and not
    worth changing (unless surrounding context provides reasons
    of its own). You could try

    printf(UserFlag ? "%*d. " : "%*d\t", /* note change */
    UserFlag ? clue_width : 0,
    clue_number);

    .... but to my eye this doesn't look like an improvement.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Apr 3, 2005
    #9
  10. Arthur J. O'Dwyer

    Joe Wright Guest

    Arthur J. O'Dwyer wrote:
    >
    > On Sat, 2 Apr 2005, Chris Torek wrote:
    >
    >> Arthur J. O'Dwyer <> wrote [both > and >>]:
    >>
    >>>> ... what I have at the moment is
    >>>> if (UserFlag) printf("%*d. ", clue_width, clue_number);
    >>>> else printf("%d.\t", clue_number);

    >
    >
    >> if (UserFlag) {
    >> fmt = "%*d. ";
    >> /* and use specified clue_width */
    >> } else {
    >> fmt = "%*d.\t";
    >> clue_width = 1;
    >> }
    >> ...
    >> printf(fmt, arg1, clue_number);

    >
    >
    > ...Of course! Argh! Thank you. I hadn't been thinking of modifying
    > 'clue_width', but actually there's no reason not to.
    >
    > -Arthur


    Try this..

    #include <stdio.h>

    int main(void) {
    char *format = "%*d.\n ";
    int width = 10;
    int number = 23;
    printf(format, width, number);
    width = 0;
    printf(format, width, number);
    return 0;
    }


    --
    Joe Wright mailto:
    "Everything should be made as simple as possible, but not simpler."
    --- Albert Einstein ---
     
    Joe Wright, Apr 3, 2005
    #10
  11. On 2 Apr 2005 20:54:34 GMT, -cnrc.gc.ca (Walter
    Roberson) wrote:
    <snip>
    > I do not have my copy of the standard here to check the
    > portability of the below... I -remember- this as being part
    > of the standard (not just as a local extension on the system I'm
    > checking), but YMMV. <snip printf %position$specifier>


    It's POSIX-standard (not just local) but not C-standard.

    - David.Thompson1 at worldnet.att.net
     
    Dave Thompson, Apr 11, 2005
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ben
    Replies:
    4
    Views:
    634
    Martin Ambuhl
    Jun 26, 2004
  2. whatluo

    (void) printf vs printf

    whatluo, May 26, 2005, in forum: C Programming
    Replies:
    29
    Views:
    1,288
  3. azza

    printf affects following printf/s

    azza, Oct 17, 2010, in forum: C Programming
    Replies:
    0
    Views:
    449
  4. iC and iC++

    ignore printf

    iC and iC++, Dec 17, 2010, in forum: C Programming
    Replies:
    14
    Views:
    978
    Rich Webb
    Dec 18, 2010
  5. Rob Meade
    Replies:
    6
    Views:
    282
    Rob Meade
    Mar 1, 2004
Loading...

Share This Page