1
ファイルの処理(C言語)
2006-11 AKIYAMA M.
テキストファイル
• Windowsのテキストファイル 区切り文字で終わる可変長記録
区切り文字:CRLF 0x0d0a
(ファイルの終わり:SUB 0x1a)
• UNIXのテキストファイル
区切り文字:LF 0x0a
ファイルの終わりを示す文字: なし
Cプログラムでのファイル処理
• 手順
1. ファイルを開く 2. 入出力操作を繰返す 3. ファイルを閉じる
• ファイル型 (型名FILE)
FILE型のポインタ変数をファイル実体と対 応づける
ファイルを開く
• ヘッダファイル
#include <stdio.h>
• FILEポインタ変数の宣言
FILE *fp; /* fpは変数名の例*/
• fopen関数で変数とファイル実体を対応付ける fp = fopen( "z:¥¥vc¥¥sampledata.txt", "r" );
第1パラメータ: ファイル実体のパス名
文字列定数中の"¥¥" は'¥' のエスケープ文字である 第2パラメータ: オープンモード(後述)
• fopen関数は、FILE型のポインタを返す ファイルを開くことができなかったとき、値NULLを返す
fopen関数
• オープンモード(第2パラメータ)
"r" read 読込み
"w" write 書出し
"a" append 追加書き
"r" では、ファイルが存在しないとエラーとなる
"w"では、ファイルが存在しなければ新たに作成され、ファイ
ルが存在していれば最初に内容が消去される
"a" では、ファイルが存在しなければ新たに作成され、ファイ ルが存在していればその最後尾に追記される
fopen関数のエラーチェック
FILE *fp;
fp = fopen("sample.txt", "r" );
if ( fp == NULL ) {
perror( "sample.txt" ); exit(-1);
}
...; /* ファイルからの入力など*/
fclose( fp );
perror関数でシステムエラーメッセージを出力する
2
ファイルを閉じる
• fclose関数 fclose( fp );
パラメータ: ファイル型のポインタ 戻り値: int型
正常終了のとき0 エラーのときEOF
標準入出力ファイル
• ファイル型ポインタ
stdin 標準入力
stdout 標準出力
stderr 標準エラー出力
プログラムの実行開始時点で開かれている 終了時に閉じる必要はない
入出力関数(1) 書式付出力
• int fprintf( FILE *fp, char* fmt, arg, ... );
fp: 出力ファイルへのポインタ
fmt, arg, ... : printf関数の第1パラメータ以降と同じ 戻り値: 出力した文字数、エラーのときは負の値 fprintf( stdout, "Hello!¥n" );
は
printf( "Hello!¥n" );
と同じ
入出力関数(2) 書式付き入力
• int fscanf( FILE *fp, char* fmt, arg, ... );
fp: 入力ファイルへのポインタ
fmt, arg, ... : printf関数の第1パラメータ以降と同じ 戻り値: 入力編集した値の数、エラーのときはEOF fscanf( stdin, "%d", &a );
は
scanf( "%d", &a );
と同じ
入出力関数(3) 文字列の出力
• int fputs( char* buff, FILE *fp );
buff: 文字列へのポインタ、'¥0'の前の文字までが出 力される
fp: 入力ファイルへのポインタ
戻り値: 正常終了のときは負でない値、エラーのとき はEOF
戻り値を使わないのであればfprintf( fp, buff ) と同じ fputs( buff, stdout ); では改行文字は付加されない puts( buff ); は文字列出力後に改行される
入出力関数(4) 行単位の入力
• char* fgets( char* buff, int n, FILE *fp );
buff: 入力用の文字配列へのポインタ n: 最大でn-1文字が読込まれる fp: 入力ファイルへのポインタ
戻り値:buffの値、エラーまたはファイルの終わりに
達したときはNULL
記録の区切り文字まで、または(n-1)文字の短い方 が文字配列に読み込まれる
区切り文字は'¥n' に置き換えられ、読み込まれた文 字列の次の要素に'¥0' が入れられる
3
入出力関数(4-1) fgets()とgets()
• char* gets( char* buff );
標準入力stdinから、区切り文字までの文字列を文
字配列buff に読み込む
区切り文字は除去されて'¥0' が付加される
戻り値:buffの値、エラーまたはファイルの終わりに
達したときはNULL
入力文字数が検査されないのでバッファオーバーフ ローを起こす危険がある
fgets( buff, n, stdin ) を使うほうが安全である
入出力関数(5) 1文字の出力
• int fputc( int c, FILE *fp );
c: 出力文字
fp: 入力ファイルへのポインタ
戻り値: 正常終了のときはcの値、エラーのときは EOF
putc( c, fp) とほぼ同じ
fputc( c, stdout );はputchar( c ); と同じ
入出力関数(6) 1文字の入力
• int fgetc( FILE *fp );
fp: 入力ファイルへのポインタ
戻り値: 正常終了のときは読み込まれた文字の値、
エラーのときはEOF getc( fp ) とほぼ同じ char c; c=fputc( stdin );は char c; c=getchar(); と同じ
プログラムの例(1-1)
{ /* ファイルの割り当て*/
FILE *inf, *outf;
inf = fopen( "z:¥¥vc¥¥sample.txt", "r" );
if ( inf == NULL ) { perror( "infile" ); exit(-1); } outf = fopen( "z:¥¥vc¥¥sample_out.txt", "w" );
if ( outf==NULL ) { perror( "outfile" ); exit(-1); } /* つづく*/
プログラムの例(1-2)
/* 入力、計算、出力の繰り返し*/
for( ; ; ) { int a, b, c;
if ( fscanf( inf, "%d", &a ) == EOF ) break;
if ( fscanf( inf, "%d", &b ) == EOF ) break;
c = a+b;
fprintf( outf, "%d¥n", c );
}
/* つづく*/
プログラムの例(1-3)
/* ファイルを閉じる*/
fclose( inf );
fclose( outf );
/* 終了*/
}
プログラムを実行する前に、エディタを使ってファイル
z:¥vc¥sample.txtを作成しておく
実行終了後に ファイルz:¥vc¥sample_out.txtを確認 する
4
プログラムの例(2)
/* ファイルの複製*/
/*ファイルポインタsorc, destにファイル実体 が対応付けられているものとする */
int c;
while((c=fgetc(sorc))!= EOF) fputc(c,dest);
fclose(sorc);
fclose(dest);
文字列への書式付き出力
• int sprintf( char* out, char* fmt, args, ... );
out : 出力先の文字配列、第3パラメータargs 以降が,fmtに従って編集され、文字列とし て格納される(末尾に'¥0'が付加される)
fmt, args, ... : printf関数のパラメータと同じ 戻り値: 正常終了のとき、出力された文字数
('¥0'を含めない数)、エラーのときEOF
文字列からの書式付き入力
• int sscanf( char* in, char* fmt, args, ... );
out : 入力編集対象の文字列が格納された 文字配列、fmtに従って入力編集され、値が args以降のアドレスに格納される
fmt, args, ... : scanf関数のパラメータと同じ 戻り値: 正常終了のとき、編集された値の数、
エラーのときEOF
sscanf関数の使用例
{ char buff[256];
double a; int b;
fgets( buff, 256, stdin );
if (buff[0]=='d' ) sscanf( &buff[1], "%lf", &a );
else sscanf( &buff[1], "%d", &b );
... ; }
csv形式のファイル
• 表計算アプリケーションで、形式csvで保存し たファイル(Windowsの拡張子は.csv)
• 集計表の1行中の各列の値がコンマで区切ら れた形で並べられて1つの記録になる ( comma separated values )
• テキストファイルである
–エディタやCプログラムで入力可能である – Cプログラムで作成し、表計算アプリケーションで
読み込むことで容易にグラフ描画ができる
セキュリティが強化された入出力関数
• Microsoft Visual Studio 2005で導入された
• printf_s, fprintf_s, sprintf_s
書式指定文字列の有効性を検査する 使い方はprintf, fprintf, sprintfと同じ
• scanf_s, fscanf_s, sscanf_s
書式指定文字列の有効性を検査する バッファオーバーフローを防ぐ
書式指定%s, %cを使うときは、対応する入力先 アドレスのパラメータに続けて、読み取り文字 数を指定するパラメータを追加する
(例)char buff[100];
scanf_s( "%s", buff, 100 );