第3回(2011年10月19日)


今日の演習

 今日は以下の内容で演習を行います.


今日の目標

プログラミング言語には必ず存在する”変数”を理解し使えるようになってもらいます.具体的には,以下のような内容をしっかり身に付けてください.



フォルダーについて(先週行った作業)

 端末室のパソコンにログインした直後には、ファイルマネージャーが起動しているはずです。これを用いて、フォルダーをつくり、これまで作ってきたファイルをフォルダー内にまとめましょう。ファイルマネージャーの使い方の詳細はマニュアルにまかせて、簡単な使い方を実演します(work というフォルダーを作成してもらい、hello.c などのファイルを移動してもらいます)。
再履修の方は既に work があるかもしれません。その場合は、フォルダー作成の前にそれらの名前をそれぞれ work.old などと名前を変更してもらいます。

(work フォルダーを作成)

 実際に work というフォルダーを作成します。そして、そのwork フォルダーにこれまで作成したソースファイル(hello.c)とそれをコンパイルしたもの(hello)を移動しましょう。こんなことをして、上でおこなったターミナルでの作業(コンパイルおよび実行)には影響ないのでしょうか?(当然影響があります。)

 ターミナルを開きます。先ほどと同様、

cc  hello.c  -o  hello

としてみましょう。フォルダー作成等の作業がうまくいっていれば、エラーがでます。なぜなら、コンパイルするべきファイル hello.c を別の場所である work フォルダーに移動してしまったからです。

ホームディレクトリ(ホームフォルダー)

 ターミナルを起動した時点では、自分はホームディレクトリと呼ばれる位置にいます(ディレクトリとフォルダーは同じものだと思ってください)。それは、起動時のファイルマネージャーも同様で、起動時にはホームディレクトリの内容を表示しています。先ほどの作業で、ホームディレクトリにあったファイルを workフォルダーにファイルを移動してしまったため、ターミナルを起動した後、

cc  hello.c  -o  hello

としても、hello.c というファイルが見つからないのでエラーとなったわけです(エラーメッセージもファイルが見つからないといったものだったはずです)。正しくコンパイルするためには、work フォルダー内に自分が移動する必要があります。それには、ターミナルで次のコマンドを実行します。

cd  work

この新たに出てきたコマンド cd は Change Directory の略で、文字通り自分の位置を変更します。上記コマンドで、work フォルダーの中に移動できたので、改めて

cc  hello.c  -o  hello

としてみましょう。今度はうまくいくはずです。ついでに、コンパイルされたプログラムが実行できるかどうかも確かめておきましょう。

./hello

正しく実行できたと思います。

 ところで、ターミナル上で、そのフォルダー内のファイルの一覧を見たい場合もあるでしょう。次のコマンドで見ることができます(ls は LiSt の略です)。

ls  -l

ファイル名と、そのサイズ変更日時などが一覧として表示されます。hello.c や、そのコンパイルされた結果の hello もでていると思います。

 さて、今 work フォルダーの中にいますが、先のホームディレクトリに戻るにはどうするのか?次のコマンドで、ホームディレクトリに戻れます。

cd

当面はこれだけのことができれば十分でしょう。実際ターミナル上でもフォルダーを作成することができるのですが、この演習ではフォルダーの作成ファイルの移動ファイルのコピーはファイルマネージャーで行うことにします。(Windows や Macintosh を使いなれた人は何も問題ないでしょう)

 ターミナルで使えるフォルダーやファイル操作のコマンドのより詳しい情報はこちらにあります。

 今後、この演習で作成するファイルは全て work フォルダーに保存するようにしてください(実演します)。


前回の内容の復習

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    printf("Hello!\n");
}

- - - - - - - - - - - - - - - -

 前回は,上のサンプルソースプログラムを使って,次の事柄を学習しました.

  • Cのプログラムは関数で構成される
  • Cのプログラムには main 関数が必要である
  • 関数の有効範囲は { から } までである
  • printf は画面に文字列を表示するための標準関数である
  • \n は改行(復改)を意味する
  • プログラムの先頭には「#include <stdio.h>」を必ず書く
  • 文末にはセミコロン ; が必要である
  • C言語の文法に従わないプログラムはコンパイル時にエラーとなる

