質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

解決済

2回答

970閲覧

WideCharToMultiByteで「髙」から「0x7c62」を取得したい

n_ito

総合スコア14

VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

1クリップ

投稿2024/02/06 07:27

char taka[100];
WideCharToMultiByte(50221, 0, L"髙", -1, taka, 100, NULL, NULL);

Windowsで、上のルーチンで「髙」をJISコードに変換すると、
「1b 24 28 44 74 29 1b 28 42 00」というバイト列になりました。

「1b 24 28 44」はJIS X 0212、「1b 28 42」はアスキー文字のエスケープ文字で、
途中の「74 29」というバイト列が「髙」を表すものだと理解しました。
ところが、テキストエディタなどでこの文字のJISコードを表示させると、0x7c62となります。

「髙」が本来JISコードにないことは理解しているのですが、
この0x7429というバイト列はどういう意味で、なぜ0x7c62にならないのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2024/02/06 08:26

JISだと「1B 24 42 7C 62 1B 28 42」では?
n_ito

2024/02/06 08:43

コメントありがとうございます。 JIS X 0212を表すエスケープ文字が入ってくるのがおかしいのではとも思うのですが、 上に書いたようにWideCharToMultiByteを使うと、そのようなバイト列になるようです。 「1B 24 42 7C 62 1B 28 42」が返ってくるような指定方法があるのでしょうか。
can110

2024/02/06 08:55

以下試した結果を記載ください。 - 引数lpDefaultChar, lpUsedDefaultCharも指定 - 戻り値も取得し0ならGetLastErrorでエラーコードを取得 おそらくERROR_INVALID_PARAMETERで変換失敗すると思います。
退会済みユーザー

退会済みユーザー

2024/02/06 09:05

まず、 https://learn.microsoft.com/ja-jp/windows/win32/intl/code-page-identifiers より50221はcsISO2022JPのことであり、所謂JISコードの派生であることが分かります。 Microsoftからはこれ以上の情報の提供がありません。 他方所謂JISコード(ISO-2022-JP)には以下から https://ja.wikipedia.org/wiki/ISO-2022-JP いくつかの派生があることが分かっています。 ISO-2022を知ると分かりますが、そのサブセットでエスケープシーケンスが被ったりしません。 「1b 24 28 44」はRFC2237 https://datatracker.ietf.org/doc/html/rfc2237 によると、JIS X 0212-1990とのことなので、JIS X 0212は確定だと思います。 そして「74 29」は0x20ずつ引いて区点にすると84区9点となり、 https://www.asahi-net.or.jp/~ax2s-kmtn/ref/jisx0212/index.html によるとJIS X 0212に存在しないことになります(JISでpdfを見てもいいのですが、ユーザー登録したくないので私は見てません)。ユーザー登録してPDFを見てもいい人は見て確認すれば何か分かるかもしれませんね。
can110

2024/02/06 09:09 編集

> ところが、テキストエディタなどでこの文字のJISコードを表示させると、0x7c62となります。 そのエディタでJISで保存したファイルをバイナリエディタで開き、バイトコードを確認してください。 たぶん「1B 24 42 7C 62 1B 28 42」になっていると思いますが。 あとは以下などを参考に、いろいろ調べてみてください。 https://sakura-editor.github.io/help/HLP000271.html
n_ito

2024/02/06 09:38

> - 引数lpDefaultChar, lpUsedDefaultCharも指定 > - 戻り値も取得し0ならGetLastErrorでエラーコードを取得 コメントありがとうございます。 lpDefaultCharとlpUsedDefaultCharをNULLのまま、戻り値を確認してみたところ、 WideCharToMultiByteの戻り値は10で、成功扱いになっているようです。 ちなみに、lpDefaultCharとlpUsedDefaultCharを指定してみようとしたのですが、 BOOL bUsedDefaultChar = FALSE; int result = WideCharToMultiByte(50222, 0, L"髙", -1, taka, 100, "?", &bUsedDefaultChar); と書いてみても、GetLastErrorの値は87(パラメータが不正)となってしまいます。 「髙」の代わりに「高」などの文字を入れてみても同じです。 指定の仕方が間違っているのでしょうか。
n_ito

2024/02/06 09:46

