C++ Primer 0x09 练习题解

📔 C++ Primer 0x09 练习题解

更好的阅读体验

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

9.1 顺序容器概述

9.1 对于下面的程序任务,vectordequelist哪种容器最为适合?解释你的选择的理由。如果没有哪一种容器优于其他容器,也请解释理由。

(a) 读取固定数量的单词,将它们按字典序插入到容器中。我们将在下一章中看到,关联容器更适合这个问题。

(b) 读取未知数量的单词,总是将单词插入到末尾。删除操作在头部进行。

© 从一个文件读取未知数量的整数。将这些数排序,然后将它们打印到标准输出。

  • (a)list插入位置任意,不一定在首尾
  • (b)deque插入删除操作在头尾
  • ©vector不需要插入删除,而且要排序

9.2 容器库概览

9.2 定义一个list对象,其元素类型是intdeque

std::list<std::deque<int>> ls;

9.2.1 迭代器

9.3 构成迭代器范围的迭代器有何限制?

  • 指向同一个容器中的元素或者是容器元素最后一个元素的位置

  • end 不在 begin之前

9.4 编写函数,接受一对指向vector<int>的迭代器和一个int值。在两个迭代器指定的范围中查找给定的值,返回一个布尔值来指出是否找到。

#include <vector>
#include <iostream>

using  Iter = std::vector<int>::iterator;

bool find(Iter beg, Iter end, int x){
	while(beg!=end){
		if((*beg)==x)return true;
		++beg;
	}
	return false;
}

int main(){
	std::vector<int>vec={1,2,3,4,5,6,7};
	if(find(vec.begin(),vec.end(),3)){
		std::cout << "yes" << std::endl;
	}else{
		std::cout << "no" << std::endl;
	}
	return 0;
}

9.5 重写上一题的函数,返回一个迭代器指向找到的元素。注意,程序必须处理未找到给定值的情况。

#include <vector>
#include <iostream>

using  Iter = std::vector<int>::iterator;

Iter find(Iter beg, Iter end, int x){
	while(beg!=end){
		if((*beg)==x)break;
		++beg;
	}
	return beg;
}

int main(){
	std::vector<int>vec={1,2,3,4,5,6,7};
	Iter ret = find(vec.begin(),vec.end(),3);
	if(ret == vec.end()){
		std::cout << "no" << std::endl;
	}else{
		std::cout << *ret << " " << ret-vec.begin() << std::endl;
	}
	return 0;
}

9.6 下面的程序有何错误?你应该如何修改它?

list<int> lst1;
list<int>::iterator iter1 = lst1.begin(),
					iter2 = lst1.end();
while (iter1 < iter2) /* ... */

vectordeque 不同,list 的迭代器不支持 < 运算,只支持递增、递减、= 以及 != 运算。

while(iter1 != iter2)

9.2.2 容器类成员

9.7 为了索引intvector中的元素,应该使用什么类型?

std::vector<int>::size_type

9.8 为了读取stringlist中的元素,应该使用什么类型?如果写入list,又应该使用什么类型?

std::list<string>::const_iterator

std::list<string>::iterator

9.2.3 begin 和 end 成员

9.9 begincbegin两个函数有什么不同?

begin返回普通迭代器

cbegin返回常量迭代器

9.10 下面4个对象分别是什么类型?

vector<int> v1;
const vector<int> v2;
auto it1 = v1.begin(), it2 = v2.begin();
auto it3 = v1.cbegin(), it4 = v2.cbegin();
  • it1和it2vector<int>::iterator
  • it3和it4vector<int>::const_iterator

9.2.4 容器定义和初始化

9.11 对6种创建和初始化vector对象的方法,每一种都给出一个实例。解释每个vector包含什么值。

vector<int> vec1;//空
vector<int> vec2(10);//10个0
vector<int> vec3(10,1);//10个1
vector<int> vec4{1,2,3,4,5,6,7,8,9,10};//1~10
vector<int> vec5(vec4);//1~10
vector<int> vec6(vec5.begin(),vec5.end());//1~10

9.12 对于接受一个容器创建其拷贝的构造函数,和接受两个迭代器创建拷贝的构造函数,解释它们的不同。

  • 将一个容器创建为另一个容器的拷贝方法有两种

    • 直接拷贝整个容器,两个容器的类型和元素类型必须匹配
    • 拷贝由一个迭代器对指定的元素范围(array除外),不要求容器类型相同,元素类型也可以不同,只要能将拷贝的元素转换

9.13 如何从一个list<int>初始化一个vector<double>?从一个vector<int>又该如何创建?编写代码验证你的答案。

#include <vector>
#include <iostream>
#include <list>
using namespace std;

int main(){
	list<int>ls{1,2,3,4};
	vector<int>vec{5,6,7,8};
	
	vector<double>dvec1(ls.begin(),ls.end());
	vector<double>dvec2(vec.begin(),vec.end());
	
	for(auto v:dvec1)cout << v << " ";
	cout << endl;
	
	for(auto v:dvec2)cout << v << " ";
	cout << endl;
	return 0;
}

9.2.5 赋值和 swap

9.14 编写程序,将一个list中的char *指针元素赋值给一个vector中的string

list<char*>ls{"abc","def","ghi"};
vector<string>vec;
vec.assign(ls.cbegin(),ls.cend());

9.2.7 关系运算符

9.15 编写程序,判定两个vector<int>是否相等。

#include <vector>
#include <iostream>
#include <list>
using namespace std;

int main(){
	vector<int>vec1{1,2,3,4,5};
	vector<int>vec2{1,2,3,4,5};
	vector<int>vec3{1,2,3,5,4};
	
	cout << (vec1==vec2?"yes":"no") << endl;
	cout << (vec1==vec3?"yes":"no") << endl;
	return 0;
}

9.16 重写上一题的程序,比较一个list中的元素和一个vector中的元素。

#include <vector>
#include <iostream>
#include <list>
using namespace std;

int main(){
	vector<int>vec1{1,2,3,4,5};
	list<int>ls1{1,2,3,4,5};
	list<int>ls2{1,2,3,5,4};
	
	cout << (vec1==vector<int>(ls1.begin(),ls1.end())?"yes":"no") << endl;
	cout << (vec1==vector<int>(ls2.begin(),ls2.end())?"yes":"no") << endl;
	return 0;
}

9.17 假定c1c2是两个容器,下面的比较操作有何限制?(如果有的话)

if (c1 < c2)
  • 只有当其中元素类型也定义了相应的比较运算符时,我们才可以使用关系运算符来比较两个容器
  • 关系运算符两侧运算对象必须是类型相同的容器且必须保存相同类型的元素

9.3 顺序容器操作

9.3.1 向顺序容器添加元素

9.18 编写程序,从标准输入读取string序列,存入一个deque中。编写一个循环,用迭代器打印deque中的元素。

#include <iostream>
#include <string>
#include <deque>
using namespace std;

int main(){
	deque<string>dq;
	string s;
	while(cin>>s)dq.push_back(s);
	for(auto iter=dq.cbegin();iter!=dq.cend();++iter){
		cout << *iter << " ";
	}
	return 0;
}

9.19 重写上一题的程序,用list替代deque。列出程序要做出哪些改变。

#include <iostream>
#include <list>
#include <string>
using namespace std;

int main(){
	list<string>ls;
	string s;
	while(cin>>s)ls.push_back(s);
	for(auto iter=ls.cbegin();iter!=ls.cend();++iter){
		cout << *iter << " ";
	}
	return 0;
}

9.20 编写程序,从一个list<int>拷贝元素到两个deque中。值为偶数的所有元素都拷贝到一个deque中,而奇数值元素都拷贝到另一个deque中。

#include <iostream>
#include <list>
#include <deque>
using namespace std;

int main(){
	list<int>ls={1,2,3,4,5,6,7,8};
	deque<int>odd,even;
	for(auto e:ls){
		if(e&1)odd.push_back(e);
		else even.push_back(e);
	}
	
	for(auto e:odd)cout << e << " ";
	cout << endl;
	for(auto e:even)cout << e << " ";
	
	return 0;
}