なお,Cコンパイラーを使うとき,まずターミナル上で、コンパイルしたいファイルのあるフォルダー(work フォルダー等)に移動し

 

cc  hello.c  -o  hello

 

等と書きます,これは hello.c というファイル名のソースプログラムから hello という名前のプログラムを作成する(hello.c という名前のC言語のソースプログラムを hello という名前の機械語プログラムに翻訳する)という意味です.ここで、

 

./hello

 

とすることで、プログラムが実行されます,


前回の課題の解答例

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{

    printf("Hello!\n");
    printf("My name is Nobita\n");
    printf("How are you?\n");
}

- - - - - - - - - - - - - - - -
これをコンパイルして実行すると、ターミナルに

Hello!
My name is Nobita
How are you?

と表示されます。

確認問題

次の4行の文字列(3行目は空白行)を画面に表示するプログラムを, (i) printf 関数を何度か使って, (ii) printf 関数を1度しか用いないで, 作成せよ.

This is a 1st line.
This is a 2nd line.

This is a 4th line.

(今日はここから)コメントと字下げ

コメント

 C言語では,ソースプログラムを読みやすくするために,コメントを書き込むことができます.コメントは /* と */ で囲まれており,/* と */ で囲まれた部分にかかれていることはコンパイルに影響ありません.例えば,前回の例題ソースプログラムにコメントを書き込みましょう.(各自後ほど, エディターで hello.c を開き,次のように変更しましょう.)

- - - - - - - - - - - - - - - -

/* サンプルプログラム hello.c */
/*     
c0772001(学籍番号) 計算数学演習   */

#include <stdio.h>

/* main 関数 */
main()
{
   /* Hello! と画面に表示する */
    printf("Hello!\n");
}

- - - - - - - - - - - - - - - -

 このような短いプログラムではあまりコメントのありがたみは分かりませんが,より長いプログラムでは大変効果的です.プログラムのこの部分ではどのような処理をしているかといった内容をコメントとして書き入れる癖をつけておきましょう.

注意: 全角と半角に気をつけてください.日本語が打てる状態で * や / を書くと全角文字になってしまう場合があります.空白文字も同様に全角の空白文字となってしまうことがあります.こまめに日本語モードと英数モードを切り替えてください.このようなミスもコンパイル時にエラーとなります.例えば * / a B は半角文字ですが,* / a B は全角文字です.つづりも文法もあっているのにエラーが出る場合,まずは全角文字を使っていないか疑いましょう.

字下げ

 サンプルソースプログラムでは適当に字下げが行われていました.実は,コンパイル時には字下げは全て無視されます(コンパイラーにとっては字下げなど不要).字下げは,人間がソースプログラムを読みやすくするために行うもので,今後,より複雑なプログラムを作成する際には見やすいように字下げをしてください.字下げのスタイルは色々ありますが,今後私が示すサンプルプログラムの字下げを参考にして,自分なりに見やすい字下げを模索してみてください.


上記,コメントと字下げについては,プログラムの読みやすさという意味では特に重要です.本演習での課題として提出してもらうプログラムの採点では,読みやすさも採点の対象としますので,常に心がけてください.


変数

全てのプログラミング言語には変数と呼ばれるものがあります.変数は,データ(数値であったり,文字列であったり)を一時的に保存しておく箱によくたとえられます.コンピュータープログラムは,そのような変数と呼ばれる箱に入ったデータを処理することにより,有用な仕事をします.また,変数を用いることで,より柔軟な処理を行うことができます.(変数の使い方は,分かってしまえばなんてことも無いのですが,分かりにくいと感じたらどんどん質問してください.)

変数には,整数型実数型文字型と数種類ありますが,まずは整数型変数を扱います.整数型変数は,整数値を保存するための箱です(実数値は保存できない).