> dameoさん > そして「74 29」は0x20ずつ引いて区点にすると84区9点となり、 > https://www.asahi-net.or.jp/~ax2s-kmtn/ref/jisx0212/index.html > によるとJIS X 0212に存在しないことになります > can110さん > そのエディタでJISで保存したファイルをバイナリエディタで開き、バイトコードを確認してください。 > たぶん「1B 24 42 7C 62 1B 28 42」になっていると思いますが。 お二方コメントありがとうございます。 テキストエディタで「髙」だけを打ち込んで、JISとして保存し、 バイナリエディタで見てみたところ、「1B 24 42 7C 62 1B 28 42」となっていました。 となると、WideCharToMultiByteが正しい動作をしていないということになるのでしょうか? その場合、任意の文字列をJISコードに変換するには、他にどういう方法がありますでしょうか?
退会済みユーザー

退会済みユーザー

2024/02/06 09:48

> WideCharToMultiByteが正しい動作をしていないということになるのでしょうか? いいえ
maisumakun

2024/02/06 12:21

> テキストエディタなどでこの文字のJISコードを表示させると、0x7c62となります。 ・どのようなエディタで、どんな文字コードで記載したうえで、どんな方法を用いて確認を行いましたか?
n_ito

2024/02/06 23:56

> どのようなエディタで、どんな文字コードで記載したうえで、どんな方法を用いて確認を行いましたか? 秀丸エディタに「髙」の文字を貼り付けて、「文字コード表示」のダイアログで確認したところ、 JIS: 0x7C62 と表示されました。 また、JIS形式で保存してから開き直しても、同じ文字コードになっていることも確認しました。
maisumakun

2024/02/07 00:17

では、「0x7c62のほうが正しい」と考える根拠は何でしょうか?
n_ito

2024/02/07 00:57

> では、「0x7c62のほうが正しい」と考える根拠は何でしょうか? 0x7c62で調べるとそれなりに情報が出てきて、ファイルにもそのように保存されるのに、 0x7429だとなにも情報が出てこないので、WideCharToMultiByteで返ってくる0x7429はどういう意味なんだと疑問に思いました。
tmp

2024/02/08 09:13 編集

「髙」(U+9AD9)の該当しそうなSJISコードが2つあるのですね。JISコードの割り当てはないと書いてありましたが 2つのSJISコードEEE0とFBFC EEE0の方は、NEC選定IBM拡張文字って書いてありましたが、EEE0は単純計算するとJISコード7C62になりますが、FBFCの方は、EFを超えているので計算できない。 EEE0は、恐らくNEC選定IBM拡張文字って書いてるから特殊な方なのでしょうか エディター(内部がUNICODEのエディタ)で、SJISで保存するとFBFCのコードになります。
退会済みユーザー

退会済みユーザー

2024/02/08 09:35

SJISコードでJIS X 208の区点を計算する方法はありますが、JIS X 212はありません。 質問者(と回答者)がISO-2022を理解してからでないと話が出来ないと思いますよ。
guest

回答2

0

ベストアンサー

Windows 11、Visual Studio 2022で確認しました。

確かにWideCharToMultiByteでは、50220,50221,50222のいずれを指定しても、「髙」は0x7429を返しますね。
これが何故なのか私も知りたいです(と言ったら私も怒られるのかな)。

参考までに、サクラエディタ(GitHubでソース公開しています)では、以下のような処理により0x7C62を返しています。
(「髙」に関係する処理だけを抜き出して、単純化しています)

#include <iostream> #include <windows.h> #include <mbstring.h> int main() { const char JISESCDATA_JISX0208_1983[] = {0x1B, 0x24, 0x42}; const char JISESCDATA_ASCII7[] = {0x1B, 0x28, 0x42}; char *pDst = new char[8]; char taka[100]; // UTF-16(0x9AD9)からShift_JIS(IBM拡張文字、0xFBFC) WideCharToMultiByte(932, 0, L"髙", -1, taka, 100, nullptr, nullptr); // 2区と13区の調整(「髙」は対象外) // IBM拡張文字からNEC選定IBM拡張文字(0xEEE0) unsigned int c = ((taka[0] << 8) & 0x0000FF00) + (taka[1] & 0x000000FF); // 「髙」が含まれるFB9C~FBFC→EE80~EEE0の場合 c -= 0x0D1C; // NEC選定IBM拡張文字からJIS(0x7C62) c = _mbcjmstojis_l(c, _create_locale(LC_ALL, "Japanese_Japan.932")); // エスケープシーケンスと連結 memcpy(pDst, JISESCDATA_JISX0208_1983, 3); pDst[3] = static_cast<char>((c & 0x0000FF00) >> 8); pDst[4] = static_cast<char>(c & 0x000000FF); memcpy(&pDst[5], JISESCDATA_ASCII7, 3); // pDstに変換結果が入っている(0x1B 24 42 7C 62 1B 28 42) delete[] pDst; }