9.21 如果我们将第308页中使用insert返回值将元素添加到list中的循环程序改写为将元素插入到vector中,分析循环将如何工作。

没啥区别

insert返回值指向插入的新元素,可以借助insert实现push_front相同的功能

9.22 假定iv是一个intvector,下面的程序存在什么错误?你将如何修改?

vector<int>::iterator iter = iv.begin(),
					  mid = iv.begin() + iv.size() / 2;
while (iter != mid)
	if (*iter == some_val)
		iv.insert(iter, 2 * some_val);
  • 循环里迭代器没变,死循环
  • 循环里插入操作,迭代器没有更新,迭代器会失效

几个要点

插入后mid会失效,要更新,保证还是初始中点终止

插入元素后要多移动一步

迭代器也会失效,要更新

#include <iostream>
#include <list>
#include <vector>
using namespace std;

int main(){
	vector<int>iv={5,4,4,4,3,1};
	int some_value = 4;
	int move = 0;
	vector<int>::iterator iter = iv.begin();
	int siz=iv.size();
	while(iter != (iv.begin() + siz/2+move)){
		if(*iter == some_value){
			iter = iv.insert(iter,some_value*2);
			move++;
			iter++;iter++;
		}
		else ++iter;
	}
	for(auto v:iv)cout << v << " ";
		
	return 0;
}

9.3.2 访问元素

9.23 在本节第一个程序中,若c.size() 为1,则valval2val3val4的值会是什么?

都是容器里唯一的那个元素的值

9.24 编写程序,分别使用at、下标运算符、frontbegin 提取一个vector中的第一个元素。在一个空vector上测试你的程序。

#include <iostream>
#include <vector>

int main(){
    std::vector<int> vec;
    
    std::cout << vec.at(0);
    //terminate called after throwing an instance of 'std::out_of_range       
    std::cout << vec[0];//段错误        
    std::cout << vec.front();//段错误    
    std::cout << *vec.begin();//段错误  
      
    return 0;
}

9.3.3 删除元素

9.25 对于第312页中删除一个范围内的元素的程序,如果 elem1elem2 相等会发生什么?如果 elem2 是尾后迭代器,或者 elem1elem2 皆为尾后迭代器,又会发生什么?

  • 如果 elem1elem2 相等,迭代器范围为空,什么都不做
  • 如果 elem2 是尾后迭代器,从elem1开始删到末尾
  • elem1elem2 皆为尾后迭代器,什么都不做

9.26 使用下面代码定义的ia,将ia拷贝到一个vector和一个list中。是用单迭代器版本的eraselist中删除奇数元素,从vector中删除偶数元素。

int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };
#include <iostream>
#include <vector>
#include <list>

int main(){
	int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };
    
    std::vector<int>vec;
    std::list<int>ls;
    
    for(auto i:ia)vec.push_back(i);
    for(auto i:ia)ls.push_back(i);

	auto it1=vec.begin();
	auto it2=ls.begin();
	
	while(it1!=vec.end()){
		if((1&(*it1))==0){
			it1=vec.erase(it1);
		}else{
			++it1;
		}
	}

	
	while(it2!=ls.end()){
		if(1&(*it2)){
			it2=ls.erase(it2);
		}else{
			++it2;
		}
	}
	

	for(auto i:vec)std::cout << i << " ";
	std::cout << std::endl;
	for(auto i:ls)std::cout << i << " ";
	
    return 0;
}

9.3.4 特殊的 forward_list 操作

9.27 编写程序,查找并删除forward_list<int>中的奇数元素。

#include <iostream>
#include <forward_list>

int main(){
	std::forward_list<int>flst{1,2,3,4,5};
	auto prev = flst.before_begin();
	auto curr = flst.begin();
	while(curr != flst.end()){
		if(*curr%2)
			curr = flst.erase_after(prev);
		else{
			prev = curr;
			++curr;
		}
	}
	for(auto i:flst)std::cout << i << " ";
    return 0;
}

