2.3 多次元配列

番号 以下をクリックすると同位置にジャンプします
(1) 多次元配列の考え方
(2) 数値地図
(3) 経過日数



(1)多次元配列の考え方


旧来のC言語,C++では,
配列を要素とする配列を多次元配列としており,たとえば,

  int A[4][30];
  A[3][2] = 87;

と記述することになっていますが,
C#では,他の多くの言語と同様,以下のように自然な表現となっています。

  int[,] A = new int[4,30];
  A[3,2] = 87;

      


            図2−7 2次元配列

番号 以下をクリックすると同位置にジャンプします
(1) 多次元配列の考え方
(2) 数値地図
(3) 経過日数



(2)数値地図


2次元配列の代表例として,XYのメッシュ番号をインデックスとし
標高値を要素値とする数値地図を挙げることができます。
例えば,以下のようにXY座標をメッシュで分割し,
各マス目に標高値が入るようなデータです。
     
     図2−8 メッシュデータのイメージ

有名な国土地理院の50mメッシュ数値地図は,
約50m(正確には緯度経度で異なる)メッシュの
縦200×横200のマス目に標高値×10の整数値が入っています。

ファイルの形式は提供されているCDに付属する説明書に委ねますが,
大まかにいうと,先頭1行がタイトル及び制御データ,
2行目以降に番号と5桁刻みの標高値が入っています。

順序は,南西から東方向に200個のデータが並び,
これが北方向に並びます。

     

     図2−9 国土地理院50mメッシュ数値地図のデータの順序


国土地理院の数値地図(MEM)ファイルを読み込んで,
色地図として画面に表示するプログラムをProgram 2-12に示します。

プログラムでは,ビットマップ型の変数に描画しておき,
それを描画用オーバライドOnPaintで描画します(注)。

なお,先頭レコードのタイトル,制御データ,
2行目以降の先頭レコード番号等は無視し,
表示に必要な標高データのみ使用しています。

(注)
Onpaintで描画しないと,画面切替え等のタイミングで
フォームの再描画は行われません。


[Program 2−12] 数値地図データの読み込みと色地図表示

 コントロールとしてはbutton1(Text:数値地図読込み)と
 openFileDialog1を貼り付けます。

 (以下は,実行例です)

  

     
private double [,] pbJR=new double[201,201];
private string pbA;
private Bitmap image;

// 描画用オーバライド
protected override void OnPaint(PaintEventArgs e)
{
  base.OnPaint(e); e.Graphics.DrawImage(image,0,0);
}
private void 描画()
{
  double MX=標高最大(); double MN=標高最小();
  double DX=(MX-MN)/255; if(DX<0.000001) DX=255;
  Graphics g=Graphics.FromImage(image);
  for(int i=1; i<=200; i++)
   for(int j=1; j<=200; j++)
    {
      int C=(int)((pbJR[201-j,i]-MN)/DX);
      Brush brush = new SolidBrush(Color.FromArgb(C,C,C));
      g.FillRectangle(brush,j-1,i-1,1,1);
    }
}

private double 標高最大( )
{
  double MX=pbJR[1,1];
  for(int i=1;i<=200;i++)
    for(int j=1;j<=200;j++) if(MX<pbJR[i,j]) MX=pbJR[i,j];
  return MX;
}
private double 標高最小( )
{
  double MN=pbJR[1,1];
  for(int i=1;i<=200;i++)
    for(int j=1;j<=200;j++) if(MN>pbJR[i,j]) MN=pbJR[i,j];
  return MN;
}
private void openFileDialog1_FileOk(object sender,
                System.ComponentModel.CancelEventArgs e)
{
  StreamReader DTS;
  int ii, pbII;
  string FName=openFileDialog1.FileName;
  if(FName == "") return;
  DTS=new StreamReader(FName,System.Text.Encoding.Default);
  pbA=DTS.ReadLine(); // 制御データの無視
  pbII=0;string DT=DTS.ReadLine(); // 1行読込み
  while(DT !=null)
  {
    ii = 5; pbII=pbII+1;
    for(int j=1;j<=200;j++) // 5桁ずつ区切って西→東にデータを設定
    {
      ii = ii + 5;
      pbJR[pbII, j] = int.Parse(midStr(DT, ii, 5));
    }
    DT=DTS.ReadLine(); // 1行読込み
  }
  DTS.Close();
描画();
  this.Invalidate(); // OnPaintを強制的に引き起こす
}

private string midStr(string DT, int ist,int N)
{
  string S="";int k=ist-1;
  for(int i=1 ;i<=N;i++){S = S + DT[k]; k=k+1;}
  return S;
}
private void button1_Click(object sender, System.EventArgs e)
{
  openFileDialog1.ShowDialog();
}
private void Form1_Load(object sender, System.EventArgs e)
{
  image =new Bitmap(200,200);
}


番号 以下をクリックすると同位置にジャンプします
(1) 多次元配列の考え方
(2) 数値地図
(3) 経過日数

(3)経過日数


多次元配列は,何らかの条件で値が異なるような
表データとして用いられることも多くあります。

ここで示す例は,うるう年と通常年のときの
月の日数の違いを表で表した例です。



[Program 2−13] 経過日数

  

     
private int[,] 月日数= new int[,]
 { {31,28,31,30,31,30,31,31,30,31,30,31},
   {31,29,31,30,31,30,31,31,30,31,30,31}, };

private int うるう年判定(int Y)
{
   return (Y % 4 ==0 && Y % 100 !=0 || Y % 400 ==0)? 1:0;
}
private int 経過日数(int Y, int M, int D)
{
  int i; int 日数=D;
  int K= うるう年判定(Y);
  for (i=1; i<M; i++) 日数 += 月日数[K,i-1];
  return 日数;
}
private void button1_Click(object sender, System.EventArgs e)
{
  int Y=int.Parse(textBox1.Text);
  int M=int.Parse(textBox2.Text);
  int D=int.Parse(textBox3.Text);
  label4.Text=経過日数(Y,M,D).ToString();
}


番号 以下をクリックすると同位置にジャンプします
(1) 多次元配列の考え方
(2) 数値地図
(3) 経過日数

1. 基本的なアルゴリズム

2. 基本的なデータ構造

3. 操作を伴うデータ構造

4. 探索

5. 再帰的アルゴリズム

6. ソート

7. 集合

8. 文字列処理

9. 色々なアルゴリズム


上のタイトルをクリックします