C++ Primer Plus (第六版)编程练习记录(chapter17 输入、输出和文件)

1.编写一个程序计算输入流中第一个 之 前 的 字 符 数 目 , 并 将 之前的字符数目,并将 留在输入流中。

//main.cpp
/* *************************************************
* 文件名:
* 创建人:px
* 创建时间:2020/6/26
* 描述:
************************************************* */
#include<iostream>
#include<string>
using namespace std;
int main()
{
	cout << "Enter words please.\n";
	string str;
	getline(cin, str);
	int count;
	for (count = 0; count < str.length(); count++)
	{
		if (str[count] != '$')
			continue;
		else
			break;
	}
	cout << "There are " << count << " letters before '$'." << endl;
	return 0;
}

2.编写一个程序,将键盘输入(直到模拟的文件尾)复制到通过命令行指定的文件中。

//main.cpp
/* *************************************************
* 文件名:
* 创建人:px
* 创建时间:2020/6/26
* 描述:
************************************************* */
#include<cstdlib>
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main(int argc,char *argv[])//argc:argument count, argv:argument array
{
	ofstream fout(argv[1]);
	if (!fout.is_open())
	{
		cerr << "Can't open " << argv[1] << endl;
		exit(EXIT_FAILURE);
	}
	cout << "Enter words please.\n";
	string str;
	while (getline(cin, str) && str.length() > 0)
	{
		fout << str << endl;
	}
	fout.close();
	
	ifstream fin(argv[1]);
	if (!fin.is_open())
	{
		cerr << "Can't open " << argv[1] << endl;
		exit(EXIT_FAILURE);
	}
	char temp;
	while (fin.get(temp))
		cout << temp;
	cout << endl;
	
	cout << "Bye.\n";
	return 0;
}

3.编写一个程序,将一个文件复制到另一个文件中。让程序通过命令行获取文件名。
如果文件无法打开,程序将指出这一点。

//main.cpp
/* *************************************************
* 文件名:
* 创建人:px
* 创建时间:2020/6/26
* 描述:
************************************************* */
#include<cstdlib>
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main(int argc,char *argv[])//argc:argument count, argv:argument array
{
	//从文件1复制到文件2
	ifstream fin1(argv[1]);
	ofstream fout2(argv[2]);
	if (!fin1.is_open())
	{
		cerr << "Can't open " << argv[1] << endl;
		exit(EXIT_FAILURE);
	}
	if (!fout2.is_open())
	{
		cerr << "Can't open " << argv[2] << endl;
		exit(EXIT_FAILURE);
	}
	string temp;
	while (getline(fin1, temp) && temp.length() > 0)
		fout2 << temp << endl;
	cout << "Done.\n";
	return 0;
}

4.编写一个程序,它打开两个文本文件进行输入,打开一个文本文件进行输出。该程序将两个输入文件中对应的行并接起来,并用空格分隔,然后将结果写入到输出文件中。
如果一个文件比另一个短,则将较长文件中余下的几行直接复制到输出文件中。例如,假设第一个输入文件的内容如下:

eggs kites donuts
balloons hammers
stones

而第二个输入文件的内容如下:

zero lassitude
finnce drama

则得到的文件的内容将如下:

eggs kites donuts zero lassitude
balloons hammers finance drama
stones
//main.cpp
/* *************************************************
* 文件名:
* 创建人:px
* 创建时间:2020/6/26
* 描述:
************************************************* */
#include<cstdlib>
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main(int argc,char *argv[])//argc:argument count, argv:argument array
{
	//从文件1+文件2 复制到文件3
	ifstream fin1(argv[1]);
	ifstream fin2(argv[2]);
	ofstream fout3(argv[3]);
	if (!fin1.is_open())
	{
		cerr << "Can't open " << argv[1] << endl;
		exit(EXIT_FAILURE);
	}
	if (!fin2.is_open())
	{
		cerr << "Can't open " << argv[2] << endl;
		exit(EXIT_FAILURE);
	}
	if (!fout3.is_open())
	{
		cerr << "Can't open " << argv[3] << endl;
		exit(EXIT_FAILURE);
	}
	string temp1,temp2;
	while (!fin1.eof() && !fin2.eof())
	{
		getline(fin1, temp1);
		getline(fin2, temp2);
		fout3 << temp1 << " " << temp2 << endl;
	}
	while (!fin1.eof())
	{
		getline(fin1, temp1);
		fout3 << temp1 << endl;
	}
	while (!fin2.eof())
	{
		getline(fin2, temp2);
		fout3 << temp2 << endl;
	}
	fin1.close();
	fin2.close();
	fout3.close();
	cout << "Done.\n";
	return 0;
}