9.28 编写函数,接受一个forward_list<string>和两个string共三个参数。函数应在链表中查找第一个string,并将第二个string插入到紧接着第一个string之后的位置。若第一个string未在链表中,则将第二个string插入到链表末尾。

#include <iostream>
#include <forward_list>

using std::string;
using FL = std::forward_list<string>;

void fun(FL& flst,string a,string b){
	auto prev = flst.before_begin();
	auto curr = flst.begin();	
	while(curr != flst.end()){
		if(*curr == a){
			flst.insert_after(curr,b);
			return;
		}
		prev = curr;
		++curr;
	}
	return;
}

int main(){
	FL flst={"abc","def","ghi"};
	fun(flst,"abc","ABC");
	for(auto i:flst)std::cout << i << " ";
    return 0;
}

9.3.5 改变容器大小

9.29 假定vec包含25个元素,那么vec.resize(100)会做什么?如果接下来调用vec.resize(10)会做什么?

vec.resize(100)末尾加75个0(如果是int)

vec.resize(10)删除末尾90个元素

9.30 接受单个参数的resize版本对元素类型有什么限制(如果有的话)?

元素类型必须有默认构造函数

9.3.6 容器操作可能使迭代器失效

9.31 第316页中删除偶数值元素并复制奇数值元素的程序不能用于listforward_list。为什么?修改程序,使之也能用于这些类型。

iter+=2;//复合赋值语句不能用于这两个
++iter;++iter;//改为这个

forward_list还需要借助增加一个prev来完成增删

9.32 在第316页的程序中,向下面语句这样调用insert是否合法?如果不合法,为什么?

iter = vi.insert(iter, *iter++);

不合法,参数求职顺序不确定

9.33 在本节最后一个例子中,如果不将insert的结果赋予begin,将会发生什么?编写程序,去掉此赋值语句,验证你的答案。

迭代器失效

9.34 假定vi是一个保存int的容器,其中有偶数值也有奇数值,分析下面循环的行为,然后编写程序验证你的分析是否正确。

iter = vi.begin();
while (iter != vi.end())
	if (*iter % 2)
		iter = vi.insert(iter, *iter);
	++iter;

不正确,死循环了

iter = vi.begin();
while (iter != vi.end())
	if (*iter % 2){
			iter = vi.insert(iter, *iter);
			++iter;++iter:
	}else{
		++iter;
	}

9.4 vector 对象是如何快速增长的

9.35 解释一个vectorcapacitysize有何区别。

capacity是在不分配新的内存空间的前提下最多可以保存多少元素,size是指已经保存的元素的数目

9.36 一个容器的capacity可能小于它的size吗?

不可能

9.37 为什么listarray没有capacity成员函数?

list链表没有数量限制

array大小固定了

9.38 编写程序,探究在你的标准实现中,vector是如何增长的。

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

using namespace std;

int main()
{
	vector<int> v;

	for (int i = 0; i < 100; i++)
	{
		cout << "capacity: " << v.capacity() << "  size: " << v.size() << endl;
		v.push_back(i);
	}
	return 0;
}

clang version 13.0.0

