c++ primer(第五版)学习笔记及习题答案代码版(第九章)顺序容器

chapter 9

笔记较为零散,都是自己不熟悉的知识点。
习题答案至于一个.cc 中,需要演示某一题直接修改 #define NUM***, 如运行9.9题为#define NUM99;

1、  string和vector将元素保存在连续的内存中,由于元素是连续存储的,由元素的下标来计算其地址是非常快速的。但是,这两种容器的中间文职添加或删除元素就非常耗时:在一次插入或删除操作后,需要移动插入/删除位置之后的所有元素来保持连续存储。

list和forward_list两个容器的设计目的是令容器任何位置的添加和删除操作都很快捷。作为代价,这两个容器不支持元素的随机访问:为了访问一个元素,我们只能遍历整个容器。且与vector和deque相比,这两个额外内存开销很大。

2、 使用vector是最好的选择。如果不确定,可以只使用vector和list公共的操作:使用迭代器,不使用下标操作,避免随机访问。

迭代器范围的概念是标准库的基础。两个迭代器的元素范围被称为左闭合区间: [begin, end)

将一个新容器床创建为另一个容器的拷贝方法有两种:可以直接拷贝整个容器,或者(array除外)拷贝由一个迭代器对指定的元素的范围。

由于两个迭代器表示一个范围,因此可以使用这种构造函数来拷贝一个容器中的子序列。

3. name.assign(v.begin(),v.end());

assign调用将name中的元素替换为迭代器指定的范围中的元素的拷贝(仅用于顺序容器)。

由于其旧元素被替换,因此传递给assign的迭代器不能指向调用assign的容器。

除了array和forwar_list之外,每个顺序容器包括string都支持push_back。

4. 当我们用一个对象来初始化容器时,或将一个对象插入到容器中,实际放入到容器中的是对象值的拷贝,而不是对象本身。

容器中的元素与提供值的对象之间没有任何关联。

使用insert的返回值,insert返回的迭代器恰好指向这个新元素。

emplace操作,三个成员empalce_front, emplace,emplace_back这些操作构造而不是拷贝元素。分别对应

push_front,insert和push_back。调用push和insert成员函数时, 我们将元素类型的对象传递给它们,这些对象被拷贝到

容器中。而当我们调用一个emplace成员函数时,则是将参数传递给元素类型的构造函数。

5. 下标操作,下标运算符接受一个下标参数,返回容器中该位置的元素的引用。

因为在一个单向链表中,没有简单的方式来获取一个元素的前驱,所以在一个forward_list中添加或删除元素的操作是

通过改变给定元素之后的元素来完成的。这样,我们总是可以访问到被添加或删除操作所影响的元素。

forward_list没有定义insert/emplace/erase,而是定义了insert_after/emplace_after/srase_after的操作。

6.  由于向迭代器添加元素和从迭代器删除元素的代码可能会是迭代器失效,因此必须保证每次改变容器的操作之后都

正确地重新定位迭代器,这个建议对vector/string/deque尤为重要。

不要返回end返回的迭代器。

reserve并不改变容器中元素的数量,它仅影响vector预先分配多大的内存空间。

7. string搜索函数返回string::size_type值,该类型是一个unsigned类型,因此,用一个int或其他带符号类型来保存这些函数的返回值不是一个好主意。

顺序容器适配器:stack/queue/priority_queue。适配器是标准库的一个通用概念,容器、迭代器和函数都有适配器。

适配器是一种机制,使其某种事物的行为看起来像一种不同的类型。

 

//main.cc
#include <fstream>
#include <iostream>
#include <list>
#include <deque>
#include <vector>
#include <forward_list>
#include <stack>
using namespace std;
#define NUM952

/*9.4*/
bool find(vector<int>::iterator begin, vector<int>::iterator end, int val){
	for(vector<int>::iterator iter = begin; iter!= end; ++iter)
		if(*iter == val)
			return true;
	return false;
}
/*9.5*/
vector<int>::iterator find2(vector<int>::iterator begin, vector<int>::iterator end, int val){
	for(vector<int>::iterator iter = begin; iter!= end; ++iter)
		if(*iter == val)
			return iter;
	return end;
}
/*9.28*/
void list_input(forward_list<string> &flst, string str1, string str2){
	auto prev = flst.before_begin();
	for(auto cur = flst.begin(); 
		cur != flst.end(); prev = cur, ++cur)
		if(*cur == str1){
			flst.insert_after(cur, str2);
			return;
		}
	flst.insert_after(prev, str2);
}
/*9.43*/
void replace1(string &s, const string &oldVal,const string &newVal){
    for(auto beg = s.begin(); beg != s.end(); ++beg){
        if(*beg != oldVal.front())
            continue;
        if(distance(beg, s.end()) < distance(oldVal.begin(), oldVal.end()))
            break;
        if(string{beg, beg + oldVal.size()} == oldVal){
            auto pos = distance(s.begin(), beg);
            s.erase(beg, beg + oldVal.size());
            s.insert(beg, newVal.begin(), newVal.end());
            beg = next(s.begin(), pos + newVal.size() -1);
        }
    }
} 
/*9.44*/
void replace2(string &s, const string& oldVal, const string& newVal){
    for(string::size_type i = 0; i != s.size(); ++i)
        if(s.substr(i, oldVal.size()) == oldVal){
            s.replace(i, oldVal.size(), newVal);
            i += newVal.size() -1;
        }
}
/*9.45*/
string func(const string &name, const string &pre, const string &pos){
    string tmp(name);       //不能直接对const string直接操作
    tmp.append(pos);   //tmp.insert(tmp.size(), pos);
    tmp.insert(tmp.begin(), pre.begin(), pre.end());
    return tmp;
}
/*9.45*/
string func2(const string &name, const string &pre, const string &pos){
    string tmp(name);       //不能直接对const string直接操作
    tmp.insert(tmp.size(), pos);
    tmp.insert(0, pre);
    return tmp;
}
/*9.50*/
int sum_for_int(const vector<string> &v)
{
    int sum = 0;
    for (auto const& s : v) sum += stoi(s);
    return sum;
}

float sum_for_float(const vector<string> &v)
{
    float sum = 0.0;
    for (auto const& s : v) sum += stof(s);
    return sum;
}
/*9.51*/
class Date{ 
public:
    Date(const string& s); 
    unsigned year;
    unsigned month;
    unsigned day;
};
Date::Date(const string& s)
{
    unsigned format = 0;
    // 1/1/1900
    if (s.find_first_of("/") != string::npos) format = 0x10;
    // Jan 1, 1900
    if (s.find_first_of(",") >= 4 && s.find_first_of(",") != string::npos)
        format = 0x01;
	switch (format) {
    // format = 1/1/1900
		case 0x10:
			day = stoi(s.substr(0, s.find_first_of("/")));
			month = stoi(s.substr(s.find_first_of("/") + 1,
					 s.find_first_of("/") - s.find_last_of("/")));
			year = stoi(s.substr(s.find_last_of("/") + 1));
		break;
		 // format = January 1, 1900  or Jan 1, 1900
		case 0x01:
			day = stoi(
				 s.substr(s.find_first_of("1234567890"),
					 s.find_first_of(",") - s.find_first_of("1234567890")));
			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;
			year = stoi(s.substr(s.find_last_of(" ") + 1));
        break;
    }
}

