関数に渡す引数で

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Kou

関数に渡す引数で

#1

投稿記事 by Kou » 16年前

以前質問させて頂いたKouと申します。
今回また、わからない事があったので、質問させて頂きます。

環境
・VC++ 2008 EE
・Windows XP Home SP2

会社からの書き込みのため、個人的なファイルのアップロードができないので、以下に簡単に説明のための
ソースを表記します。

構造体
//当たり判定の矩形に関する構造体
typedef struct{
  float rect_x, rect_y;//矩形の縦横サイズ
  float b_point_x[4], b_point_y[4];//計算前の頂点の座標
  float a_point_x[4], a_point_y[4];//計算後の頂点の座標
}hitrect_t

//自機に関する構造体
typedef struct{
  int flg;//フラグ
  int img;//画像番号
  float x, y;//座標
  hitrect_t rect;//当たり判定用矩形
}ch_t;

//敵に関する構造体
typedef struct{
  int flg;//フラグ
  int img;//画像番号
  float x, y;//座標
  hitrect_t rect;//当たり判定用矩形
}enm_t;
簡略化してありますが、上記のような構造体があります。
この構造体中の【当たり判定用矩形】の部分を関数で処理し、矩形を回転させるのですが、ひとつの関数に対して数種類の構造体を引数として渡す方法がわかりません。

仮に回転計算の関数を
void RotateRect(・・・・){
  実際の計算処理;
}
とした場合、この関数に自機用の構造体も、敵用の構造体も渡せるようにすれば、
ひとつの関数で処理できるので効率的なのですが・・・
計算に関する処理は一応完成しているので、現在は自機用、敵用、弾用など分けて
実装しようとしているのですが、もし良い方法があればご教授ください。

以上長文で申し訳ありませんが、よろしくお願いします。
※一応PREタグを使用しましたが、インデントでタブが使えるのかわからなかったので、
半角スペースで字下げしてあります。

※環境部分一部追加
・DxLibを使用
・言語 C言語

Mist

Re:関数に渡す引数で

#2

投稿記事 by Mist » 16年前

以下のように引数に必要な構造体を複数書けばよいだけだと思うのですが、もっと複雑なことをお考えでしょうか?

void RotateRect(hitrect_t hirect, ch_t ch, enm_t enm);

バグ

Re:関数に渡す引数で

#3

投稿記事 by バグ » 16年前

基本的には構造体も変数も同じです。
以下、サンプルです。
#include <stdio.h>

// Rect構造体
struct Rect
{
	int X;
	int Y;
	int Width;
	int Height;
};

// Rect構造体の中身を表示する
void disp(struct Rect rect, const char* name)
{
	printf("%s\n", name);
	printf("X = %d, Y = %d, Width = %d, Height = %d\n", rect.X, rect.Y, rect.Width, rect.Height);
}

// 引数で指定されたRect構造体の中身を入れ替える
void swap(struct Rect *rect1, struct Rect *rect2)
{
	// rect1のコピーを作成する
	Rect dummy = {rect1->X, rect1->Y, rect1->Width, rect1->Height};

	// rect1へrect2の内容をコピーする
	rect1->X = rect2->X;
	rect1->Y = rect2->Y;
	rect1->Width = rect2->Width;
	rect1->Height = rect2->Height;

	// rect2へrect1の内容を保持しておいたdummyの内容をコピーする
	rect2->X = dummy.X;
	rect2->Y = dummy.Y;
	rect2->Width = dummy.Width;
	rect2->Height = dummy.Height;
}

// メイン関数
int main(void)
{
	struct Rect rect1 = {10, 10, 50, 50};
	struct Rect rect2 = {50, 50, 10, 10};

	// Rect構造体の中身を表示する(コピー渡し)
	disp(rect1, "rect1");
	disp(rect2, "rect2");

	// rect1とrect2の内容を入れ替える(参照渡し)
	swap(&rect1, &rect2);

	// Rect構造体の中身を表示する(コピー渡し)
	disp(rect1, "rect1");
	disp(rect2, "rect2");

	return 0;
}

Kou

Re:関数に渡す引数で

#4

投稿記事 by Kou » 16年前

Mist様、バグ様、早速の回答ありがとうございます。

今ひとつ構造体を引数にする場合の知識が乏しいので、確認させて頂きたいのですが、

