C言語関係掲示板

過去ログ

No.736 fprintfの可変長引数対応

[戻る] [ホームページ]
No.9097

fprintfの可変長引数対応
投稿者---fuku(2003/08/28 12:06:25)


あるループ中でファイル出力しています。
ただ,ループ毎にファイル出力先,内容が
異なっており,現在は以下のように記述
しています。

int i, i1, i2, i3;
double d1, d2, d3;
for (i=0; i<5; i++){
  
  /* i1〜i3,d1〜d3計算 */
  
  switch(i){
    case 0:
      fprintf(fp1, "%d,%lf", i1, d1);
      break;
    case 1:
      fprintf(fp2, "%d,%d,%lf", i1, i2, d1);
      break;
    case 2:
      fprintf(fp3, "%d,%d,%lf", i1, i2, d1);
      break;
    case 3:
      fprintf(fp4, "%d,%lf,%lf", i1, d2, d3);
      break;
    case 4:
      fprintf(fp5, "%d,%lf,%lf,%lf", i1, d1, d2, d3);
      break;
  }
}


今までは5回ループ固定でしたが,6回以上
に対応できるようにメンテナンスしなければ
ならなくなくなりました。
switch部分がネックになっており,何とか
switch部分を削除したいと思っております。
fprintf( fp[i], fmt[i], ...);
のように配列を用いることで解消できそう
ですが,ファイルポインタとフォーマット
部分は配列化できますが,出力変数部分を
どうやればよいのか分かりません。
何か良い手はありますでしょうか。


No.9098

Re:fprintfの可変長引数対応
投稿者---nop(2003/08/28 12:45:06)


>switch部分がネックになっており,何とか
>switch部分を削除したいと思っております。
> fprintf( fp[i], fmt[i], ...);
>のように配列を用いることで解消できそう
>ですが,ファイルポインタとフォーマット
>部分は配列化できますが,出力変数部分を
>どうやればよいのか分かりません。
>何か良い手はありますでしょうか。

引数の順番や数が不定なら、
おそらく無理でしょう。
表示する結果の変数が変わると言うことは、
それに付随する計算の処理も変わるはず。
switch()などで対応するしかないのでは?

細かい処理がわからないのでこれ以上は何とも言えない。

No.9101

Re:fprintfの可変長引数対応
投稿者---かずま(2003/08/28 13:25:22)


> switch部分がネックになっており,何とか
> switch部分を削除したいと思っております。

switch を削除すればいいんですね。関数を配列にしましょう。
#include <stdio.h>

FILE *fp1, *fp2, *fp3, *fp4, *fp5;

#define ARGS  int i1, int i2, int i3, double d1, double d2, double d3
void p1(ARGS) { fprintf(fp1, "%d,%f\n", i1, d1); }
void p2(ARGS) { fprintf(fp2, "%d,%d,%f\n", i1, i2, d1); }
void p3(ARGS) { fprintf(fp3, "%d,%d,%f\n", i1, i2, d1); }
void p4(ARGS) { fprintf(fp4, "%d,%f,%f\n", i1, d2, d3); }
void p5(ARGS) { fprintf(fp5, "%d,%f,%f,%f\n", i1, d1, d2, d3); }

void (*print[])(ARGS) = { p1, p2, p3, p4, p5 };

int main(void)
{
    int i, i1, i2, i3;  double d1, d2, d3;

    fp1 = fp2 = fp3 = fp4 = fp5 = stdout;
    i1 = 1, i2 = 2, i3 = 3, d1 = 0.1, d2 = 0.2, d3 = 0.3;

    for (i = 0; i < 5; i++){
        /* i1〜i3,d1〜d3計算 */
        print[i](i1, i2, i3, d1, d2, d3);  
    }
    return 0;
}


No.9102

Re:fprintfの可変長引数対応
投稿者---nop(2003/08/28 13:30:05)


>switch を削除すればいいんですね。関数を配列にしましょう。

個人的には出力ストリームも引数にした方がよろしいかと。

No.9110

Re:fprintfの可変長引数対応
投稿者---aki(2003/08/28 17:18:10)


i1, i2, i3 と d1, d2, d3 を配列にすればよさそうです。

#include <stdio.h>

void fprint(FILE *fp, int fmt, const int i[], const double d[])
{
    int bit, nput = 0;

    for (bit = 5; bit >= 0; bit--)
        if ((01 << bit) & fmt) {
            if (nput++) fputc(',', fp);
            if (bit >= 3)
                fprintf(fp, "%d", i[5-bit]);
            else
                fprintf(fp, "%f", d[2-bit]);
        }
    if (nput) fputc('\n', fp);
}

int main(void)
{
    static FILE *fp[] = {stdout, stderr, stderr, stdout, stderr};
    static int  fmt[] = {044,    064,    064,    043,    047   };

    int n;  int i[3];  double d[3];

    for (n = 0; n < 5; n++) {
        /* i[0]〜i[2], d[0]〜d[2] を計算 */
        fprint(fp[n], fmt[n], i, d);
    }
    return 0;
}


No.9111

Re:fprintfの可変長引数対応
投稿者---aki(2003/08/28 18:02:48)


フォーマットの指定方法を変えてみました。

#include <stdio.h>
#include <assert.h>

void fprint(FILE *fp, const char *fmt, const int i[], const double d[])
{
    int n, nput = 0;

    for (n = 0; n < 6; n++)
        if (fmt[n] != '-') {
            assert(n < 3 && fmt[n] == 'd' || n >= 3 && fmt[n] == 'f');
            if (nput++) fputc(',', fp);
            if (fmt[n] == 'd')
                fprintf(fp, "%d", i[n]);
            else
                fprintf(fp, "%f", d[n-3]);
        }

    if (nput) fputc('\n', fp);
}

int main(void)
{
    static FILE  *fp[] = {stdout,   stderr,   stderr,   stdout,   stderr  };
    static char *fmt[] = {"d--f--", "dd-f--", "dd-f--", "d---ff", "d--fff"};

    int n;  int i[3];  double d[3];

    for (n = 0; n < 5; n++) {
        /* i[0]〜i[2], d[0]〜d[2] を計算 */
        fprint(fp[n], fmt[n], i, d);
    }
    return 0;
}


No.9113

Re:fprintfの可変長引数対応
投稿者---かずま(2003/08/28 19:09:20)


>  static char *fmt[] = {"d--f--", "dd-f--", "dd-f--", "d---ff", "d--fff"};

"d---ff" だと、i[0], d[1], d[2] を出力しますが、
i[0], d[2], d[1] の順で出力したい時に困りますね。

ということで、こんなのはどうでしょう。

void fprint(FILE *fp, const char *fmt, const int i[], const double d[])
{
    char c, *p = (char *)fmt;

    while (c = *p++)
        switch (c) {
         case 'i': fprintf(fp, "%d", i[strtol(p, &p, 10)]); break;
         case 'd': fprintf(fp, "%f", d[strtol(p, &p, 10)]); break;
         default:  fputc(c, fp); break;
        }
}

    static char *fmt[] = {
        "i0,d0\n", "i0,d1,d0\n", "i0,i1,d0\n", "i0,d2,d1\n", "i0,d0,d1,d2\n"
    };