21天学通C++课后作业整理

        建议在看书的时候就直接将这部分的课后习题过一遍,当时过挺简单的,没必要忘得差不多了再回去复习重做,这块的知识点就从其他地方做题遇到不懂的再翻就行。 

 16章 STL string类

第一题

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
using namespace std;        // 指定缺省的命名空间。

int main()
{
	string instr;
	cout << "请输入一串字符:" << endl;
	cin >> instr;

	string copystr = instr;
	reverse(instr.begin(), instr.end());

	if (copystr == instr) {

		cout << "字符串为回文";
	}
	else
	{
		cout << "bushi";
	}
}

第二题 

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
using namespace std;        // 指定缺省的命名空间。

int main()
{
	string instr;
	cout << "请输入一串字符:" << endl;
	cin >> instr;
	
	int count = 0;
	for (int i = 0; i < instr.length(); i++)
	{
		if ((instr[i] == 'a') || (instr[i] == 'e') || (instr[i] == 'i') || (instr[i] == 'o') || (instr[i] == 'u'))
		{
			count++;
		}
	}
	cout << "元音数:" << count;
}

第三题 

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
using namespace std;        // 指定缺省的命名空间。
int main()
{
	string instr;
	cout << "请输入一串字符:" << endl;
	cin >> instr;
	
	int count = 0;
	for (int i = 1; i < instr.length(); i += 2)
	{
		transform(instr.begin() + i, instr.begin() + i + 1, instr.begin() + i, ::toupper);
	}
	cout << "zhuan:" << instr;
}

第四题

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
using namespace std;        // 指定缺省的命名空间。

int main()
{
	string str1 = "i";
	string str2 = "love";
	string str3 = "STL";
	string str4 = "string";

	str1.append(" ");
	str2.append(" ");
	str3.append(" ");
	str4.append(" ");
	
	str3.append(str4);
	str2.append(str3);
	str1.append(str2);
	cout << str1;
}

 第五题

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
using namespace std;        // 指定缺省的命名空间。

int main()
{
	string str1 = "good day string! today is beautiful";
	auto  findpos = str1.find('a', 0);
	while(findpos != string::npos)		//find函数在找不到结果时返回npos
	{
		
		cout <<findpos<<endl;		//返回第一个找到的位置
		auto newfindpos = findpos + 1;		//第一次找到的位置往后加1
		findpos = str1.find('a', newfindpos);		//下次查找从新位置开始,find返回新位置
	}
}

17章 STL动态数组类vector

 第一题

 自己的代码不严谨,应该像示例提前将情况都列出。使用一个函数将所有的选项都展示,在函数中输入内容,选择要实现的功能

第一题、第二题

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
#include<vector>
using namespace std;        // 指定缺省的命名空间。
template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< * count << endl;
	}
}
int main()
{
	int num;
	int stop = 10;
	vector<int>vec1;
	
	while(stop!=0)
	{
		cout << endl<<"请输入一些整数(逐个输入):" << endl;
		cin >> num;
		vec1.push_back(num);
		cout <<"输入的整数为:"<< num << endl;
		cout << "continue?(输入0停止)" << endl;
		cin >> stop;
		//show(vec1);
	}
	int cha;
	cout << "请输入查询的索引值:" << endl;
	cin >> cha;
	if (cha < vec1.size())
	{
		cout << vec1[cha]<<endl;
	}

	cout << "请输入想要查询的元素值:" << endl;
	int find_num = 0;
	cin >> find_num;
	for (auto count1 = vec1.begin(); count1 != vec1.end(); count1++)
	{
		if (*count1 == find_num)	//不严谨,对每个元素进行判断,如果有两个相同的将输出两遍
		{
			cout << "找到查询的元素";
		}
	}	
}

 第三题

重载<<运算符需要注意


char option()	//提供一个函数,实现菜单选项以及输入信息
{
	cout << "请输入想要的选项:" << endl;
	cout << "选项1:输入货物的尺寸:" << endl;
	cout << "选项2:输出货物的信息:" << endl;
	cout << "选项3:退出:" << endl;

	char opt;
	cin >> opt;

	return opt;
}
class goods
{
public:
	int length;
	int high;
	string name;

