C++中文件的读取操作,如何读取多行数据,如何一个一个的读取数据

练习8.1:编写函数。接受一个istream&参数,返回值类型也是istream&。此函数必须从给定流中读取数据,直至遇到文件结束标识时停止。

 

  1. #include <iostream>  
  2. #include <stdexcept>  
  3.   
  4. using std::istream;  
  5. using std::cin;  
  6. using std::cout;  
  7. using std::cerr;  
  8. using std::endl;  
  9. using std::runtime_error;  
  10.   
  11. istream &f(istream &in)  
  12. {  
  13.     int v;  
  14.     while(in >> v, !in.eof())  
  15.     {  
  16.         if(in.bad())  
  17.             throw runtime_error("IO Stream error.");  
  18.         if(in.fail())  
  19.         {  
  20.             cerr<<"Data error! Please try again."<<endl;  
  21.             in.clear();  
  22.             in.ignore(100, '\n');  
  23.             continue;  
  24.         }  
  25.         cout<< v <<endl;  
  26.     }  
  27.     in.clear();  
  28.     return in;  
  29. }  
  30.   
  31. int main()  
  32. {  
  33.     cout<<"Please input some numbers, enter Ctrl+Z to end"<<endl;  
  34.     f(cin);  
  35.     return 0;  
  36. }  

练习8.3:什么情况下,下面的while循环会终止?

while (cin >> i) /*. . .*/

遇到文件结束符,或者遇到了IO流错误或者读入了无效数据。


练习8.4:编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个独立的元素存于vector中。

 
    #include <iostream>  
    #include <string>  
    #include <fstream>  
    #include <vector>  
    using std::cout;  
    using std::endl;  
    using std::string;  
    using std::ifstream;  
    using std::cerr;  
    using std::vector;  
      
    int main()  
    {  
        ifstream in("data.txt");  
        if(!in) {  
            cerr<<"Can't open the file."<<endl;  
            return -1;  
        }  
      
        string line;  
        vector<string> words;  
        while(getline(in, line))  
            words.push_back(line);  
      
        in.close();  
      
        vector<string>::const_iterator it = words.cbegin();  
        while (it != words.cend())  
        {  
            cout<< *it <<endl;  
            ++it;  
        }  
        return 0;  
    }  

 


练习8.5:重写上面的程序,将每个单词作为一个独立的元素进行存储。

 

    #include <iostream>  
    #include <string>  
    #include <fstream>  
    #include <vector>  
    using std::cout;  
    using std::endl;  
    using std::string;  
    using std::ifstream;  
    using std::cerr;  
    using std::vector;  
      
    int main()  
    {  
        ifstream in("data.txt");  
        if(!in) {  
            cerr<<"Can't open the file."<<endl;  
            return -1;  
        }  
      
        string line;  
        vector<string> words;  
        while(in >> line)  
            words.push_back(line);  
      
        in.close();  
      
        vector<string>::const_iterator it = words.cbegin();  
        while (it != words.cend())  
        {  
            cout<< *it <<endl;  
            ++it;  
        }  
        return 0;  
    }  

 


练习8.6:重写7.1.1节的书店程序,从一个文件中读取交易记录。将文件名作为一个参数传递给main。

 

  1. #include <iostream>  
  2. #include <fstream>  
  3. #include "Sales_data.h"  
  4.   
  5. using std::cout;  
  6. using std::cerr;  
  7. using std::ifstream;  
  8. using std::endl;  
  9.   
  10. int main(int argc, char *argv[])  
  11. {  
  12.     if (argc != 2) {  
  13.         cerr<< "Please give the file name."<<endl;  
  14.         return -1;  
  15.     }  
  16.     ifstream in(argv[1]);  
  17.     if (!in) {  
  18.         cerr<<"Can't open the file."<<endl;  
  19.         return -1;  
  20.     }  
  21.   
  22.     Sales_data total;  
  23.     if (read(in, total)) {  
  24.         Sales_data trans;  
  25.         while(read(in ,trans)) {  
  26.             if(total.isbn() == trans.isbn())  
  27.                 total.combine(trans);  
  28.             else {  
  29.                 print(cout, total) << endl;  
  30.                 total =trans;  
  31.             }  
  32.         }  
  33.         print(cout, total)<<endl;  
  34.     }  
  35.     else {  
  36.         cerr<<" No data?!"<<endl;  
  37.     }  
  38.     return 0;  
  39. }  

