for文を使った繰り返しが二回出てくる. 一回目はデータを読み込むためのもの, 二回目は総和を計算するためのものである.#include <stdio.h> #include <stdlib.h> int main(void); int main(void){ int data[10]; char line[256]; int i; int sum; for(i=0; i<10; i++){ gets(line); data[i] = atoi(line); printf("%d\n", data[i]); } sum = 0; for(i=0; i<10; i++){ sum += data[i]; } printf("%d\n", sum); return 0; }
サイズNの配列の要素すべてについて何か処理をするときの
というのはイディオムとして覚えてしまおう. (繰り返しの上限は「i<=(N-1)」でもよいのだが, 上の方が簡潔だろう.)for(i=0; i<N; i++){ 処理 }
データを入力するところは課題1とまったく同じ. あとはそれを逆順に出力するだけだが, 上のプログラムでは for文を逆に回して(つまり変数iを9から0まで減らしながら) データを出力している.#include <stdio.h> #include <stdlib.h> int main(void); int main(void){ int data[10]; char line[256]; int i; for(i=0; i<10; i++){ gets(line); data[i] = atoi(line); printf("%d\n", data[i]); } for(i=9; i>=0; i--){ printf("%d\n", data[i]); } return 0; }
別の考え方として, for文は順方向に回して(つまり変数iを0から9まで増やしながら), 出力するデータの添字(つまり番号)を細工するという方法もある. こんな感じ:
配列の添字には「9-i」のように任意の式が書けるのを利用している. いずれにせよ, 添字が一つずれたりしないように要注意. (実際, 添字が一つずれる, というのはプロでもよくやる間違いのひとつである)for(i=0; i<10; i++){ printf("%d\n", data[9-i]); }
配列 data[i] に, i番目のデータを記憶する. そのあと, 赤字の部分で, i という整数の出現回数を求めている. 青字の部分で, その出現回数が最多記録を更新したか調べている. 求められているのが「最多回数」ではなく「最多回数出現したi」であるので, max のほかに maxi も必要になる.#include <stdio.h> #include <stdlib.h> int main(void); int main(void){ int data[10]; char line[256]; int i, j, n; int max, maxi; for(i=0; i<10; i++){ gets(line); data[i] = atoi(line); printf("%d\n", data[i]); } max = 0; for(i=0; i<10; i++){ n = 0; for(j=0; j<10; j++){ if(data[j] == i){ n++; } } if(n > max){ max = n; maxi = i; } } printf("%d\n", maxi); return 0; }
このプログラムは, 考え方2に比べると無駄が多い. プログラムを見ると, for文が二重になっていて, それぞれ10回ずつまわるから 100回の処理が行われることになる.
今度は配列 count[i] を, 「iの出現回数をかぞえる」ためにつかう. そのために, まずはじめに count の全要素を 0 にクリアしている(青色部分). ふつうの変数と同じで, 宣言しただけでは 0 になってはいないので.#include <stdio.h> #include <stdlib.h> int main(void); int main(void){ int count[10]; char line[256]; int i, j; int max, maxi; for(i=0; i<10; i++){ count[i] = 0; } for(i=0; i<10; i++){ gets(line); j = atoi(line); printf("%d\n", j); count[j] ++; } max = 0; for(i=0; i<10; i++){ if(count[i] > max){ max = count[i]; maxi = i; } } printf("%d\n", maxi); return 0; }
赤色の部分がデータを読み込むループであるが, ここで, 読み込んだデータ j を 使って count[j] を一つ増やしている. データそのものは保存していないことに注意.
さいごに, count[i] の最大値を求めるfor文があって完成である.
考え方1と比較すると, 二重のループがなく, データの個数(この場合は10)の定数倍で処理が完了する. ただし, この方法が可能であるのは, 「入力されるデータの範囲(この問題では0から9)が あらかじめ決まっている」必要がある. どういうデータがくるかわからないときには, それを数えるための配列をどれだけとればいいか決められないため.