	goods() {};
	goods(int inlen, int inhigh, string inname) 
	{ 
		length = inlen;
		high = inhigh;
		name = inname;
		cout << "初始化完成"<<endl; 
	};
	~goods() {};
};
ostream& operator<< (ostream& output, goods& ingoods)	//重载<<运算符
{
	output << "货物高:" << ingoods.high << endl << "货物长:" << ingoods.length << endl << "货物名称:" << ingoods.name << endl;
	return output;
}


int main()
{
	vector<goods> vecdate;
	char opt_choose;
	/*cout << "请输入选择的选项:";
	cin >> opt_choose;*/
	while ((opt_choose = option()) != '3')		//将上面定义好的参数传递给opt_choose,且这个值不是选项3的时候
	{
		if (opt_choose == '1')	//输入货物的尺寸
		{
			goods goods1;

			string name1 = "";
			cout << "请输入货物名称:";
			cin >> name1;

			int len1 = 0;
			cout << "请输入货物长:";
			cin >> len1;

			int high1 = 0;
			cout << "请输入货物高:";
			cin >> high1;

			vecdate.push_back(goods(len1, high1,name1));	//实例化一个对象,并将其放到vector的末尾
		}
		else if(opt_choose == '2')	//输出货物的信息
		{
			cout << "请输入想要查询的索引:介于0和"<<vecdate.size()-1 <<"之间" << endl;
			int num = 0;
			cout << "想要查询的索引值为:";
			cin >> num;
			if (num < vecdate.size())
			{
				cout << vecdate[num] << endl;	//没有将class传入cout的运算符,需要重载<<运算符
			}
		}
		
	}
	return 0;
}

 第四题

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<deque>
#include<vector>
using namespace std;        // 指定缺省的命名空间。

template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< * count << endl;
	}
}
int main()
{
	deque<string>exdeque{"hello", "cool", "C++"};
	show(exdeque);
}

 18章 STL list 和forward_list

第一题

实现的想法与17章的第一题类似,注意局部变量的使用,如果循环中用到的变量其他地方还要使用,就将其放到循环外。

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<list>
using namespace std;        // 指定缺省的命名空间。

template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< * count << endl;
	}
}

char option()	//提供一个函数,实现菜单选项以及输入信息
{
	cout << "请输入想要的选项:" << endl;
	cout << "选项1:输入存储的值:" << endl;
	cout << "选项2:输出存储的值:" << endl;
	cout << "选项3:退出:" << endl;

	char opt;
	cin >> opt;

	return opt;
}

int main()
{
	char opt;
	list<int>list1;
	while ((opt = option()) != '3')
	{
		
		int num = 0;
		if (opt  == '1')
		{
			cout << "请输入想要存储的数:";
			cin >> num;
			list1.push_front(num);
		}
		else if(opt == '2')
		{
			show(list1);
			cout << "输出";
		}
	}
	return 0;
}

第二题

在插入元素后,迭代器仍然指向原本元素,因为其解引用的值未变

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<list>
using namespace std;        // 指定缺省的命名空间。

int main()
{
	list<int>list1;
	list1.push_front(1);
	list1.push_front(2);
	list1.push_front(3);	//现在list1内部的元素为3,2,1
	auto find_1 = find(list1.begin(), list1.end(), 1);	//迭代器指向1所在位置
	auto find_3 = find(list1.begin(), list1.end(), 3);	//迭代器指向3所在位置
	//cout << *(find_1) << endl;
	//cout << *(find_3) << endl;

	list1.insert(list1.begin() , 1000);		
	list1.push_front(500);		//现在元素值为500,1000,3,2,1

	cout << *(find_1) << endl;
	cout << *(find_3) << endl;

	return 0;
}

第三题

insert(插入的位置,插入的容器起始,插入的容器终止)

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<list>
#include<vector>
using namespace std;        // 指定缺省的命名空间。

template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< * count << endl;
	}
}

int main()
{
	list<int>list1;
	vector<int>vec1{11, 12, 13};
	list1.push_front(1);
	list1.push_front(2);
	list1.push_front(3);	//现在list1内部的元素为3,2,1
	list1.insert(list1.begin(), vec1.begin(), vec1.end());
	show(list1);

	return 0;
}

第四题

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<list>
#include<vector>
using namespace std;        // 指定缺省的命名空间。

template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< * count << endl;
	}
}

bool down (const int& left,  const int& right)
{
	return left > right;
}