5.Mat和Pat想邀请他们的朋友来参加派对,就像第16章中的编程练习8那样,但现在他们希望程序使用文件。他们请您编写一个完成下述任务的程序。
● 从文本文件mat.dat中读取Mat朋友的姓名清单,其中每行为一个朋友。姓名将被存储在容器,然后按顺序显示出来。
● 从文本文件pat.dat中读取Pat朋友的姓名清单,其中每行为一个朋友。姓名将被存储在容器中,然后按顺序显示出来。
● 合并两个清单,删除重复的条目,并将结果保存在文件matnpat.dat中,其中每行为一个朋友。

//main.cpp
/* *************************************************
* 文件名:
* 创建人:px
* 创建时间:2020/6/26
* 描述:
************************************************* */
#include<cstdlib>
#include<fstream>
#include<iostream>
#include<string>
#include<list>
#include <algorithm>
using namespace std;
int main()
{
	//从文件1+文件2 复制到文件3
	ifstream fin1("mat.dat");
	ifstream fin2("pat.dat");
	if (!fin1.is_open())
	{
		cerr << "Can't open " << " mat.dat"<< endl;
		exit(EXIT_FAILURE);
	}
	if (!fin2.is_open())
	{
		cerr << "Can't open " << " pat.dat" << endl;
		exit(EXIT_FAILURE);
	}

	string temp;
	list<string> matnpat;
	while (!fin1.eof())
	{
		getline(fin1, temp);
		matnpat.push_back(temp);
	}
	while (!fin2.eof())
	{
		getline(fin2, temp);
		matnpat.push_back(temp);
	}
	fin1.close();
	fin2.close();

	matnpat.sort();
	matnpat.unique();

	ofstream fout3("matnpat.dat");
	for (string str : matnpat)
	{
		fout3 << str << endl;
	}
	cout << "Done.\n";
	return 0;
}

6.考虑14章的编程练习5中的类定义。如果还没有完成这个练习,请现在就做,然后完成下面的任务。
编写一个程序,它使用标准C++ I/O、文件I/O以及14章的编程练习5中定义的
employee、manager、fink和highfink类型的数据。该程序应包含程序清单17.17中的代码行,即允许用户将新数据添加到文件中。该程序首次被运行时,将要求用户输入数据,然后显示所有的数据,并将这些信息保存到一个文件中。当该程序再次被运行时,将首先读取并显示文件中的数据,然后让用户添加数据,并显示所有的数据。差别之一是,应通过一个指向employee类型的指针数组来处理数据。这样,指针可以指向employee对象,也可以指向从employee派生出来的其他三种对象中的任何一种。使数组较小有助于检查程序,例如,您可能将数组限定为最多包含10个元素:

const int MAX=10;
...
employee* pc[MAX];

为通过键盘输入,程序应使用一个菜单,让用户选择要创建的对象类型。菜单将使用一个switch,以便使用new来创建指定类型的对象,并将它的地址赋给pc数组中的一个指针。然后该对象可以使用虚函数setall( )来提示用户输入相应的数据:

pc[i]->setall();

为将数据保存到文件中,应设计一个虚函数writeall( ):

for(i = 0; i < index; i++)
	pc[i]->writeall(fout);

比较难处理的部分是使用文件恢复数据。问题在于:程序如何才能知道接下来要恢复的项目是employee对象、manager对象、fink对象还是highfink对象?一种方法是,在对象的数据写入文件时,在数据前面加上一个指示对象类型的整数。这样,在文件输入时,程序便可以读取该整数,并使用switch语句创建一个适当的对象来接收数据:

enum classkind{Employee, Manager, Fink, Highfink};
...
int classtype;
while((fin>>classtype).get(ch))
{
	switch(classtype)
	{
		case Employee : pc[i] = new employee;
					:break;
	}
}

然后便可以使用指针调用虚函数getall( )来读取信息:

pa[i++]->getall();
#pragma once
//class.h
#ifndef CLASS_H_
#define CLASS_H_
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
enum classkind { employee, manager, fink, highfink };

class AbstrEmp
{
private:
	string fname;
	string lname;
	string job;
public:
	AbstrEmp();
	AbstrEmp(const std::string& fn, const string& ln, const string& j) :fname(fn), lname(ln), job(j) {};
	virtual void showAll()const;
	virtual void setAll();
	virtual void writeAll(ofstream& fout);
	virtual void getAll(ifstream& fin);
	friend ostream& operator<<(ostream& os, const AbstrEmp& e);
	virtual ~AbstrEmp();
};
class Employee : public AbstrEmp
{
public:
	Employee() :AbstrEmp() {}
	Employee(const string& fn, const string& ln, const string& j) :AbstrEmp(fn, ln, j) {}
	virtual ~Employee() {}
	virtual void showAll()const { AbstrEmp::showAll(); }
	virtual void setAll() { AbstrEmp::setAll(); }
	virtual void writeAll(ofstream& fout);
	virtual void getAll(ifstream& fin);
}; 

