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++ にそれほど精通している訳でもありません。ご承知おきください)

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バイトで計算するようにしている。

CntStrUtf8.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
#include <iostream>
#include <string.h>

using namespace std;

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

public:
    int cntStr(const char*);     // Count stings
};

/*
 * Count strings
 */
int Proc::cntStr(const char *cStr)
{
   int i = 0, iCnt = 0;

   while (cStr[i] != '\0') {
       iCnt++;
       i += cntByte(cStr[i]);
   }

   return iCnt;
}

/*
 * 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 = "これは文字数 Count の テスト です。";
    int iCnt;

    try {
        Proc objMain;
        iCnt = objMain.cntStr(cStr);
        cout << "* " << cStr << "\n"
             << "  => " << strlen(cStr) << " Bytes, "
             << iCnt << " Strings" << endl;
    } catch (const char* e) {
        cerr << "[EXCEPTION] " << e << endl;
        return 1;
    }
    return 0;
}

3. コンパイル

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

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

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

4. 動作確認

以下のようにして実行してみる。
バイト数と文字数が出力される。(ちなみに、全角日本語と半角カタカナは1文字3バイト、半角英数字は1文字1バイト)

1
2
3
$ ./CntStrUtf8
* これは文字数 Count の テスト です。
  => 48 Bytes, 22 Strings

5. 参考サイト


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

以上。

Comments