第08章 IO类

C++ primer 5th 第8章 IO类

=====================================================================

第8章 IO类 278页

#ifdef DECLARATION

istream(输入流)类型,提供输入操作
ostream(输出流)类型,提供输出操作
cin,一个istream对象,从标准输入读取数据
cout,一个ostream对象,向标准输出写入数据
cerr,一个ostream对象,通常用于输出程序错误消息,写入到标准错误
>>运算符,用来从一个istream对象读取输入数据
<<运算符,用来向一个ostream对象写入输出数据
getline函数(参见3.3.2节,第78页)从一个给定的istream读取一行数据,
存入一个给定的string对象中

#endif

表8.1: IO库类型和头文件

头文件

类型

iostream

istream, wistream从流读取数据

ostream, wostream向流写入数据

iostream, wiostream读写流

fstream

ifstream, wifstream从文件读取数据

ofstream, wofstream向文件写入数据

fstream, wfstream读写文件

sstream

istringstream, wistringstream从string读取数据

ostringstream, wostringstream向string写入数据

stringstream, wstringstream读写string

 

=====================================================================

//QQ108201645编写
//读取第二行开始的数并相加
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
ifstream &inputTest(ifstream& in)
{
	char c=NULL;
	while (c != '\n')
		in.get(c);
	return in;
}
double ToNum(ifstream& in, string& s)
{
	double num;
	while (in >> s)//循环给值
	{
		if (num = strtod(s.c_str(), NULL))//当是数字时自动返回1,把s里的数字字符串转换成double类型并传给num
			break;
	}
	return num;//返回双精度浮点数
}
int main()
{
	ofstream out("1.txt");
	out << " abc 123 456" << endl;
	out << " 张三 积分 54.7859 45.2141" << endl;
	out.close();
	ifstream in("1.txt");
	if (!in)
		cerr << "未发现文件" << endl;
	inputTest(in);//略过一行
	string s;
	cout << ToNum(in, s) + ToNum(in, s) << endl;

	in.close();
	system("pause");
	return 0;
}

=====================================================================

第8章 IO类 279页    IO流无拷贝或赋值

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
using namespace std;


int main()
{
	ofstream out1, out2;
#ifdef DECLARATION
	out1 = out2;//错误,不能对流赋值
	ofstream print(ofstream);//错误,不能初始化ofstream参数
	out2 = print(out2);//错误,不能拷贝流对象
#endif
}

=====================================================================

第8章 IO类 122页   

=====================================================================

//QQ108201645编写

表8.2: IO库条件状态

strm::iostate

strm是一种IO类型, 在表8.1(第278页)中已列出.iostate是一种机器相关的类型,提供了表达状态的完整功能

strm::badbit

strm::badbit用来指出流已崩溃

strm::failbit

strm::failbit用来指出一个IO操作失败了

strm::eofbit

strm::eofbit用来指出流已到达文件结束

strm::goodbit

strm::goodbit用来指出流未处于错误状态。此值保证为零

s.eof

若流s的eofbit置位,则返回true

s.fail

若流s的failbit或badbit置位, 则返回true

s.bad

若流s的badbit置位,返回true

s.good

若流s处于有效状态, 则返回true

s.clear()

若流s中所有条件状态位复位,将流的状态设置为有效,返回void

s.clear(flags)

根据给定的flags标志位,将流s中对应条件状态位复位.flags的类型为strm::iostate. 返回void

s.setstate(flags)

根据给定的flags标志位,将流s中对应条件状态位复位.flags的类型为strm::iostate. 返回void

s.rdstate

返回流s的当前状态, 返回值类型为strm::iostate

 

=====================================================================

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

istream& process_input(istream& is)
{
	int num;
	return is >> num;
}

int main()
{
	int ival;
	cin >> ival;
	//如果输入Boo就会出错,ival对应int,但却得到B,这样就进入错误状态,如果输入一个文件结束标识符,也是错误的

	auto old_state = cin.rdstate();//记住cin当前状态;
	//rdstate成员返回一个iostate值,对应流的当前状态
	cin.clear();//使cin有效
	process_input(cin);//使用cin
	cin.setstate(old_state);//将cin置为原有状态
	//复位failbit和badbit,保持其他标志位不变
	cin.clear(cin.rdstate()&~cin.failbit&~cin.badbit);

}

=====================================================================

#include <iostream>
using std::cin; using std::cout; using std::endl;

#include <sstream>
using std::istringstream;

#include <string>
using std::string;

void read()
{
	// 设置badbit和eofbit,failbit
	cin.setstate(cin.badbit | cin.eofbit | cin.failbit);
}

void off()
{
	// 复位failbit和badbit,保持其它(eofbit)不变
	cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);
}


int main()
{
	cout << "before read" << endl;
	if (cin.good()) 
		cout << "cin's good" << endl;
	if (cin.bad())
		cout << "cin's bad" << endl;
	if (cin.fail())
		cout << "cin's fail" << endl;
	if (cin.eof())
		cout << "cin's eof" << endl;
	cout << "-----read------" << endl;
	read();
	cout << "after read" << endl;
	if (cin.good())
		cout << "cin's good" << endl;
	if (cin.bad())
		cout << "cin's bad" << endl;
	if (cin.fail()) 
		cout << "cin's fail" << endl;
	if (cin.eof())
		cout << "cin's eof" << endl;
	cout<<"-----off------"<<endl;
	off();
	cout << "after off" << endl;
	if (cin.good()) 
		cout << "cin's good" << endl;
	if (cin.bad())
		cout << "cin's bad" << endl;
	if (cin.fail())
		cout << "cin's fail" << endl;
	if (cin.eof())
		cout << "cin's eof" << endl;
	system("pause");
	return 0;
}

=====================================================================

