文字列

文字列


サイト全体の目次

稿


稿

文字列と配列

このセクションのソース

/*01*/ #include <stdio.h>
/*02*/ 
/*03*/ main()
/*04*/ {
/*05*/   char str[32] = "Hello, world.\n";
/*06*/ 
/*07*/   printf("str = %s\n", str);
/*08*/ 
/*09*/   return 0;
/*10*/ }

(untitled)

文字列と言っても、1つの変数に何文字もを入れることは出来ません。1つの文字変数には1つの文字しか入らないのです。このことは先に書いたとおり「文字変数には文字コードが入っているにすぎない」事を考えれば納得できると思います。ですから、文字列を扱うためには文字型の配列を用意し、それがあたかも文字列であるかのように扱います。ちょうど、原稿用紙の1マスには1文字しか書かないのといっしょです。

というわけで32個の要素をもつ char 型の配列 str を作りました。次に代入するのですがその前に注意することがあります。C言語では配列のの中でそこが文字列の終わりであることを\0(NULL(ヌル)文字)で認識します。だから、文字列の最後にはかならず「\0」を入れておかなくてはなりません。つまり、扱える文字列の最大文字数は「(宣言した配列数) - 1個」という事になります。list-4.2.1 では32個の配列を用意したので、最大で31文字の文字列を扱うことが出来るわけです。なお、当然ながら配列分いっぱいに使う必要はありません。後々のことを考えて、充分な配列を宣言しておきましょう。.

char x[32];    と宣言し、配列分いっぱいに文字列を代入した場合、

   |  H  |  e  |  l  | ... |  d  |  .  |  \n |  \0 |
-------------------------------------------------------
...| 528 | 529 | 530 | ... | 556 | 557 | 558 | 559 |...
-------------------------------------------------------
   |x[0] |x[1] |x[2] | ... |x[28]|x[29]|x[30]|x[31]|
「\0」は、これで1文字なのです。このほかにも「\n」などの制御文字は、
それで1文字として扱います。
	

では、代入(初期化)しましょう。ですが、実はこの代入がクセモノなのです。まず、最も簡単な方法は list-4.2.1 にあるとおり宣言と同時に初期化する場合です。ですが list-4.2.1 を見て「アレ?」と思いませんか?本当なら「\0」を書かないといけませんよね。ここでちょっと、1文字の時と比べてみましょう。

char ch = 'a';
char str[32] = "Hello, world.\n";

1文字は「'(クウォーテーション)」、文字列は「"(ダブルクウォーテーション)」で囲まれていますね。こうすることでそれが文字列であると認識します。文字列として認識された場合、文字列の最後に自動的に「\0」が付け加えられて代入されるため、わざわざ書く必要がないのです。

初期化と同時に宣言しなかった場合はかなり面倒になります。というのは、基本的に配列1つづつに、個別に代入していかなければならないからです。

char str[32];

str[0] = 'H';
str[1] = 'e';
str[2] = 'l';
str[3] = 'l';
str[4] = 'o';
 :
 :
str[12] = 'd';
str[13] = '.';
str[14] = '\n';
str[15] = '\0';

この場合、それぞれの要素は1文字変数と同じ扱いになるので「'」で囲みます。また、最後には「\0」を自分で代入しなければなりません。

ですが、これではあまりに不便なので、標準ライブラリ関数strcpyを使います。使い方は、

/* ヘッダーファイル string.h をインクルードします。 */
strcpy(str, "Hello, world.\n");

のようにします。これで、第1引数の配列に第2引数の文字列が代入されます。あるいは、すでに文字列が代入されている配列を第2引数に書いてもかまいません。その場合、
strcpy(str1, str2);

のようになります。なお、どちらの場合にしても第1引数に指定されている配列の大きさ以上のものは入れられません。そういった場合、'\0' すらも入らないのでエラーの原因になります。注意してください。