int main()
{
	list<int>list1;
	vector<int>vec1{11, 12, 13};
	list1.push_front(1);
	list1.push_front(2);
	list1.push_front(3);	//现在list1内部的元素为3,2,1
	
	list1.insert(list1.begin(), vec1.begin(), vec1.end());

	list1.sort(down);	//自定义下降
	show(list1);

	list1.reverse();	//直接将默认升序反转
	show(list1);
	return 0;
}

第19章 STL集合类set

第一题

在代码中用到了类型转换函数,将string转化为c风格字符串,在C++中,构造函数、析构函数、类型转换函数没有返回类型,在类型转换函数中,不写返回类型,但是必须出现return。类型转接中返回类型在operator后面的括号前面,函数运算符是在类型在operator前面

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<set>
#include<string>
using namespace std;
template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< *count<< endl;
	}
}
class books
{
public:
	string names;
	string num;
	string coutdata;

	books(const string inkeys, const string inmeaning) :names(inkeys), num(inmeaning),coutdata(inkeys+inmeaning) {};
	
	//使用sort排序
	bool operator < (const books& inword) const
	{
		return (this->names < inword.names);	//对于string没有<运算符
	}
	//使用find函数
	bool operator ==(const string& inkey)	//判断输入的词与当前词的索引相同
	{
		return(inkey == this->names);
	}
	operator  const char* () const	//将string类转换为c风格,函数后面的const不可少
	{

		return coutdata.c_str();
	}
};
int main()
{
	set<books>set_ex;
	set_ex.insert(books{ "xiaoming","1111111111" });
	set_ex.insert(books{ "xiaoli","222222222" });
	set_ex.insert(books{ "xiaowang","3333333" });
	set_ex.insert(books{ "xiaozhang","444444444" });

	show(set_ex);
cout << "请输入想要查询的名字:";
	string input;
	getline(cin, input);		//有getline就不需要在前面cin了,只需要在内部传入cin
	auto element = set_ex.find(books(input, " "));
	if (element != set_ex.end())
	{
		cout << "查找的电话号码为:" << (*element).num << endl;
	}
	else
	{
		cout << "没有查到该人" << endl;
	}
	return 0;
}

第二题

        set会在插入元素时自动排序,所以对于不是基本数据类型的元素需要重载<运算符,如果想要使用find函数还需要重载==运算符。

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<set>
#include<string>
using namespace std;
class word
{
public:
	string keys;
	string meaning;

	word(const string inkeys, const string inmeaning) :keys(inkeys), meaning(inmeaning) {};
	//template<typename T1>
	bool operator < (const word& inword) const
	{
		return (this->keys < inword.keys);	//对于string没有<运算符
	}
	bool operator==(const string& inkey)	//判断输入的词与当前词的索引相同
	{
		return(inkey == this->keys);
	}
};
int main()
{
	set<word>set_ex;
	word word1("book", "to learn");	//set在插入时对元素进行排序,需要重载<运算符
	word word2("water", "to drink");
	
	set_ex.insert(word1);
	set_ex.insert(word2);

	cout << "请输入想要查询的词:";
	string input;
	getline(cin,input);		//有getline就不需要在前面cin了,只需要在内部传入cin
	auto element = set_ex.find(word(input, " "));
	if (element != set_ex.end())
	{
		cout << "单词的含义是" << (*element).meaning << endl;
	}
	else
	{
		cout << "没有查到该单词" << endl;
	}
	return 0;
}

第三题 

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<set>
#include<string>
using namespace std;
template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< (*count)<< endl;
	}
}
int main()
{
	set<int>set_ex;
	multiset<int>mulset_ex;
	
	set_ex.insert(5);
	set_ex.insert(5);

	mulset_ex.insert(5);
	mulset_ex.insert(5);
	mulset_ex.insert(5);
	
	show(set_ex);
	cout << "下面是multiset的输出。"<<endl;
	show(mulset_ex);
	return 0;
}

第20章 STL映射类map

第一题

可包含重复元素的关联容器,可以使用STL::multimap实现

multimap<string, string> numbercount;

第二题

在结构体里创建一个二元谓词(跟二元函数类似,但是返回值类型是bool),根据string元素进行排序

struct fpredicate
{
	bool operator <(const wordpropetry& lsh, const wordpropetry& rah)const
	{
		return (lsh.word < rah.word);
	}
};

