【入門】C言語の配列について図でわかりやすく解説!
int aa; int aa[10];
C言語を勉強していて、上記二つの違いで迷ったことはありませんか?
今回は配列を用いた変数宣言について徹底解説していきます。
配列とは
変数aaとaa[10]の違いは?
aaの場合
下記の様にソースコードを書いて実行したとき、どう出力されると思いますか?
int aa=0, n; for(n=0; n<10; n++){ aa = n; } printf("%d\n", aa);
*1
ある程度勉強してきている人はすぐに分かると思いますが、
9
と出力されます。for文がわからない方に関してはまた後日別記事にて紹介することにします。
変数aaのイメージは、「値が1つだけ入る箱」です。
値が1つしか入らないので、代入された値に再度代入されると情報は上書きされます。
aa[10]の場合
それに対して
int aa[10], n=0; for(n=0; n<10; n++){ aa[n] = n; }
上記のソースコードを見ると一見さっきと同じ構造に見えます。
for(n=0; n<10; n++){ printf("%d ", aa[n]); }
しかしprintf()すると、出力結果は、
0 1 2 3 4 5 6 7 8 9
となります。
aaの時と違って、aa[10]は「10個の箱が用意されるイメージ」つまり、一度で同時に10個変数を宣言することができます。
注意点
int aa[10];
と定義すると10個の変数が用意されますが、さっきの図の最後の箱をみてください。
aa[9]となっています。
要するに変数の数的には10個ですが、最後の変数の番号は9となります。これは最初の変数の番号が0から始まるために起こります。
10個目の値が欲しいからといってaa[10]としてしまうと、出力したときに
warning: array index 10 is past the end of the array (which contains 10 elements)
と出ることがあります。これは要素数が10個しかないのに11個目をindex*2しているために起こっています。
ターミナルによって警告(warning)がでないことがあります。このときには11個目の値は定義されていないため、予期していない乱数が表示されます。身に覚えのない乱数が出たときには変数のindexを確認することをおすすめします。
文字列を取得するchar型配列
char型配列の定義
C言語では原則として、文字列を取得するときにはchar型配列を用います。
char aa[100]; printf("文字列を入力してください : "); scanf("%s", aa); printf("%s\n", aa);
上記のソースコードは文字列を取得してそのまま返すプログラムです。 解説
char aa[100];
文字列入力ではユーザー*3が何文字入力するかわからないので、余裕をもった範囲で定義します。
ここが重要!
printf("文字列を入力してください : "); scanf("%s", aa); printf("%s\n", aa);
scanf()をよくみてください。「aaの前に&がありません!!」
さらにprintf()をみてください。「aaに[ ]がついていません!!」
ここが本当によく間違われる部分です。
文字列取得の時のscanf()の変換文字は%sで、aaには&をつけないのがルールです。
出力の時のprintf()は文字列全体を出力したい時、aa[]というindexは使用しません。aaは文字列の塊として表されているため、aaを代入することによって、文字列全体を出力することができます。
文字数を取得する
配列にはとても便利な機能が備わっています。 今回は2つ紹介していきたいと思います。
char aa[10] = "Hello"; int len=0; while(aa[len] != 0){ len++; } printf("%sの文字数は%dです\n", aa, len);
配列の初期値は長さを宣言しなくてもいい
char aa[] = "Hello";
この変数宣言をみて、[]になにも値が入っていないことに気がつきましたか?これがまず1つめの配列の便利な機能です。
変数宣言で配列の初期値を定義する時にはindexを指定する必要はありません。なぜならindexが定義されていないと勝手に空気を読んで長さを定義してくれるからです。これはchar型配列に限らず、どの配列でも適用できます。ただし、少し書き方が異なることに注意してください。今回はint(整数)での例を紹介しておきます。
int bb[] = {0, 1, 2, 3, 4, 5};
数字列の場合は{}で囲ってあげる必要があります。上記のソースコードの場合は
int bb[6] = {0, 1, 2, 3, 4, 5};
と同じです。
【注意】やりがちなミス
int bb[5]; bb[] = {0, 1, 2, 3, 4};
この様に書いてはいけません。配列の初期値は必ず、変数宣言の時でないといけないルールがあります。
なので宣言文と代入文に分けて書かないように気をつけましょう。
配列の最後には必ず「0」がくる
char aa[10] = "Hello";
「Hello」の文字数は5文字なので要素には以下の図の箱の様に入ります。
5つ目(aa[4])の箱まで順番にHelloが入っています。ここで6つ目(aa[5])の箱に注目してみてください。「0」という値が入っています。
char型配列では文字数よりも要素数が多かったとき、最後の位置を表すために「0」が必ず用いられます。これを利用して以下のソースコードで文字数を取得できます。
int len = 0; while(aa[len] != 0){ len++; }
解説
while文はカッコ内が真である限りループするので、aa[len] != 0 つまり言い換えると、最後の位置「0」が来たときにbreakする(ループから抜ける)ということです。
整数lenの初期値は0なのでaa[0]から始まって値は"H"*4が入っています。
これをループして整数lenを1ずつ加算していき、最終的にlen=5となったときにaa[len]=0となるため、ループから抜け文字数が取得できます。
まとめ + 応用
今回は配列について紹介してきました。ここからは少し難しい話なので今は飛ばしていただいて構いません。
先ほどaa[0]="H"と申し上げましたが厳密には少し違います。コンピュータは文字列をそのまま受け取ることができないので、いったんASCIIコードという番号に変換する必要があります。よって実際にはaa[0]には「72」という番号が入っています。
英数字記号はASCIIコードの32~126まで10進数1バイトで表される番号で定義されています。日本語は種類が多過ぎて1バイトでは表しきれないため、今の知識の段階では表示させることはできません。
このASCIIコードの性質を用いれば大文字から小文字に変換するプログラムも作ることができます。アルファベット以外は*(アスタリスク)になるように設定しています。ASCIIコードを検索して番号を確認してからぜひ参考にしてみてください。
#include <stdio.h> int main(void){ printf("99文字以下の文字列を入力してください "); char aa[100], bb[100]; scanf("%s", aa); int i=0; printf("変換された文字列は"); while(aa[i] != 0){ if(65 <= aa[i] && aa[i] <= 90){ // 65 <= aa[i] <= 90 bb[i] = aa[i] + 32; printf("%c", bb[i]); } else if(97 <= aa[i] && aa[i] <= 122){ // 98 <= aa[i] <= 122 bb[i] = aa[i] - 32; printf("%c", bb[i]); } else{ printf("*"); } i++; } printf("です.\n"); }