CONTENTS / BACK-PAGE / NEXT-PAGE

 ここでやっとプログラミングについて解説する。そのためには、プログラム言語を1つ定めてその文法を説明するとともに、プログラミングのノウハウについて解説していく。本講座では、最近特に注目されているC言語を用いることにする。

3 C言語の基本文法

 本章では、C言語の基本的な事柄について解説する。はじめに具体的なCプログラムを提示し、プログラムの書き方や約束事を順次説明していく。

3.1 簡単なプログラムスタイル

 Cプログラムの基本的なスタイルと標準出力関数について学ぶ。Cのごく 簡単なプログラムを示しながら解説する。


プログラム3−1

/*  1 */  /*  Example program 3-1  */
/*  2 */  /*  programmed by Nanashino Gonbe.   1992.4.1   */
/*  3 */  #include <stdio.h>
/*  4 */  main()
/*  5 */  {
/*  6 */       printf(" This is a sample program for C language.\n");
/*  7 */  }
 プログラム3−1が一般的なCプログラムの基本スタイルである。以下、 1行づつ細かく解説する。

***解説***

1,2: 注釈文(コメント文)でCプログラムの実行には、一切影響しない文である。注釈は '/*' と '*/' の間に書かなければならない。通常プログラムの先頭や途中にこのように注釈行を入れ、プログラムに対する説明やプログラミングした人の名前,作成した日時などを記入しておく。こうすることによって、プログラムが読みやすくなったり、 Version 管理がしやすくなる。
3:標準入出力ライブラリを利用することを宣言する。ここでは、すべてのプログラムにこの宣言を入れると考えてよい。
4:関数名を書き、()内に引数を書く。引数については後で詳しく説明する。この場合関数名はmainである。Cプログラムにはmainが必要で、実行はmainから始まる。
5:関数mainの本体の範囲を示すための開始記号である。
6:実行結果を出力するための関数 printf を用いて、
This is a sample program for C language.
とメッセージを出力する。printf 関数で”と”で囲まれた部分の文字列を出力することができる。この文字列を変更することにより、異なったメッセージを出すことができる。文字列の最後の \n は、文字列出力後改行することを指示する制御文字である。但し,UNIXなどでは¥のかわりに\を用いるので注意されたい。(わきみち参照)実際 printf 関数本体も、main() と同様に{からプログラムが始まり}で終るスタイルをしている。 printf の関数の実体は標準入出力ライブラリ stdio.h の中にあり、頻繁に使われるような関数はここで用意されている。これを利用するために、3:のような宣言をする必要がある。

 プログラムの1文の終には;(セミコロン)を付ける約束になっている。

7:関数mainの本体の範囲を示す終止記号である。

3.2 変数を使う

 変数の概念および、標準入力関数と四則演算について学ぶ。

変数とは?

 記憶域(メモリ)につけた名前で、そこにある値を格納したり引き出したりすることができるものである。変数を区別するために名前をつけて使う。これが変数名であり、プログラムでは変数名を自由に(変数名として用いてはいけない特殊な名前がある。後章で解説する。)宣言して使うことができる。変数の概念をより理解するために、a、bそれぞれ名前の付いたお皿があり、aのお皿にご飯が、bのお皿に目玉焼きが入っているとする。このとき、a、bが変数名であり、aのお皿の中身つまりご飯が変数aの値で、bのお皿の中身の目玉焼きが変数bの値である。この状態で、お皿aに目玉焼きを入れるとご飯が見えなくなり、目玉焼きの前に何が入っていたのかがわからなくなる。このように1つの変数には1つの値しか格納できず、最後に格納された値がその変数の現在の値となる。プログラム3−2を考えよう。


プログラム3−2

2つの整数を入力し、それらの和,差,積,商を求める。
/*  1 */  /*   Program 3-2                                   */
/*  2 */  /*                             1991.4.2            */
/*  3 */  #include <stdio.h>
/*  4 */  main()
/*  5 */  {
/*  6 */       int a, b, wa, sa, seki;
/*  7 */       float  syou;
/*  8 */ 
/*  9 */       scanf("%d %d",&a,&b);
/* 10 */       wa = a + b;
/* 11 */       sa = a - b;
/* 12 */       seki = a * b;
/* 13 */       syou = a / b;
/* 14 */       printf("%d %d %d %f\n",wa,sa,seki,syou);
/* 15 */  }

***解説***

