第13講 ベクタの学習
第9話 ベクタのアドレスを直接関数に渡すその1
新規プロジェクトで次のようなフォームを作り、下のようにコーティングしてください。

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
         vector< vector<int> > a;
         a.resize(5);
         int i;
         String^ w;
         for(i=0;i<5;i++)(a[i]).resize(4);
           a=f1(a);
           w=g1(w,a);
           label1->Text=w;
         }
         vector< vector<int> > f1(vector< vector<int> > x){
           int i,j,m,n;
           m=x.size();
           n=(x[0]).size();

           for(i=0;i<m;i++)
             for(j=0;j<n;j++)
               x[i][j]=rand()%1000;

           return(x);
         }
         String^ g1(String^ w,vector< vector<int> > x){
           int i,j,m,n;
           m=x.size();
           n=(x[0]).size();
           for(i=0;i<m;i++){
             for(j=0;j<n;j++)
               if(x[i][j]<10)
                 w+=L"000"+(x[i][j]).ToString()+L" ";
               else if(x[i][j]<100)
                 w+=L"00"+(x[i][j]).ToString()+L" ";
               else if(x[i][j]<1000)
                 w+=L"0"+(x[i][j]).ToString()+L" ";
               else
                 w+=(x[i][j]).ToString()+L" ";
               w+=L"\n";
           }
           return(w);
        }

(コピーペースト用

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
vector< vector<int> > a;
a.resize(5);
int i;
String^ w;
for(i=0;i<5;i++)(a[i]).resize(4);
a=f1(a);
w=g1(w,a);
label1->Text=w;
}
vector< vector<int> > f1(vector< vector<int> > x){
int i,j,m,n;
m=x.size();
n=(x[0]).size();
for(i=0;i<m;i++)
for(j=0;j<n;j++)
x[i][j]=rand()%1000;

return(x);
}
String^ g1(String^ w,vector< vector<int> > x){
int i,j,m,n;
m=x.size();
n=(x[0]).size();
for(i=0;i<m;i++){
for(j=0;j<n;j++)
if(x[i][j]<10)
w+=L"000"+(x[i][j]).ToString()+L" ";
else if(x[i][j]<100)
w+=L"00"+(x[i][j]).ToString()+L" ";
else if(x[i][j]<1000)
w+=L"0"+(x[i][j]).ToString()+L" ";
else
w+=(x[i][j]).ToString()+L" ";
w+=L"\n";
}
return(w);
}




ソースコードの内容を解説する前に、
書き方について一言説明しておきましょう。
           for(i=0;i<m;i++){
             for(j=0;j<n;j++)
               if(x[i][j]<10)
                 w+=L"000"+(x[i][j]).ToString()+L" ";
               else if(x[i][j]<100)
                 w+=L"00"+(x[i][j]).ToString()+L" ";
               else if(x[i][j]<1000)
                 w+=L"0"+(x[i][j]).ToString()+L" ";
               else
                 w+=(x[i][j]).ToString()+L" ";

               w+=L"\n";
           }

               if(x[i][j]<10)
                 w+=L"000"+(x[i][j]).ToString()+L" ";
               else if(x[i][j]<100)
                 w+=L"00"+(x[i][j]).ToString()+L" ";
               else if(x[i][j]<1000)
                 w+=L"0"+(x[i][j]).ToString()+L" ";
               else
                 w+=(x[i][j]).ToString()+L" ";

は1文であることに注意してください。1文なので
             for(j=0;j<n;j++){
               if(x[i][j]<10)
                 w+=L"000"+(x[i][j]).ToString()+L" ";
               else if(x[i][j]<100)
                 w+=L"00"+(x[i][j]).ToString()+L" ";
               else if(x[i][j]<1000)
                 w+=L"0"+(x[i][j]).ToString()+L" ";
               else
                 w+=(x[i][j]).ToString()+L" ";

             }
{}がなくてもよいのです。しかし、
           for(i=0;i<m;i++){
               ・
               ・
               ・
           }
については、中が2文になっているので{}がないとエラーします。


さて、内容の解説に入りましょう。最初に注目して頂きたいのは、
a=f1(a);です。ここはf1(a);にしてvoid f1(vector< vector<int> > x)
(その際にはもちろん、return(x);は削らないとエラーになります。void型ですから何も返してはいけません。)としても良さそうに思われますが、
実験するとうまくいきません。正しくは、
と表示されなければならないのに
となってしまいます。
f1で処理している間に、aのアドレスが進んでしまうのでg1で表示されているアドレスは、
a+5*4以降になってしまうのではないかというのが私の推測です。
a+5*4以降は代入されていませんので、初期値である0が表示されてしまうのではないでしょうか。
ですから、やはりaの最初のアドレスをreturn(x);で返してやらなければならないのでしょう。
a=f1(a)は?が浮かぶ方もいらっしゃると思いますが、=が数学とは違い←であることに注意して、
=によってaのアドレスを最初に戻していると解釈すれば、?は消えると思いますが、どうでしょうか。
f1によって、aに一連の操作を加え、それをaに戻していると解釈すれば、
摩訶不思議に覚えたa=f1(a)も自然ではないでしょうか。
a=a+5などと何も変わりません。これもaに操作を加え(具体的には5を加えている)、aに戻しているのです。
操作を加え元に戻していると考えれば、w=g1(w,a)も何の不思議もありません。
wに操作を加え、それをwに代入することによって新たなwとしているのです。

m=x.size();n=(x[0]).size();はベクタのサイズを取得しています。
m=x.size();で行数を、n=(x[0]).size();で列数を取得しています。
ベクタと配列はここにも違いがあります。
aが配列であれば、行数と列数の情報も送らなければならず、a=f1(a,m,n)と引数が増えてしまいますが、
ベクタの場合f1(a)でよいのです。.size()で行数や列数などのサイズを取得できるからです。
サイズを決定するときは.resize()で、サイズ取得は.size()です。

では、また問題を出しましょう。
問1 2次元ベクタbを用意して、次のように表示させるプログラミングを考えましょう。

ただし、データを作るときと表示させるときはf1とg1を再利用してください。
問2 さらに、2つの行列の和も表示させましょう。

ただし、新しい2次元ベクタは用意しないで、ベクタa、bのみで実現してください。


第11講第6話へ
 第12講第1話へ 第13講第8話へ 第13講第10話へ


vc++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