From:http://washitake.com/cpp/kanji.php
charcode 変換
説明はどうでもいいから動くソースを出せという人は、後ろのほうへ…
文字コード?
日本語をはじめとする多くのアジア言語は、0〜255 までしか表せない char 型ではとても表現できません。そこで、複数の char 型を組み合わせて表現しています。ところが、日本語の場合この組み合わせ型に大きく3通りの方法があり、主に使用している OS によってその傾向が異なります。
この複数によって表される文字の数値「文字コード」と呼び、文字コードの番号付け、というか組み合わせの体系ことを「文字符号化方法 (character encoding)」とか「文字セット (character set)」などと呼びます。
伝統的に、Microsoft Windows や Apple Mac OS では Shift_JIS (内部的には Unicode ですが) が使用され、サーバーで用いられる UNIX では EUC が用いられています。また、電子メールやニュースグループでは ISO-2022-JP と呼ばれる文字セットを用います。
なお、最後のものを JIS コードと呼ぶこともありますが、実際には Shift_JIS も JIS 規格 (参考規格ですが) ですので、JIS コードだけがJIS規格というわけではありません。
文字セットについては 文字コードとエンコーディング にわかりやすく記述されています。
文字セットの構成
各文字セットは、以下の文字で構成されています。(参考)
ISO-2022-JP
制御コード
0x00〜0x1F、0x7F
ASCII文字
0x20〜0x7E
半角カタカナ
0x21〜0x5F
0xA1〜0xDF
漢字
第1バイト : 0x21〜0x7E
第2バイト : 0x21〜0x7E
補助漢字
第1バイト : 0x21〜0x7E
第2バイト : 0x21〜0x7E
Shift_JIS
制御コード
0x00〜0x1F, 0x7F
ASCII文字
0x20〜0x7E
半角カタカナ
0xA1〜0xDF
漢字
第1バイト : 0x81〜0x9F, 0xE0〜0xFC
第2バイト : 0x40〜0x7E, 0x80〜0xFC
日本語EUC
制御コード
0x00〜0x1F, 0x7F
ASCII文字
0x20〜0x7E
漢字
第1バイト : 0xA1〜0xFE
第2バイト : 0xA1〜0xFE
半角カタカナ
第1バイト : 0x8E
第2バイト : A1〜0xDF
補助漢字
第1バイト : 0x8F
第2バイト : 0xA1〜0xFE
第3バイト : 0xA1〜0xFE
文字セットの判定
与えられた文字列の文字コードを変換するためには、まずその文字コードがどの種類なのかを認識する必要があります。
上記の文字セットの構成を、バイトごとにグラフに書いてみると、文字コードは以下のように判定できることがわかります。
7ビット文字で、エスケープシーケンスがない
ASCII文字
エスケープシーケンスを含んでいる
ISO-2022-JP
「1文字目が 0x81〜0x9F かつ 2文字目が 0x40〜0x7E / 0x80〜0xFC」あるいは「1文字目が 0xE0〜0xFC かつ 2文字目が 0x40〜0x7E」
Shift_JIS
「1文字目が 0xA1〜0xDF / 0xFD〜0xFE かつ 2文字目が 0xA1〜0xFE」
EUC
それ以外
EUCかShift_JISかが判別できない
そこで、これを素直にインプリメントしてみましょう。
int get_charset(string& source)
{
unsigned int xpos = 0;
while (xpos < source.length()) {
unsigned char lead_byte = static_cast<unsigned char>(source[xpos]);
unsigned char trail_byte = static_cast<unsigned char>(source[xpos+1]);
if (lead_byte == 0x1E && (trail_byte == '$' || trail_byte == '(')) {
cout << "ISO-2022-JP" << endl;
return 1;
}
if (((0x81 <= lead_byte && lead_byte <= 0x9F) ||
(0xE0 <= lead_byte && lead_byte <= 0xEF)) &&
(0x40 <= trail_byte && trail_byte <= 0x9F)) {
cout << "Shift_JIS" << endl;
return 2;
}
if (0xF0 <= lead_byte || (0xFD <= trail_byte && trail_byte <= 0xFF)) {
cout << "EUC" << endl;
return 3;
}
xpos++;
}
cout << "Unknown..." << endl;
return -1;
}
もちろん、これでは不十分です(たとえば trail_byte == '\0' の場合など)が、たいていの文書であればこれだけでも文字セットを判別できると思います。
なお、文字コードにおける 0x8E などは、char == unsigned char での話です。通常の処理系では char == signed char ですので、(静的)キャストして char → unsigned char という変換をする必要があります。また、これをせずに文字コードを 0x8F → -0x71 などと読み替えるのも一つの方法です。速度的には、定数値を変化させるだけの後者が速いはずです (実際の所はどうなんでしょう?) が、読みやすさから言うと前者がお奨めです。
文字セットを変換する
各文字セットの文字は、それぞれ以下のように相互変換可能です。
ISO-2022-JP → Shift_JIS
void j2s(unsigned char* buf, unsigned char* dest)
{
unsigned char row_offset = (buf[0] < 0x5F) ? 0x70 : 0xB0;
unsigned char cell_offset = (buf[0] % 2) ? ((buf[1] > 0x5F) ? 0x20 : 0x1F) : 0x7E;
dest[0] = ((buf[0] + 1) / 2) + row_offset;
dest[1] = buf[1] + cell_offset;
}
ISO-2022-JP → utf-8
void j2e(unsigned char* buf, unsigned char* dest)
{
dest[0] = buf[0] | 0x80;
dest[1] = buf[1] | 0x80;
/* ただし、「半角」文字の場合
dest[0] = '\x8E';
dest[1] = buf[0] | 0x80;
補助漢字の場合は
dest[0] = '\x8F';
dest[1] = buf[0] | 0x80;
dest[2] = buf[1] | 0x80;
*/
}
Shift_JIS → ISO-2022-JP
void s2j(unsigned char* buf, unsigned char* dest)
{
unsigned char row_offset = (buf[0] < 0xA0) ? 0x70 : 0xB0;
unsigned char cell_offset = (buf[1] < 0x9F) ? ((buf[1] > 0x7F) ? 0x20 : 0x1F) : 0x7E;
dest[0] = ((buf[0] - row_offset) / 2) - (c2 < 0x9F ? 1 : 0);
dest[1] = buf[1] - cell_offset;
}
EUC → ISO-2022-JP
void e2j(unsigned char* buf, unsigned char* dest)
{
switch (buf[0]) {
case 0x8E:
dest[0] = buf[1] & 0x7f;
// ただし、「半角」文字のエスケープ ESC ( I が必要
// 8ビット JIS が使用できるなら dest[0] = buf[1] でもよい。
break;
case 0x8F:
dest[0] = buf[1] & 0x7f;
dest[1] = buf[2] & 0x7f;
// ただし、補助漢字のエスケープ ESC $ ( D が必要
break;
default:
dest[0] = buf[0] & 0x7F;
dest[1] = buf[1] & 0x7F;
}
return;
}
Shift_JIS → EUC : 上記の s2j と j2e を組み合わせます。
EUC → Shift_JIS : 上記の e2j と j2s を組み合わせます。
その他の実装
あとは、ISO-2022-JP におけるエスケープシーケンスの実装と、「半角」文字や「機種依存」文字をいかに処理するかですが、ここでは割愛します。各自考えてみてください。
あるいは、nkf などのソースを読むか…
また、下に掲載していますが、一通り動作するソースもダウンロードできますので、ご利用ください。
分享到:
相关推荐
新世纪日本语教程是一套针对日本语学习者的教材,它详细地介绍了日语的各个方面,包括基础语法、词汇、句型和会话等。该教程适合于初学者以及已经有一定基础的学习者,其内容结构严谨、循序渐进,是一份全面且深入的...
旧版 中日交流标准日本语 (初级上) pdf格式 共407页; 图书信息: 作者:人民教育出版社 (日)光村图书出版社株式会社合 目录 序言 本册内容与结构 日语基础知识 第1单元 …… 第6单元 附录 I.课文译文 II....
标准日本语APP破解版,需注册账号,以前注册过的账号仍可以使用,对于想学日语的人来说非常好用的APP,APP里的内容为标准日本语(第二版)的内容,并且还附带读听功能,即使是零基础的人也能根据APP自学。
《日本语达人之道》是一本深受日语学习者喜爱的教材,特别强调口语能力和地道的日语表达。这本书的PDF版本提供了方便的电子阅读体验,使学习者能够在任何时间、任何地点进行日语学习,不再受纸质书籍的限制。在本文...
破解版标准日本语APP_安卓版,资源已经破解,安装完直接申请帐号,然后其他操作跟正版一样
《中日交流标准日本语初级上 语音朗读(mp3)》是为学习日语初学者准备的一套音频资源,旨在帮助学习者通过听觉训练掌握正确的日语发音和语调。这套资源基于人教版《中日交流标准日本语》初级上册,涵盖了教材中的...
新版标准日本语中级课文单词word版 新版标准日本语中级课文单词word版
新标准日本语破解版app软件下载,包括初中级课程教程。
《中日交流标准日本语中级上下册》是学习日语的重要教材,主要针对已经掌握了一定日语基础知识的学习者,旨在提升他们的日语听说读写能力。本套教材以其科学的编排、实用的内容和丰富的文化注解,深受广大日语学习者...
新版中日交流标准日本语初级下同步测试卷 ( 第 26 课 ) 、 将下列汉字用平假名填入 l. 新春 7 . 值段 13 . 普通 18 . 会費 2 . 家族 8 . 季節 14 . 駔前 19 . 事務所 3 . 最近 9 . 来過 20 . 体 中 。 ...
《大家的日本语》是一本广泛使用的日语学习教材,主要针对初级至中级的学习者设计。下册通常在上册的基础上进一步深入,涵盖了更复杂的语法结构、词汇以及实用的日常对话。下面,我们将详细探讨“大家的日本语下册...
新版标准日本语app破解版,仅限安卓系统,已有五十音图和初级的资源包,没有中高级的
《标准日本语36-40课后答案》中的练习题,不仅覆盖了日语中常见的语法变化,还通过各种情景应用,使学生能够更好地理解语言的实用性和生动性。 首先,我们来看一下日语句型练习。它要求学习者通过替换练习来掌握...
【默写版】新版标准日本语单词表.pdf
新版中日交流标准日本语(初级)同步练习:练习、模拟试题录音内容.pdf
《大家的日本语》是一套广受欢迎的日语学习教材,特别适合初级阶段的学习者。这套教材以其贴近生活、实用性强的特点,深受初学者的喜爱。"大家的日本语1-2册教材.PDF格式"提供了完整的电子版教材,方便学生随时随地...
内容包括:标准日本语初级上下册视频教程完整版 由于文件过大,只提供百度网盘下载地址和提取码,请放心下载。 信誉第一!如有任何问题,可以发私信或者评论区留言。
《新编标准日本语单词》这本词汇资源,以其全面性和系统的编排,成为了许多日语学习者的重要工具书。 该书很可能采用了日语五十音图的顺序,为读者提供了一个清晰的学习路径。五十音图是日语发音的基础,掌握五十音...
在当今多元化的语言学习潮流中,《旧版标准日本语 初中级 单词》这份资料无疑成为众多日语学习者的一份宝贵资产。它不仅是学习者构建日语词汇体系的基石,也是其稳步提升日语能力的助力。 “标准日本语”系列教材自...