6回目の授業


4回目の課題について

―アルゴリズム(コンピュータプログラム)は,
問題が機械的に解けるように,あらゆることを明示した,Step by Step の手順のことである。
どのStepも,散々骨を折って,詳細に説明されねばらなず,
一つとして,偶然や直観,経験や解釈,さらには想像力に委ねられてはならない。
(ポール・ホフマン, 数学の悦楽と罠―アルキメデスから計算機数学まで―, 白揚社)


―大抵の人は,学校で数学を習った苦い経験から,
数学が細部にこだわる厳しい学問であることを十分承知しているが,
あらゆる人間の営みの中で数学が一番自由で創造的であることを理解するに至る人は極めて少ない。

絶対的な厳密性は,意味のある夢を見る自由を手に入れる切符なのだ。

(ドナル・オシア, ポアンカレ予想, 新潮文庫)




第5章

配列の使用方法



 科学技術計算をする際に,ベクトルや行列を避けて通ることができないのは皆さんもご存じの通りです。

例えば,ディジタル化された音響信号はベクトルによって表されますし,2次元平面の画像信号は行列によって表されるのが自然ですので,それらの音響・画像信号といったものに対して何らかの処理を加えたい時(雑音を除去したいとか,圧縮したいとか)には,ベクトルや行列の演算をしなければなりません。

そのようなベクトルや行列によって表される数値データをプログラミング言語で取り扱うためには,配列と呼ばれるものを使用するのが便利です。


配列とは

 プログラミング言語における配列とは,同じ型の変数の集合であり,表示の仕方としては,数学におけるベクトルとほぼ同じ形式で表現されます。

よって,数学におけるベクトルをプログラミング言語で扱う場合には,配列を使用するのが便利です。

また,数学において,ベクトルのベクトル(要するに,ベクトルの集合)は,マトリクス(行列)と呼びますが,これについても配列で表現するのが便利です。


配列の型宣言

 C言語において配列を使用するためには,これまでに扱ってきた普通の変数と同様に,最初に型宣言をしておかなければなりません。

配列の型宣言は,以下のような形式で書きます。
    型名 配列名[要素数] ;        /* ベクトルを扱いたい場合 */
    型名 配列名[行数][列数] ;    /* 行列を扱いたい場合 */
例えば,int型(整数型)で要素数が3のベクトルとして,nxという配列名の配列を使いたいときは,
    int nx[3] ;
と宣言します。

また,double型(浮動小数点型)で2行3列の行列として,dxという配列名の配列を使いたいときは,
    double dx[2][3] ;
と宣言します。(このような配列を多次元配列と呼びます。)

 このように型宣言された配列は,プログラム中で
    nx[2] = 17 ;         /* 配列nxの2番目の要素に17を代入 */
    dx[1][2] = 27.8 ;    /* 多次元配列dxの1行2列目の要素に27.8を代入 */
のように書くことによって,自由に数値を代入して記憶させておくことができます。

(注意) C言語では,配列の要素番号を表す添字の値は,0から始まります。つまり上の例で言うと,
ということになります。すなわち,プログラム中で添字として書けるのは,

“宣言した次元数(行数,列数) - 1” まで

です。

プログラム中で,
    int nx[3] ;
    nx[3] = 17 ;  /* 恐怖の代入 */
のようなコードを書いた場合,コンパイルはエラーが出ずにとおります(!!!)が,配列 nx には,三つの要素(nx[0], nx[1], nx[2] まで)の分のメモリ領域しか確保されていないため,nx[3] という参照はメモリ中のどこの場所をさす結果となるのかは,プログラムが実際に走るまで全く分かりません。

運悪く,OSの使用しているメモリ領域を指してしまった場合には,17という値を代入することによってOSを書き換えてしまうことになりますので,場合によってはシステム全体がフリーズすることにもつながります。
(世の中に出回っているソフトウェアのバグは,ほとんどがこれが原因であると言われています。)

配列を使用するときには,必ず,添字の値が変化する範囲が,

0 〜 宣言した要素数(行数,列数) - 1

となっているかを,必ず,確認しましょう!



配列の使用上の注意


#印はプリプロセッサ



 プログラム中,main( ) 関数の前に,# で始まる記述を書くことがあります。

これは,“プリプロセッサ”といって,コンパイルの前処理機構のための指示文を表します。

プリプロセッサには多くの種類がありますが,代表的なものとしては,“マクロ定義”と“ファイルの取込み”の二つがあります。


