プログラミング言語 C 第 8 講 システム標準関数 ( 入出力関数 )
システム標準関数 システムに備え付けの関数 例 ) printf( ); scanf( ); 標準出力関数 標準入力関数 A. 入出力用の関数 高水準入出力関数 高水準言語 (OS に依存しない ) 低水準入出力関数 機械語レベル (OS に依存 ) B. それ以外の関数 引数と関数の型 ( 戻り値 ) に注目しましょう 例 ) FILE * fopen ( char* file, char* mode ); [ 関数の型 ][ 関数名 ][ 引数の型 ]
ファイルのオープン / クローズ ファイルのオープン関数 FILE * fopen ( char* file, char* mode ); ファイル名 オープンの状態 ファイル構造体 ファイルの入出力を管理するための一連のデータの集まり mode "r" : 読み出し専用 "r+" r/w "w" : 書き込み専用 "w+" r/w "a" : 追加書き込み "a+" r/w "b" : バイナリモード ( 画像や音声など ) ファイルのクローズ関数 int fclose( FILE* fp ); オープンで指定したファイル構造体
オープン / クローズの例 char fi[50]; FILE *fp; printf("input file name: "); scanf("%s", fi ); START 文字列型配列 fi[50] ファイルポインタ *fp Input file name: ファイル名を入力 if ( (fp = fopen ( fi, "r")) == NULL) { } fprintf(stderr, "Error: file open [%s]. n", fi); exit (1); 強制終了 stderr fclose (fp); : 標準エラー出力 オープンエラー Yes ファイルを読み出し専用テキストでオープンする オープンできないか? ファイルをクローズする END No
1 文字入出力 入力 出力 int getc ( FILE* fp ); int putc ( int c, FILE* fp ); 書き込む文字コード 読み出した文字コード 書き込んだ文字コード 例 ) ファイルから 1 文字ずつ読み出して 画面に表示する while((c = getc(fp))!= EOF) { putc(c, stdout); } stdout ファイルの最後 (End of File) : 標準出力 オープンで指定したファイル構造体 printf("%c", c); A 65 c 読み出し専用でオープン A magical place where all your childhood dreams come true....... EOF
練習問題 1 キーボードからテキストファイルの名前を入力して そのファイルの内容を 1 文字ずつ読み込んで画面に表示するプログラムを作成しましょう ファイル名 :08text.c 実行したら ファイル名に 08text.c と入力して 結果を見てみましょう /* 08text.c (2011/06/10) */ /* 学籍番号氏名 */ 実行例 ) #include <stdio.h> #include <stdlib.h> main() { int c; char fi[50]; FILE *fp;
ヒント /* 08text.c (2011/06/10) */ /* 学籍番号氏名 */ #include <stdio.h> #include <stdlib.h> main() { int c; char fi[50]; FILE *fp; ファイル名の入力 オープン / クロースの例 スライド参照 ファイルのオープン オープン / クロースの例 スライド参照 START 整数型変数 i 文字列型配列 fi[50] ファイルポインタ *fp ファイル名を入力してください : ファイル名を入力 ファイルを読み出し専用テキストでオープンする オープンできないか? No ファイルの最後まで ファイルから 1 文字入力 Yes オープンエラー } fclose(fp); ファイル内容の表示 1 文字入出力 スライド参照 入力した文字を表示する ファイルをクローズする END
1 行入出力 入力最大文字数 char* fgets ( char* b, int n, FILE* fp ); 文字列のポインタ 文字列 オープンで指定したファイル構造体 出力 int fputs ( char* b, FILE* fp ); 書き出した最後の文字 stdin : 標準入力 stdout : 標準出力 stderr : 標準エラー出力 標準入力 標準出力 char* gets ( char* b ); int puts ( char* b ); [ = fgets ( b, n, stdin ); ] [ = fputs ( b, stdout ); ]
'A' str[0] 1 行入出力の例 例 ) ファイルから 1 行ずつ読み出して 画面に表示する char str[256]; while((fgets(str, 256, fp))!= NULL) { } ' ' str[1] A magical fputs(str, stdout) ; 'm' str[2] 'a' str[3] 'g' str[4] 'i' str[5] str[6] 読み出す行がない 'c' printf("%s", str); 'a' str[7] 'l' str[8] ' 0' str[9] 読み出し専用でオープン A magical place where all your childhood dreams come true....... EOF
練習問題 2 キーボードからテキストファイルの名前を入力して そのファイルの内容を 1 行ずつ読み込んで 行番号をつけて画面に表示するプログラムを作成しましょう ファイル名 :08line.c 実行したら ファイル名に 08line.c と入力して 結果を見てみましょう /* 08line.c (2011/06/10) */ /* 学籍番号氏名 */ 実行例 ) #include <stdio.h> #include <stdlib.h> main() { int i = 1; char str[256]; char fi[50]; FILE *fp;
ヒント 2 /* 08line.c (2011/06/10) */ /* 学籍番号氏名 */ #include <stdio.h> #include <stdlib.h> main() { int i = 1; char str[256]; char fi[50]; FILE *fp; ファイル名の入力 オープン / クロースの例 スライド参照 START 整数型変数 i 文字列型配列 fi[50] ファイルポインタ *fp ファイル名を入力してください : ファイル名を入力 ファイルを読み出し専用テキストでオープンする オープンできないか? No 入力行がある間 Yes オープンエラー } ファイルのオープン オープン / クロースの例 スライド参照 ファイル内容の表示 1 行入出力の例 スライド参照 1 行ごとに行番号を表示する fclose(fp); printf("%s", str); を利用するといいでしょう ファイルから 1 行入力 行番号と文字列を表示 ファイルをクローズする END
書式付き入出力 (1) 標準入力 ( キーボード ) 標準出力 ( 画面 ) int scanf ("%d", &a); int printf ("%d", a); 書式化した文字列 ( いつも使っている書き方 ) 入力 int fscanf ( FILE* fp, "%d", &a ); オープンで指定したファイル構造体 出力 int fprintf ( FILE* fp, "%d", a ); 例 ) fp = fopen ( fi, w") fprintf( fp, "A magical place "); fprintf( fp, "where all your "); fprintf( fp, "childhood dreams "); fprintf( fp, "come true. n "); A magical place where all your childhood dreams come true.......
書式付き入出力 (2) 文字列入力 int sscanf ( char* b, "%d", &a ); 文字列出力 int sprintf ( char* b, "%d", a ); 文字列配列に対して入出力する 例 ) char b[12]; sprintf(b, "A magical" ); 'A' ' ' 'm' 'a' 'g' 'i' 'c' 'a' 'l' ' 0' b[0] b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] b[10] b[11]
バイナリのオープン / クローズ char FILE 強制終了 fi[50]; *fp; printf("input file name: "); scanf("%s", fi ); if ((fp = fopen ( fi,"wb")) == NULL) { } fprintf(stderr, "Error: file open [%s]. n", fi); exit (1); fclose (fp); オープンエラー Yes START 文字列型配列 fi[50] ファイルポインタ *fp Input file name: ファイル名を入力 ファイルを書き込み専用バイナリでオープンする オープンできないか? No ファイルをクローズする END
バイナリの入出力 入力 size_t fread(void *ptr, size_t size, size_t n, FILE *fp); 型のサイズ 配列の要素数 出力 size_t fwrite(void *ptr, size_t size, size_t n, FILE *fp); 入出力の配列名 オープンで指定したファイル構造体 size_t 型は,unsigned int 型のことで再定義されたデータ型である 出力の例 ) unsigned short header[13]; unsigned char bmp[200][200][3]; fwrite(header, 2, 13, fp); // ( ヘッダーを書き込む ) fwrite(bmp, 1, 200*200*3, fp); // ( 画像データを書き込む )
bmp 画像のフォーマット (1) Windows Bitmap OS/2 Bitmap ヘッダー + 画像データ ヘッダー 2 byte ファイルタイプ 'BM' 4 byte ファイルサイズ byte 2 byte 予約領域 0 2 byte 予約領域 0 画像 データ 4 byte ファイル先頭から画像データまでのオフセット byte 4 byte 情報ヘッダのサイズ 12 2 byte 画像の幅 ピクセル 2 byte 画像の高さ ピクセル 2 byte プレーン数 1 2 byte 1 画素あたりのデータサイズ bit 例 )200x200 ピクセルの 24 ビットサイズの画像 unsigned short header[13] = {0x4d42, 54490, 1, 0, 0, 26, 0, 12, 0, 200, 200, 1, 24};
bmp 画像のフォーマット (2) 画像データ (24bit 画像 ) 1 画素のカラーパレット 赤 (R) 0 ~ 255 緑 (G) 0 ~ 255 青 (B) 0 ~ 255 画像データの並び 1 byte (8 bit) 1 byte (8 bit) 1 byte (8 bit) 3 byte (24 bit) (0,4) (0,0) B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R B G R (3,4) (3,0)
光と色の三原色 光モニター 赤緑青 色プリンタ シアンマゼンタイエロー
[199][][] 画像の多次元配列 200x200 の bmp 画像の場合 i unsigned char bmp[200][200][3]; 縦の数横の数色の数 bmp 画像の 3 次元配列 [199][0][] [199][1][] [199][2][] [199][199][] bmp[199][199][2] [2][][] [2][0][] [2][1][] [2][2][] [2][199][] [1][][] [1][0][] [1][1][] [1][2][] [1][199][] [0][][] bmp[0][0][0] [0][0][] [0][1][] [0][2][] [0][199][] [][0][] [][1][] [][2][] [][199][] bmp[0][199][2] j ( j, i ) 番目の画素 : bmp[i][j][0] bmp[i][j][1] bmp[i][j][2]
練習問題 3 すべてが青色の 200x200 ピクセルの bmp 画像を作成しよう プロジェクト名 :08bmp 入力 : ファイル名 (blue.bmp) 処理 : 青色の bmp 画像の作成 出力 :bmp ファイル 200 ピクセル /* 08bmp.c (2011/06/10) */ /* 学籍番号氏名 */ #include <stdio.h> #include <stdlib.h> main( ) { 実行例 ) 200ピクセル bmp[200][200][3] char fi[50]; int i, j; FILE *fp; 3 原色 ( 青, 緑, 赤 ) unsigned short header[13] = {0x4d42, 54490, 1, 0, 0, 26, 0, 12, 0, 200, 200, 1, 24}; unsigned char bmp[200][200][3];
ヒント 1 START 文字列型配列 fi[50] 整数型変数 i, j ファイル構造体 *fp unsigned short 型 header[13] unsigned char 型 bmp[200][200][3] i=0 から 199 まで j=0 から 199 まで bmp[i][j][0] 青の数値 bmp[i][j][1] 緑の数値 bmp[i][j][2] 赤の数値 j に 1 を足す i に 1 を足す 1 "Input file name :" ファイル名を fi に入力 ファイルを書き込み専用バイナリでオープンする オープンできないか? No 1 ヘッダーを書き込む 画像データを書き込む ファイルをクローズする END Yes オープンエラー
ヒント 2 色の設定 bmp[i][j][0] = 青 bmp[i][j][1] = 緑 実際の色 bmp[i][j][2] = 赤 数値の順番に気をつけて! ユーザー設定の数値に注目! 作成した blue.bmp 画像は, エクスプローラから開きましょう [ スタート ] ボタン [ ドキュメント ] [cprog] [08bmp] [08bmp]
課題 次に示すような 200x200 ピクセルの画像を作成しよう ファイル名 :08rect.c 入力 : 出力ファイル名 (rect.bmp) 処理 :bmp 画像の作成 出力 : 以下のようなbmp 画像 実行例 ) ソースファイルと結果の bmp 画像を A4 の用紙に印刷して提出しましょう (bmp 画像は Word に貼り付けて裏面に印刷しましょう ) bmp 画像を印刷するときは, 大きさに気をつけましょう (Word に貼り付けて大きさを調整しましょう )
ヒント 1 START? のところは各自考えよう点線部分を必要なだけ追加しよう 2 文字列型配列 fi[50] 整数型変数 i, j ファイルポインタ *fp unsigned short 型 header[13] unsigned char 型 bmp[200][200][3] i=0 から? まで j=0 から? まで bmp[i][j][0] 青 ( 背景 ) bmp[i][j][1] 緑 ( 背景 ) bmp[i][j][2] 赤 ( 背景 ) j に 1 を足す i に 1 を足す 1 i=? から? まで j=? から? まで bmp[i][j][0] 青 ( 四角形 ) bmp[i][j][1] 緑 ( 四角形 ) bmp[i][j][2] 赤 ( 四角形 ) j に 1 を足す i に 1 を足す "Input file name :" ファイル名を fi に入力 ファイルを書き出し専用バイナリでオープンする オープンできないか? No ヘッダーを書き込む 画像データを書き込む ファイルをクローズする Yes オープンエラー 1 2 END
ヒント 2 画像の座標を考えよう y ( i ) 200 座標を参考にして繰り返しの範囲を考えましょう 100 0 100 200 x ( j )