問題が発生したため、プログラムが正しく動作しなくなりました。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
伊藤博文非公式ファンクラブ

問題が発生したため、プログラムが正しく動作しなくなりました。

#1

投稿記事 by 伊藤博文非公式ファンクラブ » 8年前

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関数しか作ってません。。。

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

Re: 問題が発生したため、プログラムが正しく動作しなくなりました。

#2

投稿記事 by box » 8年前

提示されたコードは、変なところに全角の空白があるので、
そのままではコンパイルが通りません。

質問者さんのところでおかしな動きをしているコードを
そのまま貼ってください。
伊藤博文非公式ファンクラブ さんが書きました:

コード:

		double Temp[13]; // 1月から12月までの平均気温と年間平均気温

		double Rain[13]; //1月から12月までの平均降水量と年間平均降水量
	for(i=0;i<13;i++)
	{
		Temp[i+1] = NULL ;
		Rain[i+1] = NULL ;
	}
iが12のとき、Temp[13]やRain[13]といった、配列の定義範囲外にアクセスしています。
定義時にTemp[13]と書くと、アクセスできるのはTemp[0]~Temp[12]の13個です。
伊藤博文非公式ファンクラブ さんが書きました:

コード:

	cin >> Temp[13] ;
	cin >> Rain[13] ;
ここも同じです。
伊藤博文非公式ファンクラブ さんが書きました:

コード:

			if(Find_RainMin() == Rain[11] || Rain[12] || Rain[1] || Rain[2])
			else if(Find_RainMin() == Rain[6] || Rain[7] || Rain[8] || Rain[9])
			if(Check_North_or_South() == Rain[6] || Rain[7] || Rain[8] || Rain[9])
			else if(Check_North_or_South() == Rain[11] || Rain[12] || Rain[1] || Rain[2])
これらのif文はどういう意図で書いていますか?
例えば1個目の場合、Find_RainMin()関数の戻り値が「Rain[11]かRain[12]かRain[1]かRain[2]のいずれか」という意図ですか?
だとすると、意図どおりになっていません。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 問題が発生したため、プログラムが正しく動作しなくなりました。

#3

投稿記事 by みけCAT » 8年前

全角スペースを半角スペース2個に置換して適当に実行した限りでは強制終了は再現できませんでしたが、とりあえず気付いたことを書きます。
  • C++のコードの文字列やコメント以外の場所に全角スペースを書いてはいけません。全て削除してください。
  • TempとRainは13要素しか無いため、Temp[13]やRain[13]にアクセスしてはいけません。要素数を増やしてください。
  • NULLを数値の0として使うべきではありません。素直に0と書いてください。
伊藤博文非公式ファンクラブ さんが書きました:エラーの通知もないのでどこを修正すればいいのかわからんのです。
gdbなどのデバッガ上で実行するといいかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

伊藤博文非公式ファンクラブ

Re: 問題が発生したため、プログラムが正しく動作しなくなりました。

#4

投稿記事 by 伊藤博文非公式ファンクラブ » 8年前

みけ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]のいずれか」という意図ですか?
だとすると、意図どおりになっていません。
その通りの意図なのですが、その場合どうのようにすればいいのでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 問題が発生したため、プログラムが正しく動作しなくなりました。

#5

投稿記事 by みけCAT » 8年前

伊藤博文非公式ファンクラブ さんが書きました:ところで、
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])
…と書きましたが、これはFind_RainMin()を無駄に大量に呼んでいるし、無駄に長いので良くないかもしれません。
ループと配列を用い、フラグを立てるようにするとさらに良くなるでしょう。

コード:

// 値を取得する
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で殴ればいい!(死亡フラグ)

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

Re: 問題が発生したため、プログラムが正しく動作しなくなりました。

#6

投稿記事 by box » 8年前

伊藤博文非公式ファンクラブ さんが書きました: その通りの意図なのですが、その場合どうのようにすればいいのでしょうか?
だとすると、まあふつうは

コード:

    double ret = Find_RainMin();
    if (ret == Rain[11] || ret == Rain[12] || ret == Rain[1] || ret == Rain[2]) {
        // ここにやりたいことを書く
    }
こんな風にするんでしょうね。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

伊藤博文非公式ファンクラブ

Re: 問題が発生したため、プログラムが正しく動作しなくなりました。

#7

投稿記事 by 伊藤博文非公式ファンクラブ » 8年前

指摘されたところをとりあえず修復し、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 ;
}
ケッペンの気候区分を調べていただくとお分かりになるでしょうが、現在つまづいているのは乾燥気候の判定プログラムです。なぜかどのデータを入力しても(自分で乾燥気候をの種類を既に調べたもの)前述のように「乾季無」と判定されてしまいます。。。

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

Re: 問題が発生したため、プログラムが正しく動作しなくなりました。

#8

投稿記事 by box » 8年前

プログラムだけではなく、テストに使ったデータも提示してください。できれば複数の組を。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

かずま

Re: 問題が発生したため、プログラムが正しく動作しなくなりました。

#9

投稿記事 by かずま » 8年前

switch文に break; がないから、いつも最後の case の結果になっているようです。

閉鎖

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