#author("2017-10-09T09:56:09+09:00","default:takataka","takataka")
*応用プログラミング及び実習 2017年度 第4回 [#bebe2b15]

//&color(#ff0000){工事中};
 
#contents


**注意 [#o3f5d008]

- 実習のすすめ方について [[AProg/2017/ex00]]
- Linux環境での操作についてわからないことがあったら [[Docs/4UNIXBeginners]]
- &color(red){締切に間に合わずチェックを受けられなかった課題は自分で完成させておくこと.}; 先の回には,過去の課題のプログラムを改造して新たなプログラムを作る課題があります. 締切後には点数はつきませんが,質問等は随時どうぞ.

**課題A(self) 締切:今回の実習終了時 [#kadaiA]


ソースを分割して作成/コンパイルする方法を理解するために,次のことをやってみよう.

+講義資料のmain01.cとhoge01.cを実際に作成し,コンパイル・リンクしてprog01という実行ファイルを作り,実行してみる
+Q1,Q2をやってみる
+main02.cを作成し,Q3をやってみる
//+hoge01.cに次のような関数の定義を追加して,main02.cでhogeとともにその関数も呼び出すようにしてみよう
//--関数名は自分で決める
//--引数はint型のもの1つ
//--戻り値はint型,引数の値を用いた適当な計算結果を返す

**課題B(self) 締切:今回の実習終了時 [#kadaiB]

分割コンパイルのさらなる学習のため,下記のプログラムを分割してみよう.

***step1 [#cf4d1c43]

- 下記のプログラムをそのままコンパイルして実行.
- &color(white,blue){check}; 分割コンパイルと関係ないですが,最大値を求める関数に間違いがあります.
-- どこが間違いか,どんな入力だと間違いが発覚するか,を考えなさい
-- 間違いを修正しなさい

***step2 [#r63bc926]

ソースを分割しよう.次の3つのファイルに分けること.
:ex04b.c|
--関数 main の定義を含むソースファイル
:ex04pimax.c|
--そのほかの関数の定義を含むソースファイル
--ダウンロードしてstep1で修正した ex04b.c をコピーして編集したらはやいでしょう
:ex04pimax.h|
--ヘッダファイル.次のようにしよう
#pre{{
#ifndef EX04PIMAX_H  // 複数回インクルードされたときのエラーを避けるための処置
#define EX04PIMAX_H  // #ifndef の相方は↓にあり.詳しくは講義資料参照

ここに必要なものを書く

#endif  // ifndef の終わり
}}

&color(white,blue){check}; 元のプログラムでは,関数 pipi で必要なため,
 #include <math.h>
がありました.分割した時は,この文はどこに書くのがよいでしょう? 必要ない所も含めてあちこちに書いちゃっても当然プログラムは動きますが,理解を深めるため,最小限にするならどこに書けばよいか,を考えてみてください.

&gist(178d35c2d95bc99e67c0);

**課題C(TA&takataka) 締切: 後述  [#kadaiC]

- TAチェック課題としての締め切り: 今回の実習終了20分前
- takatakaチェック課題としての締め切り: 来週月曜13時まで(提出法については [[AProg/2017/ex00]]参照)


画像の画素値を格納した2次元配列を受け取り,その画像を上下反転させる処理を行う関数を紙に書きなさい.
- 関数名は flipV とすること
- 戻り値,引数などは自分で適切なものを考えること.引数の順序については,画素値反転の関数 negate と同じにすること.関数内で使わないものを引数に指定しないこと.
- 上下反転をどうやったらよいかについては,紙に具体的な1次元配列を書いて,それをどのように操作したら前後の値を入れ替えられるか,手順を考えましょう.forループの回り方を考えて,実際にループ1回ずつの処理を紙の上でやってみたら,間違いも発見しやすいでしょう.最終的には,実は簡単なプログラムだということがわかるかも.
**課題D(TA) 締切:次回実習開始直後 [#kadaiD]

これまでの成果を組み合わせて,「画像をファイルから読み込む → 「画素値反転して上下反転する」を101回繰り返す → 画像をファイルへ書き出す」という処理をするプログラムを作ろう.ただし,分割コンパイルの技を使い,次のようなファイル構成とすること.

:ex04d.c|
-- 関数 main のみを含むソースファイル.
-- 適当な場所で,ex04image.c で定義された関数を呼び出す
-- [[AProg/2017/ex03#kadaiD]] のプログラムをコピーして修正したら楽でしょう
:ex04image.c| 次の関数たちの定義を含むソースファイル
-- readPGMHeader  ( [[AProg/2017/ex03#kadaiB]] )
-- readPGMBody ( [[AProg/2017/ex03#kadaiC]] )
-- writePGM ( [[AProg/2017/ex03#kadaiC]] )
-- negate ( [[AProg/2017/ex02#kadaiC]] )
-- flipV  ( [[AProg/2017/ex04#kadaiC]] )
-- こちらも [[AProg/2017/ex03#kadaiD]] のプログラムをコピーして修正したら楽でしょう
:ex04image.h| ex04image.c に書かれたものを使うために必要な情報を書いたヘッダファイル.次のようなものを書くことになるでしょう
-- 関数のプロトタイプ宣言
-- &color(white,blue){check}; 画像の最大サイズを表す定数 MAX_WIDTH, MAX_HEIGHT は,ex04d.c と ex04image.c の両方で使いたくなります.したがって,ex04image.h の中でこれらを #define して,ex04d.c と ex04image.c はどちらも ex04image.h をインクルードするようにすればよいでしょう.
-- &color(white,blue){check}; readPGMHeader, readPGMBody, writePGM は,引数に FILE 構造体の変数へのポインタを指定しています.この FILE 構造体は,stdio.h の中で定義されています.したがって,プロトタイプ宣言を置くところで stdio.h をインクルードしておく必要があります.そうすると,ex04image.h の中で stdio.h をインクルードしておくのが楽かもしれません.
-- 以上のことから,ex04image.h は次のような内容になるでしょう → [[本当にみます?>https://gist.github.com/takatakamanbou/28b7432af05f0f6ee019]]

&color(white,blue){check}; 関数 readPGMHeader で isspace という関数を,関数 getnum で isdigit という関数を使っており,これらの関数のために ctype.h というヘッダファイルが必要です.ということは,[[AProg/2017/ex03#kadaiD]] のプログラム中の
 #include <ctype.h>
と同じものを &color(white){ ex04image};.c の中に書かないといけませんね.
 


**課題S(おまけ) 締切: 次回実習終了まで [#kadaiS]

//&color(#ff0000){工事中};

&color(blue){簡単なアニメーション(もどき)を作ってみよう};

+ ex04image.c に,次のような関数を追加する(もちろんPPMの方で作っても可)
-- 関数名 shiftH
-- 引数で渡された画像を右に1画素ずらす.ただし,右からはみ出た画素は左端に入れる
+ 画像を読み込んだあと,shiftH を呼んではファイルに書き出すことを一定回数(画像の幅の分とか)繰り返すプログラムを作成する
-- ファイル名は,hoge000.pgm, hoge001.pgm, hoge002.pgm ... のように,「同じ文字列 + 同じ桁数で1ずつ増えていく数 + 拡張子」としておこう
+ display コマンドでお馴染みの ImageMagick という画像処理ツール群に,animate というコマンドがあり,コマンドライン引数で指定されたファイルをパラパラ漫画にして表示してくれます.上記のファイル名の例では,
 $ animate hoge*.pgm   または   hoge???.pgm
とすればおけ.画像のウィンドウをクリックしてメニューを選択すると,切り替えスピードを調節したりもできます.

ここからは課題の要件ではありませんが,もっと遊びたい人向けのアイデア
- shiftH を,「1画素右にずらす」ではなく,「引数で指定された画素分(負なら左へ)ずらす」にする
- shift という関数として,横縦それぞれの平行移動量を引数で指定するようにする.これで斜め移動も可能に


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS