ページ 1 / 1
構造体内の配列
Posted: 2011年1月13日(木) 11:15
by tsutsu#
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
};
これだと、構文エラーが出るんですが、だめなんですかね???
Re: 構造体内の配列
Posted: 2011年1月13日(木) 11:40
by Blue
配列の初期化リストの指定は変数宣言時のみ有効です。
int a[4];
a = {1, 2, 3, 4};
と構造体でなくても同じエラーになります。
Re: 構造体内の配列
Posted: 2011年1月13日(木) 11:43
by Blue
追記
コード:
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};
のみでよさげ。
Re: 構造体内の配列
Posted: 2011年1月13日(木) 14:06
by tsutsu#
宣言をヘッターファイルに置くことは可能なんですかね???
なんとかそうしたいんですが....
Re: 構造体内の配列
Posted: 2011年1月13日(木) 14:09
by Blue
ヘッターファイルってなんでしょうか?
ちょっと質問内容が理解できないのですが、
もう少し、○○したいってことを具体的に説明してもらえませんかね?
Re: 構造体内の配列
Posted: 2011年1月13日(木) 14:17
by tsutsu#
今テトリスを作っていまして、自分で作った*.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で構造体を宣言したいんです。
Re: 構造体内の配列
Posted: 2011年1月13日(木) 14:25
by Blue
*.hをインクルードしている*.cppファイルはいくつありますか?
そしてどんなエラーがでているのでしょうか?
たぶん、extern指定子を使えばなんとかなるかと。
参考:
http://www.geocities.jp/ky_webid/c/032.html
Re: 構造体内の配列
Posted: 2011年1月13日(木) 14:41
by tsutsu#
*.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' の左側はクラス、構造体、共用体でなければなりません
Re: 構造体内の配列
Posted: 2011年1月13日(木) 16:22
by maru
ヘッダーファイル(*.h)には
コード:
typedef struct {
char field[15][10];
} FIELDSTATE;
extern FIELDSTATE f_state;
ソースファイル(*.c)には
コード:
FIELDSTATE f_state = { 0 };
でいいはずです。
コンパイルしていないのでエラーが出たらごめんなさい。
Re: 構造体内の配列
Posted: 2011年1月13日(木) 16:41
by tsutsu#
コード:
*.hで宣言して
typedef struct {
char field[15][10];
} FIELDSTATE;
extern FIELDSTATE f_state;
*.cで定義してみたら
FIELDSTATE f_state = { 0 };
ストレージクラスが正しくありませんと言われました。
Re: 構造体内の配列
Posted: 2011年1月13日(木) 16:54
by softya(ソフト屋)
それで問題ないはずですので、ソースコード全体を提示したもらった方が良いかも知れません。
Re: 構造体内の配列
Posted: 2011年1月13日(木) 17:05
by maru
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にしてもコンパイルは通ります。
実際のコードとエラーメッセージを見せてください。
Re: 構造体内の配列
Posted: 2011年1月13日(木) 17:15
by tsutsu#
コード:
// *.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' : ストレージ クラスが正しくありません。
が出ます。
Re: 構造体内の配列
Posted: 2011年1月13日(木) 17:24
by softya(ソフト屋)
エラーの原因は、C++のクラス定義の中でグローバル変数として定義しようとしているからです。
クラスのメンバ変数として定義したいなら、
コード:
typedef struct {
char field[15][10];
} FIELDSTATE;
は外に出して、
コード:
extern FIELDSTATE f_state;
は
FIELDSTATE f_state;
として下さい。
この場合は、初期値は宣言できないので、コンストラクタで初期化してください。
【修正】
あるいは、今の形のままクラス宣言の外に全て出してしまうかです。
これだとクラス定義されないグローバルな変数になります。
Re: 構造体内の配列
Posted: 2011年1月13日(木) 17:50
by Blue
f_stateはメンバですのでクラスごと違う値を持ちたいということであれば、
externはとって、コンストラクタで初期化してください。
だたし、前述の通り、宣言時にしか初期化リストは使えないので、memsetとかを使って0で初期化してください。
グローバル変数のように、クラスごと違う値でなくてもよいのであれば、
staticメンバ変数にして、*.cppで実態を定義してください。