char型の配列にひらがなの文字列を格納してみます そのときひらがなの文字列はchar型の配列内に生成された配列変数にどのように格納されているのでしょうか?

ソーラー「あの 全角文字のひらがなって


char型配列に格納することができるのかな?


だって


char型の配列によって作られる


配列内の文字の入れ物


配列変数って


例えば


hairetuのchar型の配列宣言


char hairetu[3];


によって作られる


char型の配列変数


hairetu[0]

hairetu[1]

hairetu[2]


となっているけど


この


hairetu[0]

hairetu[1]

hairetu[2]


はchar型なので1バイトまでしかデータを格納できないはずだよね


あんまり関係ないかもしれないけど


前のエピソードで次のような例があったよね。


#include <iostream>


using namespace std;


int main() {


char a='あ';


cout<<a<<"\n";


return 0;


}


このプログラムをビルド実行すると



警告 C4305 '初期化中': 'int' から 'char' へ切り詰めます。

警告 C4309 '初期化中': 定数値が切り捨てられました。


と表示されますが



コマンドプロンプト画面に



が表示されます



____________________________________________________


警告 C4309 '初期化中': 定数値が切り捨てられました。

警告 C4305 '初期化中': 'int' から 'char' へ切り詰めます。



"2バイト文字である'あ'から1バイト分だけデータをchar型に格納している"


ということを警告しています。



このことは後述されます。  

           


                solarplexussより


____________________________________________________


ソーラー「


このように なんか


ひらがなは


うまくchar型の変数aに格納できなかったよね」



てんC「はい そうでしたね。


それでは


実際に


char型の配列に


ひらがな ねこねこ の文字列を


格納してみましょう。ソーラーさん。😊


プログラムを以下のように構成してみました。



#include <iostream>


using namespace std;


int main() {


char hairetu[]="ねこねこ";


cout<< hairetu<<"\n";


return 0;


}


てんC「ビルドっ」


ソーラー「おっとっとっ」


ソーラー「てんC おっとっと


ていう おかしを


ビルドをきいておもいだしちゃったな」



ビルド実行結果


ねこねこ



ソーラー「おおぅ ひらがなもchar型の配列に格納できてるね」


てんC「ひらがなもchar型の配列に格納できるのですの


簡単でした。」



ソーラー「このとき



char型の配列変数宣言、初期化


char hairetu[]="ねこねこ";


によって生成される配列変数は


次のように


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]



の9つになるんじゃないかな?


ひらがな1文字は2バイト文字だから


ねこねこは合計8バイトのデータ量をもつことになる。


8バイトのデータ量を格納するには


1バイトのデータを格納できるchar型の配列変数が8つ


hairetu[0]👈1バイトのデータ格納容量をもちます

hairetu[1]👈1バイトのデータ格納容量をもちます

hairetu[2]👈1バイトのデータ格納容量をもちます

hairetu[3]👈1バイトのデータ格納容量をもちます

hairetu[4]👈1バイトのデータ格納容量をもちます

hairetu[5]👈1バイトのデータ格納容量をもちます

hairetu[6]👈1バイトのデータ格納容量をもちます

hairetu[7]👈1バイトのデータ格納容量をもちます



いるはずだよね。


それに


ねこねこを


まとまった1つの文字列とコンピュータに認識させるのに


ヌル文字\0



hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]


に格納された


ねこねこにつづいて


char型の配列変数


hairetu[8]


に格納させる必要があるので



文字列 ねこねこ を配列に格納するには


合計9個のchar型の配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


が必要になると思うんだ。


さて


どのようにひらがなの文字列データ


"ねこねこ"



これらの


配列変数に格納されているのかな?


1バイト文字ずつしか


char型の配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


には格納できないよね。


2バイト文字のひらがなをどうやって格納しているのかな?


🌞


ソーラーはねこねこのデータ量


8バイト


それにねこねこのあとに


ねこねこを文字列とするためにつけられるヌル文字\0のデータ量


1バイト


合計9バイト


をchar型配列に格納しようとしているので


char型の配列には


1バイトの文字データを格納する


char型の配列変数が9バイト分


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


の9つ用意されると予想しています


🌞


てんC「それでは


char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


にどのようにひらがなのデータが格納されているか


char型の配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


に格納されているデータを


直接


cout出力表示してみます。


プログラムを以下のように構成しました。


文字列データ"かくかく"をchar型の配列hairetuに格納しています。」


#include <iostream>


using namespace std;


int main() {


char hairetu[] = "かくかく";


cout << hairetu[0] << "\n";

cout << hairetu[1] << "\n";

cout << hairetu[2] << "\n";

cout << hairetu[3] << "\n";

cout << hairetu[4] << "\n";

cout << hairetu[5] << "\n";

cout << hairetu[6] << "\n";

cout << hairetu[7] << "\n";

cout << hairetu[8] << "\n";

return 0;


}


ソーラー「それでは ビルド実行すると・・・」


ビルド実行結果


(空白)

続行するには何かキーを押してください . . ._



