これまで、プログラム中で何回も文字列を扱ってきたのですが、
何故か、文字列を記憶する変数は1度も説明したことがありませんでした。
その理由は簡単です。C言語には文字列を記憶する変数がないからです。
文字列用の変数がないのは、文字列が特殊な性質を持つためです。
文字列は、何文字になるのかが事前に予測出来ません。
5文字程度で済むこともあれば、何千文字という文字数になることもあります。
この様に、場合によって必要とされるメモリのサイズが異なってくるのです。
この様な事情があるため、C言語には文字列用の変数がありません。
[ 他の言語では ]
C言語以外の多くの言語は、次の方法で文字列変数を用意しています。
1、メモリを固定的に確保(文字数が制限される上、メモリが無駄になる。)
2、メモリを可変的に確保(速度が遅くなる)
(1は古いBASICやPASCAL、2はJavaなど。C++にも2に似た機能がある)
C言語ではプログラマーが自由な方法を選べるので柔軟です。
前項では、C言語には、文字列変数はないと書きましたが、
文字列変数はなくても、文字変数であれば用意されています。
文字列と違い、文字は必ず1文字であるため、変数で扱うことが出来るのです。
C言語では、文字変数として、char(キャラ)型が用意されています。
char型の変数には、1文字を記憶しておくことが出来ます。
文字は '' で囲むことで表現します。
また、%c指定子を使えば、printf関数で表示することが出来ます。
次のプログラムは、char型の変数に文字を記憶して表示する例です。
このプログラムの実行結果は、次の通りになります。#include <stdio.h> int main(void) { char c = 'A'; printf("%c\n",c); return 0; }
この様に、char型を使えば、文字を変数と同様に取り扱うことが可能です。
A
[ 全角文字は駄目 ]
実は、この方法では、全角文字を扱うことは出来ません。
char型で記憶出来る文字の種類は最大で255種類が限界で、
何千文字もある日本語の文字を記憶しておくことは出来ないのです。
この問題を解決する手段として、wchar_t型が用意されているのですが、
入門書ではほとんど触れられていないようですし、
ややこしくなるので、wchar_t型については第2巻で扱うことにします。
前項では、char型で1文字を取り扱うことが出来ることを説明しましたが、
これは、コンピュータで使われる文字コードの仕組みを利用しています。
文字コードとは、文字に1対1で対応する番号をつけて表現する方法のことです。
[ 文字コード ]
コンピュータで使われる文字に1対1で対応する番号をつけて表現する方法。
ASCIIコードという規格では半角のアルファベットや記号が割り当てられている。
日本語を扱えるコードとして、JIS、シフトJIS、EUCが使われている他、
世界中の言語を扱えるコードとして Unicode が普及している。
例えば、前項のプログラムでは、'A' をchar型変数cに代入しましたが、
これは、A が65番に割り当てられているので、コンパイラが 'A' を 65 と解釈し、
その65がcに代入されただけのことに過ぎません。
また、printf関数で A が表示されたのも、変数の中身が65だったので、
printf関数の方で A と表示するように処理しただけのことなのです。
つまり、コンピュータでは全ての文字は番号で表されており、
char型はその番号を記憶しておくに過ぎないということなのです。
char型で記憶されている文字は、実は単なる番号であることを前項で説明しましたが、
このことを利用すれば、文字に対して計算を行うことも出来ます。
例えば、文字コードでは、基本的に文字の番号は順番通りに定義されています。
半角アルファベットでは、A が65、Bが66、Cが67、のように決められています。
つまり、Aに足し算を行うと、何番目のアルファベットの文字を取り出すことが出来ます。
次のプログラムは、10番目のアルファベットを取り出す例です。
このプログラムの実行結果は、次の通りになります。#include <stdio.h> int main(void) { char c = 'A' + 9; /* 最初は0なので9を足す */ printf("%c\n",c); return 0; }
数字を使う時には、引き算で本来の数値を知ることも出来ます。
J
このプログラムの実行結果は、次の通りになります。#include <stdio.h> int main(void) { char c = '8'; /* 数字 */ int suuti = c - '0'; /* 数値に変換 */ printf("%d\n",suuti); return 0; }
このプログラムでは、数値に変換した結果を%d指定子で表示させています。
8
ただし、先ほどのプログラムの問題点は、数字以外の文字も変換されることです。
例えば、'A' は65番なので、'A' を数値に変換させると17になってしまいます。
この問題を解決するには、変換する文字が数字であるかを判定する必要があります。
これは比較的簡単です。文字の番号が、'0' 〜 '9' の間にあるか調べるだけです。
次のプログラムは、数字を数値に変換し、数字以外は全て0に変換する例です。
このプログラムの実行結果は、次の通りになります。#include <stdio.h> int main(void) { char c = 'A'; /* 数字 */ int suuti; if (c >= '0' && c <= '9') { /* 判定部分 */ suuti = c - '0'; /* 数値に変換 */ } else { suuti = 0; } printf("%d\n",suuti); return 0; }
もちろん、数字を指定した場合には、ちゃんと数値に変換されます。
0
ある文字が数値かどうかを調べる方法は、アルファベットにも応用出来ます。
ただし、大文字の 'Z' から 小文字の 'a' には連続していないので、
'A' 〜 'Z' と 'a' 〜 'z' をそれぞれ調べる必要があります。
また、これらの機能は関数化されており、次の関数が使えます。
なお、これらの関数の使用には、ctype.h を #include する必要があります。
名前 | 文字種類 | 文字一覧 |
---|---|---|
isalnum | 英数字 | (A〜Z,a〜z,0〜9) |
isdigit | 10進数 | (0〜9) |
isxdigit | 16進数 | (A〜F,a〜f,0〜9) |
isalpha | 英字 | (A〜Z,a〜z) |
isupper | 英大文字 | (A〜Z) |
islower | 英小文字 | (a〜z) |
ispunct | 記号 | (!"#$%&'()*+,- /:;<=>?@^_`{|}~) |
isspace | スペース | (0x09〜0x0D,0x20) |
実行結果は、先ほど全く同じになります。#include <stdio.h> #include <ctype.h> int main(void) { char c = 'A'; int suuti; if (isdigit(c)) { /* 判定部分 */ suuti = c - '0'; } else { suuti = 0; } printf("%d\n",suuti); return 0; }