(追記)
dameoさんの指摘により、上記ソースの参照元を追記します。
https://github.com/sakura-editor/sakura

処理内容ソース関数
UTF-16からIBM拡張文字sakura_core\charset\codeutil.hMyWideCharToMultiByte_JP
2区と13区の調整sakura_core\charset\codeutil.cppSjisFilter_basis
IBM拡張文字からNEC選定IBM拡張文字sakura_core\charset\codeutil.cppSjisFilter_ibm2nec
NEC選定IBM拡張文字からJISsakura_core\charset\codeutil.cpp_mbcjmstojis_j
エスケープシーケンスと連結sakura_core\charset\CJis.cppCJis::UniToJis

(追記・その2)
JISCに登録して「JIS X 0212-1990」規格書を見ましたが、「髙」に関する記載はありませんでした。
あとは、WideCharToMultiByte APIのソースを見るしかないですね。

(追記・その3)
FreeBSD 13.2、iconvコマンド

パラメーター
CP502200x1B 24 42 7C 62 1B 28 42
CP502210x1B 24 42 7C 62 1B 28 42
CP502220x1B 24 42 7C 62 1B 28 42
ISO-2022-JP-1warning: invalid characters: 1
ISO-2022-JP-2warning: invalid characters: 1
ISO-2022-JPwarning: invalid characters: 1
JISX0208:1990不正なバイト列です

Ubuntu 22.04.3、iconvコマンド

パラメーター
CSISO2022JPillegal input sequence at position 0
CSISO2022JP2illegal input sequence at position 0
ISO-2022-JP-2illegal input sequence at position 0
ISO-2022-JP-3illegal input sequence at position 0
ISO-2022-JPillegal input sequence at position 0
ISO2022JPillegal input sequence at position 0
ISO2022JP2illegal input sequence at position 0

FreeBSD 13.2、PHP 8.1.27
Ubuntu 22.04.3、PHP 8.1.2
mb_convert_encoding関数(2環境とも結果は同じ)

パラメーター
CP502200x1B 24 42 7C 62 1B 28 42
CP50220raw0x1B 24 42 7C 62 1B 28 42
CP502210x1B 24 42 7C 62 1B 28 42
CP502220x1B 24 42 7C 62 1B 28 42
ISO-2022-JP0x3F
ISO-2022-JP-MS0x1B 24 42 7C 62 1B 28 42
JIS0x3F
JIS-ms0x1B 24 42 7C 62 1B 28 42

※0x3FはUS-ASCIIで「?」

私の結論としては、WideCharToMultiByteに50220,50221,50222を指定して0x7429を返す動作は変だと思います。0x7C62が正しい。

投稿2024/02/09 23:35

編集2024/02/11 13:08
hiroki-o

総合スコア1059

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2024/02/10 00:06

ISO-2022の仕様を確認しましょう。JIS X 208を使って変換するコードを見ても理解はできないでしょう。
n_ito

2024/02/13 00:41

> 私の結論としては、WideCharToMultiByteに50220,50221,50222を指定して0x7429を返す動作は変だと思います。0x7C62が正しい。 hiroki-oさん、詳しい解説ありがとうございます。 また、現象を確認していだたきありがとうございます。 この「1b 24 28 44 74 29 1b 28 42 00」というバイト列をMultiByteToWideCharに渡すと ちゃんと「髙」に戻るので、0x7429はどこかで定義されているのかとも思ったのですが、 ネット上で探しても見つからないので、この値をそのまま使っていいのか困っていました。 サクラエディタのコードも非常に参考になります。 WideCharToMultiByteの結果である0x7429の値を信じないとなると、 いろいろ自力で変換する必要が出てくるのですね。
退会済みユーザー

退会済みユーザー