1,2:注釈行である。1,2行に渡って注釈を書くことができる。しかしプログラム3−1のように、1行づつ /* */ で囲むことを勧める。
3:標準入出力関数ライブラリを利用することの宣言をする。実は、 #include は<>内に書かれたライブラリ(ファイル)を取り込むための命令であり、標準入出力関数ライブラリ名は stdio.h である。つまりこの位置に stdio.h の内容が挿入される。
6:mainで用いる変数の宣言文である。int以下のa,b, ... , seki はそれぞれ整数を扱う変数であることを示している。これらの変数は、整数型(int型)であるという。
7:変数 syou を用いるための宣言である。変数syouは、浮動小数点型(float型)であることを宣言している。
8:6,7行目の宣言文と9行目以下の実行文との間に空白行を置き、プログラムを見やすくした。たいていの場合,宣言文と実行文あるいは実行文でも作業内容が異なるところで空白行を空けてプログラムを見やすくする。
9:標準入力関数 scanf を用い、変数aとbに数値を入力する。” ”内は入力フォーマットと呼び、%dは整数であることを示す。,後のaとbが入力する変数名であり、” ”内の1つ目の%dがaに、2つ目がbに対応している。変数名の前に&を付けているのは格納位置を示すためであり、scanf のパラメータとして格納位置を示してやる必要がある。ここでは、 scanf のパラメータには&を付けることと、&が付くことにより格納位置を示すことを覚えていればよい。
10:変数aの値と変数bの値を足した結果を変数waに代入する。この操作を代入と呼ぶ。数学の=は、左辺の値と右辺の値が等しいことを意味するが、Cプログラムでは、=は、=の右辺の値を左辺の変数に格納することを意味する。

 よってCプログラムでは、

x = x + 1;
のような代入文を書くことができる。これは、xの値に1を加えその結果をxに格納する文である。つまり、代入文の左辺は格納位置(メモリの番地)を、右辺は値を表している。
11:変数aの値と変数bの値を引いた結果を変数saに代入する。
12:変数aの値と変数bの値を掛けた結果を変数sekiに代入する。
13:変数aの値を変数bの値で割った結果を変数syouに代入する。一般的に、整数を整数で割った結果は実数になるため変数syouは、7:でfloat型で宣言した。14:標準出力関数 printf を用い10−13で計算した結果を出力する。printf の” ”を出力フォーマットと呼び、変数wa,sa,sekiの値が%dつまり整数で出力され、変数syouの値が%fつまり実数で出力される。

 プログラムの文の終には;を付ける約束があったが、6−14の後ろには すべて;がついていることを確認すること。また、#include文,main() の 後ろには;を付けないことに注意せよ。

 また、プログラムは上から下へと順に実行される。ここでは、9,10, 11,12,13,14と順に実行される。


変数の理解を更に深めるために、次のプログラムを考える。

プログラム3−3 変数a、bの値の入れ換えをする。

/*  1 */  /*  Program 3-3                              */
/*  2 */  /*         swap data           1992.4.3      */
/*  3 */  #include <stdio.h>
/*  4 */  main()
/*  5 */  {
/*  6 */       int a, b, dummy;
/*  7 */ 
/*  8 */       a = 10;      /*  initialize  a <- 10  */
/*  9 */       b = 30;      /*  initialise  b <- 30  */
/* 10 */       printf("initial state   a = %d,   b = %d\n",a,b);
/* 11 */ 
/* 12 */       dummy = a;
/* 13 */       a = b;
/* 14 */       b = dummy;
/* 15 */       printf("swapped state   a = %d,   b = %d\n",a,b);
/* 16 */  }

***解説***

8,9:初期状態として、変数aに10、変数bに30を代入する。
10:printf関数を用いて,変数a,bの値を出力する。
12:変数dummyにaの値(つまり10)を代入する。この時点で変数aの値と変数dummyの値は共に10である。
13:変数aにbの値(30)を代入する。この時点で変数aとbの値は共に30である。
14:変数bにdummyの値(10)を代入する。この時点で変数bとdummyの値は共に10である。
15: printf 関数を用いて、変数a、bの出力をする。

プログラム3−3の実行結果

	initial state   a = 10,   b = 30
	swapped state   a = 30,   b = 10

 変数a,b,dummyの値をプログラムの実行ステップごとに追跡して みる。以下の表は、各ステップ実行直後の各変数の値を示した。ここで ? は値が未定義(定まっていない)であることを示している。

	 ステップ   aの値   bの値  dummyの値
	──────────────────────────
	   8     10     ?     ?
	   9     10    30     ?
	  10     10    30     ?
	  11     10    30     ?
	  12     10    30    10
	  13     30    30    10
	  14     30    10    10
	  15     30    10    10

 よって初期状態として aの値は10,bの値は30 であったが、ステ ップ15の出力時には、aが30,bが10に入れ換った。このように、2 つの変数の値を入れ換えるには、必ず一時的な変数(ここではdummy) を用意しステップ12,13,14のように3段階の操作を必要とする。こ れが変数の性質でもある。


練習問題

ステップ12,13,14を

	a = b;
	b = a;
とプログラムを変更したとき、結果がどうなるか。考察せよ。


3.3 文字を扱う

 今まで学んだ変数は、数値を扱うためのものであった。しかし、プログラ ムでは文字を扱うこともある。そこで、文字型の変数の利用について解説し よう。プログラム3−4は

プログラム3−4 入力された文字をそのまま出力する。

