Существуют ли практические приложения для формата% n в семействе printf / scanf? - PullRequest
17 голосов
/ 09 декабря 2008
int x;
printf("hello %n World\n", &x);
printf("%d\n", x);

Ответы [ 8 ]

15 голосов
/ 09 декабря 2008

Это не так полезно для printf(), но может быть очень полезно для sscanf(), особенно если вы анализируете строку в нескольких итерациях. fscanf() и scanf() автоматически увеличивают свои внутренние указатели на количество прочитанных входных данных, а sscanf() - нет. Например:

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
    ...
}
5 голосов
/ 09 декабря 2008

Может использоваться для совершения злодеяний .

4 голосов
/ 09 декабря 2008

Зависит от того, что вы подразумеваете под практическим. Для этого всегда есть другие способы (например, распечатать в строковом буфере с помощью s [n] printf и вычислить длину).

Тем не менее

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);

должен производить

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

(хотя и не проверял, я не рядом с компилятором C)

Это практически практический способ выравнивания вещей, но я не хотел бы видеть это в коде. Есть лучшие способы сделать это.

3 голосов
/ 09 декабря 2008

Это довольно эзотерично. Если вам потребуется заменить заполнитель в сгенерированной строке позже, возможно, вы захотите запомнить индекс в середине строки, чтобы вам не нужно было сохранять исходный параметр printf или анализировать строку.

1 голос
/ 09 декабря 2008
#include <stdio.h>
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;
}

Я что-то здесь упускаю наверняка. Помидоры слишком далеко направо.

1 голос
/ 09 декабря 2008

Возможно, это можно использовать как быстрый способ получить длины различных подстрок.

0 голосов
/ 27 апреля 2010

Вы можете позвонить

int _get_printf_count_output();

чтобы узнать, включена ли поддержка% n, или используйте

int _set_printf_count_output( int enable );

Включение или отключение поддержки формата% n.

от MSDN VS2008

0 голосов
/ 09 декабря 2008

Вот что-то из кода CRT VS2005:

/* if %n is disabled, we skip an arg and print 'n' */
if ( !_get_printf_count_output() )
{
   _VALIDATE_RETURN(("'n' format specifier disabled", 0), EINVAL, -1);
   break;
}

, который вызывает это:

альтернативный текст http://www.shiny.co.il/shooshx/printfn.png

для следующей строки:

    printf ("%s other stuff: %n", thing, &len);

Я предполагаю, что это в основном, чтобы избежать того, о чем говорит @eJames

...