int main(){
/*9.1*/
#ifdef NUM91
	cout <<"(a)vector,因为我们不需要在中间添加或删除元素. (b)deque,因为deque两端添加删除操作很快, 并且不需要在中间添加/删除元素.  (c)vector不需要在头尾添加删除元素."<<endl;
#endif
/*9.2*/
#ifdef NUM92
	list< deque<int> > li;	
#endif
/*9.3*/
#ifdef NUM93
	cout <<"begin和end迭代器,begin和end必须指向相同的容器,begin靠自身叠加接近end的位置."<<endl;
#endif
/*9.4*/
#ifdef NUM94
	int val(3);
	vector<int> vec = {1, 2, 3, 4, 5};
	cout << find(vec.begin(), vec.end(), val) <<endl;
#endif
/*9.5*/
#ifdef NUM95	
	int val(3);
	vector<int> vec(10,1);
	cout << *find2(vec.begin(), vec.end(), val) <<endl;
#endif
/*9.6*/
#ifdef NUM96
	cout <<"运算符‘<’不能用在list迭代器中,修改 while(iter1 != iter2) "<<endl;
#endif
/*9.7*/
#ifdef NUM97
	cout<< "vector<int>::size_type "<<endl;
#endif
/*9.8*/
#ifdef NUM98
	cout <<"读取list<string>::const iterator, 写入list<string>::iterator "<<endl;	
#endif
/*9.9*/
#ifdef NUM99
	cout<< "cbegin是const_iterator类型的,begin是iterator类型. "<<endl;
#endif
/*9.10*/
#ifdef NUM910
	vector<int> v1;
	const vector<int> v2;
	auto it1 = v1.begin();
	auto it2 = v2.begin(), it3 = v1.cbegin(), it4 = v2.cbegin();
	cout  << "1.vector<int>::iterator 2/3/4.vector<int>::const_iterator"<<endl;
#endif
/*9.11*/
#ifdef NUM911
	vector<int> vec;    //0
	vector<int> vec1(10);   //10个元素0
	vector<int> vec2(10, 1);  //1个1  
	vector<int> vec3{1,2,3,4,5};  //1,2,3,4,5
	vector<int> vec4(other_vec);   //other_vec
	vector<int> vec5(other_vec.begin(), other_vec.end());  //other_vec 
#endif
/*9.12*/
#ifdef NUM912
	cout<<"接收一个容器创建拷贝对象是拷贝其所有元素, 但是接收两个迭代器创建拷贝的构造函数则是拷贝两个迭代器之间的元素: [begin, end) " <<endl;
#endif
/*9.13*/
#ifdef NUM913
	vector<int> vec(5,1);
	list<int> li(5,2);
	vector<double> dec(li.begin(), li.end());
	for(auto i : li)
		cout << i;
	cout <<endl;
	for(auto v : dec)
		cout << v;
	cout <<endl;
//from vector<int> to vector<double>
	vector<double> dvec(vec.begin(), vec.end());
	for(auto i : vec)
		cout << i;
	cout <<endl;
	for(auto v : dvec)
		cout << v;
	cout <<endl;
#endif
/*9.14*/
#ifdef NUM914
	list<const char*> li = {"c++ & linux"};
	vector<string> vec(li.cbegin(), li.cend());
	for(auto &i : li)
		cout << i;   cout <<endl;
	for(auto &v : vec)
		cout << v;   cout <<endl;
#endif
/*9.15*/
#ifdef NUM915
	vector<int> vec1 = {1,2,3,4,5}, vec2= {1,2,3,4};
	cout << boolalpha << (vec1 == vec2) << endl;
#endif
/*9.16*/
#ifdef NUM916
	list<int> li = {1,2,3,4,5};
	vector<int> vec1= {1,2,3,4};
	vector<int> vec2 = {1,2,3,4,5};
	cout << boolalpha << (vector<int>(li.begin(), li.end()) == vec1) << endl;
	cout << noboolalpha <<(vector<int>(li.begin(), li.end()) == vec2) << endl;
#endif
/*9.17*/
#ifdef NUM917
	cout << "1.c1c2必须是相同类型的容器.2.c1c2的元素必须是相同类型. "<<endl;
#endif
/*9.19*/
#ifdef NUM918
	string str;
	deque<string> deq;
	while(cin >> str)
		deq.push_back(str);
	for(deque<string>::iterator it = deq.begin(); it != deq.end(); ++it)
		cout << *it << " ";
	cout <<endl;
#endif
/*9.19*/
#ifdef NUM919
	list<string> input;
	for(string str; cin >> str; input.push_back(str))
		;
	for(auto it = input.cbegin(); it != input.cend(); ++it)
		cout << *it << " ";
	cout <<endl;
#endif
/*9.20*/
#ifdef NUM920
	list<int> list1 = {1,2,3,4,5,6,7,8,9};
	deque<int> deq1, deq2;
	for(auto it = list1.cbegin(); it != list1.cend(); ++it)
		if(*it % 2)
			deq2.push_back(*it);  //odd
		else 
			deq1.push_back(*it);  //even
//	deque<int> odd, even;
//  for (auto i : l) (i & 0x1 ? odd : even).push_back(i);
	for(auto &i : deq1)
		cout << i <<' ';
	cout <<endl;
	for(auto &i : deq2)
		cout << i <<' ';
	cout <<endl;
#endif
/*9.21*/
#ifdef NUM921
	string word;
	vector<string> vec;
	auto iter = vec.begin();
	while(cin >> word)
		iter = vec.insert(iter, word);
	for(auto &i : vec) 
		cout << i <<" ";     cout << endl;
#endif
/*9.22*/
#ifdef NUM922
	cout <<"死循环,mid永远不能达到mid, 并且在insert之后,mid就无效了."<<endl;
//fixed
	int some_value = 2;
	vector<int> iv = {1,2,3,4,5,6,7,8,9};
	vector<int>::iterator iter = iv.begin(), mid = iv.begin() + iv.size()/2;
	while(iter !=mid){
		if(*mid == some_value)
			mid = iv.insert(mid, 2*some_value);
		else
			--mid;
	}
	for(auto &i : iv) 
		cout << i <<" ";     cout << endl;
#endif
/*9.23*/
#ifdef NUM923
	vector<int> c(1,2);
	if(!c.empty()){
		auto val = *c.begin(), val2 = c.front();
		cout << "val: "<<val <<" ";
		auto last = c.end();
		auto val3 = *(--last);
		cout << "val3: "<<val3 <<" ";
		auto val4 = c.back();
		cout <<"val4: " <<val4<<endl;
	}
#endif
/*9.24*/
#ifdef NUM924
	vector<int> vec(0);
	cout << "vec.at(): "<<vec.at(1)<< " "   //out of range
		<<" vec[1]: "<< vec[1] <<" "		//segmentation fault 
		<<" vec.front(): "<<vec.front()<<" "  //segmentation fault
		<<" vec.begin(): " << *vec.begin()<<endl;  //segmentation fault
#endif
/*9.25*/
#ifdef NUM925
	list<int> lst = {1,2,3,4,5,6,7,8,9};
	auto elem1 = lst.begin();
	auto elem2 = lst.begin();
	lst.erase(elem1, elem2);
cout <<"如果elem1和elem2迭代器相等,什么也不发生."<<endl;
	elem1 = lst.end();
	elem2 = lst.end();
	lst.erase(elem1, elem2); 
	for(auto &i : lst) 
		cout << i <<" ";     cout << endl;
#endif
/*9.26*/
#ifdef NUM926
	int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89};
    vector<int> vec(ia, end(ia));     //end()
    list<int> lst(vec.begin(), vec.end());
	for(auto it = lst.begin(); it != lst.end(); ++it)
		if(*it % 2)
			it = lst.erase(it);  //erase(a)返回指向被删除元素之后元素的迭代器
	for(auto it = vec.begin(); it != vec.end(); ++it)
		if(!(*it %2))
			it = vec.erase(it);
	for(auto &i : lst) 
		cout << i <<" ";     cout << endl;
	for(auto &i : vec) 
		cout << i <<" ";     cout << endl;
