不完全型構造体のポインタが複数ほしい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ウーパールーパー山田
記事: 19
登録日時: 5年前

不完全型構造体のポインタが複数ほしい

#1

投稿記事 by ウーパールーパー山田 » 5年前

コード:

struct tagEnemy *Enemy;
データ隠蔽のために不完全型構造体を使っていますが
例えば上記のソースコードの場合、敵をたくさん出現させたいときに配列を使いたいですが構造体のサイズが分からないので配列は使えません
がんばってポインタ一つ一つに命名していってもいいのですが
それだと配列の添字とfor文を使った場合のように敵の処理を一度に済ませることができません

なにか良い方法はないのでしょうか?それとも複数のオブジェクトが欲しい場合に不完全型構造体を使うのが間違いなのでしょうか?
投げやりなのですが自分ではどんなに考えても調べても解決できませんでした

ご教授よろしくお願いします

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 不完全型構造体のポインタが複数ほしい

#2

投稿記事 by softya(ソフト屋) » 5年前

そういう場合に使われるのが、ポインタを使ったリスト構造です。
struct tagEnemyの実体はmallocして、リスト構造体自体もmallocします。リスト構造体には、次のリスト構造体ポインタとstruct tagEnemy *Enemy;を持てば良いでしょう。
http://www9.plala.or.jp/sgwr-t/c/sec15-5.html
C++ならstd::listなど便利なライブラリがあるんですが、C言語は自分で実装してください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6312
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 不完全型構造体のポインタが複数ほしい

#3

投稿記事 by みけCAT » 5年前

素直にポインタの配列ではダメなのでしょうか?

コード:

#include <stdio.h>
#include <stdlib.h>

struct tagEnemy *generateEnemy(int data);
void freeEnemy(struct tagEnemy *e);
void printEnemy(const struct tagEnemy *e);

int main(void) {
	struct tagEnemy *Enemy[3];
	int i;
	Enemy[0] = generateEnemy(3);
	Enemy[1] = generateEnemy(4);
	Enemy[2] = generateEnemy(6);

	for (i = 0; i < 3; i++) {
		printEnemy(Enemy[i]);
	}

	for (i = 0; i < 3; i++) {
		freeEnemy(Enemy[i]);
	}
	return 0;
}

struct tagEnemy {
	int data;
};

struct tagEnemy *generateEnemy(int data) {
	struct tagEnemy *e = (struct tagEnemy*)malloc(sizeof(struct tagEnemy));
	if (e == NULL) exit(1);
	e->data = data;
	return e;
}

void freeEnemy( struct tagEnemy *e) {
	free(e);
}

