プログラミング入門 第12回講義 2次元配列の復習と応用 2次元配列の復習(2) 標準入出力・エラー出力(5) リダイレクト(8)

Slides:



Advertisements
Similar presentations
1 繰り返し処理 while 文 と do 文 所定回反復(特定回数の繰り返し)には for 文を用いた while( 式 ) 文 式が真であるかぎり、文を繰り返し実行する 繰り返す回数が不定の場合に用いる 繰り返し回数が明示的に決まらない場合には while 文、 do 文を用いる ある手順を、例えば.
Advertisements

配列の宣言 配列要素の初期値 配列の上限 メモリ領域 多次元配列 配列の応用
初年次セミナー 第8回 データの入力.
プログラミング入門2 第4回 配列 for文 変数宣言 初期化
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
第13回構造体.
ファーストイヤー・セミナーⅡ 第8回 データの入力.
配列(2) 第10回[平成15年6月26日(木)]:PN03-10.ppt 今日の内容 1 素数を求める(教科書の例):復習
第12回構造体.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
画像ファイル(ppm)の読み書き 画像データ用のメモリ確保・解放
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
問題提起その 1 一文字ずつ文字(数字)を読み込み、それぞれの文字が何回入力されたかを数えて出力するプログラム。
プログラミング入門 第5回講義 第5回講義 制御の流れ(1) ループ(その1) - while - インデント(3) ループとは(7)
第13回 プログラミングⅡ 第13回
第8回 プログラミングⅡ 第8回
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
第6章 2重ループ&配列 2重ループと配列をやります.
精密工学科プログラミング基礎 第9回資料 (12/11 実施)
画像ファイル(ppm)の読み書き 画像データ用のメモリ確保・解放
2014/05/02 知的画像処理研究室 M1 中津美冴 画像情報処理1 ~画像処理プログラミング~ 2014/05/02 知的画像処理研究室 M1 中津美冴
精密工学科プログラミング基礎Ⅱ 第3回資料 今回の授業で習得してほしいこと: 2次元配列の使い方 (前回の1次元配列の復習もします.)
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
C言語講座 第3回 ポインタ、配列.
プログラミング 2 ファイル処理.
プログラミング論 ファイル入出力
東京工科大学 コンピュータサイエンス学部 担当 亀田弘之
関数と配列とポインタ 1次元配列 2次元配列 配列を使って結果を返す 演習問題
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第2回 ファイル処理 情報・知能工学系 山本一公
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
プログラミング序論 2. n人のインディアン.
アルゴリズムとデータ構造 補足資料5-2 「サンプルプログラムsetop.c」
indentについて forやifの「中身」を右に寄せる. forやifの「外枠」は右に寄せない. int x; x = 3;
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
岩村雅一 知能情報工学演習I 第10回(後半第4回) 岩村雅一
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング論 ファイル入出力
デジタル画像とC言語.
UNIX演習 情報ネットワーク特論.
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
プログラムの制御構造 配列・繰り返し.
精密工学科プログラミング基礎Ⅱ 第4回資料 今回の授業で習得してほしいこと: 文字列の扱い ファイル入出力の方法 コマンドライン引数の使い方
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
東京工科大学 コンピュータサイエンス学部 担当 亀田弘之
プログラミング序論演習.
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
東京工科大学 コンピュータサイエンス学部 担当 亀田弘之
プログラミング入門2 第13回、14回 総合演習 情報工学科 篠埜 功.
復習 Cにおけるループからの脱出と制御 break ループを強制終了する.if文と組み合わせて利用するのが一般的. continue
プログラミング入門2 第5回 配列 for文 変数宣言 初期化
東京工科大学 コンピュータサイエンス学部 担当 亀田弘之
アルゴリズムとデータ構造 補足資料6-1 「サンプルプログラムcat1.c」
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
2005年度 データ構造とアルゴリズム 第2回 「C言語の復習:配列」
コンピュータープログラミング (C言語)(10) 1.ファイル入出力
プログラミング入門2 第5回 配列 変数宣言、初期化について
第4回 配列.
第2章 数値の入力と変数 scanfと変数をやります.
岩村雅一 知能情報工学演習I 第13回(後半第7回) 岩村雅一
第5回 配列.
プログラミング演習I 補講用課題
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
= 55 課題6-1 #define _CRT_SECURE_NO_WARNINGS
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

プログラミング入門 第12回講義 2次元配列の復習と応用 2次元配列の復習(2) 標準入出力・エラー出力(5) リダイレクト(8) パイプ(12) 2次元配列の応用(画像処理)(14)   マークのあるサンプルプログラムは /home/course/prog0/public_html/2013/lec/source/ 下に置いてありますから、各自自分のディレクトリに コピーして、コンパイル・実行してみてください

