構造体内の配列

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

構造体内の配列

#1

投稿記事 by tsutsu# » 14年前

typedef struct {
char field[15][10];
} FIELDSTATE;
FIELDSTATE f_state;

f_state.field[15][10] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15
};

これだと、構文エラーが出るんですが、だめなんですかね???

Blue

Re: 構造体内の配列

#2

投稿記事 by Blue » 14年前

配列の初期化リストの指定は変数宣言時のみ有効です。

int a[4];
a = {1, 2, 3, 4};

と構造体でなくても同じエラーになります。

Blue

Re: 構造体内の配列

#3

投稿記事 by Blue » 14年前

追記

コード:

FIELDSTATE f_state = {
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15
    }
};
と宣言時に初期化リストを指定すればよいかと。

もっとも全部 0 でいいなら
FIELDSTATE f_state = {0};
のみでよさげ。

tsutsu#

Re: 構造体内の配列

#4

投稿記事 by tsutsu# » 14年前

宣言をヘッターファイルに置くことは可能なんですかね???


なんとかそうしたいんですが....

Blue

Re: 構造体内の配列

#5

投稿記事 by Blue » 14年前

ヘッターファイルってなんでしょうか?

ちょっと質問内容が理解できないのですが、
もう少し、○○したいってことを具体的に説明してもらえませんかね?

tsutsu#

Re: 構造体内の配列

#6

投稿記事 by tsutsu# » 14年前

今テトリスを作っていまして、自分で作った*.hの中で
// フィールド
typedef struct {
char field[15][10];
} FIELDSTATE;
FIELDSTATE f_state = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 11
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 12
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 13
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 14
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15
};
を*.hで宣言すると構文エラーになるんですけど、*.cppだとエラーにならないんですよ、ただ自分は*.hで構造体を宣言したいんです。

Blue

Re: 構造体内の配列

#7

投稿記事 by Blue » 14年前

*.hをインクルードしている*.cppファイルはいくつありますか?
そしてどんなエラーがでているのでしょうか?




たぶん、extern指定子を使えばなんとかなるかと。
参考:http://www.geocities.jp/ky_webid/c/032.html

tsutsu#

Re: 構造体内の配列

#8

投稿記事 by tsutsu# » 14年前

*.hをインクルードしてるファイルは5個あります。
typedef struct {
char field[15][10];
} FIELDSTATE;
FIELDSTATE f_state = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 11
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 12
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 13
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 14
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15
};
このまま宣言すると、
構文エラー : '{'
'{' の前に予期しないトークンがありました。関数の本体は無視されます
'f_state' : 定義されていない識別子です。
'.field' の左側はクラス、構造体、共用体でなければなりません

maru
記事: 150
登録日時: 14年前

Re: 構造体内の配列

#9

投稿記事 by maru » 14年前

ヘッダーファイル(*.h)には

コード:

typedef struct {
char field[15][10];
} FIELDSTATE;
extern FIELDSTATE f_state;
ソースファイル(*.c)には

コード:

FIELDSTATE f_state = { 0 };
でいいはずです。
コンパイルしていないのでエラーが出たらごめんなさい。

tsutsu#

Re: 構造体内の配列

#10

投稿記事 by tsutsu# » 14年前

コード:

*.hで宣言して
typedef struct {
     char field[15][10];
} FIELDSTATE;
extern FIELDSTATE f_state; 

*.cで定義してみたら
FIELDSTATE f_state = { 0 }; 
ストレージクラスが正しくありませんと言われました。

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

Re: 構造体内の配列

#11

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

それで問題ないはずですので、ソースコード全体を提示したもらった方が良いかも知れません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

maru
記事: 150
登録日時: 14年前

Re: 構造体内の配列

#12

投稿記事 by maru » 14年前

tsutsu# さんが書きました: ストレージクラスが正しくありませんと言われました。
はて?
VC2010 でコンパイルしてみましたがC/C++どちらでも問題なくコンパイル/リンク出来ましたが...

コード:

/* a.h */
typedef struct {
     char field[15][10];
} FIELDSTATE;
extern FIELDSTATE f_state; 

/* a.c */
include "A.h"
FIELDSTATE f_state = { 0 }; 
int main()
{
	return 0;
}
a.cをa.cppにしてもコンパイルは通ります。

実際のコードとエラーメッセージを見せてください。

tsutsu#

Re: 構造体内の配列

#13

投稿記事 by tsutsu# » 14年前

コード:

// *.h
//モードの基底クラスとモード変更時のフェード処理	#ifndef __MODESTRUCT__H
#ifndef __MODESTRUCT__H
#define __MODESTRUCT__H
#include "DxLib/DxLib.h"

class ModeStructer {	// モードの基礎となる抽象クラス
protected:
	char* name;
	int number;
	int ForDecide;
	int ForCancel;
	int Submit_Decide;// FALSE->NG TRUE->OK
	int Submit_Cancel;// FALSE->NG TRUE->OK
public:
	ModeStructer::ModeStructer(){
		name = "enpty";
		number = -1;
		ForDecide = -1;
		ForCancel = -1;
		Submit_Decide = 0;
		Submit_Cancel = 0;
	}
	virtual ModeStructer::~ModeStructer(){	// 抽象クラスの仮想デストラクタ
	}
	void SetData ( char* s, int n, int d, int c ){
		name      = s;	// モードの名前
		number    = n;	// モードの番号
		ForDecide = d;	// デフォルト
		ForCancel = c;	// デフォルト
	}
	void setDecide(int d) {
		ForDecide = d;
	}
	void setCancel(int c) {
		ForDecide = c;
	}
	virtual void init() = 0;//画像や音声、その他の初期化
	virtual void enter() = 0;//モードに入る直前の処理
	virtual void action() = 0;//モード内の動作
	virtual void exit() = 0;//モードから抜ける直前の処理
	void dispName() { printfDx ( "%s\n", name); };
	void dispNumber() { printfDx ( "%d\n", number); };
};