#endif
/*9.27*/
#ifdef NUM927
	forward_list<int> flst = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (auto prev = flst.before_begin(), curr = flst.begin(); 
		curr != flst.end();) 
		if(*curr & 0x1 )
			curr = flst.erase_after(prev);
		else {
			prev = curr;
			++curr;
		}
	for(auto &i : flst) 
		cout << i <<" ";     cout << endl;
#endif
/*9.28*/
#ifdef NUM928
	forward_list<string> flst = {"linux","Nick","Josh"};
	list_input(flst, "linux", "&c++");
	for(auto &i : flst) 
		cout << i <<" ";     cout << endl;
#endif
/*9.29*/
#ifdef NUM929
	vector<int> vec(25);
	cout << vec.size() <<endl;
	vec.resize(100);	//add 75 items
	cout << vec.size() <<endl;   
	vec.resize(10);     //erase 90 from the back
	cout << vec.size() <<endl;
#endif
/*9.30*/
#ifdef NUM930
	cout <<"如果容器包含一个类类型元素,resize增加元素,必须提供元素类型的初始值,或者元素类型必须提供一个构造函数. "<<endl;
#endif
/*9.31*/
#ifdef NUM931
    list<int> lst= {0,1,2,3,4,5,6,7,8,9};
    auto iter = lst.begin();
    while(iter != lst.end()){
        if(*iter%2){
            iter = lst.insert(iter, *iter);
            advance(iter,2);
        }else
            iter = lst.erase(iter);
    }
    for(auto &i : lst) cout << i <<" "; 
    cout <<endl;
