在不斷學習 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;
}

這是運行一次之後的結果, 因為包含隨機演算法, 所以每次的結果都可能會有些不同 :

【C++ 實戰】I/O、容器與泛型演算法-Jonny'Blog