ファイル分割をして関数を使用しようとしたのですがうまくいきません

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

ファイル分割をして関数を使用しようとしたのですがうまくいきません

#1

投稿記事 by 輪入道 » 12年前

マウスの入力テストとファイル分割の練習として、マウスの左ボタンが押された瞬間に何か処理をするプログラムを作っております。
ファイル分割をして「Mouse.cpp」、「Mouse.h」、「main.cpp」の3つに分け、処理をさせようとしています。
左ボタンが押された瞬間の処理は2.9章の方法を参考にさせていただきました。

コードは以下の通りです。
[Mouse.cpp]

コード:

#include "DxLib.h"

//マウスの入力状態更新
void Mouse_Update(){
	
	int MouseX, MouseY ;
	int MouseLeftInput = 0 ;
	
	SetMouseDispFlag( TRUE );	//マウスカーソルを表示状態にする
	
	GetMousePoint( &MouseX, &MouseY );	//マウスの位置を取得
	
	if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){	//左ボタンが押されているか確認する
		MouseLeftInput++;
	}
	else{
		MouseLeftInput=0;
	}

}
[Mouse.h]

コード:

#ifndef DEF_MOUSE_H	//二重include防止

#define DEF_MOUSE_H

//マウスの入力状態を更新する
void Mouse_Update();

#endif
[main.cpp]

コード:

#include "DxLib.h"
#include "Mouse.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
	ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK );

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
		Mouse_Update();		//マウスの更新
	}

	if( MouseLeftInput == 1 ){   //左ボタンが押された瞬間
	//処理
	}

	DxLib_End();
	return 0;
}
これで実行すると、main.cppの11行目で次のエラーがでます。
「error C2065: 'MouseLeftInput' : 定義されていない識別子です。」

なぜこのようなエラーが出るのでしょうか?
このエラーの解決方法がわかりません。
ちなみに、Mouse_Update関数の変数の宣言に「extern」をつけても上のエラーが出ます。

私は「やさしいC」という本を一通り読み、管理人様のサイトも目を通しましたが、応用力が乏しく、実践的なプログラミングには全く未熟です。
コンパイラはVC++ 2010 Express、OSはWindows vistaです。
初歩的な質問で申し訳ありませんが、ご助言をお願いします。

derok
記事: 51
登録日時: 12年前

Re: ファイル分割をして関数を使用しようとしたのですがうまくいきません

#2

投稿記事 by derok » 12年前

MouseLeftInputはローカル変数のため、外部から参照することはできません。
グローバル領域で定義して、ヘッダーファイルにint MouseLeftInput=0;と書いて下さい。
後、

コード:

 
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
       Mouse_Update();     //マウスの更新
}
 
if( MouseLeftInput == 1 ){   //左ボタンが押された瞬間
    //処理
}
ですけど、メインループの外側で処理をしても意味は無いと思いますが。
後、あまりexternは使うべきではないと思います。

コード:

int GetMouseLeftInput(){
	return MouseLeftInput;
}
を使った方がいいと思います。

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

Re: ファイル分割をして関数を使用しようとしたのですがうまくいきません

#3

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

これは実行エラーではなくリンクエラーですね。実行まで到達していません。
「やさしいC」にも解説があると思いますが、変数のスコープと寿命の理解が不十分なので問題点が理解できないんだと思います。

さて、エラーとなっているMouseLeftInputですが、定義をみるとMouse_Update()のローカル変数となっています。
つまり、Mouse_Update()関数に入った特に作成され関数を抜けるまでの生存寿命の変数ですので、寿命的に外部から参照することはできません。
それとローカル変数のスコープは{}内に限定されるの、これも同様にMouse_Update()関数内でしかMouseLeftInputは参照できません。
2重に参照不能な条件が揃っていますのでWinMain()から参照することは不可能なのです。

「変数の記憶寿命とスコープ」 ※ 重要ポイント!
http://www2.ee.knct.ac.jp/el/E3/E305/lifeandscope.html
ちなみに、Mouse_Update関数の変数の宣言に「extern」をつけても上のエラーが出ます。
これは、Mouse_Update関数だけの宣言ですので、MouseLeftInputには一切影響を与えません。

