文字列と配列
だんだん難しくなってきましたが、がんばって乗り切ってください。後で楽になります。
たくさんの変数をまとめて扱いたいときがあります。例えば、文字列を扱うときがそうです。
C語では、一文字は'a'のように表しますが、文字列は"abc"のように表します。'ab'という書き方は出来ません。"a"は一文字からなる文字列と言う意味で、正しい書き方です。
一文字はchar型で扱うことは、既に説明しましたが、"hello!"のような文字列はどのように変数に入れたらいいでしょうか。
一つのやり方として下のような記述の仕方があります。(ただし、このやり方はあくまで説明のための例で、もっと良いやり方があります。)
//プロジェクト名: string1 #include <stdio.h> //メイン関数 //実行は必ずここから始まる。 int main() { char a0, a1, a2, a3, a4, a5; a0 = 'h'; a1 = 'e'; a2 = 'l'; a3 = 'l'; a4 = 'o'; a5 = '!'; printf("%c%c%c%c%c%c", a0, a1, a2, a3, a4, a5); getc(stdin);//Enterキーが押されるまで待つ return 0;//処理の終わり } |
char a0, a1, a2, a3, a4, a5;は、a0〜a5の6つの変数をchar型として宣言しています。一つずつchar a0; char a1; …としても同じです。
次に、上のプログラムを配列を使って書き直します。以降main関数の外側は省略します。
//プロジェクト名: array1 int main() { char a[7]; a[0] = 'h'; a[1] = 'e'; a[2] = 'l'; a[3] = 'l'; a[4] = 'o'; a[5] = '!'; a[6] = '\0'; // a[6] = 0;と書いても同じ printf("%s", a); getc(stdin);//Enterキーが押されるまで待つ return 0;//処理の終わり } |
char a[7];で7個のchar型の変数で構成される配列を宣言します。変数は、a[0]という使い方をします。括弧の中に0から数えて何番目の変数なのかを数字で指定します。ここで、7という数字に気をつけてください。char a[7];と書いた場合使える変数はa[0]〜a[6]です。
最初のプログラムでは、a0〜a5を使っていましたが、この例題ではa[0]〜a[6]を使っています。一つ多いのに気づいたでしょうか?a[6]='\0';は文字列の最後を表す記号で終端記号(terminal)といいます。'\0'=0です。
配列の内容をまとめて表示するときは、printf("%s", a);のようにします。%sはstring(文字列)の意味です。 aは、char a[7]で指定した変数の名前のaのことです。
a[0]、a[3]などとすると、1番目、4番目の変数を、それぞれ操作(代入、内容を取り出す、など)することが出来ますが、単にaとするとどうなるのでしょう。配列は、必ず順番に隣り合ってパソコンのどこか(実際にはメモリー)に格納されています。aにはその場所を数字で表したものが入っています。この場所や場所を示す数字のことをアドレスといいます。人間には意味不明の数字ですが、printfにとっては意味ある数字です。aに入っている数字から配列の場所を見つけa[0]の内容から次々に表示していきます。そして内容が'\0'になったところで表示を終了します。もし、a[6]='\0';をプログラムから取ってしまうとどうなるでしょう。試してみてください。
2番目のプログラムでは、文字を一文字ずつ代入するのが面倒でしたが、もっと楽な書き方があります。
//プロジェクト名: array2 int main() { char a[] = "hello!"; printf("%s", a); getc(stdin);//Enterキーが押されるまで待つ return 0;//処理の終わり } |
意味は、2番目のプログラムと同じですが、こちらのほうがずっと簡単ですね。書き方が違うだけです。
char a[] =
"hello!";と書くと"hello!"の文字数が自動的に数えられて文字数+終端記号つまり6+1個のchar型の変数の配列が確保されます。
char a[] = "hello!";にはもう一つ違う書き方があります。
int main(int argc, char* argv[]) { char* a = "hello!"; printf("%s", a); getc(stdin);//Enterキーが押されるまで待つ return 0;//処理の終わり } |
char a[] としたとき、aは配列の場所が入ると説明しましたが、配列の場所だけでなく単に場所としたのがchar* aという書き方です。
char* a = "hello!";とするとhello!+終端記号がメモリの中に連続して格納されます。そしてその(先頭の)場所が数字として変数aに格納されます。
char* b;という書き方は変数bがchar型の一文字又は配列の場所を格納する変数であることを宣言しています。*がつくとそうなるというC語の約束です。このaやbのような変数をポインタ(pointer)といいます。この名前は、場所を指し示すという意味から来ています。ポインタを理解出来ればC言語を半分以上理解したといって良いでしょう。最初はちょっと難しく感じるかもしれませんが、いつか分かりますので、すぐに理解できなくてもあせらず行きましょう。
//プロジェクト名: array3 int main() { char* a = "hello!"; char* b; //場所を入れる変数(ポインタ) b = a; //bにaが指し示す場所を入れる printf("%s", b); //bの内容から"hello!"の場所を見つて表示する getc(stdin);//Enterキーが押されるまで待つ return 0;//処理の終わり } |
上のプログラムでは、aに入った"hello!"の場所を示す情報をbに入れて、bを使って"hello!"を表示しています。
もちろん、intやdouble型の配列も定義できます。void以外全ての型の配列を定義できます。
//プロジェクト名: array4 int main(int argc, char* argv[]) { int a[3]; double b[4]; a[0] = 1; a[1] = 2; a[2] = 3; b[0] = 3.14; b[1] = 0.00159; b[2] = 0.00000265; b[3] = 0.000000008979; printf("a[0]= %d; a[1]= %d; a[2]= %d;\n", a[0], a[1], a[2]); printf("b[0]= %f; b[1]= %f; b[2]= %f; b[3]= %f;\n", b[0], b[1], b[2], b[3]); getc(stdin);//Enterキーが押されるまで待つ return 0;//処理の終わり } |
配列とは関係ありませんが、b[2]とb[3]の表示が代入した数字と違ってますね。C語には有効桁があってあまり大きすぎる数字や小さすぎる数字は誤差が出て正しく扱えません。この仕組みについては、別の機会に説明します。
表示の仕方が面倒ですが、文字列のように単にaやbと書く方法はありません。しかし、後で出てくる繰り返し構文を使うともっと楽に表示できます。
代入はもっと楽に書けます。
//プロジェクト名: array4 int main() { int a[] = {1,2,3};
double b[] =
{3.14, 0.00159,0.00000265, 0.000000008979}; |
ただし、int* a = {1,2,3};とは書けません。
int a[] = {1,2,3};として、
int* c = a;
はOKです。これは、理屈というよりも、そういうものとして覚えて置いてください。
それでは次へ進みましょう。