2024/02/13 01:25

ベストアンサーで初めて通知があったので、今修正に気付きました。 まるで間違っていますよ。 正しい正しくないだけで言えば、もしISO-2022-JPであれば0x7C62はJIS X 208なら範囲外なので全く正しくありません。 > (追記) > dameoさんの指摘により、上記ソースの参照元を追記します。 > https://github.com/sakura-editor/sakura 十分ではありません。私が示したようにきちんとリビジョンとコード範囲を指定しましょう。 > JISCに登録して「JIS X 0212-1990」規格書を見ましたが、「髙」に関する記載はありませんでした。 JIS X 208にもないと思いますよ。 ついでに言えば213にも。 > FreeBSD 13.2、iconvコマンド CP50220~2の結果については、きちんとissueでもあげるべきですね。 iconvのバージョンわかりませんが、MSに合わせない理由がないので。Ubuntuなどの結果を見る限り、多分間違ったエイリアスが切られているのだと思います。 PHPも同様だと思います。 0x7C62が正しいとかではなく、JIS X 208を使っているのが不適切です。 誰もコードページ5022Xについては誰もコードポイントを規定しておらず、MSしか使っていないのですから、それに合わせる以外の選択肢はありません。 (MSから出てそうなのはISO-2022-JP-1という仕様だけですが、これでも212を使うこと以外、細かい規定はありません。他はIANAの名前登録くらいです。) 213を使用するISO-2022-JP-3については、IANAの登録すらありません。 サクラエディタのコード変換は_mbcjmstojis_lを使いたいがために、わざわざIBM拡張文字からNEC選定IBM拡張文字に変換をかけるほどのものであり、ロケール指定まで使っておいてわざわざCP5022Xを使わない理由が分からないくらいです。 ただ、何度も言いますが、まずはなぜJIS X 208に固執して、合ってるだの間違ってるだの言うのでしょう? CP50220を規定したMSが、エスケープシーケンスでJIS X 212を使っているのに、わざわざJIS X 208を使う理由は何でしょう? 所謂JISコードが昔からMSだけ違う使い方をしていて(髙とか①なんてそもそもJISじゃ使いません)、それはShift_JISとMS932(現CP932)/Windows-31Jが同じようで違っているのと同じことですよ。
退会済みユーザー

退会済みユーザー

2024/02/13 02:42 編集

一応追記しておくと、ISO-2022-JP-1はJIS X 208も普通に使っています。 JIS X 212は補助漢字という位置づけなので。 なので、私はUnicode→JISしかしてないのでチェックしていませんが、おそらくMicrosoftは50220→Unicode時、JIS X 208もちゃんと変換してると思いますよ。 (追記)ここは別の外字扱いで髙には変換してくれませんでしたね。ちょっと確認した結果を貼っておきます。 #include <windows.h> #include <cstdio> #include <clocale> int main() { using namespace std; setlocale(LC_CTYPE, ""); char taka_208[] = {"\x1B\x24\x42\x7C\x62\x1b(B"}; wchar_t wch[100]; auto len = MultiByteToWideChar(50220, 0, taka_208, sizeof(taka_208)/sizeof(taka_208[0]), wch, sizeof(wch) / sizeof(wch[0])); printf("converted %d chars.\n", len); if (len > 0) { wprintf(L"converted -> %lc(0x%04x)", wch[0], wch[0]); } else { printf("error: 0x%08X\n", GetLastError()); } return 0; } // converted 2 chars. // converted -> (0xe2d3) あと、前に少し触れましたが、シフトJIS2バイト文字<->JIS X 208コードポイントは割と簡単な計算式で変換できます。版によって若干の入れ替えがある程度です。
tmp

2024/02/13 03:11

hiroki-oさん、調べたものまとめ、大変参考になります。(無償だし面倒だから結論だけが多い中) しかし、0x7429は、どこからきたのでしょうかね。EUC-JPに変換するとF429になってました。
退会済みユーザー

退会済みユーザー

2024/02/13 09:20 編集

私のコードはそこに回答してるものですよ。 何度も言っていますが、ISO-2022をきちんと知ってください。
退会済みユーザー

退会済みユーザー

2024/02/13 13:33 編集

