第7講 for文以外の繰り返し処理
第3話 前話問題解答と解説
前話問題解答例
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
//変数の宣言
int a,b,c,i;
long w;
//条件値(はじめの値、合計上限値、変化の幅)を取得
a=int::Parse(textBox1->Text);
b=int::Parse(textBox2->Text);
c=int::Parse(textBox3->Text);
//初期化
w=0;
i=a;
//1乗の和の計算と表示
while(w+i<=b){
w=w+i;
i=i+c;
}
textBox4->Text=w.ToString();
//2乗の和の計算と表示
w=0;
i=a;
while(w+i*i<=b){
w=w+i*i;
i=i+c;
}
textBox5->Text=w.ToString();
//3乗の和の計算と表示
w=0;
i=a;
while(w+i*i*i<=b){
w=w+i*i*i;
i=i+c;
}
textBox6->Text=w.ToString();
//4乗の和の計算と表示
w=0;
i=a;
while(w+i*i*i*i<=b){
w=w+i*i*i*i;
i=i+c;
}
textBox7->Text=w.ToString();
}
};
}
(赤の部分を本日(2011/07/10)に訂正しました。)
解説
どうです。皆さんうまくいきましたか。
うまくいかなかった方もいらっしゃるのではないでしょうか。
実は前話の課題をwhile文で実行するのは、かなり難しいのです。
私もうっかり最初は次にようにしてしまいました。
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
//変数の宣言
int a,b,c,i;
long w;
//条件値(はじめの値、終わりの値、変化の幅)を取得
a=int::Parse(textBox1->Text);
b=int::Parse(textBox2->Text);
c=int::Parse(textBox3->Text);
//初期化
w=0;
i=a;
//1乗の和の計算と表示
while(1){
w=w+i;
i=i+c;
if(w>b)break;
}
textBox4->Text=w.ToString();
//2乗の和の計算と表示
w=0;
i=a;
while(1){
w=w+i*i;
i=i+c;
if(w>b)break;
}
textBox5->Text=w.ToString();
//3乗の和の計算と表示
w=0;
i=a;
while(1){
w=w+i*i*i;
i=i+c;
if(w>b)break;
}
textBox6->Text=w.ToString();
//4乗の和の計算と表示
w=0;
i=a;
while(1){
w=w+i*i*i*i;
i=i+c;
if(w>b)break;
}
textBox7->Text=w.ToString();
}
};
}
ところがこれだと実行結果例は、
となり、すべてが合計条件値を超えてしまっています。
理由は、if(w>b)break;でループを抜ける判定するときすでに上限値を超えてしまっています。
そこで、if(w>b)break;をif(w=>b)break; と改良したらどうでしょうか。
確かに、1乗の和だけ条件を満たしました。
しかし、2乗以上ではすべて10を超えてしまいました。
理由は、1乗の場合は
1+2+3+4=10なので、if(w=>b)break;でたまたま条件に反せずループを抜け出しただけです。
2乗の場合は、
1の2乗+2の2乗=1+4=5<10なので、ループ処理が続きます。
次の
1の2乗+2の2乗+3の2乗=1+4+9=14でループを抜けることになりますが、
すでに上限値の10を超えてしまっています。
w=w+i*i;
i=i+c;
の処理をしてから、判定していることに問題があるのでしょうか。
もし、そうなら次のように改良すれば、問題は解決するはずです。
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
//変数の宣言
int a,b,c,i;
long w;
//条件値(はじめの値、終わりの値、変化の幅)を取得
a=int::Parse(textBox1->Text);
b=int::Parse(textBox2->Text);
c=int::Parse(textBox3->Text);
//初期化
w=0;
i=a;
//1乗の和の計算と表示
while(1){
if(w=>b)break;
w=w+i;
i=i+c;
}
textBox4->Text=w.ToString();
//2乗の和の計算と表示
w=0;
i=a;
while(1){
if(w=>b)break;
w=w+i*i;
i=i+c;
}
textBox5->Text=w.ToString();
//3乗の和の計算と表示
w=0;
i=a;
while(1){
if(w>=b)break;
w=w+i*i*i;
i=i+c;
}
textBox6->Text=w.ToString();
//4乗の和の計算と表示
w=0;
i=a;
while(1){
if(w=>b)break;
w=w+i*i*i*i;
i=i+c;
}
textBox7->Text=w.ToString();
}
};
}
ところが実行結果は同じです。
なぜでしょうか。
w=w+i;
i=i+c;
の処理をする前にループを抜けているのに、なぜうまくいかないのでしょうか。
理由は、簡単です。if(w=>b)break; の判定が行われたとき、2乗以降では上限値の10を超えてしまっているのです。
1の2乗+2の2乗=1+4=5 の次は、1の2乗+2の2乗+3の2乗=1+4+9=14ですでに超えてしまっています。
1の2乗+2の2乗=1+4=5 のとき、5<10でif(w=>b)break;の条件式を満たしませんから、
w=w+i;
i=i+c;
の処理は行われてしまうのです。
そして、その処理をした際に、
1の2乗+2の2乗+3の2乗=1+4+9=14で上限値の10を超えてしまうのです。
超えた後に、textBox5->Text=w.ToString();での表示ですから当然14が表示されてしまいます。
つまり、最後の処理
w=w+i;
i=i+c;
は余計だったのです。
以上の問題を解決するためには、while(w+i*i<=b)のように条件を変更すればよいのです。
while文が前判定であるのに対して、
後判定を行う処理もあります。
それが、do...while文です。
do{
・
・
・
}while(条件式);
その際の注意は、while文では『}』で終わっているため『;』がいらないのに対して、
do...while文の場合は最後が『)』であるため『;』がいるということです。
;は文の終わりを示しますが、『}』でもC言語は文の終わりと見なしてくれます。
ですから、『}』で終わるときは『;』がいらないのです。
それ以外は、『;』は普通の文の『。』に相当するものなので必ず入れなければなりません。
プログラムをdo...while文で書き直してみましょう。
第2話へ 第4話へ