C言語 標準関数 | 応用 | サンプル

標準関数
構文
応用

管理人

プライバシーポリシー


可変引数関数

可変引数な関数を作成するには、以下の3つのマクロをセットで使用する必要がある。

#include <stdarg.h>

① void va_start( va_list list , decision );
  ■機能:可変引数にアクセスする前の初期処理。
  ・list:可変引数を処理する為に①②③が使用する変数。
          単に「va_list list;」として定義するだけで良い。
  ・decision:
          可変引数の個数や(必要ならば)データ型が
          決定可能な情報。
          引数指定でのデータ型は無く、
          どのようなデータ型でも変数名を書けばよい。
          可変引数の個数やデータ型を決定する最も安易な
          方法は、個数をdecisionに指定し、
          可能であればデータ型を固定とすれば、
          決定可能な情報は、引数個数だけで済む。→サンプル1
          データ型を固定できないのであれば、
          例えば、printf関数などで使用する
          フォーマット指定子"%s%d%f"や
          もっと略して"sdf"でも、
          個数やデータ型を決定する情報になりうる。
          →サンプル2
  ■戻り値:なし

② data_type va_arg( va_list list , data_type );
  ■機能:可変引数にアクセスしてその変数を取り出す処理。
          通常、可変引数の個数回、forやwhileなどの
          繰り返し文で繰り返す。
  ・list:①と同じ。
  ・data_type:
          取り出す可変引数のデータ型をダブルクォート(")で
          囲まず、そのままcharやint、char* などと指定する。
  ■戻り値:
          第2引数のdata_typeで指定したデータ型に従って
          取り出した可変引数の1つ。
          繰り返しで1つずつ取り出す。

③ void va_end( va_list list );
  ■機能:可変引数にアクセスした後の終了処理。
  ・list:①と同じ。
  ■戻り値:なし

サンプル1
(可変引数の個数を決定可能な情報として指定)

#include <stdarg.h>

/* 可変引数である関数を定義 */
/*(指定された不定引数を全て加算する関数)*/
void vararg_func( int * sum , int argc , ... ) {
  va_list list;/* 定義するだけで値は設定しない */
  int i;

  *sum = 0;/* 加算結果をクリア */

  /* ①可変引数にアクセスする前の初期処理 */
  /* 第2引数に指定するargcは、vararg_func引数"..."の
                            直ぐ左側でなければならない*/

  /*(直ぐ左側→sumとargcを入れ替えると
                            コンパイルエラーになる)*/

  va_start( list ,  argc );

  for( i=0 ; i<argc ; i++ ) {
    /* ②可変引数にアクセスしてその変数を取り出す処理 */
    /* 第2引数にint型を固定指定 */
    *sum += va_arg( list , int );
  }

  /* ③可変引数にアクセスした後の終了処理 */
  va_end( list );
}

/* メイン関数 */
main() {
  int argv[3];
  int i , argc , sum;

  /* データ件数を求める */
  argc = sizeof( argv )/sizeof( argv[0] );

  /* データを設定 */
  for( i=0 ; i<argc ; i++ ) {
    argv[i] = i + 1;
  }

  /* 不定引数の加算関数を呼び出す */
  /*(sumを指定して結果を得ることも可能)*/
  vararg_func( &sum , argc , argv[0] , argv[1] , argv[2] );

  /* 加算結果を出力 */
  printf( "sum=%d\n" , sum );/* 6 */
}

サンプル1の実行結果
(可変引数の個数を決定可能な情報として指定)

sum=6

サンプル2
(可変引数の個数やデータ型を決定可能な情報として指定)

#include <stdarg.h>

/* 可変引数である関数を定義 */
/*(指定された不定引数を全て表示する関数)*/
void vararg_func( char * argv , ... ) {
  va_list list;/* 定義するだけで値は設定しない */
  int i;
  char * cp;

  /* ①可変引数にアクセスする前の初期処理 */
  /* 第2引数に指定するargcは、vararg_func引数"..."の
                            直ぐ左側でなければならない*/

  va_start( list ,  argv );

  /* cpの文字列の長さが引数個数を意味し
     文字列の各文字がデータ型を意味する */

  for( cp=( char * )argv , i=0 ; *cp != '\0'
                              ; cp++ , i++ ) {
    if( *cp == 's' ) { /* char*型 */
      /* ②可変引数にアクセスしてその変数を取り出す処理 */
      /* 第2引数にchar*型を指定 */
      printf( "argv(%d)=%s\n" , i
                   , va_arg( list , char * ));
    }
    else
    if( *cp == 'c' ) { /* char型 */
      /* ②可変引数にアクセスしてその変数を取り出す処理 */
      /* 第2引数にchar型を指定したい時は
                    int型を指定した上でchar型にcastする */

      printf( "argv(%d)=%c\n" , i
                   , ( char )va_arg( list , int ));
    }
    else
    if( *cp == 'd' ) { /* int型 */
      /* ②可変引数にアクセスしてその変数を取り出す処理 */
      /* 第2引数にint型を指定 */
      printf( "argv(%d)=%d\n" , i
                   , va_arg( list , int ));
    }
  }

  /* ③可変引数にアクセスした後の終了処理 */
  va_end( list );
}

/* メイン関数 */
main() {
  /* 不定引数の加算関数を呼び出す */
  /* "scd":各々String , Char , Intを意味し
                      文字列の長さがデータ個数を意味する */

  vararg_func( "scd" , "abc" , 'd' , 123 );
}

サンプル2の実行結果
(可変引数の個数やデータ型を決定可能な情報として指定)

argv(0)=abc
argv(1)=d
argv(2)=123


Copyright © 2008-2015 http://hitorilife.com All Rights Reserved.