cppPrimer学习-9th
cppPrimer学习9th
目录
源代码
知识点
我的小模版
#include <forward_list>
#include <iostream>
#include <list>
#include <vector>
using namespace std;
template <typename T>
void print(T src)
{
for (auto ch : src)
cout << ch <<",";
cout<<endl;
}
int main(int argc, const char** argv)
{
while(1);
}
-
resize改变的是size,reserve表示的是容量的预分配
-
在string转数字的时候,使用
if(ch.find_first_of("0123456789")!=string::npos)
后再来处理数字避免异常等,可以看练习题9.50.转换数字的字符串第一个字符要是合法的+-.0123456789
-
string用char来构造,string(1,ch)
练习题
9.1
9.1 对于下面的程序任务,vector, deque和list哪种容器最为合适?解释你选择的理由。如果没有哪一种容器优于其它容器,也请解释理由。
读取固定数量的单词,将它们按字典序插入到容器中。我们将在下一章看到,关联容器更适合这个问题。
读取未知数量的单词,总是将新单词插入到末尾。删除操作在头部进行。
从一个文件中读取未知数量的整数。将这些整数排序,然后打印到标准输出。
-
别人的答案使用
list
,因为涉及到中间插入,但是按照书本的解释,我觉得可以先使用vector
存放,再使用sort
排序,这里作者有写固定数量 -
使用
deque
-
因为整数是小容量大小的数据元素,这里使用
vector
,再使用sort
9.2
定义一个list对象,其元素类型是int的deque。
list< deque<int> >
9.3
构成迭代器范围的迭代器有何限制
[begin,end)
begin++ 能够到达end
9.4
/**
* 编写一个函数,接受一对指向vector的迭代器和一个int值。在两个迭代器指定的范围中查找给定的值,返回一个布尔值来指出是否找到
*/
#include <iostream>
#include <vector>
using namespace std;
bool findInt(vector<int>::iterator src_begin, vector<int>::iterator src_end, int num)
{
for (vector<int>::iterator i = src_begin; i != src_end; i++) {
if (*i == num) return true;
}
return false;
}
int main(int argc, const char** argv)
{
vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
for (auto ch : a) {
cout << ch << ",";
}
cout << endl;
bool find = findInt(a.begin(), a.end(), 155);
cout << "find 155 is " << boolalpha << find << endl;
find = findInt(a.begin(), a.end(), 1);
cout << "find 1 is " << boolalpha << find << endl;
while (1) {
;
}
return 0;
}
9.5
/**
*重写上一题的函数,返回一个迭代器指向找到的元素。注意,程序必须处理未找到给定值的情况
*/
#include <iostream>
#include <vector>
using namespace std;
vector<int>::iterator findInt(vector<int>::iterator src_begin, vector<int>::iterator src_end, int num)
{
for (vector<int>::iterator i = src_begin; i != src_end; i++) {
if (*i == num) return i;
}
return src_end;
}
int main(int argc, const char** argv)
{
vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
for (auto ch : a) {
cout << ch << ",";
}
cout << endl;
auto find = findInt(a.begin(), a.end(), 155);
if (find == a.end()) {
cout << "no number find" << endl;
}
find = findInt(a.begin(), a.end(), 1);
if (find != a.end()) {
cout << "find 1 is " << *find << endl;
}
while (1) {
;
}
return 0;
}
9.6
下面程序有何错误?你应该如何修改?
list<int> lstl;
list<int>::iterator iter1 = lstl.begin(),
iter2 = lstl.end();
while (iter1 < iter2) /* ... */
迭代器是指针,对于指针比较大小没有什么意义,如果是 vector 或者 array 或者 deque 的话内存连续可以用作遍历
但是list 的地址不是连续的
9.7
为了索引int的vector中的元素,应该使用什么类型?
vector<int> sizetype 索引也就是下标
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, const char** argv)
{
vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8};
cout << a.size() << endl; // 8
while (1)
;
return 0;
}
9.8
为了读取string的list的元素,应该使用什么类型?如果写入list,又该使用什么类型
写: list<string>::iterator
读: list<string>::const_iterator
9.9
begin和cbegin两个函数有什么不同
iterator 和 const_iterator
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 vector<int>::iterator
it2 vector<int>::const_iterator
it3 vector<int>::const_iterator
it4 vector<int>::const_iterator
9.11
/*
对6种创建和初始化vector对象的方法,每一种都给出一个实例。解释每个vector包含什么值
*/
#include <iostream>
#include <vector>
using namespace std;
void printVecInfo(const vector<int> src)
{
cout << "size=" << src.size() << " : ";
for (auto ch : src) cout << ch << ",";
cout << endl;
}
int main(int argc, const char** argv)
{
using C = vector<int>;
C a1;
C a2{1, 2, 3, 4, 5, 6, 7, 8, 9};
C a3 = a2;
C a4(a2.begin(), a2.begin() + 2);
C a5(5);
C a6(6, 1);
printVecInfo(a1); // size=0 :
printVecInfo(a2); // size=9 : 1,2,3,4,5,6,7,8,9,
printVecInfo(a3); // size=9 : 1,2,3,4,5,6,7,8,9,
printVecInfo(a4); // size=2 : 1,2,
printVecInfo(a5); // size=5 : 0,0,0,0,0,
printVecInfo(a6); // size=6 : 1,1,1,1,1,1,
while (1) {
;
}
return 0;
}
9.12
对于接受一个容器创建其拷贝的构造函数,和接受两个迭代器创建拷贝的构造函数,解释它们的不同
答案在p300顶部
接受一个容器创建其拷贝的构造函数,要求两个容器类型及元素类型必须匹配。
接受两个迭代器创建拷贝的构造函数,不要求容器类型匹配,而且元素类型也可以不同,只要拷贝的元素能转换就可以
list<int> numbers = {1, 2, 3, 4, 5};
list<int> numbers2(numbers); // ok, numbers2 has the same elements as numbers
vector<int> numbers3(numbers); // error: no matching function for call...
list<double> numbers4(numbers); // error: no matching function for call...
list<int> numbers = {1, 2, 3, 4, 5};
list<int> numbers2(numbers.begin(), numbers.end); // ok, numbers2 has the same elements as numbers
vector<int> numbers3(numbers.begin(), --numbers.end()); // ok, numbers3 is {1, 2, 3, 4}
list<double> numbers4(++numbers.beg(), --numbers.end()); // ok, numbers4 is {2, 3, 4}
forward_list<float> numbers5(numbers.begin(), numbers.end()); // ok, number5 is {1, 2, 3, 4, 5}
9.13
/*如何用一个list<int>初始化一个vector<double>, 从一个vector<int>又该如何创建*/
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main(int argc, const char** argv)
{
list<int> a = {1, 2, 3, 4, 5, 6, 7};
vector<double> b(a.begin(), a.end());
vector<int> c = {1, 2, 3, 4, 5, 6, 7};
vector<double> d(c.begin(), c.end());
return 0;
}
9.14
/*
编写程序,将一个list中的char*指针(指向C风格字符串)元素赋值给一个vector中的string
*/
#include <iostream>
#include <list>
#include <string>
#include <vector>
using namespace std;
int main(int argc, const char** argv)
{
list<const char*> a(10, "hello");
vector<string> b;
b.assign(a.begin(), a.end());
for (auto ch : b) cout << ch << endl;
while (1)
;
}
9.15
// 编写程序,判定两个vector是否相等。
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, const char** argv)
{
vector<int> a = {1, 2, 3, 4, 5, 6};
vector<int> b = {2, 2, 3, 4, 5, 6};
cout << boolalpha << (a == b) << endl;
while (1)
;
}
9.16
/*重写上一题的程序,比较一个list中的一个元素和一个vector中的元素。
先转换list到vector 再比较
*/
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main(int argc, const char** argv)
{
list<int> a(5, 1);
vector<int> b(6, 1);
cout << boolalpha << (vector<int>(a.begin(), a.end()) == b) << endl;
while (1)
;
return 0;
}
9.17
假定c1和c2是两个容器,下面的比较操作有何限制
容器类型相同
容器元素类型相同
容器的元素支持比较运算 包括=,<
9.18
/*
编写程序,从标准输入读取string序列,存入一个deque中。编写一个循环,用迭代器打印deque中的元素
备注: 这里需要使用ctrl+z
*/
#include <deque>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int main(int argc, const char** argv)
{
string tmp;
deque<string> put;
while (cin >> tmp) {
put.push_back(tmp);
}
cout << "you input :\n";
for (auto ch = put.begin(); ch != put.end(); ch++) {
cout << *ch << endl;
}
while (1) {
/* code */
}
return 0;
}
9.19
重写上题程序,用list代替deque。列出程序要做出哪些改变。
将deque改为list类型 iterator的类型也改为list即可。
9.20
/*
从一个list拷贝元素到两个deque中。值为偶数的所有元素都拷贝到一个deque中,而奇数值元素都拷贝到另一个deque中
*/
#include <deque>
#include <iostream>
#include <list>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::deque;
using std::endl;
using std::list;
using std::string;
using std::vector;
// 大佬的代码
// int main()
// {
// list<int> l{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// deque<int> odd, even;
// for (auto i : l) (i & 0x1 ? odd : even).push_back(i);
// for (auto i : odd) cout << i << " ";
// cout << endl;
// for (auto i : even) cout << i << " ";
// cout << endl;
// return 0;
// }
int main()
{
list<int> src;
deque<int> dst1;
deque<int> dst2;
int num;
while (cin >> num) src.push_back(num);
for (int num : src) {
if (num & 0x01)
dst1.push_back(num);
else
dst2.push_back(num);
}
cout << "one" << endl;
for (int num : dst1) {
cout << num << " ";
}
cout << endl;
cout << "two" << endl;
for (int num : dst2) cout << num << " ";
cout << endl;
while (1)
;
return 0;
}
9.21
/* 如果我们将308页中使用insert返回值将元素添加到list中的循环程序改写为将元素插入到vector中,分析循环将如何工作
list<string> lst;
auto iter =lst.begin();
while(cin>>word)
iter=lst.insert(iter,word)
*/
一直往头部插入,vector 会执行拷贝移动
9.22
/*
假定iv是一个int的vector,下面的程序存在什么错误?你将如何修改?
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);
}
}
1. iter 是iv 的迭代器,插入后长度变了,mid也就失效了 同时当vector扩大时,地址全部失效了
2. 死循环,iter没有++
insertDoubleValue2 是我写的,,这里取巧了,因为end是一直变的,我们根据end-cursor就好了
*/
#include <iostream>
#include <vector>
using std::vector;
void insertDoubleValue(vector<int>& iv, int some_val)
{
auto cursor = iv.size() / 2;
auto iter = iv.begin(), mid = iv.begin() + cursor;
while (iter != mid) {
if (*iter == some_val) {
iter = iv.insert(iter, 2 * some_val);
++iter;
++cursor;
mid = iv.begin() + cursor;
}
++iter;
}
}
void insertDoubleValue2(vector<int>& iv, int some_val)
{
auto cursor = iv.size() / 2;
auto iter = iv.begin();
while (iter != iv.end() - cursor) {
if (*iter == some_val) {
iter = iv.insert(iter, 2 * some_val);
++iter;
}
++iter;
}
}
void print(const vector<int>& iv)
{
for (auto i : iv) std::cout << i << " ";
std::cout << std::endl;
}
int main()
{
vector<int> iv = {1, 1, 1, 1, 1, 7, 1, 9, 8};
insertDoubleValue(iv, 1);
print(iv);
iv = {1, 1, 1, 1, 1, 7, 1, 9, 8};
insertDoubleValue2(iv, 1);
print(iv);
while (1)
;
}
9.23
在本节第一个程序(309页)中,若c.size()为1, 则val, val2, val3和val4的值会是什么
第一个元素
9.24
编写程序,分别使用at、下标运算符、front和begin提取一个vector中的第一个元素。
在一个空vector上测试你的程序
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, const char** argv)
{
std::vector<int> v;
std::cout << v.at(0); // terminating with uncaught exception of type std::out_of_range
std::cout << v[0]; // Segmentation fault: 11
std::cout << v.front(); // Segmentation fault: 11
std::cout << *v.begin(); // Segmentation fault: 11
while (1) return 0;
}
9.25
对于312页中删除一个范围内的元素的程序,如果elem1与elem2相等会发生什么?
如果elem2是尾后迭代器,或者elem1和elem2皆为尾后迭代器,又会发生什么
elem1=slist.erase(elements,elem2)
1. 不删除元素,不发生改变
2. 清空元素
3. 不删元素,不发生改变
9.26
/*
使用下面代码定义的ia,将ia拷贝到一个从vector和一个list中。
使用单迭代器版本的erase从list中删除奇数元素,从vector中删除偶数元素。
*/
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main(int argc, const char** argv)
{
int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89};
// 这么做也可以,说明迭代器是+1的计算方式
// vector<int> va(ia, ia + sizeof(ia) / sizeof(int));
vector<int> va(begin(ia), end(ia));
list<int> lb(va.begin(), va.end());
for (auto it = va.begin(); it != va.end();) {
if ((*it) % 2)
it = va.erase(it);
else
it++;
}
for (auto it = lb.begin(); it != lb.end();) {
if ((*it) % 2)
it++;
else
it = lb.erase(it);
}
for (auto ch : va) cout << ch << ",";
cout << endl;
for (auto ch : lb) cout << ch << ",";
cout << endl;
while (1)
;
return 0;
}
9.27
/*
编写程序,查找并删除forward_list中的奇数元素。
*/
#include <forward_list>
#include <iostream>
using namespace std;
int main(int argc, const char** argv)
{
forward_list<int> flst = {2, 1, 2, 3, 4, 5, 6, 7, 8, 9};
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 ch : flst) cout << ch << ",";
while (1)
;
return 0;
}
9.28
/*
编写函数,接受一个forward_list和两个string共三个参数。
函数应在链表中查找第一个string,并将第二个string插入到紧接着第一个string之后的位置。
若第一个string未在链表中,则将第二个string插入到链表末尾。
*/
#include <forward_list>
#include <iostream>
#include <string>
using namespace std;
void insert_lst(forward_list<string>& src, string after, string what)
{
if (src.empty()) {
return;
}
auto prev = src.before_begin();
auto curr = src.begin();
while (curr != src.end()) {
if (*curr == after) {
src.insert_after(curr, what);
return;
}
else {
curr++;
prev++;
}
}
src.insert_after(prev, what);
}
int main(int argc, const char** argv)
{
forward_list<string> lst = {"www", ".baidu", ".com"};
insert_lst(lst, ".baidu", ".hello");
for (auto ch : lst) cout << ch << endl;
insert_lst(lst, "xxx", ".hello");
for (auto ch : lst) cout << ch << endl;
while (1)
;
return 0;
}
9.29
假定vec包含25个元素,那么vec.resize(100)会做什么?如果接下来调用vec.resize(10)会做什么
1. 尾部添加75个0,同时可能因为移动拷贝,迭代器失效
2. 丢弃尾巴的90个元素
9.30
接受单个参数的resize版本对元素类型有什么限制
如果是类的话,需要有默认构造函数,或者初始值
9.31
// 大佬使用了 advance(prv, 2) 来操作迭代器
/*第316页中删除偶数值元素并复制奇数值元素的程序不能用于list或forward_list。
修改程序,使之也能用于这些类型
*/
#include <forward_list>
#include <iostream>
#include <list>
#include <vector>
using namespace std;
template <typename T>
void print(T src)
{
for (auto ch : src)
cout << ch <<",";
cout<<endl;
}
int main(int argc, const char** argv)
{
vector<int> v1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
list<int> l1(v1.begin(),v1.end());
forward_list<int> l2(v1.begin(),v1.end());
// 删除偶数元素,复制每个奇数元素
auto it1 = v1.begin();
while (it1 != v1.end()) {
if (*it1 % 2) {
it1 = v1.insert(it1, *it1);
it1+=2;
}
else {
it1=v1.erase(it1);
}
}
print(v1);
{ // list 使用两个++
// 删除偶数元素,复制每个奇数元素
auto it1 = l1.begin();
while (it1 != l1.end()) {
if (*it1 % 2) {
it1 = l1.insert(it1, *it1);
it1++;
it1++;
}
else {
it1=l1.erase(it1);
}
}
print(l1);
}
{ // forward_list 只有insert_after
// 删除偶数元素,复制每个奇数元素
auto curr = l2.begin();
auto prev=l2.before_begin();
while (curr != l2.end()) {
if (*curr % 2) {
prev = l2.insert_after(prev,*curr);
prev++; // 指向了原来的curr
//curr=prev; // 可以注释掉,这里不会发生迭代器失效
curr++;
}
else {
curr=l2.erase_after(prev);
}
}
print(l2);
}
while (1);
return 0;
}
9.32
316页的程序中,向下面语句这样调用insert是否合法?如果不合法,为什么?
iter = vi.insert(iter, *iter++);
*从右到左
iter++ 从左到右.++ 操作的是iter
*iter++ 根据优先级 *iter 然后iter++
https://stackoverflow.com/questions/2934904/order-of-evaluation-in-c-function-parameters
无法确认是先执行 *iter++ 还是先 insert
或者返回后 先赋值给iter 还是先iter++,再返回给iter
9.33
在本节最后一个例子中,如果不将insert的结果赋予begin,将会发生什么?
编写程序,去掉此赋值语句,验证你的答案。
#include "include.h"
int main(int argc, const char** argv) {
vector<int> ivec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto iter = ivec.begin();
while (iter != ivec.end()) {
++ iter;
/* iter = */ivec.insert(iter, 42);
// 调试可以发现 刚开始 iter=2
// 执行玩insert后=0 失效了
++ iter;
}
print(ivec);
while(1);
return 0;
9.34
死循环
/*假定vi是一个保存int的容器,其中有偶数值也要奇数值,分析下面循环的行为,然后编写程序验证你的分析是否正确。*/
#include "include.h"
int main(int argc, const char** argv) {
vector<int> v1={1,2,3,4,5,6,7,8,9};
auto iter=v1.begin();
while(iter!=v1.end())
{
if(*iter%2)
{
iter=v1.insert(iter,*iter);
// ++iter; ///-----if里面也需要++一次
}
++iter;
}
print(v1);
while(1);
return 0;
}
9.35
解释一个vector的capacity和size有何区别
capacity 表示不用重新分配内存时占用的内存大小
size 表示已经存储的元素的大小
9.36
一个容器的capacity可能小于它的size吗
不会
capacity >= size
9.37
为什么list或array没有capacity成员函数?
list 是链表,插入的时候分配内存
array 是固定大小的
9.38
/**
编写程序,探究在你的标准库实现中,vector是如何增长的
*/
#include "include.h"
void printInfo(vector<int> &v)
{
cout <<"size="<<v.size()<<endl;
cout <<"capacity="<<v.capacity()<<endl;
}
int main(int argc, const char** argv) {
vector<int> v1;
printInfo(v1); //size=0,capacity=0
v1.push_back(1); //size=1,capacity=1
printInfo(v1);
v1.push_back(1); //size=2,capacity=2
printInfo(v1);
v1.push_back(1); //size=3,capacity=4
printInfo(v1);
while(1);
return 0;
}
9.39
vector<string> svec;
svec.reserve(1024);
string word;
while (cin >> word) {
svec.push_back(word);
}
svec.resize(svec.size() + svec.size()/2);
1. 分配容量为1024的容器,如果超了的话再分配
2. 填充后1/4 为空串 最后使用resize只能改变vector的size,不能改变其capacity
9.40
如果上一题的程序读入了256个词,在resize之后容器的capacity可能是多少?
如果读入了512个、1000个或1048个词呢?
256---256+256/2=384-------1024
512---512+512/2=768-------1024
1000--1000+1000/2=1500----这个可能是2048,但实际是//size=1500 capacity=2000
1048--1024*2=1536---------2048吧
// 可以看出来 直接 resize 出来的 capacity= resize*2-----这里可能编译器做法不一样的
// 直接push一个个的是+1
#include "include.h"
template<typename T>
void printInfo(const T& v)
{
cout <<"size="<<v.size()<<endl;
cout <<"capacity="<<v.capacity()<<endl;
}
int main(int argc, const char** argv) {
vector<string> svec;
svec.reserve(1024);
string word;
for(int i=0;i<1000;i++){
svec.push_back("123");
}
svec.resize(svec.size() + svec.size()/2);
printInfo(svec);//size=1500 capacity=2000----------------------------
vector<string> svec2;
svec2.reserve(1024);
for(int i=0;i<1500;i++){
svec2.push_back("123");
}
printInfo(svec2);//size=1500 capacity=2048--------------------------
while(1);
return 0;
}
9.41
/*
从vector<char> 创建 string
*/
#include "include.h"
int main(int argc, char const *argv[])
{
vector<char> vstr={'1','2','3','\0'};
string s(vstr.begin(),vstr.end());
cout<<s<<endl;
while(1);
return 0;
}
9.42
假定你希望每次读取一个字符存入一个string中,而且知道最少需要读取100个字符,应该如何提高性能
使用reserve提前分配好空间,来确保 capacity 大于100
9.43
9.44
/*
编写一个函数,接受三个string参数s,oldVal和newVal.使用迭代器及insert和erase函数将s中所有oldVal替换为newVal。测试你的程序,用它替换通用的简写形式,如,将“tho”替换为“though”,将“thru”替换为“through”。
replaceString 迭代器
replaceString0 下标+replace
*/
#include "include.h"
// 使用了下标,和replace
void replaceString0(string& s,string& sold, string& snew)
{
size_t sold_size=sold.size();
for(size_t i=0;i+sold_size<s.size();i++)
{
if(s.substr(i,sold_size)==sold)
{
s.replace(i,sold_size,snew);
i+=snew.size();
}
}
}
// 使用了下标,不符合题目
void replaceString1(string& s,string& sold, string& snew)
{
size_t sold_size=sold.size();
for(size_t i=0;i+sold_size<s.size();i++)
{
if(s.substr(i,sold_size)==sold)
{
s.erase(i,sold_size);
s.insert(i,snew);
i+=snew.size();
}
}
}
// 使用迭代器 转换了下标
void replaceString2(string& s,string& sold, string& snew)
{
size_t sold_size=sold.size();
for(auto beg=s.begin(); distance(beg,s.end()) >=distance(sold.begin(),sold.end());beg++)
{
if(s.substr(beg-s.begin(),sold_size)==sold)
{
s.erase(beg-s.begin(),sold_size);
s.insert(beg-s.begin(),snew);
advance(beg,snew.size());
}
}
}
// 完全使用迭代器
void replaceString(string& s,string& sold, string& snew)
{
size_t sold_size=sold.size();
for(auto beg=s.begin(); distance(beg,s.end()) >=distance(sold.begin(),sold.end());beg++)
{
// if(s.substr(beg-s.begin(),sold_size)==sold)
if(string(beg,beg+sold.size())==sold)
{
beg=s.erase(beg,beg+sold_size);
beg=s.insert(beg,snew.begin(),snew.end());
advance(beg,snew.size());
}
}
}
int main(int argc, char const *argv[])
{
{
string s="123 456 789 ";
string sold="456";
string snew="AAAA";
replaceString(s,sold,snew);
cout << s <<endl;
}
{
string s="123 456 789 ";
string sold="456";
string snew="AAAA";
replaceString0(s,sold,snew);
cout << s <<endl;
}
while(1);
return 0;
}
9.45
9.46
/*
9.45
接受一个表示名字的string参数和两个分别表示前缀(如“Mr."或”Ms.“)和后缀(Jr或III)的字符串。\
使用迭代器及insert和append函数将前缀和后缀加到给定的名字中,将生成的新string返回。
9.46
重写上一题的函数,这次使用位置和长度来管理string,并只使用insert
*/
#include "include.h"
string fullName(const string& s,const string& before,const string& after)
{
string full(s);
full.insert(full.begin(),before.begin(),before.end());
full.append(after);
return full;
}
string fullName2(const string& s,const string& before,const string& after)
{
string full(s);
full.insert(0,before);
full.insert(full.size(),after);
return full;
}
int main(int argc, char const *argv[])
{
cout << fullName("layty","Mr."," good")<<endl;
cout << fullName2("layty","Mr."," good")<<endl;
while(1);
return 0;
}
9.47
/*
编写程序,首先查找string "ab2c3d7R4E6"中的每个数字字符,然后查找其中每个字母字符。编写两个版本的程序,第一个要使用find_fisrt_of,第二个要使用 find_first_not_of
*/
#include "include.h"
void find1(const string& s)
{
string number("0123456789");
string abc;
for(int i=0;i<26;i++)
{
abc.push_back('a'+i);
abc.push_back('A'+i);
}
string::size_type pos=0;
while( (pos=s.find_first_of(number,pos)) != string::npos)
{
cout << s[pos]<<endl;
pos++;
}
pos=0;
while( (pos=s.find_first_of(abc,pos)) != string::npos)
{
cout << s[pos]<<endl;
pos++;
}
//----------------------------------------------------------
pos=0;
while( (pos=s.find_first_not_of(number,pos)) != string::npos)
{
cout << s[pos]<<endl;
pos++;
}
pos=0;
while( (pos=s.find_first_not_of(abc,pos)) != string::npos)
{
cout << s[pos]<<endl;
pos++;
}
}
int main(int argc, char const *argv[])
{
find1("123ABC456");
while(1);
return 0;
}
9.48
假定name和numbers的定义如325页所示,number.find(name)返回什么?
string name = "AnnaBelle";
string number = "0123456789";
auto result = number.find(name);
if (result == string::npos) {
cout << "npos" << endl;
}
返回 string::npos
9.49
/*
如果一个字母延伸要中线之上,如d或f,则称其有上出头部分。如果延伸到中线之下,则称其有下出头部分。编写程序,读入一个单词文件,输出最长的既不包含上出头部分,也不包含下出头部分的单词。
*/
#include <fstream>
#include "include.h"
int main(int argc, char const *argv[])
{
ifstream file("E:\\Reading\\C++\\C+++Primer\\CppPrimer-master\\CppPrimer-master\\ch09\\ex9_49.cpp");
if(!file)
{
cout << "file open filed"<<endl;
while(1);
return -1;
}
string s;
string get;
while(file>>s)
{
if(s.find_first_not_of("aceimnorsuvwxz")==string::npos)
{
if(get.size()<s.size())
get=s;
}
}
cout << "get: "<<get <<endl;
while(1);
return 0;
}
9.50
/*
编写程序处理一个vector,其元素都表示整形值。计算vector中所有元素之和。修改程序,使之计算表示浮点值的string之和
*/
#include "include.h"
int sum_int(const vector<string>& s)
{
int n=0;
for(auto ch : s)
{
if(ch.find_first_of("0123456789")!=string::npos)
if(ch.substr(ch.find_first_of("+-.0123456789")).size())
{
n+=stoi(ch);
}
}
return n;
}
double sum_double(const vector<string>& s)
{
double n=0;
for(auto ch : s)
{
if(ch.find_first_of("0123456789")!=string::npos)
if(ch.substr(ch.find_first_of("+-.0123456789")).size())
{
n+=stod(ch);
}
}
return n;
}
int main(int argc, char const *argv[])
{
vector<string> s={"---","2.1","2.1","-3"};
cout << "sum="<<sum_int(s)<<endl;
cout << "sum="<<sum_double(s)<<endl;
while(1);
return 0;
}
9.51
/*
设计一个类,它有三个unsigned成员,分别表示年、月和日。为其编写构造函数,接受一个表示日期的string参数。你的构造函数应该能处理不同数据格式,如January 1,1900、1/1/1990、Jan 1 1900等。
*/
#include "include.h"
#include <array>
class mydate
{
private:
/* data */
unsigned int year=1990;
unsigned int month=1;
unsigned int day=1;
public:
mydate(const string& s);
~mydate();
};
mydate::mydate(const string& s1="")
{
string s(s1);
if(s.empty()) return;
string::size_type pos;
string::size_type year_pos,month_pos;
string::size_type pos_day,pos_month,pos_year;
if((pos=s.find("/"))!= string::npos) // 1/1/1990
{
// day
s=s.substr(s.find_first_of("0123456789"));
day=stoul(s,&pos_day);
// month
s=s.substr(s.find_first_of("0123456789",pos_day));
month=stoul(s,&pos_month);
// year
s=s.substr(s.find_first_of("0123456789",pos_month));
year=stoul(s);
}
else //Jan 1 1900
{
std::array<std::string, 12> month_names{"Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
for(int i=0;i<12;i++)
{
if(s.find(month_names[i])!=string::npos)
{
month=i+1;
break;
}
}
// day
s=s.substr(s.find_first_of("0123456789"));
day=stoul(s,&pos_day);
// year
s=s.substr(s.find_first_of("0123456789",pos_day));
year=stoul(s);
}
cout<< "year="<<year<<" month="<<month<<" day="<<day<<endl;
}
mydate::~mydate()
{
}
int main(int argc, char const *argv[])
{
mydate("3/4/2021");
mydate("Dec 2 2022");
mydate("January 1,2023");
while(1);
return 0;
}
9.52
#include "include.h"
#include <stack>
int main(int argc, char const *argv[])
{
// 1*(2+10)-11
stack<string> s;
string abc="1*(2+10)-1";
string num;
string::size_type i=0;
for(auto ch : abc)
{
i++;
if(ch>='0' && ch <='9')
{
num.append(string(1,ch));
if(i==abc.size())
{
s.push(num);
}
}
else
{
if(!num.empty())
{
s.push(num);
}
s.push(string(1,ch));
num.erase();
}
}
while(!s.empty())
{
cout<<s.top()<<endl;
s.pop();
}
auto& expr = "This is (Mooophy(awesome)((((wooooooooo))))) and (ocxs) over";
stack<char> s1;
int ok=0;
for(auto ch: expr)
{
s1.push(ch);
if(ch=='(') ok++;
if(ch==')' && ok)
{
while(s1.top()!='(')
{
s1.pop();
}
s1.pop();
s1.push('#');
ok--;
}
}
string output;
for (; !s1.empty(); s1.pop()) output.insert(output.begin(), s1.top());
cout << output << endl; // "This is # and # over"
while(1);
return 0;
}