2次元配列の宣言と構造 int data[3][5]; 全体は配列 data [0][0] [1][0] [2][0] [0][1] 3行5列の int型 2次元配列 int data[3][5]; 列添字は0から 列数-1まで 全体は配列 data [0][0] [1][0] [2][0] [0][1] [1][1] [2][1] [0][2] [1][2] [2][2] [0][3] [1][3] [2][3] [0][4] [1][4] [2][4] 一つずつを「要素」と言う data[行添字][列添字] 行添字は0から 行数-1まで 2

マクロを利用した 2次元配列の宣言と初期化 マクロを利用した二次元配列宣言例 #define GYOU 3 #define RETSU 5 マクロ名 マクロの値 #define GYOU 3 #define RETSU 5 int data[GYOU][RETSU] = {{1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7}}; 行サイズを省略可能 (初期化データ の個数で判断) 列優先で初期化 3

2次元配列要素の入出力 #include <stdio.h> #define GYOU 3 #define RETSU 5    2次元配列要素の入出力 #include <stdio.h> #define GYOU 3 #define RETSU 5 main(){ int data[GYOU][RETSU], i, j; for(i = 0; i < GYOU; i++){ for(j = 0; j < RETSU; j++){ scanf("%d", &data[i][j]); } printf("%d ", data[i][j]); printf("\n"); std1dc1{s1000000}1: ./a.out 0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 std1dc1{s1000000}2: /home/course/prog0/public_html/2013/lec/source/lec12-1.c 4

標準入出力 C scanf(),printf()は、それぞれ標準入力ファイル(キーボード)、標準出力ファイル(ディスプレイ)への出力に対応 標準出力 ファイル 標準入力ファイル  プログラム C 標準エラー出力 ファイル lec12-6 参照

標準エラー出力(p.47,349) 標準出力とは 別に 出力したい fprintf(stderr,"書式",変数リスト); 標準出力とは 別に 出力したい 出力をリダイレクトやパイプする場合に、エラーメッセージを標準出力に出力していると、エラーメッセージも画面に表示されず、リダイレクトやパイプの対象になってしまう。 このためエラー出力用の標準ファイルを別に設け(標準エラー出力と呼ぶ)、リダイレクト・パイプの場合も画面にエラーメッセージを表示するようにしている。標準エラー出力への出力は以下のようにして行う 1 fprintf(stderr,"書式",変数リスト); 例:fprintf(stderr,"入力した値がおかしい\n");

プログラム内の標準入出力と標準エラー (p.47) この中で定義 #include <stdio.h> main() { scanf( … ); … printf( … ); fprintf(stderr ,…); } 標準入力から入力 標準出力ヘ出力 標準エラーヘ出力 2

標準入出力とリダイレクション (p.365) リダイレクションとは リダイレクションの例 標準入出力ファイルの 切り替え  をプログラムの外で行う機能 リダイレクションの例 キーボード入力 → テキストファイル入力に変更 (予めデータを格納しておいたテキストファイルを入力として使用する) ディスプレイ表示 → テキストファイル出力に変更 (出力結果をテキストファイルに保存して後からでも見れるようにする) 3

標準入出力のリダイレクションの書式 実行ファイル名 < 入力ファイル名 実行ファイル名 > 出力ファイル名 実行ファイル名 < 入力ファイル名 例: プログラム ./a.out の標準入力を test.dat から読み込む ./a.out < test.dat 実行ファイル名 > 出力ファイル名 実行ファイル名 >> 出力ファイル名 4 例: ./a.out の標準出力を test.dat に書き込む ./a.out > test.dat ./a.out >> test.dat 先頭から 書込(上書き) 末尾に 追記書き

リダイレクションの例(1) 例1. ファイル一覧をファイルlist.txtに書込む 例2. list.txtの行数、単語数、文字数を表示する ls > list.txt 例2. list.txtの行数、単語数、文字数を表示する wc < list.txt 例3. list.txtから 文字列「Aizu」を含む行 だけ     file.txtに書き込む grep Aizu < list.txt > file.txt 5 入力ファイル 出力ファイル

リダイレクションの例(2) リダイレクションでファイル中のデータの平均を計算する std1dc1{s1000000}1: ./a.out   リダイレクションの例(2) リダイレクションでファイル中のデータの平均を計算する std1dc1{s1000000}1: ./a.out 1 2 3 4 5 2 3 4 5 6 Control+d(コントロールキーとDキーを同時に押す) Average = 3.500000 std1dc1{s1000000}2: ./a.out < lec12-2.data std1dc1{s1000000}3: cat lec12-2.data std1dc1{s1000000}4: #include <stdio.h> #include <stdlib.h> main() { int i, data, result, sum = 0; for(i = 0;; i++){ result = scanf("%d",&data); if (result == EOF) break; if (result != 1) exit(1); sum += data; } printf("Average = %f\n",(double)sum/i); Control+dは入力の終わりを示す /home/course/prog0/public_html/2013/lec/source/lec12-2.c

