ページ 1 / 1
不完全型構造体のポインタが複数ほしい
Posted: 2015年8月04日(火) 23:46
by ウーパールーパー山田
コード:
struct tagEnemy *Enemy;
データ隠蔽のために不完全型構造体を使っていますが
例えば上記のソースコードの場合、敵をたくさん出現させたいときに配列を使いたいですが構造体のサイズが分からないので配列は使えません
がんばってポインタ一つ一つに命名していってもいいのですが
それだと配列の添字とfor文を使った場合のように敵の処理を一度に済ませることができません
なにか良い方法はないのでしょうか?それとも複数のオブジェクトが欲しい場合に不完全型構造体を使うのが間違いなのでしょうか?
投げやりなのですが自分ではどんなに考えても調べても解決できませんでした
ご教授よろしくお願いします
Re: 不完全型構造体のポインタが複数ほしい
Posted: 2015年8月04日(火) 23:58
by softya(ソフト屋)
そういう場合に使われるのが、ポインタを使ったリスト構造です。
struct tagEnemyの実体はmallocして、リスト構造体自体もmallocします。リスト構造体には、次のリスト構造体ポインタとstruct tagEnemy *Enemy;を持てば良いでしょう。
http://www9.plala.or.jp/sgwr-t/c/sec15-5.html
C++ならstd::listなど便利なライブラリがあるんですが、C言語は自分で実装してください。
Re: 不完全型構造体のポインタが複数ほしい
Posted: 2015年8月05日(水) 00:02
by みけCAT
素直にポインタの配列ではダメなのでしょうか?
コード:
#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);
}
}
Re: 不完全型構造体のポインタが複数ほしい
Posted: 2015年8月05日(水) 00:05
by softya(ソフト屋)
敵の数の上限が決まっているなら、みけCATさんの方法をおすすめします。その方法の方がバグが少ないですから。[誤字修正]
【ご指摘ありがとうございます。敬称がもれておりました。みけCATさんすいません。】
Re: 不完全型構造体のポインタが複数ほしい
Posted: 2015年8月05日(水) 00:32
by 超初級者
他の人のハンドルに敬称が付いていないのは
誤字ではないのかな?
Re: 不完全型構造体のポインタが複数ほしい
Posted: 2015年8月05日(水) 09:48
by ウーパールーパー山田
質問する前にみけCATさんのやりかたで試していたのですがコンパイルが通りませんでした
ですが、どうやらポインタ配列とは関係ないところの記述ミスが原因でコンパイルが通らなかったようです
お手数おかけしました 本当にすみません
(配列はサイズが分からないと宣言できないから、たとえ不完全構造体のポインタでも配列は作れないのかという
思い込みが自分の中にあったので記述ミスを探すのを怠っていました)
ただ、疑問なのですがお二人ともmallocを使用していますが、mallocを使用しない方法でもいいのでしょうか?
例えばtagEnemy構造体が定義されているファイルにstaticなtagEnemy構造体の実体を
置いておいて、その実体のアドレスをみけCATさんのコードでいうgenerateEnemy()で返してあげるという方法はアリでしょうか?
(みけCATさんのコードでいうとtagEnemyが定義されているファイルにstatic struct tagEnemy Enemy[3];と書いてあるということです)
キャラクターの表示数は決まっています 動的に要素数を変更する必要はないです
Re: 不完全型構造体のポインタが複数ほしい
Posted: 2015年8月05日(水) 10:51
by みけCAT
ウーパールーパー山田 さんが書きました:質問する前にみけ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);
}
}
Re: 不完全型構造体のポインタが複数ほしい
Posted: 2015年8月05日(水) 11:02
by softya(ソフト屋)
実体が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);
}
}
Re: 不完全型構造体のポインタが複数ほしい
Posted: 2015年8月05日(水) 11:05
by softya(ソフト屋)
あるいは敵構造体ポインタ自体を隠してしまって、外部には敵番号だけでやりとりするのも方法です。
その方が色々とシンプルかもしれません。
Re: 不完全型構造体のポインタが複数ほしい
Posted: 2015年8月11日(火) 00:16
by ウーパールーパー山田
みけCAT さんが書きました:
指す先の型にかかわらず、ポインタはサイズが(環境によって)決まっています。
だから配列も作れます。
もしサイズが決まっていなかったら、単体の
コード:
struct tagEnemy *Enemy;
も定義できないのではないでしょうか?
そうでした 迂闊でした、、、
それと毎度毎度コードを書いてくださりありがとうございます すごく分かりやすいです!
softya(ソフト屋) さんが書きました:あるいは敵構造体ポインタ自体を隠してしまって、外部には敵番号だけでやりとりするのも方法です。
その方が色々とシンプルかもしれません。
先に挙げてくれた先頭ポインタを返却する方法もそうですがどの方法を使えば一番スマートに
書けるのか今、考えあぐねているところでしてまだ疑問に思うところがあって調べている最中ですので
「解決!」ボタンはまだ押しません ごめんなさい