それよりも心配なのでは、
if( MouseLeftInput == 1 ){ //左ボタンが押された瞬間
//処理
}
この処理がWinMain()のループの外にあることです。
これは処理の順番がよく理解できていない事を示しています。
こちらの方が基礎部分において実に大きな問題です。

プログラムの学習の過程において
1.mainだけでプログラムを書く。
2.1つのファイルで関数分割して書く
3.ファイル分割をして書く。
の段階を踏んでいないのでは無いかと思いますので、順番を踏んで理解されることをオススメします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: ファイル分割をして関数を使用しようとしたのですがうまくいきません

#4

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

derok さんが書きました:MouseLeftInputはローカル変数のため、外部から参照することはできません。
グローバル領域で定義して、ヘッダーファイルにint MouseLeftInput=0;と書いて下さい。
それだとエラーになりますので、ヘッダに初期値を書いてはいけません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

derok
記事: 51
登録日時: 12年前

Re: ファイル分割をして関数を使用しようとしたのですがうまくいきません

#5

投稿記事 by derok » 12年前

softya(ソフト屋) さんが書きました:
derok さんが書きました:MouseLeftInputはローカル変数のため、外部から参照することはできません。
グローバル領域で定義して、ヘッダーファイルにint MouseLeftInput=0;と書いて下さい。
それだとエラーになりますので、ヘッダに初期値を書いてはいけません。
すいません、勘違いしてました。
でもエラー起きなかったんですよね・・

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

Re: ファイル分割をして関数を使用しようとしたのですがうまくいきません

#6

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

1ファイルしかヘッダをインクルードしていない場合に限定して言えばエラーは起きません。
ファイルが増えてヘッダをインクルードしてるファイルが2つ以上になるとエラーとなります。
試しにmain.cppとMouse.cppの両方で初期値を書いたMouse.hをインクルードしてみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

derok
記事: 51
登録日時: 12年前

Re: ファイル分割をして関数を使用しようとしたのですがうまくいきません

#7

投稿記事 by derok » 12年前

softya(ソフト屋) さんが書きました:1ファイルしかヘッダをインクルードしていない場合に限定して言えばエラーは起きません。
ファイルが増えてヘッダをインクルードしてるファイルが2つ以上になるとエラーとなります。
試しにmain.cppとMouse.cppの両方で初期値を書いたMouse.hをインクルードしてみてください。
そうなんですか、あまりヘッダーファイルで変数を宣言しないのでを知りませんでした。
今後、このようなことがない様に気をつけます。

輪入道

Re: ファイル分割をして関数を使用しようとしたのですがうまくいきません

#8

投稿記事 by 輪入道 » 12年前

回答ありがとうございました!
すみません、if文がメインループの外にあるのはケアレスミスでした、気をつけます。
derok さんが書きました:

コード:

int GetMouseLeftInput(){
	return MouseLeftInput;
}
を使った方がいいと思います。
なるほど!この方法でできました。
softya(ソフト屋) さんが書きました:これは実行エラーではなくリンクエラーですね。実行まで到達していません。
「やさしいC」にも解説があると思いますが、変数のスコープと寿命の理解が不十分なので問題点が理解できないんだと思います。

さて、エラーとなっているMouseLeftInputですが、定義をみるとMouse_Update()のローカル変数となっています。
つまり、Mouse_Update()関数に入った特に作成され関数を抜けるまでの生存寿命の変数ですので、寿命的に外部から参照することはできません。
それとローカル変数のスコープは{}内に限定されるの、これも同様にMouse_Update()関数内でしかMouseLeftInputは参照できません。
2重に参照不能な条件が揃っていますのでWinMain()から参照することは不可能なのです。
分かりやすい説明ありがとうございます。
なぜ変数が参照できなかったのか、よく理解できました。
softya(ソフト屋) さんが書きました: 1.mainだけでプログラムを書く。
2.1つのファイルで関数分割して書く
3.ファイル分割をして書く。
なるほど、いきなりファイル分割から始めてました。
まずはmainだけから始めてみます。

ヘッダで初期化をしてはいけないというのも勉強になりました。
お二方とも回答ありがとうございました!

閉鎖

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