2006 年度「計算機基礎論3B」 2006-10-20

§13 初めてのCプログラム

(13.1) プログラムを書くに当たっては テキストエディタで「ソースファイル」を作成し、 「コンパイラ」でそれを「コンパイル」し、「実行ファイル」を作る (のが普通である)。

(13.2) 「実行ファイル」はコンピュータが読んで実行するもので、 人間が読んでもまずわからない。 「ソースファイル」は文字だけが並んでいるテキストファイルで、 訓練をつめば読み書きができるようになる。 「コンパイル」はここでは「変換する」「翻訳する」ぐらいの意味である。 ソースファイルを書く際に用いる言語はいろいろあるが、 ここでは「C言語」(シーげんご)を用いる。 C言語で書かれたソースファイルを実行ファイルにコンパイルするコンパイラのことを 「Cコンパイラ」とも言う。 Cコンパイラの使い方は、この授業の範囲では極めて簡単である。 よって、 これから学ぶことの中心はC言語によるソースファイルの書き方である。 以下、「プログラミング」と言ったらそれを指す。

(13.3) コンピュータにおいて、 バックスラッシュ「」と円マーク「」 は半角文字では同じものと思ってよい。 スラッシュ「」は別物である。向きが違う。混同しないように。 右手で文字を書く人にとって書きやすいほうがスラッシュ、 逆向きがバックスラッシュと覚えるとよい。 (「全角文字」とはほぼ正方形をしている「あいうえおABC123」などの文字。 「半角文字」はそれを縦に半分に割った大きさの、 「ABC123」などの文字。 この節の「」「」「」 はいずれも全角文字である。)

(13.4) 次の例は参考書としてあげておいたカーニハン/リッチー著・石田晴久訳「プログラミング言語C第2版」(共立出版) (以下 K&R2 と略す)の §1.1 とほとんど同じである。 上下の「===」の行はプログラムには含まれない。 また、「hello.c」とあるのはこの名前をつけることを勧める、 の意味である。 C言語のソースファイルは「.c」で終わる名前でなければならない。

== hello.c =====================================================================
#include <stdio.h>

main() {
    printf("hello, world\n");
}
================================================================================

(13.5) 1 行目。 きょうのところはこれは「決まり文句」と考えよう。 「#」は Shift しながら 3 のキーを打つ。 この記号は楽譜の中で使ったときの名称から 「シャープ」と呼んでおくが、正式名称は別にあったと思う。 include は英単語そのままだ。 この次にスペースを入れているが、入れなくてもよい。 stdio.h を囲む 「< >」は不等号をカッコの代わりに使っているもの。 Shift しながらカンマとピリオドのキーを打つ。

2 行目は空行である。見やすくするためにおいたもの。意味はない。

3 行目と 5 行目もCプログラムに必ずおくもの。 「main」の次にあるのは小カッコの開きと閉じ。 Shift しながら 8 と 9 のキーを打つ。 この次にスペースを入れているが、入れなくてもよい。 その次にあるのは中カッコの開き。 5 行目にあるのが中カッコの閉じ。 中カッコは、Shift しながらタイピング練習で使った大カッコのキーを打つ。 これらの中カッコは 4 行目を囲んでいる。つまり、 「main() { ... }」のことである。 こう書かずに上のようにする理由はそのうちわかってくる。 また、この中カッコの書き方は K&R2 とやや異なる。 この授業では一貫して私の書き方で教えるので、 すでに自分流のつけ方を編み出している人以外はとりあえずそれにならうこと。

よって、4 行目がこのプログラムのうちで最も意味のある部分だということになる。 この行は頭に空白がある。 この空白は Tab(タブ)キーを一度押すことでとる。 空白を置く理由はそのうちわかってくる。 このように行頭に空白を置くことを「字下げ」「インデント」という。 また、そこには tab という見えない文字があると考える。

printf() は元々用意されている「関数」である。 「プリントエフ」と読むことが多いかと思う。 関数の原語は function で、ここでは本来の意味である「機能」に近い。 この関数の機能は後ろの小カッコの中の文字列を印字する(=画面に書く) ことである。 文字列は二重引用符「" "」で囲む。 二重引用符は Shift しながら 2 のキーを打つ。 ここでは印字される文字列に「\n」が含まれている。 「\n」はこの二文字で「改行」を意味する。 すなわち、これを画面に書くとそこで改行する。 よって、「hello, world\n」を画面に書くということは、 「hello, world」を画面に書いて最後に改行する、 ということになる。

4 行目の最後にはセミコロン「;」がついている。 C言語では文はセミコロンで終わることになっているので、忘れてはいけない。 また、この「セミコロン」などの名称もこの機会にきちんと覚えてしまうとよい。

(13.6) これをコンパイル・実行する際の流れは次の通り。

  1. emacs hello.c」としてソースファイル hello.c を作る。
  2. gcc hello.c」としてコンパイルする。 何も出力されずにプロンプトが出れば成功である。 そのときは実行ファイル a.out ができている。
  3. ./a.out」でプログラムを実行する。

(13.7) 注意: 教科書では cc とあるがここのシステムでは gcc である。 実行させる際、a.out の前の ./ に注意。 a.out から(たとえば)hello という名前に改名した場合は、 「./hello」として実行する。 (改名(=ファイル名の変更)は §10.1 参照。)

(13.8) 注意: プログラムをホームページからコピーした場合には、 インデントの空白は tab ではなくスペース四つになるが、 コンパイル結果には影響しないので気にしなくてよい。

(13.9) 練習問題(第〇部)

  1. 上のサンプルプログラムを内容とするファイル hello.c を作り、コンパイルし、できた実行ファイル a.out を実行せよ。 ソースファイルは、自分で打ち込むのと、ホームページからコピーするのと、 両方やってみるとよい。
  2. 上でできた実行ファイル a.outhello と改名してから実行してみよ。

