苦しんで覚えるC言語

文字の扱い方


文字列を扱う変数


これまで、プログラム中で何回も文字列を扱ってきたのですが、
何故か、文字列を記憶する変数は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;
}
このプログラムの実行結果は、次の通りになります。

A
この様に、char型を使えば、文字を変数と同様に取り扱うことが可能です。
全角文字は駄目
実は、この方法では、全角文字を扱うことは出来ません。
char型で記憶出来る文字の種類は最大で255種類が限界で、
何千文字もある日本語の文字を記憶しておくことは出来ないのです。

この問題を解決する手段として、wchar_t型が用意されているのですが、
入門書ではほとんど触れられていないようですし、
ややこしくなるので、wchar_t型についてはここでは扱いません。

目次に戻る

文字コード


前項では、char型で1文字を取り扱うことが出来ることを説明しましたが、
これは、コンピュータで使われる文字コードの仕組みを利用しています。
文字コード
コンピュータで使われる文字に1対1で対応する番号をつけて表現する方法。
ASCIIコードという規格では半角のアルファベットや記号が割り当てられている。
日本語を扱えるコードとして、JIS、シフトJIS、EUCが使われている他、
世界中の言語を扱えるコードとして Unicode が普及している。
文字コードとは、文字に1対1で対応する番号をつけて表現する方法のことです。
次の表は、半角文字の番号表として最も使われている規格であるASCIIコードの例です。

番号番号(16進数)文字
620x3e>
630x3f?
640x40@
650x41A
660x42B
670x43C
680x44D
970x61a
980x62b
この表を丸暗記しようとしないで下さい
こういった表を出すと、受験勉強のように丸暗記しようとする人が出てくるのですが、
暗記する必要は全くありません。もちろん筆者も暗記しておりません。
重要なことは、すべての文字には番号がついているという仕組みのほうです。
char型変数に文字を代入するのは、この番号を代入しているだけのことであり、
要するに char型は普通の整数型と全く同じなのです。

例えば、前項のプログラムでは、'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
数字を使う時には、引き算で本来の数値を知ることも出来ます。
数字にも文字の番号が割り当てられており、例えば '0' は48番に割り当てられています。
数字から '0' の番号を引き算すれば、数値に変換され計算に使用できます。
次のプログラムは、数字を数値に変換する例です。

#include <stdio.h>

int main(void)
{
	char c = '8';	/* 数字 */
	int suuti = c - '0';	/* 数値に変換 */
	printf("%d\n",suuti);
	return 0;
}
このプログラムの実行結果は、次の通りになります。

8
このプログラムでは、数値に変換した結果を%d指定子で表示させています。

ただし、先ほどのプログラムの問題点は、数字以外の文字も変換されることです。
例えば、'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
isdigit10進数0~9
isxdigit16進数A~F a~f 0~9
isalpha英字A~Z a~z
isupper英大文字A~Z
islower英小文字a~z
ispunct記号!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
isspaceスペース0x09~0x0D 0x20
次のプログラムは、isdigit関数を使って先ほどのプログラムを書き換えた例です。

#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;
}
実行結果は、先ほど全く同じになります。

目次に戻る