《C++ Primer》第8章 IO库
8.2 文件输入输出习题答案
练习8.4:编写函数,以读模式打开一个 文件,将其内容读入到一个string的vector中,将每一行作为一个独立的元素存于vector中。
【出题思路】
本题练习文件输入和流的逐行输入,还练习了使用迭代器遍历容器中的元素。
【解答】
data.txt里的内容
C++ is a middle-level programming language developed
by Bjarne Stroustrup starting in 1979 at Bell Labs.
C++ runs on a variety of platforms, such as Windows,
Mac OS, and the various versions of UNIX.
#include#include #include #include using namespace std; int main() { ifstream in("../chapter08/data.txt"); //打开文件 cout << "输入字符串; " << endl; if(!in) { cerr << "无法打开输入文件" << endl; return -1; } string line; vector words; while(getline(in, line))//从文件中读取一行 { words.push_back(line);//添加到vector中 } in.close(); //输入完毕,关闭文件 vector ::const_iterator it = words.begin(); //迭代器 while(it != words.end())//遍历vector { cout << *it << endl;//输出vector中的元素 ++it; } return 0; }
运行结果:
练习8.5:重写上面的程序,将每个单词作为一个独立的元素进行存储。
【出题思路】
本题练习逐个数据的输入方式。
【解答】
将第18行的while (getline(in, line)){
改为while (in >> line){即可。
#include#include #include #include using namespace std; int main() { ifstream in("../chapter08/data.txt"); //打开文件 cout << "输入字符串; " << endl; if(!in) { cerr << "无法打开输入文件" << endl; return -1; } string line; vector words; while(in >> line) //从文件中读取每一个单词 { words.push_back(line);//添加到vector中 } in.close(); //输入完毕,关闭文件 vector ::const_iterator it = words.begin(); //迭代器 while(it != words.end())//遍历vector { cout << *it << endl;//输出vector中的元素 ++it; } return 0; }
运行结果:
练习8.6:重写7.1.1节的书店程序(第229)页,从一个文件中读取交易记录。将文件名作为一个参数传递给main(参见6.2.5节,第196页)。
【出题思路】
通过一个较大的例子继续练习文件输入,并练习从命令行获取参数及参数合法性的检测。
【解答】
#ifndef PROGRAM08_06_H #define PROGRAM08_06_H #include#include class Sales_data { friend std::istream& operator >> (std::istream&, Sales_data&); friend std::ostream& operator << (std::ostream&, const Sales_data&); friend bool operator < (const Sales_data&, const Sales_data&); friend bool operator == (const Sales_data&, const Sales_data&); friend Sales_data add(const Sales_data &lhs, const Sales_data &rhs); friend std::istream &read(std::istream &is, Sales_data &item); friend std::ostream &print(std::ostream &os, const Sales_data &item); public: Sales_data() = default; Sales_data(const std::string &book): bookNo(book) { //std::cout << "call ======Sales_data(const std::string &book): bookNo(book)=============" << std::endl; } //explicit Sales_data(std::istream &is) Sales_data(std::istream &is) { //std::cout << "call ======Sales_data(std::istream &is)=============" << std::endl; is >> *this; } Sales_data(const std::string &book, const unsigned num, const double sellp, const double salep); //定义公有函数成员 public: Sales_data& operator += (const Sales_data&); double avg_price() const; std::string isbn() const { return bookNo; } //combine函数用于把两个ISBN相同的销售记录合并在一起 Sales_data& combine(const Sales_data &rhs) { units_sold += rhs.units_sold; //累加书籍的销售量 saleprice = (rhs.saleprice * rhs.units_sold + saleprice * units_sold) / (rhs.units_sold + units_sold); //重新计算实现销售价格 discount = saleprice / sellingprice; //重新计算实际折扣 revenue += rhs.revenue; //总销售额 return *this; //返回合并后的结果 } // 定义私有数据成员 private: std::string bookNo; // 书籍编号,隐式初始化为空串 unsigned units_sold = 0; // 销售量,显式初始化为0 double sellingprice = 0.0; // 原始价格,显式初始化为0.0 double saleprice = 0.0; // 实售价格,显式初始化为0.0 double discount = 0.0; // 折扣,显式初始化为0.0 double revenue = 0.0; // 总收入 }; Sales_data::Sales_data(const std::string &book, const unsigned num, const double sellp, const double salep) { bookNo = book; units_sold = num; sellingprice = sellp; saleprice = salep; if(0 != sellingprice) { discount = saleprice / sellingprice; //计算实际折扣 } } //add Sales_data add(const Sales_data &lhs, const Sales_data &rhs) { Sales_data sum = lhs; sum.combine(rhs); return sum; } //read std::istream& read(std::istream &is, Sales_data &item) { is >> item.bookNo >> item.units_sold >> item.sellingprice >> item.saleprice; return is; } //print std::ostream& print(std::ostream &os, const Sales_data &item) { os << item.isbn() << " " << item.units_sold << " " << item.sellingprice << " " << item.saleprice << " " << item.discount; return os; } inline bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs) { return lhs.isbn() == rhs.isbn(); } Sales_data operator + (const Sales_data&, const Sales_data&); inline bool operator == (const Sales_data &lhs, const Sales_data &rhs) { // must be made a friend of Sales_item return lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue && lhs.isbn() == rhs.isbn(); } inline bool operator != (const Sales_data &lhs, const Sales_data &rhs) { return !(lhs == rhs); // != defined in terms of operator== } Sales_data& Sales_data::operator += (const Sales_data& rhs) { units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; } // assumes that both objects refer to the same ISBN Sales_data operator + (const Sales_data& lhs, const Sales_data& rhs) { Sales_data ret(lhs); // copy (|lhs|) into a local object that we'll return ret += rhs; // add in the contents of (|rhs|) return ret; // return (|ret|) by value } //接收4个参数分别为:ISBN,销售量,原价,实际售价 std::istream& operator >> (std::istream& in, Sales_data& s) { in >> s.bookNo >> s.units_sold >> s.sellingprice >> s.saleprice; // check that the inputs succeeded if (in) s.revenue = s.units_sold * s.saleprice; else s = Sales_data(); // input failed: reset object to default state return in; } std::ostream& operator << (std::ostream& out, const Sales_data& s) { out << s.isbn() << " " << s.units_sold << " " << s.revenue << " " << s.avg_price(); return out; } double Sales_data::avg_price() const { if (units_sold) return revenue / units_sold; else return 0; } #endif // PROGRAM08_06_H
#include#include #include #include #include "program08_06.h" using namespace std; int main(int argc, char *argv[]) { if(argc != 2) { cerr << "请给出文件名" << endl; return -1; } cout << "文件名:" << argv[1] << endl; 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()) //检查isbn { total.combine(trans); //更新变量total当前的值 } else { print(cout, total) << endl; //输出结果 total = trans; //处理下一本书 } } print(cout, total) << endl; //输出最后一条交易 } else //没有输入任何信息 { cerr << "没有数据" << endl; //通知用户 } return 0; }
QtCeate调试参数设置
运行结果:
练习8.7:修改上一节的书店程序,将结果保存到一个文件中。将输出文件名作为第二个参数传递给main函数。
【出题思路】
本题练习文件输出。
【解答】
头文件与练习8.6 一样。
#include#include #include #include #include "program08_06.h" using namespace std; int main(int argc, char *argv[]) { if(argc != 3) { cerr << "请给出输入,输出文件名" << endl; return -1; } cout << "输入文件名:" << argv[1] << endl; cout << "输出文件名:" << argv[2] << endl; ifstream in(argv[1]); if(!in) { cerr << "无法打开输入的文件" << endl; return -1; } ofstream out(argv[2]); 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()) //检查isbn { total.combine(trans); //更新变量total当前的值 } else { print(out, total) << endl; //输出结果 total = trans; //处理下一本书 } } print(out, total) << endl; //输出最后一条交易 } else //没有输入任何信息 { cerr << "没有数据" << endl; //通知用户 } return 0; }
设置输出参数
运行结果:
练习8.8:修改上一题的程序,将结果追加到给定的文件末尾。对同一个输出文件,运行程序至少两次,检验数据是否得以保留。
【出题思路】
本题练习文件的追加模式。
【解答】
将上一题程序的第19行ofstream out l(argv[2]);
改为ofstream out(argv[2],ofstream::app);。
头文件也练习8.6 一样
#include#include #include #include #include "program08_06.h" using namespace std; 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()) //检查isbn { total.combine(trans); //更新变量total当前的值 } else { print(out, total) << endl; //输出结果 total = trans; //处理下一本书 } } print(out, total) << endl; //输出最后一条交易 } else //没有输入任何信息 { cerr << "没有数据" << endl; //通知用户 } cout << "run sucess============" << endl; return 0; }
设置命令行参数
第一次运行:
第二次运行:



