发现答案资源不全,因此贴出自己的解答,都为STL应用基础题,如有谬误,还请不吝赐教。
第一题
要求:回文字符串判断(假定字符串中没有大小写、空格、标点符号等问题)
解答:
#include<iostream> #include<string> #include<ctype> #include<algorithm> int main(void) { using namespace std; string input; bool isPal(string); string tmp = ""; cout << "Enter a string(empty string to quit):"; while (getline(cin,input) && input.size() > 0) { if (isPal(tmp)) cout << "It's a palindrome." << endl; else { cout << "It isn't a palindrome" << endl; } cout << "Enter a string(empty string to quit):"; } } bool isPal(std::string s) { std::string r(s.rbegin(), s.rend()); if (r == s) return true; else return false; }
第二题
要求:第一题拓展,加上输入字符串中有大小写、空格和标点符号的情况,程序需要将这些忽略掉
解答:
#include<iostream> #include<string> #include<ctype> #include<algorithm> int main(void) { using namespace std; string input; bool isPal(string); string tmp = ""; cout << "Enter a string(empty string to quit):"; while (getline(cin,input) && input.size() > 0) { for (auto e : input) { if (isalpha(e)) tmp.push_back(tolower(e)); } if (isPal(tmp)) cout << "It's a palindrome." << endl; else { cout << "It isn't a palindrome" << endl; } cout << "Enter a string(empty string to quit):"; } } bool isPal(std::string s) { std::string r(s.rbegin(), s.rend()); if (r == s) return true; else return false; }
第三题
要求:从文件中读取单词,利用vector存储并输出到屏幕上,并打印个数
解答:
1.在.cpp文件目录下新建text文件“data.txt”,打开编辑并保存如下内容:
apiary beetle cereal danger ensign florid garage health insult jackal keeper loaner manage nonce onset
plaid quilt remote stolid train useful valid whence xenon yearn zippy2.
#include<iostream> #include<iterator> #include<fstream> #include<string> #include<vector> int main() { using namespace std; ifstream fin("data.txt"); string input; vector<string>v1; while (fin >> input) { v1.push_back(input); } copy(v1.begin(), v1.end(), ostream_iterator<string, char>(cout, " "));//打印单词 cout << endl << "共计" << v1.size() << "个单词"; fin.close(); cout << endl; system("pause"); return 0; }
第四题
要求:编写一个具有老式风格的接口函数,原型如下
int reduce(long ar[], int n);
实参应是数组名和数组元素个数,该函数对数组进行排序,删除重复值,返回缩减后数组中的元素数目。用STL函数编写。
解答:
#include<iostream> #include<list> #include<iterator> int main() { using namespace std; int reduce(long[], int); long arr[] = { 1,4500,3120, 2791, 3200, 14, 560, 14, 3120, 3200, 3200, 3200 };//测试数组 cout << "调用reduce前,数组元素依次如下" << endl; for (long e : arr) { cout << e << " "; } int count = sizeof(arr) / sizeof(long); cout << endl << "共有" << count << "个元素" << endl; count = reduce(arr, count); cout << "调用reduce后,数组元素依次如下" << endl; for (int i = 0; i < count; i++) { cout << arr[i] << " "; } cout << endl << "共有" << count << "个元素" << endl; cout << endl; system("pause"); return 0; } int reduce(long arr[], int n) { std::list<long> myList; std::copy(arr, arr + n, std::back_insert_iterator<std::list<long>>(myList)); myList.sort(); myList.unique(); int i = 0; for (long e : myList) { arr[i++] = e; } return myList.size(); }
第五题
要求:与第四题相同,但要编写的是模板函数,并用long实例和string实例测试
解答:
#include<iostream> #include<list> #include<iterator> #include<string> template<typename T> void out(T arr[],int n);//因为long和string对象均可用cout打印,因此这里简化代码也用了模板 template <typename T> int reduce(T arr[], int n); using namespace std; int main() { long arr[] = { 1,4500,3120, 2791, 3200, 14, 560, 14, 3120, 3200, 3200, 3200 };//测试数组 string arr2[] = { "haha", "heihei", "hehe", "haha", "haha", "heihei" }; out(arr,sizeof(arr)/sizeof(long)); out(arr2, sizeof(arr2) / sizeof(string)); cout << endl; system("pause"); return 0; } template<typename T> void out(T arr[],int n) { cout << "调用reduce前,数组元素依次如下" << endl; int count = n; for (int i = 0; i < count; i++) { cout << arr[i] << " "; } cout << endl << "共有" << count << "个元素" << endl; count = reduce(arr, count); cout << "调用reduce后,数组元素依次如下" << endl; for (int i = 0; i < count; i++) { cout << arr[i] << " "; } cout << endl << "共有" << count << "个元素" << endl; } template <typename T> int reduce(T arr[], int n) { std::list<T> myList; std::copy(arr, arr + n, std::back_insert_iterator<std::list<T>>(myList)); myList.sort(); myList.unique(); int i = 0; for (T e : myList) { arr[i++] = e; } return myList.size(); }
第六题
要求:用STL模板类queue实现ATM模拟,允许用户输入三个数:队列的最大长度、程序模拟的持续时间(单位为小时)和平均每小时的客户数。程序使用循环,每次循环代表一分钟。在每分钟的循环中,程序将完成下面的工作:
- 判断是否来了新客户。如果来了,且此时队列未满,则将它添加到队列中,否则拒绝客户入队;
- 如果没有客户在进行交易,则选取队列的第一个客户。确定该客户的已等候时间,并将waitTime计数器设置为新客户所需的处理时间。
- 如果客户正在处理中, 则将waitTime计数器减1.
- 记录各种数据,如获得服务的客户数目、被拒绝的客户数目、排队等候的累积时间以及累积的队列长度等。
当模拟循环结束时, 程序将报告各种统计结果。
解答:
为了更多地利用STL,并完成一个稍完整的ATM小系统,这里把本题复杂化,写得比较多
//---ATM.h #pragma once #include<ctime> #include<queue> #include<vector> using namespace std; //尽管这里其实没必要数据封装以及继承,但为了迎合OOP思想,还是写个类吧 class ATM { private: int maxLength; time_t startTime; double duration; int averageClientNum; queue<time_t> line; vector<time_t> comeTime; int currentLeftTime = 0; double totalWaitingTime = 0; int totalLineLength = 0; int currentClientNum = 0; int rejectClientNum = 0; void circle(); void createComeTime(); bool isCome(); bool isFull(); void enter(); void reject(); void deal(); int getDealTime(); time_t getWaitingTime(time_t before); int getCurrentClientNum(); int getRejectClientNum(); double getTotalWaitingTime(); int getTotalLineLength(); void over(); public: ATM(int maxL = 3, double dur = 24, int aver = 40) :maxLength(maxL), duration(dur), averageClientNum(aver) {}; void work(); };
//--ATP.cpp #include "ATM.h" #include<iostream> #include<ctime> #include<queue> #include<vector> #include<Windows.h> using namespace std; #define MAXDEALTIME 5 void ATM::over() { cout << "------------------" << endl; cout << "当前统计结果如下" << endl; cout << "------------------" << endl; cout << "获得服务的客户数目:" << getCurrentClientNum() << endl; cout << "被拒绝的的客户数目:" << getRejectClientNum() << endl; cout << "排队等候的累积时间:" << getTotalWaitingTime() << endl; cout << "累积的队列长度:" << getTotalLineLength() << endl; } void ATM::work() { //这方便测试,假设一小时是一分钟;一分钟是一秒; startTime = time(0); double minutes = 60 * duration; createComeTime(); cout << "ATM开始运行" << endl; while (static_cast<double>(time(0) - startTime) <= minutes) { Sleep(1000); circle(); } cout << "时间到,ATM运行结束" << endl; } void ATM::circle() { cout << "---------------------------------------------------------------------" << endl; if (isCome()) { if (isFull()) { cout << "当前队列已满" << endl; reject(); } else { enter(); if (currentLeftTime == 0) { deal(); currentLeftTime = getDealTime(); } } } else { cout << "没有客户前来" << endl; } if (currentLeftTime > 0) { currentLeftTime--; cout << "当前客户交易剩余时间为" << currentLeftTime << endl; if(currentLeftTime == 0) cout << "当前客户交易结束" << endl; } over(); cout << "本轮循环结束" << endl; cout << "---------------------------------------------------------------------" << endl; } void ATM::createComeTime() { srand(time(NULL)); int totalClientNum = duration * averageClientNum; time_t cometime; for (int i = 0; i < totalClientNum; i++) { cometime = (rand() % static_cast<long>(60 * duration-1)) + startTime+1; comeTime.push_back(cometime); } sort(comeTime.begin(), comeTime.end()); } bool ATM::isCome() { time_t currentTime = time(NULL); if (comeTime.size() > 0 && comeTime.front() <= currentTime) return true; return false; } bool ATM::isFull() { if (line.size() >= maxLength) return true; return false; } void ATM::enter() { line.push(comeTime.front()); double waitingTime =static_cast<double>(getWaitingTime(comeTime.front())); totalWaitingTime += waitingTime; cout << "新客户已入队,他已等候时间为" << waitingTime << endl; totalLineLength++; } void ATM::reject() { cout << "入队请求被拒" << endl; comeTime.erase(comeTime.begin()); rejectClientNum++; } void ATM::deal() { totalWaitingTime += static_cast<double>(time(NULL) - line.front()); line.pop(); cout << "当前客户交易开始" << endl; comeTime.erase(comeTime.begin()); currentClientNum++; } int ATM::getDealTime() { return rand() % MAXDEALTIME+1; } time_t ATM::getWaitingTime(time_t before) { return time(NULL) - before; } int ATM::getCurrentClientNum() { return currentClientNum; } int ATM::getRejectClientNum() { return rejectClientNum; } double ATM::getTotalWaitingTime() { return totalWaitingTime; } int ATM::getTotalLineLength() { return totalLineLength; }
//--main.cpp #include"ATM.h" int main(void) { using namespace std; int maxLength, averageClientNum; double duration; cout << "请输入队列最大长度:"; cin >> maxLength; cout << "请输入程序模拟的持续时间(单位为小时):"; cin >> duration; cout << "请输入平均每小时的客户数:"; cin >> averageClientNum; ATM atm1(maxLength, duration, averageClientNum); atm1.work(); cout << endl; system("pause"); return 0; }
第七题
使用了random_shuffle,用法陈旧因此弃掉
第八题
题目:
Mat和Pat希望邀请他们的朋友来参加派对。他们分别输入自己的朋友姓名列表,然后将两人的朋友姓名列表合并,得到不重复的被邀请者名单。
解答:
分析后可知,采用STLset容器极其相关算法最为简单,也就是求并集的过程,但注意set_union同copy一样,最后的一个参数要求输出迭代器且被输出容器容量足够,不能用C.begin(),因此采用insert_iterator构造输出迭代器
#include<iostream> #include<iterator> #include<set> #include<vector> #include<algorithm> #include<string> int main(void) { using namespace std; void input(string, set<string>&); set<string>nameList1, nameList2, nameList3; input("Mat", nameList1); input("Pat", nameList2); set_union(nameList1.begin(), nameList1.end(), nameList2.begin(), nameList2.end(), insert_iterator<set<string>>(nameList3, nameList3.begin())); cout << "最终得出的邀请名单如下:" << endl; for (string e : nameList3) { cout << e << endl; } cout << endl; system("pause"); return 0; } void input(std::string name, std::set<std::string>& s) { std::cout << "请输入" << name << "的朋友名单(以空格分隔,回车结束):"; std::string tmp; std::vector<std::string> v; while (std::cin >> tmp) { v.push_back(tmp); if (std::cin.get() == '\n') break; } std::copy(v.begin(), v.end(), std::insert_iterator<std::set<std::string>>(s,s.begin())); }
第九题
要求:利用ctime中的clock()和STL完成下列目的
- 创建大型vector<int>对象vi0, 并使用rand()给它赋初值;
- 创建vector<int>对象vi和list<int>对象li, 它们的长度和初始值与vi0相同;
- 计算使用STL算法sort()对vi进行排序所需的时间,再计算使用list的方法sor()对li进行排序所需的时间。
- 将li重置为排序的vi0内容,并计算执行如下操作所需的时间:将li的内容复制到vi中,对vi进行排序,并将结果复制到li中。
解答:
#include<iostream> #include<vector> #include<algorithm> #include<ctime> #include<random> #include<list> #include<iterator> using namespace std; clock_t getTime(list<int>&li); clock_t getTime(vector<int>&vi); clock_t getTime(list<int>&li, vector<int>&vi); void copy2(list<int>& li, vector<int>&vi); int main(void) { int getRandom(int e); vector<int>vi0(1000); vector<int>vi; list<int>li; random_device dev; uniform_int_distribution<int> dist(-100, 100); for (auto &e : vi0) { e = dist(dev); } copy(vi0.begin(), vi0.end(), insert_iterator<vector<int>>(vi, vi.begin())); copy(vi0.begin(), vi0.end(), insert_iterator<list<int>>(li, li.begin())); cout << "初始化完成" << endl; cout << "使用sort()对vi进行排序所需的时间为:" << getTime(vi) << endl; cout << "使用li.sort()对li进行排序所需的时间为:" << getTime(li) << endl; cout << "先将li拷贝到vi在对vi使用STL sort()排序后再拷贝会li所需的时间为:" << getTime(li,vi) << endl; cout << endl; system("pause"); return 0; } clock_t getTime(list<int>&li) { clock_t start = clock(); li.sort(); return clock() - start; } clock_t getTime(vector<int>&vi) { clock_t start = clock(); sort(vi.begin(),vi.end()); return clock() - start; } clock_t getTime(list<int>&li, vector<int>&vi){ clock_t start = clock(); copy2(li, vi); return clock() - start; } void copy2(list<int> &li, vector<int> &vi) { vi.clear(); for (int e : li) { vi.push_back(e); } sort(vi.begin(), vi.end()); li.clear(); for (int e : vi) { li.push_back(e); } }
第十题
原题没意思,这里我加以改编题目拓展了一下。
要求:实现一个书单相关功能,使其能够实现如下功能(使用vector<shared_ptr<Review>>存储书籍信息)
- 按原始顺序显示
- 按字母表顺序显示
- 按评级升序显示
- 按评级降序显示
- 按价格升序显示
- 按价格降序显示
- 退出
假设书单内容为如下:
- Harry Potter and the Goblet of Fire 9 ¥68.5
- To Kill a Mockingbird 7 ¥78
- Pride and Prejudice 8 ¥70.50
- Fifty Shades of Grey 5 ¥71
- Great Expectations 7 ¥ 45
解答:
#include<iostream> #include<vector> #include<memory> #include<string> #include<algorithm> #include<iterator> using namespace std; typedef struct Review { string name; int rate; double price; }Review; class BookList { private: vector<shared_ptr<Review>> books; static bool cmpByAlpha(shared_ptr<Review> first, shared_ptr<Review> second); static bool cmpByRate(shared_ptr<Review> first, shared_ptr<Review> second); static bool cmpByPrice(shared_ptr<Review> first, shared_ptr<Review> second); void out(vector<shared_ptr<Review>> b = {}); public: BookList(vector<shared_ptr<Review>> &arr); void outByInit(); void outByAlpha(bool sequence = true); void outByRate(bool sequence = true); void outByPrice(bool sequence = true); }; bool BookList::cmpByAlpha(shared_ptr<Review> first, shared_ptr<Review> second) { if(first->name >= second->name) return false; return true; } bool BookList::cmpByRate(shared_ptr<Review> first, shared_ptr<Review> second) { if (first->rate >= second->rate) return false; else return true; } bool BookList::cmpByPrice(shared_ptr<Review> first, shared_ptr<Review> second) { if (first->price >= second->price) return false; else return true; } void BookList::out(vector<shared_ptr<Review>> b) { if (b.size() == 0) b = books; for (auto e : b) { cout << "-----------------------------" << endl; cout << "name: " << e->name << endl; cout << "rate: " << e->rate << endl; cout << "price: ¥" << e->price << endl; cout << "-----------------------------" << endl << endl; } } BookList::BookList(vector<shared_ptr<Review>> &arr) { for (auto e : arr) { books.push_back(e); } } void BookList::outByInit() { cout << "按原序输出如下" << endl; out(); } void BookList::outByAlpha(bool sequence) { vector<shared_ptr<Review>> books2; copy(books.begin(), books.end(), insert_iterator<vector<shared_ptr<Review>>>(books2, books2.begin())); if (sequence) { cout << "按字母升序输出如下" << endl; sort(books2.begin(), books2.end(), BookList::cmpByAlpha); } else { cout << "按字母降序输出如下" << endl; sort(books2.rbegin(), books2.rend(), BookList::cmpByAlpha); } out(books2); } void BookList::outByRate(bool sequence) { vector<shared_ptr<Review>> books2; copy(books.begin(), books.end(), insert_iterator<vector<shared_ptr<Review>>>(books2, books2.begin())); if (sequence) { cout << "按评级升序输出如下" << endl; sort(books2.begin(), books2.end(), BookList::cmpByRate); } else { cout << "按评级降序输出如下" << endl; sort(books2.rbegin(), books2.rend(), BookList::cmpByRate); } out(books2); } void BookList::outByPrice(bool sequence) { vector<shared_ptr<Review>> books2; copy(books.begin(), books.end(), insert_iterator<vector<shared_ptr<Review>>>(books2, books2.begin())); if (sequence) { cout << "按价格升序输出如下" << endl; sort(books2.begin(), books2.end(), cmpByPrice); } else { cout << "按价格降序输出如下" << endl; sort(books2.rbegin(), books2.rend(), cmpByPrice); } out(books2); } int main(void) { int showMenu(); vector<shared_ptr<Review>> arr = { shared_ptr<Review>(new Review{"Harry Potter and the Goblet of Fire",9,68.5}), shared_ptr<Review>(new Review{"To Kill a Mockingbird", 7, 70.50}), shared_ptr<Review>(new Review{"Pride and Prejudice", 8, 70.50}), shared_ptr<Review>(new Review{" Fifty Shades of Grey", 5, 71.0}), shared_ptr<Review>(new Review{"Great Expectations", 7, 45.0}), }; BookList list1(arr); int option; while ((option = showMenu()) != 0) { switch (option) { default: continue; break; case 1: list1.outByInit(); break; case 2: list1.outByAlpha(); break; case 3: list1.outByAlpha(false); break; case 4: list1.outByRate(); break; case 5: list1.outByRate(false); break; case 6: list1.outByPrice(); break; case 7: list1.outByPrice(false); break; } system("pause"); system("cls"); } cout << endl; system("pause"); return 0; } int showMenu() { cout << "本程序是一个书单打印程序,请输入整数0-7选择打印方式" << endl; cout << "1.按原序打印;" << endl; cout << "2.按字母升序打印;" << endl; cout << "3.按字母降序打印;" << endl; cout << "4.按评级升序打印;" << endl; cout << "5.按评级降序打印;" << endl; cout << "6.按价格升序打印;" << endl; cout << "7.按价格降序打印;" << endl; cout << "0.退出;" << endl; int input; cin >> input; return input; }
这里尤其注意一个点,自定义的谓词函数不能是稳定的,因为sort()非稳定算法。所以应是当">="时返回顺序错误(false),而写“>”会报错。