変数にはそれぞれ符号付型(signed)と符号無し型(unsigned)の二種類がありますが,当面符号付型を用います(負の数も扱いたいので). 


C言語における変数の宣言と変数の使用

 C言語では,変数を使う場合には関数のはじめの部分で全て宣言しておく必要があります.次に簡単なサンプルソースプログラムを示します.エディターで打ち込み,ファイル名を 1019-1.c として work フォルダーに保存して、コンパイル、実行してみてください.(説明の為に行番号をつけています.エディターにて打ち込む時には行番号は打ち込まないでください.)

- - - - - - - - - - - - - - - -

 1: #include <stdio.h>
 2:
 3: main()
 4: {
 5:     int  a, b, c;
 6: 
 7:     a = 5;
 8:     b = 12;
 9:     c = a+b;
10:
11:    printf(" %d\n", c);
12: }

- - - - - - - - - - - - - - - -

 なお,サンプルプログラム 1019-1.c をコンパイル,実行するにはターミナルを開いて,

cd  work

cc  1019-1.c  -o  1019-1

./1019-1

とします.はじめの cd  work は自分の位置を work フォルダーに移動することを意味していました.


以下プログラムの説明です。

5行目:
 これはこれから main 関数の中で使う変数を
宣言している部分です.int は Integer の略で,整数型の変数を宣言する場合に使います.その int のあとに a, b, c と列挙されていますが,このようにカンマで区切って列挙することで,一度に整数型変数 a, b, c を宣言することができます.行の最後のセミコロンは文の終わりを示しています.宣言とは,先ほどの変数は箱だという説明に沿って考えると,整数を入れることができる a, b, c とそれぞれ名前のついた3つの箱を用意したことになります.

7行目:
 整数型変数 a に整数 5 を
代入しています.代入とは,箱の例でいえば,整数を入れることができる箱に整数である 5 という数値を入れることに対応します.行の終わりのセミコロンは文の終わりを示しています(以下同様).

8行目:
 同様に整数型変数 b に整数 12 を代入しています.

9行目:
 整数型変数 c に a+b の結果(a と b の和)を代入しています.先の7,8行目で a には 5,b には 12がそれぞれ入っているので,c には 5+12 の結果である 17 が入ります.もちろん 17 も整数です(整数同士を足し合わせたのだから当然です). この例からわかることは,変数同士の演算(この場合は足し算)の場合は,その変数の内容(保存されている数値)同士に対し演算が行われ,その演算式は演算結果の値を持つということです.つまりこの例では,c には a+b の演算結果である 17 が代入されます.

11行目:
 整数型変数 c の内容を printf 関数を用いて画面に表示します.詳しくは,次の節で説明します. 

 5行目の宣言は次のように書いても同じことです.ただし,サンプルプログラムのように列挙した方がすっきりしていますね.

    int a;
    int b;
    int c;

また,次のプログラムでもサンプルプログラム同じ結果を得ることができます.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    printf(" %d\n", 5+12);
}

- - - - - - - - - - - - - - - -

上記ソースプログラムは,先ほどのサンプルソースプログラムよりもずっと簡単に見えます.なぜわざわざ変数なんてものを使うのでしょうか.それは,今後習う事柄を理解することで明らかになりますので,楽しみにしておいてください.今は変数の定義の仕方と簡単な使い方を覚えてください.


printf 関数を使って変数の内容を画面に表示する

 先の例題プログラムにコメントをいれて書き直したものを次に示します.ここでの目標は,整数型変数の内容を画面に表示する場合のprintf 関数の使い方をマスターすることです.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    /* 整数型の変数 a, b, c を用意する */
    int  a, b, c;

    /* 整数型変数 a に値 5 を代入 */
    a = 5;
    /* 整数型変数 b に値 12 を代入 */
    b = 12;

    /* 整数型変数 c に a+b の結果を代入 */
    c = a+b;

    /* 変数 c の内容を画面に表示 */
    printf("%d\n", c);
}

- - - - - - - - - - - - - - - -

最後の printf 関数以外は既に説明済みです.