class Manager : virtual public AbstrEmp
{
private:
	int inchargeof;
protected:
	int inChargeOf()const { return inchargeof; }
	int& inChargeOf() { return inchargeof; }
public:
	Manager() :AbstrEmp(), inchargeof(0) {}
	Manager(const string& fn, const string& ln, const string& j0, int ico = 0)
		:AbstrEmp(fn, ln, j0), inchargeof(ico) {}
	Manager(const AbstrEmp& e, int ico) :AbstrEmp(e), inchargeof(ico) {}
	Manager(const Manager& m) :AbstrEmp(m) { inchargeof = m.inchargeof; }
	virtual ~Manager(){	}

	virtual void showAll()const;
	virtual void setAll();
	virtual void writeAll(ofstream& fout);
	virtual void getAll(ifstream& fin);
};

class Fink : virtual public AbstrEmp
{
private:
	string reportsto;
protected:
	const string reportsTo() const { return reportsto; }
	string& reportsTo() { return reportsto; }
public:
	Fink() :AbstrEmp() {}
	Fink(const string& fn, const string& ln, const string& j, const string& rpo) :AbstrEmp(fn, ln, j), reportsto(rpo) {}
	Fink(const AbstrEmp& e, const string& rpo) :AbstrEmp(e), reportsto(rpo) {}
	Fink(const Fink& e) :AbstrEmp(e) {}
	virtual ~Fink(){}

	virtual void showAll()const;
	virtual void setAll();
	virtual void writeAll(ofstream& fout);
	virtual void getAll(ifstream& fin);
};

class HighFink : public Manager, public Fink
{
public:
	HighFink() :AbstrEmp(), Manager(), Fink() {}
	HighFink(const string& fn, const string& ln, const string& j, const string& rpo, int ico)
		:AbstrEmp(fn, ln, j), Manager(fn, ln, j, ico), Fink(fn, ln, j, rpo) {}
	HighFink(const AbstrEmp& e, const string& rpo, int ico)
		:AbstrEmp(e), Manager(e, ico), Fink(e, rpo) {}
	HighFink(const Fink& f, int ico) :AbstrEmp(f), Fink(f), Manager(f, ico) {}
	//Manager(f,ico)将f回传给AbstrEmp(),但会被虚继承的机制阻断,这样写只是利用Manager(f,ico)重设了ico
	HighFink(const Manager& m, const string& rpo) :AbstrEmp(m), Manager(m), Fink(m, rpo) {}
	HighFink(const HighFink& h) :AbstrEmp(h), Manager(h), Fink(h) {}
	virtual ~HighFink(){}
	virtual void showAll()const;
	virtual void setAll();
	virtual void writeAll(ofstream& fout);
	virtual void getAll(ifstream& fin);
};
#endif // !CLASS_H_
//class.cpp
#include"class.h"

AbstrEmp::AbstrEmp()
{
	fname = "None";
	lname = '\0';
	job = "None";
}

void AbstrEmp::showAll() const
{
	cout << endl;
	cout << "Name: " << fname << " " << lname << endl;
	cout << "Job:" << job << endl;
}

void AbstrEmp::setAll()
{
	cout << "Enter first name: ";
	getline(cin, fname);
	cout << "Enter last name: ";
	getline(cin, lname);
	cout << "Enter job: ";
	getline(cin, job);
}

void AbstrEmp::writeAll(ofstream& fout)
{
	fout << fname << " " << lname << " " << job;
}

void AbstrEmp::getAll(ifstream& fin)
{
	fin >> fname;
	fin >> lname;
	fin >> job;
}

ostream& operator<<(ostream& os, const AbstrEmp& e)
{
	os << std::endl;
	os << e.fname << " " << e.lname;
	return os;
}
AbstrEmp:: ~AbstrEmp()
{
}


void Manager::showAll() const
{
	AbstrEmp::showAll();
	cout << "Inchargeof: " << inchargeof << endl;
}

void Manager::setAll()
{
	AbstrEmp::setAll();
	cout << "Enter inchargeof: ";
	cin >> inChargeOf();
}

void Manager::writeAll(ofstream& fout)
{
	fout << classkind::manager << " ";
	AbstrEmp::writeAll(fout);
	fout <<" "<< inchargeof << endl;
}

