- PR -

C# インデックスが配列の境界外です

投稿者投稿内容
AKIR
常連さん
会議室デビュー日: 2005/11/08
投稿数: 34
投稿日時: 2005-11-23 18:40
こんな例外です。
System.IndexOutOfRangeException: インデックスが配列の境界外です。
at musasi.Ranking.Sortplayer() in c:\vc#.net\musasi\musasi\ranking.cs:line 678
at musasi.Ranking.OnPaint(PaintEventArgs pea) in c:\vc#.net\musasi\musasi\ranking.cs:line 764
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Kazuki
ぬし
会議室デビュー日: 2004/10/13
投稿数: 298
投稿日時: 2005-11-23 19:30
全部ってどれのことですか??

例外が出たときの
sortpとplayerとtiの中身はどうなってました?
どれかのサイズが4未満になってるだけだと思うのですが。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-23 20:23
原因は教えられたのですから、その原因を探る方法は判りますよね?
5 回に 1 回くらい起きるとのことで、ti[i] の値が、player の配列の範囲を超えてるのだと予想します。

コード:


public void Sortplayer() {
for (int i = 0; i < 4; i++) {
try {
sortp[i] = player[ti[i]];
} catch {
string stPrompt = string.Empty;
stPrompt += "sortp は、0 〜 " + (sortp.Length - 1).ToString() + " の範囲で配列を確保しています" + System.Environment.NewLine;
stPrompt += "player は、0 〜 " + (player.Length - 1).ToString() + " の範囲で配列を確保しています" + System.Environment.NewLine;
stPrompt += "ti は、0 〜 " + (ti.Length - 1).ToString() + " の範囲で配列を確保しています" + System.Environment.NewLine;
stPrompt += "それに対して、i の値は " + i.ToString() + " です" + System.Environment.NewLine;

if (i <= ti.Length - 1) {
stPrompt += "ti[" + i.ToString() + "] は、" + ti[i].ToString() + " の値になっています" + System.Environment.NewLine;

if (ti[i] > player.Length - 1) {
stPrompt += System.Environment.NewLine;
stPrompt += "繰り返しますが、player は、0 〜 " + (player.Length - 1).ToString() + " の範囲で配列を確保しています" + System.Environment.NewLine;
stPrompt += "それに対して、ti[" + i.ToString() + "] の値が " + ti[i].ToString() + " ですよね?" + System.Environment.NewLine;
stPrompt += "これは範囲を超えてるってことです";
}

}

MessageBox.Show(stPrompt);
}
}
}


# 配列の変数を使う場合、普通は「players」など複数系の命名をします。

[ シグネチャを削除 ]

[ メッセージ編集済み 編集者: じゃんぬねっと 編集日時 2006-10-12 11:49 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-11-23 22:20
引用:

AKIRさんの書き込み (2005-11-23 18:12) より:
じゃんぬさんのソースでできました。全部4でした。


オン書き+人様のコードに継ぎ接ぎなので、検証していませんでした。失礼しました。

 ただ、スコープが外れているから、ということであれば、修正方法もご存じだと思いますが?


 それで、大事なのは、なぜその例外(この場合は IndexOutOfRangeException)が発生するか、です。それは理解されているでしょうか?理解できていれば、「全部4」という返答はない、と思うのですが。。。

 全部4、ということですが、じゃんぬさんの 23 日 09:08 のコードであれば、宣言されている範囲が出るだけです。私が追加したかったのは、実際に参照しようとしている値です。20:23 の、じゃんぬさんのコードで追加してあるとおりです。
# セミコロン2つ連続って、エラーになりません?
___________________________________________________________________
□ written by Jitta on 2005/11/23
□ Microsoft MVP :Visual Developer ASP/ASP.NET Oct.2005-Sept.2006
_________________
AKIR
常連さん
会議室デビュー日: 2005/11/08
投稿数: 34
投稿日時: 2005-11-24 07:03
じゃんぬねっとさんの新しいソースつかったら、lengthはどれも0〜3までだったんですが、ti[3]のあたいが5、6、7、8、9、11となってでてきたウィンドウが全部で6つです。playerは4つしか確保してないんでここがout of rangeだったんですね。
でも実装する前のTest段階のときはこんなエラーでませんでした。また、繰り返しますがコンストラクタに移してからエラーはでません。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-24 08:43
引用:

AKIRさんの書き込み (2005-11-24 07:03) より:

playerは4つしか確保してないんでここがout of rangeだったんですね。


ご理解頂けたようで嬉しいです。

引用:

でも実装する前のTest段階のときはこんなエラーでませんでした。
また、繰り返しますがコンストラクタに移してからエラーはでません。


それは、我々には判り得ない事情です。
引き続き、検証してみてください。

また、配列のインデックスに配列を使うと、混乱の元になります。
多段階配列に置き換えると可読性が良くなるでしょう。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
AKIR
常連さん
会議室デビュー日: 2005/11/08
投稿数: 34
投稿日時: 2005-11-24 10:08
コード:
public int[] ti = new int[4];
		int zi = 0;
		int k = 0;
		int[] yi = new int[500];
		int[] player = new int[] {1,2,3,4};
		public int[] sortp = new int[4];

		public bool Titya()
		{
					
			Random r = new Random(unchecked((int)DateTime.Now.Ticks));						
			for( int i = 0 ; i < 4 ; i++ )
			{
				ti[i] = r.Next(0,4);
								
				if( i > 0 )
				{
				initj:
					for(int j = 0;j < i;j++)
					{
						if(ti[j]==ti[i])
						{
							if(i>2)
							{
								ti[i]=zi;
								zi++;
								goto initj;
				
							}
							Random r2 = new Random(~unchecked((int)DateTime.Now.Ticks));							
							for(;k<100;k++)
							{
								yi[k] = r2.Next(0,4);
												
												
								if(yi[k]!=ti[i])
								{
									ti[i]=yi[k];
									k++;
									goto initj;
								}
							}
						}
					}
				}
			}	
			return true;
		}


これだけだとエラーはでないんですが。ti[]はこんな感じで0から3までの数字が入るようになってるんですけど、zi++としてるところでエラーになる(かな?)かもしれないような気がするのですが、わけわかりません。
すなめり
常連さん
会議室デビュー日: 2003/01/29
投稿数: 37
お住まい・勤務地: 横浜
投稿日時: 2005-11-24 18:53
Titya()を2回以上呼び出すと、ziの値が4以上になりうると思いますので、エラーの原因はそこかと。
Titya()の最初の部分でziを(多分kも)ゼロクリアすると、エラーは発生しなくなるかと思います。

なお、このプログラムは、0から3の値が一回ずつランダムに現れる配列を作成しようとしているのではないかと思いますが、ランダムの値によってはそうならない可能性があります。
#例えば、たまたまランダムの値がすべてゼロとなった場合等。

「配列 シャッフル」で検索をかけると、いろいろアルゴリズムが出てきますので、そちらを参考にされるのがよいのでは。

スキルアップ/キャリアアップ(JOB@IT)