第8講 ポインタと配列の学習
第5話 2次元配列と1次元配列の関係

第4話問題の解答例
Form1

プログラムソース
#pragma once
#include<stdlib.h>
char *i;
char a[10][10];
   ・
   ・
   ・
#pragma endregion
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
          i=(char *)malloc;
          String^ w="";
          char j;
          char k;
          for(j=0;j<10;j++){
            for(k=0;k<10;k++){
              *(i+10*j+k)=10*j+k+1;
              if(*(i+10*j+k)<10)w=w+L"00"+(*(i+10*j+k)).ToString()+L" ";
              if((*(i+10*j+k)>=10) & (*(i+10*j+k)<100))w=w+L"0"+(*(i+10*j+k)).ToString()+L" ";
              if(*(i+10*j+k)>=100)w=w+(*(i+10*j+k)).ToString()+L" ";
            }
            w=w+L"\n";
          }
          label1->Text=w;
          w=L"";
          for(j=0;j<10;j++){
            for(k=0;k<10;k++){
            a[j][k]=10*j+k+1;
            if(a[j][k]<10)w=w+L"00"+(a[j][k]).ToString()+L" ";
            if((a[j][k]>=10) & (a[j][k]<100))w=w+L"0"+(a[j][k]).ToString()+L" ";
            if(a[j][k]>=100)w=w+(a[j][k]).ToString()+L" ";
          }
          w=w+L"\n";
       }
       label2->Text=w;
     }
  };
}

プログラム解説
if(*(i+10*j+k)<10)w=w+L"00"+(*(i+10*j+k)).ToString()+L" ";
if((*(i+10*j+k)>=10) & (*(i+10*j+k)<100))w=w+L"0"+(*(i+10*j+k)).ToString()+L" ";
if(*(i+10*j+k)>=100)w=w+(*(i+10*j+k)).ToString()+L" ";
の部分は、
if(*(i+10*j+k)>=100){
  w=w+(*(i+10*j+k)).ToString()+L" ";
}
else{
  if(*(i+10*j+k)>=10){
    w=w+L"0"+(*(i+10*j+k)).ToString()+L" ";
  }
  else{
    w=w+L"00"+(*(i+10*j+k)).ToString()+L" ";
  }
}
としても同じです。
なぜなら、
100以上ならw=w+(*(i+10*j+k)).ToString()+L" ";が
100以上でなく(つまり100未満)で10以上ならw=w+L"0"+(*(i+10*j+k)).ToString()+L" ";が、
10以上でないなら(すなわち10未満なら)w=w+L"00"+(*(i+10*j+k)).ToString()+L" ";が
実行されるからです。
ですが、if〜else文の場合、入れ子が2段になりわかりにくいですね。
まだ、3つのランクですからいいのですがこれが5桁当たりになると、
入れ子(ネスト)が4段になりより複雑になるます。
if(*(i+10*j+k)>=10000){
  w=w+(*(i+10*j+k)).ToString()+L" ";
}
else{
  if(*(i+10*j+k)>=1000){
    w=w+L"0"+(*(i+10*j+k)).ToString()+L" ";
  }
  else{
    if(*(i+10*j+k)>=100){
      w=w+L"00"+(*(i+10*j+k)).ToString()+L" ";
    }
    else{
      if(*(i+10*j+k)>=10){
        w=w+L"000"+(*(i+10*j+k)).ToString()+L" ";
      }
      else{
        w=w+L"0000"+(*(i+10*j+k)).ToString()+L" ";
      }
    }
  }
}
ですが、
if(*(i+10*j+k)<10)w=w+L"0000"+(*(i+10*j+k)).ToString()+L" ";
if((*(i+10*j+k)>=10) & (*(i+10*j+k)<100))w=w+L"000"+(*(i+10*j+k)).ToString()+L" ";
if(*(i+10*j+k)>=100 & (*(i+10*j+k)<1000))w=w+L"00"+(*(i+10*j+k)).ToString()+L" ";
if(*(i+10*j+k)>=1000 & (*(i+10*j+k)<10000))w=w+L"0"+(*(i+10*j+k)).ToString()+L" ";
if(*(i+10*j+k)>=1000)w=w+(*(i+10*j+k)).ToString()+L" ";
という書き方なら、文は増えますが入れ子はありません。
ネスト(入れ子)が深くなると、複雑になりますので、
基本的にはif〜else文の使用は、ネストが1段のときに限定してif文を使用する習慣をつけましょう。

さて、if文以外で特に注目して頂きたいのは、
片一方は、1次元のポインタ(というよりポインタは1次元しかありません)であり、
他方は2次元の配列であるのに結果が同じだと言うことです。
例えば、次のようにプログラムソースを変更してみましょう。
#include<stdlib.h>
char a[10][10];
char b[100];
   ・
   ・
   ・   
#pragma endregion
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
          String^ w="";
          char j;
          char k;
          for(j=0;j<10;j++){
            for(k=0;k<10;k++){
              b[10*j+k]=10*j+k+1;
              if(b[10*j+k]<10)w=w+L"00"+(b[10*j+k]).ToString()+L" ";
              if((b[10*j+k]>=10) & (b[10*j+k]<100))w=w+L"0"+(b[10*j+k]).ToString()+L" ";
              if(b[10*j+k]>=100)w=w+(b[10*j+k]).ToString()+L" ";
            }
            w=w+L"\n";
          }
          label1->Text=w;
          w=L"";
          for(j=0;j<10;j++){
            for(k=0;k<10;k++){
            a[j][k]=10*j+k+1;
            if(a[j][k]<10)w=w+L"00"+(a[j][k]).ToString()+L" ";
            if((a[j][k]>=10) & (a[j][k]<100))w=w+L"0"+(a[j][k]).ToString()+L" ";
            if(a[j][k]>=100)w=w+(a[j][k]).ToString()+L" ";
          }
          w=w+L"\n";
       }
       label2->Text=w;
     }
  };
}実行結果は、

でまったく変わりありません。
以上から、2つのことがわかります。
1つめは、ポインタと1次元配列はまったく同じであること。
2つめは、2次元配列は1次元配列でも表現できること、すなわち2次元配列はポインタでも表現できること。

ということは、1次元配列またはポインタで、多次元配列を表現できることがわかります。
例えば、
char a[10][10][10];
char b[1000];
ならば、
a[i][j][k]=b[100*i+10*j+k]
というわけです。
では皆さん、ここで問題です。
char a[5][5][5];
char b[125];
char *c;
なら、
a[i][j][k]は、1次元配列とポインタではどのように表現されるでしょうか。
例によって解答は20行下に示します。




















a[i][j][k]=b[25*i+5*j+k]
c=(char *)malloc;
a[i][j][k]=*(c+25*i+5*j+k)
c=(char *)malloc;が必要なわけは、変数の場合変数のアドレスが自動的に割り振られるのに対して、
ポインタの場合アドレスが割り振られないからです。
c=(char *)malloc;によって、コンピュータに自動的にアドレスを割り振るようにお願いしているわけです。
では、次の問題です。
char a[8][4][5];
char b[160];
char *c;
の場合は、どうでしょうか。
解答は第6話で。




第4話へ 第6話へ



初心者のためのjava 入門 基礎から応用まで
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第2部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第3部
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすい vb 入門 vba 入門 基礎から応用まで 第1部
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