2012-02-10 17 views
2

フォーマット文字列はchar *format = "hello %d world %d"、配列はint array[2] = {10, 20};です。これは単なる例であり、配列に出力される値の数は任意で、最大サイズの配列で、印刷する値の数をカウントします。 (int array[MAX]; int array_count)。C言語:printf形式の文字列で個々の書式指定子にアクセスする方法は?

明らかに私は標準prinf(format, ..)を使用することはできません。だから、私は何をしているのですか?私はフォーマット文字列を歩いて、それからただ一つのフォーマット指定子でサブ文字列を抽出し、printf(sub-string, array[index]);を使い、サブ文字列を次のフォーマット指定子に進めます。

私は何かlibsがあるかどうか知りたいのですが、印刷形式の文字列では、その文字列の最初の書式指定子のオフセットが返ってくるので、私はいくつかの作業を省くことができますか?

+0

最初の書式指定子を見つけることは非常に簡単です: 'x = strstr(input、"% "); if(x && input [x]!= '%'){/ * do things * /} ' – ssube

+0

%を検索しているだけなら、それは簡単です。しかし、私は、C形式指定子が、 "\%"が%を無視するか、 "%%"が何か他のものを意味すると言ったような任意のフォーマット指定子を持っているかどうかは分かりませんでした。そのため、フォーマット指定子を詳細に理解する必要があるので、自分でデコーダを書くことを検討したいと思ったのはなぜですか。だから問題は、すべてのフォーマット指定子がただ1つの "%"であることが保証され、先行する/超過している文字は問題になりませんか?私は座って、フォーマット指定子を詳細に読む必要があると思います:) – Gopa

+0

フォーマット指定子はプラットフォームによって異なる傾向があります(カーネルやシステムライブラリの場合は覚えていませんが、プラットホーム内で相対的に一定に保ちます)それらの間であまりにも多くの変更をしないでください。彼らはまた私の経験でエスケープ文字として%を使用する傾向がありますので、%%は非形式の%です(したがって、次の文字が%であることを確認するスニペットです)。大量のデータが必要な場合は、完全なパーサを使用する方が良いかもしれませんが、ルールは簡単であり、型を探すのが簡単です。 – ssube

答えて

0

私は1つ持っています。しかし、ここに投稿するのは少し大きいです。メールで私に連絡 - プロフィールを参照してください。あなたがに取得しているもののいくつかのアイデアを持っているので、ここで

は、ヘッダーです:

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

まあ、printf-parseのGNUのlibcの実装はオープンソースです。ライセンスはプロジェクトに合っていることを確認する必要があります。

もう1つのオプションは、foreign function interfaceライブラリを使用して、動的な引数の数で関数を呼び出すことです。 avcallはこれを許可する必要があり、おそらくlibffiで行うことができます。

+0

avcallは興味深いように聞こえますが、以前はそれについて知りませんでした。一方、私は単純にstrstrを使うことにしました。これは、上記のように書式指定子の詳細を調べた後、%%が処理される唯一の "特殊なケース"のように見えます。 – Gopa

関連する問題