• ベストアンサー

関数をの引数について。

以下のように、関数を呼び出すときに引数の個数を可変にするスマートなやり方は、何かあるでしょうか? $arrは配列 func1($arr) { // $arrの個数が3個のとき func2($arr[0], $arr[1], $arr[2]); // $arrの個数が5個のとき func2($arr[0], $arr[1], $arr[2], $arr[3], $arr[4]); } 例えば、 $args = '$arr[0], $arr[1], $arr[2]' としたとき、 func2($args) とすると、func2には文字列として渡りますが、これを上のように func2($arr[0], $arr[1], $arr[2]) として呼びたいです。 こんな方法何かあるでしょうか? よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
noname#223623
noname#223623
回答No.4

疑問の多い質問だがそれは置いといて、希望してるであろうことを素直に考えてみた。といってもそれ自体理解してるかどうかも怪しいのだが。 呼出し部分のコードを文字列として生成。それをevalで実行というのが考えられる。次のがそのサンプル。 # ここから <?php function func2($arg1, $arg2, $arg3) { echo "\$arg1:$arg1, \$arg2:$arg2, arg3:\$$arg3\n"; } $arr = array('りんご', 'バナナ', 'メロン'); $args = ''; for ($i = 0; $i < count($arr); $i++){ $args .= "\$arr[$i],"; } $code_str = 'func2(' .rtrim($args, ',') .');'; var_dump($code_str); # debug こういう文字列を作って eval($code_str); # evalで実行させる ?> # ここまで 当然だがこういう呼びかたでfunc2がうまく動くというのが前提。実際にどうなるかはfunc2の中身がわからないので保証できない。 func2側で対応するという話なら既に回答があるとおり可変長の引数や引数のデフォルト値を決める方法で対応すればいいと思います。

ryuryu252
質問者

お礼

お忙しい中、ご回答どうもありがとうございます。 教えていただいた方法で解決することができました!! 今回のfunc2()は既に可変長引数を受け取るようになっているのですが、第1引数をSQL文、第2引数以降をSQL文に渡すパラメータとして受け取る仕様の関数だったので、どうしても呼び出し側でパラメータをばらして渡す必要がありました。 このテクニックは、今後も役立ちそうです。 本当にどうもありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.3

#1ですが、意味わかんなくなってきました。 > func2()を呼び出す部分の引数を可変にしたいのです。 つまりfunc2()の仮引数が可変であれば良い、という事とは別なのでしょうか? func2()が可変引数に対応した記述で定義されていない限り、可変引数を 利用した呼び出しは不可能だと思いますよ。 もしくは渡したい値がfunc1()実引数の配列の中身と決まっているのなら、 #2さんの仰るとおり、配列をそのまま渡すべきです。 func2()の仮引数に明示的に意味合いが存在し、かつそれを別々の仮引数として 定義したい場合に限り、func2()を先に述べたような方法で可変引数として 対応可能な定義にした方が良いかと思います。 (もしくは渡される実引数の数にMAX値が存在するならば、#2で紹介のある通り、 デフォルト値を有する仮引数の定義方法) いずれにしても、func2()はもう出来上がっているからいじりたくない、 func2()を呼び出す所だけを可変にしたいという考え方では不可能だと思います。 何せfunc2()がその呼び出し方法に対応した定義と処理ではないのですから。 func2()の中身は絶対にいじりたくないんだ!という事であれば、func2()を 呼び出す前にfunc2()の呼び出し方に変換してくれるような関数を ワンクッション噛ませないといけませんね。

ryuryu252
質問者

お礼

お忙しい中、ご回答ありがとうございました。 #4の方の方法で解決することができました。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • mpx
  • ベストアンサー率71% (149/209)
回答No.2

func2にも$arr(配列)のまま渡して、func2の受け側で配列要素数を判定して処理するほうが素直ですが、 func2($arr[0], $arr[1], $arr[2])として引数の数を可変にしたいのなら function func2($a1,$a2=null,$a3=null,$a4=null,$a5=null,$a6=null){ のようにfunc2を定義すればよいです。

ryuryu252
質問者

お礼

お忙しい中、ご回答ありがとうございました。 今回func2()は、既に可変長引数を受け取ることができるようになっているのですが、#4の理由で、呼び出し側で引数をばらす必要がありました。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

PHPって確か引数の指定が強制されないんですよね。 なので function func2() {  switch (func_num_args()) {   case 1:    echo func_get_arg(0);    break;   case 2:    echo func_get_arg(0);    echo func_get_arg(1);    break;   case 3:    echo func_get_arg(0);    echo func_get_arg(1);    echo func_get_arg(2);    break;  } func2($arr[0], $arr[1], $arr[2]); みたく出来ちゃいます。 http://jp2.php.net/manual/ja/function.func-get-arg.php 左のリストに似たような関数名のものが全てそれを実現するのに 利用されるであろう関数群になります。 ただこれをすると、PDTなどの統合開発環境を利用している環境で、 当該関数を呼び出そうとして出てくるはずの引数のリストが 出てきません。 (関数定義で引数がないので当然ですが) PHPは他の言語と同等のオーバーロードがサポートされていませんので、上記方法か __call()を利用する方法くらいで対応するしかありませんね。 http://jp2.php.net/manual/ja/language.oop5.overloading.php

ryuryu252
質問者

お礼

ご回答どうもありがとうございます。 すいません、私の質問の仕方が良くなかったようなのですが、今回はfunc2()の中身ではなく、func2()を呼び出す部分の引数を可変にしたいのです。 つまり、func1()に渡ってきた配列の要素数によって、 func2($arr[0], $arr[1], ……, $arr[n-1]); という形でfunc2()をコールしたいのです。 もし何か方法をご存知でしたら、よろしくお願いします。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 可変長引数関数の引数の文字列サイズを取得したい

    以下のような可変長の文字列を受け取れる関数があったとします。 ...の部分で引数を受け取ることが可能ですが、この場合引数の文字列サイズを 知ることは可能なのでしょうか? 関数を呼び出してみて例を挙げるとするなら、  GetArgs( "%s", "あいうえお" ); この「あいうえお」の部分の文字数をGetArgs内で知りたいのです。 void GetArgs( char * FormatString, ... ) {   va_list VaList;   va_start( VaList, FormatString );   // ここでFormatStringの引数の文字列サイズを取得したい   va_end( VaList ); }

  • VBで、関数を関数の引数にするは?

    VBで関数の引数に、関数を呼ぶにはどのようにすればいいでしょうか?  例えば以下のようなイメージです   DEF FUNC1(X)=X^2   DEF FUNC2(F,a,b)=F(a)+F(b)     関数FUNC2では、関数Fを引数にする     つまりFUNC2(FUNC1,1,2)は     FUNC1(1)+FUNC1(2)=1^2+2^2=5 こんな感じです。 お教えください。

  • 関数を引数とする方法?

    いつもお世話になっています。 MFCでプログラムをしています。 今、任意の関数(Func1)を 積分する関数(Func2)を作っています。 現在は、被積分関数の数だけ、 積分関数(Func2)を書いているのですが、 非効率的なので、なるべく汎用性を持たせたいと 考えています。 参考書(新C言語入門シニア編)の該当個所で、 クラスでない通常の関数を引数とする場合は、 うまくいったのですが、 クラスのメンバ関数を引数とした場合、 どうしてもコンパイルエラーが 発生してしまいます。 関数Func、I及びエラーメッセージは大凡次のとおりです。今のところ、引数とする関数(Func1)の引数は、 同一個数としています。 <被積分関数の例> double ClassA::Func1 (double a){ return a * 10; } <積分関数> double ClassA::Func2 (double (*f)(double), double a, double b){ return b * f(a); } void classA::Integration() { ... Func2(Func1,a,b); ... } <エラーメッセージ> classA::Integrationの呼び出し箇所で、 「1番目の引数を double(double)からdouble(__cdecl)(double)に 変換できません」 と出ます。 double(double)の部分は合っているようなのですが、 (__cdecl)の部分が違うということまでは 分かりました。 メンバ関数であることが原因のようなので、 Func2での引数宣言を double ClassA::Func2 (double (ClassA::*f)(double), double a, double b){ return b * f(a); } に変えてみたところ、 引数受け渡しのところはクリアするのですが、 Func2(Func1,a,b); の呼び出し時に、Func2が関数ではないという エラーがでます。 アドバイス又は参考URL等を 教えていただければ助かります。 よろしくお願いします。

  • 可変長引数関数のマクロ関数について

    可変長引数をとる関数をマクロで置き換えたいのですが、 この方法だとできません。うまく実現できないでしょうか? ------------------------------------------------------- #define TRACE(arg, ...) trace(__FILE__,__LINE__,arg, ...) void trace(char *file, int line, char *arg, ...) {   ...(略)... } func() {   ...   TRACE("hello %s", "taro");   ... } ------------------------------------------------------- よくあるトレース処理だと思いますがこんな感じです。 他にも代替手段は考えつきますが、 可変長引数の関数のマクロが可能かが知りたいです。 どなたがご存知の方がいらっしゃいましたら、よろしくお願いします。

  • 可変長引数をもつオーバライド関数について

    オーバライド関数について質問があります。 以下のようなクラスAとBがあります。 クラスAは基本クラスです。 クラスBはクラスAから導出しました。 ------------------------------------ CLASS A { public: virtual void func(char* p, ...); } ------------------------------------ CLASS B : public A { public: void func(char* p, ...); } ------------------------------------ メンバ関数の func() はオーバライド関数で、可変長の引数を持っています。 今、クラスBの func() の中で、クラスAの func() をコールするようにコーディングしました。 ----------------------------------- void B::func(char* p, ...) { : : A::func( ???? ) : : } ----------------------------------- ところが、クラスBの func()が受け取った引数を、そのままクラスAの func() に渡したいのですが、どうしたらいいのか分かりません。これって無理でしょうか? 教えて下さい。

  • 2番目に小さい引数を返す関数

    mysql5で2番目(またはN番目)に小さい(または大きい)引数を返す関数はありますか 例えば、 func(2番目, 2, 15, 7) のようにして7を返してくれるような関数はありますか または真ん中の数を返してくれる関数はありますか func(2, 15, 7) で7が返る これはさすがにないか・・・

    • ベストアンサー
    • MySQL
  • 関数ポインタ配列の関数名を検索

    関数ポインタ配列に格納されている関数名を文字列で検索して 配列の番号を得たいのですが、どんな方法が考えられるでしょうか? void (*p_func[])(char*) = {   display,   output, }; int main() {   int fncNo;   fncNo = serchFnc( "display" ); //このserchFnc関数を作りたい   p_func[ fncNo ]( "abcd" );   return 0; } 上の例ですとdisplay関数が実行されます。 関数を50個ぐらいまで増やす予定なので追加や削除に耐えられるような 保守性のある方法が理想です。 構造体を使って関数名と検索文字列をワンセットに出来ないか考えたんですけど 適切な方法が思いつきませんでした。

  • array関数に指定する引数が可変個の場合どうしたらよいでしょうか?

    array関数に指定する引数が可変個の場合どうしたらよいでしょうか? arrValue = Array("a","b","c") 上記のように、array関数を使ってvariant型の変数に格納したいのですが、 arrayに指定する個数が可変個の場合、どうやったらよいのでしょうか? arrayに指定する値は、他のプログラムによって 配列型変数"aaa"に格納済みです。 aaaに格納される配列数は可変個のため、 dim aaa() as string で定義して、取得できた数によって Redim で再定義しています。 aaaの配列数に応じて、if文などで、 配列数が1個だったら、arrValue = Array(aaa(0)) 配列数が2個だったら、arrValue = Array(aaa(0),aaa(1)) とすればできないことはないのですが、何個までを想定すればよいかも わからないため、困っています。 何かよい方法はないでしょうか?

  • 可変個引数の関数

    今現在可変個引数をとる関数を作成しています。 物としてはprintfと同等のものなのですが、可変個引数の取得の方法がわからず停滞してしまっています。 printtest("%s",str); と記述してstrの中身が出力されるようにしたいのです。 どうかご助力のほどよろしくお願いいたします。

  • 可変個引数を使った関数で文字の長さを知りたい

    可変個引数を使った引数を使って引数の文字列の長さを知りたいのですがどうすればいいのかわかりません。 DXライブラリを使って文字列の長さを測って文字をどこにおくのかを決めているため文字列の長さがわからないと困ってしまいます。 どのようにすれば可変個引数を使った引数の文字列の長さを測れますか? 大体以下のような感じで作っています。 void kai( int *x , int *y ); //文字列を改行する関数 int JC( unsigned char code ); //文字が1バイト文字 か 2バイト文字か判別する void mozi_show2( int x , int y , int xm , int yb , int color , int char_set , const char *s , ... ){   int i = 0;   int xs = 0 , ys = 0;   int m_color = color;   char One[ 2 ]; //1バイト文字格納用   char Two[ 3 ]; //2バイト文字格納用   const char* p;   va_list args;   va_start( args , s );   p = s;   while( *p != '\0' ){     switch( *p ){       case '%':         p++;         assert( *p != '\0' );         switch( *p ){           case 'd':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%d" , va_arg( args , int ) );             //purintfと使い方はほぼ同じで左から文字を表示したいX座標・文字を表示したいY座標             //文字の色・文字の書式・格納用文字列・表示したいint型の数値をあらわしています             xs += 16;             /*             xs += GetDrawFormatStringWidthToHandle( char_set , "%d" , va_arg( args , int ) );             本来ならこの関数を使って文字列の長さを計る左から             文字列の書式・格納用文字列・長さを測りたいint型文字列             これを使うと別のものを計っているみたいで文字の長さがわからない             文字の長さってどうやって計るの?             */             break;           case 'f':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%f" , va_arg( args , double ) );             break;           case 'c':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%c" , va_arg( args , char ) );             break;           case 's':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%s" , va_arg( args , const char* ) );             break;           case '%':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%%" );             xs += GetDrawStringWidthToHandle( "%" , 1 , char_set );             break;         }         p++;         break;       default:         if( JC( *p ) ){           Two[ 0 ] = *p;           Two[ 1 ] = *( p + 1 );           Two[ 2 ] = '\0';           DrawStringToHandle( x + xs , y + ys * yb , Two , m_color , char_set );           xs += GetDrawStringWidthToHandle( Two , 2 , char_set );           p += 2;         }         else{           One[ 0 ] = *p;           One[ 1 ] = '\0';           DrawStringToHandle( x + xs , y + ys * yb , One , m_color , char_set );           xs += GetDrawStringWidthToHandle( One , 1 , char_set );           p++;         }         break;     }     if( xs > xm ){       kai( &xs , &ys );     }   }   va_end( args ); } void zitu_draw( void ){   char *str = "%d個 OK";   int i = 12;   mozi_show2( 100 , 100 , 300 , 15 , red_s , MG_14_0 , str , i );   //左から 文字を表示するX座標・文字を表示するY座標・文字を改行する文字列の長さ   //改行した時のY座標の縦幅・文字色・文字の書式・表示したい文字列・%dに表示したいint型の値 }