C言語の文字と文字列の扱いは難しく、多くのC入門者に深い溜め息
をつかせたでしょう。多くの参考書ではややこしい事をだらだらと書い
てあり、よけいに混乱してしまいます。
簡潔に説明しますと、文字とは a とか b とかを差し、文字列とは
Hello とかを差します。プログラムの中では文字列は[’]を付けて表し
文字列は[”]を付けて表します。
'A' /* Aという文字 */
"Hello" /* Hello という文字列 */
'Hello' /* 文字列なのに '' で囲っているのでエラー */
"a" /* これはエラーでは無く a という文字列 */
では宣言の方法ですが、文字の場合は簡単です。
char cMoji ; /* cMoji という文字型を宣言 */
cMoji = 'a'; /* cMoji に a を代入 */
では文字列はどのように表すかというと、実は文字列は文字の配列と
して表現されます。
では配列というのは何なのか?簡単にいうと同じ型の変数をいくつも
作る事ができる機能です。次の様に宣言します。
int iValue[3];
これで、int型の変数を3つ作った事になります。では、その3つ
をどの様にして識別するのでしょうか?それは添え字を付けて区別
します。3つ作ったのだから iValue[0] と iValue[1] と iValue[2]
という風にそれぞれを指定します。注意する点は最後の変数の添え字
が「3」では無い所です。添え字は0から始めるので最後の変数の添
え字は配列宣言の時に指定した数字より1少ない数になります。
iValue[3] = 123 と書いてしまうとエラーが起こりますので注意しま
しょう。
先程文字列は文字の配列であると言いました。では文字列を格納す
る為に文字型の配列を作りましょう。ここは8文字くらいあればいい
ので
char szMoji[8];
という感じです。では文字列を代入してみましょう。配列ですから
添え字を付けて指定します。
szMoji[0] = 'H';
szMoji[1] = 'E';
szMoji[2] = 'L';
szMoji[3] = 'L';
szMoji[4] = 'O';
これで szMoji に "HELLO" と入った事になります。次にこの状態か
ら szMoji に "abc" と代入してみましょう。
szMoji[0] = 'a';
szMoji[1] = 'b';
szMoji[2] = 'c';
さて、ここで szMoji の中身がどうなっているのか見てみましょう。
szMoji[0] → 'a'
[1] → 'b'
[2] → 'c'
[3] → 'L'
[4] → 'O'
[5] → ?
[6] → ? まだ何も代入されていないので未定
[7] → ?
ここで困った事がおきています。最初に "HELLO" と入れ、次に"abc"
と入れたわけですが、中では "abcLO" となっていてどこで文字列が終
わりなのか判断できません。
そこでC言語の約束として、文字列の最後には \0 という文字を入れ
ておく、という風に決められています。これはヌルコードと呼ばれ、エ
スケープシーケンス文字です。書くと2文字ですが、一字の文字として
扱われます。
つまり最初からもう一度やりなおすと
szMoji[0] = 'H';
szMoji[1] = 'E';
szMoji[2] = 'L';
szMoji[3] = 'L';
szMoji[4] = 'O';
szMoji[5] = '\0'; /* 最後にヌルを代入 */
それで、次に "abc" を代入すると
szMoji[0] = 'a';
szMoji[1] = 'b';
szMoji[2] = 'c';
szMoji[3] = '\0'; /* これも最後にヌル */
ここでまた、szMoji を見てみますと、
szMoji[0] → 'a'
[1] → 'b'
[2] → 'c'
[3] → '\0' /* ヌル */
[4] → 'O'
[5] → '\0'
[6] → ? まだ何も代入されていないので未定
[7] → ?
となりCでは最初に \0 が表れるまでが文字列とされているので "abc"
という文字であると判断できるのです。
しかし、いちいち文字を代入するのにあんな風に書いていたら日が暮れて
しまいます。そこでCには strcpy という関数があります。ストリングコピ−
です。これを使うと、
strcpy(szMoji,"Hello");/* 文字列として考える時は添え字は無し */
としただけで代入されます。もちろんこれで szMoji[0] には 'H' が、
szMoji[1] には 'E' が入っています。ここで忘れてはいけないのが、
strcpy というのを使う為には文字列ライブラリである を
呼んでやらないといけないのです。ですから いつもの
#include <stdio.h>
に加えて
#include <stdio.h>
と書いて下さい。ここでまた、話が変わりますが、文字列の大きさという
のは最初に決めなければなりません。どういう事かというと
char szBuffer[**]
^^この部分が文字列の大きさで後で変更は出来ない。
という事です。くれぐれも注意しましょう。例えば "Hello World !"と
いう文字列を格納するためには 13 文字あればよさそうに思いますが、
先程の話を思い出して下さい。文字列の最後にはヌルコードが必要なので
す。ですから一つ足して計14文字分確保しなければならないので、
char szBuffer[14];
となります。この配列の数は非常にナイーブな物で、確保した領域より
大きな文字列を代入したりすると、面倒な異常を起こします。比較的大き
めに領域を確保するようにしましょう。
また、いちいち strcpy を使うのはあまりにも面倒なので宣言した時と
同時になら他の変数型のような代入が出来ます。
char szBuffer[14] = "Hello World !";
しかし途中で中身を変更しようとして
szBuffer = "123";
とするとエラーがおきます。szBuffer に文字列は代入できません。szBuffer[**]
は文字型である事はもう分かったでしょう。では szBuffer というのは一体何者で
しょうか?
実はこいつはポインタなのです。
char szBuffer[100];
の時点で100文字分のメモリが確保され、その先頭のアドレスを持つポインタ
なのです。配列ではカッコを抜いた文字がポインタとなります。つまり
szBuffer[0] と *szBuffer は同じなのです。もう少し詳しく説明しましょう。
char szBuffer[100] = "123456789";
と入れます。すると szBuffer というのは "123456789" という文字列が格納さ
れているアドレスの先頭を指すポインタです。つまり szBuffer が指し示すのは
'1' という文字です。また、szBufferは配列ですから szBuffer[0] は1文字目で
ありまして、'1' ということになります。
だから szBuffer = "123" はポインタ型に文字列を代入しようとしていること
になるのです。もちろんエラーとなります。
文字は非常に奥が深く様々なテクニックがあります。しかし今後やっていく予定
のMFCには新しく文字列に関する変数型(実はクラス)が存在し、このような事
を考えなくても構わない、まるでBASICのように簡単に文字列を操作出来る様
になっています。なので軽く考えても構わないのでしょうか。という事で今回はこ
れまで。次回は関数です。
|