练习8.1 编写函数,接受一个istream&参数,返回值类型也是istream&。此函数须从给定流中读取数据,直至遇到文件结束标识时停止。它将读取的数据打印在标准输出上。完成这些操作后,在返回流之前,对流进行复位,使其处于有效状态。
练习8.2 测试函数,调用参数为cin.
答案:
1 #include <iostream> 2 using namespace std; 3 istream& func(istream& os) 4 { 5 int v; 6 while (os >> v, os.eof() != 1)//只有在碰到结束符时才停止输入,windows下为ctrl+z 7 { 8 if (os.bad()) 9 throw runtime_error("IO流错误"); 10 if (os.fail())//遇到数据型错误时,必须清空缓冲区 11 { 12 cerr << "数据型错误,重新输入" << endl; 13 os.clear(); 14 //清理方式1 ,直接清空缓冲区中的当前新行的剩余数据 15 os.ignore(100,'\n');//必须清理缓冲区,清理错误数据,否则过不去 16 continue; 17 } 18 cout << v << endl; 19 } 20 os.clear();//必须复位恢复流正常状态,后续才可继续使用输入 21 return os; 22 } 23 24 istream& func2(istream& os) 25 { 26 int v; 27 while (os >> v, os.eof() != 1)//只有在碰到结束符时才停止输入 28 { 29 if (os.bad()) 30 throw runtime_error("IO流错误"); 31 if (os.fail())//遇到数据型错误时,必须清空缓冲区 32 { 33 cerr << "数据型错误,重新输入" << endl; 34 os.clear(); 35 //清理方式2,只清空遇到的错误类型数据,后面正确类型的数据保留。 36 while (!isspace(cin.get()))//只把空白符之前(包括空白符)的错误型数据读取出来扔掉 37 continue; 38 continue; 39 } 40 cout << v << endl; 41 } 42 os.clear();//必须复位恢复流正常状态,后续才可继续使用输入 43 return os; 44 } 45 int main() 46 { 47 //istream mycin; //错误,不能自定义标准IO流对象,其构造函数都是私有的。 48 func(cin); 49 //用于测试如果不复位,能否继续使用cin, 并不能。 50 //cin.clear(); 51 //int v;//继续输入 52 //cin >> v; 53 //cout << v << endl; 54 }
练习8.3 什么情况下,下面的while
循环会终止?
1 while (cin >> i) /* ... */ 1 while (cin >> i) /*...*/
1 while (cin >> i) /*...*/1 while (cin >> i) /*...*/
答案:
当遇到了IO流错误,或者遇到文件结束符,或者读入了无效数据时,会终止循环。
即当badbit,failbit,eofbit任何一个流状态位被置位时将会终止循环。
练习8.4 编写函数,以读模式打开一个文件,将其内容读入到一个string
的vector
中,将每一行作为一个独立的元素存于vector
中。
答案:
1 #include <iostream> 2 #include <fstream> 3 #include <vector> 4 #include <string> 5 using namespace std; 6 int main() 7 { 8 //方式1 9 ifstream fcin("temp.txt"); 10 if (!fcin)//如果打开文件失败 11 { 12 cout << "文件打开失败" << endl; 13 return -1; 14 } 15 16 string strbuf(""); 17 vector<string> vi; 18 while (std::getline(fcin, strbuf)) 19 { 20 vi.push_back(strbuf); 21 } 22 23 //读取完毕后打印vector进行测试 24 for (auto iter = vi.begin(); iter != vi.end(); iter++)//传统for 25 { 26 cout << *iter << endl; 27 } 28 29 fcin.close(); 30 }
1 #include <iostream> 2 #include <fstream> 3 #include <vector> 4 #include <string> 5 using namespace std; 6 int main() 7 { 8 //方式2 9 ifstream fcin; 10 fcin.open("temp.txt"); 11 if (!fcin)//如果打开文件失败 12 { 13 cout << "文件打开失败" << endl; 14 return -1; 15 } 16 string strbuf(""); 17 vector<string> vi; 18 while (std::getline(fcin, strbuf)) 19 { 20 vi.push_back(strbuf); 21 } 22 23 //读取完毕后打印vector进行测试 24 for (auto line : vi)//范围for 25 { 26 cout << line << endl; 27 } 28 29 fcin.close(); 30 }
练习8.5 重写上面的程序,将每个单词作为一个独立的元素进行存储。
答案:
1 #include <iostream> 2 #include <fstream> 3 #include <vector> 4 #include <string> 5 using namespace std; 6 int main() 7 { 8 9 ifstream fcin("temp.txt"); 10 if (!fcin)//如果打开文件失败 11 { 12 cout << "文件打开失败" << endl; 13 return -1; 14 } 15 16 string strbuf(""); 17 vector<string> vi; 18 while (fcin >> strbuf)//从第一个非空白字符开始按单词读取,到空白符结束 19 { 20 vi.push_back(strbuf); 21 } 22 23 //读取完毕后打印vector进行测试 24 for (auto iter = vi.begin(); iter != vi.end(); iter++)//传统for 25 { 26 cout << *iter << endl; 27 } 28 29 fcin.close(); 30 }
练习8.6 修改书店程序
重写7.1.1节的书店程序,从一个文件中读取交易记录。将文件名作为一个参数传递给main
。
答案:
1 //Sales.cpp 2 3 #include <iostream> 4 using std::istream; 5 using std::ostream; 6 7 #include "Sales_data.h" 8 Sales_data::Sales_data(std::istream& is) 9 { 10 // read will read a transaction from is into this object 11 read(is, *this); 12 } 13 14 double Sales_data::avg_price() const { 15 if (units_sold) 16 return revenue / units_sold; 17 else 18 return 0; 19 } 20 21 // add the value of the given Sales_data into this object 22 Sales_data& Sales_data::combine(const Sales_data& rhs) 23 { 24 units_sold += rhs.units_sold; // add the members of rhs into 25 revenue += rhs.revenue; // the members of ``this'' object 26 return *this; // return the object on which the function was called 27 } 28 29 Sales_data add(const Sales_data& lhs, const Sales_data& rhs) 30 { 31 Sales_data sum = lhs; // copy data members from lhs into sum 32 sum.combine(rhs); // add data members from rhs into sum 33 return sum; 34 } 35 36 // transactions contain ISBN, number of copies sold, and sales price 37 istream& read(istream& is, Sales_data& item) 38 { 39 double price = 0; 40 is >> item.bookNo >> item.units_sold >> price; 41 item.revenue = price * item.units_sold; 42 return is; 43 } 44 45 ostream& print(ostream& os, const Sales_data& item) 46 { 47 os << item.isbn() << " " << item.units_sold << " " 48 << item.revenue << " " << item.avg_price(); 49 return os; 50 }View Code
1 //Sales_data.h 2 3 #ifndef SALES_DATA_H 4 #define SALES_DATA_H 5 6 #include <string> 7 #include <iostream> 8 9 class Sales_data { 10 friend Sales_data add(const Sales_data&, const Sales_data&); 11 friend std::ostream& print(std::ostream&, const Sales_data&); 12 friend std::istream& read(std::istream&, Sales_data&);// 13 public: 14 // constructors 15 Sales_data() 16 : units_sold(0), revenue(0.0) 17 { 18 } 19 Sales_data(const std::string& s) 20 :bookNo(s), units_sold(0), revenue(0.0) 21 { 22 } 23 Sales_data(const std::string& s, unsigned n, double p)//书的isbn字符串,销售数量,单价 24 :bookNo(s), units_sold(n), revenue(p * n) 25 { 26 } 27 Sales_data(std::istream&); 28 29 // operations on Sales_data objects 30 std::string isbn() const //返回isbn 31 { return bookNo; } 32 Sales_data& combine(const Sales_data&);//+= 33 double avg_price() const; //计算本书的单价 34 private: 35 std::string bookNo;//ISBN 36 unsigned units_sold;//本书已销售数量 37 double revenue;//销售总金额 38 }; 39 40 41 // nonmember Sales_data interface functions 42 Sales_data add(const Sales_data&, const Sales_data&); 43 std::ostream& print(std::ostream&, const Sales_data&); 44 std::istream& read(std::istream&, Sales_data&); 45 46 // used in future chapters 47 inline 48 bool compareIsbn(const Sales_data& lhs, const Sales_data& rhs) 49 { 50 return lhs.isbn() < rhs.isbn(); 51 } 52 #endifView Code
1 #include "Sales_data.h" 2 #include <iostream> 3 #include <fstream> 4 using namespace std; 5 //已假设文件内同一类书的所有交易项(每单交易项)均是紧挨连续在一起的,且每行都一条订单交易项 6 7 int main(int args,char* argv[]) 8 { 9 fstream fcin(argv[1]);//关联并打开参数指定的文件 10 if (!fcin) 11 { 12 cout << "文件打开失败" << endl; 13 return -1; 14 } 15 16 Sales_data total;//用于保存同类书的数据总和 17 18 if (read(fcin, total)) 19 { 20 Sales_data next; 21 while (read(fcin, next)) 22 { 23 if (total.isbn() == next.isbn())//如果是相同书,则累加交易量 24 { 25 total.combine(next);//累加 26 } 27 else//碰到下一种书,则打印上一种书的交易总量 28 { 29 print(cout, total) << endl;// 打印上一种书的交易总量 30 total = next;//为统计下一种书做准备 31 } 32 } 33 print(cout, total) << endl;// 补刀,打印最后一种书的交易总量 34 } 35 else 36 { 37 cout << "一条交易数据也没读取到" << endl; 38 } 39 41 std::cout << "Hello World!\n"; 42 }
练习8.7
//修改上一节的书店程序,将结果保存到一个文件中。将输出文件名作为第二个参数传递给main函数。 #include "Sales_data.h" #include <iostream> #include <fstream> using namespace std; //已假设文件内同一类书的所有交易项(每单交易项)均是紧挨连续在一起的,且每行都一条订单交易项 int main(int args,char* argv[]) { fstream fcin(argv[1]);//关联并打开参数指定的文件 if (!fcin) { cout << "文件1打开失败" << endl; return -1; } fstream fcout(argv[2]); //关联并打开参数指定的文件 默认打开in|out if (!fcout) { cout << "文件2打开失败" << endl; fcin.close(); return -1; } Sales_data total;//用于保存同类书的数据总和 if (read(fcin, total)) { Sales_data next; while (read(fcin, next)) { if (total.isbn() == next.isbn())//如果是相同书,则累加交易量 { total.combine(next);//累加 } else//碰到下一种书,则打印上一种书的交易总量 { // 把上一种书的交易总量写入文件 print(fcout, total) << endl; total = next;//为统计下一种书做准备 } } print(fcout, total) << endl;// 补刀,写入最后一种书的交易总量 } else { cout << "一条交易数据也没读取到" << endl; } fcin.close(); fcout.close(); }
练习8.8
//修改上一题的程序,将结果追加到给定的文件末尾。对同一个输出文件,运行程序至少两次,检验数据是否得以保留。 #include <iostream> #include <fstream> using namespace std; //已假设文件内同一类书的所有交易项(每单交易项)均是紧挨连续在一起的,且每行都一条订单交易项 int main(int args,char* argv[]) { fstream fcin(argv[1]);//关联并打开参数指定的文件 if (!fcin) { cout << "文件1打开失败" << endl; return -1; } fstream fcout(argv[2],fstream::app); //关联并打开参数指定的文件 默认打开out|app if (!fcout) { cout << "文件2打开失败" << endl; fcin.close(); return -1; } Sales_data total;//用于保存同类书的数据总和 if (read(fcin, total)) { Sales_data next; while (read(fcin, next)) { if (total.isbn() == next.isbn())//如果是相同书,则累加交易量 { total.combine(next);//累加 } else//碰到下一种书,则打印上一种书的交易总量 { // 把上一种书的交易总量写入文件 print(fcout, total) << endl; total = next;//为统计下一种书做准备 } } print(fcout, total) << endl;// 补刀,写入最后一种书的交易总量 } else { cout << "一条交易数据也没读取到" << endl; } fcin.close(); fcout.close(); }
练习8.9
使用你为8.1.2节第一个练习所编写的函数打印一个istringstream
对象的内容。
那个题的循环读取的判断方式并不适合用读取字符串流对象上,因为用在字符串输入流对象中的数据结尾可能不存在空白符,导致在最后一次读取数据后无法再进入循环,造成最后一次的数据没有打印。. 或者说之前那个题的写法不好。不通用。 下面是其他人的代码:虽然考虑的简单,但胜在没BUG,通用。 //之前那个题的: std::istream& func(std::istream &is) { std::string buf; while (is >> buf) std::cout << buf << std::endl; is.clear(); return is; } //现在这个题的: #include <iostream> #include <sstream> using std::istream; istream& func(istream &is) { std::string buf; while (is >> buf) std::cout << buf << std::endl; is.clear(); return is; } int main() { std::istringstream iss("hello"); func(iss); return 0; }
标签:类库,std,const,istream,Sales,C++,IO,include,data From: https://www.cnblogs.com/toupifama917/p/18413581