さてさて、strcpy の例でお気づきになったでしょうか?

strcopy(str1, str2);

この引数はいずれも配列の文字部分だけです。ということは、これは配列の先頭アドレスを書いているにすぎないのです。これはどういうことなのでしょうか。

この関数では、第2引数から渡された文字列を、第1引数で指定されたアドレスを先頭とする領域に代入していきます。それに対し第2引数の方は、第2引数で指定されたアドレスから「\0」までを文字列として処理します。

要するに、C言語では指定されたアドレス(ポインタ)から「\0」までを文字列として扱うことになっているのです。

文字列の詳細

このセクションのソース

文字列の理解を深めるために list-4.2.2 を見てください。

/*01*/ #include <stdio.h>
/*02*/ #include <string.h>
/*03*/ 
/*04*/ main()
/*05*/ {
/*06*/   char str1[32] = "Hello, Programing.";
/*07*/   char str2[32] = "World.";
/*08*/   char *st = &str1[7];
/*09*/ 
/*10*/   printf("strcpy 前\n");
/*11*/   printf("str1 = %s\n", str1);
/*12*/ 
/*13*/   strcpy(st, str2);
/*14*/ 
/*15*/   printf("strcpy 後\n");
/*16*/   printf("str1 = %s\n", str1);
/*17*/ 
/*18*/   st = &str1[14];
/*19*/   printf("str1 の後ろ = %s\n", st);
/*20*/ 
/*21*/   return 0;
/*22*/ }

(untitled)

まず、char 型ポインタ変数 st には str1 の「P」にあたる部分、つまり str[7] を指しておきます。そして、strcpy で st のアドレス(つまり str[7])以降を文字列 str2 に置き換えます。これで、次の printf 文では「Hellow, World.」と表示されるはずです。なお、「Hellow, World.ming.」とならないのは「World」の直後に「\0」が自動的に代入されるからです。ですが、その後ろには「Programing.」の残骸「ing.(及び '\0')」が残るので、「'i'」にあたる部分のアドレスを文字列のはじめとして指定すれば、そこを文字列として扱うことができます。.

   |  l  |  d  |  .  |  \0 |  i  |  n  |  g  |  .  |  \0 |
-------------------------------------------------------------
...| 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 |...
-------------------------------------------------------------
   |x[10]|x[11]|x[12]|x[13]|x[14]|x[15]|x[16]|x[17]|x[18]|
	

このことから、指定されたアドレスから「\0」までを文字列として扱うことを再確認してください。このことは、他の関数を使う上ではもちろんのこと、C言語で文字列を扱う上での大原則ですので、きちんと理解しておきましょう。

さて、printf での文字列の扱いです。printf で文字列を表示するための変換文字は「%s」です。そして、第2引数以降で指定されたアドレス(普通は文字列の先頭アドレス)から「\0」までを1つの文字列として表示します。

ちなみに、漢字などの2バイト(全角)文字は char 型配列のうち2バイト分、つまり2つ分を使って文字列として扱います。ですから、漢字1文字を扱いたい場合でも、最低「2バイト + ’\0’の分」で、3バイト以上の配列が必要になります(char str[3] = "漢"; のように)。

練習問題

問題-4.2.1

プログラムの先頭で、大文字と小文字が存在する文字列

char str[32] = "HeLlo, woRLd.";

を宣言し、ポインタをうまく利用することによって大文字だけの文字列に直してください。

練習問題回答例

問題-4.2.2

ポインタ p を使って str を先頭から '\0' まで読み取って行きます。その際、p の指す要素が小文字であるならばそこを大文字に変えます。


読み込み中・・・
10秒待っても表示が変わらない場合、次の理由が考えられます。
・Javascript が無効になっています。
・検索エンジンのキャッシュを見ています。
サイトホームへ / 上位ページへ / ページトップへ / PAROFトレンドショッピングへ
Copyright (C) 2010 totobon all right reserved.