Язык C: Как получить доступ к отдельным спецификаторам формата в строке формата printf? - PullRequest
2 голосов
/ 10 февраля 2012

У меня есть строка формата скажем char *format = "hello %d world %d" и массив int array[2] = {10, 20}; со мной. Это просто для примера, число значений, которые будут напечатаны в массиве, может быть произвольным, массив максимального размера со счетчиком количества значений, которые будут напечатаны. (int array[MAX]; int array_count).

Так что, очевидно, я не смогу использовать для этого стандарт prinf(format, ..). Так что я думаю, что я буду обходить строку формата и извлекать из нее подстроку только с одним спецификатором формата, использовать printf(sub-string, array[index]); и перемещать подстроку к следующему описателю формата - что-то вроде того, что делает printf внутри.

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

Ответы [ 2 ]

0 голосов
/ 10 февраля 2012

Хорошо, реализация GNU libc printf-parse имеет открытый исходный код.Вам нужно убедиться, что лицензирование соответствует вашему проекту.

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

0 голосов
/ 10 февраля 2012

У меня есть один. Это немного большой, чтобы разместить здесь, хотя. Свяжитесь со мной по электронной почте - смотрите мой профиль.

Вот заголовок, так что у вас есть представление о том, что вы получаете:

/*
@(#)File:           $RCSfile: printfmt.h,v $
@(#)Version:        $Revision: 2.1 $
@(#)Last changed:   $Date: 2011/07/18 16:30:54 $
@(#)Purpose:        Parse printf() format string for conversion specification
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 2011
@(#)Product:        :PRODUCT:
*/

/*TABSTOP=4*/

#ifndef JLSS_ID_PRINTFMT_H
#define JLSS_ID_PRINTFMT_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>

#ifdef MAIN_PROGRAM
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_printfmt_h[];
const char jlss_id_printfmt_h[] = "@(#)$Id: printfmt.h,v 2.1 2011/07/18 16:30:54 jleffler Exp $";
#endif /* lint */
#endif /* MAIN_PROGRAM */

typedef enum PFP_Errno
{
    PFE_NoError,            /* No error */
    PFE_InvalidFormat,      /* Found % with no valid conversion specifier */
    PFE_NumberOverflow,     /* Number too big (max: 16,383) (should not be seen by users) */
    PFE_WidthOverflow,      /* Field width too big (max: 16,383)     */
    PFE_PrecOverflow,       /* Field precision too big (max: 16,383) */
    PFE_InvalidModifier,    /* Invalid modifier characters */
    PFE_MissingNDollar,     /* One n$ was present and others were missing */
    PFE_RepeatedFlag,       /* One of the flags was repeated */
    PFE_DollarOverflow,     /* Value in n$ too big (max: 16,383) */
    PFE_InvalidError,       /* Error number is not recognized */
    PFE_BufferTooSmall,     /* Buffer too small */
    PFE_BogusWidth,         /* Faulty width specification */
    PFE_BogusPrecision,     /* Faulty precision specification */
} PFP_Errno;

enum
{
    FWP_None   = -1,
    FWP_Star   = -2,
};

typedef enum PFP_Status
{
    PFP_Found  = +1,
    PFP_Error  = -1,
    PFP_Finish =  0,
} PFP_Status;

typedef struct PrintFormat
{
    const char *start;          /* Pointer to % symbol */
    const char *end;            /* Pointer to conversion specifier */
    PFP_Errno   error;          /* Conversion error number */
    short       width;          /* Field width (FPW_None for none, FPW_Star for *) */
    short       precision;      /* Field precision (FPW_None for none, FPW_Star for *) */
    short       conv_num;       /* n of %n$ (0 for none) */
    short       width_num;      /* n of *n$ for width (0 for none) */
    short       prec_num;       /* n of *n$ for precision (0 for none) */
    char        flags[6];       /* [+-0# ] */
    char        modifier[3];    /* hh|h|l|ll|j|z|t|L */
    char        convspec;       /* [diouxXfFeEgGAascp] */
} PrintFormat;

/*
** print_format_parse() - isolate and parse next printf() conversion specification
**
**  PrintFormat pf;
**  PFP_Status rc;
**  const char *format = "...%3$+-*2$.*1$llX...";
**  const char *start = format;
**  while ((rc = print_format_parse(start, &pf)) == PFP_Found)
**  {
**      ...use filled in pf to identify format...
**      start = pf.end + 1;
**  }
**  if (rc == PFP_Error)
**      ...report error, possibly using print_format_error(pf.error)...
*/
extern PFP_Status  print_format_parse(const char *src, PrintFormat *pf);
extern const char *print_format_error(PFP_Errno err);
extern PFP_Status  print_format_create(PrintFormat *pf, char *buffer, size_t buflen);

#ifdef __cplusplus
}
#endif

#endif /* JLSS_ID_PRINTFMT_H */
...