capacity: 0  size: 0
capacity: 1  size: 1
capacity: 2  size: 2
capacity: 4  size: 3
capacity: 4  size: 4
capacity: 8  size: 5
capacity: 8  size: 6
capacity: 8  size: 7
capacity: 8  size: 8
capacity: 16  size: 9
capacity: 16  size: 10
capacity: 16  size: 11
capacity: 16  size: 12
capacity: 16  size: 13
capacity: 16  size: 14
capacity: 16  size: 15
capacity: 16  size: 16
capacity: 32  size: 17
capacity: 32  size: 18
capacity: 32  size: 19
capacity: 32  size: 20
capacity: 32  size: 21
capacity: 32  size: 22
capacity: 32  size: 23
capacity: 32  size: 24
capacity: 32  size: 25
capacity: 32  size: 26
capacity: 32  size: 27
capacity: 32  size: 28
capacity: 32  size: 29
capacity: 32  size: 30
capacity: 32  size: 31
capacity: 32  size: 32
capacity: 64  size: 33
capacity: 64  size: 34
capacity: 64  size: 35
capacity: 64  size: 36
capacity: 64  size: 37
capacity: 64  size: 38
capacity: 64  size: 39
capacity: 64  size: 40
capacity: 64  size: 41
capacity: 64  size: 42
capacity: 64  size: 43
capacity: 64  size: 44
capacity: 64  size: 45
capacity: 64  size: 46
capacity: 64  size: 47
capacity: 64  size: 48
capacity: 64  size: 49
capacity: 64  size: 50
capacity: 64  size: 51
capacity: 64  size: 52
capacity: 64  size: 53
capacity: 64  size: 54
capacity: 64  size: 55
capacity: 64  size: 56
capacity: 64  size: 57
capacity: 64  size: 58
capacity: 64  size: 59
capacity: 64  size: 60
capacity: 64  size: 61
capacity: 64  size: 62
capacity: 64  size: 63
capacity: 64  size: 64
capacity: 128  size: 65
capacity: 128  size: 66
capacity: 128  size: 67
capacity: 128  size: 68
capacity: 128  size: 69
capacity: 128  size: 70
capacity: 128  size: 71
capacity: 128  size: 72
capacity: 128  size: 73
capacity: 128  size: 74
capacity: 128  size: 75
capacity: 128  size: 76
capacity: 128  size: 77
capacity: 128  size: 78
capacity: 128  size: 79
capacity: 128  size: 80
capacity: 128  size: 81
capacity: 128  size: 82
capacity: 128  size: 83
capacity: 128  size: 84
capacity: 128  size: 85
capacity: 128  size: 86
capacity: 128  size: 87
capacity: 128  size: 88
capacity: 128  size: 89
capacity: 128  size: 90
capacity: 128  size: 91
capacity: 128  size: 92
capacity: 128  size: 93
capacity: 128  size: 94
capacity: 128  size: 95
capacity: 128  size: 96
capacity: 128  size: 97
capacity: 128  size: 98
capacity: 128  size: 99

9.39 解释下面程序片段做了什么:

vector<string> svec;
svec.reserve(1024);//预先分配1024个元素空间
string word;
while (cin >> word)
	svec.push_back(word);
svec.resize(svec.size() + svec.size() / 2);//元素数量变为原来1.5倍
//如果元素数量变 1.5 倍后超过1024则重新分配空间

9.40 如果上一题的程序读入了256个词,在resize之后容器的capacity可能是多少?如果读入了512个、1000个、或1048个呢?

  • 256:capacity=1024
  • 512:capacity=1024
  • 1000,1048:如果两倍增长,那么capacity=2048

9.5 额外的 string 操作

9.5.1 构造 string 的其他方法

9.41 编写程序,从一个vector<char>初始化一个string

vector<char>vec={'a','b','c'};
string s(vec.begin(),vec.end());

9.42 假定你希望每次读取一个字符存入一个string中,而且知道最少需要读取100个字符,应该如何提高程序的性能?

使用 reserve(100) 函数预先分配100个元素的空间。

9.5.2 改变 string 的其他方法

9.43 编写一个函数,接受三个string参数是soldValnewVal。使用迭代器及inserterase函数将s中所有oldVal替换为newVal。测试你的程序,用它替换通用的简写形式,如,将"tho"替换为"though",将"thru"替换为"through"。

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

using namespace std;

void fun(string &s,const string &oldVal,const string &newVal){
	for(auto it = s.begin(); it != s.end();){
		if(oldVal == s.substr(it-s.begin(),oldVal.size())){
			it = s.erase(it,it+oldVal.size());
			it = s.insert(it,newVal.begin(),newVal.end());
			it += newVal.size();
		}else{
			++it;
		}
	}	
}

