tags:

views:

640

answers:

8
int x;
printf("hello %n World\n", &x);
printf("%d\n", x);
+3  A: 

It's fairly esoteric. If you need to replace a placeholder in the generated string later you might want to remember an index into the middle of the string, so that you don't have to either save the original printf parameter or parse the string.

Darron
A: 

maybe a quick way to get the lengths of various substrings?

Nathan Fellman
+3  A: 

Depends what you mean by practical. There are always other ways to accomplish it (print into a string buffer with s[n]printf and calculate the length, for example).

However

int len;
char *thing = "label of unknown length";
char *value = "value value value"
char *value2="second line of value";
printf ("%s other stuff: %n", thing, &len);
printf ("%s\n%*s, value, len, value2);

should produce

label of unknown length other stuff: value value value
                                     second line of value

(although untested, I'm not near a C compiler)

Which is just about practical as a way of aligning things, but I wouldn't want to see it in code. There are better ways of doing it.

Paul
Apart from the missing semicolon and closing quote, this doesn't work as indicated because the total width of %*s (including value2) is set to len, not the number of initial spaces. So you'll either have to add strlen(value2) to len or use something like printf("%s\n%*s%s",value,len,"",value2).
mweerden
@mweerden, thanks, that will teach me to write things like this on the train (I should have used a right-aligned example, which would have worked :)) The idea is still clear, I hope. And it's still too "clever" for real code.
Paul
+9  A: 

It's not so useful for printf(), but it can be very useful for sscanf(), especially if you're parsing a string in multiple iterations. fscanf() and scanf() automatically advance their internal pointers by the amount of input read, but sscanf() does not. For example:

char stringToParse[256];
...
char *curPosInString = stringToParse;  // start parsing at the beginning
int bytesRead;
while(needsParsing())
{
    sscanf(curPosInString, "(format string)%n", ..., &bytesRead);  // check the return value here
    curPosInString += bytesRead;  // Advance read pointer
    ...
}
Adam Rosenfield
+2  A: 

It can be used to perform evil deeds.

e.James
A: 
shoosh
+1  A: 

#include int main(int argc, char* argv[]) { int col10 = (10 - 1); int col25 = (25 - 1);

    int pos1 = 0;
    int pos2 = 0;

    printf("    5    10   15   20   25   30\n");

    printf("%s%n%*s%n%*s\n",                     "fried", 
                            &pos1, col10 - pos1, "green",   
                            &pos2, col25 - pos2, "tomatos");


    printf("    ^    ^    ^    ^    ^    ^\n");

    printf("%d %d\n", pos1, pos2);
    printf("%d %d\n", col10 - pos1, col25 - pos2);

    return 0;
}

I am missing something here for sure. Tomatos is too far to the right.

EvilTeach
The problem is that you can't use the values that get assigned to pos1 and pos2 in the same call to printf. All arguments are evaluated before the call, meaning that col10-pos1==col10 and col25-pos2==col25. The correct positioning of "green" is accidental. You also made the same mistake as Paul.
mweerden
lol, yep I'm with it now
EvilTeach
A: 

you can call

int _get_printf_count_output();

to see if %n support is enable, or use

int _set_printf_count_output( int enable );

to Enable or disable support of the %n format.

from MSDN VS2008

yur