-->

C/C++

ICUでUTF-8の文字列を1文字ごとに分割する - Qiita

なーるほど。

「BreakIterator(ubrk.h)を使って書記素を取得する」ってので見た目1文字づつ取れるのね。

このエントリーをはてなブックマークに追加

確か古いバージョンのVisual Studioでは、exeのプロジェクトでプロジェクトの依存関係を設定するだけでよかったはずなんだけど、VS2017ではそれではダメみたいだ。
ということでVS2017での方法を書く。

ソリューションには、testlibというスタティックライブラリのプロジェクトと、testというexeのプロジェクトがあって、testプロジェクトのexeにtestlibプロジェクトで生成されるライブラリをリンクしたいものとします。

ソリューションエクスプローラーでtestプロジェクトの参照を右クリックしてポップアップメニューから参照の追加を選択する。

001

参照の追加ダイアログが表示されるのでtestlibにチェックを入れてokボタンを押す。

002

これでOKだ。



このエントリーをはてなブックマークに追加

C言語でやったUnicodeの正規化のC++版だ。C言語の時と同じようにICUを使う。ICUには、C++のAPIも用意されているのでそっちを使う。

こんな感じだ。

#include <stdio.h>
#include <stdlib.h>
#include "unicode/unistr.h"
#include "unicode/normalizer2.h"

void dump(char *mem, int size);

int main()
{
	icu::UnicodeString src("がぎぐげご", "utf-8");
	printf("src.length()=%d\n", src.length());
	dump((char*)src.getBuffer(), src.length() * sizeof(UChar));
	
	// (1) Unicodeの正規化(NFD)の準備
	UErrorCode err = U_ZERO_ERROR;
	const icu::Normalizer2 *normalizer = icu::Normalizer2::getNFDInstance(err);
	if(U_FAILURE(err)) {
		fprintf(stderr, "err=%d\n", err);
		exit(1);
	}

	// (2) 正規化する。
	err = U_ZERO_ERROR;
	icu::UnicodeString dest = normalizer->normalize(src, err);
	if(U_FAILURE(err)) {
		fprintf(stderr, "err=%d\n", err);
		exit(1);
	}
	printf("dest.length()=%d\n", dest.length());
	dump((char*)dest.getBuffer(), dest.length() * sizeof(UChar));
	

	return 0;
}


void dump(char *mem, int size)
{
	int addr, offset;
	
	for(addr = 0; addr < size; addr += 16) {
		printf("%04X ", addr & 0xffff);
		for(offset = 0; offset < 16; offset++) {
			if(addr + offset >= size) {
				break;
			}
			printf("%02X ", mem[addr + offset] & 0xff);
		}
		printf("\n");
	}	
}

(追記)
コンパイルは、こうだ。

$ g++ -Wall -o unicode2 `icu-config --cppflags --ldflags` unicode2.cpp

このエントリーをはてなブックマークに追加

UnicodeのライブラリICUを使ってUnicodeの正規化を行ってみる。
Unicodeの正規化とは、簡単に言うと見た目が「が」の文字を1つのコード「が」で表す場合と「か」+「゛」(濁点)の2つで表す場合がある。前者を合成文字で後者が結合文字って言う。これらを変換することを正規化っていう。(かなり適当な説明なんで詳しくはググってくれw)

とりあえず、ソースを示す。

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include "unicode/ustring.h"
#include "unicode/unorm2.h"

void dump(char *mem, int size);

int main()
{
	char *src = "がぎぐげご";
	UErrorCode err;
	int32_t destLen;
	UChar *dest, *dest2;
	int32_t numSubstitutions;
	
	/* (1) UTF8からUnicodeへの変換後の文字数を取得する。 */
	err = U_ZERO_ERROR;
	u_strFromUTF8WithSub(NULL, 0, &destLen, src, -1, 0xfffd, &numSubstitutions, &err);
	printf("destLen=%d\n", destLen);
	
	/* (2) 変換後の文字列を入れるメモリを確保 */
	dest = (UChar*)calloc(destLen + 1, sizeof(UChar));
	if(!dest) {
		fprintf(stderr, "malloc error\n");
		exit(1);
	}
	
	/* (3) UTF8からUnicodeへ変換 */
	err = U_ZERO_ERROR;
	u_strFromUTF8WithSub(dest, destLen + 1, &destLen, src, -1, 0xfffd, &numSubstitutions, &err);
	if(U_FAILURE(err)) {
		fprintf(stderr, "err=%d\n", err);
		exit(1);
	}
	printf("destLen=%d\n", destLen);	
	dump((char*)dest, (u_strlen(dest) + 1) * sizeof(UChar));

	/* (4) Unicodeの正規化(NFD) */
	err = U_ZERO_ERROR;
	const UNormalizer2 *normalizer = unorm2_getNFDInstance(&err);
	if(U_FAILURE(err)) {
		fprintf(stderr, "err=%d\n", err);
		exit(1);
	}
	/* (5) 正規化後のサイズを取得 */
	err = U_ZERO_ERROR;
	int32_t destLen2 = unorm2_normalize(normalizer, dest, -1, NULL, 0, &err);
	printf("destLen2=%d\n", destLen2);
	
	/* (6) 正規化後の文字列を入れるメモリを確保 */		
	dest2 = (UChar*)calloc(destLen2 + 1, sizeof(UChar));
	if(!dest2) {
		fprintf(stderr, "malloc error\n");
		exit(1);
	}
	/* (7) 正規化する */
	err = U_ZERO_ERROR;
	destLen2 = unorm2_normalize(normalizer, dest, -1, dest2, destLen2 + 1, &err);
	if(U_FAILURE(err)) {
		fprintf(stderr, "err=%d\n", err);
		exit(1);
	}
	dump((char *)dest2, (u_strlen(dest2) + 1) * sizeof(UChar));
	
	free(dest2);
	free(dest);
	
	return 0;
}

void dump(char *mem, int size)
{
	int addr, offset;
	
	for(addr = 0; addr < size; addr += 16) {
		printf("%04X ", addr & 0xffff);
		for(offset = 0; offset < 16; offset++) {
			if(addr + offset >= size) {
				break;
			}
			printf("%02X ", mem[addr + offset] & 0xff);
		}
		printf("\n");
	}	
}

ソースはUTF-8で保存しておいて、コンパイルはこんな感じでする。

$ gcc -o unicode -I/opt/local/include -L/opt/local/lib -licuuc unicode.c

ICUは、MacPortsを使ってインストールしているものとする。

(1) UTF8からUnicodeへ変換した時の文字数を取得。変換できない文字があった場合は0xfffdにして変換するように指定している。また、ICUのAPIで渡すエラーコードが入る変数はU_ZERO_ERRORで初期化しておかないといけない。
(2) メモリ確保。
(3) UTF8からUnicodeへ変換
(4) 正規化の準備。ほんとは、合成文字列への変換を試したかったんだが結合文字列の「がぎぐげご」のUTF8を用意するのが面倒くさかったので、結合文字列の変換するとこにした。合成文字列への変換する場合はunorm2_getNFCInstance()を使う。
(5) 正規化後のサイズ取得。ここでやってる方法はドキュメントに書いてないので注意。
(6) メモリ確保。
(7) 正規化する。

(追記)
icu-configってのが用意されているようなので、コンパイルはこんな感じでする。

$ gcc -Wall -o unicode `icu-config --cflags --ldflags` unicode.c

このエントリーをはてなブックマークに追加


Addons Node.js v0.11.11 Manual & Documentation

こちらに書かれている。
けっこー、面倒くさそうだ(^^;) 



このエントリーをはてなブックマークに追加

↑このページのトップヘ