void Manager::getAll(ifstream& fin)
{
	AbstrEmp::getAll(fin);
	fin >> inchargeof;
}

void Fink::showAll() const
{
	AbstrEmp::showAll();
	cout << "Reperts to: " << reportsto << endl;
}

void Fink::setAll()
{
	AbstrEmp::setAll();
	cout << "Enter reportsto: ";
	getline(cin, reportsTo());
}

void Fink::writeAll(ofstream& fout)
{
	fout << classkind::fink << " ";
	AbstrEmp::writeAll(fout);
	fout << " " << reportsto << endl;
}

void Fink::getAll(ifstream& fin)
{
	AbstrEmp::getAll(fin);
	fin >> reportsto;
}

void HighFink::showAll() const
{
	AbstrEmp::showAll();
	cout << "Inchargeof: " << Manager::inChargeOf() << endl;
	cout << "Reportsto: " << Fink::reportsTo() << endl;
}

void HighFink::setAll()
{
	AbstrEmp::setAll();
	cout << "Enter number of in-charge-of: ";
	cin >> Manager::inChargeOf();
	cout << "Enter name reports to: ";
	cin.get();
	getline(cin, Fink::reportsTo());
}

void HighFink::writeAll(ofstream& fout)
{
	fout << classkind::highfink << " ";
	AbstrEmp::writeAll(fout);
	fout << " " << inChargeOf() <<" "<< reportsTo() << endl;
}

void HighFink::getAll(ifstream& fin)
{
	AbstrEmp temp;
	temp.getAll(fin);
	int in;
	string re;
	fin >> in;
	fin >> re;
	*this = HighFink(temp, re, in);
}

void Employee::writeAll(ofstream& fout)
{
	fout << classkind::employee << " ";
	AbstrEmp::writeAll(fout);
	fout << endl;
}

void Employee::getAll(ifstream& fin)
{
	AbstrEmp::getAll(fin);
}
//main.cpp
/* *************************************************
* 文件名:
* 创建人:px
* 创建时间:2020/6/28
* 描述:
************************************************* */
#include<iostream>
#include<fstream>
#include<string>
#include"class.h"

const int MAX = 4;
int main(void)
{
	using namespace std;
	int count = 0;
	AbstrEmp* pc[MAX];
	cout << "Enter number to create object(q to quit).\n"
		<< "0: employee\t" << "1: manager\n"
		<< "2: fink\t" << "3: highfink\n";
	int classtype;
	char ch;
	while ((cin >> classtype).get() && count < MAX )
	{
		switch (classtype)
		{
		case employee:
			pc[count] = new Employee;
			pc[count]->setAll();
			pc[count]->showAll();
			break;
		case manager:
			pc[count] = new Manager;
			pc[count]->setAll();
			pc[count]->showAll();
			break;
		case fink:
			pc[count] = new Fink;
			pc[count]->setAll();
			pc[count]->showAll();
			break;
		case highfink:
			pc[count] = new HighFink;
			pc[count]->setAll();
			pc[count]->showAll();
			break;
		default:
			cout << "Wrong enter.\n";
			break;
		}
		count++;
	}
	cout << "while loop end.\n";
	//将输入信息存储到文件中
	ofstream fout("test6.txt");
	if (!fout.is_open())
	{
		cerr << "Can't open " << " test6.txt" << endl;
		exit(EXIT_FAILURE);
	}
	else
	{
		cout << "test6.txt is opened.\n";
	}

	for (int i = 0; i < count; i++)
		pc[i]->writeAll(fout);
	fout.close();
	cout << "Written.\n";
	//delete[] pc;//释放内存
	//读取该文件并增加对应条例

	ifstream fin("test6.txt");
	if (!fin.is_open())
	{
		cerr << "Can't open " << " test6.txt" << endl;
		exit(EXIT_FAILURE);
	}
	fin.clear();
	//应该下面是出错了
	AbstrEmp* pt[MAX];
	int count2 = 0;
	while ((fin >> classtype).get() && count2 < count)
	{
		switch (classtype)
		{
		case employee:
			pt[count2] = new Employee;
			pt[count2]->getAll(fin);
			pt[count2]->showAll();
			break;
		case manager:
			pt[count2] = new Manager;
			pt[count2]->getAll(fin);
			pt[count2]->showAll();
			break;
		case fink:
			pt[count2] = new Fink;
			pt[count2]->getAll(fin);
			pt[count2]->showAll();
			break;
		case highfink:
			pt[count2] = new HighFink;
			pt[count2]->getAll(fin);
			pt[count2]->showAll();
			break;
		default:
			cout << "Wrong.\n";
			break;
		}
		count2++;
	}
	fin.close();
	//delete[] pt;
	return 0;
}