整数値を画面に表示するにはこの例のように

 printf("%d\n", c);

とします.\n は前回でてきた改行を示すものでした(前回言い忘れましたが,特殊文字と呼びます).

問題は %d です.printf 関数の中で用いられる %d のことを,変換文字列といいます.%d の d は decimal(10進数)の頭文字の d に由来します.つまり, %d は対応する変数または数値を,10進数整数として表示する働きをもちます.対応する変数または数値とは,今の場合は整数型変数 c ということになります.

複数の数値を表示したい場合は,次のように書くこともできます.

 printf("%d %d %d\n", a, b, c);

この場合,%d が3つ並んでいますが,これらはそれぞれ後に続く a, b, c に対応しています.

先の例題プログラムを次のように変更してみましょう.printf 関数のところだけ変更されています.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    /* 整数型の変数 a, b, c を用意する */
    int  a, b, c;

    /* 整数型変数 a に値 5 を代入 */
    a = 5;
    /* 整数型変数 b に値 12 を代入 */
    b = 12;

    /* 整数型変数 c に a+b の結果を代入 */
    c = a+b;

    /* 変数 a,b,c の内容を画面に表示 */
    printf("%d %d %d\n", a, b, c);
}

- - - - - - - - - - - - - - - -

この場合も,3つの %d があり,それぞれ後ろの a, b, c に対応しています.つまり,変換文字列と, printf 関数の第2引数以降の引数の数は一致しています.

また

 printf("a=%d\nb=%d\na+b=%d\n", a, b, c);

として実行してみてください。こちらの方が見栄えがいいですね


 先の例でもありましたが,対応するものは変数である必要はありません.次のような使い方も可能です.

 printf("%d\n", 4+5);

この場合,9と表示されます.

 今後この演習では、以下の変換文字列がよく使われます.

%d

10進数で出力する

%f %lf

浮動小数点数として出力する (%lf は倍精度浮動小数点時・後述)

このような変換文字列を,変数の型や表示したい様式にあわせて使うことになります.


言葉で説明するとごちゃごちゃしてわかりにくいですが,あれこれ自分で試してみるのが一番良いと思います.次の課題に取り組んでください.

課題1

 例題プログラム 1019-1.c を変更して,整数型変数の加算以外の演算を試してください(整数型変数とprintf関数の使い方に慣れてください.). C言語では + の他に

+

加算

-

減算

*

乗算

/

除算

%

剰余  (整数のみ)

が利用できます.


実数型変数

実数型変数は 

 float  u, v, w;

というように宣言します.float は,浮動小数点数の(floating point number)からきています.また, printf 関数で実数型変数を表示する場合の変換文字列は %f です.以下のプログラムをエディターで打ち込み実行してください.(これは、円の面積の近似値を求めるプログラムです。自分なりに、コメント文も付け加えてください。)ファイル名は 1019-2.c としてください.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    float pi, r, s;

    pi = 3.14159;
    r = 2.0;

    s = pi*r*r;

    printf("面積は %f です.\n", s);
}

- - - - - - - - - - - - - - - -

このプログラムでは、実数型変数 pi, r, s を用意し,pi には 3.14159 という値を代入し,r には 2.0 という値を代入しています. さらには s に pi*r*r (円の半径を r とした場合の円の面積を求める公式)の計算結果を代入しています.最後の printf 関数で画面に表示される s の値が,半径 2 の円の面積(の近似値)ということになります.

注意 1: 実数型変数に値を入れる場合、r = 2.0 のように、少数点つきで値を与えるようにします。(逆に整数型変数に値を入れる場合、n = 2 のように、整数で与えます。)