//forward_list
    forward_list<int> flst = {0,1,2,3,4,5,6,7,8,9};
    auto prev = flst.before_begin(), it = flst.begin();
    while(it!= flst.end()){
        if(*it % 2){
            it = flst.insert_after(prev, *it);
            advance(it, 2);
            advance(prev, 2);
        }else
            it = flst.erase_after(prev);
    }
    for(auto &i : flst) cout << i <<" "; 
    cout <<endl;
#endif
/*9.32*/
#ifdef NUM932
    vector<int> lst= {0,1,2,3,4,5,6,7,8,9};
    auto iter = lst.begin();
    while(iter != lst.end()){
        if(*iter%2){
            iter = lst.insert(iter, *iter++); //不合法,iter赋值不明确
            iter += 1;
        }else
            iter = lst.erase(iter);
    }
    for(auto &i : lst) cout << i <<" "; 
    cout <<endl;

#endif
/*9.33*/
#ifdef NUM933
    vector<int> vec = {0,1,2,3,4,5,6,7,8,9};
    auto begin = vec.begin();
    while(begin != vec.end()){
        ++begin;
        vec.insert(begin, 42);   //程序崩溃,insert的操作无效,begin访问了不存在的内存
        ++begin;
    }
    for(auto &i : vec)  cout << i <<" ";
    cout <<endl;
#endif
/*9.34*/
#ifdef NUM934
    vector<int> vec = {0,1,2,3,4,5,6,7,8,9};
    auto iter = vec.begin();
    while(iter != vec.end()){
        if(*iter % 2)
            iter = vec.insert(iter, *iter);//无限循环
        ++iter;
    }
    for(auto &i : vec)  cout << i <<" ";
    cout <<endl;
#endif
/*9.35*/
#ifdef NUM935
    cout << "size表示容器已经拥有的元素的数量大小. capacity表示在容器扩容之前,容器一共能够拥有多少元素."<<endl;
#endif
/*9.36*/
#ifdef NUM936
    cout << "capacity cannot be less than size"<<endl;
#endif
/*9.37*/
#ifdef NUM937
    cout << "list链表结构的存储元素并不是连续的,而array的大小是固定的,不能增加元素."<<endl;
#endif
/*9.38*/
#ifdef NUM938
    vector<string> vec;
    string word = "word";
    int size;
    while(1){
        vec.push_back(word);
        size = vec.capacity();
        cout<< size<<endl;
        if(size > 100)
            return 0;
    }
#endif
/*9.39*/
#ifdef NUM939
    vector<string> svec;
    svec.reserve(1024);     // 设定capacity初始值 1024
    string word;
    while (cin >> word)     
         svec.push_back(word);
    svec.resize(svec.size()+svec.size()/2); // 设定capacity初始值 3/2's 
#endif
/*9.40*/
#ifdef NUM940
    vector<string> svec;
    svec.reserve(1024);     
    string word = "word";
    int flag = 0;
    while (flag < 1048){    //改变数值,512时capacity1024,1000/2000,1048/2000
         svec.push_back(word);
        ++flag;
    }
    svec.resize(svec.size()+svec.size()/2); 
    cout << svec.capacity() <<endl; 
#endif
/*9.41*/
#ifdef NUM941
    vector<char> vec{'l','i','n','u','x'}; 
    string str(vec.begin(), vec.end());
    cout << str << endl; 