int main(){
	string s{"123456789"};
	fun(s,"123","567");
	fun(s,"abc","def");
	cout << s << endl;
	return 0;
}

9.44 重写上一题的函数,这次使用一个下标和replace

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

using namespace std;

void fun(string &s,const string &oldVal,const string &newVal){
	for(size_t pos = 0; pos+oldVal.size() <= s.size(); ++pos){
		if(s.substr(pos,oldVal.size())==oldVal){
			s.replace(pos,oldVal.size(),newVal);
			pos += newVal.size();
		}else{
			++pos;
		}
	}
}

int main(){
	string s{"123456789"};
	fun(s,"123","567");
	fun(s,"abc","def");
	cout << s << endl;
	return 0;
}

9.45 编写一个函数,接受一个表示名字的string参数和两个分别表示前缀(如"Mr.“或"Mrs.”)和后缀(如"Jr.“或"III”)的字符串。使用迭代器及insertappend函数将前缀和后缀添加到给定的名字中,将生成的新string返回。

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

using namespace std;

string fun(string& name,const string& pre,const string& suf){
	name.insert(name.begin(),pre.begin(),pre.end());
	name.append(suf);
	return name;
}

int main(){
	string name("Fishingrod");
	cout << fun(name,"Mr.",".zsl");
	return 0;
}

9.46 重写上一题的函数,这次使用位置和长度来管理string,并只使用insert

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

using namespace std;

string fun(string& name,const string& pre,const string& suf){
	name.insert(0,pre);
	name.insert(name.size(),suf);
	return name;
}

int main(){
	string name("Fishingrod");
	cout << fun(name,"Mr.",".zsl");
	return 0;
}

9.5.3 string 搜索操作

9.47 编写程序,首先查找string"ab2c3d7R4E6"中每个数字字符,然后查找其中每个字母字符。编写两个版本的程序,第一个要使用find_first_of,第二个要使用find_first_not_of

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

using namespace std;

int main(){
	string s("ab2c3d7R4E6");
	string num("0123456789");
	for(int i=0;s[i];){
		auto pos = s.substr(i).find_first_not_of(num);
		if(pos!=string::npos){
			cout << s[pos+i];
			i = pos+1+i;
		}else{
			++i;
		}
	}
	cout << endl;
	
	for(int i=0;s[i];){
		auto pos = s.substr(i).find_first_of(num);
		if(pos==string::npos){
			cout << s[i++];
		}else{
			cout <<s.substr(i,pos);
			i = pos+i+1; 
		}
	}
	return 0;
}

9.48 假定namenumbers的定义如325页所示,numbers.find(name)返回什么?

string::npos

9.49 如果一个字母延伸到中线之上,如d或f,则称其有上出头部分(ascender)。如果一个字母延伸到中线之下,如p或g,则称其有下出头部分(descender)。编写程序,读入一个单词文件,输出最长的既不包含上出头部分,也不包含下出头部分的单词。

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

std::string find(const std::string& s,std::string& longest){
	std::string str("aceimnorsuvwxz");
	if(s.find_first_not_of(str)==std::string::npos){
		return (s.size()>longest.size())?s:longest;
	}
	return longest;
}
int main(int argc,char **argv){
	std::ifstream ifs(argv[1]);
	if(ifs){
		std::string longest,s;
		while(ifs>>s){
			longest = find(s,longest);
		}
		std::cout << longest << std::endl;
	}
	return 0;
}

9.5.5 数值转换

9.50 编写程序处理一个vector<string>,其元素都表示整型值。计算vector中所有元素之和。修改程序,使之计算表示浮点值的string之和。

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

using std::vector;
using std::string;
using std::cout;
using std::cin;

int main(){
	vector<string>v;
	for(string s;cin>>s;v.push_back(s));
	int sum=0;
	for(auto i:v)sum+=std::stoi(i);
	cout << sum;
	return 0;
}
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

using std::vector;
using std::string;
using std::cout;
using std::cin;

int main(){
	vector<string>v;
	for(string s;cin>>s;v.push_back(s));
	double sum=0;
	for(auto i:v)sum+=std::stod(i);
	cout << sum;
	return 0;
}

