予習と復習

言い訳を並べればキリがないのだが、ついにプログラミングの勉強を放り投げだしてしまった。
プログラミングをしよう!→それにはまずUNIXを導入してからかな?→
→インストールがわからない→ネットで調べてみよう→面白い記事が一杯!
上記の流れを経て、すっかりC言語に触れなくなってしまったのだ。

と、いうことでこうしてブログに投稿することでCの復習と予習をしてみようと思う。





思う……のだが、ちょっとばかり問題が起こってしまった。
復習&予習というのは、僕が大学で受けているプログラミング授業の予復習のことなのだが、
そもそもにおいてその授業お進行予定が当初のそれと大幅に変わっているようなのだ。
というか、前回なんの前触れも無しにファイル入出力を指示された時は軽くパニックになった。
精々ポインタと再帰関数くらいまでなら頭に入ってはいるが、
ファイル入出力に関してはは見たことすらなかったのだ。
シラバス(授業予定)では、前回の授業は配列の予定になっていたはずなのだが……
(おかげで油断していたというのもある)
マクロ定義(#define)やプリプロセッサ程度のことならまだしも、
唐突に出てきたポインタ演算子は多くの生徒が理解していないのではないだろうか。
むしろ僕自身があまりよく理解していない。



まぁともかく復習だ。
前回の情報処理演習(プログラミングの授業)でやった内容はこうだ。

「階乗を計算するプログラムを作成せよ」
三角関数表を表示するプログラムを作成せよ」
「既成プログラムを用いて三角関数表をdatファイルに出力するプログラムを作成せよ」

この三つだ。
階乗計算は提出義務がないので別に無視しても構わなかったのだが、一応書いた。
基本的には授業開始時に配られるプリントに書いてあるソースコードを写してしまえば
プログラムは十分出来上がり、動作も問題ないので大した内容ではない。
(恐らく意図的に一部ミスが仕込まれていたが、修正は容易だった)

が、問題点が二つあった。
それは「gnuplotを用いたグラフ表示」と……やはりというかなんというか「ファイル入出力」だ。


問題その1「gnuplotの値域がおかしい」
とりあえず三角関数表をプログラム実行により作成することはできた。
この後は授業でなされる指示に従いグラフを作成するだけ……というところで、起こった。
三角関数のグラフであるから当然値域は -1 < y < 1 となるはずだ。
ところが実際作成されたグラフは 0 < y < 1 の値域しか持たなかった。
当然グラフの見た目が変わってくる。
(それでも数値自体は合っているからグラフとしては正しいのだが)
一人で悩んでいても埒があかなかったのでTA(ティーチングアシスタント)に質問した。
だがTAの方も問題とその解決法を把握していなかったらしい。
TAは院生の人達が生徒の質問に答える役割なので、gnuplotという如何にもマイナーそうな代物の扱いについてはそうなるのも致し方ないとは言えるだろう。
TAに質問をしても解決が得られなかったので、困った時のgoogle先生に聞いてみた。
即座にgnuplotのマニュアルサイトが見つかったのでそこに載っている方法を試したが……何故かやはりこれでも上手くいかない。
一体どうしたことかとTAと二人で首を捻りながら試行錯誤する内に、突然またもや何故か成功した。成功した理由はわからないが、一旦gnuplotを終了して再起動させたのが良かったのかもしれない。
とりあえずこれで一つ目の問題はことなきを得た。


問題その2「ファイル入出力がよくわからない」
これは単純な話、使い慣れないからどうやったらいいのかよくわからなかったのだ。
FILE *f が何を意味し、fopen・fprintf・fcloseをどう使ったらいいのか説明があまりにも少なかった。入力に用いるファイル名と、出力に用いるファイル名が同じだったのが尚更悪かった。拡張子の違いはあるものの、どれがopenでどれがcloseなのかはさっぱりだった。
なんどかエラーを出していく内に少しずつわずかにではあるが把握できるようになったという具合だ。
これについてもまぁ、授業の時間内にコードと取っ組み合いをして解決できた。


さて、これで前回の授業中に生じた二つの問題点について説明ができたわけであるが、後者については今後の予習も兼ねてもう少し書いておきたいので、一応曖昧な知識ながら現時点で把握もとい推測していることを書こう。



FILE *f; (ファイルポインタ作成。FILE型構造体へのポインタ)

この1行の意味は横に書いてある通りだ。実際授業プリントにもそう書いてある。
だが、ファイルポインタとは何か? ファイルとはどのファイルのことか? については何も触れられていない。そしてファイルポインタが他のポインタとどう違うのかは僕もまだ理解していない。
問題なのはこの1行を書いたソースコードの名前が"f.c"であり、その"f.c"をコンパイルして作られたプログラムを実行した時に得られるファイルの名前もf(正確には"f.dat")であることだ。
どちらの"f"であるのか? 
……まぁ本当なら考えなくてもすぐわかることなのだろう。一応ポインタの項目については一度なりとも一通り目を通した身であるのなら尚更だ。
前回に投稿した記事のリンク「プログラミングスレまとめ in vip」によれば
「ポインタとは、アドレスを入れるための変数である」
「アドレスとは、変数の住所のことである」
と執拗に三度に渡って書いてある。残念ながら、僕にとっては三度読んでもなかなか理解しづらかったというのが正直な所だ。
ともかく、この1行は"f"というファイルの住所入れる変数を確保している……らしい。
それさえわかれば問題ない。既にこのソースコード(拡張子が".c"の"f.c"というファイル)はこの時点
、ソースを書いている段階でアドレス(住所)が確保されている。そうでなければそもそも僕がソースを書くべき対象のファイルが存在しないからだ。
(正確にはきちんとファイルを保存するまでは未確定なのかもしれないが)
となれば、この1行で確保される"f"の住所というのは"f.dat"に他ならない。

要するにこの1行の意味はこうだ。
「(これから"f.dat"というファイルを作りますので)"f"を作る場所を確保して下さいねー」
恐らく、という言葉をつけざるをえないがこんなところだろう。


f=fopen("f.dat","w"); (ファイル名f.datのファイルを指定したモードで開く)

プリントによる説明文にはさらに「正しくオープンされるとファイルポインタが返される」とあった。ポインタが返される? 返すというのは返り値のことだろうか?
とりあえず、これにより先程用意された"*f"の"f"に"f.dat"ファイルが開かれた。これでファイルに書き込む準備がなされたということだろう。となるとこの行の時点で"f.dat"ファイルが作成されているのかもしれない。確認の仕方はわからないが……
初見で勘違いをしていたが、プログラミングにおける=記号はあくまで代入記号だった。
ということは"f"というファイル(変数?)にfopenしたものを代入する……と読むのか。(?)


fprintf(f,"~~(変換指定文字 ; %dとか)",(変数名 ; sinxとか) ); (ファイルに書き込む)

先程の行でファイルの開き方にモードの指定があるのだからわざわざprintfとしなくてもいいのではないか? と思うのだがそれには僕の知らない理由があるのだろうということにしておく。
普段のprintfの前にfが一文字くっついて、更に「どこにある」「何を」書くのかに付け加えて「何処へ」書くのかも加わった。
(変換指定文字の前にある"f"のこと。ファイルを開いた(fopen)時に代入される側のファイル(変数?)。本来なら"function"などといったファイル名が入る)


fclose(f); (fopenで開いたポインタ"f"が示すファイルを閉じる)

fopenの行で開かれたファイルを閉じる行であろう。どうして開けたままではいけないのか? を考えてはいけないものらしい。そもそもポインタを開くってどういうことなのだろうか。ファイルを開くわけではないのか?
僕はこの行に、fopenで書き込む相手側であるdatファイルの名前を書いてしまった。だが、それでは間違いであるようだ。どのファイルをオープンしているのか勘違いしていたのが原因だろう。

要するに

FILE *example;
example=fopen("test.dat","w");
fprintf(example," %f %f ", x );

とあった時、(途中にある余分な行は省いてある)次に来るはずのfcloseの行を間違えて

fclose(test);

と、してしまったのだ。これでは間違いである。恐らくこの間違いはポインタへの理解が足りてないことから生じてるのではないかと僕は勝手に考えている。本来fcloseで書かれるべきは、

fclose(example);

である。これはfopenやfcloseというのが最初に用意されたexampleポインタに作用するワードだからだろう……と思っている。&や*も無しにポインタを扱われるついていけないのだが、真実はまだはっきりとしていないからなんともいえない。

と、ざっと前回の授業で一番の問題点だと感じた部分についてまとめて思ったことをずらずらと並べてはみたのだが……問題なのは、疑問点がはっきりとしていないことである。
こうではないか? と考えることは出来てもそれを上手く他人に伝えられそうにない。
実際、今日のこの記事は最高に駄文と成り下がっているだろう。
今度の授業でTAに聞こうにも聞けず、結局分からないものが分からないままとなってしまう。
勉強の姿勢としては最悪だ。だが、どうしていいのかわからないのも事実だ。

とりあえず、次回の授業はあまりシラバスや進捗状況からぶっ飛んだ内容でないのを祈ろう。

書き始めたら思いの外長くなってしまったため予習まで手が回らなかった。
このまま関数のポインタ利用とか手続きに突入したらお手上げになるかもしれない……
プログラミング授業の先が不安でしょうがない。