配列

今回の記事の内容は配列です。配列については学習することが多いので記事を2つに分けさせていただきました!

アドレスの話が出たりプログラミング特有の考え方があったりと理解しづらい分野ですが、なるべく丁寧に説明していくので頑張っていきましょう!

前回の復習

前回の記事では演算子について見ていきました。演算子は数が多いので覚えるのが大変ですがひとつひとつは大したことないものばかりなので、使いながら徐々に覚えていけば良いでしょう。

前回の練習問題の解答例

A問題

岩ちょこ君のお財布には1100円入っています。電車の切符を買うには250円必要です。電車に乗った場合に財布の中に残るお金はいくらでしょうか。『算術演算子』を用いて計算してください。なお岩ちょこ君はICカードを持っていないものとします。

解答例

#include <stdio.h>

int main() {
  int money = 1100;
  int ticket = 250;
  int answer = money - ticket;
  printf("%d\n", answer);
  return 0;
}

このように変数を作って書いておくと所持金や運賃が変わった場合に対応しやすいので、なるべく直接数値を書く部分を減らす工夫をしましょう。また『-=』演算子を用いることで、以下のように変数をひとつ節約した書き方ができます。

#include <stdio.h>

int main() {
  int money = 1100;
  int ticket = 250;
  money -= ticket;
  printf("%d\n", money);
  return 0;
}

B問題

2^8を『シフト演算子(<<, >>)』を用いて計算してください。(確認で算術演算子の『*』を使った場合の計算結果も表示すると正しく計算できているか確認できるので、試してみると良いでしょう)

解答例

#include <stdio.h>

int main() {
  int num = 1;
  int pow = 8;
  num = num << pow;
  printf("%d\n", num);
  return 0;
}

左シフトを用いて2^nを計算することができます。詳しくは紙の上で実験してみてください。今回のソースコードでは、2^nのnの部分がpowに当たります。

C問題

53×7を『シフト演算子(<<, >>)』を用いて計算してください。(確認で算術演算子の『*』を使った場合の計算結果も表示すると正しく計算できているか確認できるので、試してみると良いでしょう)

解答例

#include <stdio.h>

int main() {
  int num = 53;
  num = (num << 0) + (num << 1) + (num << 2);
  printf("%d\n", num);
  return 0;
}

53×7 = 53×(2^0 + 2^1 + 2^2)と考えられることから、それぞれを計算して和をとってあげれば解が得られます。

D問題

『論理積(&)』を用いて2019÷8のあまりを計算してください。(確認で算術演算子の『%』を使った場合の計算結果も表示すると正しく計算できているか確認できるので、試してみると良いでしょう)

解答例

#include <stdio.h>

int main() {
  int num = 2019;
  int mask = 8 - 1;
  num = num & mask;
  printf("%d\n", num);
  return 0;
}

2019を2進数に直した時の下3桁を『&』演算子で取り出す処理をしています。
4桁目の重みは2^3, 5桁目の重みは2^4となることから、4桁目以降は全て8で割り切れます。

ただし、このようなあまりの求め方はほとんど使う機会がないので、忘れてしまっても構いません。ただし2進数表記をした時に特定の桁を取り出す操作をする時には、&演算子を使うことになるので頭の片隅に入れておいて必要な時に見直しができる程度には覚えておきましょうね。

配列

前回の練習問題ではややトリッキーな演算子の使い方を実践してもらいました。できなかった問題はソースコードを眺めてみるなりコピペで動かしてみるなりしてどんな処理をしているのかを理解しておくと良いと思います。

今回の記事の内容は配列になります。配列というものを考えるにあたり、以下のソースコードを考えてみます。

#include <stdio.h>

int main() {
  int scoreA = 85;
  int scoreB = 33;
  int scoreC = 50;
  int scoreD = 91;
  int scoreE = 29;
  return 0;
}

このソースコードはA~E君のテストの点数をscoreA, scoreB, scoreC, scoreD, scoreEという名前の5つの変数を作って管理しています。

一見すると何も問題がないように思えるソースコードですが、実際にこのコードを使おうとすると大きな問題が生じます。