9.51 设计一个类,它有三个unsigned成员,分别表示年、月和日。为其编写构造函数,接受一个表示日期的string参数。你的构造函数应该能处理不同的数据格式,如January 1,1900、1/1/1990、Jan 1 1900 等。

#include <iostream>
#include <string>

class Time{
private:
	unsigned year;
	unsigned month;
	unsigned day;

public:
	Time() = default;
	Time(std::string s){
		if(s.find_first_of("/")!=std::string::npos){//1/1/1990
			day = stoi(s.substr(0,s.find_first_of("/")));
			month = stoi(s.substr(s.find_first_of("/")+1,
				(s.find_last_of('/')-s.find_first_of('/'))));
			year = stoi(s.substr(s.find_last_of("/")+1,4));
		}else{
			if( s.find("Jan") < s.size() )  month = 1;
			if( s.find("Feb") < s.size() )  month = 2;
			if( s.find("Mar") < s.size() )  month = 3;
			if( s.find("Apr") < s.size() )  month = 4;
			if( s.find("May") < s.size() )  month = 5;
			if( s.find("Jun") < s.size() )  month = 6;
			if( s.find("Jul") < s.size() )  month = 7;
			if( s.find("Aug") < s.size() )  month = 8;
			if( s.find("Sep") < s.size() )  month = 9;
			if( s.find("Oct") < s.size() )  month =10;
			if( s.find("Nov") < s.size() )  month =11;
			if( s.find("Dec") < s.size() )  month =12;
			
			if(s.find_first_of(" ")!=std::string::npos
			&&s.find_first_of(" ")>3){//January 1,1900
				s[s.find(",")]=' ';
			}

			day = stoi(s.substr(s.find_first_of(" ")+1,
				(s.find_last_of(' ')-s.find_first_of(' '))));
			year = stoi(s.substr(s.find_last_of(" ")+1,4));
		}
	} 

public:
	void print(){
		std::cout << year << " " 
				<< month << " " 
				<< day << std::endl;
	}
};

int main(){
	Time t1("January  1,1900");
	Time t2("Jan 1 1900");
	Time t3("1/1/1900");
	
	t1.print();
	t2.print();
	t3.print();

	return 0;
}

9.6 容器适配器

9.52 使用stack处理括号化的表达式。当你看到一个左括号,将其记录下来。当你在一个左括号之后看到一个右括号,从stackpop对象,直至遇到左括号,将左括号也一起弹出栈。然后将一个值(括号内的运算结果)push到栈中,表示一个括号化的(子)表达式已经处理完毕,被其运算结果所替代。

emm不完整版的栈算表达式?下面这个直接是表达式求值的

#include<bits/stdc++.h>
using namespace std;

stack<int> num;
stack<char> op;

void eval(){
    auto b=num.top();num.pop();
    auto a=num.top();num.pop();
    auto c=op.top();op.pop();
    int x=0;
    if(c=='+')x=a+b;
    else if(c=='-')x=a-b;
    else if(c=='*')x=a*b;
    else x=a/b;
    num.push(x);
}
int main()
{
    unordered_map<char,int>pr{{'+',1},{'-',1},{'*',2},{'/',2},{'(',0}};//运算符优先级
    string s;
    cin>>s;
    for(int i=0;i<s.size();i++)
    {
        auto c=s[i];
        if(isdigit(c))//转数字
        {
            int x=0,j=i;
            while(j<s.size()&&isdigit(s[j]))
                x=x*10+s[j++]-'0';
            i=j-1;
            num.push(x);
        }
        else if(c=='(')op.push(c);
        else if(c==')')//括号直接算
        {
            while(op.top()!='(')eval();
            op.pop();
        }
        else
        {
            while(op.size()&&pr[op.top()]>=pr[c])eval();//如果当前优先级比前面的低就算
            op.push(c);//操作符入栈
        }
    }
    while(op.size())eval();//剩余计算
    printf("%d",num.top());
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值