※「セキュリティ保護のため...」というメッセージが出る方・日本語が入力できない方へ
文字の表現


数字と文字

初期のコンピュータは数だけを扱っていればよかったが、やはりそのうち文字も扱おうという動きが出てくる。例えば計算結果を印刷するのに

    135.72   23.98  17.16
などのように、数字だけを並べられるより
    sum = 135.72,  mean = 23.98,  standard deviation = 17.16
のように印刷してもらった方が、見やすいというものである。

そのため、コンピュータというのは文字も扱うようになるのであるが、初期のFORTRANには、この文字を扱う専用の仕組みは存在しなかった。そのため、文字も普通の数字用の変数(の配列)に格納して使用し、入出力の際はA変換というものを使って、読み書きした。

この伝統はCにも受け継がれており、Cは文字専用のデータ形式を持たない。通常1バイト整数を格納するためのタイプである char型の変数の配列に格納し、sscanf/sprintf の %c や %s で変換するようになっている。

これに対して、COBOLの場合は逆に全てのデータが文字の世界だが、特に数としては使用しないというものを X というpictureで表現することにしていた。数の場合は 9 である。このほかCOBOLの場合は編集型として Z とか ¥ とかいったpictureも使用できる。

Perlもテキスト整形用として生まれた言語なので、このCOBOLの方式を継承している。同系列に属するものとしてはJavaやHyperScriptなどもある。

明確に数と文字を分離して考えるようになったのは確か ALGOL からではなかったかと思う。(確認しようと思ったがALGOLを勉強した時のノートが出てこなかった。なにせ20年前のノートなので。。。)

BASICの場合は、タイプを変数の接尾辞で分けるという考え方を取り、数は A%とかA#などで表現し、文字列はA$で表現するといったやり方を採用した。(ただしこの接尾辞の使い方は処理系によって異なる。これがBASICの互換性の悪さのひとつである)

C++では、Cと同様に char型の変数で文字列を扱うことも可能だが、文字列専用の String という型を持っている。このStringは基本的にBASICの文字型の考え方を継承するものだが、使い勝手は遙かによくなっている。

文字列の維持の仕方

文字列のコンピュータ内部での維持の仕方は大きく3通りがある。

(1)COBOL方式(固定長方式)

COBOLやFORTRANなどで文字列を扱う時はだいたいこういう方式である。

この場合、文字列は単にそこにあるだけで、何の管理もされない。文字列の終わりがどこかというのはプログラム側がきちんと管理しておく必要がある。

例えばCOBOLで

    01  CONST-AREA.
        02 A.
           03  A-1    PIC X(06) VALUE "TODAY "
           03  A-2    PIC X(03) VALUE "IS "
           03  A-2    PIC X(07) VALUE "SUNDAY."
のようになっていた場合、A-1を出力すれば TODAY しか出力されない。C的な考えだと TODAY IS SUNDAY. まで出そうなものだが、そこまで出力するには A-1 ではなく A を出力する必要があるのである。

(2)BASIC方式(可変長方式)

BASICの文字列では先頭に文字列の長さが書かれていて、そのあとに文字列が続くようになっている。たとえば上記の "TODAY IS SUNDAY." をBASICのプログラム上で書いた場合は、実際にはコンピュータの中には、16,T,O,D,A,Y, ,I,S, ,S,U,N,D,A,Y,. のように格納されるのである(実際にはもう少し制御データが付加されることがある。また文字列自体は別のところに格納され、そこへのポインタのみが記録される処理系も多い)。BASICプログラムはこの先頭の長さのところを見て、その文字列を処理する。

多くの昔のBASICはこの長さのところが1バイトであったため、255文字を越える文字列を扱うことができなかった。

Pascalの文字列や、C++のString型もこのBASIC方式である。むろんC++では先頭の文字列の長さは通常4バイトで処理されるので、一度に4GBまでの文字列を扱うことが理論上可能である。

(3)C方式(不定長方式)

Cの文字列は最後に null (0) を付けることで管理される。この方式は管理が楽なのが特徴で、あまりオーバーヘッドを起こさずにいろいろな処理を記述したいCにはとてもよくあったデータ管理方式である。

つまり、上記の文字列の場合、Cでは実際には T,O,D,A,Y, ,I,S, ,S,U,N,D,A,Y,.,0h のように記録されるわけである。そのため、strlen のような関数は PascalやBASICでは先頭の文字列長を読めば答えが得られる軽いものであるのに対して、Cでは文字列を実際にたどってみないと得られない重たいものとなる。(実際にはCPUの文字検索命令で一発で答えは返ってくる。しかし1ワード moveすれば済む Pascal よりは当然遅い)

ASCIIとEBCDIC

数のところにも書いたのだが、文字をコード化する時の方式が実はASCII(=JIS)とEBCDICという2通りの流儀がある。ASCII (American Standard Code for Information Interchange) はアメリカの ANSI (American National Standards Institue) が定めたもので、EBCDIC (Extended Binary Coded Decimal Interchage Code) はIBM社が作ったものである。日本では JISコードが定められているが、ASCIIの後半のあまり使われない部分にカナ文字を埋め込んだものなので、事実上 ASCIIと同じものと思ってよい。

