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