1.7 文字と文字列とポインタ Menuへ戻る

      C言語の文字と文字列の扱いは難しく、多くのC入門者に深い溜め息
    をつかせたでしょう。多くの参考書ではややこしい事をだらだらと書い
    てあり、よけいに混乱してしまいます。

      簡潔に説明しますと、文字とは a とか b とかを差し、文字列とは
    Hello とかを差します。プログラムの中では文字列は[’]を付けて表し
    文字列は[”]を付けて表します。

      'A'           /* Aという文字 */
      "Hello"       /* Hello という文字列 */
      'Hello'       /* 文字列なのに '' で囲っているのでエラー */
      "a"           /* これはエラーでは無く a という文字列 */

      では宣言の方法ですが、文字の場合は簡単です。

      char cMoji ;    /* cMoji という文字型を宣言 */
      cMoji = 'a';    /* cMoji に a を代入 */

      では文字列はどのように表すかというと、実は文字列は文字の配列と
    して表現されます。

      では配列というのは何なのか?簡単にいうと同じ型の変数をいくつも
    作る事ができる機能です。次の様に宣言します。

      int iValue[3];

      これで、int型の変数を3つ作った事になります。では、その3つ
    をどの様にして識別するのでしょうか?それは添え字を付けて区別
    します。3つ作ったのだから iValue[0] と iValue[1] と iValue[2]
    という風にそれぞれを指定します。注意する点は最後の変数の添え字
    が「3」では無い所です。添え字は0から始めるので最後の変数の添
    え字は配列宣言の時に指定した数字より1少ない数になります。
    iValue[3] = 123 と書いてしまうとエラーが起こりますので注意しま
    しょう。

      先程文字列は文字の配列であると言いました。では文字列を格納す
    る為に文字型の配列を作りましょう。ここは8文字くらいあればいい
    ので

      char szMoji[8];

      という感じです。では文字列を代入してみましょう。配列ですから
    添え字を付けて指定します。

      szMoji[0] = 'H';
      szMoji[1] = 'E';
      szMoji[2] = 'L';
      szMoji[3] = 'L';
      szMoji[4] = 'O';

      これで szMoji に "HELLO" と入った事になります。次にこの状態か
    ら szMoji に "abc" と代入してみましょう。

      szMoji[0] = 'a';
      szMoji[1] = 'b';
      szMoji[2] = 'c';

      さて、ここで szMoji の中身がどうなっているのか見てみましょう。

    szMoji[0]  → 'a'
          [1]  → 'b'
          [2]  → 'c'
          [3]  → 'L'
          [4]  → 'O'
          [5]  → ?
          [6]  → ?  まだ何も代入されていないので未定
          [7]  → ?

      ここで困った事がおきています。最初に "HELLO" と入れ、次に"abc"
    と入れたわけですが、中では "abcLO" となっていてどこで文字列が終
    わりなのか判断できません。

      そこでC言語の約束として、文字列の最後には \0 という文字を入れ
    ておく、という風に決められています。これはヌルコードと呼ばれ、エ
    スケープシーケンス文字です。書くと2文字ですが、一字の文字として
    扱われます。

      つまり最初からもう一度やりなおすと

      szMoji[0] = 'H';
      szMoji[1] = 'E';
      szMoji[2] = 'L';
      szMoji[3] = 'L';
      szMoji[4] = 'O';
      szMoji[5] = '\0';   /* 最後にヌルを代入 */

      それで、次に "abc" を代入すると

      szMoji[0] = 'a';
      szMoji[1] = 'b';
      szMoji[2] = 'c';
      szMoji[3] = '\0';  /* これも最後にヌル */

      ここでまた、szMoji を見てみますと、

    szMoji[0]  → 'a'
          [1]  → 'b'
          [2]  → 'c'
          [3]  → '\0'  /* ヌル */
          [4]  → 'O'
          [5]  → '\0'
          [6]  → ?  まだ何も代入されていないので未定
          [7]  → ?

      となりCでは最初に \0 が表れるまでが文字列とされているので "abc"
    という文字であると判断できるのです。

      しかし、いちいち文字を代入するのにあんな風に書いていたら日が暮れて
    しまいます。そこでCには strcpy という関数があります。ストリングコピ−
    です。これを使うと、

      strcpy(szMoji,"Hello");/* 文字列として考える時は添え字は無し */

      としただけで代入されます。もちろんこれで szMoji[0] には 'H' が、
    szMoji[1] には 'E' が入っています。ここで忘れてはいけないのが、
    strcpy というのを使う為には文字列ライブラリである  を
    呼んでやらないといけないのです。ですから いつもの

    #include <stdio.h>

      に加えて

    #include <stdio.h>

      と書いて下さい。ここでまた、話が変わりますが、文字列の大きさという
    のは最初に決めなければなりません。どういう事かというと

      char szBuffer[**]
                    ^^この部分が文字列の大きさで後で変更は出来ない。

      という事です。くれぐれも注意しましょう。例えば "Hello World !"と
    いう文字列を格納するためには 13 文字あればよさそうに思いますが、
    先程の話を思い出して下さい。文字列の最後にはヌルコードが必要なので
    す。ですから一つ足して計14文字分確保しなければならないので、

      char szBuffer[14];

      となります。この配列の数は非常にナイーブな物で、確保した領域より
    大きな文字列を代入したりすると、面倒な異常を起こします。比較的大き
    めに領域を確保するようにしましょう。

      また、いちいち strcpy を使うのはあまりにも面倒なので宣言した時と
    同時になら他の変数型のような代入が出来ます。

      char szBuffer[14] = "Hello World !";

      しかし途中で中身を変更しようとして

      szBuffer = "123";

      とするとエラーがおきます。szBuffer に文字列は代入できません。szBuffer[**]
    は文字型である事はもう分かったでしょう。では szBuffer というのは一体何者で
    しょうか?

      実はこいつはポインタなのです。

      char szBuffer[100];

      の時点で100文字分のメモリが確保され、その先頭のアドレスを持つポインタ
    なのです。配列ではカッコを抜いた文字がポインタとなります。つまり

      szBuffer[0] と *szBuffer は同じなのです。もう少し詳しく説明しましょう。

      char szBuffer[100] = "123456789";

      と入れます。すると szBuffer というのは "123456789" という文字列が格納さ
    れているアドレスの先頭を指すポインタです。つまり szBuffer が指し示すのは
    '1' という文字です。また、szBufferは配列ですから szBuffer[0] は1文字目で
    ありまして、'1' ということになります。

      だから szBuffer = "123" はポインタ型に文字列を代入しようとしていること
    になるのです。もちろんエラーとなります。

      文字は非常に奥が深く様々なテクニックがあります。しかし今後やっていく予定
    のMFCには新しく文字列に関する変数型(実はクラス)が存在し、このような事
    を考えなくても構わない、まるでBASICのように簡単に文字列を操作出来る様
    になっています。なので軽く考えても構わないのでしょうか。という事で今回はこ
    れまで。次回は関数です。