7. たくさんのデータを処理するための配列(2/3)
7.3 文字列の取扱い
C言語では文字の取扱いが複雑です。そもそも、用語が分かりにくいため、用語に付いて説明します。
- 文字
- 半角の英字・数字・記号の1文字です。char型の変数で取り扱えます。
- 文字列
- 2文字以上の文字の並びです。日本語などの文字コードは1文字でも複数バイトを使用しますので、例え1文字の場合でも文字列扱いになります。char型の変数では取り扱えません。
- ヌル(Null)文字
- 8ビット(1バイト)全て0の文字で、文字列の最後を表すために使用します。「付録1.ASCIIコード表」で「NUL」と表記してある文字です。文字としては\0(バックスラッシュと0)と記述します。(文字定数として指定する場合は'で括って'\0'と記述します)当講座では「ヌル文字」と呼ぶことにします。
文字は既に説明したとおり、char型のデータとして取り扱えますので、char型の変数に代入したり参照したりすることができます。また、定数として記述する場合は'(アポストロフィ)で括ります。
一方、文字列は単なるchar型の変数では取り扱えませんので、char型の配列で取り扱うことになります。また、文字列の最後を表すためにヌル文字も使用します。
定数として記述する場合は"(引用符)で括りますが、ヌル文字はコンパイラが自動的に付け加えますので指定する必要はありません。(文字列の定数はprintf関数でメッセージを出力するときに使いました)
文字列の取扱いは面倒ですので、C言語では「文字列処理ライブラリ」として文字列を取り扱う関数が沢山提供されています。どのような関数があるかを確認しておくと良いでしょう。
7.3.1 形式
宣言時に初期値を指定しない場合は要素数を指定しますが、格納する文字列の文字数が確定できないことが多いと思います。その場合は予想する最大文字数を指定するしかありません。もし、最大文字数を越えてしまった場合はオーバーフローとなり、プログラム実行時に異常終了するかもしれませんので、要素数は多めに指定しておいた方が良いでしょう。(完全な対応策ではありませんが…)
宣言時に初期値を指定する場合は要素数は省略できます。省略した場合はコンパイラが適切な要素数の配列として確保してくれます。日本語を初期値として指定する場合は1文字が何バイトか調べるのも大変ですので、要素数は省略した方が良いでしょう。
char型の配列に定数の文字列を代入することは出来ません。(配列に配列を代入することになるためです)
※ 宣言時に初期値を指定しない場合
char 配列名[要素数];
※ 宣言時に初期値を指定する場合
char 配列名[] = "初期値"; ← 初期値の文字列の最後にヌル文字は不要です
文字列の入出力もscanf関数やprintf関数で出来ますが、変数の場合と使い方が若干異なります。具体的には例題プログラムをご覧ください。
scanf関数で入力する場合の書式制御文字列は%sになります。そして、入力した文字列を格納するchar型の配列名を指定しますが、この配列名には&記号は付けませんので注意して下さい。また、入力したデータにはヌル文字が付加されて、文字列として指定した配列に格納されます。
printf関数で出力する場合の書式制御文字列も%sになります。
7.3.2 例題
例題1
入力された文字列(10文字以下の半角文字列)の文字数を数えて出力します。
#include <stdio.h>
int main()
{
char mojiretu[11];
int counter; /* 添字と文字数カウンターを兼ねる */
/* 文字列の入力 */
printf("10文字以下の半角文字列を入力してください ==> ");
scanf("%s", mojiretu);
counter = 0;
while( mojiretu[counter] != '\0')
{
++counter; /* 添字と文字数カウンターのカウントアップ */
}
/* 入力文字数の出力 */
printf("「%s」の文字数は%dです\n", mojiretu, counter);
return 0;
}
$ ./ex07_3.prg
10文字以下の半角文字列を入力してください ==> Hello
「Hello」の文字数は5です
$
- 4行目
- scanf関数で入力した文字列を格納するためのchar型の配列です。入力文字列の文字数は最大10文字と想定していますので、ヌル文字分を含めて要素数を11としています。
- 9行目
- scanf関数で文字列を入力します。書式制御文字列は%sで、入力した文字列はmojiretu配列に格納します。mojiretuには&を付けませんので注意してください。
- 11〜15行目
- mojiretu配列にヌル文字が現れるまで繰り返し処理を行います。繰り返しの中で添字を進めることと、文字数を数えることを行っています。
- 17行目
- scanf関数で入力した文字列と文字数を出力します。文字列の出力に対する書式制御文字列は%sです。
例題2
入力された文字列(10文字以下の半角文字列)の最後の文字から先頭文字の順(逆順)に出力します。
#include <stdio.h>
int main()
{
char mojiretu[11];
int index;
/* 文字列の入力 */
printf("10文字以下の半角文字列を入力してください ==> ");
scanf("%s", mojiretu);
/* ヌル文字を探す */
for(index = 0; mojiretu[index]; ++index)
;
/* ヌル文字の前の文字(最後の文字)から先頭の文字まで */
printf("逆順で出力します\n");
for(--index; index >= 0; --index)
{
printf("%c", mojiretu[index]);
}
printf("\n");
return 0;
}
$ ./ex07_4.prg
10文字以下の半角文字列を入力してください ==> Hello
逆順で出力します
olleH
$
- 12〜13行目
- ヌル文字の要素まで添字を進めます。ヌル文字の1つ前が最後の文字です。
- 17〜20行目
- ヌル文字の1つ前から先頭文字まで添字を戻しながら繰り返します。繰り返しの中で1文字ずつ出力します。1文字出力ですので書式制御文字列は%cです。