ソーラー



〘か〙 が




〘く〙 が



にあたるのかな?




コンパイル結果の


〘ュ〙



〘続行するには何かキーを押してください . . ._〙


の間が空白スペースになっているのは


\0がcout出力表示されると


空白が表示されるからだね。」


てんC「


ひらがな か の画像データ情報を呼び出すためのデータが


メモリ内で


次のように2バイト(16ビット)


0100101010101010で表されているとすると


char hairetu[]="かくかく";


によって生成されるchar型の配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]



まずは


hairetu[0]に


0100101010101010の右から8ビット分(1バイト分)の


10101010が収められ


その次に


hairetu[1]に


0100101010101010の左から8ビット分(1バイト分)の


01001010がおさめられているとおもわれます。


つまり

画像データ か の

データ情報を呼び出すためのデータが


0100101010101010の

2バイトの情報量をもっていたとしても


hairetu[0]

hairetu[1]


を通して


1バイトずつ分割して


メモリに格納されているのではないでしょうか?




hairetu[0]だけに 


画像データ か



格納しなくても



つまり



hairetu[0]だけを通して


画像データ か の

データ情報を呼び出すためのデータ


0100101010101010



メモリに格納しなくてもよいわけですね。



1バイトしか格納容量のないchar型 の変数a


に ひらがな か を格納するときとは違い



このように ひらがな か も



配列charの配列変数に分割して


格納することができるわけです。


そして


hairetu[0]のアクセスしているメモリには01001010

hairetu[1]のアクセスしているメモリには10101010


と分割して格納されたデータを


cout << hairetu[0] << "\n";

cout << hairetu[1] << "\n";


とcout出力表示すると


01001010

10101010


に対応した画像データ



が表示されるのではないでしょうか?」



ソーラー「そんな感じがするね😊」



てんC「もう1つ


ひらがなの文字列 るんるんは どのように


char型の配列変数宣言


char hairetu[]="るんるん";


によって生成される配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


に格納されているか試してみます。


以下のようにプログラムを構成して


#include <iostream>


using namespace std;


int main() {


char hairetu[] = "るんるん";


cout << hairetu[0] << "\n";

cout << hairetu[1] << "\n";

cout << hairetu[2] << "\n";

cout << hairetu[3] << "\n";

cout << hairetu[4] << "\n";

cout << hairetu[5] << "\n";

cout << hairetu[6] << "\n";

cout << hairetu[7] << "\n";

cout << hairetu[8] << "\n";

return 0;


}


ソーラー「ビルドすると・・」



ビルド実行結果


空白

空白

空白

空白

空白

空白

空白

空白

空白


ソーラー「??どうなってるのかな これ?」


てんC「おそらく画像データ る の


データ情報が


1001101010101101(2バイト)で表現されていると


すると


そのままでは


1バイトしかデータ容量をもたないchar型の配列変数には


格納できないので


hairetu[0]に1001101010101101の右から1バイト(8ビット)分の10101101


を格納


hairetu[1]に1001101010101101の左から1バイト(8ビット)分の10011010


を格納


という具合に


1バイトずつ分割して


格納しているのではないでしょうか?


そして


cout << hairetu[0] << "\n";

cout << hairetu[1] << "\n";


を実行するとビルド実行結果が


空白

空白

同じ

空白

が表示されていますね。


hairetu[0]

hairetu[1]

をとおしてメモリに格納されているデータは


格納されている数値は


10011010

10101101


とそれぞれ違うのに


同じ空白が表示されるのは


ある数値データには半角英数字などの記号が割り当てられていますが


それ以外の数値


この場合の


10011010

10101101


のようなものには


すべて

空白

が割り当てられているからでないでしょうか


ソーラーさん😊」


ソーラー「おぉっ そうかもしれないね


トレビアーンだね」




まだまだ💖




このお話は仮説の段階となっています。


C言語では


char型の配列hairetuに


char hairetu[] = "るんるん";


と格納された文字列データ"るんるん"


printf("%c\n", hairetu[0]);

printf("%c\n", hairetu[1]);

printf("%c\n", hairetu[2]);

printf("%c\n", hairetu[3]);

printf("%c\n", hairetu[4]);

printf("%c\n", hairetu[5]);

printf("%c\n", hairetu[6]);

printf("%c\n", hairetu[7]);

printf("%c\n", hairetu[8]);

printf("%c\n", hairetu[9]);


をもちいて

printf出力表示すると


コンパイル結果



が表示されます。


空白が表示されるか

が表示されるかの違いがあります。


おそらく


10011010

10101101

に対応する文字データ


をコンパイラは参照するのですが


参照元を


C言語ではシフトJISコード


C++言語ではユニコード


に設定しているため


このような違いがでるのではないかと・・・・・


推測しています。


つまり


シフトJISコードでは


10011010

10101101

に対応する文字データは



ユニコードでは


10011010

10101101

に対応する文字データは


空白


になっているとただいま仮説を立てています


                solarplexussより





  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る