一般に汎用機とかメインフレームとか呼ばれた機械やオフコンと呼ばれた機械はEBCDICを使用しており、パソコンやミニコンはASCIIコードを使用している。1980年代に国内で数百万台も売れた日本電気のN5200などは、中身はパソコンだが基本的にメインフレームとの互換性を歌っていたため、内部の処理はASCIIで行い、ファイルにはEBCDICで書くとという折衷方式を採用していた。このためN5200でプログラムを組むプログラマにとっては、数字と英字のどちらが先に処理されるかというのは頭の痛い問題だった。(ASCIIでは数字が先、EBCDICでは英字が先)

このふたつのコード体系の並びに規則性は全くないので、両者は対応表を見ながら変換する以外に手はない。下記にその一覧表および変換用データをあげる。

【JISコード表】
 
NULDLESP          
SOHD1        
STXD2        
ETXD3        
EOTD4        
ENQNAK       
ACKSYN       
BELETB       
BS CAN       
TABEM        
LF CEX       
VT ESC       
FF FS        
CR GS        
SO RS        
SI US _          
【EBCDICコード表】
 
NULDLE    SP
SOHD1        
STXD2   SYN 
ETXD3      
         
TABLF      
  BS ETB   
    ESCEOT 
  CAN     
  EM      
               
VT              
FF FS   D4        
CR GS ENQNAK_        
SO RS ACK         
SI US BELCEX       


unsigned char E2J[]=
  {0x00,0x01,0x02,0x03,0x9c,0x09,0x86,0x7f,0x97,0x8d,0x8e,0x0b,0x0c,0x0d,0x0e,0x0f,
   0x10,0x11,0x12,0x13,0x9d,0x0a,0x08,0x87,0x18,0x19,0x92,0x8f,0x1c,0x1d,0x1e,0x1f,
   0x80,0x81,0x82,0x83,0x84,0x85,0x17,0x1b,0x88,0x89,0x8a,0x8b,0x8c,0x05,0x06,0x07,
   0x90,0x91,0x16,0x93,0x94,0x95,0x96,0x04,0x98,0x99,0x9a,0x9b,0x14,0x15,0x9e,0x1a,

   0x20,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0x5b,0x2e,0x3c,0x28,0x2b,0x21,
   0x26,0xaa,0xab,0xac,0xad,0xae,0xaf,0x61,0xb0,0x62,0x5d,0x5c,0x2a,0x29,0x3b,0x5e,
   0x2d,0x2f,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x7c,0x2c,0x25,0x5f,0x3e,0x3f,
   0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x60,0x3a,0x23,0x40,0x27,0x3d,0x22,

   0x74,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0x75,0xbb,0xbc,0xbd,0xbe,
   0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0x76,0x77,0xca,0xcb,0xcc,
   0x78,0x7e,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0x79,0xd6,0xd7,0xd8,0xd9,
   0x7a,0xa0,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xda,0xdb,0xdc,0xdd,0xde,0xdf,

   0x7b,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0xe8,0xe9,0xea,0xeb,0xec,0xed,
   0x7d,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xee,0xef,0xf0,0xf1,0xf2,0xf3,
   0x24,0x9f,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,
   0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xfa,0xfb,0xfc,0xfd,0xfe,0xff};

unsigned char J2E[]=
  {0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f,0x16,0x05,0x15,0x0b,0x0c,0x0d,0x0e,0x0f,
   0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26,0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,
   0x40,0x4f,0x7f,0x7b,0xe0,0x6c,0x50,0x7d,0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,
   0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,

   0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,
   0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0x4a,0x5b,0x5a,0x5f,0x6d,
   0x79,0x57,0x59,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x70,0x71,0x72,0x73,0x74,
   0x75,0x76,0x77,0x78,0x80,0x8b,0x9b,0x9c,0xa0,0xab,0xb0,0xc0,0x6a,0xd0,0xa1,0x07,

   0x20,0x21,0x22,0x23,0x24,0x25,0x06,0x17,0x28,0x29,0x2a,0x2b,0x2c,0x09,0x0a,0x1b,
   0x30,0x31,0x1a,0x33,0x34,0x35,0x36,0x08,0x38,0x39,0x3a,0x3b,0x04,0x14,0x3e,0xe1,
   0xb1,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x51,0x52,0x53,0x54,0x55,0x56,
   0x58,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8c,0x8d,0x8e,0x8f,0x90,

   0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9d,0x9e,0x9f,0xa2,0xa3,0xa4,
   0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xac,0xad,0xae,0xaf,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
   0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xda,0xdb,
   0xdc,0xdd,0xde,0xdf,0xea,0xeb,0xec,0xed,0xee,0xef,0xfa,0xfb,0xfc,0xfd,0xfe,0xff};


(C)copyright ffortune.net 1995-2007 produced by ffortune and Lumi.
お問い合わせはこちらから