/*  1 */  /* 文字型の利用     アスキーコードの出力                */
/*  2 */  /*                              1992.4.29    */
/*  3 */  #include <stdio.h>
/*  4 */  main()
/*  5 */  {
/*  6 */       char   a, b, c, d, moji;
/*  7 */ 
/*  8 */       a = 'A';
/*  9 */       b = 's';
/* 10 */       c = 'c';
/* 11 */       d = 'i';
/* 12 */       scanf("%c",&moji);
/* 13 */       printf(" Input character: %c\n",moji);
/* 14 */       printf("      %c%c%c%c%c code: %d\n", a, b, c, d, d, moji);
/* 15 */  }

実行結果 1

Z                              <------ moji に Z を入力した場合
 Input character: Z            <------ ステップ13の出力
      Ascii code: 90           <------ ステップ14の出力

実行結果 2

7                              <------ moji に 7 を入力した場合
 Input character: 7            <------ ステップ13の出力
      Ascii code: 55           <------ ステップ14の出力

***解説***

7:文字型の変数を利用する宣言である。
8:文字型の変数aに文字Aを代入する。=の右辺は文字定数であり、 ' と ' で囲まれた文字がその値である。ステップ8の実行後のaの値はAである。(通常 a の値は'A'であると記す)
9−11:ステップ8同様、文字の代入をしている。
12:scanf 関数を用いて、文字の入力を行う。" "内の入力形式は %c と書くことにより文字型として入力することを意味する。ここでは、文字型変数 moji に文字の入力をする。ここでも moji の前に & を付けていることに注意せよ。
13:printf 関数により、入力された文字の出力をする。出力フォーマットを %c とすることにより入力されたmojiの値を文字として出力できる。
14:printf 関数により、代入した変数a,b,c,d,dの値を出力する。これらは、文字型の変数でありデータも文字型であるため、出力フォーマットとして %c を書く。また、最後の moji の出力フォーマットを %d とすることにより(アスキーコード)が出力される。第1章でも述べたように計算機の内部では、文字も数値(アスキーコード)として格納されているため、出力ファーマットの指定により文字を数値として出力することも可能である。

***注意***

 14で述べたように、文字型の変数で数値も扱うこともできるが、分かり易いプログラムを書くためには、特別な理由がない限り文字を扱うときはchar型,数値を扱うときはint型を使うこと。

 実行結果の二つ目の例で,mojiに’7’を入力した場合,Ascii code: 55 と出力されていたが,これは,入力された’7’は文字の’7’であって数 値の7ではないためである。数値の7として入力したい場合は,ステップ1 2の入力フォーマット制御記号(%c)を%dに変更すればよい。この場合 ステップ13のprintfでは

 ここで、scanf と printf の入出力フォーマットと変数の型の関係について簡単にまとめておく。

表示形式宣言入出力フォーマットの制御記号
整数型 固定小数点表示 int %d(10進数として出力)
実数型 浮動小数点表示 float %f(実数として出力)
文字型 文字表示 char %c(文字として出力)
整数型 固定小数点表示 int %x(16進数として出力)
整数型 固定小数点表示 int %o(8進数として出力)


演習問題

プログラム3−4において入出力フォ−マット制御記号の”%d”,”%c”を変更して色々な場合について確かめよ。

わきみち

”制御記号について”

 本文中で軽く述べていますが,改行の制御記号(Control Code)はMS−DOSなどでは”%n”となるのに対し,UNIXでは”\n”,となります。これは,多くの国産マシンに”\”がないためで,ワークステーションや外国産のマシンは”¥”と同じ位置に”\”があります。Cでは”¥n”の他に,”¥”で始まる制御コードが多くあるので,使うマシンによって,きちんと使い分けてください。又,本によっては”¥”ではなく”\”となっているものもありますが,”¥”と置き換えて読むようにしてください。

 先の例題においてprintf関数では最後に全て”¥n”が付いていましたが,MS−DOSでは意味を持ちません。

 たとえば,msg.c というファイル名の以下のプログラムを考えてみます。

	#include <stdio.h>
	main()
	{
	    printf("I Love You.\n");
	}
これをコンパイルし実行してみます。

A>msg
I Love You.
                   ←1行空く
A>

 そこで,¥nのないmsg2.cという以下のプログラムを同じく実行してみます。

	#include <stdio.h>
	main()
	{
	    printf("I Love You.");
	}
A>msg2
I Love You.
A>               ←1行空かない
A>

 これはMS−DOS上の”¥n”が改行とラインフィードであるのに対し ,UNIX上の”\n”は改行の意味しか持たないためです。

 比較のために,上記の二つのプログラムをUNIX上で動かしてみます。

mickey> msg
I Love You.                 ←  ”\n”があるので改行される。
mickey>
mickey> msg2
I Love You.mickey>          ←  ”\n”がないので改行されず,
                                   プロンプトが続いて出てしまう。


 とりたてて,問題があると言うわけではないのですが,MS−DOSの実行結果では,1行空白が出ても気にしないで下さい。


CONTENTS / BACK-PAGE / NEXT-PAGE