ヘッダファイル
ヘッダファイル
シューティングの館にあるように、ヘッダファイルをつかって構造体を呼び出すと言う事をしようとしています。
/* kouzou.h */
typedef struct{
double x,y,size;
int flag;
double angle;
}Player;
Player nz;
typedef struct{
int flag,pattern;
int x,y,size;
}Tama;
Tama t;
/*extern.h*/
typedef struct{
double x,y,size;
int flag;
double angle;
}Player;
extern Player nz;
typedef struct{
int flag,pattern;
int x,y,size;
}Tama;
extern Tama t;
コンパイルすると、
'Player' : 再定義されています。異なる基本型です。
'Tama' : 再定義されています。異なる基本型です。
とエラーが出てきてしまいます。
ググッてみてもさっぱり原因が分かりません。
一体どうしたらいいでしょうか?
OSはXPで、コンパイラがVisual C++2005です。
/* kouzou.h */
typedef struct{
double x,y,size;
int flag;
double angle;
}Player;
Player nz;
typedef struct{
int flag,pattern;
int x,y,size;
}Tama;
Tama t;
/*extern.h*/
typedef struct{
double x,y,size;
int flag;
double angle;
}Player;
extern Player nz;
typedef struct{
int flag,pattern;
int x,y,size;
}Tama;
extern Tama t;
コンパイルすると、
'Player' : 再定義されています。異なる基本型です。
'Tama' : 再定義されています。異なる基本型です。
とエラーが出てきてしまいます。
ググッてみてもさっぱり原因が分かりません。
一体どうしたらいいでしょうか?
OSはXPで、コンパイラがVisual C++2005です。
Re:ヘッダファイル
> コンパイルすると、
当該のヘッダーファイル群をインクルードしている
ソースファイルの中身はどうなっていますか?
ヘッダーファイルだけ見ても、「同じ構造体を
複数のヘッダーファイルで定義していると、
保守しづらくて仕様変更に弱いだろうなあ」ということがわかるだけです。
当該のヘッダーファイル群をインクルードしている
ソースファイルの中身はどうなっていますか?
ヘッダーファイルだけ見ても、「同じ構造体を
複数のヘッダーファイルで定義していると、
保守しづらくて仕様変更に弱いだろうなあ」ということがわかるだけです。
Re:ヘッダファイル
両方のヘッダーファイルに定義しているからエラーがでます。
片方の構造体を削除し、ヘッダーファイルの先頭に
#include"削除しなかったほうのヘッダーファイル"
としてください。
片方の構造体を削除し、ヘッダーファイルの先頭に
#include"削除しなかったほうのヘッダーファイル"
としてください。
Re:ヘッダファイル
やってみました。
ご教授願います。
/*extern.h*/ #include "kouzou.h" extern Player nz; extern Tama t; /*kouzou.h*/ typedef struct{ double x,y,size; int flag; double angle; }Player; Player nz; typedef struct{ int flag,pattern; int x,y,size; }Tama; Tama t; "struct Player nz" (?nz@@3UPlayer@@A) は既に main.obj で定義されています。 "struct Tama t" (?t@@3UTama@@A) は既に main.obj で定義されています。 1 つ以上の複数回定義されているシンボルが見つかりました。 とでてきてしまいます。 もしかしたらソースに問題があるかもしれないので長くなりますがソースも載せておきます。 /*main.cpp*/ #include "DxLib.h" #include <math.h> #include "extern.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){ ChangeWindowMode(TRUE); if( DxLib_Init()==-1)return -1; SetDrawScreen(DX_SCREEN_BACK); extern void fps(); extern void fpscolor(); extern void enemy1(); int image[2]; char Key[256]; int GHandle; nz.x=320; nz.y=120; nz.angle=180; nz.size=10; nz.flag=1; // 読み込み GHandle=LoadGraph("nz.png"); LoadDivGraph("back.png",2,2,1,640,480,image); fpscolor(); while(!ProcessMessage() && !ClearDrawScreen()) { GetHitKeyStateAll(Key); int RefreshTime; RefreshTime=GetNowCount(); //左回転 if(Key[KEY_INPUT_LEFT]==1){ nz.angle=nz.angle+10; //回転に制限 if(nz.angle>=250){nz.angle=250;} } //右回転 if(Key[KEY_INPUT_RIGHT]==1){ nz.angle=nz.angle-10; //回転に制限 if(nz.angle<=120){nz.angle=120;} } //自機移動 nz.x=nz.x+sin((3.141592/180.0)*nz.angle)*5; //左の壁に当たって勝手に曲がる if(nz.x<=130){ nz.x=130; nz.angle=nz.angle-10; if(nz.angle<=180){nz.angle=180;} } //右の壁に当たって勝手に曲がる if(nz.x>=510){ nz.x=510; nz.angle=nz.angle+10; if(nz.angle>=180){nz.angle=180;} } //背景 DrawGraph(0,0,image[1],FALSE); DrawGraph(0,0,image[0],TRUE); enemy1(); //自機 if(nz.flag==1){DrawRotaGraph(nz.x,nz.y,1,3.141592/180.0*nz.angle,GHandle,TRUE);} //FPS fps(); ScreenFlip(); while(GetNowCount()-RefreshTime<17); } DxLib_End(); // DXライブラリ使用の終了処理 return 0; // ソフトの終了 } /*enemy.cpp*/ #include "DxLib.h" #include "extern.h" int tHandle = LoadGraph("nz.png"); int count=0; void enemy1(){ count++; DrawFormatString(0,0,GetColor(255, 255, 255),"%d",count); { if (t.flag==1&&t.pattern==1){ t.y=t.y+5; } switch (count) { case 60: count = 0; //出現して何カウント目か測るカウンター初期化 t.flag = 1; //出現フラグを立てる t.pattern = 1; //どういう軌道を描くか t.x = 100.0; //xの初期座標 t.y = 100.0; //yの初期座標 t.size = 10; //敵の大きさ break; default: break; } if (t.flag == 1){ DrawRotaGraph(t.x,t.y,t.size,0,tHandle,TRUE ); } } } /*fps.cpp*/ #include "DxLib.h" int counter=0,FpsTime[2]={0,},FpsTime_i=0; int color_white; double Fps=0.0; char Key[256]; void fpscolor(){ color_white = GetColor(255,255,0); //白色ハンドルを取得 return; } void fps(){ if(FpsTime_i== 0) FpsTime[0]=GetNowCount(); //1周目の時間取得 if(FpsTime_i==49){ FpsTime[1]=GetNowCount(); //50周目の時間取得 Fps = 1000.0f / ((FpsTime[1] - FpsTime[0]) / 50.0f);//測定した値からfpsを計算 FpsTime_i=0;//カウントを初期化 } else FpsTime_i++;//現在何周目かカウント if(Fps != 0) DrawFormatString(565,460,color_white,"FPS %.1f",Fps); //fpsを表示 return; }長々と申し訳ないです・・・
ご教授願います。
Re:ヘッダファイル
>"struct Player nz" (?nz@@3UPlayer@@A) は既に main.obj で定義されています。
>"struct Tama t" (?t@@3UTama@@A) は既に main.obj で定義されています。
同じ名前が存在するのが問題なので、同じ名前を使わないように
って意味ですね。
externの使い方が違ったりするのかな?
<pre></pre>でくくられてないのでソース見てませんが。
>"struct Tama t" (?t@@3UTama@@A) は既に main.obj で定義されています。
同じ名前が存在するのが問題なので、同じ名前を使わないように
って意味ですね。
externの使い方が違ったりするのかな?
<pre></pre>でくくられてないのでソース見てませんが。
Re:ヘッダファイル
> "struct Player nz" (?nz@@3UPlayer@@A) は既に main.obj で定義されています。
> "struct Tama t" (?t@@3UTama@@A) は既に main.obj で定義されています。
enemy.cpp のコンパイル時に、このメッセージが出ますか?
> "struct Tama t" (?t@@3UTama@@A) は既に main.obj で定義されています。
enemy.cpp のコンパイル時に、このメッセージが出ますか?
Re:ヘッダファイル
main.cpp と enemy.cpp の双方で extern.h をインクルードしていますので、
結果として、2つの cpp ファイルで kouzou.h をインクルードしていることになります。
そうすると、main.cpp と enemy.cpp の双方で、外部変数 nz と t の実体を
定義しようとします。
外部変数の実体を定義するのは、プログラム全体のどこか1箇所でなければなりません。
結果として、2つの cpp ファイルで kouzou.h をインクルードしていることになります。
そうすると、main.cpp と enemy.cpp の双方で、外部変数 nz と t の実体を
定義しようとします。
外部変数の実体を定義するのは、プログラム全体のどこか1箇所でなければなりません。
Re:ヘッダファイル
一般的には、ヘッダーファイルの中身を以下でくくる方法があります。
#ifndef HEADER_H_ONCE /*※ヘッダーファイル特有の名前(つまりヘッダーごとに適当に決めればよい)*/
#define HEADER_H_ONCE /*※と同一*/
/*ヘッダーファイルの内容を書く*/
#endif /*どのifndefに対応しているかコメントを残すといいのではないでしょうか*/
コンパイラなどが変わると使えませんがVCではヘッダーファイルの先頭に以下の記述をする方法もあります。
#pragma once
インクルードガードをつけないと構造体の定義で二重定義してしまう事になります。
#ifndef HEADER_H_ONCE /*※ヘッダーファイル特有の名前(つまりヘッダーごとに適当に決めればよい)*/
#define HEADER_H_ONCE /*※と同一*/
/*ヘッダーファイルの内容を書く*/
#endif /*どのifndefに対応しているかコメントを残すといいのではないでしょうか*/
コンパイラなどが変わると使えませんがVCではヘッダーファイルの先頭に以下の記述をする方法もあります。
#pragma once
インクルードガードをつけないと構造体の定義で二重定義してしまう事になります。
Re:ヘッダファイル
早いとこなんとかしないといけませんね、すみません(_ _|||)
あのコードは、なるべく入門時に見ないような構文はかかないようにして作ったので余計に変に難しくなってしまっています。
本来書くべき方法ではありません。
私も理想のかき方というものはよく知りませんが、私のやっている方法を紹介します。
ExternGV.hは削除します。
あのコードは、なるべく入門時に見ないような構文はかかないようにして作ったので余計に変に難しくなってしまっています。
本来書くべき方法ではありません。
私も理想のかき方というものはよく知りませんが、私のやっている方法を紹介します。
いちいち =========GlobalVariable.h============ の中身も ===========ExternGV.h============= の中身もかえるのめんどくさいですよね。 構造体は他のヘッダファイルにかいてもいいですし、全部一つにまとめたければ こちら、変更が一度で済む方法があるので、よければご参考下さい。 まず、main関数のあるファイルの一番最初に #define GLOBAL_INSTANCE と書き、他のファイルにはこれを書きません。 そしてGlobalVariable.h内で、 #ifdef GLOBAL_INSTANCE #define GLOBAL #else #define GLOBAL extern #endif と書きます。 この意味は 「 main関数のあるファイルからこのヘッダファイルが呼ばれたときは、 「GLOBAL」という文字列は「空白」に置き換えて、 他のファイルからこのヘッダファイルが呼ばれたときは、 「GLOBAL」という文字列は「extern」という文字列に置き換えてね 」 という意味になります。 だから、これからは、全てのファイルからGlobalVariable.hを呼び、 ExternGV.hは使わないので削除してOKです。 今までGlobalVariable.hで int func_state; などと宣言していた部分は GLOBAL int func_state; に置き換えてください。オートで必要に応じてexternにしてくれる仕様になり便利です。 こうすると、宣言と同時に値代入が出来なくなるので注意してください。 GLOBAL int func_state=2; などと書くとエラーになります。これは extern int func_state=2; が出来ないのと同じ理由です。 定義で、 #define GLOBAL_VAL(v) =(v) などを用いれば出来ることは出来るのですが、 値の初期化は初期化関数を作って行ったほうがいいので、 自然と宣言と同時に値格納は使わなくてもよくなると思いますので・・。 構造体は、このファイルに普通に書いていただければOKです。 つまりまとめますと、GlobalVariable.h内で、functionというグローバル変数宣言と、 x,yを持ったptという構造体を定義したければ #ifdef GLOBAL_INSTANCE #define GLOBAL #else #define GLOBAL extern #endif GLOBAL int function; typedef struct{ int x,y; }pt_t; こんな感じになります。
ExternGV.hは削除します。
どなたかよろしくお願いします☆
メモ帳でC言語のソースを作り、ソースのある場所に「これはブドウです。」という文を入れコマンドプロンプトでそのファイルを起動させると 「意味不明な語句 ブドウ」と出力し、エンターを押すと1.野菜 2.果物 の選択肢が出力され 2.を押しエンターを押すと「登録されました」と出力されるプログラムをつくりたいのですが、どなたかわかる方よろしくお願いします(^^)☆
Re:どなたかよろしくお願いします☆
質問の意味がよく分かりません…(@_@;)
>>メモ帳でC言語のソースを作り、ソースのある場所に「これはブドウです。」という文を入れコマンドプロンプトでそのファイルを起動させると…
1:ソースを作るだけなのですか?コンパイルしたりはしないのでしょうか?もし、実行ファイルを作成するならば開発環境を提示してください。
2:『そのファイル』とはどのファイルでしょうか?
3:『ファイルを起動させる』というのがどういう事でしょうか?
>>「意味不明な語句 ブドウ」と出力し、エンターを押すと1.野菜 2.果物 の選択肢が出力され 2.を押しエンターを押すと「登録されました」と出力されるプログラムをつくりたいのですが、どなたかわかる方よろしくお願いします(^^)☆
もう少し詳しい状況説明をよろしくお願いします(^^)☆
>>メモ帳でC言語のソースを作り、ソースのある場所に「これはブドウです。」という文を入れコマンドプロンプトでそのファイルを起動させると…
1:ソースを作るだけなのですか?コンパイルしたりはしないのでしょうか?もし、実行ファイルを作成するならば開発環境を提示してください。
2:『そのファイル』とはどのファイルでしょうか?
3:『ファイルを起動させる』というのがどういう事でしょうか?
>>「意味不明な語句 ブドウ」と出力し、エンターを押すと1.野菜 2.果物 の選択肢が出力され 2.を押しエンターを押すと「登録されました」と出力されるプログラムをつくりたいのですが、どなたかわかる方よろしくお願いします(^^)☆
もう少し詳しい状況説明をよろしくお願いします(^^)☆
Re:どなたかよろしくお願いします☆
ん?
名前変わってらっしゃるみたいですけど、先週の問題はもう解決したんでしょうか?
先週の問題解決してるなら、コマンドプロンプトからの起動くらいしか躓きそうな所は無いと思うのですが。
名前変わってらっしゃるみたいですけど、先週の問題はもう解決したんでしょうか?
先週の問題解決してるなら、コマンドプロンプトからの起動くらいしか躓きそうな所は無いと思うのですが。
Re:どなたかよろしくお願いします☆
バグさんへ☆
ソースを作り、メモ帳に「これはブドウです」で保存し、コマンドプロンプトでコンパイルし起動させ保存したファイル名を入力すると「意味不明な語句 ブドウ」と出力させたいです。で、エンターを押すと1.野菜 2.果物 の選択肢が出力され 2.を押しエンターを押すと「登録されました」と出力されるプログラムをつくりたいです。
しりうす~さんへ☆
解決いたしました!
ソースを作り、メモ帳に「これはブドウです」で保存し、コマンドプロンプトでコンパイルし起動させ保存したファイル名を入力すると「意味不明な語句 ブドウ」と出力させたいです。で、エンターを押すと1.野菜 2.果物 の選択肢が出力され 2.を押しエンターを押すと「登録されました」と出力されるプログラムをつくりたいです。
しりうす~さんへ☆
解決いたしました!
Re:どなたかよろしくお願いします☆
> ソースのある場所に「これはブドウです。」という文を入れ
ソースファイルが存在するディレクトリの意味ですか?
ソース中の特定の箇所の意味ですか?
> コマンドプロンプトで
このコマンドプロンプトは、Windowsのcmd.exeの意味ですか?
あるいは一般的なhttp://ja.wikipedia.org/wiki/%E3%82%B3% ... 7%E3%83%88の意味ですか?
> そのファイルを起動させると
インタープリタか何かで起動させるのでしょうか?
コンパイルするという意味でしょうか?
あるいは、もっと別の意味でしょうか?
> 「意味不明な語句 ブドウ」と出力し、
> エンターを押すと1.野菜 2.果物 の選択肢が出力され
> エンターを押すと「登録されました」と出力される
どこに、出力するのでしょうか?
> 2.を押し
「2.」というキーか何かがあるプラットフォームなのでしょうか?
> どなたかわかる方よろしくお願いします(^^)☆
今のままでは残念ながら分かりません。
多分こうだろうと解釈したソースを貼っておきます。
ソースファイルが存在するディレクトリの意味ですか?
ソース中の特定の箇所の意味ですか?
> コマンドプロンプトで
このコマンドプロンプトは、Windowsのcmd.exeの意味ですか?
あるいは一般的なhttp://ja.wikipedia.org/wiki/%E3%82%B3% ... 7%E3%83%88の意味ですか?
> そのファイルを起動させると
インタープリタか何かで起動させるのでしょうか?
コンパイルするという意味でしょうか?
あるいは、もっと別の意味でしょうか?
> 「意味不明な語句 ブドウ」と出力し、
> エンターを押すと1.野菜 2.果物 の選択肢が出力され
> エンターを押すと「登録されました」と出力される
どこに、出力するのでしょうか?
> 2.を押し
「2.」というキーか何かがあるプラットフォームなのでしょうか?
> どなたかわかる方よろしくお願いします(^^)☆
今のままでは残念ながら分かりません。
多分こうだろうと解釈したソースを貼っておきます。
#include <stdio.h> #include <stdlib.h> /* 「これはブドウです。」 ← ある場所 */ int main(void) { puts("「意味不明な語句 ブドウ」"); int c = getchar(); if (c != '\n') return EXIT_FAILURE; puts("1.野菜 2.果物"); char s[sizeof("2.") + 1]; char format[256]; sprintf(format, "%%%us%%c", sizeof(s)); scanf(format, s, &c); if (c != '\n') return EXIT_FAILURE; puts("「登録されました」"); return EXIT_SUCCESS; }全く自信はありません。
Re:どなたかよろしくお願いします☆
つまり…
1:あらかじめ『これはブドウです』と入力されたテキストファイルを作成しておく
2:プログラムを実行すると、文字の入力待ち状態になる
3:入力された文字が1で作成されたファイルのパスであれば『これはブドウです』という文字列から『ブドウ』というキーワードを抜き出して『意味不明な語句 ブドウ』と表示する
4:エンターが入力されるまで待ち、『1.野菜 2.果物』と画面に表示して1か2を入力させる
5:2を選択した場合に『登録されました』と表示する
という流れでよいのでしょうか?
1:あらかじめ『これはブドウです』と入力されたテキストファイルを作成しておく
2:プログラムを実行すると、文字の入力待ち状態になる
3:入力された文字が1で作成されたファイルのパスであれば『これはブドウです』という文字列から『ブドウ』というキーワードを抜き出して『意味不明な語句 ブドウ』と表示する
4:エンターが入力されるまで待ち、『1.野菜 2.果物』と画面に表示して1か2を入力させる
5:2を選択した場合に『登録されました』と表示する
という流れでよいのでしょうか?
Re:どなたかよろしくお願いします☆
一部修正します。
#include <stdio.h> #include <stdlib.h> #include <string.h> /* 「これはブドウです。」 ← ある場所 */ int main(void) { puts("「意味不明な語句 ブドウ」"); int c = getchar(); if (c != '\n') return EXIT_FAILURE; puts("1.野菜 2.果物"); char s[sizeof("2.") + 1]; char format[256]; sprintf(format, "%%%us%%c", sizeof(s)); scanf(format, s, &c); if (strcmp(s, "2.") != 0 || c != '\n') return EXIT_FAILURE; puts("「登録されました」"); return EXIT_SUCCESS; }いずれにせよ、自信はありません。
Re:どなたかよろしくお願いします☆
課題の意図をまるっきり無視して作るなら、たかぎさんの載せて下さっているプログラムにファイル名("これはブドウです。"と書いたファイル名をソースにべた書きで)の判定を入れれば完成ですw
課題の意図を汲むと"これはブドウです。"の文章から"ブドウ"を切り出す際の条件が無いと、プログラムが組みにくいのかな("ブドウ"が出るまで文字列比較で良いとはいえ、汎用性考える人からすると。発展系で"オレンジ"とかもありそうですし)。
前回の問題で文字の入出力はできてるみたいですので、もう少しですね。
頑張ってください。
課題の意図を汲むと"これはブドウです。"の文章から"ブドウ"を切り出す際の条件が無いと、プログラムが組みにくいのかな("ブドウ"が出るまで文字列比較で良いとはいえ、汎用性考える人からすると。発展系で"オレンジ"とかもありそうですし)。
前回の問題で文字の入出力はできてるみたいですので、もう少しですね。
頑張ってください。
Re:どなたかよろしくお願いします☆
たかぎさんへ
ありがとうございます。自分の最終的目標は、ワードやメモ帳などの文章から、名詞や専門用語を抜き出すプログロムを作ることです。そして、抜き出された語句を表示し、自分が数字キーをたたいて 車 人 モノ 植物などに振り分け登録、保存しコンピュータが日々知識を蓄え文字で会話できるようなプログラムをつくりたいです☆
今後ともよろしくお願いします(^^)
ありがとうございます。自分の最終的目標は、ワードやメモ帳などの文章から、名詞や専門用語を抜き出すプログロムを作ることです。そして、抜き出された語句を表示し、自分が数字キーをたたいて 車 人 モノ 植物などに振り分け登録、保存しコンピュータが日々知識を蓄え文字で会話できるようなプログラムをつくりたいです☆
今後ともよろしくお願いします(^^)
Re:どなたかよろしくお願いします☆
最初の質問内容からは予想もつかない話になっていますが...
自然な文を解析するには、「形態素解析」について調べるとよいでしょう。
「茶筌」というツールないしはライブラリがありますので、使えるかもしれません。
自然な文を解析するには、「形態素解析」について調べるとよいでしょう。
「茶筌」というツールないしはライブラリがありますので、使えるかもしれません。
Re:どなたかよろしくお願いします☆
正直なところ面白半分でみていましたが(失礼)
>>コンピュータが日々知識を蓄え文字で会話できるようなプログラム
というのには少し興味をいだきました。
がんばってください(・・b
>>コンピュータが日々知識を蓄え文字で会話できるようなプログラム
というのには少し興味をいだきました。
がんばってください(・・b