第8章 IO类 281页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std;
/*
练习8.1:编写函数,接受一个istream&参数,返回值类型也是istream&。此函数
须从给定流中读取数据,直至遇到文件结束标识时停止。它将读取的数据打印在标准输
出上。完成这些操作后,在返回流之前,对流进行复位,使其处于有效状态。*/
istream& f(istream& in)
{
	int v;
	while (in>>v,!in.eof())//直到遇到文件结束符才停止读取
	{
		if (in.bad())
			throw runtime_error("IO流错误");
		if (in.fail())
		{
			cerr<<"数据错误,请重试"<<endl;
			in.clear();
			in.ignore(100, '\n');//清除以回车结束的输入缓冲区的内容
			continue;
		}
		cout<<v<<endl;
	}
	in.clear();
	return in;
}
//练习8.2:测试函数,调用参数为cin。
istream& fun(istream& input)
{
	string s;
	while (true)
	{
		input >> s;
		if (input.eof())
			break;
		else
			input.clear();
		cout << s << '\n';
	}
	input.clear();
	return input;
}
#ifdef DECLARATION
练习8.3:什么情况下,下面的while循环会终止?
while (cin >> i)    /* ... */
当cin流bad、fail、eof时循环终止
#endif
int main()
{
	cout<<"请输入整数,按Ctrl+z结束"<<endl;
	f(cin);
	cout<<"fun(cin):"<<endl;
	fun(cin);
	return 0;
}

=====================================================================

第8章 IO类 282页    管理输出缓冲

=====================================================================

//QQ108201645编写
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std;

void print(ostream& os)
{
	os << "please enter a value: ";
}
int main()
{
	print(cout);
	cout << "hi!" << endl;//输出hi和一个换行,然后刷新缓冲区
	cout << "hi!" << flush;//输出hi,然后刷新缓冲区,不附加任何额外字符
	cout << "hi!" << ends;//输出hi和一个空字符,然后刷新缓冲区
	int ival;
	cin >> ival;
	cin.tie(&cout);//仅仅是展示,标准库将cin和cout关联在一起
	//old_tie指向当前关联到cin的流(如果有的话)
	ostream *old_tie = cin.tie(nullptr);//cin不再与其他流关联
	//将cin与cerr关联;这不是一个好主意,因为cin应该关联到cout
	cin.tie(&cerr);//读取cin会刷新cerr而不是cout
	cin.tie(old_tie);//重建cin和cout间的正常关联
	return 0;
}

=====================================================================

第8章 IO类 283页    文件输入输出

=====================================================================

//QQ108201645编写

表8.3: fstream特有的操作

fstream fstrm

创建一个未绑定的文件流.fstream是头文件fstream中定义的类型

fstream fstrm(s)

创建fstream,并打开名为s的文件.s可以是string的类型,或者是一个指向C风格字符串的指针(参见3.5.4节,第109页).这些构造函数都是explicit的(参见7.5.4节,第265页).默认的文件模式mode依赖于fstream的类型

fstream fstrm(s, mode)

与前一个构造函数类似,但按指定mode打开文件

fstrm.open(s)

打开名为s的文件,并将文件与fstrm绑定. s可以是string的类型,或者是一个指向C风格字符串的指针.默认的文件mode依赖fstream的类型.返回void

fstrm.close()

关闭与fstrm绑定的文件.返回void

fstrm.is_open()

返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭

 

=====================================================================

第8章 IO类 284页    使用文件流对象

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <string>
using namespace std;


int main()
{
	string ifile = "1.txt";//指定文件名与后缀。
	ifstream in(ifile);//构造一个ifstream并打开文件
	ofstream out;//输出文件流未关联到任何文件
	in.close();//关闭文件
	return 0;
}

=====================================================================

第8章 IO类 284页    用fstream代替iostream&读写文件

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Sales_data
{
public://公有成员
	//新增构造函数(不同的类内初始化方式)
//	Sales_data() = default;//默认构造函数可以声明在类类部,也可以作为定义出现在类的外部

	explicit Sales_data(const std::string &s, unsigned n, double p) :
		bookNo(s), units_sold(n), revenue(p*n) {}
	/*Sales_data(std::istream& is)
	{
		read(is, *this);
	}*/
	//保留默认构造函数
	explicit Sales_data(std::string s = "")
		:bookNo(s) {}//bookNo(s)表示构造函数列表初始化(构造函数初始值列表)
	//只允许出现在类内声明构造函数时使用explicit
	explicit Sales_data(std::istream& is)
	{
		read(is, *this);
	}

	friend Sales_data add(const Sales_data&, const Sales_data&);
	friend std::istream& read(std::istream&, Sales_data&);
	friend std::ostream& print(std::ostream&, const Sales_data&);
	//添加一个文件流操作的友元
	friend ifstream& read(ifstream& in, Sales_data& item)
	{
		double price = 0;
		in >> item.bookNo >> item.units_sold >> price;
		item.revenue = price * item.units_sold;
		return in;
	}
	friend ofstream& print(ofstream& out, const Sales_data& item)
	{
		out << item.isbn() << " " << item.units_sold << " "
			<< item.revenue << " " << item.ave_price();
		return out;
	}

	friend std::istream& operator>>(std::istream& is, Sales_data&);//operator>>重载,支持cin>>对象名接收
	friend std::ostream& operator<<(std::ostream& os, const Sales_data&);//operator<<重载,支持cin>>对象名直接输出内容
	//之前已有的其它成员
	std::string isbn() const;
	Sales_data& combine(const Sales_data&);


private://私有成员
	double ave_price()const;
	std::string bookNo;
	unsigned units_sold = 0;//c++11开始支持类体内初始化(变量名译:单独售出)
	double revenue = 0.0;//初始化revenue(译:财政收入)
};//这里要加分号

Sales_data add(const Sales_data &lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;//把lhs的数据拷贝给sum
	sum.combine(rhs);//把rhs的数据成员加到sum当中
	return sum;
}

//定义read和print函数
std::istream& read(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}
//上面两个等同于operator>>与operator<<重载
std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}


std::string Sales_data::isbn() const
{
	//return bookNo;//用于返回Sales_data的数据成员
	return this->bookNo;//同上
	//默认情况this指针指向非常量的常量指针
}
//函数combine设计初衷类型复合赋值运算符+=
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;//把rhs的成员加到this对象的成员上
	revenue += rhs.revenue;
	return *this;//返回调用该函数的对象
}
double Sales_data::ave_price()const
{
	return units_sold ? revenue / units_sold : 0;
}

