Cプログラミング入門 第3回


1.6 配列

 いままで,いろいろな名前の変数を使用してきました。例えば,nl や c などです。例えば,変数 x を int と宣言すれば,JAIST では,4バイトの メモリ領域が確保されます。こんな感じ(一つの括弧が4バイト)。
  

nc と nl と nw のときには,このように確保されます。
      

変数の名前は何でも良いのですが,数字の数を数えるなどの場合のように, 連続した性質の量(同属性の変数)を扱う場合や,行列の成分のように 本来番号がついている変数を扱う場合には,『配列』を使いましょう。 『配列』宣言は,ほとんど変数と同じです。10この成分を持つ整数配列 n[ ] を宣言するためには,

int n[10]
と書いてやるだけです。すると,メモリ領域はこのように確保されます。
                     

それぞれの領域は,
n[0] n[1] n[2] n[3] n[4] n[5] n[6] n[7] n[8] n[9]

に対応しています。int n[10] と書いた時,0 から 9 に対応することに 注意! n[3]の値を1プラスしたければ,++n[3]とすればよいのです。 (ここで[ ]の中は数字です,文字ではありません)。同様のことは,

int n1, n2, n3, n4, n5, n6, n7, n8, n9, n10,
でもできますが,かっこ悪い上に,変数の取り扱いも難しくなるので, 止めましょう。


< 問題 >
入力したテキストの中の 0から9までの数字を数える プログラムを書け

 27ページのプログラムの本質は,上のとおりです。これを解決するのに, 問題点が3つあります。

  1. プログラムの本体をどうするか?
  2. どのようにして,数字の数を数えるのか?
  3. 数字(じつは文字!)をどのようにして扱うか?
これらの答えは,既に用意されています。
  1. 行数のカウントのプログラムを利用してやれば良い。
  2. カウンターに配列を使う。数字3のカウンターをn[3]に, 数字9のカウンターをn[9]に,としてやれば良い。
  3. 数字をアスキーコードで扱おう。0は48,9は57だから,
    n['0'-48]は,n[48-48]→n[0]だし,n['9'-48]は, n[57-48]→n[9]となる。

{
配列を宣言する int ndigit[10]

カウンターndigit[i]を0にリセット;          ←for文を使う

while(とってきた文字cがEOFでないなら)ループにはいる
  もし(cが0(48)以上 かつ 9(57)以下)ならば
    カウンターndigit['c'-48]をプラス1
    ;
結果(カウンタの値)をプリントアウト         ←for文を使う
for(i=0 から; i<10 まで;i を一つづつプラス)
  printf("%d ",n[i]);
}

配列のリセットや表示には,for文を使うのが普通です。if文については すでに説明済みですね。


1.7 関数

 始めにも述べたように,Cのプログラムとは関数の集まりです。Cの関数の イメージは例えば,『いくつかの入力に対して,最高で一つの値を出力する』 というものです。
 大抵の関数は,一つか二つの入力に対して一つの値を返しますが,ときには, 何も入力がなくても値を返すもの(getchar()もそうです)や,入力があっても 何も値を返さないもの,いや「なにもない」という値を返すものと言うべきか? もあります。(後に出てくるcopy())
 このようないろいろな関数を組み合わせて,ひとつのmainという関数が 出来上がります(こんなイメージ↓)。

 関数は出来合いのものだけではなくて,自分で作ることも出来ます。ここでは それをやりましょう。


 教科書では,いきなりベキ関数を作っています。いきなりこれでは 分かるものも分からなくなります。そこで,まず

< 問題 >
整数 x と 整数 y の和を求める関数を書け。

をやりましょう。x と yを入力すると出力 z(= x+y)がかえってくる関数です。

z=f(x,y); z=x+y
こたえは,こうなります。関数の名前を waとしましょう。

int wa(int x, int y)
{
  int z;
  z=x + y;
  return z;
}
戻り値の型 関数の名前(パラメータの型 パラメータ, ...)
{
  変数 z の宣言;
  関数の本体;
  戻り値 z を返す;
}

