マルチバイト文字(漢字とか平仮名)をC言語で扱うのは結構面倒なので、これ以降はアスキー文字(半角英数字文字)だけ取り扱います。従って今後は「文字」=「アスキー文字」と読み替えて下さい。
(半角英数字)文字は 0〜127 までの整数と一対一で対応していますので、C 言語では -128 から 127 までの整数を扱える char 型変数(※)に代入してメモリ空間に格納することが出来ます。
※ char 型変数の事を「文字型変数」と書いてある文献が多いのですが、正確には 1 byte 整数型変数と言って整数を格納する変数です。
char a; a = 'A'; // 文字はシングルクォーテーションで囲む printf("%c\n", a ); // 文字の printf 表示は %c
文字は char 型変数を使って格納出来るということは、文字「列」は char 型の配列に格納することが出来ます。
文字列を格納するために使われている char 型配列の事を「文字列配列」とか「文字列の配列」とか、あるいは単純に「文字列」とだけ呼んでいます。なお配列の長さは最大文字数を表します。
char a[256]; // 最大256文字を格納できる文字列配列
いったん文字列配列を定義すれば後はただの char 型配列ですので、普通に文字を代入することが出来ます。
char a[256]; a[0] = 'h'; a[1] = 'o'; a[2] = 'g'; a[3] = 'e';
なお上の例を実行した後のメモリ空間の状態は図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] 以降は何が入っているか分からないので?にしています。
日本語の文字列は「。」が来ると終わりですが、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'が入っていることに注目して下さい。
※ 例なのでアドレスは適当です。
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] 以降は何が入っているか分からないので?にしています。
このヌル終端文字は文字列の最後に必ず入れなければいけないものでは無いのですが、もしヌル終端文字が無いとどこで文字列が終わりなのか分からないのでプログラムの誤動作の原因になる時があります。
文字列配列を printf で表示する場合は %s を使います。
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 は使わないで下さい。 何故危険なのかは自分で調べてみましょう。 どうしても使いたい時は「書式をちゃんと書く」か「fgets」又は「scanf_s」を代わりに使いましょう。
char a[256]; scanf("%s", a ); // アドレス演算子 & は必要ない printf("%s\n", a ); // scanf するとヌル終端文字は自動的に文字列の最後に入る
参考までに、i 番目の文字を一文字だけ表示したい時は %c を使います。
char a[256]; a[0] = 'h'; a[1] = 'o'; a[2] = 'g'; a[3] = 'e'; a[4] = '\0'; printf("%c\n", a[2] ); // g と表示される
文字列配列は結局ただの char 型配列ですので、1次元配列とメモリ空間の「配列 a の i 番目の要素 a[i] のアドレス」の所で習った方法を使って i 番目の文字から文字列を開始することができます。
(1) a + i
又は
(2) &a[i]
※どちらを使っても構いませんが、文字列配列の場合は(1)の方を使う人が多いみたいです。
と言われても何の事かピンと来ないと思いますので、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 と表示される printf("%s\n", a+1 ); // oge と表示される printf("%s\n", a+2 ); // ge と表示される printf("%s\n", a+3 ); // e と表示される
普通の変数は int a = 123; の様に定義と同時に初期化可能ですが、文字列配列の場合も次の様にして初期化します。
char a[256] = "hoge"; ※ 文字数が最大文字数を超えているとコンパイル出来ません。 ※ 配列の最後の要素に自動的にヌル終端文字が入ります。
この時のメモリ空間の状態は上の図 2 と同じとなります。
なお次のやり方で文字列を初期化して作っている文献が結構ありますが、極めて危険な初期化方法なので使わない方が無難です。何故危険なのかは自分で調べてみましょう。
char *a = "hoge"; 又は char a[] = "hoge";
※ const を付けている場合は比較的安全なので良く使われている
const char *a = "hoge"; 又は const char a[] = "hoge";
しつこいようですが、文字列配列はただの 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 );