int main(int argc,char* argv[])
{
	ifstream input(argv[1]);
	ofstream output(argv[2]);
/*操作方法:首先在cpp编译exe所在目录(我的是vs2017路径C:\Users\Administrator\source\repos\01cpp\Debug)
新建一个1.txt
写入如下内容
09-99-999 5 6
09-99-999 9 12
写好并保存
然后再对这个文件夹shift+鼠标右键,调出此处dos命令窗口,我的文件是01cpp.exe
那就输入01cpp.exe 1.txt 2.txt,然后输出一个2.txt的结果
	*/
	Sales_data total;
	if (read(input, total))
	{
		Sales_data trans;
		while (read(input,total))
		{
			if (total.isbn() == trans.isbn())
				total.combine(trans);
			else
			{
				print(output, total);
				total = trans;
			}
		}
		print(output, total);
	}
	else
	{
		cerr<<"No data?!"<<endl;
	}
	return 0;
}

=====================================================================

第8章 IO类 285页    成员函数open与close

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(int argc,char* argv[])
{
	string ifile = "1.txt";
	ifstream in(ifile);//创建一个ifstream(读取文件对象in)
	ofstream out;//输出文件流未与任何文件关联
	out.open(ifile + ".copy");//打开指定文件
//如果调用open失败,failbit会被置位,因为open可能失败,进行open检测
	if (out)//检查是否成功
		cout << "打开成功" << endl;
	else
		exit(1);//退出
	in.close();//关闭文件
	in.open(ifile + "2");//打开另一个文件

	return 0;
}

=====================================================================

第8章 IO类 285页    自动构造与析构

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
using namespace std;

void process(ifstream &is)
{
	string s;
	while (is >> s)
		cout << s << endl;
}

int main(int argc, char* argv[])
{
	// 对每个传递给程序的文件执行循环操作
	for (auto p = argv + 1; p != argv + argc; ++p)
	{
		ifstream input(*p);   // 创建输出流并打开文件
		if (input) 
		{          // 如果文件打开成功,"处理"此文件
			process(input);
		}
		else
			cerr << "couldn't open: " + string(*p);
	} // 每个循环步input都会离开作用域,因此会被销毁

	auto p = argv + 1, end = argv + argc;

	ifstream input;
	while (p != end) 
	{        // 为每个文件传递给程序

		input.open(*p);       // 打开文件,自动清除流

		if (input) 
		{          // 如果文件打开成功,"处理"此文件
			process(input);
		}
		else
			cerr << "couldn't open: " + string(*p);
		input.close();        // 当我们完成它,关闭文件

		++p;                  // 增加下一个文件指针

	}
}

 

=====================================================================

第8章 IO类 285页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
/*
练习8.4:编写函数,以读模式打开一个文件,将其内容读入到一个string的vector
中,将每一行作为一个独立的元素存于vector中。*/
int main()
{
	ifstream in("1.txt");//打开文件
	if (!in)
	{
		cerr << "无法打开文件" << endl;
		return -1;
	}
	string line;
	vector<string> words;
	while (getline(in, line))//从文件读取一行
	{
		words.push_back(line);//添加到vector中

	}
	in.close();//输入完毕,关闭文件
	vector<string>::const_iterator it = words.begin();
	while (it != words.end())//遍历vector
	{
		cout << *it << endl;//输出vector中的元素
		++it;
	}
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
/*练习8.5:重写上面的程序,将每个单词作为一个独立的元素进行存储。*/
int main(int argc,char* argv[])
{
	vector<string> svec;
	ifstream in_file(argv[1]);
	if (in_file)
	{
		string s;
		while (in_file>>s)
		{
			svec.push_back(s);
		}

	}
	else
	{
		cerr<<"No file"<<endl;
		return -1;
	}
	system("pause");
	return 0;
}

 

=====================================================================

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
/*练习8.6:重写7.1.1节的书店程序(第229页),从一个文件中读取交易记录。将文件
名作为一个参数传递给main(参见6.2.5节,第196页)*/
class Sales_data
{
public://公有成员
	//新增构造函数(不同的类内初始化方式)
//	Sales_data() = default;//默认构造函数可以声明在类类部,也可以作为定义出现在类的外部

	explicit Sales_data(const std::string &s, unsigned n, double p) :
		bookNo(s), units_sold(n), revenue(p*n) {}
	/*Sales_data(std::istream& is)
	{
		read(is, *this);
	}*/
	//保留默认构造函数
	explicit Sales_data(std::string s = "")
		:bookNo(s) {}//bookNo(s)表示构造函数列表初始化(构造函数初始值列表)
	//只允许出现在类内声明构造函数时使用explicit
	explicit Sales_data(std::istream& is)
	{
		read(is, *this);
	}

	friend Sales_data add(const Sales_data&, const Sales_data&);
	friend std::istream& read(std::istream&, Sales_data&);
	friend std::ostream& print(std::ostream&, const Sales_data&);
	//添加一个文件流操作的友元
	friend ifstream& read(ifstream& in, Sales_data& item)
	{
		double price = 0;
		in >> item.bookNo >> item.units_sold >> price;
		item.revenue = price * item.units_sold;
		return in;
	}
	friend ofstream& print(ofstream& out, const Sales_data& item)
	{
		out << item.isbn() << " " << item.units_sold << " "
			<< item.revenue << " " << item.ave_price();
		return out;
	}

	friend std::istream& operator>>(std::istream& is, Sales_data&);//operator>>重载,支持cin>>对象名接收
	friend std::ostream& operator<<(std::ostream& os, const Sales_data&);//operator<<重载,支持cin>>对象名直接输出内容
	//之前已有的其它成员
	std::string isbn() const;
	Sales_data& combine(const Sales_data&);


private://私有成员
	double ave_price()const;
	std::string bookNo;
	unsigned units_sold = 0;//c++11开始支持类体内初始化(变量名译:单独售出)
	double revenue = 0.0;//初始化revenue(译:财政收入)
};//这里要加分号

Sales_data add(const Sales_data &lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;//把lhs的数据拷贝给sum
	sum.combine(rhs);//把rhs的数据成员加到sum当中
	return sum;
}

//定义read和print函数
std::istream& read(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}
//上面两个等同于operator>>与operator<<重载
std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}


