標準のマルチバイト関数を使って UTF-8 の文字列から1文字ずつ取り出す

char 型でヌル終端の文字列でかつ不正なバイト列が含まれておらず、かつロケールを決め打ちにしてよいのであれば、1文字ずつ取り出すのに `mblen`、`mbrlen`、`mbtowc`、`mbrtowc`、`mbrtoc32` を使うことができます。これらの関数の戻り値は次の文字のバイト数です。

`mblen` と `mbrlen` の使いわけは状態変数を自分で管理する必要があるかどうかです。`mbrlen` の第3引数に内部の状態をあらわす変数を指定します。

`mbtowc` と `mblen` の違いはコードポイントが必要であるかどうかです。`mbtowc` の第1引数にコードポイントが参照渡しされます。第1引数の型は wchar_t なので、OS によって結果が変わります。筆者は `wchar_t` のサイズが32ビットである Linux と Mac OS X で確認していますが、16ビットの Windows では未検証です。

`mbrtowc` と `mbtowc` の使いわけは状態変数を自分で管理する必要があるかどうかです。`mbrtowc` の第4引数で内部の状態をあらわす変数を指定します。

`mbrtoc32` は C11 で追加された関数で、`mbrtowc` と比べて　`wchar_t` の代わりに `char32_t` が使われます。2015年1月の時点では GCC で利用可能です。

`mbrtoc16` も同時に C11 で導入されましたが、U+10000 から U+10FFFF の範囲の文字に遭遇すると負の値を返すので、使い道はかぎられます。

複数の種類の OS で利用することを想定するのであれば ICU を検討する必要があるでしょう。[こちらの記事](http://qiita.com/masakielastic/items/a3387817afb0a03def2b)をご参照ください。

## テストケース

次の文字列を試すことにします。「?」(U+20BB7) は基本多言語面外の文字 (U+10000 から U+10FFFF) に対応しているかどうかを確かめるために使います。

```c
#include <stdio.h>
#include <locale.h>
#include <stdlib.h>

void print_each_char(const char*);

int main(void)
{
    //const char* str = "\U00020BB7\u91CE\u5BB6";
    const char* str = "?野家";
    const char* str2 = "?野\x80家";

    setlocale(LC_CTYPE, "ja_JP.UTF-8");
    print_each_char(str);
    puts("");
    print_each_char(str2);

    return 0;
}
```

## mblen

```c
void print_each_char(const char* str)
{
    char size;
    mblen(NULL, 0);

    while (*str) {
        size = mblen(str, MB_CUR_MAX);

        if (size < 1) {
            puts("不正なバイト列に遭遇したので、処理を中断しました。");
            break;
        }

        printf("%.*s\n", size, str);
        str += size;
    }
}
```

## mbrlen

`mbstate_t` を使うために `wchar.h` のインクルードが必要になります。

```c
#include <wchar.h>

void print_each_char(const char* str)
{
    char size;
    mbstate_t state;

    while (*str) {
        size = mbrlen(str, MB_CUR_MAX, &state);

        if (size < 1) {
            puts("不正なバイト列に遭遇したので、処理を中断しました。");
            break;
        }

        printf("%.*s\n", size, str);
        str += size;
    }
}
```

## mbtowc

```c
#include <wchar.h>

void print_each_char(const char* str)
{
    char size;
    wchar_t cp;
    mbtowc(&cp, NULL, 0);

    while (*str) {
        size = mbtowc(&cp, str, MB_CUR_MAX);

        if (size < 1) {
            puts("不正なバイト列に遭遇したので、処理を中断しました。");
            break;
        }

        printf("U+%X %.*s\n", cp, size, str);
        str += size;
    }
}
```

## mbrtowc

```c
#include <wchar.h>

void print_each_char(const char* str)
{
    char size;
    wchar_t cp;
    mbstate_t status;

    mbsinit(&status);

    while (*str) {
        size = mbrtowc(&cp, str, MB_CUR_MAX, &status);

        if (size < 1) {
            puts("不正なバイト列に遭遇したので、処理を中断しました。");
            break;
        }

        printf("U+%X %.*s\n", cp, size, str);
        str += size;
    }
}
```

## mbrtoc32

C11 で導入された `mbrtoc32` は GCC で利用可能である。

```c
#include <wchar.h>
#include <uchar.h>

void print_each_char(const char* str)
{
    char size;
    char32_t cp;
    mbstate_t status;

    mbsinit(&status);

    while (*str) {
        size = mbrtoc32(&cp, str, MB_CUR_MAX, &status);

        if (size < 1) {
            puts("不正なバイト列に遭遇したので、処理を中断しました。");
            break;
        }

        printf("U+%X %.*s\n", cp, size, str);
        str += size;
    }
}
```

## 文字数を求める

文字数を求めるだけであれば `mbstowcs` を使うことができる。ただし `mbstowcs` は OS ごとの `wchar_t` の違いを考慮しなければならない。

### mbstowcs

```c
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <stdlib.h>

int main(void)
{
    const char* str = "?野家";
    size_t size = strlen(str);
    wchar_t wchar[1000];

    setlocale(LC_CTYPE, "ja_JP.UTF-8");
    printf("%zu\n", mbstowcs(wchar, str, size));

    return 0;
}
```