AProg/2016/ex04
応用プログラミング及び実習 2016年度 第4回†
- 実習のすすめ方について AProg/2016/ex00
- Linux環境での操作についてわからないことがあったら Docs/4UNIXBeginners
- 締切に間に合わずチェックを受けられなかった課題は自分で完成させておくこと. 先の回には,過去の課題のプログラムを改造して新たなプログラムを作る課題があります. 締切後には点数はつきませんが,質問等は随時どうぞ.
課題A(self) 締切:今回の実習終了時†
ソースを分割して作成/コンパイルする方法を理解するために,次のことをやってみよう.
- 講義資料のmain01.cとhoge01.cを実際に作成し,コンパイル・リンクしてprog01という実行ファイルを作り,実行してみる
- Q1,Q2をやってみる
- main02.cを作成し,Q3をやってみる
課題B(self) 締切:今回の実習終了時†
分割コンパイルのさらなる学習のため,下記のプログラムを分割してみよう.
step1†
- 下記のプログラムをそのままコンパイルして実行.
- check 分割コンパイルと関係ないですが,最大値を求める関数に間違いがあります.
- どこが間違いか,どんな入力だと間違いが発覚するか,を考えなさい
- 間違いを修正しなさい
step2†
ソースを分割しよう.次の3つのファイルに分けること.
- ex04b.c
- ex04pimax.c
- そのほかの関数の定義を含むソースファイル
- ダウンロードしてstep1で修正した ex04b.c をコピーして編集したらはやいでしょう
- ex04pimax.h
check 元のプログラムでは,関数 pipi で必要なため,
#include <math.h>
がありました.分割した時は,この文はどこに書くのがよいでしょう? 必要ない所も含めてあちこちに書いちゃっても当然プログラムは動きますが,理解を深めるため,最小限にするならどこに書けばよいか,を考えてみてください.
&gist(178d35c2d95bc99e67c0);
課題C(TA&takataka) 締切: 後述†
- TAチェック課題としての締め切り: 今回の実習終了20分前
- takatakaチェック課題としての締め切り: 来週月曜13時まで(提出法については AProg/2016/ex00参照)
画像の画素値を格納した2次元配列を受け取り,その画像を左右反転させる処理を行う関数を紙に書きなさい.
- 関数名は flipH とすること
- 戻り値,引数などは自分で適切なものを考えること.引数の順序については,画素値反転の関数 negate と同じにすること.関数内で使わないものを引数に指定しないこと.
- 左右反転をどうやったらよいかについては,紙に具体的な1次元配列を書いて,それをどのように操作したら左右を入れ替えられるか,手順を考えましょう.forループの回り方を考えて,実際にループ1回ずつの処理を紙の上でやってみたら,間違いも発見しやすいでしょう.最終的には,実は簡単なプログラムだということがわかるかも.
課題D(TA) 締切:次回実習開始直後†
これまでの成果を組み合わせて,「画像をファイルから読み込む → 画素値反転 → 左右反転を99回繰り返し → 画像をファイルへ書き出す」という処理をするプログラムを作ろう.ただし,分割コンパイルの技を使い,次のようなファイル構成とすること.
- ex04d.c
- ex04image.c
- 次の関数たちの定義を含むソースファイル
- ex04image.h
- ex04image.c に書かれたものを使うために必要な情報を書いたヘッダファイル.次のようなものを書くことになるでしょう
- 関数のプロトタイプ宣言
- check 画像の最大サイズを表す定数 MAX_WIDTH, MAX_HEIGHT は,ex04d.c と ex04image.c の両方で使いたくなります.したがって,ex04image.h の中でこれらを #define して,ex04d.c と ex04image.c はどちらも ex04image.h をインクルードするようにすればよいでしょう.
- check readPGMHeader, readPGMBody, writePGM は,引数に FILE 構造体の変数へのポインタを指定しています.この FILE 構造体は,stdio.h の中で定義されています.したがって,プロトタイプ宣言を置くところで stdio.h をインクルードしておく必要があります.そうすると,ex04image.h の中で stdio.h をインクルードしておくのが楽かもしれません.
- 以上のことから,ex04image.h は次のような内容になるでしょう → 本当にみます?
check 関数 readPGMHeader で isspace という関数を,関数 getnum で isdigit という関数を使っており,これらの関数のために ctype.h というヘッダファイルが必要です.ということは,AProg/2016/ex03#kadaiD のプログラム中の
#include <ctype.h>
と同じものを ex04image.c の中に書かないといけませんね.
課題S(おまけ) 締切: 次回実習終了まで†
簡単なアニメーション(もどき)を作ってみよう
- ex04image.c に,次のような関数を追加する
- 関数名 shiftH
- 引数で渡された画像を右に1画素ずらす.ただし,右からはみ出た画素は左端に入れる
- 画像を読み込んだあと,shiftH を呼んではファイルに書き出すことを一定回数(画像の幅の分とか)繰り返すプログラムを作成する
- ファイル名は,hoge000.pgm, hoge001.pgm, hoge002.pgm ... のように,「同じ文字列 + 同じ桁数で1ずつ増えていく数 + 拡張子」としておこう(もちろんPPMの方で作っても可)
- display コマンドでお馴染みの ImageMagick という画像処理ツール群に,animate というコマンドがあり,コマンドライン引数で指定されたファイルをパラパラ漫画にして表示してくれます.上記のファイル名の例では,
$ animate hoge*.pgm または hoge???.pgm
とすればおけ.画像のウィンドウをクリックしてメニューを選択すると,切り替えスピードを調節したりもできます.
ここからは課題の要件ではありませんが,もっと遊びたい人向けのアイデア
- shiftH を,「1画素右にずらす」ではなく,「引数で指定された画素分(負なら左へ)ずらす」にする
- shift という関数として,横縦それぞれの平行移動量を引数で指定するようにする.これで斜め移動も可能に