ポインタで配列を歩く

添字を使わない走査

前回、a[i]*(a + i) だと確認しました。ということは、添字を回す代わりにポインタそのものを動かしても、同じ走査ができます。

int scores[5] = {80, 90, 75, 70, 85}; for (int *p = scores; p < scores + 5; p++) { printf("%d\n", *p); }

カウンタの i が消えて、代わりに p が要素の上を 1 つずつ移動しています。添字版と結果は同じです。どちらで書いてもよいのですが、ポインタ版に慣れておく理由が 2 つあります。1 つは、C の標準ライブラリや実務のコードがこの形で書かれていること。もう 1 つは、この先の連結リストのように 番号で場所を指せないデータ を扱うとき、走査はポインタでしか書けないことです。

終端をどう決めるか

ポインタ走査で肝心なのは、どこで止まるかです。scores + 5 は最後の要素の 1 つ後ろを指します。前回触れたとおり、この 1 つ後ろは「指すことだけは許されている」場所で、中身を読んではいけません。p < end の比較に使うぶんには安全です。

条件を p <= end と書くと、読んではいけない場所を読みます。うっかり <= にしたときにコンパイラは何も言わないので、ここは自分で見張ります。

終端を先に変数に取り出しておくと、意図がはっきりします。

int *end = scores + 5; for (int *p = scores; p < end; p++) { ... }

scanf にも p がそのまま渡せる

読み込みもポインタで書けます。scanf が欲しいのは書き込み先の番地なので、&scores[i] の代わりに p をそのまま渡せます。

for (int *p = scores; p < end; p++) { scanf("%d", p); }

&p ではありません。p はすでに番地です。ここで & を付けると、ポインタ変数そのものの置き場所を渡すことになり、走査用のポインタが壊れます。

最大値は値ではなく位置で持つ

合計は値を足していけば済みますが、最高点は少し工夫できます。最高点の値ではなく、最高点を指すポインタ を持ち歩く形です。

int *best = scores; for (int *p = scores; p < end; p++) { if (*p > *best) { best = p; } }

こうしておくと、値だけでなく「配列の何番目だったか」も best - scores で取り出せます。名前の配列と点数の配列を並べて持っているとき、この差がそのまま名前側の添字になります。次回以降の成績管理でそのまま使う形です。

では、点数の読み込みから集計まで、添字をひとつも使わずに書いてみましょう。

要件

  1. 点数の読み込みと集計の両方をポインタ走査で書き、添字 [] を使わない
  2. 終端は scores + COUNT で決める
  3. 合計を「合計は400点です」の形で表示する
  4. 最高点を「最高点は90点です」の形で表示する
  5. 平均を「平均は80.0点です」の形で小数第1位まで表示する

入出力例

main("80 90 75 70 85") → "合計は400点です 最高点は90点です 平均は80.0点です" main("100", "62", "88", "54", "71") → "合計は375点です 最高点は100点です 平均は75.0点です" main("45 45 45 45 45") → "合計は225点です 最高点は45点です 平均は45.0点です"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.c
学習モード

メモ

ポインタで配列を歩く

⌘S で保存