C 言語で文字列メンドクサイ

最近の Linux なら locale は ja_JP.UTF-8 でイケるようだ。

scanf – Wikipedia
scanf ってこんなに面倒だったかなぁ…
gets だと思いっきり警告だし。

wchar_t って Linux では 4 バイトなんだね。
Windows つか Visual Studio では 2 バイトなのですけど。

最近の Windows SDK のようにセキュリティ関数が存在してくれないと怖いなぁ…
文字列処理って簡単にバッファオーバーランが起こせるからね。
malloc で動的処理すればなんとかなりそうだけど std::string のほうが(略

日本語の文字数カウントとかをするには UNICODE にするのが一番なわけで。
とりあえずバッファオーバーラン等を考慮しないでうまくいったコード。

#include <stdio.h>
#include <stddef.h>
#include <locale.h>
#include <string.h>

int 
main (int argc, char *argv[])
{
    /* set locale */
    setlocale( LC_CTYPE, "ja_JP.UTF-8" );

    /* おまけ、変数バイト数チェック */
    printf("int     サイズ = %d\n", sizeof(int));
    printf("char    サイズ = %d\n", sizeof(char));
    printf("wchar_t サイズ = %d\n", sizeof(wchar_t));

    /* バッファ */
    char cin[256];
    wchar_t s[256 * 4];
    char c[4] = {0};

    /* 何か入力させる */
    printf("何か文字列を入力して Enter\n");
    scanf("%s", cin);

    /* UNICODE に変換 */
    const char *cc = cin;
    size_t t = mbsrtowcs(s, &cc, strlen(cc), NULL);
    printf("文字数は %d です\n", t);

    /* 一文字ずつ書き出ししてみる */
    int i=0;
    for (i; i<t; i++)
    {
        wctomb(c, s[i]);
        printf("%s\n", c);
    }
    return 0;
}

あーくそ!Python ならたったコレだけ、import も無しで同じことができるんだが。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

s = raw_input("何か文字列を入力して Enter\n")
u = unicode(s, "utf8")
print "文字数は %d です" % len(u)
for c in u:
    print c.encode("utf8")

しかもバッファオーバーランの心配は無いと思うし。

※追記、GLib を使えば簡単だった
gunichar | PaePoi