javascript magazine

主にjavascriptについて書こうと思っています。

c++で始点と終点を指定して文字列を切り取る

c++で始点と終点を指定して文字列を切り取る方法です。

stringのメンバ関数substrを使います。

substrの定義

basic_string substr(size_type pos = 0, size_type n = npos) const;

第1引数に始点を第2引数に終点を入れます。 終点が文字列の長さをオーバーしても最大サイズが返却されます。

// 始点からある位置までを切るとる例
string str = "aaaaaaaaaab";
printf("%s",str.substr(0,10).c_str());
// aaaaaaaaaa
// 終点がオーバーしていても例外は吐かれない
printf("%s",str.substr(0,100).c_str());
// aaaaaaaaaab

引数を1つにした場合は、それ以降の文字列が返されます。

string str = "aaaaaaaaaab";
printf("%s",str.substr(0,1).c_str());
// aaaaaaaaab

イテレーターに関して概念をまとめる

今までイテレータに関して概念はなんとなくわかっていましたが、

説明しろと言われてもちゃんとした説明ができそうになかったので、

まとめます。

イテレータ(反復子)とは

コンテナに対して反復処理を行うためのオブジェクトのことで、

イテレータはあるコンテナの特定の要素を表す。

 

イテレータの特徴として、どの種類のコンテナ要素でも同じ文法で

要素にアクセスできることが挙げられる。

 

これで、だいたい納得できた。

 

ちなみに反復子とは以下の定義です。

 

反復子は、STL コンテナー内の要素を反復処理し、個々の要素へのアクセスを提供するオブジェクトのこと。

 

引用元

https://msdn.microsoft.com/ja-jp/library/28f7db1d.aspx

 

反復という意味は、自分のイメージとしては、行ったり来たりするイメージですが、
繰り返すという意味だそうです。
まあ行ったり来たりすることも繰り返すことだろうけど、
イメージに違和感がある。

std pairのポインタの理解

pairの配列をクラス内を持つ

pair<bool,int>trump[MAX_TRUMP_NUM];

このpairの配列trumpのgetter関数をpointerで返す

pair<bool,int>*BleDevice::getTrump(){
    return this->trump;
}

これを受け取る時に確保した配列分のメモリが取られると思ったらそうではありませんでした。

pair<bool,int>*partnerTrump;
// 受け取る
partnerTrump = device.second->getTrump();
// 一つ分しかない
int size = sizeof(partnerTrump) / sizeof(pair<bool,int>);
// しかし配列分アクセスできる
for(int i = 0;i < MAX_TRUMP_NUM;++i) {
  partnerTrump[i].second;
}

stackOverFlowを見るとどうやら、サイズをチェックすることはできないらしいです。

stackoverflow.com

c++ 配列初期化あれこれ

c++の配列初期化に関して用途方法をまとめます

固定の要素数を持つ宣言
int number[4];
// sizeofで要素数を調べる
for(int i = 0;i < sizeof(number) / sizeof(number[0]);++i){
  // 代入
  number[i] = i;
}

for(int i = 0;i < 4;++i){
  // アクセス
  cout << number[i];
}
    
初期化時に要素も詰め込む場合
// 要素を指定して初期化する
int number[] = {0,1,2,3}; 

// string版
std::string[] = {"0","1","2","3"};

c++ std::vectorでランダムに並べる

c++のstdは、イテレータ型の変数をランダムに並べる関数があります。 これを使うと、std::vectorなどの要素に対してもランダムに並べることができます。

using namespace std;
vector<int>vec;
vec.push(1);
vec.push(2);
random_shuffle(vec.begin(), vec.end());

これで、いいはずですが、繰り返してみると同じ結果が返って来ます
cでそうだったように

srand(unsigned(time(NULL)));

的なものを利用するしないといけないんじゃないかと思ったら、
第3引数に_RandomNumberGeneratorを入れる必要があるみたいです。
これを入れてみると

auto rng = std::default_random_engine {};
random_shuffle(numbers.begin(), numbers.end(),rng);

しかし、今度は以下のエラーが出てコンパイルが通らない
No matching function for call to object of type 'std::__1::linear_congruential_engine<unsigned int, 48271, 0, 2147483647>
cocos2dxだからだろうか

{
    typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
    difference_type __d = __last - __first;
    if (__d > 1)
    {
        for (--__last; __first < __last; ++__first, --__d)
        {
            // ここ
            difference_type __i = __rand(__d);
            swap(*__first, *(__first + __i));
        }
    }
}    

これを解決する元気が出なかったので、手製のrandom関数を引用して適用しました。

auto seed = std::chrono::system_clock::now().time_since_epoch().count();
shuffle(numbers.begin(), numbers.end(),default_random_engine(seed));