void printEnemy(const struct tagEnemy *e) {
	if (e == NULL) {
		puts("null");
	} else {
		printf("%d\n", e->data);
	}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 不完全型構造体のポインタが複数ほしい

#4

投稿記事 by softya(ソフト屋) » 5年前

敵の数の上限が決まっているなら、みけCATさんの方法をおすすめします。その方法の方がバグが少ないですから。[誤字修正]
【ご指摘ありがとうございます。敬称がもれておりました。みけCATさんすいません。】
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

超初級者
記事: 54
登録日時: 6年前

Re: 不完全型構造体のポインタが複数ほしい

#5

投稿記事 by 超初級者 » 5年前

他の人のハンドルに敬称が付いていないのは
誤字ではないのかな?

ウーパールーパー山田
記事: 19
登録日時: 5年前

Re: 不完全型構造体のポインタが複数ほしい

#6

投稿記事 by ウーパールーパー山田 » 5年前

質問する前にみけCATさんのやりかたで試していたのですがコンパイルが通りませんでした
ですが、どうやらポインタ配列とは関係ないところの記述ミスが原因でコンパイルが通らなかったようです
お手数おかけしました 本当にすみません
(配列はサイズが分からないと宣言できないから、たとえ不完全構造体のポインタでも配列は作れないのかという
思い込みが自分の中にあったので記述ミスを探すのを怠っていました)

ただ、疑問なのですがお二人ともmallocを使用していますが、mallocを使用しない方法でもいいのでしょうか?
例えばtagEnemy構造体が定義されているファイルにstaticなtagEnemy構造体の実体を
置いておいて、その実体のアドレスをみけCATさんのコードでいうgenerateEnemy()で返してあげるという方法はアリでしょうか?
(みけCATさんのコードでいうとtagEnemyが定義されているファイルにstatic struct tagEnemy Enemy[3];と書いてあるということです)
キャラクターの表示数は決まっています 動的に要素数を変更する必要はないです

アバター
みけCAT
記事: 6312
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 不完全型構造体のポインタが複数ほしい

#7

投稿記事 by みけCAT » 5年前

ウーパールーパー山田 さんが書きました:質問する前にみけCATさんのやりかたで試していたのですがコンパイルが通りませんでした
ですが、どうやらポインタ配列とは関係ないところの記述ミスが原因でコンパイルが通らなかったようです
お手数おかけしました 本当にすみません
エラーメッセージは読みましたか?
ウーパールーパー山田 さんが書きました:(配列はサイズが分からないと宣言できないから、たとえ不完全構造体のポインタでも配列は作れないのかという
思い込みが自分の中にあったので記述ミスを探すのを怠っていました)
指す先の型にかかわらず、ポインタはサイズが(環境によって)決まっています。
だから配列も作れます。
もしサイズが決まっていなかったら、単体の

コード:

struct tagEnemy *Enemy;
も定義できないのではないでしょうか?
ウーパールーパー山田 さんが書きました:ただ、疑問なのですがお二人ともmallocを使用していますが、mallocを使用しない方法でもいいのでしょうか?
例えばtagEnemy構造体が定義されているファイルにstaticなtagEnemy構造体の実体を
置いておいて、その実体のアドレスをみけCATさんのコードでいうgenerateEnemy()で返してあげるという方法はアリでしょうか?
大丈夫だと思います。

コード:

#include <stdio.h>

struct tagEnemy *generateEnemy(int data);
void printEnemy(const struct tagEnemy *e);

int main(void) {
	struct tagEnemy *Enemy[3];
	int i;
	Enemy[0] = generateEnemy(3);
	Enemy[1] = generateEnemy(4);
	Enemy[2] = generateEnemy(6);

	for (i = 0; i < 3; i++) {
		printEnemy(Enemy[i]);
	}

	return 0;
}

struct tagEnemy {
	int data;
};

static struct tagEnemy EnemyPool[3];
static int EnemyPoolIndex = 0;

/*
バッファオーバーランに注意。(ここではエラーチェックは省略)
やりたいことによっては、一度の呼び出しで配列全体に値(ポインタ)を設定するなど、もっといい設計があるかも。
*/
struct tagEnemy *generateEnemy(int data) {
	struct tagEnemy *e = &EnemyPool[EnemyPoolIndex++];
	e->data = data;
	return e;
}

void printEnemy(const struct tagEnemy *e) {
	if (e == NULL) {
		puts("null");
	} else {
		printf("%d\n", e->data);
	}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 不完全型構造体のポインタが複数ほしい

#8

投稿記事 by softya(ソフト屋) » 5年前

実体がstaticでも構いません。

こんな案もあるという参考ですが、
struct tagEnemy *Enemy[3];自体もmain側でなくenemy側に有っても構わないです。
そうすれば、こういう関数でポインタ配列の先頭ポインタを返却できます。
struct tagEnemy **getEnemysArray();

コード:

#include <stdio.h>
#include <stdlib.h>

#define ENEMY_ARRAY_NUMS 3

struct tagEnemy **getEnemysArray();
void printEnemy(const struct tagEnemy *e);
 
int main(void) {
    struct tagEnemy **Enemy = getEnemysArray();
    int i;
 
    for (i = 0; i < ENEMY_ARRAY_NUMS; i++) {
        printEnemy(Enemy[i]);
    }
 
    return 0;
}
 
struct tagEnemy {
    int data;
};

static struct tagEnemy enemysArray[ENEMY_ARRAY_NUMS] = { {1},{2},{3} };
static struct tagEnemy *enemysPtrArray[ENEMY_ARRAY_NUMS];

struct tagEnemy **getEnemysArray() {
    int i;
	for( i=0 ; i<ENEMY_ARRAY_NUMS ; i++ ) {
		enemysPtrArray[i] = &enemysArray[i];
	}
	return enemysPtrArray;
}
 
void printEnemy(const struct tagEnemy *e) {
    if (e == NULL) {
        puts("null");
    } else {
        printf("%d\n", e->data);
    }
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 不完全型構造体のポインタが複数ほしい

#9

投稿記事 by softya(ソフト屋) » 5年前

あるいは敵構造体ポインタ自体を隠してしまって、外部には敵番号だけでやりとりするのも方法です。
その方が色々とシンプルかもしれません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ウーパールーパー山田
記事: 19
登録日時: 5年前

Re: 不完全型構造体のポインタが複数ほしい

#10

投稿記事 by ウーパールーパー山田 » 5年前

みけCAT さんが書きました: 指す先の型にかかわらず、ポインタはサイズが(環境によって)決まっています。
だから配列も作れます。
もしサイズが決まっていなかったら、単体の

コード:

struct tagEnemy *Enemy;
も定義できないのではないでしょうか?
そうでした 迂闊でした、、、
それと毎度毎度コードを書いてくださりありがとうございます すごく分かりやすいです!


softya(ソフト屋) さんが書きました:あるいは敵構造体ポインタ自体を隠してしまって、外部には敵番号だけでやりとりするのも方法です。
その方が色々とシンプルかもしれません。
先に挙げてくれた先頭ポインタを返却する方法もそうですがどの方法を使えば一番スマートに
書けるのか今、考えあぐねているところでしてまだ疑問に思うところがあって調べている最中ですので
「解決!」ボタンはまだ押しません ごめんなさい

閉鎖

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