7.下面是某个程序的部分代码。该程序将键盘输入读取到一个由string对象组成的vector中,将字符串内容(而不是string对象)存储到一个文件中,然后该文件的内容复制到另一个由string对象组成的vector中。

int main()
{
	using namespace std;
	vector<string> vostr;
	string temp;
	//acquire strings
	cout<<"Enter strings(empty line to quit):\n";
	while(getline(cin,temp)&&temp[0]!='\0')
		vostr.push_back(temp);
	cout<<"Here is your input.\n";
	for_each(vostr.begin(),vostr.end(),ShowStr());

	//store in a file
	ofstream fout("strings.dat",ios_base::out|ios_base::binary);
	for_each(vostr.begin(),vostr.end(),Store(fout));
	fout.close();

	//recover file contents
	vector<string> vistr;
	ifstream fin("strings.dat",ios_base::in|ios_base::binary);
	if(!fin.is_open())
	{
		cerr<<"Could not open file for input.\n";
		exit(EXIT_FAILURE);
	}
	GetStrs(fin,vistr);
	cout<<"\nHere are the strings read from the file:\n";
	for_each(vistr.begin(),vistr.end(),ShowStr);
	return 0;
}

该程序以二进制格式打开文件,并想使用read( )和write( )来完成I/O。余下的工作如下所述。
● 编写函数void ShowStr(const string &),它显示一个string对象,并在显示完后换行。
● 编写函数符Store,它将字符串信息写入到文件中。Store的构造函数应接受一个指定ifstream对象的参数,而重载的operator( )(const string &)应指出要写入到文件中的字符串。一种可行的计划是,首先将字符串的长度写入到文件中,然后将字符串的内容写入到文件中。例如,如果len存储了字符串的长度,可以这样做:

os.write((char *)&len,sizeof(std::size_t));
os.write(s.data,len);

成员函数data( )返回一个指针,该指针指向一个其中存储了字符串中字符的数组。它类似于成员函数c_str( ),只是后者在数组末尾加上了一个空字符。
● 编写函数GetStrs( ),它根据文件恢复信息。该函数可以使用read( )来获得字符串的长度,然后使用一个循环从文件中读取相应数量的字符,并将它们附加到一个原来为空的临时string末尾。由于string的数据是私有的,因此必须使用string类的方法来将数据存储到string对象中,而不能直接存储。

//main.cpp
/* *************************************************
* 文件名:
* 创建人:px
* 创建时间:2020/6/28
* 描述:
************************************************* */
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
void ShowStr(const string& str);
void GetStrs(ifstream& f, vector<string>& vi);
class Store
{
public:
	Store(ofstream& f) :fstr(f) {}
	~Store() {};
	void operator()(const string& str);
private:
	ofstream& fstr;
};


int main()
{
	using namespace std;
	vector<string> vostr;
	string temp;
	//acquire strings
	cout << "Enter strings(empty line to quit):\n";
	while (getline(cin, temp) && temp[0] != '\0')
		vostr.push_back(temp);
	cout << "Here is your input.\n";
	for_each(vostr.begin(), vostr.end(), ShowStr);

	//store in a file
	ofstream fout("strings.dat", ios_base::out | ios_base::binary);
	for_each(vostr.begin(), vostr.end(), Store(fout));
	//这里的Store(fout)是创建一个Store对象,成员为fout,for_each会将vostr的各个内容逐一代入到Store的operator()中去
	fout.close();

	//recover file contents
	vector<string> vistr;
	ifstream fin("strings.dat", ios_base::in | ios_base::binary);
	if (!fin.is_open())
	{
		cerr << "Could not open file for input.\n";
		exit(EXIT_FAILURE);
	}
	GetStrs(fin, vistr);
	cout << "\nHere are the strings read from the file:\n";
	for_each(vistr.begin(), vistr.end(), ShowStr);
	return 0;
}
void ShowStr(const std::string& str)
{
	std::cout << str << std::endl;
}

void GetStrs(ifstream& f, vector<string>& vi)
{
	size_t len;
	while (f.read((char*)&len, sizeof(size_t)))
	{
		char* temp = new char[len];
		f.read(temp, len);
		temp[len + 1] = '\0';
		vi.push_back(temp);
	}
}

void Store::operator()(const string& str)
{
	size_t len = str.size();
	fstr.write((char*)&len, sizeof(size_t));
	fstr.write(str.data(), len);
	//data()方法与c_str()类似,生成一个const char*指针,但是返回的数组不以空字符终止。
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值