今回はvectorクラスを利用して、簡単な成績表を作ります。
起動すると、左のような簡単なメニューが表示されます。
データを入力する時は「1」を選択します。
左の図のように氏名、得点の順に入力していきます。
入力が終了したら「氏名」に「end」と入力します。
入力が終了したらメニューから「2」を選択して、入力したデータを
表示して確認します。
[データ番号]氏名---得点
という形式で表示されます。氏名や得点を修正する場合は データ番号を指定します。
メニューの「3」を選択して得点を修正してみましょう。
データ番号1番の佐藤さんの得点を80点に修正します。
確かに佐藤さんの得点が80点に修正されています。
では、プログラムを見てみましょう。
// vector03.cpp
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int menu();
int input_data();
int show_data();
int shusei();
vector<int> point;
vector<string> shimei;
int main()
{
int menuno, endmark = 0;
string nm, yesno;
while (1) {
menuno = menu();
switch (menuno) {
case 1:
input_data();
break;
case 2:
show_data();
break;
case 3:
shusei();
break;
case 0:
endmark = 1;
break;
}
if (endmark == 1)
break;
}
return 0;
}
main関数の中は、無限ループになっています。
これを抜けることのできるのは、endmarkが1になった時のみです。
どういう時に1になるかというと、menunoが0になった時です。これは、
menu関数(自作、後出)が0を返した時(メニューで「終了」を選択した時)ですね。
int menu()
{
int no;
while (1) {
cout << endl;
cout << "**** MENU ***" << endl;
cout << "1:データ入力" << endl;
cout << "2:データ表示" << endl;
cout << "3:データ修正" << endl;
cout << "0:終了" << endl;
cout << "---> ";
cin >> no;
if (no < 0 || no > 3) {
cout << endl;
cout << "番号が不正です" << endl;
continue;
}
break;
}
return no;
}
メニューを表示する関数です。これも内部は無限ループになっています。 ユーザーが正しいメニュー番号(0-3)を入力するとループを抜けます。 戻り値はメニュー番号となりなります。
int input_data()
{
string nm;
int pt;
while (1) {
cout << "氏名 = ";
cin >> nm;
if (nm == "end")
break;
shimei.push_back(nm);
cout << "得点 = ";
cin >> pt;
point.push_back(pt);
cout << endl;
}
return (int)shimei.size();
}
データ入力の関数です。これも無限ループとなっています。氏名、得点が入力されるとpush_backメンバ関数でデータをvectorに 追加していきます。
氏名に「end」が入力されるとループを抜けて関数が終了します。
戻り値はvectorに格納されているデータの個数となります。(この値は このプログラムでは使用していません)
int show_data()
{
int i, no;
no = (int)point.size();
cout << endl;
for (i = 0; i < no; i++)
cout << "[" << i << "]" << shimei[i] << "---" << point[i] << endl;
return 0;
}
データを表示する関数です。データの個数だけfor文で、データ番号、氏名、得点を表示します。
int shusei()
{
int no, datano, pt;
string nm, yesno;
vector<int>::iterator p;
vector<string>::iterator q;
p = point.begin();
q = shimei.begin();
datano = (int)point.size();
while (1) {
cout << endl;
cout << "修正するデータの番号 = ";
cin >> no;
if (no < 0 || no >= datano) {
cout << "番号が不正です" << endl;
continue;
}
cout << "氏名 = ";
cin >> nm;
cout << "得点 = ";
cin >> pt;
q += no;
p += no;
*q = nm;
*p = pt;
cout << "続けますか(Y/N) -- ";
cin >> yesno;
if (yesno == "N")
break;
}
return 0;
}
データを修正する関数です。これまた、無限ループとなっています。まず、修正するデータ番号を入力させます。データ番号は0からデータの個数−1 までとなります。この範囲外の入力があった場合はその旨表示して、continue文で ループの最初に戻ります。
データ番号が範囲内にあれば、氏名、得点を入力させます。
さて、データの修正には「反復子」と呼ばれるものを使うと便利です。
vector<型名>::iterator 名前;というような感じで宣言します。
vector<int>::iterator p;
p = point.begin();
というようにすると、pはpointオブジェクトの最初のデータを指しています。 データそのものは
*p
で表すことができます。これを参照したり、これに代入することも可能です。
p++;
とすると、pは次のデータを指すことになります。さらに、
p += N;
とすると、pは最初に指し示していたものより、N個後ろのデータを指すことになります。
同様に
p--;
とか
p -= N;
などとすることもできます。
実際にはデータが存在しないところを指し示してしまうと、結果はどうなるかわかりませんので注意してください。
ちょっとポインタと似ているところがありますね。
さて、このプログラムでデータを追加するにはメニューから再度「データ入力」を選択すれば可能です。しかし、データの削除ができません。これを改良してみてください。
Update Nov/05/2002 By Y.Kumei