文字コード

計算機で文字を扱う場合、内部では文字に付けた番号を元に管理している。 計算機で利用できる文字には全て番号がついている。この番号のことを 文字コードという。

ASCIIコード

abcdefg... ABCD..., 0123..., !@#$ () などの、日本語入力OFFのまま入れ られる文字や記号には全てASCIIコード(American Standard Code for Information Interchange)が割り当てられている。

ASCIIコード表を以下に示す。

0123456789ABCDEF
0NULSOHSTXETXEOTENQACKBELBSHTLFVTFFCRSOSI
1DLEDC1DC2DC3DC4NAKSYNETBCANEMSUBESCFSGSRSUS
2 !"#$%&'()*+,-./
30123456789:;<=>?
4@ABCDEFGHIJKLMNO
5PQRSTUVWXYZ[\]^_
6`abcdefghijklmno
7pqrstuvwxyz{|}~DEL

この表は16進数での文字コード表記となっている。最左列の縦に並ぶ0-7が 16進数の10の位で、最上行の横に並ぶ0-Fが16進数の1の位である。たとえば、 アルファベットの大文字Aは、「4の行」の「1の列」にあるので、 16進数の「41」が文字コードとなる。以下、16進数の数字を表 すときは、先頭に 0x を付けて表す。「16進数41」==「0x41」

表中、文字コード 0x00 - 0x1Fは、制御文字といい主に端末を制御 するための文字コードが並んでいる。代表的なものとしては、

などがある。これらの制御文字をキーボードから入力するときは、制御文字 の文字コードに0x40を足した文字を、Ctrlキーを押しながらタイプ する。つまり、0x09のHTは、0x40を足した0x49がI なので、C-i が対応するキーとなる。また、慣習的に 0x00のNULは C-SPC(Ctrlを押しながらスペース)に対応させることが多い。 まとめると

0x00 NUL
C-@ (またはC-SPC)
0x01 SOH - 0x1A SUB
C-a - C-z
0x1B ESC - 0x1E RS
C-[ - C-^
0x1F US
C-_ または C-/

という風にキー入力できる。ただし、現在ではこれらの制御文字を直接画面 に出すことはほとんどないので、C-英字 などのキー入力にはカーソ ル移動したり、画面を消したりするなどの「機能」が割り当てられていることが 多い。

実際に、これらの制御文字そのものを入力したいときには

をタイプする。ためしに、BELコードを使って、端末(Terminal)のベ ルを鳴らしてみよう。Terminalで次のようにタイプする。

echo "^G"
  (^Gの部分は C-v C-g とタイプする)

Terminalで順に e c h o スペース " C-v C-g " とタイプすると、画面に echo "^G" と出ているはずな ので、それを確認したら最後に [Return] を押す。

ピッ

と音が出るはずである。ここで利用した echo というコマンド は、後続する引数をそのまま出力するものである(シェルの内部コマンド)。

また、0x1B のESC コードも端末制御をするのによく用いられ る。ESC コードに続いて一連の決まった文字を端末に出力すると、 端末の文字の種類を変えたりすることができる。有名なものに、文字色を変える エスケープシーケンスがある。

ためしに、画面に黄色の文字を出してみよう。ESC コードはシェル上とRubyプログラムでは \e で表せる。 C-v ESC とタイプしよう。

echo "Hello \e[33mworld"
Hello world

のように色の変わったメッセージが表れる。

Rubyプログラムでの文字コードの扱い

他のプログラミング言語と比較すると、Rubyでは文字コードのことを意識し なくてもプログラミングできる範囲が広くなっている。上記のように画面に出す メッセージの色を変えたいようなときは文字コードを意識する必要がある。

ある文字コードのものを画面に出力したい場合は、printf の フォーマット文字列のところに %c を指定する。たとえば、

printf("%c", 0x07)

とすると、文字コード 0x07 つまりBELが出力さ れ、端末のベルが鳴る。やってみよう。

irb
irb(main):001:0> printf("%c", 0x07)

文字コードを実際の文字に変換するのが %c である ならばその逆は何だろう。ある文字の文字コードを得るには ?文字.ord を使う。プログラム中に ?a.ord と書けば、それは 文字 'a' の文字 コード(つまり0x61)と書いたのと同じことになる。?9.ord と書けば '9' の文字コード(つまり0x39)と書いたのと同じことになる。 次のプログラムは、ASCIIコード表のうち、'!'(0x21) - 'z'(0x7A) の範囲の文字全てを出力するものである。

ascii.rb

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

char = ?!.ord			# ! の文字コード(==0x21)

while char <= ?Z.ord
  printf("ascii-code %3d(0x%02x): %c\n", char, char, char)
  char += 1
end

上記のプログラム ascii.rb を実際に実行してみること

文字列と文字コード

Rubyプログラム中の文字列は、あたかも文字コードの数値が並んで入ってい る配列のように考えることができる。たとえば、"Hello" という文字 列を考えよう。各文字の文字コードを調べると、Hは0x48、eは0x65、lは0x6c、o は0x6fとなる。これらの数値が並んで配列に入ったものをイメージしよう。

0 1 2 3 4
H e l l o
0x48 0x65 0x6c 0x6c 0x6f

文字列 "Hello" の最初の部屋(0号室)を取り出すときは、 配列のときと同様大括弧[ ]を利用する。

printf("%c\n", "Hello"[0])
↓
H
printf("%x\n", "Hello"[0].ord)     (.ordにより文字コードが得られる)
↓
48   (これは16進数。以下も同じ)
printf("%x\n", "Hello"[1].ord)
↓
65

(以下同様)

これを文字列の先頭から、末尾まで繰り返すプログラムは以下のようになる。

hellocode.rb

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

hello = "Hello"
i = 0

while i < hello.length
  printf("%c → 0x%x\n", hello[i], hello[i].ord)
  i += 1
end

本日の目次