プログラミング演習U
Frequently Asked Questions (FAQ)
よく出る質問(とその答え)
演習最初の講義はあくまで導入と課題の説明のため最小限必要なものに努めており、講義で全ての内容を教えようとはしていません。むしろ演習に多くの時間が割けるよう、なるべく30分以内に抑えようとしています。よって具体的な内容、コマンドの使い方等は教科書を各自見直してください。
また、演習時間内に課題が完成していないのに計算機室から早々に引き上げていく人が多いですが、私やTAの板橋君がその時間帯にせっかくいるのですから、大いに活用してどんどん質問してなるべく演習時間内に課題完成を心掛けてください。
やはりまず教科書・参考書を読みましょう(ビギナ−編では間に合わないかもしれません)。その上でもう一度プログラム例を見直してみて理解に努めましょう。それでも分からない点があれば(xxxが分からないではなく、このxxxがここでyyyなのが分からないともう少し具体的に)質問してください。
期末テストはペーパーテストです。
期末テストは最後の週(2/3)に行なう予定です。今までカバーした内容の理解度を測ります。よってプログラムを組むことはありませんが、プログラム例のミスを指摘するぐらいのことはするかもしれません。
テキストファイル:表示できる文字のみ、バイナリファイル:表示できないデータを含む
テキストファイルが表示できるファイルに対して、バイナリファイルは任意の16進数で構成され、必ずしも表示できる文字は含まれません。また、テキストファイルは「行」で構成されていますが、バイナリファイルは「行」と言う概念がありません。テキストファイルの代表はCのソースファイルで、全て表示可能な文字で構成されていますが、これをコンパイルした実行ファイルはバイナリファイルの典型で、必ずしも表示できない16進数で構成されます。
たとえば以下のソースファイルを表示してみます。
$ cat test.c
#include <stdio.h>
void
main() {
printf("This is a test.\n");
}
これを以前にも用いた表示コマンド、od(使い方はman odとしてオンラインマニュアル参照)を使って表示してみると
$ od -t x1 -c test.c
0000000 23 69 6e 63 6c 75 64 65 20 3c 73 74 64 69 6f 2e
# i n c l u d e < s t d i o .
0000020 68 3e 0a 0a 76 6f 69 64 0a 6d 61 69 6e 28 29 20
h > \n \n v o i d \n m a i n ( )
0000040 7b 0a 09 70 72 69 6e 74 66 28 22 54 68 69 73 20
{ \n \t p r i n t f ( " T h i s
0000060 69 73 20 61 20 74 65 73 74 2e 5c 6e 22 29 3b 0a
i s a t e s t . \ n " ) ; \n
0000100 7d 0a
} \n
ここで、1行目は16進表示、2行目はその対応文字を表します。各16進数と文字との対応はASCII文字として標準が決まっています。以上のように、全て表示できる文字から構成されていることが分かります。一方、これをコンパイルした実行ファイルは
$ od -t x1 -c test_c.exe | head
0000000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00
M Z 220 \0 003 \0 \0 \0 004 \0 \0 \0 377 377 \0 \0
0000020 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
270 \0 \0 \0 \0 \0 \0 \0 @ \0 \0 \0 \0 \0 \0 \0
0000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
と、必ずしも表示できない16進数が含まれています。
なお、以上の説明でもありましたように、表示できる文字のみで構成されているファイルも基本的にはバイナリファイルの一種とみなすことが出来ます。すなわち、テキストファイルもバイナリファイルの一種であり、全てのデータが表示可能文字で構成される特殊なバイナリファイルということが出来ます。
バイナリファイルの大きさは通常バイト数で測ります。例えば
>ls –l ファイル名
でファイルの大きさを見ると、バイト数でファイルの大きさを教えてくれます。
どちらも読み出しでファイルを開くモードですが、”b”がつくとバイナリモードとなります。4. の項で述べたようにテキストファイルもバイナリファイルの一種なので、バイナリモードでも読み書きが出来ます。ただテキストモードをつけると行末の空白を自動的に取り除いてくれたり、ちょっと話が難しくなりますが、別のコンピュータから(例えばWindowsや Mac)持ってきたテキストファイルの改行コードを自動的に変換してくれたりします。
あえて”b”をつけて例題を挙げたのはWindowsではバイナリモードでないとうまくファイルが読み込めないためですが、Unixだけでプログラムする場合はつけなくてかまいません。
EOFはEnd Of Fileの意味で、例えばファイル入力関数の一部がファイルの最後まで読んでしまった場合、戻す値がEOFになります。EOFは実はstdio.hの中で、典型的には以下のように定義されています。
#define EOF (-1)
fputc, putc, fgetc, getc, fputs, fscanfなどの関数がファイル終了時にEOFを返します。他の関数はNULLを返します。どの関数がEOFを返して、どの関数がNULLを返すかは関数の仕様ですので、これらを利用する場合は必ずオンラインマニュアルかCのテキストで使い方をチェックするようにしてください。
gccでコンパイルしてください。しかし、ほとんどの場合、ccでも大丈夫なはずです。
計算機室のワークステーションで使うccはワークステーション製造元のSUN社が提供するCコンパイラで、gccはフリーソフトとしてボランティア団体が開発したコンパイラです。基本仕様は同じですが、ccは以下の特徴があります。
・ 1社で開発しているので、やや方言があります(他のコンパイラと微妙に違う仕様)。
・ 少し古くなりつつあります。(新いコンパイラを購入すれば良いわけですが)
一方、gccは以下の特徴があります。
・ 今でもボランティア団体が開発を続けているので、最新仕様のものがただで手に入ります(計算機室のものはやや古いですが)。
・ 各種の計算機用コンパイラが開発されている(各UNIX、LinuxなどのPC UNIX含む、Windows他)ので、一つの計算機用に作成したプログラムは変更なしに他の計算機用に再コンパイルすれば動作する(可能性がある)。
大文字で書く慣習になっています。
#define文は例えば
#define MAXLINE 80
と定義しておくと、コンパイラが実際実行形式に変換する前にプログラム内にMAXLINEが現れるところは”80”と数値で置き換えます。
例えば
int i = MAXLINE;
は変換前に内部で
int i = 80;
と機械的に置き換えられます。
このようにMAXLINEは変数名ではないので、変数と区別するために大文字で記述する慣習になっています。小文字でも動作しますが、変数名と区別するため大文字にする慣習に習ったほうが良いでしょう。
ちなみに#defineと同じ種類の役割をする命令に#includeがあります。
#include <ファイル名>
は実行形式に変換する前に指定したファイルをこの行の位置(通常ソースの先頭部分)に読み込んでからコンパイルします。
プログラムの実行を強制終了する関数です。
exit(i)を実行すると、プログラムの実行が終了して、int型の変数iの値がオペレーティングシステムに戻されます。return(x)文と極めて似ていますが、return文は関数を修了して、呼び出し元にあらかじめ宣言してあった型の変数xの値を戻します。
正式には必要です。
gccだとそれでも注意だけでコンパイルできてしまうので#includeなしで使ってしまいましたが、おっしゃるとおり本当は必要です。
exitの引数は任意のint型で、プログラマが任意に決定できます。通常は正常に終了時と以上終了時で別の値を返します。
ちなみにstdlib.hの中では
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
と宣言されているので、正常終了時は
exit(EXIT_SUCCESS);
異常終了時は
exit(EXIT_FAILURE);
としておくと、他の計算機に移植しやすくなります(他の計算機でもEXIT_SUCCESSなどが同じように定義されているため)。
関連のあるいろいろな型のデータをひとつにまとめて扱えることです。特に大きいプログラムで、しかも複数のプログラマが共同作業で開発している場合、データの管理が大変になり、誤りの原因となります。そこで極めて関連の深いデータや、同じものに対する異なる型のデータを一まとめにして統一的に扱えれば、データ管理がしやすくなり、バグ(プログラムエラー)も減少することが期待できます。
少し話は難しくなりますが、構造体に関数(へのポインタ)も含むことが出来ます。構造体を定義するとき、その構造体を扱う関数郡も定義しておけば、その構造体を扱う関数も管理できます。つまり構造体1を扱うときは関数郡1を用い、構造体2を扱うときは関数郡2を用いる、といった管理が出来ます。これはオブジェクト指向に発展する概念で、C言語を拡張したC++でクラスとして実現されています。
2年生後期までにフローチャートを見たことがないのは意外でした。フローチャートについて簡単にまとめた資料を用意しました。
今回は簡単なソート方法しか扱わなかったのでそれほど大きな差はありません。それでもバブルソートはとにかく隣同士しか比較、交換しないので、極めて簡単な方法ですが、効率はソート方法の中で一番悪い方法です。単純選択法はバブルよりは若干効率は良いですが、大きな差はありません。それでもソートのデータ個数が多くなるとその差は歴然としてきます。
ソート方法はデータ処理では良く用いるので、効率の良い方法が数多く提案されています。興味のある方は、大変面白く奥の深い話題ですので、アルゴリズムの本などを参照してください。
バブルソートはソート方法の中では一番簡単で分かり易い方法だと思いますので、フローチャートの見方を勉強し、第9回資料に記載されているバブルソートのフローチャートをプログラムに組んでみて、その流れをたどって理解するよう試みてください。
実はモンテカルロ法の精度は乱数の精度に大きく依存します。発生した(x, y)の組が均等に範囲内に分布してくれれば良いのですが、標準関数のrand()はそれほど精度の高い乱数を発生してくれません。よって積分値の精度もある程度までで限界がきます。これ以上の精度を目指すのであれば、乱数の精度を上げる必要があります。rand()以上の精度の乱数を発生するアルゴリズムも各種存在します。興味がある方は調べてみてください。
かなりの方が今後Fortranを使うことがあると思いますので、やはりFortranの教則本を1冊は購入して呼んでください。
簡単に説明すればFORMAT文は入出力の書式を指定するもので、ちょうどC言語の例えばprintf文の第1引数、例えば
printf(“Answer is %d\n”,k);
の“Answer is %d\n”に相当します。上記の文をFortranで書けば
WRITE(6, 600) K
600 FORMAT(‘Answer is`, I5)
となります。FORMAT分には通常文番号を付与し、入出力文でこの文番号を用いて参照します。上記FORMAT分の第2引き数が出力変数の書式を示し、上の例のI5は5桁の整数型を指定します。その他の型は第11回の資料を参照にしてください。
C言語では”%”演算子を使えば簡単に剰余が計算できましたが、Fortranにはこの演算子はありません。Fortranでは一般的に組み込み関数MODを使えば剰余を計算できます。例えば
INTEGER A, B,
C
C = MOD(A, B)
とすれば、AでBを除算した剰余がCに代入されます。あるいは
INTEGER A, B,
C
C = A - (A / B) * B
でも剰余が計算できます。これは変数AもBも整数型であるため、(A/B)は整数で行なわれ、小数点以下が切り捨てられます。これにBを乗算すると(A/B)より剰余を除いた数が得られ、これをAから減算すると剰余が得られます。検算のプログラムを組んで、試してみてください。
これはオンラインマニュアルの環境変数にFortranのオンラインマニュアルが含まれないからです。emacsを使って.cshrcファイル内のMANPATHの設定を以下のように変更してください。
変更前:
setenv MANPATH
/usr/local/man:/usr/local/share/man:/usr/share/man:/usr/dt/share/man:/usr/openwin/share/man
変更後:
setenv MANPATH
/usr/local/man:/usr/local/share/man:/usr/share/man:/usr/dt/share/man:/usr/openwin/share/man:/opt/SUNWspro/man
設定変更後、ログオンしなおしてください。以降、
man –s 3f
intro
man –s 3f rand
などでFortranのオンラインマニュアルが表示されるはずです。
大体の方の提出が終わったところでWeb上に期間限定で公開しています。定期的にチェックしてください。
期限外や再提出になるとその度に減点していきます。期限外と再提出両方になったり、再提出を期限外で提出すると2点原点になります。出題後の5週間後の締め切りまでに受け付けられないと最低点の1点になり、提出しないと0点になります。再提出のチャンスは1回限りなのでプログラムを充分に見直して提出してください。
Created on November 22, 2001
Last update on March 31, 2020