注意 2: C言語の実数型(浮動小数点数型)には float (単精度浮動小数点数型)のほかに double (倍精度浮動小数点数型)があります.名前からわかるように,倍精度浮動小数点数型の方が,より高精度に数値を表現することができます(通常単精度浮動小数点型は32bitであって,倍精度浮動小数点型は64bitで表現される).倍精度浮動小数点数型を用いる場合,変換文字列として%lfを用いる必要があるなど,説明が煩雑になるので,演習のホームページでは実数型としては float を用いるよう統一しています(場合によって double を用いることもあります).参考のために,先のサンプルプログラムの倍精度浮動小数点数型を用いたバージョンを以下に示します.(ここでは printf 関数のみ使っているので,実際には printf 関数内の変換文字列は %f, %lf 双方どちらでもよい.後にでてくる scanf 関数の場合には double 型を用いる場合には %lf を用いる必要がある.)

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    double pi, r, s;

    pi = 3.14159;
    r = 2.0;

    s = pi*r*r;

    printf("面積は %lf です.\n", s);
}

- - - - - - - - - - - - - - - -

課題2

 サンプルプログラム 1019-2.c を変更して,半径 3.2 の円の面積(の近似値)を求めよ.


実数型変数を使うことで,円の面積(の近似値)を求めることができました.しかし,これでは違う半径の円の面積を求めたい場合,課題2のようにいちいちエディターでソースプログラムファイルを変更して,コンパイルし実行せねばなりません.半径はキーボードで我々が入力したいものです.次節では,標準関数である scanf 関数を使って,キーボードからの数値データの入力を実現します.


scanf 関数

 キーボードから数値データを入力するには scanf 関数という標準関数を用います.printf 関数は出力を行う関数でしたが,scanf 関数は入力を行う関数です.

scanf 関数による整数値の入力

 scanf 関数を用いたもっとも簡単なプログラムは次のようなものになります.ファイル名を 1019-3.c として,エディターで打ち込んでください.

- - - - - - - - - - - - - - - -

1: #include <stdio.h>
2: 
3: main()
4: {
5:     int i;
6: 
7:     scanf("%d", &i);
8:     printf("%d\n", i);
9: }

- - - - - - - - - - - - - - - -

このプログラムは,キーボードから入力された整数値データをそのまま画面に表示します.(コンパイルして実行したあと、整数値を打ち込んでEnterを押すと、その数値が表示されます。)このプログラムの中で,7行目の scanf 関数がキーボードからのデータ入力を行います.

 scanf("%d", &i);

となっていますが,前半のダブルクォーテーションで囲まれた文字列は,printf 関数と同様の変換文字列です.ただし,printf 関数のように通常の文字列と変換文字列が両方書くことはできず,scanf 関数では変換文字列のみ書くことができますこのサンプルプログラムでは,整数型変数 i に値を入力するので,整数型変数の変換文字列である %d がかかれています.そのあとには コンマ に続いて &i とかかれています.scanf 関数では,変換文字列に続いて,入力されたデータを格納する変数名がきますが,変数名の頭に & をつける必要があります.& をつけねばならない理由はもちろんあるのですが,ここでは scanf 関数では変数の頭に必ず & をつけると覚えてください.

scanf 関数による実数値の入力

 scanf 関数を用いて,実数値を入力し,それをそのまま出力するサンプルプログラムは次のようになります.ファイル名を 1019-4.c としてください(1019-3.c とほとんど同じなので,1019-3.c を変更し,別名保存しましょう).

- - - - - - - - - - - - - - - -

1: #include <stdio.h>
2: 
3: main()
4: {
5:     float a;
6: 
7:     scanf("%f", &a);
8:     printf("%f\n", a);
9: }

- - - - - - - - - - - - - - - -

入力促進メッセージの出力

 先の2つのプログラムでは,「・・を入力してください」といったメッセージは全く画面にでませんでした.これでは,プログラムを使う人にはあまりに不親切です.次のように 1019-4.c を次のように変更しましょう.

- - - - - - - - - - - - - - - -

 1: #include <stdio.h>
 
2: 
 
3: main()
 
4: {
 
5:     float a;
 
6: 
 7:     printf("実数値を入力してください: ");
 
8:     scanf("%f", &a);
 
9:     printf("入力された実数値は %f です.\n", a);
10: }

- - - - - - - - - - - - - - - -