第三题

 在map中需要使用迭代器(指针)的first和second来表达键和值,在往map中插入元素时,map名.insert(make_pair(键,值))实现

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
#include<map>
using namespace std; 
template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< count->first<< endl;
		cout << "容器中元素为:" << count->second << endl << endl;
	}
}
int main()
{
	multimap<int, int>num_set;
	num_set.insert(make_pair(1, 1));
	num_set.insert(make_pair(2, 2));
	num_set.insert(make_pair(1, 2));
	show(num_set);

	return 0;
}

第21章 理解函数对象

第一题

 函数对象是用作函数的对象,实现了operator()的类的对象

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
#include<vector>
using namespace std; 

template<typename T=int>	//提供默认参数类型,否则下方需要传入参数类型
struct Double
{
	void operator()(const T input) const
	{
		cout << input * 2 << endl;
	}
};

int main()
{
	vector<int>vec1;

	for (int i = 0; i < 10; i++)
	{
		vec1.push_back(i);
	}
	for_each(vec1.begin(), vec1.end(), Double<double>());    
    //因为在构建函数模版时提供了默认参数,所以这块可以不传入double类型

	return 0;
}

第二题

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
#include<vector>
using namespace std; 

template<typename T=int>	//提供默认参数类型,否则下方需要传入参数类型
struct Double
{
	int count;
	Double() { count = 0; };
	void operator()(const T input) 
	{
		count++;
		cout << input * 2 << endl;
	}
};

int main()
{
	vector<int>vec1;

	for (int i = 0; i < 10; i++)
	{
		vec1.push_back(i);
	}
	//Double<int>result;	result的实际类型
	// for_each返回所传入函数对象的最终状态
	auto result=for_each(vec1.begin(), vec1.end(), Double<>());
	cout << "计数器:" << result.count << endl;
	return 0;
}

第三题

 在实际使用中作为sort函数的第三个参数传入

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<vector>
using namespace std;

template<typename T>
class SortAscending
{
public:
	bool operator()(const T& num1, const T& num2)const
	{
		return(num1 < num2);
	}
};

template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< *count<< endl;
		
	}
}
int main()
{
	vector<int>vec1;

	for (int i = 10; i>0; i--)
	{
		vec1.push_back(i*10);
	}
	cout << "排序前:"<<endl; 
	show(vec1);
	sort(vec1.begin(), vec1.end(), SortAscending<int>());
	cout << "排序后:" << endl;
	show(vec1);
	return 0;
}

第22章 lamdba表达式

第一题

sort(容器.begin(), 容器.end(),
		[](auto in1, auto in2) {return in1 > in2; });

第二题

	cout << "想要添加的元素值:";
	int numinput = 0;
	cin >> numinput;
	for_each(vec.begin(), vec.end(),
		[=](int& element) {element += numinput; });

代码的使用示例

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<vector>
using namespace std; 

template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< *count<< endl;
		
	}
}

int main()
{
	vector<int>vec{1, 4, 5, 2, 6};
	show(vec);
	cout << "降序排列" << endl;
	sort(vec.begin(),vec.end());
	show(vec);

	cout << "升序排列" << endl;
	sort(vec.begin(), vec.end(),
		[](auto in1, auto in2) {return in1 > in2; });
	show(vec);

	cout << "输入在容器元素值增加的值:";
	int numinput = 0;
	cin >> numinput;
	for_each(vec.begin(), vec.end(),
		[=](int& element) {element += numinput; });
	show(vec);
	return 0;
}

第23章 STL算法

第一题

struct compare
{
    bool operator() (const string str1, const string str2)const
    {
        //因为不改变输入的字符串内容,所以使用现有的两个字符串构建新的字符串
        string copy1(str1),copy2(str2);

        //因为不区分大小写所以将两个字符串都转换为小写 
        transform(copy1.begin(),copy1.end(),tolower);
        transform(copy2.begin(),copy2.end(),tolower);

        return(copy1<copy2);
    }
};

第二题

#include <iostream>         // 包含头文件。
#include<algorithm>
#include<string>
#include<list>
#include<vector>
using namespace std;        // 指定缺省的命名空间。

template<typename T>
void show(const T& invector)
{
	for (auto count = invector.cbegin(); count != invector.cend(); count++)
	{
		cout <<"容器中元素为:"<< *count<< endl;
		
	}
}