何が問題なのかを考えるために、生徒が100人に増えた場合を想定します。まず考えられることとして生徒の数が増えると、それに伴って変数の数も増えていきますよね? そうなると変数が100個必要になりコードの中に変数が多くなり、ソースコード全体の見通しが悪くなります。更に変数が増えると管理が大変になってくることも容易に想像できます。(うっかり同じ名前の変数を作ってエラーが起きるなんてことになりかねませんよね)

これを解決する方法として配列というものを勉強していきます。参考書なんかでは『配列というのはロッカーのような連続した箱』と説明されています。しかし当時の自分はそれで納得できなかったのでもう少し踏み込んだ説明をしていきます。

変数の値やプログラムというのはメモリ(PCの作業台みたいなもの)に置かれています。この変数の値やプログラムなどが格納されている場所を指し示すものをアドレスといいます。(アドレスを日本語にすると住所なんかの意味もあるのでイメージしやすいですね)
配列というのはメモリ上に割り振られたアドレスに対して連続した領域を確保してデータを保存することができるものです。

アドレスのお話をしっかり理解するためには、アセンブリを勉強してもらうのが早いのですが、初学者には難易度が高いので今はこの程度の理解で大丈夫でしょう。ポインタの項目でもアドレスという単語は出てくるので、覚えておいて下さいね。

先ほどの例では各々の学生に対して変数を作り点数を管理していましたが、配列を用いることでメモリ上の連続した領域にデータをまとめて管理することができるわけです。

データをまとめて扱うためには配列を使うと上手くいくことがなんとなくイメージしてもらえたと思うので、この記事の後半では実際にプログラム中で配列を使えるように文法を勉強していきましょう。

まずは配列を使うための準備です。配列の基本的な文法は以下のようになります。

型名 配列名[要素数];

これを配列の宣言といいます。宣言という言葉については変数の時にも出てきましたね。ここではメモリ上に要素を入れておくアドレスを確保して配列というロッカーを準備する工程になります。

配列を宣言したらそれぞれの箱に値を代入します。

型名 配列名[要素数]; //配列の宣言部分
配列名[0] = 値;
配列名[1] = 値;
配列名[2] = 値;
/*以下省略*/

このように配列の0番目, 1番目, 2番目,……の箱にそれぞれ値を入れていきます。これを代入と呼びます。

具体的なサンプルコードで配列の宣言と代入を見ていきましょう。

#include <stdio.h>

int main() {
  int score[5]; //配列の宣言 int型の値が5つ分入るロッカー
  score[0] = 85;
  score[1] = 33;
  score[2] = 50;
  score[3] = 91;
  score[4] = 29;
  printf("%d\n", score[0]); //配列の0番目に格納された値を出力
  return 0;
}

実行結果

85

このソースコードでは4行目でint型の値を5つ格納できる配列scoreを作って、5行目以降でそれぞれの箱に値を入れています。

注目して欲しいのは配列の中の値を呼び出している部分です。10行目のprintf関数では『score[0]』と書くことで普通の変数と同じように扱えています。これは配列scoreの0番目の要素を表示してくださいという処理になっています。配列は『角括弧[~]』を使うことで~番目の値を取ってきてという指示ができ、これが配列の最大のメリットです。

また、配列は前の箱から順番に0番目, 1番目, 2番目,……と数えることにも注意してくださいね。

配列の宣言と代入について勉強しましたが、根本的な解決になっていませんね。それぞれの箱ごとに代入をしていたら結局コードの見通しは悪いままです。本当はfor文と組み合わせると数行で書けるのですがそれは置いといて、ここでは配列の初期化についてみていきます。

配列の初期化を行う際には次のように書きます。

型名 配列名[4] = {値1, 値2, 値3, 値4}; //要素数4の場合

このように記述することで、1行で配列の宣言と代入がまとめて処理することができます。この書き方ができる時はなるべくこの書き方をすると読みやすいコードになるので配列や変数を使う際には積極的に初期化を使っていきましょう。初期化のときには要素数を省略して書くこともできます。

それでは具体的に配列の初期化を使ったソースコードを書いてみましょう。

