next up previous contents
Next: 6. 課題 21 Up: 21. ポインタII Previous: 4. メモリの開放

5. 文字列の操作

ここまでメモリに関する様々な問題について学んできましたが、ここでは malloc()と共に良く使われる文字列の操作について学びます。

まず、malloc()をするにはそのメモリのサイズを決める必要があり ましたが、文字列では実際の文字列の長さを数える必要があるでしょう。 このための関数が strlen()です。strlen()は引数に 文字列へのポインタを取り、\0 までの文字数を計算し、結果として 返します。但し、\0自体は勘定しないので malloc()で利用 する場合には一つ多めにして置かなければならないのを忘れないでください。


    char buf[512];
    char *s;
    int n;
    gets(buf);
    n = strlen(buf) + 1;
    malloc( sizeof(char) * n );
    ...

上の例では、標準入力から読み込んだ文字列の長さ( + '\0' ) を n に代入し、char 型の大きさをかけた分のメモリを確保しています。 C言語では char は1byteであると決まっていますので、

    char buf[512];
    char *s;
    gets(buf);
    (char *)malloc( strlen(buf) + 1 );
    ...
と書いても構いません(ここではnの計算も上のように省略出来ます)。

次に、こうして確保されたメモリ領域にbuf[]に入っている文字列を 移しましょう。


   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   main(){
       char *s, buf[512];
       int i;
       gets(buf);
       s = (char *)malloc( strlen(buf) + 1 );
       for(i=0; buf[i]!='\0'; i++){
           s[i]=buf[i];
       }
       s[i]='\0';
       printf("%s\n", s);
  }

既に習ったようにポインタを更に活用して次のようにも書けます。


   #include <stdio.h>
   #include <stdlib.h>
   main(){
       char *s, *ps, *pd, buf[512];
       gets(buf);
       ps = buf;
       pd = s = (char *)malloc( strlen(buf) + 1 );
       for(; *ps!='\0'; ){
           *pd++ = *ps++;
       }
       *pd='\0';
       printf("%s\n", s);
  }

このように文字列をコピーすることはしばしば行うことなので、 特別にコピーのための関数 strcpy() が用意されています。


    strcpy( コピー先のメモリへのポインタ , コピー元のアドレス );

これを用いると先のプログラムはもっと短く次のように書けます。


   #include <stdio.h>
   #include <stdlib.h>
   main(){
       char *s, *ps, *pd, buf[512];
       gets(buf);
       s = (char *)malloc( strlen(buf) + 1 );
       strcpy(s, buf);
       printf("%s\n", s);
  }

strcpy では'\0'までコピーしてくれますので、 文字列末については心配する必要はありません。

さて、これで本章の最初に提示した内容は、ほぼ出来たのですが、 実はまだ少し問題が残っています。それは、ユーザーが入力する 行が何行か分からない場合にどうするかという問題です。もし、 行数が50行を越えないことが分かっているならば、ポインタ配列 を用意すれば良いでしょう。しかし、分からない場合も実際に 考えられます。そうした場合には、より高度なメモリ管理技術を 学ばなければなりません。これについては別の章で扱います。



Noriyo Kanayama