std::string Sales_data::isbn() const
{
	//return bookNo;//用于返回Sales_data的数据成员
	return this->bookNo;//同上
	//默认情况this指针指向非常量的常量指针
}
//函数combine设计初衷类型复合赋值运算符+=
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;//把rhs的成员加到this对象的成员上
	revenue += rhs.revenue;
	return *this;//返回调用该函数的对象
}
double Sales_data::ave_price()const
{
	return units_sold ? revenue / units_sold : 0;
}

int main(int argc, char const *argv[])
{
	ifstream input(argv[1]);
	Sales_data total;
	if (input >> total)
	{
		Sales_data trans;
		while (input >> total)
		{
			if (total.isbn() == trans.isbn())
				total.combine(trans);
			else
			{
				print(cout, total) << endl;
				total = trans;
			}
		}
		print(cout, total) << endl;
	}
	else
	{
		cerr << "No data?!" << endl;
		return -1;
	}
	system("pause");
	return 0;
}

=====================================================================

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
/*练习8.6:重写7.1.1节的书店程序(第229页),从一个文件中读取交易记录。将文件
名作为一个参数传递给main(参见6.2.5节,第196页)*/
class Sales_data
{
public://公有成员
	//新增构造函数(不同的类内初始化方式)
//	Sales_data() = default;//默认构造函数可以声明在类类部,也可以作为定义出现在类的外部

	explicit Sales_data(const std::string &s, unsigned n, double p) :
		bookNo(s), units_sold(n), revenue(p*n) {}
	/*Sales_data(std::istream& is)
	{
		read(is, *this);
	}*/
	//保留默认构造函数
	explicit Sales_data(std::string s = "")
		:bookNo(s) {}//bookNo(s)表示构造函数列表初始化(构造函数初始值列表)
	//只允许出现在类内声明构造函数时使用explicit
	explicit Sales_data(std::istream& is)
	{
		read(is, *this);
	}

	friend Sales_data add(const Sales_data&, const Sales_data&);
	friend std::istream& read(std::istream&, Sales_data&);
	friend std::ostream& print(std::ostream&, const Sales_data&);
	//添加一个文件流操作的友元
	friend ifstream& read(ifstream& in, Sales_data& item)
	{
		double price = 0;
		in >> item.bookNo >> item.units_sold >> price;
		item.revenue = price * item.units_sold;
		return in;
	}
	friend ofstream& print(ofstream& out, const Sales_data& item)
	{
		out << item.isbn() << " " << item.units_sold << " "
			<< item.revenue << " " << item.ave_price();
		return out;
	}

	friend std::istream& operator>>(std::istream& is, Sales_data&);//operator>>重载,支持cin>>对象名接收
	friend std::ostream& operator<<(std::ostream& os, const Sales_data&);//operator<<重载,支持cin>>对象名直接输出内容
	//之前已有的其它成员
	std::string isbn() const;
	Sales_data& combine(const Sales_data&);


private://私有成员
	double ave_price()const;
	std::string bookNo;
	unsigned units_sold = 0;//c++11开始支持类体内初始化(变量名译:单独售出)
	double revenue = 0.0;//初始化revenue(译:财政收入)
};//这里要加分号

Sales_data add(const Sales_data &lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;//把lhs的数据拷贝给sum
	sum.combine(rhs);//把rhs的数据成员加到sum当中
	return sum;
}

//定义read和print函数
std::istream& read(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}
//上面两个等同于operator>>与operator<<重载
std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}


std::string Sales_data::isbn() const
{
	//return bookNo;//用于返回Sales_data的数据成员
	return this->bookNo;//同上
	//默认情况this指针指向非常量的常量指针
}
//函数combine设计初衷类型复合赋值运算符+=
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;//把rhs的成员加到this对象的成员上
	revenue += rhs.revenue;
	return *this;//返回调用该函数的对象
}
double Sales_data::ave_price()const
{
	return units_sold ? revenue / units_sold : 0;
}

int main(int argc, char const *argv[])
{
	argv[1] = "1.txt";
	ifstream input(argv[1]);
	Sales_data total;
	if (input >> total)
	{
		Sales_data trans;
		while (input>> trans)
		{
			if (total.isbn() == trans.isbn())
				total.combine(trans);
			else
			{
				print(cout, total) << endl;
				total = trans;
			}
		}
		print(cout, total) << endl;
	}
	else
	{
		cerr << "No data?!" << endl;
		return -1;
	}
	system("pause");
	return 0;
}

=====================================================================

第8章 IO类 286页    文件模式

=====================================================================

//QQ108201645编写

表8.4: 文件模式

in

以读方式打开

out

以写方式打开

app

每次写操作前均定位到文件末尾

ate

打开文件后立即定位到文件末尾

trunc

截断文件

binary

二进制方式进行IO

#ifdef DECLARATION
只可以对ofstream或fstream对象设定out模式
只可以对ifstream或fstream对象设定in模式
只有当out也被设定时才可设定trunc模式
只要trunc没被设定,就可以设定app模式。在app模式下,即使没有显式指定
out模式,文件也总是以输出方式打开
默认情况下,即使我们没有指定trunc,以out模式打开的文件也会被截断.为了保留
以out模式打开文件的内容,我们必须同时指定app模式,这样只会将数据追加写到
文件末尾;或者同时指定in模式,即打开文件同时进行读写操作(参见17.5.3节,第676页)
将介绍对同一个文件既进行输入又进行输出的的方法
ate和binary模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用
#endif

=====================================================================

第8章 IO类 286页    文件模式

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

int main(int argc, char const *argv[])
{
	ofstream out1("file1");//隐含输出模式打开文件并截断文件
	ofstream out2("file1", ofstream::out);//隐含的截断文件
	ofstream out3("file1", ofstream::out | ofstream::trunc);
	//为了保留文件内容,我们必须显式指定app模式
	ofstream app("file1", ofstream::app);//隐含为输出模式
	ofstream app2("file1", ofstream::out | ofstream::app);
	out1.close();
	out2.close();
	out3.close();
	app.close();
	app2.close();
	system("pause");
	ofstream out;//未指定文件打开模式
	out.open("scratchpad");//模式隐含设置为输出和截断
	out.close();//关闭out以便我们将其用于其他文件
	out.open("precious", ofstream::app);//输出模式与追加
	out.close();
	return 0;
}

 

