プログラムと言う言葉の語源は、ギリシャ語の プロ (前もって) グランマ (書かれたもの) だと言われています。 そういえば運動会の日程表、研修の計画、テレビやラジオの番組表なども プログラムと言うことがありますね。 当コンテストが競うプログラムは、当然これらではありません。 ここで言うプログラムはコンピュータプログラムのことです。 コンピュータは指示された内容しか実行できません。 プログラムはコンピュータに与える命令のことなのです。
コンピュータへの命令の話をする前に人に対するお願いで考えてみましょう。 例えば「立ってください」というお願いは、相手にどういう動作を期待しているか イメージ付くと思います。 そしてそのイメージをしてもらうためのお願いは、別に"Please stand up." や "Bitte stehen Sie auf."、「請站起來」とも表現できるはずです。 やってもらいたいことに対する表現は一つで無いのです。
コンピュータへの命令も同じです。 様々な表現方法 −プログラミング言語− があります。 みなさんが学校で今までどんなコンピュータ教育のカリキュラムに接してきたかに よりますが、例えば Python, Java, Basic, Processing, C/C++ や 基本情報技術者試験用の疑似言語などを経験したことがあるかもしれません。 こういった言語は文字で命令を記述します。 以下はある「情報 I」の教科書からの抜粋です。
x=10 x=x+5 print(x) |
このようなコードを書いたり読んだりするためには、以下の三つの原則を知っておく 必要があります。
原則 1 よりこのコードは最初 「x=10」 が実行され、次に「x=x+5」が実行され、 最後に 「print(x)」が実行されるのです。 では最初の行の「x=10」とはどういう意味でしょうか。 これは原則 2 の変数です。 「x という名前の情報を蓄える変数」を作り、そこに 10 という値を入れているのです。
次の 「x=x+5」は数学的な統合ではありません。 この等号(=) は右と左が等しいという意味ではなく、左の計算結果を右に入れろという &lArr 的な意味を持ちます。 x+5 の計算ですが、今 x には 10 が入ってます。 それに 5 を足した値を x に入れるのですから、x の値は 15 になります。
そして最後の 「print(x)」は原則 3 の「名前(パラメータ)」の形をしているので関数です。 名前は print、パラメータは x です。 必ずしもそうとは限りませんが、一般に名前は機能を端的に表しています。 「print(x)」の直訳は「 x をプリントしろ」という意味でしょうか。 print を英和辞書で引くと「印刷」という意味が出てきますが、 歴史的な理由からコンピュータ界隈では「結果を提示する」という意味になります。 このため print(x) は x の中に入っている情報を画面に出すという意味になります。 今 x には 15 という値が入っているので、画面に 15 という値が出力されます。
一般にコンピュータのプログラムはこのように文字によって表現されますが、 グラフィカルにブロックをマウスで組み合せて作るものもあります。 次の絵は上述した「情報 I」の教科書で先のコードと同じページに描かれていたものです。 やっていることはどちらも同じです。
![]() |
本コンテンストで扱う言語は C/C++ 言語です。 C 言語は 50 年以上前に作られた古い言語です。 しかしコンピュータのハードウェアに近い記述ができることから、 現在でも組込みシステム内のマイコンプログラムや OS のデバイスドライバを開発するために使われています。 そのため産業界では依然として C 言語を扱える技術者の需要は高く、 工業高校などでは授業で学ぶ機会も多いと聞きます。 本ページの想定読者はコンテストに参加する高校生のみなさんですが、 そういう背景から既に C 言語に触ったことがあるという方もいるでしょう。
そういう方は既に分かっているかもしれませんが、 そうで無い方もいるかもしれませんので改めて C 言語の特徴を紹介してみます。 C 言語は先の 1〜3 に加えて次のような特徴があります。
これらの原則を説明するため、先ほど Python や Scratch で記述した処理を C 言語で書いてみましょう。
#include <stdio.h> int main(void){ int x; x=10; x=x+5; printf("%d\n", x); return 0; } |
原則 4 の謎のしきたりによっていろいろ書かれてますが、実質的な中身は
int x; x=10; x=x+5; printf("%d\n", x); |
という所だけです。 その最初の「int x;」という部分は、原則 5 で書いた部分で 「これから x という名前の変数を使いますよ」という意味です。 int というのは扱う情報の種類なんですが、ここも謎のしきたりで int と書く思っていて差し支えありません。
残り三行は Python のコードとほとんど同じです。 最後の行のプリント系の関数の使い方が若干異なっていますが、 これも謎のしきたりなので気にしなくていいです。 それよりも各行末尾にセミコロン (;) が付いていることを気にしてください。 ここが原則 6 です。 C 言語はセミコロンで命令を区切っているので、極論すれば
int x;x= 10;x=x +5;printf ( "%d\n" , x ) ; |
と書いてもかまいません。 かまわないのですが我々人間は読みにくいと思うのではないでしょうか。 プログラムの構造を人間が視覚的に理解するため空白や改行を積極的に 活用するといいでしょう。 それを示すようなコードを次に示します。 説明のため行番号を入れています。
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: |
#include <stdio.h> int main(void){ int x=0; for (int i=0; i<100; i++){ if (i%13==5){ x = x + i; } } printf("%d\n", x); return 0; } |
このコードは 0〜99 までの数のうち 13 で割ったら 5 余る数の和 (5+18+31+44+57+70+83+96) を計算させるもので (それに何の意味があるかは問わないでください)、 処理の流れを視覚化すると次のような感じになります。
処理を言語化すると「x を 0 にした後、i を 0〜99 まで変化させ、13 で割った時の余りが 5 なら x にその値を加算させ、最後に x を表示する」といった感じでしょうか。 この処理の流れは図中水色の枠で括ったように
という三つのグループが存在しています。 どこが同じグループで、どこがさらにその中のグループかということを明確に示すため、 同じグループは同じ分だけ字下げさせると、 視覚的に分かり易いコードになります。
繰り返しになりますが、字下げは単にコードを読む人間が分かり易くするため 入れることを推奨しているだけです。 コンピュータ的にはあってもなくてもかまいません。 コンピュータは波括弧でグループを判定します。 コードを見てください。 グループ A は 3 行目の右端にある左波括弧が開始の合図です。 それに対応しているのは 12 行目の右波括弧です。 同様にグループ B は 5 行目右端の左波括弧と 9 行目の右波括弧、 グループ C は 6 行目と 8 行目です。 これが原則 7 の話です。 ただ、あそこでは「複数の命令をまとめたい場合」と書いています。 つまり命令が単一の場合は括らなくてもいいのです (括ってもかまいません)。 今回の話のグループ C は x = x +i; という単一の命令です。 そのため次のように波括弧をわざわざ書かなくてもかまいません。
for (int i=0; i<100; i++){ if (i%13==5) x = x + i; } |
当たり前ですが、波括弧は必ず「ここから始まって」「ここで終わる」と対で使わないといけません。 右波括弧と左波括弧の数が一致してないとエラーになります。 これは波括弧に限らないということを書いているのが原則 8 です。 丸括弧 () もそうですし、角括弧 [] もそうです。 また括弧以外に文字列を括るダブルコーテーションや、 文字を括るシングルコーテーションもそうです。
ここまで「C 言語において空白や改行は意味は無いけど、人間が見やすいよう字下げしましょう」という話をしてきました。 コードを書くにあたって人間が見やすいよう工夫することは非常に重要です。 例えば変数の名前 −先ほどは x とか i とか付けました− なども、これは何のための変数なのかもう少し具体的に示す名前にしてみるのもいいでしょう。 後述する関数の名前も工夫すると、コードが読みやすくなります。
しかし変数名や関数名で何をやっていたか後から分かるように書くのはどうしても限界があります。 それを突破するには日本語で何をしているか書くしかありません。 しかしプログラムコード中にいきなり日本語を書くことはできません。 コンピュータはそれをプログラムとして読んでしまうからです。 そこで、ここからここまでは人間のための情報だからコードを解読する際は無視しろという指令をすることができます。 それがコメントです。 原則 9 に書いた通り、C 言語においてコメントは /* 〜 */ で書くか // 〜 で書くかのどちらかです。 以下に例を示します。
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: |
#include <stdio.h> /* コメント コメント コメント */ int main(void){ int x=0; // コメント for (int i=0; i<100; i++){ if (i%13==5){ // コメント x = x + i; } } /* コメント コメント */ printf("%d\n", x); return 0; } |
3〜5 行目はコメントです。 /* が「ここからコメント」という意味で、*/ が「ここまでがコメント」という 意味です。 その間はすべてコメントです。 4 行目は何も書かれてませんが「ここから」と「ここまで」の間なのでコメントです。 13 行目後半から 14 行目前半も /* と */ の間なのでコメントです。 一方で 7 行目後半や 10 行目もコメントです。 // は「ここまで」という印が無く、行のお終いまでがコメントです。
原則 2 で「『名前(パラメータ)』という形の関数でいろいろできる」と書きました。 関数は予め用意されているのもありますが、自分で作ることもできます。 以下のプログラムは二つのパラメータの最小公倍数を表示する関数を作り、 それを二回呼び出すものです。
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: |
#include <stdio.h> void printlcm(int a, int b){ int mul=a*b; while (b){ int tmp = b; b = a%b; a = tmp; } printf("%d\n", mul/a); } int main(void){ printlcm(6, 4); printlcm(21, 14); return 0; } |
具体的にどんな処理をしているのかは気にしなくてかまいません。 とにかく次の二点だけ感じてもらえたらと思います。 一つ目は
void printlcm(int a, int b){ 〜処理〜 } int main(void){ 〜処理〜 } |
という形になっていることです。 これにより printlcm 及び main という名前の二つの関数が作られてます。 C 言語ではプログラムは main という名前の関数から始まるという約束があるので、 このプログラムは 14 行目から始まります。
感じてほしいと思う二つ目は 14 行目と 15 行目でパラメータを変えて printlcm が二回呼ばれていることです。 14 行目のように printlcm 関数が呼び出されると、 その実態である 3〜11 行目に実行が移ります。 printlcm 関数の処理が終わるということは 14 行目の処理が終わることを意味するので、 処理は 15 行目に進みます。 そこでもう一度 printlcm 関数が呼び出され、もう一度 3〜11 行目が実行されるのです。 つまりこのコードでは 4〜10 行目の処理は二回行われるのです。