マルチバイト文字(漢字とか平仮名)をC言語で扱うのは結構面倒なので、これ以降はアスキー文字(半角英数字文字)だけ取り扱います。従って今後は「文字」=「アスキー文字」と読み替えて下さい。


1.文字と char 型変数

(半角英数字)文字は 0〜127 までの整数と一対一で対応していますので、C 言語では -128 から 127 までの整数を扱える char 型変数(※)に代入してメモリ空間に格納することが出来ます。

※ char 型変数の事を「文字型変数」と書いてある文献が多いのですが、正確には 1 byte 整数型変数と言って整数を格納する変数です。

(半角英数字)文字を char 型変数に代入する例:
char a;
a = 'A';  // 文字はシングルクォーテーションで囲む
printf("%c\n", a ); // 文字の printf 表示は %c

2.文字列と文字列配列

文字は char 型変数を使って格納出来るということは、文字「列」は char 型の配列に格納することが出来ます。

文字列を格納するために使われている char 型配列の事を「文字列配列」とか「文字列の配列」とか、あるいは単純に「文字列」とだけ呼んでいます。なお配列の長さは最大文字数を表します。

文字列配列の定義例:
char a[256]; // 最大256文字を格納できる文字列配列

いったん文字列配列を定義すれば後はただの char 型配列ですので、普通に文字を代入することが出来ます。

文字列配列への文字の代入例:
char a[256];

a[0] = 'h';
a[1] = 'o';
a[2] = 'g';
a[3] = 'e';

なお上の例を実行した後のメモリ空間の状態は図1の様になります。

図1: 上の例を実行した後のメモリ空間

※ 例なのでアドレスは適当です。

a = 0x01 0x02 0x03 0x04 0x05 0x06 ・・・
a[0] = 'h' a[1] = 'o' a[2] = 'g' a[3] = 'e' a[4] = ? a[5] = ? ・・・

※ a[4] 以降は何が入っているか分からないので?にしています。


3. ヌル終端文字

日本語の文字列は「。」が来ると終わりですが、C 言語でも「ヌル終端文字」という特殊な文字を使って文字列の終了を表します。「ヌル文字」とか単に「終端文字」とだけ呼ばれる事もあります。

ヌル終端文字:
'\0'

※ C言語では '\0' は整数 0 と同一

具体的には、次のように文字列配列の最後の要素にヌル終端文字を代入することで「以上で文字列は終わり」という事を示します。

ヌル終端文字の使用例:
char a[256];

a[0] = 'h';
a[1] = 'o';
a[2] = 'g';
a[3] = 'e';
a[4] = '\0';

上の例を実行した後のメモリ空間の状態は次の図 2 の様になります。最後の要素に'\0'が入っていることに注目して下さい。

図2: 上の例を実行した後のメモリ空間

※ 例なのでアドレスは適当です。

a = 0x01 0x02 0x03 0x04 0x05 0x06 ・・・
a[0] = 'h' a[1] = 'o' a[2] = 'g' a[3] = 'e' a[4] = '\0' a[5] = ? ・・・

※ a[5] 以降は何が入っているか分からないので?にしています。

このヌル終端文字は文字列の最後に必ず入れなければいけないものでは無いのですが、もしヌル終端文字が無いとどこで文字列が終わりなのか分からないのでプログラムの誤動作の原因になる時があります。


4. 文字列配列の printf と scanf

文字列配列を printf で表示する場合は %s を使います。

文字列の printf 例:
char a[256];

a[0] = 'h';
a[1] = 'o';
a[2] = 'g';
a[3] = 'e';
a[4] = '\0';  // ヌル終端文字が無いと pritnf が誤動作するので注意 !

printf("%s\n", a ); // hoge と表示される

文字列配列に文字列を scanf で取り込みたい時も %s を使います。 ただし変数の時と違って今回は文字列配列の先頭アドレスを指定するのでアドレス演算子 & を前に付ける必要はありません。またヌル終端文字は自動的に文字列の最後に入ります。

文字列の scanf 例:

※ scanf で文字列を入力することはセキュリティ的に「最高レベルで」危険なので、基本的に文字列の入力に scanf は使わないで下さい。 何故危険なのかは自分で調べてみましょう。 どうしても使いたい時は「書式をちゃんと書く」か「fgets」又は「scanf_s」を代わりに使いましょう。

char a[256];

scanf("%s", a ); // アドレス演算子 & は必要ない
printf("%s\n", a ); // scanf するとヌル終端文字は自動的に文字列の最後に入る

参考までに、i 番目の文字を一文字だけ表示したい時は %c を使います。

i 番目の文字の printf 例:
char a[256];

a[0] = 'h';
a[1] = 'o';
a[2] = 'g';
a[3] = 'e';
a[4] = '\0';

printf("%c\n", a[2] ); // g と表示される


5. 文字列配列の i 番目の文字から文字列を開始する

文字列配列は結局ただの char 型配列ですので、1次元配列とメモリ空間の「配列 a の i 番目の要素 a[i] のアドレス」の所で習った方法を使って i 番目の文字から文字列を開始することができます。

文字配列の i 番目の文字から文字列を開始する方法:

(1) a + i

又は

(2) &a[i]

※どちらを使っても構いませんが、文字列配列の場合は(1)の方を使う人が多いみたいです。

と言われても何の事かピンと来ないと思いますので、printf を使った具体例を示します。

i 番目の文字から文字列を表示する例:
char a[256];

a[0] = 'h';
a[1] = 'o';
a[2] = 'g';
a[3] = 'e';
a[4] = '\0';  // ヌル終端文字が無いと pritnf が誤動作するので注意 !

printf("%s\n", a );  // hoge と表示される
printf("%s\n", a+1 );  // oge と表示される
printf("%s\n", a+2 );  // ge と表示される
printf("%s\n", a+3 );  // e と表示される


6. 文字列配列の初期化

普通の変数は int a = 123; の様に定義と同時に初期化可能ですが、文字列配列の場合も次の様にして初期化します。

文字列配列の初期化方法:

char a[256] = "hoge";

※ 文字数が最大文字数を超えているとコンパイル出来ません。
※ 配列の最後の要素に自動的にヌル終端文字が入ります。

この時のメモリ空間の状態は上の図 2 と同じとなります。

なお次のやり方で文字列を初期化して作っている文献が結構ありますが、極めて危険な初期化方法なので使わない方が無難です。何故危険なのかは自分で調べてみましょう。

危険な文字列の初期化方法:
char *a = "hoge";

又は

char a[] = "hoge";

※ const を付けている場合は比較的安全なので良く使われている

const char *a = "hoge";

又は

const char a[] = "hoge";

7. 文字列配列の配列渡し(文字列渡し)

しつこいようですが、文字列配列はただの char 型配列ですので、「配列渡し」で学んだ方法を使って関数呼び出し可能です。なお「文字列配列の配列渡し」と書くと長いので単に「文字列渡し」とだけ呼んでいる人も多いです。

文字列渡しの例:
void HOGE( char *pa )
{
   printf( "%s\n", pa );   // 文字列全体を表示する

  ※ 関数の中で i 番目の文字にアクセスしたい時は *(pa+i)記法 や pa[i] 記法の好きな方を使う

   printf( "%c\n", *(pa+1) );   // 1 番目の文字を表示する
   pa[2] = 'A';  // 2番目の文字を 'A' に置き換える
}


(関数の呼び出し方の例)

char a[256] = "hoge";

※ 文字列配列の先頭アドレスを渡す(アドレス演算子 & を配列名の前に付けない)
HOGE( a );