#include <stdio.h>

int main() {
  int score[5] = {85, 33, 50, 91, 29};
  printf("%d\n", score[0]);
  return 0;
}

実行結果

85

このように書くことで『tc0601.c』と同じ処理を7行で書くことができました!

最後に、配列を使う際によく用いられるsizeof演算子について説明をします。sizeof演算子というのはバイト数を取得することができる演算子になります。試しに次のコードを実行してみましょう。

#include <stdio.h>

int main() {
  int n = sizeof(int);
  printf("%d\n", n);
  return 0;
}

実行結果

4

私の環境では4と出力されましたが、もしかしたら2と出力された人もいるかもしれません。

このように『sizeof(int);』はint型の数値1つに何バイト用いられているかを調べるために使われます。sizeof演算子を配列に対して用いた場合のサンプルコードを見ていきましょう。

#include <stdio.h>

int main() {
  int number[7] = {49, 11, 39, 18, 33, 24, 71};
  int n = sizeof(number);
  printf("%d\n", n);
  return 0;
}

実行結果

28

このようにすることで配列がメモリ上で何バイト確保しているのかを調べることができます。(int型1つで4バイトで、それが7つ分あるから4×7=28となりますね)
このsizeof演算子を用いることで配列の要素数を計算することができます。具体的に下のコードで確認してみましょう。

#include <stdio.h>

int main() {
  int number[9] = {13, 44, 45, 13, 37, 18, 33, 24, 71}; //要素数9個
  int n = sizeof(number);
  int m = sizeof(int);
  printf("%d\n", n / m);
  return 0;
}

実行結果

9

sizeof演算子を用いて要素数を取得することができました!これを用いることでテストの平均点を計算するプログラムを書く際にも要素数を取得して計算できるので便利ですね。

配列とは、メモリ上で連続したアドレスに要素を格納することができる箱を作り、そこでデータをまとめて扱うことができる方法のことを指す。配列の各要素にアクセスする際には『角括弧[]』を用いて前から何番目というのを指定することで取り出したり、値を更新したりできる。

配列は0番目, 1番目, 2番目,……と一番最初を0番目と数えることに注意が必要!

sizeof演算子を用いるとその変数や配列、型などに何バイト使われるかを調べることが可能で、これを用いて配列の要素数を計算することができる。

まとめ

今回の記事では配列について勉強しました。また配列とともによく使われるsizeof演算子についても触れてみました。復習として練習問題にもチャレンジしてみてくださいね。今回の内容を簡単にまとめてみましょう。

  • 配列というのはデータをまとめて扱うことができるもの。
  • 配列を使う際には角括弧[]を用いてアクセスする必要がある。
  • sizeof演算子を用いると変数や型などのバイト数を調べることができる。

for文を勉強すると配列のありがたさがよくわかるので楽しみにしていてください!次回は配列の応用を見ていきます。

練習問題

A問題

岩ちょこ君のクラスには6人の生徒がいます。岩ちょこ君の調査によるとA君からF君の成績は順番に、5, 2, 6, 2, 8, 1であることが判明しました。今日はC君の三者面談です。C君の成績を親御さんに見せてあげるプログラムを作成してください。(配列を作ってそこから値を取り出すようなプログラムを書いてみてくださいね)

B問題

岩ちょこ君のクラスでは生徒が5人います。そして今日は年1回の身長を測定する日です。その結果、A君からE君の身長は順番に、150.3, 142.6, 160.4, 146.7, 152.2でした。A君の身長を出力してください。

C問題

岩ちょこ君のクラスには中二病四天王がいます。彼らによるとA君は四天王の中でも最弱らしいです。A君の戦闘力をスカウターで測定すると3でした。残りの四天王もついでにスカウターで測定したところ、戦闘力が5, 7, 9であることがわかりました。四天王の戦闘力の平均値をsizeof演算子を用いて計算してください。

演算子【C言語講座#5】

配列の応用【C言語講座#7】


最後まで記事を見ていただきありがとうございます。また別の記事でお会いできることを祈っております。

Print Friendly, PDF & Email

C言語カテゴリの最新記事