

C言語でbase64のデコーダを作成しています。自分のやり方だと、例えばエンコードされた平仮名の「あ」をデコードするときに、2バイトのデータを一度10進数に変換しました。すると33440(0x82a0)の値が計算できてSJISの2バイトの文字コード表と照らし合わせると平仮名の[あ」を指しているのですが、2バイトのデータである(0x82a0)を文字に変換して出力する方法がわかりません。

環境  
win7 64bit  
vs 2013


CC BY-SA 4.0
2018-08-22T11:08:35.793
47729
2018-08-22T16:02:11.397
28645
question
c 文字コード
2バイトの10進数を全角文字に変換して出力する方法がわからない。


Base64と言うのは3バイト単位のバイナリデータをASCII文字中の特定の64文字から4文字を使って表すための方法です。元の「バイナリデータ」が何らかの文字列を表していたとしても、文字ごとの区切りが処理の区切りになることはありません。

例えば、元の文字列として`"Aあ"`なんて2文字からなる文字列を考えてみます。これをSJISのバイナリデータで表すと、

[code]

    41 82 A0
    
[/code]

の3バイトになります。これをBase64に変換する場合には、`41 82
A0`の3バイトをまとめて変換する必要があります。`"A"`と`"あ"`は別の文字だからといって、文字単位で処理するとBase64にはなりません。

[code]

    41 82 A0 ⇒ "QYKg"
    
[/code]

こうやって、なんらかのバイナリデータが元としてある場合に、それから(`"QYKg"`のような)文字列表現を作ることが、「Base64エンコード」です。このバイナリデータがどうやって作られたのか、はBase64とは直接の関係はありません。

* * *

逆に入力としてBase64の文字列がある場合、それを4文字ごとに区切って処理します。

今仮にBase64の入力が`"QYKg"`だったとします。この場合、全体がちょうど4文字ですから、この4文字をまとめて、バイナリデータに変換しないといけません。

で、その結果が`41 82 A0`と言う3バイトのバイナリデータになります。

で、この`41 82
A0`と言う3バイトのバイナリデータを作ると言う処理が、Base64のデコードをした、と言うことになります。その3バイトが実はSJIS文字列を表しているとかなんとかは、Base64とは直接関係なく、バイナリデータをいかに文字列として解釈するのか、と言った部分になります。

(追記)  
この「バイナリデータをいかに文字列として解釈するのか」まで必要なのであれば、C言語の文字列のルールに従って末尾にNULを付け加えてやるだけです。例えば`binBuf`なんて十分なサイズを持った`char`配列に`len`バイト(`int`型)の「バイナリデータ」が出来ているとしたら、

[code]

    //...あなたのBase64デコード処理の後
    binBuf[len] = '\0';
    printf("result=%s\n", binBuf); //-> Aあ
    
[/code]

と言ったコードを書いてやれば、一文字ずつ変換する必要なく元の文字列が表示されます。(もちろん出力先の端末の文字コードは元の文字列の文字コードと同じである必要があります。)

※Base64エンコードする前の元データに末尾のNUL文字を入れておけば、デコードした後NUL終端する必要がなくなるんですが、他言語で作ったBase64テキストと結果が違ってくるのであまりやりません。

* * *

いかがでしょうか?まだ何か違うと言う点があればおしらせください。


CC BY-SA 4.0
2018-08-22T12:29:00.427
47732
2018-08-22T16:02:11.397
2018-08-22T16:02:11.397
13972
13972
47729
answer