7行目に printf 文が加わりました(9行目も変更されています).このように,入力促進メッセージは,scanf 関数に先立って printf 関数で表示する必要があります.次のように書きたくなる人もいるかもしれませんが,このような書き方はできません

間違った例

scanf("実数値を入力してください: %f", &a);


円の面積を求めるプログラム(改良版)

 では,scanf 関数を使って,先にでてきた円の面積を求めるプログラムを改良しましょう.

 次のサンプルプログラムを 1019-5.c としてエディターで打ち込んでください(行番号は無視してください).これまでの知識で十分理解できるはずです.

- - - - - - - - - - - - - - - -

 1: #include <stdio.h>
 2:
 3: main()
 4: {
 5:     float pi, r, s;
 6: 
 7:     pi = 3.14159;
 8:    
 9:     printf("円の半径(実数)を入力してください:");
10:     scanf("%f", &r);
11:
12:     s = pi*r*r;
13:
14:     printf("円の面積は %f です.\n", s);
15: }

- - - - - - - - - - - - - - - -

このサンプルプログラムは,先ほどのサンプルプログラム 1019-2.c を少しだけ変更した内容となっています.先のプログラムで ,

 r = 2.0;

としていた部分が,printf 関数と scanf 関数に置き換わっています.ターミナルでコンパイルし,実行すると,

 円の半径を入力してください:

と表示され,その状態でとまります.そこで,メッセージどおりに,面積を求めたい円の半径を入力します.例えば, 3.2 と打ち込んで,Enter キーをおしてみましょう.半径 3.2 の円の面積が求まったでしょうか?

 この節でわかったことをまとめると,

printf 関数と scanf 関数を組み合わせて用いれば,メッセージを表示して,キーボードから数値を変数に読み込むことができる

ということになります.


処理が実行される順番.

プログラム中の処理の数が少しづつが増えてきました。(変数の宣言、入力、演算、出力。。。。)ここまでの作業でもう気づいていると思われますが、コンピューターがプログラムを実行する場合、プログラムに書かれている順序で処理が行われます。ですので、処理の配置を適切に行わないと、当然正しく動きませんので、ご注意ください。(例えば先ほどの 1019-5.c でprintf() と scanf() の順序を変えたりしてもらうと、分かると思います。)

これまでの内容の復習として次の課題に取り組んでください.

課題3

 円の半径を入力すると,円の面積および円の円周を計算して両方を画面に表示するプログラムを作成せよ.

課題4

 下記のサンプルプログラムを ,プログラムの利用者が自由に整数値 a, b を入力できるように scanf 関数をつかったものに変更せよ.さらには,足し算だけでなく,その他 a-b, a*b, a/b, a%b 全ての結果を表示するようにせよ. 

  1. b を 0 としてみよ.その場合 0 での割り算が生じ不都合がでる.この問題を回避するには来週以降習う,条件分岐が必要となる.
  2. a = 1, b = 2 としたとき a/b の結果は 0 となる.やってみよ.

 1: #include <stdio.h>
 2:
 3: main()
 4: {
 5:     int  a, b, c;
 6: 
 7:     a = 5;
 8:     b = 12;
 9:     c = a+b;
10:
11:    printf(" %d\n", c);
12: }

課題5

 課題4の変数を全て実数型(float)に変更したプログラムを作成せよ.(a%b 以外を計算して表示するようにする.)a = 1.0, b = 2.0 としたとき a/b の結果はどうなるか?

課題6

4つの実数値, w, x, y, z の入力を促し, それらを入力するとその4つの値の平均値 a, 分散 v を表示するプログラムを作成せよ.

今日学んだ事

  • フォルダーを作成し,ファイルをフォルダーに移動しました
  • 変数(整数型と実数型)を使えるようになりました
  • 変数を使った足し算を行いました
  • 変数を使ったいろいろな計算をしました
  • 変数の内容を printf 関数を用いて画面に表示できるようになりました
  • scanf 関数を使って,数値データをキーボードから入力できるようになりました
  • scanf 関数では,変数名の頭に & をつける必要がありました

戻る