一応iconvについて調べてみました。Ubuntu 22.04のものは私の環境だとglibc2.35に付属するiconv実装でした。コードでいうとこの辺です(マイナーバージョンは適当)。 https://elixir.bootlin.com/glibc/glibc-2.35.9000/source/iconvdata/iso-2022-jp.c freebsdはcitrusプロジェクトのiconv実装を使っており、 http://citrus.bsdclub.org/ コードはこの辺 https://cgit.freebsd.org/src/tree/lib/libiconv_modules/ISO2022/citrus_iso2022.c?h=stable/13 古い上に実績の少ないBSD系の実装を元に何かを言っても仕方ないので、本家libiconv現行最新 https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.17.tar.gz をビルドしてubuntuで動かしてみました。(./configure;makeしただけ) $ ./iconv_no_i18n --version iconv (GNU libiconv 1.17) Copyright (C) 2000-2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Bruno Haible. $ echo '髙' | ./iconv_no_i18n -f UTF-8 -t CP50221 | hexdump -C 00000000 1b 24 28 44 74 29 1b 28 42 0a |.$(Dt).(B.| 0000000a $ 当たり前の結果が普通に返ってきましたよ。
hiroki-o

2024/02/13 14:55

tmpさん IBM拡張文字から30個くらい選んで、WideCharToMultiByteで50221と20932(EUC-JP)の変換結果を比較したところ、差分が0x8000,0x8080のどちらかでした。何か関係がありそうです。 ちなみに、サクラエディタのEUC変換結果とは異なりました。
退会済みユーザー

退会済みユーザー

2024/02/13 20:48 編集

EUC-JPも正しいISO-2022の派生ですよ。 何度も言っていますが、きちんとコードを提示するか、場所とリビジョンと範囲含めて示すかして、他の人が再現できるようにしないと意味がありません。 一応「髙」だけやってみました。 #include <windows.h> #include <cstdio> #include <clocale> int main() { using namespace std; setlocale(LC_CTYPE, ""); wchar_t wtaka[] = {L"髙"}; char ch[100]; UINT cps[] = { 20932, 51932 }; DWORD flags[] = { 0, WC_ERR_INVALID_CHARS }; for (size_t icps = 0; icps < sizeof(cps) / sizeof(cps[0]); ++icps) { for (size_t iflags = 0; iflags < sizeof(flags) / sizeof(flags[0]); ++iflags) { printf("[codepage=%d, flags=%d]\n", cps[icps], flags[iflags]); auto len = WideCharToMultiByte(cps[icps], flags[iflags], wtaka, sizeof(wtaka) / sizeof(wtaka[0]), ch, sizeof(ch) / sizeof(ch[0]), NULL, NULL); printf("converted %d chars.\n", len); if (len > 0) { printf("converted -> %s(", ch); for (decltype(len) i = 0; i < len; ++i) printf("%02hhx", ch[i]); printf(")\n"); } else { printf("error: 0x%08X\n", GetLastError()); } } } return 0; } //[codepage = 20932, flags = 0] //converted 3 chars. //converted->・(f42900) //[codepage = 20932, flags = 128] //converted 0 chars. //error: 0x000003EC //[codepage = 51932, flags = 0] //converted 0 chars. //error : 0x00000057 //[codepage = 51932, flags = 128] //converted 0 chars. //error : 0x00000057 コードページが51932もEUCだったので、とりあえずやってみたのですが、51932は今は亡きIEの付属DLLであるmlang.dllにあるConvertINetUnicodeToMultiByte()で使用される幻のコードページだったので使えませんでした。ただし、結果を見て分かるとおり、20932では正しいISO-2022出力になっていない(JIS X212を置いてある場所の指示がなく、2バイト目をGRにしていない)ので、20932を使うなら正しい範囲(機種依存文字を使用せず、JIS X212/213も使用しないEUC-JP)であることを事前に使う側が保証する必要がありそうです。 巷の噂では51932がWindowsのコードページにおける使えるEUC-JPだった「ようです」。昨今EUC-JPは見る影もないので、IE消滅時に別の手段で51932を使えるようにしなかったのではないかと個人的に「推測しています」。つまり一言で言えば今日のWindowsで、無条件にEUC-JPを扱える(本格使用できる)コードページはない、ということです。そして51932(以下から推測)を再現するiconv上の名前もチラ見した限りではありませんでした。 https://ja.wikipedia.org/wiki/EUC-JP https://ja.wikipedia.org/wiki/Extended_Unix_Code https://en.wikipedia.org/wiki/Extended_Unix_Code
退会済みユーザー

