C语言:如何访问printf格式字符串中的各个格式说明符?

时间:2012-02-10 05:46:57

标签: c count format printf specifier

我有一个格式字符串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在内部。

所以我很想知道是否有任何libs,给定一个打印格式字符串将返回该字符串中第一个格式化说明符的偏移量,这样它可以节省我一些工作?

2 个答案:

答案 0 :(得分:0)

我有一个。不过,这里发布的内容有点大。通过电子邮件与我联系 - 查看我的个人资料。

这是标题,因此您可以了解自己的目标:

/*
@(#)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 */

答案 1 :(得分:0)

嗯,printf-parse的GNU libc实现是开源的。您必须确保许可适合您的项目。

另一种选择是使用foreign function interface库来使用动态数量的参数进行函数调用。 avcall应允许此操作,也可以使用libffi完成。