😃
Re: C言語でひらがなの部分文字列
この記事を見て,おお〜こりゃ便利だとなりました😂
それで早速使ってみたら,変なことになってしまい……🥲
#include <stdio.h>
#include <stdint.h>
int main(void){
uint8_t *str = "ひらがな";
printf("%.*s\n", 9, str);
}
出力が「ひらか」になってしまったんですね😯
ひらがなの場合、1文字は3バイトなので、
どうやら濁点が含まれるとそうとは限らないらしく,なるほどと🤔
同じ記事に書かれていた,strndup
の方でも,うまく行かず……😭
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int main(void){
uint8_t *src = "ひらがな";
uint8_t *dest = strndup(src, 9);
printf("%s\n", dest);
}
調べていると,どうやらこういう場合は ICU (International Components for Unicode) というものを使うのが良いのだそうです✋😃
コード例です👇
#include <stdio.h>
#include <unicode/ubrk.h>
int main(void){
uint8_t *str = "ひらがな";
UErrorCode err = U_ZERO_ERROR;
UText *text = utext_openUTF8(NULL, str, -1, &err);
UBreakIterator *iter = ubrk_open(UBRK_CHARACTER, "ja_JP", NULL, 0, &err);
ubrk_setUText(iter, text, &err);
int32_t len = 0;
for(int i = 0; i < 3; i++){
printf("%d文字目は%dバイト目から", i + 1, len + 1);
len = ubrk_next(iter);
printf("%dバイト目まで\n", len);
}
printf("%.*s\n", len, str);
utext_close(text);
ubrk_close(iter);
}
出力は以下のようになりました!
1文字目は1バイト目から3バイト目まで
2文字目は4バイト目から6バイト目まで
3文字目は7バイト目から12バイト目まで
ひらが
ちゃんと「ひらが」になっています😆
「が」は7バイト目から12バイト目までの6バイトだったんですね🤣
Discussion
文字がどのようなコードポイントで構成されているかは
uniname
(homebrew、Debian の uniutils) もしくはuconv
(homebrew の icu4c、Debian の icu-devtools) で調べることができます。1つのコードポイントで表現される形式は NFC、2つのコードポイント(「基底文字」と「結合文字」)で表現される形式は NFD と呼ばれます。
uconv
で変換できます (「Unicode 正規化」)。PCRE2 をサポートする GNU grep (macOS は homebrew の grep で導入) を使って書記素クラスター単位(「
\X
」)の処理をすることができますありがとうございます😊😊😊
uconv も GNU grep も動きました,これで安心です😆😆😆