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软件下载,包括初中级课程教程。
《中日交流标准日本语中级上下册》是学习日语的重要教材,主要针对已经掌握了一定日语基础知识的学习者,旨在提升他们的日语听说读写能力。本套教材以其科学的编排、实用的内容和丰富的文化注解,深受广大日语学习者...
《旧版标准日本语 初中级 单词》是一份重要的学习资料,主要针对学习日语的初学者和进阶者。"标准日本语"是日语教学领域中广泛使用的一套教材,以其系统性和实用性著称。此压缩包包含了四份文档:z1.doc、z2.doc、c2...
新版中日交流标准日本语初级下同步测试卷 ( 第 26 课 ) 、 将下列汉字用平假名填入 l. 新春 7 . 值段 13 . 普通 18 . 会費 2 . 家族 8 . 季節 14 . 駔前 19 . 事務所 3 . 最近 9 . 来過 20 . 体 中 。 ...
《大家的日本语》是一本广泛使用的日语学习教材,主要针对初级至中级的学习者设计。下册通常在上册的基础上进一步深入,涵盖了更复杂的语法结构、词汇以及实用的日常对话。下面,我们将详细探讨“大家的日本语下册...
新版标准日本语app破解版,仅限安卓系统,已有五十音图和初级的资源包,没有中高级的
【默写版】新版标准日本语单词表.pdf
新版中日交流标准日本语(初级)同步练习:练习、模拟试题录音内容.pdf
《新编标准日本语单词》是一本专门为学习日语的人准备的词汇资源,它涵盖了日语学习的基础和关键单词,是提升日语能力的重要参考资料。这个压缩包文件包含了一个名为“单词”的文件,很可能是一个文本文件或者电子书...
内容包括:标准日本语初级上下册视频教程完整版 由于文件过大,只提供百度网盘下载地址和提取码,请放心下载。 信誉第一!如有任何问题,可以发私信或者评论区留言。
【IT日本語】在软件开发领域,特别是在与日本企业合作时,掌握日语沟通技巧显得尤为重要。邮件作为主要的沟通工具,不仅用于解决问题,汇报项目进度,还在于建立双方的信任和理解,这对于长期合作至关重要。良好的...
《大家的日本语》是一套广受欢迎的日语学习教材,特别适合初级阶段的学习者。这套教材以其贴近生活、实用性强的特点,深受初学者的喜爱。"大家的日本语1-2册教材.PDF格式"提供了完整的电子版教材,方便学生随时随地...