退会済みユーザー

2024/02/14 12:48 編集

mlang.dllを使って「髙」を変換してみました。 #include <iostream> #include <iomanip> #include <windows.h> #include <Mlang.h> int main() { HMODULE h = LoadLibrary(TEXT("mlang.dll")); if (!h) return 1; typedef HRESULT(WINAPI* CONVERTINETUNICODETOMULTIBYTE)( LPDWORD lpdwMode, DWORD dwEncoding, LPCWSTR lpSrcStr, LPINT lpnWideCharCount, LPSTR lpDstStr, LPINT lpnMultiCharCount ); auto ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddress(h, "ConvertINetUnicodeToMultiByte"); DWORD mode = 0; char ch[100]; int cps[] = { 51932, 50221 }; for (size_t icps = 0; icps < sizeof(cps)/sizeof(cps[0]); ++icps) { using namespace std; cout << "[codepage=" << cps[icps] << "]" << endl; INT len = sizeof(ch) / sizeof(ch[0]); ConvertINetUnicodeToMultiByte(&mode, cps[icps], L"髙", NULL, ch, &len); for (decltype(len) i = 0; i < len; ++i) { cout << hex << setw(2) << setfill('0') << static_cast<uint32_t>(static_cast<uint8_t>(ch[i])) << dec << " "; } cout << endl; } FreeLibrary(h); } //[codepage = 51932] //fc e2 //[codepage = 50221] //1b 24 42 7c 62 1b 28 42 ただし以下の関数には厳しい但し書きがついています。 https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741107(v=vs.85) > [ConvertINetUnicodeToMultiByte is available for use in the operating systems specified in the > Requirements section. It may be altered or unavailable in subsequent versions. Instead, use > MultiByteToWideChar or WideCharToMultiByte. ] ※public domainですが、↓のコードを参考にしています。 https://github.com/win-iconv/win-iconv/blob/v0.0.8/win_iconv.c
guest

0

回答ではありません。

なんか質問者から中途半端な返事と結果だけ聞く質問が多く、これを見たらと言っても調べてる気配すらなく、話が進みそうにないので、とりあえず調査用のコードを貼っておきます。

cpp