標準入出力とパイプ(p.21) パイプとは パイプの例 二つのプログラムの標準出力と標準入力を 結合 する機能。コマンド間に「|」を挟む 二つのプログラムの標準出力と標準入力を 結合 する機能。コマンド間に「|」を挟む パイプの例 cat lec12-2.c | grep result catの出力が、grepの入力となる 6 lec12-2.c中の単語 「result」がある行を全て表示する パイプ catコマンド grepコマンド ファイル 出力処理 標準出力 標準入力 ファイル 入力処理

パイプの例 例1. ディレクトリ内のファイルをファイル容量の大きい順に表示 例2. そのディレクトリ内のファイルの数を数える ls -l | sort -k 4,4 -nr 例2. そのディレクトリ内のファイルの数を数える ls | wc -l 例3. result.txt(IDと点数のペアデータ) から 得点の高い順に 10人表示する cat result.txt | sort -k 2,2 -nr | head -10 7

2次元配列の応用 (簡単な画像処理) 画像を標準入力から入力 入力された画像を処理(例えば左に90度回転) 画像を標準出力に出力 エラー情報は 標準エラー出力 に表示 8 画像処理 標準 入力 標準 出力 標準エラー出力 エラー

簡単な画像形式 Plain PBM(Portable Bitmap)形式 Plain PBM形式は画像を保存する形式で、displayコマンド等で画像として表示できますが、テキストファイルなので、0/1のデータをそのままテキストとして目で見ることも出来ます 横(x)軸 原点 縦(y)軸 白黒2値画像 必ず「P1」(magic number) 横x×縦yドットの白黒2値画像をデジタルデータとして表現  1:黒  0:白 (左上から横に) 画像の大きさ:横xドット、縦yドット  (この場合は横320×縦160) P1 320 160 0 0 0 0 1 0 1 0 ..... 1 1 0 0 0 1 0 0 1 1 0 1 1 0 1 ..... 0 0 1 0 1 0 1 ..... PBM形式白黒2値画像データ(テキストファイル) y列 1行のデータ数はx個 今回のプログラムでは、データ部分を 2次元配列に格納する。

データ入力部分(共通部分) 取り扱える画像の最大の大きさ (縦、横) 画素データ 読み込み #include <stdio.h>   データ入力部分(共通部分) 最初に「P1」と書いていないものは、データ形式が違う この部分はプログラミング入門では扱わない文字型を使用しているので、今のところは呪文だと思っておいてください (詳しくはp.67,p.139参照) 画像用二次元配列 #include <stdio.h> #include <stdlib.h> #define MAX_X 800 #define MAX_Y 800 #define BLACK 1 #define WHITE 0 main(){ int img_data[MAX_Y][MAX_X]; int i, j, x_size, y_size;   if (getchar() != 'P' || getchar() != '1'){ fprintf(stderr, "データの形式が違います\n"); exit(1); } scanf("%d", &x_size); scanf("%d", &y_size); if (x_size > MAX_X || y_size > MAX_Y){ fprintf(stderr, "データが大きすぎます\n"); exit(2); for (i = 0; i < y_size; i++){ for (j = 0; j < x_size; j++){ if(scanf("%d",&img_data[i][j]) != 1){        fprintf(stderr, "データ入力に異常があります\n");        exit(3); if(img_data[i][j] != WHITE && img_data[i][j] != BLACK){ fprintf(stderr, "データが異常でした\n"); exit(4); x,yそれぞれの画素数を得る 取り扱える画像の最大の大きさ (縦、横) 画素数が多すぎる場合 エラーメッセージは全て標準エラー出力へ scanf入力データがおかしいか 個数より早くEOFになった場合 データが白黒ではない場合 画素データ 読み込み 各エラーコードに対応したサンプルデータが /home/course/prog0/public_html/2013/lec/source/lec12-err{1,2,3a,3b,4}.pbm にあるので試してみるとよい