(13.10) 以下の練習ではソースファイル名は指定しない。適当につけること。 hello.c の内容を次々と変更していっても構わない。

(13.11) また、emacs をいちいち終了せずに

  1. ソースファイルを変更する、
  2. 「File」「Save (current buffer)」 (または Ctrl+X Ctrl+S を順に押す)で保存する、
  3. コンパイル・実行する
をくり返して進めてゆくこともできる。 (このときには「emacs hello.c &」のように 「&」をつけて emacs を起動することが必要。)

(13.12) プロンプトが出ているところで「↑」キーを何度か押すと、 以前に打ち込んだコマンドが出てくる。 行きすぎたら「↓」で戻れる。 それを編集してから実行することもできる。

(13.13) 練習問題(第一部)

  1. 上のサンプルプログラムから「;」 を抜かすと正しいプログラムでなくなり、コンパイル時にエラーメッセージが出る。 これを体験せよ。 閉じるほうの二重引用符を抜かしたらどうなるか、などもやってみよ。
  2. 同様に、最後の中カッコ閉じを抜かしてみよ。
  3. 上のサンプルプログラムから \n を取り除いたプログラムを作れ。 (作って終わり、ではない。コンパイルし、実行し、結果を確認すること。 以下同様。)
  4. 上のサンプルプログラムを元に、 「hello, 」と「world\n」 の二度に分けて出力するプログラムを作れ。 (ヒント:
        printf("...");
        printf("...");
    
    のようになる。)
  5. hello, world\n\n」と出力し、 次に「hello, world\n」を出力するようなプログラムを実行したら、 全体の出力結果はどうなるか。 プログラムを書きながら予想し、 それからプログラムを実行して、納得するまでよく考えよ。

(13.14) 練習問題(第二部)

  1. 「こんにちは、世界」のような、 適当な日本語を出力するプログラムを書け。
  2. printf の前のあきは半角スペースかタブでなければならないが、 もしも間違えて全角スペースにしてしまったらコンパイラはどのようなエラーメッセージを出すか、 試してみよ。 (emacs+Wnn では、全角スペースは日本語入力モードにしたのち 「大文字の Z」「スペース」と打てば入力できる。)
  3. 文字列を囲む二重引用符は半角でなければならないが、 (いわゆる)日本語(←全角文字のこと) を入力した直後には間違えて全角の二重引用符を打ってしまうことがある。 そうしたらコンパイラはどのようなエラーメッセージを出すか、 試してみよ。
  4. 最後の中カッコ閉じは半角でなければならないが、 もしも全角だったらどうなるか。

§14 ごく簡単な計算

== tasizan.c ===============================================
    /* たし算  1990-04-28, written by Iwase */

#include <stdio.h>

main() {
    int a, b, sum;                /* 変数の宣言 */

    a = 2;                        /* 代入 */
    b = 3;
    sum = a + b;

    printf("%d たす %d は %d です.\n", a, b, sum);
}
============================================================

(14.1) 1行目。 「/*」と「*/」とで囲まれた部分はコメントである。 何を書いてもコンパイルしてできる実行ファイルには関係ないので、 自由にメモを書くことができる。 ここでは、何をするプログラムか、いつ誰が作ったかを書いている。 その下のコメントは以下で説明する際の便宜のためにつけたものである。 これらは諸君は打ち込まなくても構わない。

(14.2) 「変数の宣言」の行。 変数を使う場合、前もって「宣言」しておく必要がある。 ここでは「変数 a, b, sumint 型」と宣言している。 変数名には小文字を使うのが普通である。 「int 型」は整数のみを格納できる「整数型」の一つで、 この名前は整数 integer に由来している。 私は「イントがた」と読んでいる。 変数の宣言はこの位置で行なわなければならない。 その次には空行をおくと見やすくなる。 なお、中カッコの中の行は(空行以外)すべて字下げする。

(14.3) 「代入」の行。 「a = 2」は、「a は 2 に等しい」という平叙文ではなく、 「a に 2 を代入せよ」という命令文である。 その下の二行も同様。 プログラムは特に指定しなければ上から下へと実行されるので、 sum = a + b; を実行したあとの sum の値は 5 になる。 なお、 「=」は Shift しながら「-」のキー、 「+」は Shift しながらセミコロンのキーを打つ。 「a = 2;」の 「a」「=」「2」の間にはスペースを置いても置かなくてもよい。

(14.4) printf 文の行。 記号「%d」は、順に後ろの変数の値に置き換わって画面に出力される。 ここでは、 一つめの %da の値で、 二つめの %db の値で、 三つめの %dsum の値で置き換わる。

    printf("%d たす %d は %d です.\n", a, b, sum);
            --      --    --           -  -  ---
            |       |     |            |  |   |
            +-------|-----|------------+  |   |
                    +-----|---------------+   |
                          +-------------------+
よって、出力は「2 たす 3 は 5 です.」のあと改行、となる。 「%」は Shift しながら 5 のキーを打つ。 (読点「」の代わりに半角のピリオドを使っているのは単に趣味の問題である。)

(14.5)

(14.6) 練習: 0 で割り算をするとどうなるか試せ。具体的には、

(14.7) 練習: 出力の文の二重引用符の間の文字列からスペースを除去し、 「printf("%dたす%dは%dです.\n", a, b, sum);」 としたら出力はどう変わるか。 「printf("%d%d%d\n", a, b, sum);」としたらどうなるか。

(14.8) 注意:「core を出力しました」と言われたら、 core.????(「?」は数字)という名前のファイルができている。 このファイルは場所ふさぎなだけなので、 なるべく早く削除すること。 (削除については §10.1 参照。)


岩瀬順一