多くのプログラミング言語には「文字列型」という専用の型があります。Cにはありません。Cの文字列は char の配列、それだけです。この一文が、このトラック全体の土台になります。
まず1文字。char は文字1個を入れる型で、シングルクォートで書きます。
char c = 'A';
printf("%c\n", c); // A文字が複数並んだものが文字列です。だから char の配列を使います。
#include <stdio.h>
int main(void)
{
char s[6] = "hello";
printf("%s\n", s); // hello ← 文字列は %s
printf("%c\n", s[0]); // h ← 1文字は %c
return 0;
}"hello" は5文字なのに、なぜ配列は6個ぶんなのでしょうか。最後に終わりの印が1つ入るからです。これが次のトピックの主役、ヌル文字です。
なぜ専用の型がないのか
Cが作られた1970年代、コンピュータのメモリは現在の何十万分の1しかありませんでした。言語に機能を足せば、その分だけ実行時の負担が増えます。Cは「文字が並んでいるだけ」という最小の表現を選び、細かい処理はプログラマと標準関数に任せました。おかげでCは小さく速い言語になり、その代わり、文字列の扱いには少しの手間と注意が必要になっています。これから出てくる約束事は、すべてこの割り切りから来ています。
文字列を作る3つの場面
- 決まった文字列を持ちたい →
char s[] = "hello"; - あとから中身を入れる箱がほしい →
char buf[64];(大きさを多めに取る) - 入力を受け取りたい →
char line[64];に読み込む
どの場合も「char の配列」であることは変わりません。違うのは大きさの決め方だけです。
1文字ずつ触れる
文字列は配列なので、添字でどの文字にも直接アクセスできます。
#include <stdio.h>
int main(void)
{
char s[6] = "hello";
s[0] = 'H'; // 1文字だけ書き換える
printf("%s\n", s); // Hello
for (int i = 0; i < 5; i++) {
printf("[%c]", s[i]); // [H][e][l][l][o]
}
printf("\n");
return 0;
}配列でできることは、文字列でも全部できます。前のトラックで身につけた「for文で全要素を回す」型が、そのまま使えるわけです。
クォートの違いに敏感になる
'A'… シングルクォート。文字1個(char型、大きさ1バイト)"A"… ダブルクォート。文字列(char配列、'A'と終わりの印で2バイト)
見た目はよく似ていますが、まったくの別物です。char c = "A"; と書くとコンパイラに怒られます。キーボードの入力ミスで起きやすい間違いなので、エラーが出たらまずクォートの種類を疑ってください。
罠・注意
- 書式指定子を間違えると表示が壊れます。1文字は
%c、文字列は%s。printf("%s", s[0])は文字列として1文字を読もうとして異常終了することがあります。 - 配列の大きさは「入れたい文字数 + 1」が最低ラインです。ここを1つケチると、次のトピックで扱う深刻な事故につながります。
- 日本語の文字は1文字が複数バイトを占めるため、
s[0]で1文字取り出す方法は使えません。詳しくは t09-07 で扱います。
まとめ: Cの文字列は char の配列。%s で丸ごと、%c で1文字。配列の技がそのまま通用します。