左90度回転出力 m個 n個 n個 m個 左90度 データ 出力   左90度回転出力 最初にP1と画素数を出力 左90度 m個 printf("P1\n"); printf("%d %d\n", y_size, x_size); for (i = 0; i < x_size; i++){ for (j = 0; j < y_size; j++){ printf("%d ",img_data[j][x_size-1-i]); } printf("\n"); (x_size) 縦横反転するので y,xの順となる [0][0] [0][1] [0][m-2] [0][m-1] [1][0] [1][1] [1][m-1] データ 出力 [2][0] [2][m-1] n個 [3][0] [3][m-1] 1行分終了で改行 (y_size) 左90度回転 [n-1][0] [n-1][1] [n-1][m-2] [n-1][m-1] n個 (y_size) [0][m-1] [1][m-1] [n-2][m-1] [n-1][m-1] [0][m-2] [1][m-2] [n-1][m-2] [0][m-3] [n-1][m-3] m個 [0][m-4] [n-1][m-4] (x_size) /home/course/prog0/public_html/2013/lec/source/lec12-rl.c [0][0] [1][0] [n-2][0] [n-1][0]

実行ファイルにrotlと言う名前を付ける 実行結果 元データの表示 実行ファイルにrotlと言う名前を付ける std1dc1{s1000000}1: display lec12-1.pbm & std1dc1{s1000000}2: gcc lec12-rl.c -o rotl std1dc1{s1000000}3: ./rotl < lec12-1.pbm | display & std1dc1{s1000000}4: 元画像ファイルを リダイレクトで入力 元画像 結果をdisplay コマンドにパイプ

  白黒反転プログラム 最初にP1とx,yの画素数を出力 printf("P1\n"); printf("%d %d\n", x_size, y_size); for (i = 0; i < y_size; i++){ for (j = 0; j < x_size; j++){ if(img_data[i][j] == BLACK) printf("%d ",WHITE); else printf("%d ",BLACK); } printf("\n"); データ 出力 黒なら白を出力 白なら黒を出力 /home/course/prog0/public_html/2013/lec/source/lec12-iv.c その他以下のプログラムソースがある(注:演習問題の関係で、公開していないものがあります) 右90度回転 左右反転 上下反転 辺縁検出 /home/course/prog0/public_html/2013/lec/source/lec12-rr.c /home/course/prog0/public_html/2013/lec/source/lec12-lr.c /home/course/prog0/public_html/2013/lec/source/lec12-ud.c /home/course/prog0/public_html/2013/lec/source/lec12-eg.c

実行結果 std1dc1{s1000000}1: gcc lec12-iv.c -o invrt 左90度回転の後 白黒反転 std1dc1{s1000000}1: gcc lec12-iv.c -o invrt std1dc1{s1000000}2: ./rotl < lec12-1.pbm | ./invrt | display & std1dc1{s1000000}3: このようにパイプで処理をどんどん繋いで行く事が出来る ファイルからリダイレクト 元画像

ノイズ除去 意味のある画像だと、ぽつんと点があることはあまりない そこで、ある点を見た時 自分が黒点で、両隣の点が白い場合 自分が白点で、両隣の点が黒い場合 は「ノイズ=雑音(この場合は画像中のゴミ)」と認識して 両隣の色で置き換えることにする。 つまり: 例えば以下のような感じで画像が改善される

ノイズ除去プログラム /home/course/prog0/public_html/2013/lec/source/lec12-nc.c   ノイズ除去プログラム printf("P1\n"); printf("%d %d\n", x_size, y_size); for (i = 0; i < y_size; i++){ printf("%d ",img_data[i][0]); for (j = 1; j < x_size-1; j++){ if(img_data[i][j-1] == WHITE && img_data[i][j] == BLACK && img_data[i][j+1] == WHITE){ printf("%d ",WHITE); } else if(img_data[i][j-1] == BLACK && img_data[i][j] == WHITE && img_data[i][j+1] == BLACK){ printf("%d ",BLACK); else printf("%d ",img_data[i][j]); printf("%d ",img_data[i][x_size-1]); printf("\n"); 行の先頭は隣がないのでそのまま出力 横方向の両端を除いた点に関して処理を行う 白黒白なら白を出力 黒白黒なら黒を出力 2つのケース以外の場合はそのまま出力 行の最後は隣がないのでそのまま出力 /home/course/prog0/public_html/2013/lec/source/lec12-nc.c

実行結果 std1dc1{s1000000}1: gcc lec12-nc.c -o hncut 結果を display コマンドに パイプ std1dc1{s1000000}1: gcc lec12-nc.c -o hncut std1dc1{s1000000}2: ./hncut < lec12-2.pbm | display & std1dc1{s1000000}3: ファイルからリダイレクト 元画像 コマンドdisplay -> xv – 置換 細かい点状のノイズを加えた ノイズは減ったが一部細い線が欠落した

パイプとリダイレクションのまとめ パイプのまとめ リダイレクションまとめ 標準入力の切り替え → コマンドの前に「|」 例:ls | wc -l 標準出力の切り替え → コマンドの後に「|」  例:cat hoge.txt | head リダイレクションまとめ 標準入力の切り替え → <    例:./a.out < in.txt 標準出力の切り替え(ファイル書き換え) → >  例:ls > out.txt 標準出力の切り替え(ファイルに追加)  → >>  例:ls >> out.txt