#endif
/*9.42*/
#ifdef NUM942
    string str; char c;
    str.reserve(100);
    while(cin >> c)
        str.insert(str.begin(),c); //stirng不能插入string类型
    cout << str <<endl;
    cout <<"先reserve足够的空间给string对象."<<endl;
#endif
/*9.43*/
#ifdef NUM943
{
    string str{"tho, thru"};
    replace1(str, "thru", "through");
    replace1(str, "tho", "though");
    std::cout << str << std::endl;
}
    string str{"thoughtho, thru"};
    replace1(str, "thru", "through");
    replace1(str, "tho", "though");
    std::cout << str << std::endl;
#endif
/*9.44*/
#ifdef NUM944
    string str{"tho, thru"};
    replace2(str, "tho", "though");
    replace2(str, "thru", "through");
    cout << str <<endl;
#endif
/*9.45*/
#ifdef NUM945
    string name = {"Show"}; 
    cout << func(name, "Mr.", ",Jr") <<endl;
#endif
/*9.46*/
#ifdef NUM946
    string name = {"Show"}; 
    cout << func(name, "Mr.", ",Jr") <<endl;
#endif
/*9.47*/
#ifdef NUM947
{    string numbers{"123456789"};
    string alphabet{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};
    string str{"ab2c3d7R4E6"};   
    cout << "numeric: ";
    for(string::size_type pos = 0; (pos = str.find_first_of(numbers, pos)) 
                            != string::npos;++pos){
        cout << str[pos] <<" ";
    }
    cout <<"\nalphabet characters: ";
    for(string::size_type pos = 0; (pos = str.find_first_of(alphabet, pos)) 
                            != string::npos;++pos){
        cout << str[pos] <<" ";
    }
    cout <<endl;
}    
    string numbers{"123456789"};
    string alphabet{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};
    string str{"ab2c3d7R4E6"};   
    cout << "numeric: ";
    for(string::size_type pos = 0; (pos = str.find_first_of(alphabet, pos)) 
                            != string::npos;++pos){
        cout << str[pos] <<" ";
    }
    cout <<"\nalphabet characters: ";
    for(string::size_type pos = 0; (pos = str.find_first_of(numbers, pos)) 
                            != string::npos;++pos){
        cout << str[pos] <<" ";
    }
    cout <<endl;
#endif
/*9.48*/
#ifdef NUM948
    string name("r2d2"), numbers("0123456789");
    cout << numbers.find(name) <<endl;
    cout << "返回npos."<<endl;
#endif
/*9.49*/
#ifdef NUM949
    ifstream ifs("./test.txt");
    string longest_word;
    if(!ifs){   
        cout <<"No text! " <<endl;
        return -1;
    }
    for(string word; ifs >> word; )
        if(word.find_first_not_of("aceimnorsuvwxz") == string::npos &&
            word.size() > longest_word.size())
                longest_word = word;
    cout << longest_word <<endl;
#endif
/*9.50*/
#ifdef NUM950
    vector<string> vec{"1","2","3.12","4.12"};
    cout << sum_for_int(vec) <<endl;
    cout << sum_for_float(vec) << endl;
#endif
/*9.51*/
#ifdef NUM951

	Date d("99/21/3871");
	cout << d.day << " " << d.month << " " << d.year << " "<<endl;
#endif
/*9.52*/
#ifdef NUM952
    auto& expr = "This is (Mooophy(awesome)((((wooooooooo))))) and (ocxs) over";
    auto repl = '#';
    auto seen = 0;

    stack<char> stk;

    for (auto c : expr) {
        stk.push(c);
        if (c == '(') ++seen;   // open
        if (seen && c == ')') { // pop elements down to the stack
            while (stk.top() != '(') stk.pop();
            stk.pop();      // including the open parenthesis
            stk.push(repl); // push a value indicate it was replaced
            --seen;         // close
        }
    }
    // Test
    string output;
    for (; !stk.empty(); stk.pop()) 
		output.insert(output.begin(), stk.top());
    cout << output << endl; // "This is # and # over"
#endif
	return 0;
}

参考资料:
c++ primer中文版第五版,电子工业出版社。
c++ primer第四版习题解答,人民邮电出版社。
pezy@github https://github.com/pezy/CppPrimer
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值