みなさんはクラスというものをどのように思いましたか。クラスはプログラマが独自に定義した「型」です。この「型」を使うことで、いくらでも「オブジェクト」がつくれます。つまり、
クラス名 変数(あれば引数);
と書くだけで、オブジェクト(インスタンスともいう)が生成され、変数がそのオブジェクトを表すのでした。このような「クラス」の使い方はいろいろありますが、基本的には、「プログラムの部品」(あるいは、オブジェクトを部品と考えると、「部品の設計図」)であると言えるでしょう。
この「部品」はまたプログラム本体とかなり独立なものです。つまり、一度書いたクラスはそのまま別のプログラムでも使えるはずなのです。このように他の部分と比較的独立していて使いまわしが出来るということは「クラス」の大きな長所なのです。
まず、第一に他人と協力してプログラムを組むのに便利です。例えば、動物園のプログラムを書くとしましょう。このとき、クラスとして「熊」や「ライオン」や「象」をそれぞれ別のプログラマが書いて持ちよるということが出来ます。
第二に、自分ひとりでプログラムを書く場合でも、プログラムをつくりやすくなります。俗に「半年前に書いたコードは他人が書いたコードと同じ」と言います。ちょっとプログラムを書くとこれはすぐ実感できるのではないでしょうか。クラスを使えばそうではなくなる...と言うつもりはありません。それでも、プログラムが明白に部品に分けられているので、後で読んでも理解しやすいのです。自分の書いたプログラムが理解しやすいも何もないものだと思うかもしれませんが、実際これは重要です。
前回のおみくじプログラムでは、「おみくじ」をわざわざクラスにした理由はあまりわかりません。しかし、例えば、おみくじと猫が関連したプログラムをつくるならこのクラス「おみくじ」とクラス「猫」をそのまま持ってきて、それらを組み合わせるプログラムを書けばよいのです。
a > b aがbより大
a >= b aがbより大かまたは等しい
a < b aがbより小
a <= b aがbより小かまたは等しい
a == b aとbが等しい //「=」がふたつあることに注意
a != b aとbが等しくない
この「条件」を使ってwhile文というものは次のように書かれます。
while(条件){
処理
}
//while_sample.cpp
#include <iostream>
using namespace std;
int main()
{
int i;
i = 0;
while(i < 100){
cout << i <<
" "; //見やすさのため数字の後に空白をいれた
i++;
//iを1増やせという意味です。(下を参照)
}
}
Fig.1 while_sample.exeの実行画面
while_sample.cppの説明は次のようになります。
まず整数を入れる変数iが定義され、iに0が代入されます。それから、while文になるわけですが、while文では最初に条件がチェックされます。0は100より小さいので、whileの中の条件「i < 100」が成立し、whileの中カッコの処理が実行されます。
whileの中カッコの中にはcout文がありますね。これが実行されるとiが画面に出力されるわけですが、それはつまり画面に0と出力されるということです。その後、
「i++;」というものがあります。これは、「iを1増やせ」という意味になるのです。(ちなみに、「i--;」とすると、「iを1減らせ」になります。)ここで覚えてください。これで、iが1増えて1になります。
そして、また、whileの条件「i < 100」が調べられますが、当然、1は100より小さいので条件が成立し、whileの中カッコの処理が実行されます。それは、画面に「1」と出力し、また、「i++;」でiを1増やし、iは2になり、...と続いていくのです。
iが99になって出力された後に「i++;」で1増やされて100となると、「i < 100」の条件が成立しなくなるので、whileの処理は終了します。ちなみにこのような繰り返しをループといい、ループが終わることをループをぬけるなどとも言います。上の例では「iが100になると(プログラムの実行が)ループをぬける」などと言います。
このようなループはプログラミングでは必須なので自分でもいろいろ実験してください。
ところで、C++では
int i;
i = 0;
int i = 0; //「iという整数変数を使うがその値をはじめに0にする」という意味
と書くことができます。以下では、このような書き方も使います。ループを実現するには、for文というものもあります。たとえば、while_sample.cppと同じ動作をするプログラムを、for文を使って次のように書けます。
//for_sample.cpp
#include <iostream>
using namespace std;
int main()
{
int i;
for(i = 0; i < 100; i++){
cout << i << "
";
}
}
forの丸カッコの中は「はじめにiを0として、iが100より小さい間は中カッコの中の処理を実行する。ただし、処理を実行するたびにiを1増やす」という意味になります。これはあれこれ考えるよりこのままの形で覚えてください。例えば、「愛してる」と100回繰り返すプログラムはどうすればよいでしょう。それは、次のようになります。
//for_sample2.cpp
#include <iostream>
using namespace std;
int main()
{
int i;
for(i = 0; i < 100; i++){
cout << "愛してる ";
}
}
Fig.2 for_sample2.exeの実行画面(もういいよって感じ?)
なお、「iの定義」は、for文の丸カッコの最初のところですることもできます。つまり、
for(int i = 0; i < 100; i++){
cout << "愛してる ";
}
のようにfor文を書くこともできるのです。この場合、iはfor文内のみで有効な変数になります。
それでは、for_sample2.cppと同じ動作をするプログラムをwhileを使って書いてみてください。それは、次のようになりますね。
//while_sample2.cpp
#include <iostream>
using namespace std;
int main()
{
int i = 0;
while(i < 100){
cout << "愛してる ";
i++;
}
}
ところで、もし、次のようなプログラムをコンパイルして実行したらどうなるでしょう。
//エラー
#include <iostream>
using namespace std;
int main()
{
int i = 0;
while(i < 100){
cout <<
"愛してる ";
}
}
しかし、以下のプログラムをみてください。
//input100.cpp
#include <iostream>
using namespace std;
int main()
{
int i = 0;
while(i != 100){
cout << "好きな数字を入力してください。"
<<endl;
cin >> i;
}
cout << "終了しました。" <<endl;
}
Fig.3 input100.exeの実行画面
whileの丸カッコの中には「!=」がありますね。この意味は「iが100に等しくない限りループを続ける」なのです。もう一度上に書いた「条件」のところを見て考えてみてください。
実は、上のような仕組みをわざと無限ループを使って実現することもあります。それには、while(1)(または、for(;;))というものを使います。こう書くと無限ループになるのです。
そして、無限ループであっても、そうではない普通のループであっても、ループの中で「break;」という命令を実行するとループからぬける(ループを終了する)ということになっています。これを使うとinput100.cppと同じ動作をするプログラムを次のように書くことができるのです。
//mugenloop.cpp
#include <iostream>
using namespace std;
int main()
{
int i = 0;
while(1){
cout << "好きな数字を入力してください。"
<<endl;
cin >> i;
if(i == 100){
break;
}
}
cout << "終了しました。" <<endl;
}
このような無限ループはいろいろなところで使えます。たとえば、「大魔王とヒーローの対決ゲーム」で、対決の決着がつくまでゲームを続けるようにすることもできます。しかし、そのためにはもう一つ準備がいるので、次回はその話をしましょう。
そのかわり、ここでは、練習問題をひとつ出します。正解がでるまで同じ質問を繰り返すプログラムを書いてください。...答えは、次のようになるでしょう。
//quiz.cpp
#include <iostream>
using namespace std;
int main()
{
int i;
while(1){
cout << "日本一高い山はどれですか。"
<< endl;
cout << "数字を入力してください。"
<< endl;
cout << "1.ヒマラヤ 2.富士山 3.ロッキー"
<< endl;
cin >> i;
if(i == 2){
break;
}
cout << "はずれです。"
<< endl; //不正解の場合breakされないので
//この文が実行される。
}
//ループ終了後次の文が実行される。
cout<<"正解なので終了しました。"<<endl;
}
Fig.4 quiz.exeの実行画面
この手のプログラムの基本形ですので、よく考えてみてください。
それでは、前回のおみくじクラスを使って「7日(1週間)分のうらないを一度にやる」プログラムを書いてみます。
//omikuji3.cpp
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
class Omikuji
{
int un; //ラッキーナンバー
public:
Omikuji(); //コンストラクタ
void hiku();
};
//コンストラクタ、ラッキーナンバーをユーザに代入してもらいます
Omikuji::Omikuji()
{
srand( (unsigned)time( NULL ) );
cout<<"自分のラッキーナンバー(1〜5)を入力してください。"<<endl;
cin>>un; //自分のラッキーナンバーを代入
}
//おみくじを引く
void Omikuji::hiku()
{
int x;
x = rand() % 5 + 1; //1〜5の乱数を発生させ、xに代入、これが引いたおみくじの番号
cout << "あなたの運勢は";
if(x == un){
//xとunが等しければ大吉
cout << "大吉ということです。"
<< endl;
}
else{
//xとunが等しくなければ「普通」
cout<<"並みということです。"<<endl;
}
}
int main()
{
Omikuji ok; //おみくじ
cout << "1週間分の占いです。"
<< endl;
for(int i = 0; i < 7; i++){
cout << "今日から"
<< i << "日後:" << endl;
ok.hiku();
}
}
Fig.5 omikuji3.exeの実行画面
残念ながら表示がちょっとさえないですね。これをよくするには、Omikujiを少々書き直す必要が出てきますが、それは「わずか」であるはずです。