skipping parameters with printf

J

John Devereux

Hi,

I would like to know if their is a conversion specifier, or other
method, that will allow me to not use particular arguments to printf.

Failing that, is it permissable to simply "not use" the parameter if
it is at the end of the parameter list?


For example,

printf("%02d:%02d:%02d", hours, minutes, seconds); /* 11:59:00 */
printf("%02d:%02d", hours, minutes, seconds); /* 11:59 */


Thanks,
 
W

Walter Roberson

I would like to know if their is a conversion specifier, or other
method, that will allow me to not use particular arguments to printf.
Failing that, is it permissable to simply "not use" the parameter if
it is at the end of the parameter list?
For example,
printf("%02d:%02d:%02d", hours, minutes, seconds); /* 11:59:00 */
printf("%02d:%02d", hours, minutes, seconds); /* 11:59 */

Answering your second question: when printf() and kin reach the
end of the conversion specification, they stop attempting to convert
values, so your second example will be fine.

Answering your first question: The C89 standard does not offer any
mechanism to "skip" values or convert them out of order.

There is a common extension to the printf family which offers a
prefix immediately after the %, consisting of an argument number
followed by a $ and when this appears, the specified value is the
next one converted. Note that $ is not a part of the standard C
character set, so this extension is doubly non-portable.
 
I

Irrwahn Grausewitz

John Devereux said:
I would like to know if their is a conversion specifier, or other
method, that will allow me to not use particular arguments to printf.

Failing that, is it permissable to simply "not use" the parameter if
it is at the end of the parameter list?

For example,

printf("%02d:%02d:%02d", hours, minutes, seconds); /* 11:59:00 */
printf("%02d:%02d", hours, minutes, seconds); /* 11:59 */

It's ok to pass more arguments to printf than are to be consumed by
the format specifiers (but, of course, not the other way round).

From ISO/IEC 9899:1999 (E) 7.19.6.1p2:
[...] If there are insufficient arguments for the format, the
behavior is undefined. If the format is exhausted while arguments
remain, the excess arguments are evaluated (as always) but are
otherwise ignored. [...]

Best regards
 
R

Robert Gamble

Answering your second question: when printf() and kin reach the
end of the conversion specification, they stop attempting to convert
values, so your second example will be fine.

Answering your first question: The C89 standard does not offer any
mechanism to "skip" values or convert them out of order.

There is no way to do this in C99 either. In fact, I don't even think
it would be possible to design a version that did do this with the current
stdarg facility since it would need to know the type of the value being
skipped to access arguments after it.
There is a common extension to the printf family which offers a
prefix immediately after the %, consisting of an argument number
followed by a $ and when this appears, the specified value is the
next one converted. Note that $ is not a part of the standard C
character set, so this extension is doubly non-portable.

I am pretty sure the $n feature is part of the Posix standard so it is
portable systems implementing Posix. When using this notation you have
to use it exclusively when accessing parameters used in the format
string. You can't use this feature to "skip" arguments either since there
can't be gaps in the indexes for the reason mentioned above.

Robert Gamble
 
A

Anonymous 7843

printf("%02d:%02d:%02d", hours, minutes, seconds); /* 11:59:00 */
printf("%02d:%02d", hours, minutes, seconds); /* 11:59 */

Have you considered strftime()?
 
W

Walter Roberson

I am pretty sure the $n feature is part of the Posix standard so it is
portable systems implementing Posix.


It is not part of POSIX.1-1990; possibly a different POSIX binding.

When using this notation you have
to use it exclusively when accessing parameters used in the format
string. You can't use this feature to "skip" arguments either since there
can't be gaps in the indexes for the reason mentioned above.

That sounds reasonable; I'd have to find the appropriate standard to
see. The man page I happen to be looking at (SGI IRIX) phrases it this way:

When numbered argument specifications are used, specifying the Nth
argument requires that all the leading arguments, from the first to the
(N-1)th, be specified at least once, in a consistent manner, in the
format string.

and there is no format specifier or modifier present on this system that
allows for the possibility of supressing output.
 
R

Robert Gamble

It is not part of POSIX.1-1990; possibly a different POSIX binding.

It's in the 2003 Edition but it is marked as an XSI entension, which I
didn't realize in my initial post as I hadn't checked, so it is possible
that some Posix conforming platforms won't support it.
That sounds reasonable; I'd have to find the appropriate standard to
see. The man page I happen to be looking at (SGI IRIX) phrases it this
way:

When numbered argument specifications are used, specifying the Nth
argument requires that all the leading arguments, from the first to
the (N-1)th, be specified at least once, in a consistent manner, in
the format string.

Here is how my man page puts it (glibc 2.3.4):

The C99 standard does not include the style using `$', which comes from
the Single Unix Specification. If the style using `$' is used, it must
be used throughout for all conversions taking an argument and all width
and precision arguments, but it may be mixed with `%%' formats which do
not consume an argument. There may be no gaps in the numbers of arguments
specified using `$'; for example, if arguments 1 and 3 are specified,
argument 2 must also be specified somewhere in the format string.

If you want to look it up in the standard its in the "System Interfaces"
volume of the IEEE Std 1003.1 specification (I was looking at the 2003
Edition).

Robert Gamble
 
L

Lawrence Kirby

.


There is no way to do this in C99 either. In fact, I don't even think
it would be possible to design a version that did do this with the current
stdarg facility since it would need to know the type of the value being
skipped to access arguments after it.

It would be easy enough to skip values using a mechanism similar to
scanf()'s * assignment suppression flag. The conversion specifier would
still determine the type of the corresponding argument.

Lawrence
 
R

Robert Gamble

Lawrence said:
It would be easy enough to skip values using a mechanism similar to
scanf()'s * assignment suppression flag. The conversion specifier would
still determine the type of the corresponding argument.

Right, the type would be required to do this, that was the whole point.
I was referring to a mechanism to "skip the next n aguments" without
providing any other information about them.

Robert Gamble
 
J

John Devereux

Robert Gamble said:
Right, the type would be required to do this, that was the whole
point. I was referring to a mechanism to "skip the next n aguments"
without providing any other information about them.

It was indeed the scanf suppression flag that made me think it might
be worth asking about a printf equivalent.
 
P

Peter Shaggy Haywood

Groovy hepcat Robert Gamble was jivin' on Thu, 08 Sep 2005 17:47:57
-0400 in comp.lang.c.
Re: skipping parameters with printf's a cool scene! Dig it!
There is no way to do this in C99 either. In fact, I don't even think
it would be possible to design a version that did do this with the current
stdarg facility since it would need to know the type of the value being
skipped to access arguments after it.

Sure, it could be easily done. You just have to allow a display
suppression flag in the conversion specifier; much like scanf()'s
assignment suppression flag. Then the format string would simply have
a conversion specifier with this flag coresponding to the argument to
be ignored. Simple!
Simple example:

#include <stdio.h>
#include <stdarg.h>

void prints(const char *fmt, ...)
{
va_list arg;
const char *p;
FILE *fp = stdout;

va_start(arg, fmt);

for(p = fmt; *p; p++)
{
if('%' == *p)
{
/* We have a conversion specifier. */
int ignore = 0;
const char *sarg;
int iarg;

p++;
if('!' == *p)
{
/* Flag to ignore coresponding argument. */
ignore = 1;
p++;
}

switch(*p)
{
case 's': /* string */
sarg = va_arg(arg, const char *);
if(!ignore)
{
ignore = 0;
fputs(sarg, fp);
}
break;

case 'd': /* int */
iarg = va_arg(arg, int);
if(!ignore)
{
ignore = 0;
fprintf(fp, "%d", iarg);
}
break;
}
}
else
{
fputc(*p, fp);
}
}

va_end(arg);
}

int main(void)
{
prints("%s %!s %s\n", "foo", "bar", "baz");
prints("%d %d %!d %d\n", 1, 2, 3, 4);
return 0;
}

Here the simplified printf-like function, prints(), understands two
different types of conversion specifiers; one for a string and one for
an int. If the ! flag is used, the coresponding argument will be
ignored.
This program prints the following output:

foo baz
1 2 4

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 
R

Robert Gamble

Groovy hepcat Robert Gamble was jivin' on Thu, 08 Sep 2005 17:47:57
-0400 in comp.lang.c.
Re: skipping parameters with printf's a cool scene! Dig it!


Sure, it could be easily done. You just have to allow a display
suppression flag in the conversion specifier; much like scanf()'s
assignment suppression flag. Then the format string would simply have
a conversion specifier with this flag coresponding to the argument to
be ignored. Simple!

I meant that this could not be done without providing the type of argument
being skipped. Apparently this was not well-articulated, sorry.

Robert Gamble
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top