C++で配列の中身を以下のように初期化したい場合があります。
#include <iostream> #include <array> using namespace std; int main() { array<int , 10> arr; //配列の値を「0,1,2,...,N」と初期化 int i = 0; for(auto& val : arr) { val = i++; } for(const auto val : arr) { cout << val << endl; } return 0; }
もちろん、この書き方でも問題ありませんが、便利な関数としてiota(※itoaじゃないです)というものが実装されました。
#include <iostream> #include <array> #include <numeric> using namespace std; int main() { array<int , 10> arr; //配列の値を「0,1,2,...,N」と初期化 iota(arr.begin(), arr.end(), 0); for(const auto val : arr) { cout << val << endl; } return 0; }
引数はそれぞれ、
・第一引数 シーケンス先頭
・第二引数 シーケンス終端
・第三引数 初期化の最初の値
となっています。つまり、第三引数に渡した値を始めとして、そこから順番に「+1」していった値を配列に代入しています。
他の例として、以下のように文字のA~Zまでを順番に入れるということもできます。
#include <iostream> #include <array> #include <numeric> using namespace std; int main() { array<char , 26> arr; //配列の値を「A,B,C,...,Z」と初期化 iota(arr.begin(), arr.end(), 'A'); for(const auto val : arr) { cout << val << endl; } return 0; }
今回のように、「0,1,2,...,N」と値が入った配列はその値を長さNの配列の添字として利用することが出来ます。
次にshuffleについて説明します。さっきのiotaによって生成した「0,1,2,...,N」という値を配列の添字に使えると言いましたが、順番にではなく、ランダムな添字で配列にアクセスしたいうことがあります。そのような場合に使えるのがshuffle関数です。
#include <iostream> #include <array> #include <numeric> #include <algorithm> #include <random> using namespace std; int main() { array<int , 10> arr; //配列の値を「0,1,2,...,N」と初期化 iota(arr.begin(), arr.end(), 0); for(const auto val : arr) { cout << val << ' '; } cout << endl; //random_deviceによるランダムに並び替え shuffle(arr.begin(), arr.end(), random_device{}); for(const auto val : arr) { cout << val << ' '; } cout << endl; return 0; }
shuffle関数の引数は
・第一引数 シーケンス先頭
・第二引数 シーケンス終端
・第三引数 乱数生成の種類
となっています。第三引数は、C++11講座10回で説明した乱数生成の種類(mt19937等)を指定してあげればいいです。
※実は、前からrandom_shuffleという同様の機能の関数はあったが、乱数の生成が標準のrandを採用していたため精度が悪い問題がありました。(ちなみに、rand、srand、random_shuffleなどはC++14で非推奨になったらしいです。)