通常のASCII文字列であれば
string str = "ABCDE"; cout << str.at( 0 );
というふうにstringのat()関数を使えば指定したインデックスの1文字が取得できます。
正確には、at()関数で取得できるのは指定したインデックスの1バイトであるため、2バイト文字や3バイト文字を含む日本語文字列( UTF-8 )を分割しようとすると、困ったことに本来2バイトや3バイトで一文字になっているものも容赦なく1バイトずつに分割されてしまいます。
そこで、ここ( UTF8エンコードをデコードする )を参考にして、
一度at()関数で1バイトずつ分割
▼
UTF-8での1バイトごとのビットパターンを識別
▼
2~3バイト文字の場合は連結して1文字に
▼
string型のvectorに連結した文字を追加
という手順で実装しました。
ofApp.h
class ofApp : public ofBaseApp
{
public:
void setup();
vector< string > separateUTF8String( string _srcStr );
string srcStr;
};
ofApp.cpp
void ofApp::setup()
{
srcStr = "はろーわーるど!Hello, world!";
vector< string > letters_uc = separateUTF8String( srcStr );
for( string s : letters_uc )
{
cout << s << endl;
}
}
vector< string > ofApp::separateUTF8String( string _srcStr )
{
vector< string > letters;
for( int i = 0; i < _srcStr.length(); ++i )
{
string bin_str = ofToBinary( _srcStr.at( i ) );
// 1 byte character
if( bin_str.find( "0" ) == 0 )
{
letters.push_back( ofToString( _srcStr.at( i ) ) );
}
// 2 byte character
else if( bin_str.find( "110" ) == 0 )
{
letters.push_back( ofToString( _srcStr.at( i ) ) + ofToString( _srcStr.at( i + 1 ) ) );
}
// 3 byte character
else if( bin_str.find( "1110" ) == 0 )
{
letters.push_back( ofToString( _srcStr.at( i ) ) + ofToString( _srcStr.at( i + 1 ) ) + ofToString( _srcStr.at( i + 2 ) ) );
}
// continue byte ( second or later byte )
else if( bin_str.find( "10" ) == 0 )
{
}
}
return letters;
}
実行結果
は
ろ
ー
わ
ー
る
ど
!
H
e
l
l
o
,w
o
r
l
d
!