これをmainのなかで呼び出してやると,printf ("%d \n",wa(3,2)) で 5 と いう答がでてきます。当然 wa(32,21)→53 です。

 このような関数を一度定義してしまえば,main関数の中だけでなく, 任意の関数の中で使うことが出来ます。私達は,この関数の機能 (何を入れれば何が出てくるか)だけ知っていれば,これらを ブラックボックスとして使うことが出来ます。関数どうしが独立に ブラックボックスとして扱える,これがC言語の良い所です。


 教科書に戻ります。教科書にはただ単に「関数 power とそれをテストする 主プログラムを示す。」とだけあります。これでわかれば苦労はしないので, 少し説明を加えます。

 著者は次のように考えました。

  1. まず,ベキ関数 power (int版) を作ろう。
    1. たとえば,4^3は,4×4×4=64だ。
    2. それなら power(4,3)→64 となるような関数を作ろう。
    3. その中身は,4を3回掛け合わせるようなもので良い。
    4. 一般的には, base(底)を n 回掛け合わせよう。
  2. それをmainでチェックしよう。
    1. 関数 power がうまくできてるかどうかを確かめよう。
    2. 2^0〜2^9 と (-3)^0〜 (-3)^9 を計算させてみよう。
それぞれを,プログラムにすると,教科書のようになります。まず,ベキ関数 power (int版) です。本当に power(4,3)→64 となるか,確かめて下さい。

int power(int base, int n)
{
  int i, p;
  p = 1;
  for(i = 1; i < n; ++i)
    p = p * base;
  return p ;
}
パラメータは,base と n
{
  変数の宣言
  初期値設定
  次の行を n 回繰り返す
    base を掛け合わせる。
  結果を返す(戻り値は p )
}

 次にチェックのための,main関数です。printfのところは,書式設定はしてません。
main( )
{
  int i;
  for(i = 0; i < 10; ++i)
   printf( i, power(2,i), 
    power(-3,i) );
  return 0;
}
mainはパラメータなし
{
  変数の宣言
  iを0から9まで変えて,次の行を繰り返す
   i と power(2,i) と 
    power(-3,i) を表示
  正常終了
}

今までなかったものに,return 0;があります。これは,「mainも 関数である以上,何らかの値を返すべきである」というポリシーに従った ものだと考えてもらって良いです。では,返す値として適当なものは, ということで,正常終了に対応する0を返すわけです。今までは, 省略していただけです。

 これらの関数は別々のファイルにすることも出来ますが,私達の レベルでは,一つのファイルにするのが良いでしょう。その場合は, 一般には次のように書きます。

#まずヘッダファイルの読み込み
#記号定数の定義

プロトタイプ1
プロトタイプ2
  :
  :
main( )
{        }
関数1( )
{        }
関数2( )
{        }
  :
  :

ここで「プロトタイプ」とは,Cコンパイラに対して,あらかじめこのような 関数を使用すると言うことを教える役割をします。パラメータや戻り値の型が, 実際の関数のそれと一致するように書きましょう。


33ページからの「歴史のはなし」は,知っている人には意味がありますが, 初心者には百害あって一利もありません。理解する必要はありません。

ちょっと一言
 対数関数や三角関数をCで使うためには,数学ライブラリを読み込む必要が あります。その方法は,つぎのとおり。
  1. #include<stdio.h>の次の行に,
    #include<math.h>と書く。
  2. 普通通りに(対数関数や三角関数を用いて)プログラムを書く。
  3. コンパイルの時に, -lmオプションを付けてコンパイルする。
     gcc filename -lm [return] または,
     gcc -o objectname filename -lm [return]


1.8 引数 − 値による呼出し

 ここでは,いろいろややこしいことが書いてありますが,要約すると,

ということです。でも,仮引数(パラメーター)や実引数ってなんでしょう?  上のpower関数を例にとって説明します。 引数の値の受渡しは,例えば,mainから任意の関数を呼び出す場合は, 次のようになっています。上のpowerの例で考えてみて下さい。

[流れ] [main]  [任意の関数]
 ↓  
実引数→仮引数へ受渡し
 ↓    ↓
変↓    ↓
化↓ 関数内部で計算
せ↓    ↓
ず↓    ↓
 ↓←←←←戻り値
 ↓  

関数の内部から実引数を変えることは出来ません。逆に言えば,実引数は 変化しないので,安心して任意の関数の中で計算が出来ます。

 上のプログラムを見ると,mainにもpowerにも変数 i がつかわれていますが, 両者は,全く独立です。何の関係もありません。

が,関数をブラックボックスとして使える大きな理由です。


次へ進む
C入門もくじへ
小矢野のホームページへ

このページの御感想・御意見は koyano@jaist.ac.jp まで。