class ModeChanger {
	int alpha;
	int phase;
	int Completed;
	int DecOrCan;
public:
	ModeChanger::ModeChanger() {
		alpha = 0;
		phase = 0;
		Completed = 0;
		DecOrCan = 0;
	};
	int Fade ( int, int );
	int FadeStream( int, int, int, int );
	int GetPhase() { return phase; };
	int GetComp() { return Completed; };
	void SetPhase(int p) { phase = p; };
};

// モードの派生クラス設計図をここにまとめる
// mainでnewするときに充てる番号を指定して書いておくこと

// モード番号 : 0
class Title : public ModeStructer {
	// 必須関数
public:
	virtual void init(); virtual void enter();
	virtual void action(); virtual void exit();
};
class Playing : public ModeStructer {
	// 構造体の定義と宣言わここ
	/* ゲームステータス */
	typedef struct {
		int Handle[5];
	} GLOBALSTATE;
	GLOBALSTATE g_state;

	/* フィールドステータス */
	typedef struct {
		char field[15][10];
	} FIELDSTATE;
	extern FIELDSTATE f_state;
	/*- ブロックステータス -*/
	typedef struct {
		int xPos, yPos;
		int Speed;
		int Handle[7];
		int no;
	} TETRISPLAYSTATE;
	TETRISPLAYSTATE t_state;
public:
	// 関数定義わここ
	virtual void init(); virtual void enter();
	virtual void action(); virtual void exit();

	void TetrisMain ();
	void BlockDisplay ( char(*field)[10], int Handle );

};

#endif



// *.c
#include "header/ModeStructer.h"
#include "header/extern.h"
#pragma warning (disable : 4244)

//ModeStructerクラスを継承し、各々のモード処理をactionとする
//そのモードで必要なメンバ変数の初期化、画像の読み込み
void Playing::init() {
	// 基本的に画像の読み込みのみ
	/*- 背景・ステータス -*/
	g_state.Handle[0] = LoadGraph("data/bg.bmp");

	/*- プレイヤ~ -*/
	LoadDivGraph("data/parts.bmp", 7, 7, 1, 32, 32, t_state.Handle);
}

// モードに入るたびに行われる初期化
void Playing::enter() {
	// 決定もしくはキャンセルして次のモードに行く事を許可するか禁止するか決めておきます
	// 変数初期化わここ
	Submit_Decide = FALSE;
	Submit_Cancel = FALSE;
	// ブロックステータス
	t_state.xPos = 3;
	t_state.yPos = 0;
	t_state.Speed = 40;
	t_state.no = 0;
}
void Playing::action() {
	printfDx("プレイ中\n");
/*--------------------
*		GAMEMAIN	 *
----------------------
*/
	DrawGraph( 0, 0, g_state.Handle[0], TRUE );
	// フィールドステータス

	TetrisMain ( );
}

// モードを出た後の初期化
void Playing::exit() {
}

/*-------------------------------
*	関数名 : TetrisMain ( )		*
*	概要   : テトリスメイン		*
---------------------------------
-*/
void Playing::TetrisMain ( )
{
	char BlockShape[][6] = {
		{-1,  0,  1,  0,  0,  1},   // Block 1
		{ 0, -1,  0,  1,  1,  0},   // Block 2
		{ 0, -1, -1,  0,  1,  0},   // Block 3
		{ 0, -1,  0,  1, -1,  0},   // Block 4
	};
	t_state.Speed--;
	if( t_state.Speed == 0 ){
		t_state.Speed = 40;
		f_state.field[t_state.yPos][t_state.xPos] = 0;
		if( t_state.yPos < 14 ){
			t_state.yPos++;
		}
	}
	f_state.field[t_state.yPos][t_state.xPos] = 1;

	for( int i = 0; i < 15; i++ ){
		for( int j = 0; j < 10; j++ ){
			if( f_state.field[i][j] != 0 ){
				DrawGraph( (j * 32), i * 32, t_state.Handle[0], FALSE );
			}
		}
	}
}
こんな感じです。これだけでは動かないのでご了承願います。

エラーコードは : 1>h:\project01\source\header\modestructer.h(86) : error C2071: 'Playing::f_state' : ストレージ クラスが正しくありません。
が出ます。

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

Re: 構造体内の配列

#14

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

エラーの原因は、C++のクラス定義の中でグローバル変数として定義しようとしているからです。
クラスのメンバ変数として定義したいなら、

コード:

    typedef struct {
        char field[15][10];
    } FIELDSTATE;
は外に出して、

コード:

    extern FIELDSTATE f_state;
は
 FIELDSTATE f_state;
として下さい。
この場合は、初期値は宣言できないので、コンストラクタで初期化してください。

【修正】
あるいは、今の形のままクラス宣言の外に全て出してしまうかです。
これだとクラス定義されないグローバルな変数になります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Blue

Re: 構造体内の配列

#15

投稿記事 by Blue » 14年前

f_stateはメンバですのでクラスごと違う値を持ちたいということであれば、
externはとって、コンストラクタで初期化してください。
だたし、前述の通り、宣言時にしか初期化リストは使えないので、memsetとかを使って0で初期化してください。

グローバル変数のように、クラスごと違う値でなくてもよいのであれば、
staticメンバ変数にして、*.cppで実態を定義してください。

閉鎖

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