今回は文字を入れる変数、つまり「文字変数」です。まずは1文字変数から見ていきましょう。
/*01*/ #include <stdio.h>
/*02*/
/*03*/ main()
/*04*/ {
/*05*/ char ch;
/*06*/
/*07*/ ch = 'a';
/*08*/
/*09*/ printf("ch = %c\n", ch);
/*10*/
/*11*/ return 0;
/*12*/ }
変数の型が char になっています。char は 8bit 整数(-128~127の整数)を扱える型でしたが、整数を扱う以外に文字を扱うときに用いることの多い型でもあります。ここでは、文字を扱うための型として見ていきましょう。
次に初期化です。この例では ch に「a」を代入(初期化)しているのですが「a」は「’(シングルクウォーテーション)」で挟まれていますね。シングルクウォーテーションにより代入するものが1文字であることを表します。なお、初期化は整数の場合と同様、宣言時にも行うことができます。
printf で1文字変数を表示するには変換文字を「%c」とします。ちなみに、第2引数には直接文字を書いてもかまいません。
printf("ch = %c\n", 'a');
ところで、文字型変数には実際に「a」という文字が入っているわけではありません。コンピュータは原則として「0」と「1」の情報しか扱うことが出来ません。しかし、逆に言えば2進数は使えるわけで、そのため int 型なら 4byte(=2の32乗)分の数字が表せるという仕組みでした。
そこでコンピュータでは、文字を2進数に対応させて扱っています。どういうことかというと、たとえば「1100001(=97)」という2進数には「a」が対応付けられていて、「1100010(=98)」という2進数には「b」が対応付けられています。そして、文字に対応付けされた数を「文字コード」といい、その規則は「ASCII(アスキー) 文字コード」というもので標準化されています。なお、ASCII 文字はアルファベットなどがほとんどで、 7ビット分あればすべて表すことができます。そのため、文字を扱うには 8bit(1byte) の char 型変数を用意し、指定された文字の文字コードの値を格納するのです。
さて、文字変数には文字コード、すなわち数値が格納されているわけですから、printf の中で変換文字を「%d」にすると、10進数でそのコードを知ることができます。なお、第2引数の部分は変数でなく直接「'a'」とやってもかまいません。
printf("a = %d\n", 'a');
ということは、逆に変換文字を「%c」にしておいて第2引数に「文字コード」を書くとどうなると思いますか?
printf("97 = %c\n", 97);
さらに、この文字コードにはおなじみの「\n」なども改行コードとして定義されていて、変換文字を「%d」にしておいて第2引数を「'\n'」とするとそのコードを見ることができます。
ちなみにもうお気づきの方もいるかもしれませんが、文字といえども所詮は数値。int 型の変数に ASCII コードを入れて変換文字「%c」とやってもきちんと文字が出てきます。
なお、平仮名や漢字などの文字は「2バイト(全角)文字」と呼ばれ char 型変数 1つでは使えません。漢字は、char 型2つ(つまり2バイト)で1文字となるので、次章でやる「文字列」として扱います。
次の説明に入る前に、文字コード表を表示するソース list-4.1.2 を載せてますので、実行して文字コードを確認してみてください。
/*01*/ #include <stdio.h>
/*02*/
/*03*/ main()
/*04*/ {
/*05*/ int i, j;
/*06*/
/*07*/ for(i = 0; i < 16; i++){
/*08*/ for(j = 0; j < 8; j++){
/*09*/ if( i + j*16 == 7 ||
/*10*/ i + j*16 == 8 ||
/*11*/ i + j*16 == 9 ||
/*12*/ i + j*16 == 10 ||
/*13*/ i + j*16 == 13 ||
/*14*/ i + j*16 == 26 ||
/*15*/ i + j*16 == 27){
/*16*/ printf("%3d: * ", j*16 + i);
/*17*/ continue;
/*18*/ }
/*19*/ printf("%3d: %-3c", j*16 + i, j*16 + i);
/*20*/ }
/*21*/ printf("\n");
/*22*/ }
/*23*/
/*24*/ return 0;
/*25*/ }
/*
注意1:コード「8・9・10・13」は制御文字のため
if 文で例外扱いにします。
同様にコード「7・26・27」は調整のため
if 文で例外扱いにします。
注意2:このソースは Win98 上の VC++6.0 で
確認しました。状況によってはうまく表示
できないかもしれません。その場合、
「注意1」同様に if 文で制御してください。
printf 文で表示するための表の構成
--------------------------------------------------------
| 15*0 + 0 | 15*1 + 0 | 15*2 + 0 | ........ | 15*7 + 0 |
|----------|----------|----------|----------|----------|
| 15*0 + 1 | 15*1 + 1 | 15*2 + 0 | ........ | 15*7 + 0 |
|----------|----------|----------|----------|----------|
| 15*0 + 2 | 15*1 + 2 | 15*2 + 0 | ........ | 15*7 + 0 |
|----------|----------|----------|----------|----------|
| 15*0 + 3 | 15*1 + 3 | 15*2 + 0 | ........ | 15*7 + 0 |
|----------|----------|----------|----------|----------|
| : | : | : | : | : |
| : | : | : | : | : |
|----------|----------|----------|----------|----------|
| 15*0 + 15| 15*1 + 3 | 15*2 + 0 | ........ | 15*7 + 15|
--------------------------------------------------------
内側の for ループで横向きに1行表示し、
それが終わったら改行して次の行(外側の for ループ)へ
うつります。
*/
さて、文字がタダのコード(数値)であることを考えるとこんなこともできます。
ch = 'e' - 3;
ch = 101 - 3;
ch = 98;
ch = 'e' ch -= 'a' - 'A';
ch = 101; ch -= 97 - 65;
ch = 'e' ch += 'A' - 'a'
小文字か大文字のアルファベットを入力し、小文字なら大文字に、大文字なら小文字に変換してください。
#include <stdio.h>
main()
{
char ch;
printf("アルファベットを入力してください。: ");
scanf("%c", &ch);
if('a' <= ch && ch <= 'z'){
ch -= 'a' - 'A';
printf("変換しました。 -> %c\n", ch);
}else if('A' <= ch && ch <= 'Z'){
ch += 'a' - 'A';
printf("変換しました。 -> %c\n", ch);
}else{
printf("小文字か大文字のアルファベットを入力してください。\n");
}
return 0;
}