C++ Primer 0x08 练习题解

📔 C++ Primer 0x08 练习题解

更好的阅读体验

推荐阅读 《C++ Primer 5th》知识点总结&练习题解

8.1 IO类

8.1.2 条件状态

8.1 编写函数,接受一个istream&参数,返回值类型也是istream&。此函数须从给定流中读取数据,直至遇到文件结束标识时停止。它将读取的数据打印在标准输出上。完成这些操作后,在返回流之前,对流进行复位,使其处于有效状态。

8.2 测试函数,调用参数为cin

#include <iostream>

std::istream& fun(std::istream& is){
	std::string buf;
	while(is >> buf){
		std::cout << buf << std::endl;	
	}
	is.clear();
	return is;
}

int main(){
	std::istream& is = fun(std::cin);
	std::cout << is.rdstate() << std::endl;
	return 0;
}

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

while (cin >> i) /*  ...    */
  • 如果badbitfailbiteofbit任一被置位,检测流状态的条件就会失败

8.2 文件输入输出

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

void read(const std::string& ifile,std::vector<std::string>& vec){
	std::ifstream input(ifile);
	if(input){
		std::string buf;
		while(geline(input,buf)){
			vec.push_back(buf);
		}
	}	
}

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

void read(const std::string& ifile,std::vector<std::string>& vec){
	std::ifstream input(ifile);
	if(input){
		std::string buf;
		while(input >> buf){
			vec.push_back(buf);
		}
	}	
}

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

#include <iostream>
#include <string>
#include <fstream>

struct Sales_data {
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

int main(int argc,char **argv){
	std::ifstream input(argv[1]);
	
	Sales_data total,item;
    double price = 0;
    if(input){
    	if (input >> total.bookNo >> total.units_sold >> price){
        total.revenue = total.units_sold * price;
        while (input >> item.bookNo >> item.units_sold >> price){
            item.revenue = item.units_sold * price;
            if (total.bookNo == item.bookNo) {
                total.units_sold += item.units_sold;
                total.revenue += item.revenue;
            }else {
                std::cout << total.bookNo << " " 
                		<< total.units_sold << " "
                		<< total.revenue << std::endl;
                total = item;
            }
        }
        std::cout << total.bookNo << " " 
				<< total.units_sold << " "
				<< total.revenue << std::endl;
	    }else {
	        std::cerr << "No data?!" << std::endl;
	        return -1;
	    }
    }
    
	return 0;
}

8.2.2 文件模式

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

#include <iostream>
#include <string>
#include <fstream>

struct Sales_data {
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

int main(int argc,char **argv){
	std::ifstream input(argv[1]);
	std::ofstream output(argv[2]);
	Sales_data total,item;
    double price = 0;
    if(input){
    	if (input >> total.bookNo >> total.units_sold >> price){
        total.revenue = total.units_sold * price;
        while (input >> item.bookNo >> item.units_sold >> price){
            item.revenue = item.units_sold * price;
            if (total.bookNo == item.bookNo) {
                total.units_sold += item.units_sold;
                total.revenue += item.revenue;
            }else {
                output << total.bookNo << " " 
                		<< total.units_sold << " "
                		<< total.revenue << std::endl;
                total = item;
            }
        }
        output << total.bookNo << " " 
				<< total.units_sold << " "
				<< total.revenue << std::endl;
	    }else {
	        std::cerr << "No data?!" << std::endl;
	        return -1;
	    }
    }
    
	return 0;
}

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

#include <iostream>
#include <istream>
#include <string>
#include <fstream>

struct Sales_data {
        std::string bookNo;
        unsigned units_sold = 0;
        double revenue = 0.0;
};

int main(int argc,char **argv){
    std::ifstream input(argv[1]);
    std::ofstream output(argv[2],std::ofstream::app);
    Sales_data total,item;
    double price = 0;
    if(input){
        if (input >> total.bookNo >> total.units_sold >> price){
        total.revenue = total.units_sold * price;
        while (input >> item.bookNo >> item.units_sold >> price){
            item.revenue = item.units_sold * price;
            if (total.bookNo == item.bookNo) {
                total.units_sold += item.units_sold;
                total.revenue += item.revenue;
            }else {
                output  << total.bookNo << " " 
                                << total.units_sold << " "
                                << total.revenue << std::endl;
                total = item;
            }
        }
        output << total.bookNo << " " 
                                << total.units_sold << " "
                                << total.revenue << std::endl;
            }else {
                std::cerr << "No data?!" << std::endl;
                return -1;
            }
    }
    
    return 0;
}

8.8 string 流

8.3.1 使用 istringstream

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

#include <iostream>
#include <sstream>

std::istream& fun(std::istream& is){
	std::string buf;
	while(is >> buf){
		std::cout << buf << std::endl;	
	}
	is.clear();
	return is;
}

int main(){
	std::string line;
	getline(std::cin,line);
	std::istringstream record(line);
	std::istream& is = fun(record);
	std::cout << is.rdstate() << std::endl;
	return 0;
}

8.10 编写程序,将来自一个文件中的行保存在一个vector<string>中。然后使用一个istringstreamvector读取数据元素,每次读取一个单词。

#include <iostream>
#include <sstream>
#include <vector>

int main(){
	std::string line,word;
	std::vector<std::string>vec;
	while(getline(std::cin,line)){
		std::istringstream record(line);
		if(record){
			while(record >> word){
				vec.push_back(word);
			}
		}
		
	}
	for(auto v:vec)std::cout << v << std::endl;
	
	return 0;
}

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

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

struct PersonInfo {
    std::string name;
    std::vector<std::string> phones;
};

int main(){
    std::string line, word;
    std::vector<PersonInfo> people;
    std::istringstream record;
    while (getline(std::cin, line)){
        PersonInfo info;
        record.clear();record.str(line);
        record >> info.name;
        while (record >> word)
            info.phones.push_back(word);
        people.push_back(info);
    }
    
    for (auto &p : people){
        std::cout << p.name << " ";
        for (auto &s : p.phones)
            std::cout << s << " ";
        std::cout << std::endl;
    }
    
    return 0;
}

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

只需要聚合类即可,不需要类内初始化

8.3.2 使用 ostringstream

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

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>

struct PersonInfo {
    std::string name;
    std::vector<std::string> phones;
};

bool vaild(const std::string& str){
	return isdigit(str[0]);
}

std::string format(const std::string& str){
	return str.substr(0,3) + "-" + str.substr(3,3) + "-" + str.substr(6);
}
int main(int argc,char **argv){
	
	std::ifstream input(argv[1]);
    std::string line, word;
    std::vector<PersonInfo> people;
    std::istringstream record;
    
    while (getline(input, line)){
        PersonInfo info;
        record.clear();record.str(line);
        record >> info.name;
        while (record >> word)
            info.phones.push_back(word);
        people.push_back(info);
    }
    
    for(const auto &entry:people){
    	std::ostringstream formatted,badNums;
    	for(const auto &nums:entry.phones){
    		if(!vaild(nums)){
    			badNums << " " << nums;
    		}else{
    			formatted << " " << nums;
    		}
    	}
    	if(badNums.str().empty())
    		std::cout << entry.name << " " << formatted.str() << std::endl;
    	else
    		std::cerr << "input error: " << entry.name
    			<< "invaild number(s) " << badNums.str() << std::endl;
    }
    
    return 0;
}

8.14 我们为什么将entrynums定义为const auto&

不需要改变,所以用const

它们是类类型,使用引用可以避免拷贝:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值