mk-mode BLOG

このブログは自作の自宅サーバに構築した Debian GNU/Linux で運用しています。
PC・サーバ構築等の話題を中心に公開しております。(クローンサイト: GitHub Pages

ブログ開設日2009-01-05
サーバ連続稼働時間
Reading...
Page View 合計
Reading...
今日
Reading...
昨日
Reading...

C++ - UTF-8 文字列から部分文字列を抽出!

[ プログラミング ] [ C言語 ]

こんばんは。

C++ で UTF-8 の文字列から部分文字列を抽出する方法についての記録です。
前回の「C++ - UTF-8 文字列の文字数をカウント!」の応用です。

(C++ にそれほど精通している訳でもありません。ご承知おきください)

0. 前提条件

  • Linux Mint 17 での作業を想定。
  • g++(c++) のバージョンは 4.8.2

1. UTF-8 について

UTF-8 について詳細に説明はしないが、UTF-8 の仕様では1バイト目の先頭からの連続するビット数(1 となっているビットの連続数)で1文字のバイト数が決まるということを理解しておく。
さらに、このことから以下のように定義されていることも理解しておく。(参照・ RFC 3629

  • 1バイト目: 0x00 〜 0x7f → 1 バイト
  • 1バイト目: 0xc2 〜 0xdf → 2 バイト
  • 1バイト目: 0xe0 〜 0xef → 3 バイト
  • 1バイト目: 0xf0 〜 0xf7 → 4 バイト
  • 1バイト目: 0xf8 〜 0xfb → 5 バイト
  • 1バイト目: 0xfc 〜 0xfd → 6 バイト

2. C++ ソースコード作成

実際には、5、6バイトの文字は使用しないかも知れないが、実装しておいた。
また、当てはまらない文字があれば、それは0バイトで計算するようにしている。

SubStrUtf8.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <string.h>

using namespace std;

/*
 * [CLASS] Proc
 */
class Proc
{
    int cntByte(unsigned char);           // Count bytes

public:
    char* subStr(const char*, int, int);  // Get substring
};

/*
 * Get substring
 */
char* Proc::subStr(const char *cStr, int iStart, int iLength)
{
    static char cRes[1024];
    char* pRes = cRes;
    int i = 0, iPos = 0;
    int iByte;

    while (cStr[i] != '\0') {
        iByte = cntByte(cStr[i]);
        if (iStart <= iPos && iPos < iStart + iLength) {
            memcpy(pRes, (cStr + i), iByte);
            pRes += iByte;
        }
        i += iByte;
        iPos++;
    }
    *pRes = '\0';

    return cRes;
}

/*
 * Count bytes
 */
int Proc::cntByte(unsigned char cChar)
{
   int iByte;

   if ((cChar >= 0x00) && (cChar <= 0x7f)) {
       iByte = 1;
   } else if ((cChar >= 0xc2) && (cChar <= 0xdf)) {
       iByte = 2;
   } else if ((cChar >= 0xe0) && (cChar <= 0xef)) {
       iByte = 3;
   } else if ((cChar >= 0xf0) && (cChar <= 0xf7)) {
       iByte = 4;
   } else if ((cChar >= 0xf8) && (cChar <= 0xfb)) {
       iByte = 5;
   } else if ((cChar >= 0xfc) && (cChar <= 0xfd)) {
       iByte = 6;
   } else {
       iByte = 0;
   }

   return iByte;
}

/*
 * Execution
 */
int main(){
    const char* cStr = "コレハ 部分文字列取得の TEST です。";
    char* cRes;

    try {
        Proc objMain;
        cRes = objMain.subStr(cStr, 2, 13);
        cout << "* " << cStr << "\n"
             << "  => " << cRes << endl;
    } catch (const char* e) {
        cerr << "[EXCEPTION] " << e << endl;
        return 1;
    }
    return 0;
}

3. コンパイル

作成した C++ ソースコードをコンパイルする。

1
# g++ -Wall -O2 -o SubStrUtf8 SubStrUtf8.cpp

何も出力されなければ成功。

4. 動作確認

以下のようにして実行してみる。
指定位置・長さの部分文字列が抽出されることを確認する。

1
2
* コレハ 部分文字列取得の TEST です。
  => ハ 部分文字列取得の TE

5. 参考サイト


C, C++ 等で文字列を多用する場合に役立ちそうな話題でした。

以上。

Comments