Создание C отформатированные строки (не печатающий их)

После уик-энда анализа я получил ответ:

SELECT
        AREAS.RA_NAME
    ,   AREAS.RA_DESC
    ,   COUNT( DISTINCT AD_Results.Name) AS RA_AD_Objects
    ,   COUNT( DISTINCT tblAssets.AssetID) AS RA_LS_Objects
FROM AREAS
JOIN AD_Results ON CHARINDEX(AREAS.RA_NAME, AD_Results.[Parent Container]) > 0
LEFT JOIN tblADComputers ON CHARINDEX(AREAS.RA_NAME, tblADComputers.OU) > 0
LEFT JOIN tblAssets ON tblAssets.AssetID = tblADComputers.AssetID
GROUP BY AREAS.RA_NAME, AREAS.RA_DESC
ORDER BY AREAS.RA_NAME
GO

Весь СЧЕТ (СЛУЧАЙ ... перепутал его, и он не был действительно необходим.

91
задан nbro 28 March 2016 в 12:00
поделиться

5 ответов

Use sprintf.

int sprintf ( char * str, const char * format, ... );

Write formatted data to string Composes a string with the same text that would be printed if format was used on printf, but instead of being printed, the content is stored as a C string in the buffer pointed by str.

The size of the buffer should be large enough to contain the entire resulting string (see snprintf for a safer version).

A terminating null character is automatically appended after the content.

After the format parameter, the function expects at least as many additional arguments as needed for format.

Parameters:

str

Pointer to a buffer where the resulting C-string is stored. The buffer should be large enough to contain the resulting string.

format

C string that contains a format string that follows the same спецификации в формате printf (подробности см. в printf).

... (additional arguments)

В зависимости от строки формата функция может ожидать последовательность дополнительные аргументы, каждый из которых содержит значение, которое будет использоваться для замены спецификатор формата в строке формата (или указатель на хранилище местоположение, для п). Там должно быть как минимум столько же аргументов как количество значений, указанных в спецификаторах формата. дополнительный arguments are ignored by the function.

Example:

// Allocates storage
char *hello_world = (char*)malloc(13 * sizeof(char));
// Prints "Hello world!" on hello_world
sprintf(hello_world, "%s %s!", "Hello" "world");
84
ответ дан 24 November 2019 в 06:51
поделиться

Если у вас есть код для log_out () , перепишите его. Скорее всего, вы можете сделать:

static FILE *logfp = ...;

void log_out(const char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    vfprintf(logfp, fmt, args);
    va_end(args);
}

Если требуется дополнительная информация о регистрации, которую можно распечатать до или после показанного сообщения. Это сохраняет распределение памяти и сомнительные размеры буфера и так далее и тому подобное. Вероятно, вам нужно инициализировать logfp в ноль (нулевой указатель) и проверить, является ли он нулевым, и открыть файл журнала соответствующим образом - но код в существующем log_out () должен иметь дело с с этим в любом случае.

Преимущество этого решения в том, что вы можете просто назвать его, как если бы это был вариант printf () ; действительно, это незначительный вариант для printf () .

Если у вас нет кода для log_out () , подумайте, можете ли вы заменить его на такой вариант как указано выше. Возможность использования одного и того же имени будет зависеть от среды вашего приложения и конечного источника текущей функции log_out () . Если он находится в том же объектном файле, что и другая необходимая функция, вам придется использовать новое имя. Если вы не можете понять, как его точно воспроизвести, вам придется использовать какой-то вариант, подобный приведенному в других ответах, который выделяет соответствующий объем памяти.

void log_out_wrapper(const char *fmt, ...)
{
    va_list args;
    size_t  len;
    char   *space;

    va_start(args, fmt);
    len = vsnprintf(0, 0, fmt, args);
    va_end(args);
    if ((space = malloc(len + 1)) != 0)
    {
         va_start(args, fmt);
         vsnprintf(space, len+1, fmt, args);
         va_end(args);
         log_out(space);
         free(space);
    }
    /* else - what to do if memory allocation fails? */
}

Очевидно, вы теперь вызываете log_out_wrapper () вместо log_out () - но выделение памяти и т. д. выполняется один раз. Я оставляю за собой право перераспределять пространство одним ненужным байтом - я не проверял дважды, содержит ли длина, возвращаемая функцией vsnprintf () завершающий ноль или нет.

Если он находится в том же объектном файле, что и другая необходимая функция, вам придется использовать новое имя. Если вы не можете понять, как точно его реплицировать, вам придется использовать какой-то вариант, подобный приведенному в других ответах, который выделяет соответствующий объем памяти.

void log_out_wrapper(const char *fmt, ...)
{
    va_list args;
    size_t  len;
    char   *space;

    va_start(args, fmt);
    len = vsnprintf(0, 0, fmt, args);
    va_end(args);
    if ((space = malloc(len + 1)) != 0)
    {
         va_start(args, fmt);
         vsnprintf(space, len+1, fmt, args);
         va_end(args);
         log_out(space);
         free(space);
    }
    /* else - what to do if memory allocation fails? */
}

Очевидно, вы теперь вызываете log_out_wrapper () вместо log_out () - но выделение памяти и т. д. выполняется один раз. Я оставляю за собой право перераспределять пространство одним ненужным байтом - я не проверял дважды, содержит ли длина, возвращаемая функцией vsnprintf () завершающий ноль или нет.

Если он находится в том же объектном файле, что и другая необходимая функция, вам придется использовать новое имя. Если вы не можете понять, как точно его реплицировать, вам придется использовать какой-то вариант, подобный приведенному в других ответах, который выделяет соответствующий объем памяти.

void log_out_wrapper(const char *fmt, ...)
{
    va_list args;
    size_t  len;
    char   *space;

    va_start(args, fmt);
    len = vsnprintf(0, 0, fmt, args);
    va_end(args);
    if ((space = malloc(len + 1)) != 0)
    {
         va_start(args, fmt);
         vsnprintf(space, len+1, fmt, args);
         va_end(args);
         log_out(space);
         free(space);
    }
    /* else - what to do if memory allocation fails? */
}

Очевидно, вы теперь вызываете log_out_wrapper () вместо log_out () - но выделение памяти и т. д. выполняется один раз. Я оставляю за собой право перераспределять пространство одним ненужным байтом - я не проверял дважды, содержит ли длина, возвращаемая функцией vsnprintf () завершающий ноль или нет.

вам придется использовать некоторый вариант, подобный приведенному в других ответах, который выделяет соответствующий объем памяти.

void log_out_wrapper(const char *fmt, ...)
{
    va_list args;
    size_t  len;
    char   *space;

    va_start(args, fmt);
    len = vsnprintf(0, 0, fmt, args);
    va_end(args);
    if ((space = malloc(len + 1)) != 0)
    {
         va_start(args, fmt);
         vsnprintf(space, len+1, fmt, args);
         va_end(args);
         log_out(space);
         free(space);
    }
    /* else - what to do if memory allocation fails? */
}

Очевидно, теперь вы вызываете log_out_wrapper () вместо log_out () - но выделение памяти и т. д. выполняется один раз. Я оставляю за собой право перераспределять пространство одним ненужным байтом - я не проверял дважды, содержит ли длина, возвращаемая функцией vsnprintf () завершающий ноль или нет.

вам придется использовать некоторый вариант, подобный приведенному в других ответах, который выделяет соответствующий объем памяти.

void log_out_wrapper(const char *fmt, ...)
{
    va_list args;
    size_t  len;
    char   *space;

    va_start(args, fmt);
    len = vsnprintf(0, 0, fmt, args);
    va_end(args);
    if ((space = malloc(len + 1)) != 0)
    {
         va_start(args, fmt);
         vsnprintf(space, len+1, fmt, args);
         va_end(args);
         log_out(space);
         free(space);
    }
    /* else - what to do if memory allocation fails? */
}

Очевидно, теперь вы вызываете log_out_wrapper () вместо log_out () - но выделение памяти и т. д. выполняется один раз. Я оставляю за собой право перераспределять пространство одним ненужным байтом - я не проверял дважды, содержит ли длина, возвращаемая функцией vsnprintf () завершающий ноль или нет.

3
ответ дан 24 November 2019 в 06:51
поделиться

It sounds to me like you want to be able to easily pass a string created using printf-style formatting to the function you already have that takes a simple string. You can create a wrapper function using stdarg.h facilities and vsnprintf() (which may not be readily available, depending on your compiler/platform):

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

// a function that accepts a string:

void foo( char* s);

// You'd like to call a function that takes a format string 
//  and then calls foo():

void foofmt( char* fmt, ...)
{
    char buf[100];     // this should really be sized appropriately
                       // possibly in response to a call to vsnprintf()
    va_list vl;
    va_start(vl, fmt);

    vsnprintf( buf, sizeof( buf), fmt, vl);

    va_end( vl);

    foo( buf);
}



int main()
{
    int val = 42;

    foofmt( "Some value: %d\n", val);
    return 0;
}

For platforms that don't provide a good implementation (or any implementation) of the snprintf() family of routines, I've successfully used a nearly public domain snprintf() from Holger Weiss.

11
ответ дан 24 November 2019 в 06:51
поделиться

http://www.gnu.org/software/hello/manual/libc/Variable-Arguments-Output.html дает следующий пример для печати в stderr. Вы можете изменить его, чтобы вместо этого использовать функцию журнала:

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

 void
 eprintf (const char *template, ...)
 {
   va_list ap;
   extern char *program_invocation_short_name;

   fprintf (stderr, "%s: ", program_invocation_short_name);
   va_start (ap, template);
   vfprintf (stderr, template, ap);
   va_end (ap);
 }

Вместо vfprintf вам нужно будет использовать vsprintf, где вам нужно предоставить соответствующий буфер для печати. ​​

-2
ответ дан 24 November 2019 в 06:51
поделиться

Я этого не делал, поэтому просто хочу указать на правильный ответ.

C имеет положения для функций, которые принимают неопределенное количество операндов, используя Заголовок . Вы можете определить свою функцию как void log_out (const char * fmt, ...); и получить va_list внутри функции. Затем вы можете выделить память и вызвать vsprintf () с выделенной памятью, форматом и va_list .

В качестве альтернативы вы можете использовать это для написания функции, аналогичной sprintf () , который выделяет память и возвращает отформатированную строку, генерируя ее более или менее, как указано выше. Это будет утечка памяти, но если вы просто выходите из системы, это может не иметь значения.

0
ответ дан 24 November 2019 в 06:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: