C++を最近始めました。
VC++ の開発者コマンドプロントプトでケッペンの気候区分判定プログラムを作っている最中です。
ところが乾季を判定するプログラムで
”問題が発生したため、プログラムが正しく動作しなくなりました。”
と表示され、判定がいかなる場合でも 乾季無し となってしまいます。。。
エラーの通知もないのでどこを修正すればいいのかわからんのです。以下にコードを示します。
code
#include <iostream>
using namespace std;
#define NORTH 1
#define SOUTH 2
#define FALSE 0
#define SUMMER 3
#define WINTER 4
class Koppen
{
private:
double Temp[13]; // 1月から12月までの平均気温と年間平均気温
double Rain[13]; //1月から12月までの平均降水量と年間平均降水量
public:
Koppen(); //初期化コンストラクタ
void SetTemp(); //(温度のセット)
void SetRain(); //(降水量のセット)
double Find_TempMax(); //年間最高気温を返す
double Find_TempMin(); //年間最小気温を返す
double Find_RainMax(); //年間最大降水量を返す
double Find_RainMin(); //年間最小降水量を返す
int Check_North_or_South() ; // 北半球だとNORTH、南半球だとSOUTHを返す
int Check_DrySeason() ; // 乾季が夏の場合SUUMERを返し、冬だとWINNTERを返し、判定不能の場合FALSEを返す
};
Koppen :: Koppen() // クラス内変数の初期化コンストラクタ
{
int i ;
for(i=0;i<13;i++)
{
Temp[i+1] = NULL ;
Rain[i+1] = NULL ;
}
}
void Koppen :: SetTemp() //12ヶ月の気温を入力 + 年間平均気温を入力
{
int i;
for(i=0;i<12;i++)
{
cout << i+1 << "月の平均気温:";
cin >> Temp[i+1];
}
cout << "年間平均気温:";
cin >> Temp[13] ;
}
void Koppen :: SetRain() // 12ヶ月の降水量を入力 + 年間平均降水量を入力
{
int i;
for(i=0;i<12;i++)
{
cout << i+1 << "月の平均降水量:" ;
cin >> Rain[i+1];
}
cout << "年間平均降水量:" ;
cin >> Rain[13] ;
}
double Koppen :: Find_TempMax() // 最高気温を返す
{
double tmax = Temp[1] ;
int i;
for(i=0;i<12;i++)
{
if(Temp[i+1] > tmax) tmax = Temp[i+1] ;
}
return tmax;
}
double Koppen :: Find_TempMin() // 最低気温を返す
{
double tmin = Temp[1];
int i;
for(i=0;i<12;i++)
{
if(Temp[i+1] < tmin) tmin = Temp[i+1] ;
}
return tmin ;
}
double Koppen :: Find_RainMax() // 最高降水量を返す
{
double rmax = Rain[1] ;
int i;
for(i=0;i<12;i++)
{
if(Rain[i+1] > rmax) rmax = Rain[i+1] ;
}
return rmax ;
}
double Koppen :: Find_RainMin() // 最低降水量を返す
{
double rmin = Rain[1] ;
int i ;
for(i=0;i<12;i++)
{
if(Rain[i+1] < rmin) rmin = Rain[i+1] ;
}
return rmin ;
}
int Koppen :: Check_North_or_South() // 北半球の場合NORTHを返し、南半球の場合SOUTHを返す
{
int summer,winter ;
int north_or_south ;
summer = Temp[6]+Temp[7]+Temp[8]+Temp[9] ;
winter = Temp[11]+Temp[12]+Temp[1]+Temp[2] ;
if(summer > winter) north_or_south = NORTH ;
if(summer < winter) north_or_south = SOUTH ;
return north_or_south ;
}
int Koppen :: Check_DrySeason() // 乾季が夏の場合SUUMERを返し、冬だとWINNTERを返し、判定不能の場合FALSEを返す
{
int KARI_DrySeason = NULL ;
switch( Check_North_or_South() )
{
case NORTH :
if(Find_RainMin() == Rain[11] || Rain[12] || Rain[1] || Rain[2])
{
KARI_DrySeason = WINTER ;
}
else if(Find_RainMin() == Rain[6] || Rain[7] || Rain[8] || Rain[9])
{
KARI_DrySeason = SUMMER ;
}
else
{
KARI_DrySeason = FALSE ;
}
case SOUTH :
if(Check_North_or_South() == Rain[6] || Rain[7] || Rain[8] || Rain[9])
{
KARI_DrySeason = WINTER ;
}
else if(Check_North_or_South() == Rain[11] || Rain[12] || Rain[1] || Rain[2])
{
KARI_DrySeason = SUMMER ;
}
else
{
KARI_DrySeason = FALSE ;
}
}
int winter_or_summer = NULL ;
switch(KARI_DrySeason)
{
case WINTER :
if(Find_RainMax() >= Find_RainMin() * 10)
{
winter_or_summer = WINTER ;
}
else
{
winter_or_summer = FALSE ;
}
case SUMMER :
if(Find_RainMax() >= Find_RainMin() * 3)
{
winter_or_summer = SUMMER ;
}
else
{
winter_or_summer = FALSE ;
}
case FALSE :
winter_or_summer = FALSE ;
}
return winter_or_summer ;
}
int main() //ここからmain関数
{
Koppen ob ;
ob.SetRain();
ob.SetTemp();
if(ob.Check_DrySeason() == WINTER)
{
cout << "冬乾季\n" ;
}
else if(ob.Check_DrySeason() == SUMMER)
{
cout << "夏乾季\n" ;
}
else if(ob.Check_DrySeason() == FALSE)
{
cout << "乾季なし\n" ;
}
else
{
cout << "エラー\n" ;
}
return 0;
}
/code
まだ未完成なので完全な気候区分はできず、int Koppen :: Check_DrySeason 関数の動作チェックのためのmian関数しか作ってません。。。
問題が発生したため、プログラムが正しく動作しなくなりました。
Re: 問題が発生したため、プログラムが正しく動作しなくなりました。
提示されたコードは、変なところに全角の空白があるので、
そのままではコンパイルが通りません。
質問者さんのところでおかしな動きをしているコードを
そのまま貼ってください。
定義時にTemp[13]と書くと、アクセスできるのはTemp[0]~Temp[12]の13個です。
例えば1個目の場合、Find_RainMin()関数の戻り値が「Rain[11]かRain[12]かRain[1]かRain[2]のいずれか」という意図ですか?
だとすると、意図どおりになっていません。
そのままではコンパイルが通りません。
質問者さんのところでおかしな動きをしているコードを
そのまま貼ってください。
iが12のとき、Temp[13]やRain[13]といった、配列の定義範囲外にアクセスしています。
定義時にTemp[13]と書くと、アクセスできるのはTemp[0]~Temp[12]の13個です。
ここも同じです。
これらのif文はどういう意図で書いていますか?伊藤博文非公式ファンクラブ さんが書きました:
例えば1個目の場合、Find_RainMin()関数の戻り値が「Rain[11]かRain[12]かRain[1]かRain[2]のいずれか」という意図ですか?
だとすると、意図どおりになっていません。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。
プログラムは思ったとおりには動かない。書いたとおりに動く。
Re: 問題が発生したため、プログラムが正しく動作しなくなりました。
全角スペースを半角スペース2個に置換して適当に実行した限りでは強制終了は再現できませんでしたが、とりあえず気付いたことを書きます。
- C++のコードの文字列やコメント以外の場所に全角スペースを書いてはいけません。全て削除してください。
- TempとRainは13要素しか無いため、Temp[13]やRain[13]にアクセスしてはいけません。要素数を増やしてください。
- NULLを数値の0として使うべきではありません。素直に0と書いてください。
gdbなどのデバッガ上で実行するといいかもしれません。伊藤博文非公式ファンクラブ さんが書きました:エラーの通知もないのでどこを修正すればいいのかわからんのです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 問題が発生したため、プログラムが正しく動作しなくなりました。
現在修復中です。。。 ご指摘ありがとうございます。修正が終わったらちゃんと貼ろうと思います。みけCAT さんが書きました:全角スペースを半角スペース2個に置換して適当に実行した限りでは強制終了は再現できませんでしたが、とりあえず気付いたことを書きます。
•C++のコードの文字列やコメント以外の場所に全角スペースを書いてはいけません。全て削除してください。
•TempとRainは13要素しか無いため、Temp[13]やRain[13]にアクセスしてはいけません。要素数を増やしてください。
•NULLを数値の0として使うべきではありません。素直に0と書いてください。
ところで、
その通りの意図なのですが、その場合どうのようにすればいいのでしょうか?box さんが書きました: これらのif文はどういう意図で書いていますか?
例えば1個目の場合、Find_RainMin()関数の戻り値が「Rain[11]かRain[12]かRain[1]かRain[2]のいずれか」という意図ですか?
だとすると、意図どおりになっていません。
Re: 問題が発生したため、プログラムが正しく動作しなくなりました。
素直に書きましょう。伊藤博文非公式ファンクラブ さんが書きました:ところで、
その通りの意図なのですが、その場合どうのようにすればいいのでしょうか?box さんが書きました: これらのif文はどういう意図で書いていますか?
例えば1個目の場合、Find_RainMin()関数の戻り値が「Rain[11]かRain[12]かRain[1]かRain[2]のいずれか」という意図ですか?
だとすると、意図どおりになっていません。
if(Find_RainMin() == Rain[11] || Find_RainMin() == Rain[12] || Find_RainMin() == Rain[1] || Find_RainMin() == Rain[2])
ループと配列を用い、フラグを立てるようにするとさらに良くなるでしょう。
// 値を取得する
double min = Find_RainMin();
int ns = Check_North_or_South();
// フラグ変数
bool flag[4];
// フラグに対応する位置(-1は対応する位置なし)
static const int rain_index[13] = {-1, 0, 0, -1, -1, -1, 1, 1, 1, 1, -1, 0, 0};
static const int ns_index[13] = {-1, 3, 3, -1, -1, -1, 2, 2, 2, 2, -1, 3, 3};
// フラグを初期化
for (int i = 0; i < 4; i++) flag[i] = false;
// 条件を満たしていたらフラグを立てる
for (int i = 0; i < 13; i++) {
if (rain_index[i] >= 0 && min == Rain[i]) flag[rain_index[i]] = true;
// 本当にCheck_North_or_Southの戻り値とRainの要素を比較するのは適切な処理なのかな…?
if (ns_index[i] >= 0 && ns == Rain[i]) flag[ns_index[i]] = true;
}
// フラグに応じた処理を実行する
if (flag[0]) // if(Find_RainMin() == Rain[11] || Rain[12] || Rain[1] || Rain[2])
else if(flag[1]) // else if(Find_RainMin() == Rain[6] || Rain[7] || Rain[8] || Rain[9])
if(flag[2]) // if(Check_North_or_South() == Rain[6] || Rain[7] || Rain[8] || Rain[9])
else if(flag[3]) // else if(Check_North_or_South() == Rain[11] || Rain[12] || Rain[1] || Rain[2])
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 問題が発生したため、プログラムが正しく動作しなくなりました。
だとすると、まあふつうは伊藤博文非公式ファンクラブ さんが書きました: その通りの意図なのですが、その場合どうのようにすればいいのでしょうか?
こんな風にするんでしょうね。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。
プログラムは思ったとおりには動かない。書いたとおりに動く。
Re: 問題が発生したため、プログラムが正しく動作しなくなりました。
指摘されたところをとりあえず修復し、Windowsからのエラー通知はなくなりました。ありがとうございます。
おそらく配列の箇所が一番の要因だったと思われました。
ところで、修復したプログラムをテストしてみたところ、何故か未だに「乾季なし」しか表示されません。
以下にソースと入力するデータを示します。
ケッペンの気候区分を調べていただくとお分かりになるでしょうが、現在つまづいているのは乾燥気候の判定プログラムです。なぜかどのデータを入力しても(自分で乾燥気候をの種類を既に調べたもの)前述のように「乾季無」と判定されてしまいます。。。
おそらく配列の箇所が一番の要因だったと思われました。
ところで、修復したプログラムをテストしてみたところ、何故か未だに「乾季なし」しか表示されません。
以下にソースと入力するデータを示します。
#include <iostream>
using namespace std;
#define NORTH 1
#define SOUTH 2
#define SUMMER 3
#define WINTER 4
#define FALSE 5
class Koppen
{
private:
double Temp[12];
double Rain[12];
public:
Koppen();
void SetTemp(); //確定(温度のセット)
void SetRain(); //確定(降水量のセット)
//double Find_TempAverage();
//double Find_RainAverage(); <-こいつらは後々作ろうかと(気温と降水量の年間平均値)
double Find_TempMax(); //最高気温を返す
double Find_TempMin(); //最低気温を返す
double Find_RainMax(); //最大降水量を返す
double Find_RainMin(); //最小降水量を返す
int Check_North_or_South() ; // 北半球だとNORTH、南半球だとSOUTHを返す
int Check_DrySeason() ; // 乾季が夏の場合SUUMERを返し、冬だとWINNTERを返し、判定不能の場合FALSEを返す
};
Koppen :: Koppen() // クラス内変数の初期化コンストラクタ
{
int i ;
for(i=0;i<12;i++)
{
Temp[i] = 0 ;
Rain[i] = 0 ;
}
}
void Koppen :: SetTemp() //12ヶ月の気温を入力 + 年間平均気温を入力
{
int i;
for(i=0;i<12;i++)
{
cout << i+1 << "月の平均気温:";
cin >> Temp[i];
}
}
void Koppen :: SetRain() // 12ヶ月の降水量を入力 + 年間平均降水量を入力
{
int i;
for(i=0;i<12;i++)
{
cout << i+1 << "月の平均降水量:";
cin >> Rain[i];
}
}
double Koppen :: Find_TempMax() // 最高気温を返す
{
double tmax = Temp[0];
int i;
for(i=0;i<12;i++)
{
if(Temp[i] > tmax) tmax = Temp[i];
}
return tmax;
}
double Koppen :: Find_TempMin() // 最低気温を返す
{
double tmin = Temp[0];
int i;
for(i=0;i<12;i++)
{
if(Temp[i] < tmin) tmin = Temp[i] ;
}
return tmin ;
}
double Koppen :: Find_RainMax() // 最高降水量を返す
{
double rmax = Rain[0] ;
int i;
for(i=0;i<12;i++)
{
if(Rain[i] > rmax) rmax = Rain[i] ;
}
return rmax ;
}
double Koppen :: Find_RainMin() // 最低降水量を返す
{
double rmin = Rain[0] ;
int i ;
for(i=0;i<12;i++)
{
if(Rain[i] < rmin) rmin = Rain[i] ;
}
return rmin ;
}
int Koppen :: Check_North_or_South() // 北半球の場合NORTHを返し、南半球の場合SOUTHを返す
{
int summer,winter ;
int north_or_south ;
summer = Temp[5]+Temp[6]+Temp[7]+Temp[8] ;//6月から9月までの気温の合計
winter = Temp[10]+Temp[11]+Temp[0]+Temp[1] ;//11月から2月までの気温の合計
if(summer > winter) north_or_south = NORTH ;
if(summer < winter) north_or_south = SOUTH ;
return north_or_south ;
}
int Koppen :: Check_DrySeason()
{
int KARI_DrySeason = 0 ;
double min = Find_RainMin();//最小降水量を求める
double max = Find_RainMax();//最大降水量を求める
switch(Check_North_or_South())
{
case NORTH :
if((min == Rain[10]) || (min == Rain[11]) || (min == Rain[0]) || (min == Rain[1]))
{
KARI_DrySeason = WINTER ;
}
else if((min == Rain[5]) || (min == Rain[6]) || (min == Rain[7]) || (min == Rain[8]))
{
KARI_DrySeason = SUMMER ;
}
else
{
KARI_DrySeason = FALSE ;
}
case SOUTH :
if((min == Rain[5]) || (min == Rain[6]) || (min == Rain[7]) || (min == Rain[8]))
{
KARI_DrySeason = WINTER ;
}
else if((min == Rain[10]) || (min == Rain[11]) || (min == Rain[0]) || (min == Rain[1]))
{
KARI_DrySeason = SUMMER ;
}
else
{
KARI_DrySeason = FALSE ;
}
}
int winter_or_summer = NULL ;
switch(KARI_DrySeason)
{
case WINTER :
if( max >= min * 10)
{
winter_or_summer = WINTER ;
}
else
{
winter_or_summer = FALSE ;
}
case SUMMER :
if(max >= min * 3)
{
winter_or_summer = SUMMER ;
}
else
{
winter_or_summer = FALSE ;
}
case FALSE :
winter_or_summer = FALSE ;
cout << "ここだよ~ん\n";//(チェックの際に使いました。。。)
}
return winter_or_summer ;
}
int main()
{
Koppen ob ;
ob.SetRain() ;
ob.SetTemp() ;
if(ob.Check_DrySeason() == WINTER)
{
cout << "冬乾季\n" ;
}
else if(ob.Check_DrySeason() == SUMMER)
{
cout << "夏乾季\n" ;
}
else if(ob.Check_DrySeason() == FALSE)
{
cout << "乾季なし\n" ;
}
else
{
cout << "エラー\n" ;
}
return 0 ;
}
Re: 問題が発生したため、プログラムが正しく動作しなくなりました。
プログラムだけではなく、テストに使ったデータも提示してください。できれば複数の組を。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。
プログラムは思ったとおりには動かない。書いたとおりに動く。