textデータ読み込み出力

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
つるぴか

textデータ読み込み出力

#1

投稿記事 by つるぴか » 14年前

C++で

コード:

#include<iostream>
#include<fstream>
#include<string>
using namespace std;

class Student
{
	string name, studentId;
public:
	void setName(string n){ name = n; }
	void setID(string id){ studentId = id; }
	string getName() const{ return name; }
	string getID() const{ return studentId; }
};

int main()
{
	int num, n = 0;
	string name, id;
	Student Tka;
	Student *pTka;
	pTka = &Tka;

	cout << "学生の人数を入力してください" << endl;
	cin >> num;
	pTka = new Student[num];
	ofstream fTka("meibo.txt");

	while(n < num){
		cout << "学生番号を入力してください: ";
		cin >> id;
		pTka -> setID(id);
		cout << "名前を入力してください: ";
		cin >> name;
		pTka -> setName(name);
		n++;

		fTka << pTka -> getID() << endl;
		fTka << pTka -> getName() << endl;
	}
	
	fTka << "xxx" << endl;

	return 0;
}
ここで作成したmeibo.txtを読み込み、内容を表示するプログラムを作成したいのですがうまく読み込めません。
条件として
・Studentクラスを利用し、個々の学生情報をStudentオブジェクトに格納すること。
・オブジェクトは前もって5人分生成することとし、データが5人を超える場合「6人目以降は表示されません」というエラーメッセージを出力する処理を行うこと。
・出力は
No.1
学生番号: (読み込んだ学生番号)、 氏名: (読み込んだ氏名)
のように行うこと。

オブジェクトへの格納と読み込みが良く分かってないような気がします。
お力を貸していただければ幸いです。

box
記事: 2002
登録日時: 15年前

Re: textデータ読み込み出力

#2

投稿記事 by box » 14年前

つるぴか さんが書きました: ここで作成したmeibo.txtを読み込み、内容を表示するプログラムを作成したいのですがうまく読み込めません。
3点おたずねします。
(1)そもそも、meibo.txtの内容は、質問者さんが考えたとおりになっていますか?
(2)うまく読み込めない、とは、具体的にどういう状況を指すのでしょうか?
(3)内容を表示するために、どういうプログラムを書いたのでしょうか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: textデータ読み込み出力

#3

投稿記事 by beatle » 14年前

コード:

    Student Tka;
    Student *pTka;
    pTka = &Tka;
この3行で何をしているかは理解できていますか?さらにこのあと

コード:

    pTka = new Student[num];
としています。「オブジェクトは前もって5人分生成する」のですから、この行だけでいいのです。

コード:

    pTka = &Tka;
の行は余分ですよ。

さてこのあと

コード:

        pTka -> setID(id);
こんな風にしてsetIDメソッドを呼び出していますが、これでは常に先頭の生徒のsetIDが呼ばれてしまいます。

コード:

        pTka[0].setID(id);
と同じ効果なのです。
この状況をintの配列で説明すると

コード:

int array[5];
int* p = array;
for (int i = 0; i < 5; ++i)
{
    *p = i; // array[0]~array[4]に0~4を設定しているつもり
}
のようなことをしているのと同じなのです。p++とするか、pとするかしないと、常にarray[0]にしか書き込まれないわけです。

つるぴか

Re: textデータ読み込み出力

#4

投稿記事 by つるぴか » 14年前

返信ありがとうございます。

beatleさんの書き込みを参考に元のプログラム修正しました。

コード:

#include<iostream>
#include<fstream>
#include<string>
using namespace std;

class Student
{
	string name, studentId;
public:
	void setName(string n){ name = n; }
	void setID(string id){ studentId = id; }
	string getName() const{ return name; }
	string getID() const{ return studentId; }
};

int main()
{
	int num, n = 0, i = 0;
	string name, id;
	Student Tka;
	Student *pTka;

	cout << "学生の人数を入力してください" << endl;
	cin >> num;
	pTka = new Student[num];
	ofstream fTka("meibo.txt");

	while(n < num){
		cout << "学生番号を入力してください: ";
		cin >> id;
		pTka[i].setID(id);
		cout << "名前を入力してください: ";
		cin >> name;
		pTka[i].setName(name);

		fTka << pTka[i].getID() << endl;
		fTka << pTka[i].getName() << endl;

		i++;
		n++;
	}
	
	fTka << "xxx" << endl;

	return 0;
}
boxさん
(1)出力する内容は間違っていませんが上記のプログラムに書き換えました。
(2)beatleさんの書き込みそのままのミスでした。
(3)何とか自力でできました。

コード:

#include<iostream>
#include<fstream>
#include<string>
#include<vector>
using namespace std;

class Student
{
	string name, studentId;
public:
	void setName(string n){ name = n; }
	void setID(string id){ studentId = id; }
	string getName() const{ return name; }
	string getID() const{ return studentId; }
};

int main()
{
	vector<Student> data;

	int i,total=0;
	ifstream f("meibo.txt");
	string h;
	Student s;

	while( 1 ){
		f >> h;

		if(h == "xxx") break;
		s.setID(h);
		f >> h;
		s.setName(h);
		data.push_back(s);

		total += 1;
	}

	for(i = 0 ; i < total ; i++){
		if(i>4){
			cout << "6人目以降は表示されません" << endl;
			break;
		}
		cout << "No. " << i+1 << endl;
		cout << "学生番号: " << data[i].getID() << ", 氏名: " << data[i].getName() << endl;
	}

	return 0;
}

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: textデータ読み込み出力

#5

投稿記事 by beatle » 14年前

出力する方のプログラム(No: 4で示された前者のソースコードですよね?)に関してですが、実はStudentをnum個分確保する必要はないことにお気づきですか?
さらにいうと、Studentクラスを使う必要さえありません。
meibo.txtを作成するだけなら、string変数を1つだけ使って(それこそ、No: 4の後者のソースコードのように)id, nameを1つずつ読み取って、その都度fTkaに出力すればいいですね。

アドバイスをもう1つ。
Studentクラスのメソッド設計に関してです。文字列を引数にしたり戻り値にする場合、なるべく参照を使うほうが効率が上がります。C++11ではstringは中身を全部コピーする実装になっています(ならざるを得ない)ので、値渡しだと文字列がコピーされます。

コード:

class Student
{
    string name, studentId;
public:
    void setName(const string& n){ name = n; }
    void setID(const string& id){ studentId = id; }
    const string& getName() const{ return name; }
    const string& getID() const{ return studentId; }
};

閉鎖

“C言語何でも質問掲示板” へ戻る