=====================================================================

第8章 IO类 287页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;
class Sales_data
{
public://公有成员
	//新增构造函数(不同的类内初始化方式)
//	Sales_data() = default;//默认构造函数可以声明在类类部,也可以作为定义出现在类的外部

	explicit Sales_data(const std::string &s, unsigned n, double p) :
		bookNo(s), units_sold(n), revenue(p*n) {}
	/*Sales_data(std::istream& is)
	{
		read(is, *this);
	}*/
	//保留默认构造函数
	explicit Sales_data(std::string s = "")
		:bookNo(s) {}//bookNo(s)表示构造函数列表初始化(构造函数初始值列表)
	//只允许出现在类内声明构造函数时使用explicit
	explicit Sales_data(std::istream& is)
	{
		read(is, *this);
	}

	friend Sales_data add(const Sales_data&, const Sales_data&);
	friend std::istream& read(std::istream&, Sales_data&);
	friend std::ostream& print(std::ostream&, const Sales_data&);

	friend ifstream& read(ifstream& in, Sales_data& item)
	{
		double price = 0;
		in >> item.bookNo >> item.units_sold >> price;
		item.revenue = price * item.units_sold;
		return in;
	}
	friend ofstream& print(ofstream& out, const Sales_data& item)
	{
		out << item.isbn() << " " << item.units_sold << " "
			<< item.revenue << " " << item.ave_price() << endl;
		return out;
	}

	friend std::istream& operator>>(std::istream& is, Sales_data&);//operator>>重载,支持cin>>对象名接收
	friend std::ostream& operator<<(std::ostream& os, const Sales_data&);//operator<<重载,支持cin>>对象名直接输出内容
	//之前已有的其它成员
	std::string isbn() const;
	Sales_data& combine(const Sales_data&);


private://私有成员
	double ave_price()const;
	std::string bookNo;
	unsigned units_sold = 0;//c++11开始支持类体内初始化(变量名译:单独售出)
	double revenue = 0.0;//初始化revenue(译:财政收入)
};//这里要加分号

Sales_data add(const Sales_data &lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;//把lhs的数据拷贝给sum
	sum.combine(rhs);//把rhs的数据成员加到sum当中
	return sum;
}

//定义read和print函数
std::istream& read(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price() << endl;
	return os;
}
//上面两个等同于operator>>与operator<<重载
std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}


std::string Sales_data::isbn() const
{
	//return bookNo;//用于返回Sales_data的数据成员
	return this->bookNo;//同上
	//默认情况this指针指向非常量的常量指针
}
//函数combine设计初衷类型复合赋值运算符+=
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;//把rhs的成员加到this对象的成员上
	revenue += rhs.revenue;
	return *this;//返回调用该函数的对象
}
double Sales_data::ave_price()const
{
	return units_sold ? revenue / units_sold : 0;
}
/*
练习8.6:重写7.1.1节的书店程序(第229页),从一个文件中读取交易记录。将文件名作为一
个参数传递给main(参见6.2.5节,第196页)

操作方法:首先在cpp编译exe所在目录
(我的是vs2017路径C:\Users\Administrator\source\repos\01cpp\Debug)
新建一个1.txt
写入如下内容
9-999-99 6 7
9-999-99 7 7
9-999-98 5 8
写好并保存
然后再对这个文件夹shift+鼠标右键,调出此处dos命令窗口,我的文件是01cpp.exe
那就输入01cpp.exe 1.txt
控制台将输出
9-999-99 13 91 7
9-999-98 5 40 8
*/
int main(int argc, char *argv[])
{
	if (argc != 2)
	{
		cerr<<"请给出输入,输出文件名"<<endl;
		return -1;
	}
	ifstream in(argv[1]);
	if (!in)
	{
		cerr<<"无法打开文件"<<endl;
		return -1;
	}
	Sales_data total;
	if (read(in, total))
	{
		Sales_data trans;
		while (read(in,trans))
		{
			if (total.isbn() == trans.isbn())
				total.combine(trans);
			else
			{
				print(cout, total);
				total = trans;
			}
		}
		print(cout, total);
	}
	else
	{
		cerr<<"No data"<<endl;
		return -1;
	}
	return 0;
}

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;
class Sales_data
{
public://公有成员
	//新增构造函数(不同的类内初始化方式)
//	Sales_data() = default;//默认构造函数可以声明在类类部,也可以作为定义出现在类的外部

	explicit Sales_data(const std::string &s, unsigned n, double p) :
		bookNo(s), units_sold(n), revenue(p*n) {}
	/*Sales_data(std::istream& is)
	{
		read(is, *this);
	}*/
	//保留默认构造函数
	explicit Sales_data(std::string s = "")
		:bookNo(s) {}//bookNo(s)表示构造函数列表初始化(构造函数初始值列表)
	//只允许出现在类内声明构造函数时使用explicit
	explicit Sales_data(std::istream& is)
	{
		read(is, *this);
	}

	friend Sales_data add(const Sales_data&, const Sales_data&);
	friend std::istream& read(std::istream&, Sales_data&);
	friend std::ostream& print(std::ostream&, const Sales_data&);

	friend ifstream& read(ifstream& in, Sales_data& item)
	{
		double price = 0;
		in >> item.bookNo >> item.units_sold >> price;
		item.revenue = price * item.units_sold;
		return in;
	}
	friend ofstream& print(ofstream& out, const Sales_data& item)
	{
		out << item.isbn() << " " << item.units_sold << " "
			<< item.revenue << " " << item.ave_price() << endl;
		return out;
	}

	friend std::istream& operator>>(std::istream& is, Sales_data&);//operator>>重载,支持cin>>对象名接收
	friend std::ostream& operator<<(std::ostream& os, const Sales_data&);//operator<<重载,支持cin>>对象名直接输出内容
	//之前已有的其它成员
	std::string isbn() const;
	Sales_data& combine(const Sales_data&);


private://私有成员
	double ave_price()const;
	std::string bookNo;
	unsigned units_sold = 0;//c++11开始支持类体内初始化(变量名译:单独售出)
	double revenue = 0.0;//初始化revenue(译:财政收入)
};//这里要加分号