ファイルを整理しよう



 たくさんプログラムを書いていると,ファイルの数がどんどん増えてくることでしょう。UNIXでは,ユーザーがログインすると,まず,そのユーザーのホームディレクトリが作業ディレクトリ(カレントディレクトリ)となりますので,皆さんが作成したプログラムは,ホームディレクトリの中にどんどん納められていきます。

 ホームディレクトリにどんどんファイルを保存していくことは,ワンルームマンションにどんどん荷物を放り込んでいくようなもので,ファイルの種類が多くなってくると,しまいに整理がつかなくなってしまいます。そうなると,後でなにかのファイルを探し出すときに,長大なファイル名のリストの中から目的のファイルを見つけなければならず,とても苦労します。

きれい好きな人は,そうなる前に,自分のホームディレクトリ(自分のロッカー)内に,新たにサブディレクトリ(自分の荷物を整理して入れる箱)を作ってきれいに整理しておきたくなることと思います。

 今回は,UNIX上でそのようなことをする場合に必要となる,ファイル操作のためのコマンドを幾つか紹介します。

なお,ディレクトリという用語は,Windowsのフォルダという用語と同じように理解してみてください。そうすると,ディレクトリの仕組みによってファイルを管理(整理)することの意味を把握することができると思います。


ファイル整理のためのUNIXの常用コマンド

pwd 現在の作業ディレクトリの名前を表示する
ls ファイルやディレクトリの名前の一覧を表示する
mkdir 新しいディレクトリを作成する

$ mkdir 新ディレクトリ名

と入力すると,新ディレクトリが作成されます。

cp ファイル(や ディレクトリ)をコピーする

$ cp 複写元ファイル名 複写先ファイル名

と入力すると,複写元ファイルの内容が,複写先ファイルにコピーされます。(複写元ファイルと同じ内容のファイルがもう一つ作られます。)

mv ファイル(や ディレクトリ)を移動する

$ mv 旧ファイル名 新ファイル名

と入力すると,旧ファイルの名前が,新ファイル名に変更されます。

$ mv 移動元ファイル名 移動先ディレクトリ名

と入力すると,移動元ファイルが,移動先ディレクトリの中に移動します。

cd 現在の作業ディレクトリを変更する

$ cd 新ディレクトリ名

と入力すると,現在の作業ディレクトリが,新ディレクトリに変更されます。

rm ファイルを削除する

$ rm ファイル名

と入力すると,指定したファイルが削除されます。これで削除したファイルは本当に消えてなくなりますので,注意して使って下さい。(MacやWindowsのゴミ箱のように後で取り出すことはできません。)

rmdir ディレクトリを削除する

$ rmdir ディレクトリ名

と入力すると,指定したディレクトリが削除されます。このコマンドも,ディレクトリが永久になくなりますので,注意して使って下さい。


 なお,UNIXコマンドの詳細は, man コマンドで調べることができます。
たとえば ls コマンドの詳細を調べるためには,以下のように入力します。

$ man ls(enter)

そうすると,ls コマンドに関するマニュアル(オンラインマニュアル)を読むことができます。

UNIXコマンドの使い方がよく分からない,あるいはもっと詳細なコマンドの使い方(オプションの与え方など)が知りたい,という人は,ぜひ,man コマンドを用いて,自分で調べてみて下さい。


作成したプログラムを専用のディレクトリにしまおう

 それでは,上に示したファイル整理のためのUNIXの常用コマンドを幾つか使って,これまでに作成したプログラムを専用のディレクトリに整理してみましょう。
  1. まずは,プログラムを納める専用の箱(ディレクトリ)を作ります。箱の名前は例えば program としましょう。

    $ mkdir program(enter)

  2. lsコマンドで program というディレクトリができているか確認してください。

    $ ls(enter)

  3. ホームディレクトリにある,プログラム関係のファイルを,新しく作った program という名前のディレクトリに入れ直しましょう。例えば,list1-8.c という名前のソースファイルを移動してみます。

    $ mv list1-8.c program(enter)

  4. lsコマンドで,現在の作業ディレクトリから list1-8.c というファイルがなくなっているか確認してください。

    $ ls(enter)

  5. cdコマンドで,現在の作業ディレクトリを新しく作った program という名前のディレクトリに変更します。

    $ cd program(enter)

  6. lsコマンドで,現在の作業ディレクトリ(program に変わっています)に list1-8.c というファイルができているか確認してください。

    $ ls(enter)

  7. もし必要ならば,cdコマンドで,現在の作業ディレクトリをホームディレクトリに直しておきます。

    $ cd ..(enter)

    cdの後の .. (ドットドット)は,どんなときでも現在の作業ディレクトリの親ディレクトリ(上の階層のディレクトリ)を表す特殊な記号です。現在の作業ディレクトリはホームディレクトリの中のprogramでしたので,.. はprogramの親ディレクトリであるホームディレクトリに置き換えられてUNIXに解釈されます。

今日の実習問題と宿題


(重要)  宿題の締切は次の授業が始まる前までとします。きちんと動作をチェックしてから,提出して下さい。


戻る