5.2 文字列
5.2.1 文字列を変数に保存する
これまで変数に保存した情報は、文字、整数、浮動小数点のいずれかでした。しかし、文字列を保存するという方法は、まだ解説していません。実は、C言語には文字列を表す専用の型というのがありません。
では、文字列を変数として扱いたい場合はどうするのでしょうか?文字列とは、連続した文字定数であると考えることができます。つまり、複数個の連続した ASCII コードの値です。「連続した値」というものを制御するための最適な手段は、すでに解説しています。「5.1 配列」で説明した配列こそ、文字列を表現するための手段です。
文字列は、char 型の配列として保存することができます。そして、表示する時は 1 文字ずつ順に表示するという方法が考えられるでしょう。
#include <stdio.h> int main() { char chStr[6]; int iCount; chStr[0] = 'K'; chStr[1] = 'i'; chStr[2] = 't'; chStr[3] = 't'; chStr[4] = 'y'; chStr[5] = '\n'; for(iCount = 0 ; iCount < 6 ; iCount++) printf("%c" , chStr[iCount]); return 0; }
コード1では、char 型の配列 chStr の各要素に 1 文字ずつ文字定数を代入しています。最後に printf() 関数を使って、代入した文字をやはり 1 文字ずつ表示しています。確かに文字列は表示されますが、効率的な方法とはいえません。
まず、文字を表示する場合は文字の数だけ繰り返し処理を行う必要がありますが、必ずしも文字数を管理できるとは限りません。そこで、文字列の最後は常に 0 で表すことにしましょう。このような決まりを設ければ、文字数を管理する必要がなくなります。
#include <stdio.h> int main() { char chStr[7]; int iCount; chStr[0] = 'K'; chStr[1] = 'i'; chStr[2] = 't'; chStr[3] = 't'; chStr[4] = 'y'; chStr[5] = '\n'; chStr[6] = 0; for(iCount = 0 ; chStr[iCount] ; iCount++) printf("%c" , chStr[iCount]); return 0; }
コード2はコード1を改良し、配列変数の終端は 0 であるという決まりを作り、その規則に適応した for ループを作成しています。
printf() 関数などC言語の標準関数は、まさにこれと同様に文字列の終端は 0 で終わるという規則を定めています。そのため "Kitty" というリテラル文字列は、文字配列として考えた場合、その末尾は y ではなく 0 で終わっている 6 つの要素からなる配列と考えられるのです。文字列の終端を表すこの 0 のことをNULL文字と呼びます。
printf() 関数の書式制御文字に %s を指定すると文字配列を表示することをあらわします。printf() 関数は、渡された文字配列を調べ、NULL 文字が現れるまで配列を順に表示するのです。つまり、コード2のようなことをやってくれます。そして、printf() 関数の第一引数に指定する書式制御文字列もまた、NULL で終わる文字列として扱われているのです。
#include <stdio.h> int main() { char chStr[7]; int iCount; chStr[0] = 'K'; chStr[1] = 'i'; chStr[2] = 't'; chStr[3] = 't'; chStr[4] = 'y'; chStr[5] = '\n'; chStr[6] = 0; printf("%s : %s" , "Kitty" , chStr); return 0; }
このプログラムの printf() 関数に注目してください。printf() 関数は "Kitty" というリテラル文字列と chStr 配列変数を引数として渡しています。リテラル文字列は暗黙的にその末尾が NULL 文字となります。そして、chStr は明示的に chStr[6] に 0 を代入しています。これらは、NULL 文字で終わる文字配列として printf() 関数によって画面に表示されます。
ところで、printf() 関数に chStr 配列変数を渡す時に、添字を使わずに変数名のみを指定しています。配列では、添字を指定せずに変数名だけを指定した場合、その配列の先頭を表します。ただし、より正確には配列の先頭のメモリアドレスを表すと言うべきでしょう。これについてはポインタを解説する時に詳しく説明します。配列とポインタは密接な関係を持っているため、配列を十分に理解するためには、ポインタの理解が必要です。