int main()
{
    list<string>listname;
    listname.push_back("xiaoming");
    listname.push_back("xiaoli");
    listname.push_back("xiaowang");
    show(listname);    

    vector<string>vec1(3);
    copy(listname.begin(),listname.end(),vec1.begin());
    show(vec1);
    
	return 0;
}

第三题

        std::sort( )与 stdstable sot( )之间的区别在于,后者在排序时保持对象的相对位置不变。由于该应用程序需要按生成顺序存储数据,因此应使用 stable sort(),以保持天体事件的相对顺序不变


第24章 自适应容器:栈和队列

第一题

class Person
{
public:
    int age;
    bool isFemale;
    //重载<运算符,用于判断传入对象的年龄和性别
    bool operator< (const Person& anotherperson) const
    {
        bool bret = false;
        if(age > anotherperson.age)
            bret = true;
        else if(isFemale && anotherperson.isFemale)
            bret = ture;

        return bret;
    }
};

第二题

    string str;
	cout << "输入字符串"<<endl;
	cin >> str;
	stack<int>st1;

	for (int i = 0; i < str.length(); i++)
	{
		st1.push(name[i]);
	}

	while (st1.size() != 0)
	{
		cout <<char( st1.top())<<endl;
		st1.pop();
	}

第25章 使用STL位标志

第一题

#include<bitset>
#include <iostream> 
int main()
{
	bitset<4>fourbits(1);	//初始化四位bitset;初始值0001
	cout << fourbits << endl;

	bitset<4>onefourbits(2);	//初始化四位bitset;初始值0010
	cout << onefourbits << endl;

	bitset<4>addres(fourbits.to_ullong() + onefourbits.to_ullong());
	cout << addres;
	return 0;
}

第二题

#include<bitset>
#include <iostream> 
int main()
{
	bitset<4>fourbits(1);	//初始化四位bitset;初始值0001
	cout << fourbits << endl;

	fourbits.flip();	//按位取反
	cout <<  fourbits << endl;
	return 0;
}


第26章 理解智能指针

第一题

        语句 object ->DoSomething 0有问题,因为指针在复制时失去了对对象的拥有权。这将导致程序崩溃。

第二题

代码类似下述

#include <memory>
#include <iostream>
using namespace std;

class Fish
{
public:
    Fish() {cout << "Fish: Constructed!" << endl;}
    ~Fish() {cout << "Fish: Destructed!" << endl;}

    void Swim() const 
        (cout << "pish swims in water" << endl;)
};

class Carp: public Fish
{
};

void MakeFishSwim(const unique ptr<Fish>& inFish)
{
    inpish->Swim();
}

int main ()
{
    unique ptr<Fish> myCarp (new Carp); // note thisMakeFishSwim(myCarp);
    return 0;
}

        鉴于 MakeFishSwim()接受的参数为引用,不会导致复制,因此不会出现切除问题。另外,请注意变量myCarp的实例化语法。 

        切除问题

        当把一个派生类对象赋给一个基类对象时(用对象创建对象),会发生对象切割。(另外用基类对象强制转换派生类对象也会)。父类引用或指针调用子类重写方法,实际调用结果为父类中方法

        多态的实现是通过指针和引用,对象的转换只能完成对象切割,无法完成多态

#include <iostream>
using namespace std;
//基类
class Base{
public:
	virtual void printError(){ //对象切片无法使用virtual关键字声明虚函数解决
	 cout << "基类方法!" << endl;
	 };
};
//派生类
class Derived : public Base{
public:
	 void printError(){
		cout << "派生类方法!" << endl;
	}
};
void test()
{	
	Base e = Derived(); //对象切片导致子类对象调用基类方法,而不是子类方法
	ex.printError(); //输出基类方法!
}
int main()
{
   test();
   return 0;
}

第三题

        unique_ptr 的复制构造函数和复制赋值运算符都是私有的,因此不允许复制和赋值。


第27章 使用流进行输入和输出

第一题

        在使用流并关闭它之前,需要使用 is_open()检查 open()是否成功

第二题

        不能插入到 ifstream。Ifstream 旨在用于输入,而不是输出,因此不支持流插入运算符<<。


第28章 异常处理

第一题

        绝不要在析构函数中引发异常。

第二题

        没有处理代码可能引发的异常,即缺少 ty...catch 块。

第三题

        绝不要在 catch 块中分配内存。如果 try 块内的代码分配内存失败,将导致恶性循环。

  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值