在不斷學習 C++ 的過程中, 終於學到了自己之前完全沒有接觸過的容器和泛型演算法. 因為之前沒有寫過相類似的程式碼, 所以毅然決定找點事情幹
於是根據《C++ Primer》 中的演示, 給自己出了一個問題 :
1. 宣告一個陣列, 從陣列中隨機選取單詞寫入容器
2. 刪除掉容器中重複出現的部分
3. 按照長度和字典順序進行排序
4. 找出長度大於 4 的單詞並輸出
根據概述, 我們會用到如下 C++ 語法
- 容器
- 隨機數
- 迴圈與判斷
- I/O 資料流
- 標準庫演算法
- bind() 函式
- lambda 表達式
- 函式
首先, 我們創建一個陣列, 這個陣列裡有隨機的單詞, 這些單詞長度不一. 接下來需要調用隨機演算法來隨機獲取其中的單詞, 並且放入一個容器中並且輸出一次. 之後需要對容器進行一次排序, 這次排序只需要按照字典順序就可以了, 這是為了之後標準庫演算法做準備. 然後就可以重新進行排序了, 這次不算是真正的排序, 因為只是將重複的單詞放到容器的後面. 放到後面之後, 我們需要將這些重複的元素刪除掉並且再次進行排序. 這次排序與上次排序有些不同, 因為這次首先要按照單詞的長度進行排序, 長度相同的情況下才進行字典排序. 在這之後, 我們需要找出容器中第一個出現的長度大於規定長度的單詞, 但是我們需要的是疊代器, 而不是序列中的註標. 統計之後, 輸出相關的交互信息. 最後將容器的全部元素進行一次輸出, 看看結果是否正確就可以了
不過我們需要注意的是, 一些操作要用到多次的, 例如輸出, 可以將其寫成一個函式重複呼叫
以下是我所寫的實戰程式碼, 對於每一步都有詳細的輸出, 並且基本上每一步也都有非常詳盡的註解
大家可以作為參考. 不過最重要的就是自己實戰, 因為沒有實戰, 你永遠都只能是原地踏步
#include <iostream>
#include <array>
#include <vector>
#include <random>
using namespace std;
using std::placeholders::_1;
/* Print all elements of the container by using ostream.
* The T must be a container and there are the functions cbegin() and cend() in the container. */
template <typename T>
inline void out(T &_t, ostream &os) {
for_each(_t.cbegin(), _t.cend(), [&os](const string &str) -> void {
os << str << "\t";
});
os << endl;
}
/* Used to print the situation such as 1 apple or 2 and more apples.
* It is needed that the T should support addition. */
template <typename T>
inline void outString(unsigned count, const T &cmp1, const T &cmp2, ostream &os) {
if(count == 1) {
os << cmp1;
}else {
os << cmp1 + cmp2;
}
}
int main(int argc, char *argv[]) {
const array<const char *, 5> stringArray {"bool", "do", "int", "signed", "typename"};
uniform_int_distribution<unsigned> u(0, 4); //Use the normal distribution.
default_random_engine e((unsigned)time(nullptr)); //Initializte the random engine.
vector<string> stringVector;
for(auto i {0}; i < 10; i++) {
auto r {u(e)}; //Yield the random number.
stringVector.emplace_back(stringArray[r]);
}
out(stringVector, cout); //Print the vector after creating.
sort(stringVector.begin(), stringVector.end()); //Sort the vector by the order of dictionary.
out(stringVector, cout); //Print the vector after sorting.
auto uni {unique(stringVector.begin(), stringVector.end())}; //Put the repeated words in the last of vector, and get the first repeated word's iterator.
out(stringVector, cout); //Print after putting.
stringVector.erase(uni, stringVector.end()); //Delete the repeated words from the vector.
out(stringVector, cout); //Print the vector after deleting.
stable_sort(stringVector.begin(), stringVector.end(), [](const string &a, const string &b) -> bool {
return a.size() < b.size();
}); //Sort by the words' length firstly, then sort by the order of dictionary.
out(stringVector, cout); //Print after sorting.
constexpr vector<string>::size_type size {4}; //Declare the size by constexpr and vector<string>::size_type.
auto it {find_if(stringVector.begin(), stringVector.end(), bind([](const string &str, vector<string>::size_type size) -> bool {
return str.size() >= size;
}, _1, size))}; //Get the iterator of the first word whose length is more than size.
/* Test module */
auto count {stringVector.end() - it}; //Get the distance between the iterators.
/** Test the type of count that whether the type is vector<string>:difference_type or not. **/
if(typeid(count) == typeid(vector<string>::difference_type)) {
cout << "OK" << endl;
}
/* Print the information of the vector. */
cout << count << " ";
outString(static_cast<unsigned>(count), string("word"), string("s"), cout);
cout << " of length " << size << " or longer : " << endl;
/** Print the words that length is more than size. **/
for_each(it, stringVector.end(), [](const string &str) -> void {
cout << str << endl;
});
cout << endl;
}
這是運行一次之後的結果, 因為包含隨機演算法, 所以每次的結果都可能會有些不同 :

自創文章, 原著 : Jonny, 如若需要轉發, 在已經授權的情況下請註明出處 :《【C++ 實戰】I/O、容器與泛型演算法》https://jonny.vip/2018/03/24/%e3%80%90cplusplus-%e5%af%a6%e6%88%b0%e3%80%91io-%e5%ae%b9%e5%99%a8%e8%88%87%e6%a8%99%e6%ba%96%e5%ba%ab%e6%bc%94%e7%ae%97%e6%b3%95/
Leave a Reply