练习8.7:修改上一节的书店程序,将结果保存到一个文件中。将输出文件名作为第二个参数传递给main函数。

 

  1. #include <iostream>  
  2. #include <fstream>  
  3. #include "Sales_data.h"  
  4.   
  5. using std::cerr;  
  6. using std::ifstream;  
  7. using std::ofstream;  
  8. using std::endl;  
  9.   
  10. int main(int argc, char *argv[])  
  11. {  
  12.     if (argc != 3) {  
  13.         cerr<< "Please give the input file name and out file name."<<endl;  
  14.         return -1;  
  15.     }  
  16.     ifstream in(argv[1]);  
  17.     if (!in) {  
  18.         cerr<<"Can't open the file."<<endl;  
  19.         return -1;  
  20.     }  
  21.     ofstream out(argv[2]);  
  22.     if (!out) {  
  23.         cerr<<"can't open output file."<<endl;  
  24.         return -1;  
  25.     }  
  26.   
  27.     Sales_data total;  
  28.     if (read(in, total)) {  
  29.         Sales_data trans;  
  30.         while(read(in ,trans)) {  
  31.             if(total.isbn() == trans.isbn())  
  32.                 total.combine(trans);  
  33.             else {  
  34.                 print(out, total) << endl;  
  35.                 total =trans;  
  36.             }  
  37.         }  
  38.         print(out, total)<<endl;  
  39.     }  
  40.     else {  
  41.         cerr<<" No data?!"<<endl;  
  42.     }  
  43.     return 0;  
  44. }  


练习8.8:修改上一题的程序,将结果追加到给定的文件末尾。对同一个输出文件,运行程序至少两次,检验数据是否得以保留。

 

  1. #include <iostream>  
  2. #include <fstream>  
  3. #include "Sales_data.h"  
  4.   
  5. using std::cerr;  
  6. using std::ifstream;  
  7. using std::ofstream;  
  8. using std::endl;  
  9.   
  10. int main(int argc, char *argv[])  
  11. {  
  12.     if (argc != 3) {  
  13.         cerr<< "Please give the input file name and out file name."<<endl;  
  14.         return -1;  
  15.     }  
  16.     ifstream in(argv[1]);  
  17.     if (!in) {  
  18.         cerr<<"Can't open the file."<<endl;  
  19.         return -1;  
  20.     }  
  21.     ofstream out(argv[2], ofstream::app);  
  22.     if (!out) {  
  23.         cerr<<"can't open output file."<<endl;  
  24.         return -1;  
  25.     }  
  26.   
  27.     Sales_data total;  
  28.     if (read(in, total)) {  
  29.         Sales_data trans;  
  30.         while(read(in ,trans)) {  
  31.             if(total.isbn() == trans.isbn())  
  32.                 total.combine(trans);  
  33.             else {  
  34.                 print(out, total) << endl;  
  35.                 total =trans;  
  36.             }  
  37.         }  
  38.         print(out, total)<<endl;  
  39.     }  
  40.     else {  
  41.         cerr<<" No data?!"<<endl;  
  42.     }  
  43.     return 0;  
  44. }  

练习8.3.1:使用你为8.1.2节第一个练习所编写的函数打印一个istringstream对象的内容。

 

  1. #include <iostream>  
  2. #include <sstream>  
  3. #include <string>  
  4. #include <stdexcept>  
  5.   
  6. using std::istream;  
  7. using std::ostringstream;  
  8. using std::istringstream;  
  9. using std::string;  
  10. using std::cout;  
  11. using std::cerr;  
  12. using std::endl;  
  13. using std::runtime_error;  
  14.   
  15. istream &f(istream &in)  
  16. {  
  17.     int v;  
  18.     while(in >> v, !in.eof())  
  19.     {  
  20.         if(in.bad())  
  21.             throw runtime_error("IO Stream error.");  
  22.         if(in.fail())  
  23.         {  
  24.             cerr<<"Data error! Please try again."<<endl;  
  25.             in.clear();  
  26.             in.ignore(100, '\n');  
  27.             continue;  
  28.         }  
  29.         cout<< v <<endl;  
  30.     }  
  31.     in.clear();  
  32.     return in;  
  33. }  
  34.   
  35. int main()  
  36. {  
  37.     ostringstream msg;  
  38.     msg<<"C++ Primer 5th edition"<<endl;  
  39.     istringstream in(msg.str());  
  40.     f(in);  
  41.     return 0;  
  42. }  

练习8.10:编写程序,将来自一个文件中的行保存在一个vector<string>中。然后使用一个istringstream从vector读取数据元素,每次读取一个单词。
  1. #include <iostream>  
  2. #include <fstream>  
  3. #include <sstream>  
  4. #include <string>  
  5. #include <vector>  
  6.   
  7. using std::cerr;  
  8. using std::endl;  
  9. using std::cout;  
  10. using std::ifstream;  
  11. using std::istringstream;  
  12. using std::string;  
  13. using std::vector;  
  14.   
  15. int main()  
  16. {  
  17.     ifstream in("Data.txt");  
  18.     if (!in) {  
  19.         cerr<<" Can't open input file."<<endl;  
  20.         return -1;  
  21.     }  
  22.   
  23.     string line;  
  24.     vector<string> words;  
  25.     while (getline(in, line)) {  
  26.         words.push_back(line);  
  27.     }  
  28.     in.close();  
  29.   
  30.     vector<string>::const_iterator it = words.begin();  
  31.     while( it != words.end()) {  
  32.         istringstream line_str(*it);  
  33.         string word;  
  34.         while(line_str >> word)  
  35.             cout<< endl;  
  36.         ++it;  
  37.     }  
  38.   
  39.     return 0;  
  40. }  

练习8.11:本节的程序在外层while循环中定义了istringstream对象。如果record对象定义在循环之外,你需要对程序进行怎么样的修改?重写程序,将record的定义移到while循环之外,验证你设想的修改方法是否正确。

 

  1. #include <iostream>  
  2. #include <sstream>  
  3. #include <string>  
  4. #include <vector>  
  5.   
  6. using std::cin;  
  7. using std::istringstream;  
  8. using std::string;  
  9. using std::vector;  
  10.   
  11. struct PersonInfo {  
  12.     string name;  
  13.     vector<string> phones;  
  14. };  
  15.   
  16. int main()  
  17. {  
  18.     string line, word;  
  19.     vector<PersonInfo> people;  
  20.     istringstream record;  
  21.   
  22.     while (getline(cin,line)) {  
  23.         PersonInfo info;  
  24.         record.clear();  
  25.         record.str(line);  
  26.         record >> info.name;  
  27.         while (record >> word)  
  28.             info.phones.push_back(word);  
  29.   
  30.     people.push_back(info);  
  31.     }  
  32.   
  33.     return 0;  
  34. }  

练习8.12:我们为什么没有在PersonInfo中使用类内初始化?

由于每个人的电话号数量不固定,因此更好的方式不是通过类内初始化指定人名和所有电话号码,而是在缺省初始化之后,在程序中设置人名并逐个添加电话号码。


练习8.13:重写本节的电话号码程序,从一个命名文件而非cin读取数据。

 

  1. #include <iostream>  
  2. #include <fstream>  
  3. #include <sstream>  
  4. #include <string>  
  5. #include <vector>  
  6.   
  7. using std::cerr;  
  8. using std::endl;  
  9. using std::cout;  
  10. using std::ifstream;  
  11. using std::istringstream;  
  12. using std::ostringstream;  
  13. using std::string;  
  14. using std::vector;  
  15.   
  16. struct PersonInfo {  
  17.     string name;  
  18.     vector<string> phones;  
  19. };  
  20.   
  21. string format(const string &s) { return s; }  
  22.   
  23. bool valid(const string &s)  
  24. {  
  25.     return true;  
  26. }  
  27.   
  28. int main(int argc, char *argv[])  
  29. {  
  30.     string line, word;  
  31.     vector<PersonInfo> people;  
  32.     istringstream record;  
  33.   
  34.     if (argc != 2) {  
  35.         cerr<<"Please give the file name."<<endl;  
  36.         return -1;  
  37.     }  
  38.     ifstream in(argv[1]);  
  39.     if(!in)  
  40.     {  
  41.         cerr<<"can't open input file"<<endl;  
  42.         return -1;  
  43.     }  
  44.   
  45.     while (getline(in, line)) {  
  46.         PersonInfo info;  
  47.         record.clear();  
  48.         record.str(line);  
  49.         record >> info.name;  
  50.         while(record >> word)  
  51.             info.phones.push_back(word);  
  52.   
  53.         people.push_back(info);  
  54.   
  55.     }  
  56.   
  57.     ostringstream os;  
  58.     for (const auto &entry : people) {  
  59.         ostringstream formatted, badNums;  
  60.         for(const auto &nums : entry.phones) {  
  61.             if (!valid(nums)) {  
  62.                 badNums << " "<< nums;  
  63.             }  
  64.             else  
  65.                 formatted << " " <<format(nums);  
  66.         }  
  67.         if (badNums.str().empty())  
  68.             os <<entry.name<<" "<<formatted.str()<<endl;  
  69.         else  
  70.             cerr<<"input error: "<<entry.name<<" invalid number(s) "<<badNums.str()<<endl;  
  71.     }  
  72.     cout<<os.str()<<endl;  
  73.   
  74.     return 0;  
  75. }  

练习8.14:我们为什么将entry和nums定义为const auto&?

这两条语句分别适用范围for语句枚举people中所有项和每项的phones中的所有项。使用const表明在循环中不会改变这些项的值;auto是请求编译器依据vector元素类型来推断出entry和nums的类型,既简化代码又避免出错;使用引用的原因是,people和phones的元素分别是结构对象和字符串对象,使用引用即可避免对象拷贝。

 
 

练习8.1:编写函数。接受一个istream&参数,返回值类型也是istream&。此函数必须从给定流中读取数据,直至遇到文件结束标识时停止。

 

  1. #include <iostream>  
  2. #include <stdexcept>  
  3.   
  4. using std::istream;  
  5. using std::cin;  
  6. using std::cout;  
  7. using std::cerr;  
  8. using std::endl;  
  9. using std::runtime_error;  
  10.   
  11. istream &f(istream &in)  
  12. {  
  13.     int v;  
  14.     while(in >> v, !in.eof())  
  15.     {  
  16.         if(in.bad())  
  17.             throw runtime_error("IO Stream error.");  
  18.         if(in.fail())  
  19.         {  
  20.             cerr<<"Data error! Please try again."<<endl;  
  21.             in.clear();  
  22.             in.ignore(100, '\n');  
  23.             continue;  
  24.         }  
  25.         cout<< v <<endl;  
  26.     }  
  27.     in.clear();  
  28.     return in;  
  29. }  
  30.   
  31. int main()  
  32. {  
  33.     cout<<"Please input some numbers, enter Ctrl+Z to end"<<endl;  
  34.     f(cin);  
  35.     return 0;  
  36. }  

练习8.3:什么情况下,下面的while循环会终止?

while (cin >> i) /*. . .*/

遇到文件结束符,或者遇到了IO流错误或者读入了无效数据。


练习8.4:编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个独立的元素存于vector中。

 

  1. #include <iostream>  
  2. #include <string>  
  3. #include <fstream>  
  4. #include <vector>  
  5. using std::cout;  
  6. using std::endl;  
  7. using std::string;  
  8. using std::ifstream;  
  9. using std::cerr;  
  10. using std::vector;  
  11.   
  12. int main()  
  13. {  
  14.     ifstream in("data.txt");  
  15.     if(!in) {  
  16.         cerr<<"Can't open the file."<<endl;  
  17.         return -1;  
  18.     }  
  19.   
  20.     string line;  
  21.     vector<string> words;  
  22.     while(getline(in, line))  
  23.         words.push_back(line);  
  24.   
  25.     in.close();  
  26.   
  27.     vector<string>::const_iterator it = words.cbegin();  
  28.     while (it != words.cend())  
  29.     {  
  30.         cout<< *it <<endl;  
  31.         ++it;  
  32.     }  
  33.     return 0;  
  34. }  

练习8.5:重写上面的程序,将每个单词作为一个独立的元素进行存储。

 

  1. #include <iostream>  
  2. #include <string>  
  3. #include <fstream>  
  4. #include <vector>  
  5. using std::cout;  
  6. using std::endl;  
  7. using std::string;  
  8. using std::ifstream;  
  9. using std::cerr;  
  10. using std::vector;  
  11.   
  12. int main()  
  13. {  
  14.     ifstream in("data.txt");  
  15.     if(!in) {  
  16.         cerr<<"Can't open the file."<<endl;  
  17.         return -1;  
  18.     }  
  19.   
  20.     string line;  
  21.     vector<string> words;  
  22.     while(in >> line)  
  23.         words.push_back(line);  
  24.   
  25.     in.close();  
  26.   
  27.     vector<string>::const_iterator it = words.cbegin();  
  28.     while (it != words.cend())  
  29.     {  
  30.         cout<< *it <<endl;  
  31.         ++it;  
  32.     }  
  33.     return 0;  
  34. }  

练习8.6:重写7.1.1节的书店程序,从一个文件中读取交易记录。将文件名作为一个参数传递给main。

 

  1. #include <iostream>  
  2. #include <fstream>  
  3. #include "Sales_data.h"  
  4.   
  5. using std::cout;  
  6. using std::cerr;  
  7. using std::ifstream;  
  8. using std::endl;  
  9.   
  10. int main(int argc, char *argv[])  
  11. {  
  12.     if (argc != 2) {  
  13.         cerr<< "Please give the file name."<<endl;  
  14.         return -1;  
  15.     }  
  16.     ifstream in(argv[1]);  
  17.     if (!in) {  
  18.         cerr<<"Can't open the file."<<endl;  
  19.         return -1;  
  20.     }  
  21.   
  22.     Sales_data total;  
  23.     if (read(in, total)) {  
  24.         Sales_data trans;  
  25.         while(read(in ,trans)) {  
  26.             if(total.isbn() == trans.isbn())  
  27.                 total.combine(trans);  
  28.             else {  
  29.                 print(cout, total) << endl;  
  30.                 total =trans;  
  31.             }  
  32.         }  
  33.         print(cout, total)<<endl;  
  34.     }  
  35.     else {  
  36.         cerr<<" No data?!"<<endl;  
  37.     }  
  38.     return 0;  
  39. }  

练习8.7:修改上一节的书店程序,将结果保存到一个文件中。将输出文件名作为第二个参数传递给main函数。

 

  1. #include <iostream>  
  2. #include <fstream>  
  3. #include "Sales_data.h"  
  4.   
  5. using std::cerr;  
  6. using std::ifstream;  
  7. using std::ofstream;  
  8. using std::endl;  
  9.   
  10. int main(int argc, char *argv[])  
  11. {  
  12.     if (argc != 3) {  
  13.         cerr<< "Please give the input file name and out file name."<<endl;  
  14.         return -1;  
  15.     }  
  16.     ifstream in(argv[1]);  
  17.     if (!in) {  
  18.         cerr<<"Can't open the file."<<endl;  
  19.         return -1;  
  20.     }  
  21.     ofstream out(argv[2]);  
  22.     if (!out) {  
  23.         cerr<<"can't open output file."<<endl;  
  24.         return -1;  
  25.     }  
  26.   
  27.     Sales_data total;  
  28.     if (read(in, total)) {  
  29.         Sales_data trans;  
  30.         while(read(in ,trans)) {  
  31.             if(total.isbn() == trans.isbn())  
  32.                 total.combine(trans);  
  33.             else {  
  34.                 print(out, total) << endl;  
  35.                 total =trans;  
  36.             }  
  37.         }  
  38.         print(out, total)<<endl;  
  39.     }  
  40.     else {  
  41.         cerr<<" No data?!"<<endl;  
  42.     }  
  43.     return 0;  
  44. }  


练习8.8:修改上一题的程序,将结果追加到给定的文件末尾。对同一个输出文件,运行程序至少两次,检验数据是否得以保留。

 

  1. #include <iostream>  
  2. #include <fstream>  
  3. #include "Sales_data.h"  
  4.   
  5. using std::cerr;  
  6. using std::ifstream;  
  7. using std::ofstream;  
  8. using std::endl;  
  9.   
  10. int main(int argc, char *argv[])  
  11. {  
  12.     if (argc != 3) {  
  13.         cerr<< "Please give the input file name and out file name."<<endl;  
  14.         return -1;  
  15.     }  
  16.     ifstream in(argv[1]);  
  17.     if (!in) {  
  18.         cerr<<"Can't open the file."<<endl;  
  19.         return -1;  
  20.     }  
  21.     ofstream out(argv[2], ofstream::app);  
  22.     if (!out) {  
  23.         cerr<<"can't open output file."<<endl;  
  24.         return -1;  
  25.     }  
  26.   
  27.     Sales_data total;  
  28.     if (read(in, total)) {  
  29.         Sales_data trans;  
  30.         while(read(in ,trans)) {  
  31.             if(total.isbn() == trans.isbn())  
  32.                 total.combine(trans);  
  33.             else {  
  34.                 print(out, total) << endl;  
  35.                 total =trans;  
  36.             }  
  37.         }  
  38.         print(out, total)<<endl;  
  39.     }  
  40.     else {  
  41.         cerr<<" No data?!"<<endl;  
  42.     }  
  43.     return 0;  
  44. }  

练习8.3.1:使用你为8.1.2节第一个练习所编写的函数打印一个istringstream对象的内容。

 

  1. #include <iostream>  
  2. #include <sstream>  
  3. #include <string>  
  4. #include <stdexcept>  
  5.   
  6. using std::istream;  
  7. using std::ostringstream;  
  8. using std::istringstream;  
  9. using std::string;  
  10. using std::cout;  
  11. using std::cerr;  
  12. using std::endl;  
  13. using std::runtime_error;  
  14.   
  15. istream &f(istream &in)  
  16. {  
  17.     int v;  
  18.     while(in >> v, !in.eof())  
  19.     {  
  20.         if(in.bad())  
  21.             throw runtime_error("IO Stream error.");  
  22.         if(in.fail())  
  23.         {  
  24.             cerr<<"Data error! Please try again."<<endl;  
  25.             in.clear();  
  26.             in.ignore(100, '\n');  
  27.             continue;  
  28.         }  
  29.         cout<< v <<endl;  
  30.     }  
  31.     in.clear();  
  32.     return in;  
  33. }  
  34.   
  35. int main()  
  36. {  
  37.     ostringstream msg;  
  38.     msg<<"C++ Primer 5th edition"<<endl;  
  39.     istringstream in(msg.str());  
  40.     f(in);  
  41.     return 0;  
  42. }  

练习8.10:编写程序,将来自一个文件中的行保存在一个vector<string>中。然后使用一个istringstream从vector读取数据元素,每次读取一个单词。
  1. #include <iostream>  
  2. #include <fstream>  
  3. #include <sstream>  
  4. #include <string>  
  5. #include <vector>  
  6.   
  7. using std::cerr;  
  8. using std::endl;  
  9. using std::cout;  
  10. using std::ifstream;  
  11. using std::istringstream;  
  12. using std::string;  
  13. using std::vector;  
  14.   
  15. int main()  
  16. {  
  17.     ifstream in("Data.txt");  
  18.     if (!in) {  
  19.         cerr<<" Can't open input file."<<endl;  
  20.         return -1;  
  21.     }  
  22.   
  23.     string line;  
  24.     vector<string> words;  
  25.     while (getline(in, line)) {  
  26.         words.push_back(line);  
  27.     }  
  28.     in.close();  
  29.   
  30.     vector<string>::const_iterator it = words.begin();  
  31.     while( it != words.end()) {  
  32.         istringstream line_str(*it);  
  33.         string word;  
  34.         while(line_str >> word)  
  35.             cout<< endl;  
  36.         ++it;  
  37.     }  
  38.   
  39.     return 0;  
  40. }  

练习8.11:本节的程序在外层while循环中定义了istringstream对象。如果record对象定义在循环之外,你需要对程序进行怎么样的修改?重写程序,将record的定义移到while循环之外,验证你设想的修改方法是否正确。

 

  1. #include <iostream>  
  2. #include <sstream>  
  3. #include <string>  
  4. #include <vector>  
  5.   
  6. using std::cin;  
  7. using std::istringstream;  
  8. using std::string;  
  9. using std::vector;  
  10.   
  11. struct PersonInfo {  
  12.     string name;  
  13.     vector<string> phones;  
  14. };  
  15.   
  16. int main()  
  17. {  
  18.     string line, word;  
  19.     vector<PersonInfo> people;  
  20.     istringstream record;  
  21.   
  22.     while (getline(cin,line)) {  
  23.         PersonInfo info;  
  24.         record.clear();  
  25.         record.str(line);  
  26.         record >> info.name;  
  27.         while (record >> word)  
  28.             info.phones.push_back(word);  
  29.   
  30.     people.push_back(info);  
  31.     }  
  32.   
  33.     return 0;  
  34. }  

练习8.12:我们为什么没有在PersonInfo中使用类内初始化?

由于每个人的电话号数量不固定,因此更好的方式不是通过类内初始化指定人名和所有电话号码,而是在缺省初始化之后,在程序中设置人名并逐个添加电话号码。


练习8.13:重写本节的电话号码程序,从一个命名文件而非cin读取数据。

 

  1. #include <iostream>  
  2. #include <fstream>  
  3. #include <sstream>  
  4. #include <string>  
  5. #include <vector>  
  6.   
  7. using std::cerr;  
  8. using std::endl;  
  9. using std::cout;  
  10. using std::ifstream;  
  11. using std::istringstream;  
  12. using std::ostringstream;  
  13. using std::string;  
  14. using std::vector;  
  15.   
  16. struct PersonInfo {  
  17.     string name;  
  18.     vector<string> phones;  
  19. };  
  20.   
  21. string format(const string &s) { return s; }  
  22.   
  23. bool valid(const string &s)  
  24. {  
  25.     return true;  
  26. }  
  27.   
  28. int main(int argc, char *argv[])  
  29. {  
  30.     string line, word;  
  31.     vector<PersonInfo> people;  
  32.     istringstream record;  
  33.   
  34.     if (argc != 2) {  
  35.         cerr<<"Please give the file name."<<endl;  
  36.         return -1;  
  37.     }  
  38.     ifstream in(argv[1]);  
  39.     if(!in)  
  40.     {  
  41.         cerr<<"can't open input file"<<endl;  
  42.         return -1;  
  43.     }  
  44.   
  45.     while (getline(in, line)) {  
  46.         PersonInfo info;  
  47.         record.clear();  
  48.         record.str(line);  
  49.         record >> info.name;  
  50.         while(record >> word)  
  51.             info.phones.push_back(word);  
  52.   
  53.         people.push_back(info);  
  54.   
  55.     }  
  56.   
  57.     ostringstream os;  
  58.     for (const auto &entry : people) {  
  59.         ostringstream formatted, badNums;  
  60.         for(const auto &nums : entry.phones) {  
  61.             if (!valid(nums)) {  
  62.                 badNums << " "<< nums;  
  63.             }  
  64.             else  
  65.                 formatted << " " <<format(nums);  
  66.         }  
  67.         if (badNums.str().empty())  
  68.             os <<entry.name<<" "<<formatted.str()<<endl;  
  69.         else  
  70.             cerr<<"input error: "<<entry.name<<" invalid number(s) "<<badNums.str()<<endl;  
  71.     }  
  72.     cout<<os.str()<<endl;  
  73.   
  74.     return 0;  
  75. }  

练习8.14:我们为什么将entry和nums定义为const auto&?

这两条语句分别适用范围for语句枚举people中所有项和每项的phones中的所有项。使用const表明在循环中不会改变这些项的值;auto是请求编译器依据vector元素类型来推断出entry和nums的类型,既简化代码又避免出错;使用引用的原因是,people和phones的元素分别是结构对象和字符串对象,使用引用即可避免对象拷贝。

 
 

posted @ 2017-03-06 20:00  zqlucky  阅读(20748)  评论(0编辑  收藏  举报