PG日誌

受託系 PG が C# の事を書いています

std::stringの日本語の長さを取得する

C++でstd::stringに日本語が設定されているときに、size(), length()メソッドで文字列長を取得しようとすると日本語の長さが取得できません。中身がマルチバイト可変長 + 特殊ルールという構造になっているようで、1文字が1バイト~6バイトとなっているため中身のバイト数が帰ってきているようです。

なので文字列長の取得方法は、ここに記載されている内容仕様そのものを理解して自分で実装するか、Google検索で"c++ string 日本語 長さ“とか、3rd製のライブラリを利用するなどなど、あると思いますが、どれも割と労力を要するので、こちらを参考に、日本語が入ってるstringの長さを取得するクラスを自作してみます。

クラス定義

StringUtil.hを作成して以下を定義します。

#include <string>

using namespace std;

class StringUtil
{
    static int lenByte(unsigned char c)
    {
        if ((c >= 0x00) && (c <= 0x7f))
        {
            return 1;
        }
        else if ((c >= 0xc2) && (c <= 0xdf))
        {
            return 2;
        }
        else if ((c >= 0xe0) && (c <= 0xef))
        {
            return 3;
        }
        else if ((c >= 0xf0) && (c <= 0xf7))
        {
            return 4;
        }

        return 0;
    }

public:

    static int lenUtf8(std::string &str)
    {
        auto _pstr = str.c_str();

        int i = 0;
        int len = 0;

        while (_pstr[i] != '\0')
        {
            len++;
            i += lenByte(_pstr[i]);
        }

        return len;
    }
};

利用側コード

上記コードをmainから呼び出してみます。

#include <iostream>
#include "StringUtil.h"

int main()
{
    std::string message = u8"abcあいう亞位鵜アイウ123";
    cout << "Len = " << StringUtil::lenByte(message) << endl;

    // Len = 15
}

これで、よくある文字列を処理するくらいなら問題ないかと思います。

さいごに

あくまで簡単な長さの取得なのでグローバルかつセンシティブなプログラムでは他にもいろいろ考えることがありそうです。