第8講 関数の学習
第3話 関数の戻り値と引数
第2話問題解答
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
//変数の宣言
int w1,w2,w3,w4;
w1=f1();//1から50までの整数の和
w2=f2();//2から100までの偶数の和
w3=f3();//1から100までの整数の2乗の和
w4=f4();//2から100までの偶数の2乗の和
textBox5->Text=(w1+w2+w3+w4).ToString();
}
int f1(void){
int i,w;
w=0;
for(i=1;i<101;i++){
w+=i;
}
textBox1->Text=w.ToString();
return w;//wを戻り値として戻す
}
int f2(void){
int i,w;
w=0;
for(i=2;i<101;i+=2){
w+=i;
}
textBox2->Text=w.ToString();
return w;//wを戻り値として戻す
}
int f3(void){
int i,w;
w=0;
for(i=1;i<101;i++){
w+=i*i;
}
textBox3->Text=w.ToString();
return w;//wを戻り値として戻す
}
int f4(void){
int i,w;
w=0;
for(i=2;i<101;i+=2){
w+=i*i;
}
textBox4->Text=w.ToString();
return w;//wを戻り値として戻す
}
};
}
同じ課題を今度は、累積値を引数として渡すことによって、成し遂げてみましょう。
累積なのでForm1も次のように改造しておくことにしましょう。
引数付き関数は、次のように書きます。
int 関数名(int w){
・
・
・
retun w;
}
そして、System::Void button1_Clickから関数を呼び出すとき、
w1=f1(0);//1から50までの整数の和
w2=f2(w1);//1から50までの整数の和
・
・
・
のように使います。
ここでの注意点は、
f2(w1)の()内の変数名とint f2(int w)の()内の変数名は、異なっていても全然問題ないということです。
ですから、例えば
int f2(int a){
int i;
for(i=1;i<101;i+=2){
a+=i;
}
textBox2->Text=a.ToString();
return a;
}
でもよいですし、
int f2(int w){
int i;
for(i=1;i<101;i+=2){
w+=i;
}
textBox2->Text=w.ToString();
return w;
}
でもよいのです。関数内で統一されていればよいわけです。
int i,w; のwがないことと
w=0;がない点に注目して下さい。
int w;とすると重複して宣言されることになり、エラーします。
もしw=0;を入れると、累積でなくなってしまいます。
f1(0)の合計値にさらに足していくことによって、すべての合計値の和を求めようとしているので累積でなくてはいけないわけです。
わかりやすさを優先するなら、f2(・)の()内の変数名とint f2(・・・)の()内の変数名を同じにして、
f2(w)で関数を呼び出し、
int f2(int w){
int i;
for(i=1;i<101;i+=2){
w+=i;
}
textBox2->Text=w1.ToString();
return w;
}
ということになります。
この場合は、System::Void button1_Clickの部分は
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
//変数の宣言
int w;
w=0;
w=f1(w);//1から50までの整数の和
w=f2(w);//2から100までの偶数の和
w=f3(w);//1から100までの整数の2乗の和
w=f4(w);//2から100までの偶数の2乗の和
textBox5->Text=w.ToString();
}
でもよいことになります。
w=f1(w);に対して?マークが浮かんでいる方もいらっしゃるかと思います。
これは、wに対してf1の加工をしてそれを改めてwの値にしなさいということなのです。
基本は、w=w+aなどと同じです。これもwを加工して新たにwの値としています。
では皆さん、プログラミングを考えてみてください。
解答例は、例によって30行下。
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
//変数の宣言
int w;
w=0;
w=f1(w);//1から50までの整数の和
w=f2(w);//2から100までの偶数の和
w=f3(w);//1から100までの整数の2乗の和
w=f4(w);//2から100までの偶数の2乗の和
textBox5->Text=w.ToString();
}
int f1(int w){
int i;
for(i=1;i<101;i++){
w+=i;
}
textBox1->Text=w.ToString();
return w;//wを戻り値として戻す
}
int f2(int w){
int i;
for(i=2;i<101;i+=2){
w+=i;
}
textBox2->Text=w.ToString();
return w;//wを戻り値として戻す
}
int f3(int w){
int i;
for(i=1;i<101;i++){
w+=i*i;
}
textBox3->Text=w.ToString();
return w;//wを戻り値として戻す
}
int f4(int w){
int i;
for(i=2;i<101;i+=2){
w+=i*i;
}
textBox4->Text=w.ToString();
return w;//wを戻り値として戻す
}
};
}
実は、引数は複数以上でもよいのです。複数以上使って、
pragma once
int a[5][5],b[5][5],i,j;
namespace while文による2次元ループ {
using namespace System;
・
・
・
#pragma endregion
String^ w=L"";
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
f1(); //データ1発生
f2(); //データ1表示
f3(); //データ2発生
f4(); //データ2表示
f5(); //データ1とデータ2の和の計算と表示
}
void f1(void){
i=0;
while(i<5){
j=0;
while(j<5){
a[i][j]=5*i+j+1;
j++;
}
i++;
}
}
void f2(void){
i=0;
while(i<5){
j=0;
while(j<5){
if(a[i][j]<10)w+=L"0"+(a[i][j]).ToString()+L"
";
if(a[i][j]>=10)w+=(a[i][j]).ToString()+L" ";
j++;
}
w+=L"\n";
i++;
}
label1->Text=w;
}
void f3(void){
i=0;
while(i<5){
j=0;
while(j<5){
b[j][i]=5*i+j+1;
j++;
}
i++;
}
}
void f4(void){
i=0;
w=L"";
while(i<5){
j=0;
while(j<5){
if(b[i][j]<10)w+=L"0"+(b[i][j]).ToString()+L"
";
if(b[i][j]>=10)w+=(b[i][j]).ToString()+L" ";
j++;
}
w+=L"\n";
i++;
}
label2->Text=w;
}
void f5(void){
i=0;
w=L"";
while(i<5){
j=0;
while(j<5){
if(a[i][j]+b[i][j]<10)w+=L"0"+(a[i][j]+b[i][j]).ToString()+L"
";
if(a[i][j]+b[i][j]>=10)w+=(a[i][j]+b[i][j]).ToString()+L"
";
j++;
}
w+=L"\n";
i++;
}
label3->Text=w;
}
};
}
グローバル変数int a[5][5],b[5][5],i,j;とString^ w=L"";
をローカル変数に直したいと思います。
2次元配列そのものを渡すことはできませんので、
2次元配列をポインタのポインタに変更して、ポインタのポインタのアドレスを渡します。
例えば、 private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e)の部分は
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
//変数の宣言
int **a,**b,i;
String^ w;
//ポインタのポインタとポインタの初期化
a=(int**)malloc(100);
for(i=0;i<5;i++)a[i]=(int*)malloc(20);
b=(int**)malloc(100);
for(i=0;i<5;i++)b[i]=(int*)malloc(20);
//データ1発生
f1(a,w);
//データ1表示
w=L"";
w=f2(a,w);
label1->Text=w;
//データ1表示
f3(b,w);
//データ2表示
w=L"";
w=f4(b,w);
label2->Text=w;
//データ1とデータ2の和の計算と表示
w=L"";
w=f5(a,b,w);
label3->Text=w;
}
とします。
そして、f1とf2については
void f1(int** a,String^ w){
・
・
・
}
String^ f2(int** a,String^ w){
・
・
・
return w;
}
等とします。
また、mallocを使うためには冒頭でインクルードファイルのstdlib.hを
インクルードしておく必要があることを忘れないようにしましょう。
#pragma once
#include<stdlib.h> //malloc使うためにインクルードファイルstdlib.hを読み込む
namespace while文による2次元ループ {
・
・
第2話へ 第4話へ