前回、fopen() のテキストモードなどの解説も終わったので、簡単なファイル処理。
fscanf,fprintf
まずは基本ということで、今までの scanf+printf をファイル版の fscanf+fprintf に変えて、 データの入出力のプログラム。 一応昨年度までにやっているはずなので、簡単な説明に留める。
#include <stdio.h> void main() { FILE* fp_in ; FILE* fp_out ; if ( (fp_in = fopen( "data.txt" , "rt" )) != NULL ) { if ( (fp_out = fopen( "out.txt" , "wt" )) != NULL ) { char name[ 100 ] ; int p[ 3 ] ; while( fscanf( fp_in , "%s%d%d%d" , name, &p[0], &p[1], &p[2] ) == 4 ) { fprintf( fp_out , "%s %lf¥n" , name , (p[0]+p[1]+p[2]) / 3.0 ) ; } fclose( fp_out ) ; } fclose( fp_in ) ; } }
来週のこの時間は、ファイル入出力の演習ということで、 上記のような、データ読み込み&出力のプログラム作成を演習課題とする。
getc,putc
1文字づつ入出力を行う処理のサンプルで、以下のプログラムを示す。
このプログラムで、(1)入力データが無い場合は、EOF(End Of File) C言語では -1 が定数で割り当てられていることを説明。 また、このプログラムで、1文字データを記憶する変数 c が、なぜ char 型でなく int型なのか説明。 (2) このプログラムで、キーボード上でファイル入力終了のための、"^Z"(Windowsの場合 / unixなら"^D")を説明。 (3) このプログラムは、1文字を入力したらすぐさま大文字化して出力する。 しかし、"This is a pen."と入力しても、入力文字と出力文字が交互に、"TThHiIsS aA pPeEnN.."と出力されないことを説明。 入力バッファリング・出力バッファリングの説明を行う。
#include <stdio.h> void main() { int c ; while( (c = getchar()) != EOF ) { if ( c >= 'a' && c <= 'z' ) c = (c-'a') + 'A' ; putchar( c ) ; } }
バッファオーバーフロー対策の入出力
以下のプログラムは、予想以上の長い文字列を入力すると、バッファ溢れを利用して、 想定外のプログラムを実行できる可能性があって、極めて危険。
char name[ 10 ] ; scanf( "%s" , name ) ;
バッファオーバーフローによる脆弱性攻撃を防ぐには、以下の様な方法が一般的。
char buff[ 1000 ] ; while( fgets( buff , sizeof( buff ) , fp ) != NULL ) { char name[ 1000 ] ; int x , y ; if ( sscanf( buff , "%s%d%d" , name , &x , &y ) == 3 ) { // name , x , y を使う処理 } }