1#include <iostream> 2#include <string> 3#include <map> 4#include <vector> 5#include <iomanip> 6#include <windows.h> 7auto create_sjis2ws() { 8 std::map<std::string, std::wstring> sjis2ws; 9 char ch[3]; 10 ch[1] = 0; 11 ch[2] = 0; 12 for (ch[0] = 0x20; ch[0] != 0; ++ch[0]) { 13 wchar_t wch[3]; 14 int len = MultiByteToWideChar(932, MB_ERR_INVALID_CHARS, ch, 1, wch, sizeof(wch) / sizeof(wch[0])); 15 if (len == 1) { 16 sjis2ws[std::string(ch)] = std::wstring(1, wch[0]); 17 } 18 else { 19 for (ch[1] = 0x20; ch[1] != 0; ++ch[1]) { 20 int len = MultiByteToWideChar(932, MB_ERR_INVALID_CHARS, ch, 2, wch, sizeof(wch) / sizeof(wch[0])); 21 if (len == 1) { 22 sjis2ws[std::string(ch)] = std::wstring(1, wch[0]); 23 } 24 } 25 26 } 27 } 28 return sjis2ws; 29} 30template<typename K, typename V> 31auto create_ws2sjis(const std::map<K,V>& sjis2ws) { 32 std::map<std::wstring, std::vector<std::string>> ws2sjis; 33 for (const auto& sjis2ws_pair : sjis2ws) { 34 const auto& sjis = sjis2ws_pair.first; 35 const auto& ws = sjis2ws_pair.second; 36 auto it = ws2sjis.find(ws); 37 if (it == ws2sjis.end()) { 38 it = ws2sjis.insert(std::make_pair(ws, std::vector<std::string>())).first; 39 } 40 it->second.push_back(sjis); 41 } 42 return ws2sjis; 43} 44const struct sequence_type { 45 std::string escapes; 46 std::string name; 47 int char_length; 48} seq_type[] = { 49 {"\x1b(B", "ASCII", 1}, 50 {"\x1b(J", "JIS X 0201-1976", 1}, 51 {"\x1b$@", "JIS X 0208-1978", 2}, 52 {"\x1b$B", "JIS X 0208-1990", 2}, 53 {"\x1b$(D", "JIS X 0212-1990", 2}, 54 {"\x1b$A", "GB 2312-80", 2}, 55 {"\x1b$(C", "KS X 1001-1992", 2}, 56 {"\x1b.A", "ISO/IEC 8859-1(high)", 1}, 57 {"\x1b.F", "ISO/IEC 8859-7(high)", 1}, 58 {"\x1b$(O", "JIS X 0213:2000(1)", 2}, 59 {"\x1b$(P", "JIS X 0213:2000(2)", 2}, 60 {"\x1b$(Q", "JIS X 0213:2004(1)", 2}, 61 {"\x1b(I", "JIS X 0201(kana)", 1}, 62 //{"\x1b$(?", "JIS X 0208-1990(gaiji)", 2}, 63}; 64template<typename T> 65auto create_jis2ws(const T& ws2sjis) { 66 std::map<std::pair<std::string, std::string>, std::wstring> jis2ws; 67 for (const auto& ws2sjis_pair : ws2sjis) { 68 const auto& ws = ws2sjis_pair.first; 69 char jis[100]; 70 auto len = WideCharToMultiByte(50221, 0, ws.c_str(), static_cast<int>(ws.length()), jis, sizeof(jis) / sizeof(jis[0]), NULL, NULL); 71 if (len <= 0 || (jis[0] == '?' && ws[0] != L'?')) continue; 72 std::string jisstr(jis, len); 73 const sequence_type* pst = &seq_type[0]; 74 for (const auto& st : seq_type) { 75 const auto& esc = st.escapes; 76 if (jisstr.substr(0, esc.length()) == esc) { 77 pst = &st; 78 jisstr = jisstr.substr(esc.length(), st.char_length); 79 break; 80 } 81 } 82 jis2ws[std::make_pair(pst->name, jisstr)] = ws; 83 } 84 return jis2ws; 85} 86template<typename JIS, typename WS, typename SJIS> 87void print_JISX0212_1990(const std::map<JIS,WS>& jis2ws, const std::map<WS, SJIS>& ws2sjis) { 88 std::cout << "<pre>" << std::endl; 89 for (const auto& jis2ws_pair : jis2ws) { 90 const auto& jis = jis2ws_pair.first; 91 const auto& ws = jis2ws_pair.second; 92 if (jis.first == "JIS X 0212-1990") { 93 std::wcout << jis2ws_pair.second; 94 std::cout << ":Unicode(BMP)(" 95 << std::hex 96 << std::setw(4) << std::setfill('0') << static_cast<int>(ws[0]) 97 << std::dec 98 << ")"; 99 std::cout 100 << ": ISO-2022-JP-2(" << jis.first << ")" 101 << "("; 102 for (auto ch : jis.second) { 103 std::cout 104 << std::hex 105 << std::setw(2) << std::setfill('0') 106 << static_cast<int>(ch) 107 << std::dec; 108 } 109 std::cout 110 << "): Windows_31J"; 111 std::cout 112 << std::hex; 113 for (const auto& s : ws2sjis.at(ws)) { 114 std::cout << "(" << std::hex; 115 for (auto ch : s) { 116 std::cout << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<unsigned char>(ch)); 117 } 118 std::cout << std::dec << ")"; 119 } 120 std::cout 121 << std::endl; 122 } 123 } 124} 125int main(int argc, char* argv[]) 126{ 127 auto r = setlocale(LC_CTYPE, argc > 1 ? argv[1] : ""); 128 if (r == nullptr) { 129 std::cerr << "invalid locale!" << std::endl; 130 return 1; 131 } 132 auto sjis2ws = create_sjis2ws(); 133 auto ws2sjis = create_ws2sjis(sjis2ws); 134 auto jis2ws = create_jis2ws(ws2sjis); 135 print_JISX0212_1990(jis2ws, ws2sjis); 136 return 0; 137}

cmd

1C:\>hoge.exe .UTF-8 >hoge.html 2C:\>hoge.html

投稿2024/02/07 04:15

編集2024/02/08 10:27
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問