Mist様
>void RotateRect(hitrect_t hirect, ch_t ch, enm_t enm);
の方法で渡した場合、自機用、敵用の構造体内のhitrectに対して処理する場合、
void RotateRect(hitrect_t hitrect, ch_t ch, emn_t emn){
  ch.hitrect.b_point_x[0] = 計算処理;
}
の様な使い方が出来ると言う事でしょうか?

バグ様
サンプルまで付けて頂き、ありがとうございます。
このサンプルでは構造体がひとつでしたが、サンプル内のRect構造体が他の複数の構造体の中に共通項目としてある場合、基本的にはMist様の回答の様になるのでしょうか?

欲を言えば、頂点の回転計算をするのが自機、敵、弾など複数になるので、
引数の数をなるべく減らせれば・・・と考えています。
そのような事は可能なのでしょうか?

Mist

Re:関数に渡す引数で

#5

投稿記事 by Mist » 16年前

しょうもない突込みだけど、
Rect dummy

struct Rect dumy

でないとコンパイルエラー。

あと、swapの中は3行で十分じゃない?

struct Rect dummy = *rect1;
*rect1 = *rect2;
*rect2 = dummy;

Mist

Re:関数に渡す引数で

#6

投稿記事 by Mist » 16年前

hitrect_tがch_tとemn_tとで共通部分なら以下で十分と思いますが。
※参照渡しに変更
void RotateRect(ch_t *ch, emn_t *emn){
    ch->rect.b_point_x[0] = 計算処理;
}
> 欲を言えば、頂点の回転計算をするのが自機、敵、弾など複数になるので、
> 引数の数をなるべく減らせれば・・・と考えています。
その関数に必要のない引数を渡すことは無駄にしかなりませんが、単に引数が多いという理由だけで関数に必要な引数を無理やり減らそうというのは設計思想としておかしいと思います。
必要な引数は多くても全て渡すべきです。

Mist

Re:関数に渡す引数で

#7

投稿記事 by Mist » 16年前

構造体の中身を更新したい場合はバグさんの書かれているように参照渡しにしてくださいね。

バグ

Re:関数に渡す引数で

#8

投稿記事 by バグ » 16年前

>Mistさん

>>しょうもない突込みだけど、
>>Rect dummy
>>↓
>>struct Rect dumy
>>でないとコンパイルエラー。

おっと、C++の書き方に慣れているので、ついやってしまったようです。失礼しましたm(__)m


>>あと、swapの中は3行で十分じゃない?
>>struct Rect dummy = *rect1;
>>*rect1 = *rect2;
>>*rect2 = dummy;

あ、これはわざとです。
サンプルとして、ああいう書き方の方が分かり易いかなぁ…と思いまして(^_^;)
実際にはその3行で問題ないですね。

バグ

Re:関数に渡す引数で

#9

投稿記事 by バグ » 16年前

>Kouさん

> 欲を言えば、頂点の回転計算をするのが自機、敵、弾など複数になるので、
> 引数の数をなるべく減らせれば・・・と考えています。

どうしても引数を減らしたいのならば、共通する項目を構造体にして、その構造体をメンバとすればいいかと思います。関数に渡す際はその構造体の中にある構造体を渡す…みたいな感じでしょうか?

toyo

Re:関数に渡す引数で

#10

投稿記事 by toyo » 16年前

ch_tとenm_tがまったく同じなのは簡略化のためですか?
まったく同じ構造体なら分ける必要は無いと思いますが

Kou

Re:関数に渡す引数で

#11

投稿記事 by Kou » 16年前

toyo様
ch_tとenm_tの内容が同じなのは、表記上の簡略化のためです。
実際は座標などの似たようなのはありますが、それぞれメンバとなる変数の数や種類が違います。
紛らわしくてすみませんでした。

Mist様、バグ様
回答及びご意見ありがとうございます。

私なりに整理しますと、

1.関数に渡す引数は、Mist様のご指摘のように、数が多くとも必要となるであろう情報は全て渡す。
2.引数で渡す値は、バグ様のサンプルに習い、参照渡しにして関数内で値を直接操作する。

この考え方で実装してみます。
今回はこれで一応解決とさせて頂きますが、実装途中にまたわからない事がありましたら、
このトピで質問させて頂きます。
その際はまた、よろしくお願いします。

Mist様、バグ様、toyo様、ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る