13
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

c++でもpythonのstr型のメソッドを使いたい!

Last updated at Posted at 2018-08-21

自分はpythonをよく利用するのですが、pythonは文字列操作が割と強力な印象を受けます(特にスライス)
普段使いのC++でもpythonみたいに文字列操作したい!
ってことでstd::stringを継承したpythonのstr型のメソッドがほとんどそのまま使える文字列クラスを作ってみました。

自分のサイトを開設しより詳しく書き直しました!

https://e-tec-memo.herokuapp.com/article/24/

py_string

使用感的にはstd::stringでpythonのstr型のメソッドが使えるだけですかねw
std::stringを継承しているのでstd::stringで出来ることは全部できます。
シングルヘッダーライブラリにしたのでインクルードするだけですぐに使えます。
名前空間はpyです。

##使い方
###基本形

example.cpp
#include "py_string.hpp"
#include <iostream>

using namespace std;

int main(int argc,char*argv[])
{
  py::string pystr = "hello world!";//py_stringでもpy::stringと同じ

  cout << pystr << endl;
}

std::stringと同じです。
##split

example.cpp
py::string spstr = "12,3,4-2,2";
std::deque<py::string> slist; //std::vectorでもOK

spstr.split(slist, ",",2);
for (auto &&s : slist)
{
    cout << s << endl;
}
//出力
//12
//3
//4-2,2

第一引数はテンプレートを使っているのでpush_backをメンバ関数に持っているcontainerクラスなら何でもいけるはずです。
第二引数を省略するとタブやスペースなどの空白文字で分割されます。
第三引数で分割する最大数を指定できます。分割後の要素数は指定した数+1になります。
std::stringにほしい機能の一つです。そのうち対応してくれないかなぁ...
##format

example.cpp
py::string fstr = "{} is {} than {}";
cout << fstr.format(3,"bigger",1) << endl;
//"3 is bigger than 1."
cout << fstr.format(2,"smaller",4) << endl;
//"2 is smaller than 4."

{}が先頭から順に引数リストで置き換えられます。

##replace

example.cpp
py::string rstr = "1+2-3";
cout << rstr.pyreplace("-","=");
//1+2=3

文字列中に登場する第一引数とマッチするすべての要素が第二引数で置き換えられます。
第三引数に数を渡すと置き換える最大数を指定できます。
※std::stringのreplaceと違って自身が置き換わるのではなく置換後の文字列が返ります。

##slice
添字演算子[]がc++の制約で一つしか引数が取れなかったので初期化リストっぽい書き方で対応することにしました。

example.cpp

pystr[{0,5}];
//hello

若干書きづらいですが許容範囲内かな?

slice.py

string[0:3]
string[3:]
string[::-1]

上記のコードに相当する書き方は

slice.cpp
string[{0,3}];
string[{3,nullptr}];
string[{nullptr,nullptr,-1}];

です。
コロンだけはnullptrで代用することにしました。
この書き方が気持ち悪いと感じる人は、

slice.cpp
string.slice(0,3);
string.slice(3,nullptr);
string.slice(nullptr,nullptr,-1);

といったようにメンバ関数の形でも同じように呼び出せます。

##添字演算子[]

example.cpp
py::string astr = "0123456789";
cout << astr[0] << endl;
// 0
cout << astr[-1] << endl; //一番最後の要素
// 9
cout << astr[-3] << endl; //後ろから三番目の要素
// 7

添字演算子をオーバーライドして負の数を利用して後ろからのアクセスもできるようにしました。代入も可能です。
atでも同じことができるようにしてあります。

##その他
一部のstd::stringと名前が被るかつオーバーロード解決ができないメソッドにはpy~って感じの名前をつけています。

それぞれのメソッドの動作は
https://docs.python.org/ja/3/library/stdtypes.html#string-methods
を参照してください。

言語機能的に実装が難しい、あるいは私の技能不足で実装しきれていないメソッドも少しあります。
※pythonではエラーを送出するメソッド(e.g. indexなど)はエラーを送出しないようにしています。

今後もできるものは実装していきたいので、
もし「これできるよ!」とか「こっちのほうが効率的じゃない?」みたいなのがあれば是非プルリクください。
エラー報告もしてもらえると助かります。issue、pull request等

13
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?