自作関数について

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

自作関数について

#1

投稿記事 by dast » 14年前

しつこいほど何度もお世話になっています。プログラミングの勉強をしている者です。
一度基本を見直した方がいいと言われたので基本的な構文を使って参考書を読みながらプログラムを作っていたのですが、最初に次のようなプログラムを作りました。この時点では普通にビルドできましたし考えていたとおりの動き(ゲームの枠と背景を描画し、その中にいるキャラクターが左右のキー入力に合わせて動くというものです)もしました。

main.cpp

コード:

#define GLOBAL_INSTANCE
#include "ヘッダー/GLOBAL_int.h"

int Key[256];
int gpUpdateKey(){
	char tmpKey[256];
	GetHitKeyStateAll(tmpKey);
	for(int i=0;i<256;i++){
		if(tmpKey[i]!=0){
			Key[i]++;
		}else{
			Key[i]=0;
		}
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen(DX_SCREEN_BACK); // ウィンドウモードに設定,DXライブラリ初期化処理,描写先を裏画面に設定




		board = LoadGraph("画像/ボード/枠.png");//枠をboardにロードする
		back5 = LoadGraph("画像/背景/1.png");
		deta_board = LoadGraph("画像/ボード/パラメータ表示部分.png");//パラメータ表示部分をdeta_boardにロードする
		LoadDivGraph("画像/キャラクタ/ドット/自機.png",12,4,3,38,41,ziki);//自機の画像を12分割してロード
	    img = (cnt%48)/12;
		while(ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0){
			DrawGraph(20,80,back5,TRUE);//背景の描写


			DrawRotaGraph(x,444,1.0,0.0,ziki[img],TRUE);//自機の描写
			img = (cnt%48)/12;
			cnt++;

			DrawGraph(0,0,board,TRUE);//枠を描写
			DrawGraph(20,15,deta_board,TRUE);//パラメータ表示部分を描写

			if(Key[KEY_INPUT_LEFT]>=1 && x>=MIN_X && Key[KEY_INPUT_RIGHT]==0){
				img+=8;
				x-=2;
			}
			if(Key[KEY_INPUT_RIGHT]>=1 && x<=MAX_X && Key[KEY_INPUT_LEFT]==0){
				img+=4;
				x+=2;
			}
		}
        DxLib_End();    // DXライブラリ終了処理
        return 0;
}
GLOBAL_int.h

コード:

#include "DxLib.h"

#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL exturn
#endif



GLOBAL int board;//枠用変数
GLOBAL int back5;//1面背景用変数
GLOBAL int deta_board;//パラメータ表示部分用変数
GLOBAL int ziki[12];//自機用変数
GLOBAL int x=320;//自機の位置 初期位置320
GLOBAL int MAX_X=619;//移動領域 右端
GLOBAL int MIN_X=20;//移動領域 左端
GLOBAL int cnt=0;//画像ループ用変数1
GLOBAL int img;//画像ループ用変数2

ですがこのままだとmain.cppの中身が長すぎると感じたので、とりあえず画像のロード部分(main.cppの24~27行目)を他のソースに分けようと次のようにしました

main.cpp

コード:

#define GLOBAL_INSTANCE
#include "ヘッダー/GLOBAL_int.h"

int Key[256];
int gpUpdateKey(){
	char tmpKey[256];
	GetHitKeyStateAll(tmpKey);
	for(int i=0;i<256;i++){
		if(tmpKey[i]!=0){
			Key[i]++;
		}else{
			Key[i]=0;
		}
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen(DX_SCREEN_BACK); // ウィンドウモードに設定,DXライブラリ初期化処理,描写先を裏画面に設定

		extern void load_img();
	    img = (cnt%48)/12;
		while(ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0){
			DrawGraph(20,80,back5,TRUE);//背景の描写


			DrawRotaGraph(x,444,1.0,0.0,ziki[img],TRUE);//自機の描写
			img = (cnt%48)/12;
			cnt++;

			DrawGraph(0,0,board,TRUE);//枠を描写
			DrawGraph(20,15,deta_board,TRUE);//パラメータ表示部分を描写

			if(Key[KEY_INPUT_LEFT]>=1 && x>=MIN_X && Key[KEY_INPUT_RIGHT]==0){
				img+=8;
				x-=2;
			}
			if(Key[KEY_INPUT_RIGHT]>=1 && x<=MAX_X && Key[KEY_INPUT_LEFT]==0){
				img+=4;
				x+=2;
			}
		}
        DxLib_End();    // DXライブラリ終了処理
        return 0;
}
GLOBAL.h

コード:

#include "DxLib.h"

#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL exturn
#endif



GLOBAL int board;//枠用変数
GLOBAL int back5;//1面背景用変数
GLOBAL int deta_board;//パラメータ表示部分用変数
GLOBAL int ziki[12];//自機用変数
GLOBAL int x=320;//自機の位置 初期位置320
GLOBAL int MAX_X=619;//移動領域 右端
GLOBAL int MIN_X=20;//移動領域 左端
GLOBAL int cnt=0;//画像ループ用変数1
GLOBAL int img;//画像ループ用変数2

load.cpp

コード:

#include"../ヘッダー/GLOBAL_int.h"

void load_img(){
board = LoadGraph("画像/ボード/枠.png");//枠をboardにロードする
back5 = LoadGraph("画像/背景/1.png");
deta_board = LoadGraph("画像/ボード/パラメータ表示部分.png");//パラメータ表示部分をdeta_boardにロードする
LoadDivGraph("画像/キャラクタ/ドット/自機.png",12,4,3,38,41,ziki);//自機の画像を12分割してロード
}
そうしたらビルド時に大量のエラーが出ました。それも変更する前には何のエラーも起きず、今回の変更において一切手を加えていないGLOBAL.hに関してです。そのときのエラーメッセージは次の通りです

コード:

1>コンパイルしています...
1>main.cpp
1>load.cpp
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : error C2144: 構文エラー : 'int' は ';' によって先行されなければなりません。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(12) : error C2144: 構文エラー : 'int' は ';' によって先行されなければなりません。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(12) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(12) : error C2086: 'int exturn' : 再定義されました。
1>        c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : 'exturn' の宣言を確認してください。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(13) : error C2144: 構文エラー : 'int' は ';' によって先行されなければなりません。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(13) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(13) : error C2086: 'int exturn' : 再定義されました。
1>        c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : 'exturn' の宣言を確認してください。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(14) : error C2144: 構文エラー : 'int' は ';' によって先行されなければなりません。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(14) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(14) : error C2086: 'int exturn' : 再定義されました。
1>        c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : 'exturn' の宣言を確認してください。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(15) : error C2144: 構文エラー : 'int' は ';' によって先行されなければなりません。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(15) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(15) : error C2086: 'int exturn' : 再定義されました。
1>        c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : 'exturn' の宣言を確認してください。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(16) : error C2144: 構文エラー : 'int' は ';' によって先行されなければなりません。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(16) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(16) : error C2086: 'int exturn' : 再定義されました。
1>        c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : 'exturn' の宣言を確認してください。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(17) : error C2144: 構文エラー : 'int' は ';' によって先行されなければなりません。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(17) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(17) : error C2086: 'int exturn' : 再定義されました。
1>        c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : 'exturn' の宣言を確認してください。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(18) : error C2144: 構文エラー : 'int' は ';' によって先行されなければなりません。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(18) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(18) : error C2086: 'int exturn' : 再定義されました。
1>        c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : 'exturn' の宣言を確認してください。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(19) : error C2144: 構文エラー : 'int' は ';' によって先行されなければなりません。
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(19) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(19) : error C2086: 'int exturn' : 再定義されました。
1>        c:\users\pcuser\documents\visual studio 2008\projects\game\ヘッダー\global_int.h(11) : 'exturn' の宣言を確認してください。
いったいどうしたらロード部分を他のソースに置きながらプログラムをいじる前と同じ動作をさせることができるでしょうか?
ご鞭撻のほどよろしくお願いします。

box
記事: 2002
登録日時: 15年前

Re: 自作関数について

#2

投稿記事 by box » 14年前

exturn
という予約語はありません。
つづりを確認してください。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

box
記事: 2002
登録日時: 15年前

Re: 自作関数について

#3

投稿記事 by box » 14年前

あと、よけいなお世話かもしれませんが、基本的な文法を勉強するのであれば、
 ・ゲームプログラミングの要素
 ・Windowsプログラミングの要素
という、基本的な文法と直接関係ない部分はできれば取り払う方が
いいのではないかと思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

dast

Re: 自作関数について

#4

投稿記事 by dast » 14年前

おっしゃる通りGLOBAL_int.h6行目のexternをexturnと書き間違えていました。
それで書き直したところ、今度はまた別のエラーメッセージが出てきました。

コード:

1>コンパイルしています...
1>main.cpp
1>load.cpp
1>コードを生成中...
1>リンクしています...
1>load.obj : error LNK2005: "int x" (?x@@3HA) は既に main.obj で定義されています。
1>load.obj : error LNK2005: "int MAX_X" (?MAX_X@@3HA) は既に main.obj で定義されています。
1>load.obj : error LNK2005: "int MIN_X" (?MIN_X@@3HA) は既に main.obj で定義されています。
1>load.obj : error LNK2005: "int cnt" (?cnt@@3HA) は既に main.obj で定義されています。
1>C:\Users\PCUser\Documents\Visual Studio 2008\Projects\GAME\Debug\GAME.exe : fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。
「変数のいくつかがもう定義されているよ」みたいなことが書かれているようなのですが私はGLOBAL.h以外の場所でこれらの変数を定義した覚えが無いのですが、ひょっとしてmain.cppでのif文の条件指定が定義とみなされているのでしょうか?
この場合どうしたらいいのでしょうか?

追記
>>基本的な文法を勉強するのであれば基本的な文法と直接関係ない部分はできれば取り払う方が
いいのではないかと思います。

助言していただき誠にありがとうございます。是非そうしていきたいと思います。
ただその傍らでこちらのプログラムも引き続き弄っていきたいと思います。これも趣味なので。
その際しょうもなかったり脳が足りていないような質問をしていくことになると思うので今後もよろしくお願いします。
(嫌だと言われれば返す言葉もありませんが……)

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

Re: 自作関数について

#5

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

main.objとload.obj に同時に同じ名前の実体があると言うエラーですね。
ヘッダで実体が必要な初期値が書かれているのか問題だと思います。

コード:

GLOBAL int x=320;//自機の位置 初期位置320
GLOBAL int MAX_X=619;//移動領域 右端
GLOBAL int MIN_X=20;//移動領域 左端
GLOBAL int cnt=0;//画像ループ用変数1
なにかワーニングエラーは出てませんでしたか?
初期値はヘッダに書かないでください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

box
記事: 2002
登録日時: 15年前

Re: 自作関数について

#6

投稿記事 by box » 14年前

コード:

    extern int n = 100;
は、どこか別のファイルで定義してある変数nを使う、というextern本来の意味だけでなく、
変数nの定義と初期化も行なっています。
ところが、変数nはすでに別のファイルで定義済みです。よって、「多重定義」という意味のリンクエラーが出ているのだと思います。

下記のプログラムは正しく動きます。
main.c

コード:

#include <stdio.h>

int n = 100;

void f(void);

int main(void)
{
    f();
    return 0;
}
func.c

コード:

#include <stdio.h>

extern int n; // 別のファイルで定義してあるnをここで使う、という意味

void f(void)
{
    printf("n=%d\n", n);
}
ところが、下記のプログラムは「nを多重定義している」という意味のリンクエラーが出ます。
main.c

コード:

#include <stdio.h>

int n = 100;

void f(void);

int main(void)
{
    f();
    return 0;
}
func.c

コード:

#include <stdio.h>

extern int n = 100; 

void f(void)
{
    printf("n=%d\n", n);
}
質問者さんの今の状態は、まさに後の方のコードと同じですね。
ゲームプログラミングやWindowsプログラミングの要素をすべて取り払った上記の単純なコードで、
両者の違いを研究してみてはいかがでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

閉鎖

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