Sales_data add(const Sales_data &lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;//把lhs的数据拷贝给sum
	sum.combine(rhs);//把rhs的数据成员加到sum当中
	return sum;
}

//定义read和print函数
std::istream& read(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price() << endl;
	return os;
}
//上面两个等同于operator>>与operator<<重载
std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}


std::string Sales_data::isbn() const
{
	//return bookNo;//用于返回Sales_data的数据成员
	return this->bookNo;//同上
	//默认情况this指针指向非常量的常量指针
}
//函数combine设计初衷类型复合赋值运算符+=
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;//把rhs的成员加到this对象的成员上
	revenue += rhs.revenue;
	return *this;//返回调用该函数的对象
}
double Sales_data::ave_price()const
{
	return units_sold ? revenue / units_sold : 0;
}
/*
练习8.8:修改上一题的程序,将结果追加到给定的文件末尾。对同一个输出文件,运
行程序至少两次,检验数据是否得以保留。

操作方法:首先在cpp编译exe所在目录
(我的是vs2017路径C:\Users\Administrator\source\repos\01cpp\Debug)
新建一个1.txt
写入如下内容
9-999-99 6 7
9-999-99 7 7
9-999-98 5 8
写好并保存
然后再对这个文件夹shift+鼠标右键,调出此处dos命令窗口,我的文件是01cpp.exe
那就输入01cpp.exe 1.txt 2.txt回车后再次输出
控制台无输出,运行两次后,2.txt将在末尾追加结果
*/
int main(int argc, char *argv[])
{
	if (argc != 3)
	{
		cerr<<"请给出输入,输出文件名"<<endl;
		return -1;
	}
	ifstream in(argv[1]);
	if (!in)
	{
		cerr<<"无法打开输出文件"<<endl;
		return -1;
	}
	ofstream out(argv[2],ofstream::app);
	if (!out)
	{
		cerr << "无法打开输出文件" << endl;
		return -1;
	}
	Sales_data total;
	if (read(in, total))
	{
		Sales_data trans;
		while (read(in,trans))
		{
			if (total.isbn() == trans.isbn())
				total.combine(trans);
			else
			{
				print(out, total);
				total = trans;
			}
		}
		print(out, total);
	}
	else
	{
		cerr<<"No data"<<endl;
		return -1;
	}
	return 0;
}

 

=====================================================================

第8章 IO类 287页    string流

表8.5:stringstream特有的操作

sstream strm

strm是一个未绑定的stringstream对象。sstream是头文件sstream中定义的一个类型

sstream strm(s)

strm是一个sstream对象,保存string s的一个拷贝。此构造函数是explicit的(参见7.5.4节,第265页)

strm.str()

返回strm所保存的string的拷贝

strm.str(s)

将string s拷贝到strm中。返回void

=====================================================================

第8章 IO类   288页     使用istringstream

=====================================================================

