すでにファイルに保存してある場合は、メニューの6番を選択します。
メニューの2番を選択すると、確かに成績表が読み込まれているのが
わかります。
これに、データを継ぎ足したり、削除したりして保存することができます。
ここでは、簡単のためファイル名は決まったものを使うようにしてあり、 ユーザーがファイル名を入力することはできません。
では、プログラムを見てみましょう。
// vector05.cpp #define FNAME "seiseki.txt" #include <iostream> #include <vector> #include <string> #include <fstream> using namespace std; int menu(); int input_data(); int show_data(); int shusei(); int del(); int read_file(); int write_file(); vector<int> point; vector<string> shimei;ファイルを扱うためfstreamライブラリをインクルードします。(iostreamライブラリが あれば、fstreamライブラリが無くても可。ここでは、ライブラリ名を覚えるためインクルード)
read_file, write_file関数が増えました。
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 4: del(); break; case 5: write_file(); break; case 6: read_file(); break; case 0: endmark = 1; break; } if (endmark == 1) break; } return 0; }メニューの5,6が増えました。
int menu() { int no; while (1) { cout << endl; cout << "**** MENU ***" << endl; cout << "1:データ入力" << endl; cout << "2:データ表示" << endl; cout << "3:データ修正" << endl; cout << "4:データ削除" << endl; cout << "5:ファイルに保存" << endl; cout << "6:ファイルから読み出し" << endl; cout << "0:終了" << endl; cout << "---> "; cin >> no; if (no < 0 || no > 6) { cout << endl; cout << "番号が不正です" << endl; continue; } break; } return no; }メニューの5,6番が増えています。
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(); } 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; } int shusei() { int no, datano, pt; string nm, yesno; vectorこれらの関数に変更はありません。::iterator p; vector ::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; } int del() { int no, datano; char yn[8]; vector ::iterator p; vector ::iterator q; p = point.begin(); q = shimei.begin(); while (1) { datano = (int)point.size(); if (datano == 0) { cout << "データがありません" << endl; return -1; } show_data(); cout << "削除するデータの番号 -- "; cin >> no; if (no < 0 || no > datano) { cout << "番号が不正です" << endl; return -2; } cout << no << "番のデータ(" << shimei[no] << ")を削除しますか(Y/N) -- "; cin >> yn; if (strcmp(yn, "Y") == 0) { p += no; point.erase(p); q += no; shimei.erase(q); cout << "削除されました" << endl; p = point.begin(); q = shimei.begin(); } cout << "続けますか(Y/N) -- "; cin >> yn; if (strcmp(yn, "Y") != 0) break; } return 0; }
int read_file() { ifstream file_in; int data_no, i, p; string yn, data, data2; const char *lpszStr; data_no = (int)shimei.size(); if (data_no != 0) { cout << "現在のデータが無効になりますがよろしいですか(Y/N)--"; cin >> yn; if (yn == "N" || yn == "n") return -2; //現在のデータをすべて削除 for (i = 0; i < data_no; i++) { shimei.pop_back(); point.pop_back(); } } file_in.open(FNAME); if (!file_in.is_open()) { cout << "ファイルのオープンに失敗しました" << endl; return -1; } getline(file_in, data); lpszStr = data.c_str(); data_no = atoi(lpszStr); for(i = 0; i < data_no; i++) { getline(file_in, data); shimei.push_back(data); getline(file_in, data); lpszStr = data.c_str(); p = atoi(lpszStr); point.push_back(p); } file_in.close(); return 0; }ファイルからデータを読み出すには、ifstreamクラスを使います。
ファイルから読み出す前に、現在すでにデータ入力が行われているかどうかを 調べます。簡単のため、ファイルから読み出す場合は、現在入力されている データは削除して、新たに読み込んだデータのみを使うようにします。
ファイルをオープンするには、ifstreamクラスのopenメンバ関数を使います。
ファイルがオープンされたかどうかを確認するにはis_openメンバ関数を使います。
getline関数でファイルの1行目を読み出します。ここには、データの個数が書かれているもの とします。上のプログラムではstringクラスのdataオブジェクトとして読み込まれます。
さて、これをint型に変換するにはC言語に慣れ親しんだ人にはatoi関数を使いたくなるものです。 しかし、
atoi(data);
などとすることはできません。これには、stringクラスのc_strメンバ関数を使って 文字列へのポインタを取得する必要があります。
次に、データの個数だけファイルから読み出して、push_backします。
データを読み終わったらcloseメンバ関数でファイルをクローズします。
int write_file() { ofstream file_out; int data_no, n; data_no = (int)point.size(); if (data_no == 0) { cout << "保存すべきデータがありません" << endl; return -1; } cout << data_no << "個のデータがあります" << endl; file_out.open(FNAME, ios_base::trunc); file_out << (int)shimei.size() << endl; for (n = 0; n < data_no; n++) { file_out << shimei[n] << endl; file_out << point[n] << endl; } file_out.close(); return 0; }ファイルに書き込む関数です。
ofstreamクラスを使います。
openメンバ関数でファイルをオープンします。この時、オープンモードにios_base::trunc を指定して、もしすでにファイルが存在してデータがあった場合は切り詰めるようにします。
データを書き終わったらcloseメンバ関数で、ファイルをクローズします。
さて、今回行ったファイル入出力は第28章で行ったファイル入出力とほとんど同じですね。
Update Jan/29/2003 By Y.Kumei