#include<sstream>
#include<string>
#include<iostream>
using namespace std;
int main()
{
	/*istringstream从string读取数据(类似ifstream),ostringstream从string写入数据(类似ofstream),stringstream既可以读数据,也可以写数据(类似fstream)*/
	string s = "abc 123 hello world", out;
	istringstream isg("测试 123 abc 测试");
	cout << "1 isg格式化输出:" << isg.str() << endl << endl;
	isg.clear();//重复使用字符串流时,每次都要调用clear
	isg.str(s);
	isg >> out;//读取到string的out对象
	cout << "out = " << out << endl;//打印输出
	isg >> out;
	cout << "out = " << out << endl;
	isg >> out;
	cout << "out = " << out << endl;
	isg >> out;
	cout << "out = " << out << endl;
	isg >> out;
	cout << "2 isg格式化输出:" << isg.str() << endl << endl;

	ostringstream msg;
	msg << "哈 你好 123 abc" << endl;//写入字符串
	cout << "1 msg格式化输出:" << msg.str() << endl;//格式化输出
	msg.clear();
	msg.str(s);//把s存入msg
	cout << "2 msg格式化输出:" << msg.str() << endl << endl;
	msg << "内容 打印";
	cout << "3 msg格式化输出:" << msg.str() << endl << endl;
	msg.str("");//清空数据
	msg.clear();//clear() 方法只是重置了stringstream的状态标志,并没有清空数据。
	out = "123";
	msg << out;
	out = " abc";
	msg << out;
	out = " hello world";
	msg << out;
	cout << "4 msg格式化输出:" << msg.str() << endl << endl;
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include<iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;

struct PersonInfo
{
	string name;
	vector<string> phones;
};
int main()
{
	string line, word;//分别保存来自输入的一行和单词
	vector<PersonInfo> people;//保存来自输入的所有记录
	//遂行从输入读取数据,直至cin遇到文件尾(或其他错误)
	while (getline(cin,line))
	{
		PersonInfo info;//创建一个保存此记录数据的对象
		istringstream record(line);//将记录绑定到刚读入的行
		//假设line="张三 13500000000"
		//则info.name="张三"
		//再把第二个传给word,然后放入info.phones的vector
		record >> info.name;//读取名字
		while (record>>word)//读取电话号码
		{
			info.phones.push_back(word);//保存它们
		}
		people.push_back(info);//将此记录追加people末尾

	}
	system("pause");
	return 0;
}

=====================================================================

第8章 IO类 289页    练习题

=====================================================================

//QQ108201645编写
#include<iostream>
#include <sstream>
#include <string>
using namespace std;
/*练习8.9:使用你为8.1.2节(第281页)第一个练习所编写的函数打印一个istringstream对象的内容。*/

istream& f(istream& in)
{
	string v;
	while (in >> v, !in.eof())
	{
		if (in.bad())
			throw runtime_error("IO流错误");
		if (in.fail())
		{
			cerr << "数据错误,请重试" << endl;
			in.clear();//防止fail和bad
			in.ignore(100, '\n');
			continue;
		}
		cout<<v<<endl;
	}
	in.clear();
	return in;
}
int main()
{
	ostringstream msg;
	msg << "C++ Primer 第五版" << endl;
	istringstream in(msg.str());// 返回in所保存的string的拷贝
	f(in);

	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include<iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
/*练习8.10:编写程序,将来自一个文件中的行保存在一个vector中。然后
使用一个istringstream从vector读取数据元素,每次读取一个单词。*/

int main()
{
	string line;
	vector<string> words;
	while (getline(cin, line))//从文件读取一行
	{
		words.push_back(line);//添加到vector中
	}
	in.close();
	vector<string> ::const_iterator it = words.begin();//迭代器
	while (it!=words.end())//遍历vector
	{
		istringstream line_str(*it);
		string word;
		while (line_str>>word)//通过istringstream从vector中读取数据
		{
			cout << word << " ";
		}
		cout<<endl;
		++it;
	}
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include<iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

/*练习8.11:本节的程序在外层while循环中定义了istringstream 对象。如果
record 对象定义在循环之外,你需要对程序进行怎样的修改?重写程序,将record
的定义移到while循环之外,验证你设想的修改方法是否正确*/
class PersonInfo
{
public:
	string name;
	vector<string> phones;
};

int main()
{
	string line, word;//创建string两个对象
	vector<PersonInfo> people;//创建一个存放类类型的vector,用来保存输入的所有记录
	istringstream record;
	while (getline(cin, line))//读取一行存放line
	{
		PersonInfo info;//创建一个保存记录的对象
		record.clear();//重复使用字符串流时,每次都要调用clear
		record.str(line);//绑定line
		record >> info.name;//读取名字,把第一个空格前的字符串传给info.name
		while (record >> word)//读取电话号码,把第二个空格前的字符串传给word
			info.phones.push_back(word);//再把word的字符串放入info.phones
		people.push_back(info);//将记录追加到末尾
	}

	system("pause");
	return 0;
}

=====================================================================

第8章 IO类   289页     使用ostringstream

=====================================================================

//QQ108201645编写
#include<iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

class PersonInfo
{
public:
	string name;
	vector<string> phones;
};
bool valid(const string &s)
{
	return true;
}
string format(const string &s) 
{  
	return s; 
}
vector<PersonInfo> getData(istream &is)
{
	string line, word;//创建string两个对象
	vector<PersonInfo> people;//创建一个存放类类型的vector,用来保存输入的所有记录
	istringstream record;
	while (getline(cin, line))//读取一行存放line
	{
		PersonInfo info;//创建一个保存记录的对象
		record.clear();//重复使用字符串流时,每次都要调用clear
		record.str(line);//绑定line
		record >> info.name;//读取名字,把第一个空格前的字符串传给info.name
		while (record >> word)//读取电话号码,把第二个空格前的字符串传给word
			info.phones.push_back(word);//再把word的字符串放入info.phones
		people.push_back(info);//将记录追加到末尾
	}
	return people;
}
ostream& process(ostream &os, vector<PersonInfo> people)
{
	for (const auto &entry : people)//对people中每一项
	{
		ostringstream formatted, badNums;//每个循环步创建的对象
		for (const auto& nums : entry.phones)//对应PersonInfo中vector<string> phones的每个string对象
		{
			if (!valid(nums))
				badNums << " " << nums;//将数的字符串形式存入badNums
			else
				formatted << " " << format(nums);//format(nums)连同空格写入到formatted
		}
		if (badNums.str().empty())//没有错误的数
			os << entry.name << " "//打印名字
			<< formatted.str() << endl;//和格式化的数
		else//否则打印错误的名字
			cerr << "input error : " << entry.name
			<< " invalid number(s) " << badNums.str() << endl;
	}
	return os;
}
int main()
{
	process(cout, getData(cin));
	system("pause");
	return 0;
}

=====================================================================

第8章 IO类 289页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
//练习8.13:重写本节的电话号码程序,从一个命名文件而非cin读取数据。
class PersonInfo
{
public:
	string name;
	vector<string> phones;
};
bool valid(const string &s)
{//17章介绍如何验证电话号码,现在只返回true
	return true;
}
string format(const string &s) 
{  
	return s; 
}

int main()
{
	ofstream file_("people.txt",ios::out|ios::binary);
	//创建文件people,以写入方式打开,二进制方式
	if (!file_)
		cerr<<"未发现文件"<<endl;
	file_<<"abc 123 456"<<endl;//写入字符串
	file_ << "hello 456 789" << endl;//写入第二行字符串
	file_.close();//关闭
	ifstream file("people.txt");//cpp目录下新建一个people.txt并输入abc 123保存或默认使用上面的代码创建文件
	if (!file)
	{
		cerr << "No file" << endl;
		return -1;
	}
	string line, word;
	vector<PersonInfo> people;
	while (getline(file,line))
	{
		PersonInfo info;
		istringstream record(line);
		record >> info.name;
		while (record>>word)
		{
			info.phones.push_back(word);
		}
		people.push_back(info);

	}
	//读取完后关闭文件
	file.close();
	for (const auto &entry : people)
	{
		ostringstream formatted, badNums;
		for (const auto &nums : entry.phones)
		{
			if (!valid(nums))
				badNums << " " << nums;
			else
			{
				formatted << " " << format(nums);
			}
		}
		if (badNums.str().empty())
			cout<<entry.name<<" "<<formatted.str()<<endl;
		else
		{
			cerr<<" input error: "<<entry.name<<" invalid number(s) "<<badNums.str()<<endl;
		}
	}

	/*练习8.14:我们为什么将entry和nums定义为 const auto& ?
		一是避免拷贝,二是防止改变它们。*/

	system("pause");
	return 0;
}

 

=====================================================================

//改写成迭代器
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;

class PersonInfo
{
public:
	string name;
	vector<string> phones;
};
bool vaild(const string& s)
{
	return true;
}
string format(const string &s)
{
	return s;
}

int main()
{
	ofstream outfile("people.txt");
	if (!outfile)
		cerr << "未发现文件,并创建" << endl;
	outfile << "张三 135 13801" << endl;
	outfile << "李四 186 1330" << endl;
	outfile.close();
	ifstream infile("people.txt");
	if (!infile)
	{
		cerr << "未发现文件,退出" << endl;
		exit(1);//退出
	}
	string line, word;
	vector<PersonInfo> people;
	istringstream record;
	while (getline(infile, line))
	{
		PersonInfo info;
		record.clear();
		record.str(line);

		record >> info.name;
		while (record >> word)
			info.phones.push_back(word);
		people.push_back(info);
	}
	//读取完关闭
	infile.close();
	for (vector<PersonInfo>::const_iterator entry = people.begin();
		entry != people.end(); ++entry)
	{
		ostringstream formatted, badNums;
		for (vector<string>::const_iterator nums = entry->phones.begin();
			nums != entry->phones.end(); ++nums)
		{
			if (!vaild(*nums))
				badNums << " " << *nums;
			else
				formatted << " " << format(*nums);
		}
		if (badNums.str().empty())
			cout << entry->name << " " << formatted.str() << endl;
		else
			cerr << " input error: " << entry->name << " invalid number(s) " << badNums.str() << endl;
	}
	system("pause");
	return 0;
}

=====================================================================

//改写for循环

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

class PersonInfo
{
public:
	string name;
	vector<string> phones;
};
bool valid(const string& s)
{
	return true;
}

string format(const string& s)
{
	return s;
}

vector<PersonInfo> getdata(istream& s)
{
	string line, word;
	vector<PersonInfo> people;
	istringstream record;
	cout<<"输入一行内容,如果输入end则结束"<<endl;
	while (getline(cin,line)&&line!="end")
	{
		PersonInfo info;
		record.clear();//清除内容
		record.str(line);//绑定line
		record >> info.name;
		while (record>>word)
		{
			info.phones.push_back(word);
		}
		people.push_back(info);
		cout << "输入一行内容,如果输入end则结束" << endl;
	}
	return people;
}

ostream& process(ostream& os, vector<PersonInfo> people)
{
	for (size_t i = 0; i < people.size(); i++)
	{
		ostringstream formatted, badNums;
		for (size_t j = 0; j < people[i].phones.size(); j++)
		{
			if (!valid(people[i].phones[j]))
				badNums << " " << people[i].phones[j];
			else
				formatted << " " << format(people[i].phones[j]);
		}
		if (badNums.str().empty())
			os << people[i].name << " " << formatted.str() << endl;
		else
			os<<"input error: "<<people[i].name<< " "<<badNums.str()<<endl;
	}
	return os;
}
int main()
{
	process(cout, getdata(cin));
	system("pause");
	return 0;
}

=====================================================================

 

#include <fstream>
#include <time.h>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
#pragma warning(disable:4996)
size_t nums = 1;

string RetTime()
{//获取系统时间
	time_t timep;//创建timep对象
	time(&timep);//获取系统时间,返回一个指针
	/*time_t time(time_t *seconds) 返回自纪元 Epoch(1970-01-01 00:00:00 UTC)起经过的时间,
	以秒为单位。如果 seconds 不为空,则返回值也存储在变量 seconds 中。
	seconds -- 这是指向类型为 time_t 的对象的指针,用来存储 seconds 的值。*/
	char tmp[64];
	struct tm * p = localtime(&timep);
	//	cout<<asctime(p)<<endl;//把时间转成字符串
	strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", p);
	//格式化结构 *p 表示的时间,并把它存储在 tmp 中。最大字符数为sizeof(tmp)
	return tmp;
}



void DeleteFileRow()
{
	ifstream infile("1.txt");
	if (!infile)
		cerr << "未发现文件并创建" << endl;
	string line;
	vector<string> svec;
	while (getline(infile,line))
	{
		svec.push_back(line);
	}
	infile.close();
	size_t flag = 0;
	while (svec.size() > 9)
	{
		svec.erase(svec.begin());
		flag = 1;
	}
	if (flag == 1)
	{
		ofstream out("1.txt");
		if (!out)
		{
			cerr << "未发现文件" << endl;
			return;
		}
		for (auto i : svec)
		{
			out.write(i.c_str(), i.size());
			out << endl;//因为读取时不会读到行数,所以直接加一个换行
		}
		out.close();
	}
}
void GetLog()
{
	DeleteFileRow();
	ofstream out("1.txt", ios::out | ios::binary | ios::app);
	if (out.fail())
		cerr << "未发现文件" << endl;
	string buf = RetTime();
	out << "(" << nums++ << ") " << buf.c_str() << endl;
	out.close();
}

int main()
{
	cout << "错误信息" << endl;
	while (true)
	{
		GetLog();
	}
	system("pause");
	return 0;
}

=====================================================================

 

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
bool Gline_(ifstream& fin,string& s)
{
	char c[1024]{ 0 };
	size_t i = 0;
	while (!fin.eof())
	{
		fin.get(c[i]);
		if (c[i] == '\n')
		{
			i = -1;
			break;
		}
		i++;
	}
	s = c;
	return !fin.eof();//返回是否结束
}

int main()
{
	ofstream open("1.txt");
	if(open.fail())
		cerr<<"未发现文件"<<endl;
	open << "abcqqq 123" << endl;
	open << "bcd 123" << endl;
	open.close();
	ifstream in("1.txt");

	vector<string> svec;
	/*=====================================================================*/
	//假设用getline将会少了换行符
	/*string line;
	while (getline(in,line))
	{
		svec.push_back(line);
	}*/
	/*=====================================================================*/
	/*char c[1024]{ 0 };
	size_t i = 0;
	while (!in.eof())
	{
		in.get(c[i]);
		if (c[i]== '\n')
		{
			svec.push_back(c);
			i = -1;
			memset(c, 0, 1024);
		}
		i++;
	}*/
	/*=====================================================================*/
	//自定义Gline_实现
	string line;
	while (Gline_(in,line))
	{
		svec.push_back(line);
	}
	/*=====================================================================*/
	in.close();
	open.open("2.txt");
	for (auto i : svec)
	{
		cout << i.size() <<" "<<i;//长度与内容
		open.write(i.c_str(), i.size());
	}
	open.close();
	system("pause");
	return 0;
}

=====================================================================

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值