>100 Views
February 21, 22
スライド概要
C プログラミング入門
URL: https://www.kkaneko.jp/pro/adp/index.html
金子邦彦研究室
URL: https://www.kkaneko.jp/index.html
金子邦彦(かねこくにひこ) 福山大学・工学部・教授 ホームページ: https://www.kkaneko.jp/index.html 金子邦彦 YouTube チャンネル: https://youtube.com/user/kunihikokaneko
cp-14. ファイル処理 (C プログラミング入門) URL: https://www.kkaneko.jp/pro/adp/index.html 金子邦彦 1
アウトライン 例題1. 1行単位のファイル読み込み ファイルからの読み込み ファイルの終わり(EOF ともいう) 例題2.ファイルからのデータ読み込み ファイル中のデータの取り出し 例題3. 1行単位のファイル書き出し ファイルへの書き出し 例題4. 3行目を2回読み込む ファイルのランダムアクセス 2
ファイル読み込み プログラム ファイル •ファイルの中身は書き換わらな い 3
ファイル書き出し プログラム ファイル •ファイルの中身が書き換わる •ファイルは伸び縮みすることが ある 4
目標 • ファイルの読み書きを行うような、簡単なプログ ラムを書けるようになる • ファイルを扱う手順(オープン,読み込み,書 き出し,クローズ)を理解する 5
例題1.1行単位のファイル読み込み • ファイルを読み込んで,ファイルの中身に行 番号を付けて表示するプログラムを作る. • ファイルの読み込みでは,1行単位の読み込みを 行うために fgets 関数を使う • ファイルのオープンを行うために fopen 関数を使 い,ファイルのクローズを行うために fclose 関数 を使う 6
#include <stdio.h>
#pragma warning(disable:4996)
int main()
{
ファイルポインタ変数の宣言
char line[100];
int i = 1;
FILE *in_file;
ファイルのオープン
in_file = fopen("d:\\input.txt", "r");
(ファイルポインタが得
if ( in_file == NULL ) {
られる)
printf( "fopen() error" );
ファイルのオープンに
return 0;
失敗したかを調べている
}
while( fgets( line, 100, in_file ) != NULL ) {
printf( "[%d]%s", i, line );
ファイルの終わりに達し
ファイルの
i++;
ていないかを調べている
1行読み込み
}
fclose(in_file);
ファイルのクローズ
return 0;
(ファイルポインタを使ってクローズする)
7
}
実行結果例 [1]アレンジメントの特質 [2]・空間を分割 [3]・分割された部分(フェイス)は,凸性を有する(従って 有界)か, [4] 非有界な半空間 [5]・ボロノイ図を容易に導ける [6]・単体に容易に分解できる 8
プログラムとデータ メモリ ① line[0] fgets( line, 100, in_file ) line[1] ファイルの 1行読み込み line[2] line[3] line[4] ② printf( "[%d]%s", i, line ); 1行分の表示 9
プログラム実行順 in_file = fopen("d:\\input.txt", "r"); fgets( line, 100, in_file ) != NULL No Yes printf( "[%d]%s", i, line ); i++; fclose(in_file); 10
ファイルのオープンとクローズ • ファイルのオープン • ファイルの読み書きを行う前に、ファイルはオー プンされねばらならい • ファイルのクローズ • ファイルの読み書きが終わったら,ファイルはク ローズされねばならない 11
ファイルポインタ • ファイルポインタ変数の宣言 例)FILE *in_file; 「in_file」という名前の付いたファイルポインタ変数を宣言 • ファイルのオープン 例)in_file = fopen("d:\\input.txt", "r"); オープンすべき ファイル名 オープンモード r : 読み込みの意味 w: 書き出しの意味 ファイルのオープンを行うと,ファイルポインタが得られる • ファイルのクローズ fclose(in_file); ファイルポインタを使って,ファイルのクローズを行う 12
ファイルポインタ変数の働き ・現在のファイルのファイル位置指示子 (ファイルの読み書き位置) ・ファイルのオープンモード など 13
fgets の意味 • ファイルの1行読み込み • ファイルの一行分を読み込んで,末端の\0を付ける • ファイルには,行の終わりに,改行記号(\n)が付い ている(目には見えない) • 読み込み先(文字の配列)のサイズが,ファイルの1 行の長さより長いときは,「残りの部分」は変化しな い ファイル Mark\n 変化しない部分 文字の配列 M a r k \n \0 改行記号 文字列の末端 14
fgets で「100」を書く理由 fgets( line, 100, in_file ) 読み込み先の 配列の変数名 読み込み先の 配列のサイズ ファイルポインタ 変数名 ファイル 文字の配列 \0 文字列の末端 配列のサイズが100ならば,読み込める文字は99まで 15 (最後に必ず「\0」が付く)
NULLの意味 • fopen 関数では「ファイルオープンの失敗」 例) fopen(“d:\\input.txt", "r") if ( in_file == NULL ) { • fgets 関数では「ファイルの終わり」 例) fgets( line, 100, in_file ) != NULL 16
例題2.ファイルからのデータ読み込み • 次のような名簿ファイルを読み込んで,1列目 の氏名と,3列目の住所だけを表示するプログ ラムを作る • 各データは,空白文字で区切られる. • 1列目の氏名と,3列目の住所を取り出すために sscanf 関数を使う 金子邦彦 1200/01/01 福岡市東区箱崎 092-642-4068 ○○×× 1300/12/31 福岡市東区貝塚 092-642-3883 ●●■■ 800/05/31 福岡市東区香椎 092-642-3884 17
#include <stdio.h>
#pragma warning(disable:4996)
int main()
{
char line[100];
char name[100];
ファイルポインタ変数の宣言
char birth[100];
ファイルのオープン
char address[100];
FILE *in_file;
(ファイルポインタが得
in_file = fopen("a=d:\\Book1.csv", "r"); られる)
if ( in_file == NULL ) {
ファイルのオープンに
printf( "fopen() error" );
失敗したかを調べている
ファイルの終わりに達し
return 0; ファイルの
1行読み込み
ていないかを調べている
}
while( fgets( line, 100, in_file ) != NULL ) {
sscanf_s( line, "%s %s %s", name, birth, address );
printf( "name=%s, address=%s\n", name, address );
}
1列目,2列目,3列目の取り出し
fclose(in_file);
return 0;
ファイルのクローズ
18
}
(ファイルポインタを使ってクローズする)
実行結果例 name=金子邦彦, address=福岡市東区箱崎 name=○○××, address=福岡市東区貝塚 name=●●■■, address=福岡市東区香椎 19
プログラムとデータ メモリ line[0] line[1] line[99] ② ① fgets( line, 100, in_file ) ファイルの 1行読み込み sscanf( line, "%s %s %s", name, birth, address ); データの取り出し name birth address ③ printf( "name=%s, ... 1行分の表示 20
プログラム実行順 in_file = fopen("d:\\Book1.csv", "r"); fgets( line, 100, in_file ) != NULL No Yes sscanf( line, "%s %s %s", name, birth, address ); printf( "name=%s, address=%s\n", name, address ); fclose(in_file); 21
sscanf 関数 sscanf( line, "%s %s %s", name, birth, address ); line の中身を調べて,1列目,2列 目, 3列目のデータを name, birth, address に格納する ○○×× 1300/12/31 福岡市東区貝塚 092-642-3883 1行分 1列目 2列目 3列目 4列目 22
例題3.1行単位のファイル書き出し • 2つの浮動小数データを読み込んで,sin 関数 を使った計算を行い,計算結果をファイルに 書き出すプログラムを作る. • 「0」と「0.1」を読み込むと,0, 0.1, … 1.9 について,sin関数を使った計算を繰り返す(繰り 返し回数は20回とする) • ファイルの書き出すでは,1行単位の書き出しを 行うために fprintf 関数を使う • 書き出されたファイルは,Microsoft Excel み込み可能な形式であること で読 23
#include <stdio.h>
#include <math.h>
struct compute {
double start_x;
double step_x;
};
start_x と step_x を
キーボードから読み込む関数
void input_data( struct compute *data )
{
printf( "start_x =" );
scanf( "%lf", &(data->start_x) );
printf( "step_x =" );
scanf( "%lf", &(data->step_x) );
}
24
start_x と step_x を使って計算
を行い,結果をファイルに書き込む関数
void output_result( struct compute *data, char *file_name )
{
double x;
double y;
int i;
FILE* fp;
fp = fopen( file_name, "w" );
for( i = 0; i < 20; i++ ) {
x = data->start_x + ( i * data->step_x );
y = sin( x );
printf( "x= %lf, y= %lf\n", x, y );
fprintf( fp, "x=, %lf, y=, %lf\n", x, y );
}
fclose( fp );
}
25
int main()
{
struct compute data;
input_data( &data );
output_result( &data, "z:\\data.csv" );
return 0;
}
26
関数呼び出しの流れ main 関数 int main() input_data 関数 void input_data( struct compute *data ) 関数呼び出し 戻り input_data(&data ); return; 関数呼び出し output_result 関数 output_result(&data,"z:\\data.csv") ; void output_result( struct compute *data, char *file_name ) 戻り return; 27
1行単位のファイル読み込み の手順 ファイルのオープン fprintf 等を使って, ファイルの1行書き出し 終わりか? Yes No ファイルのクローズ 28
テキストファイルの読み書き • 読み込み • fgets と sscanf を使って,1行単位で読み込み • 書き出し • fprintf を使って,1行単位で書き出し 29
オープンモード fopen( file_name, "w" ); • “r” モード ファイル名 オープンモード (文字列) (文字列) • 読み込みモード • 引数fileで指定したファイルが存在しないか,読み 込み不可能な場合には,オープンすることができ ない. • “w” モード • 書き出しモード • 引数fileで指定したファイルが存在しない場合には, ファイルが新たに作成される.ファイルがすでに 存在した場合,ファイル中のデータはすべて捨て られる(ファイルの長さは0になる). 30
課題3.ファイルのコピー • ファイルをコピーするプログラムを作りなさい • ファイルを1行単位で読み込んで,別のファイルに1行 単位で書き出すことを繰り返す. • ファイルの読み込みでは,1行単位の読み込みを行う ために fgets 関数を使う • ファイルの書き出しでは,1行単位での書き出しを行 うために fprintf関数を使う • 2つのファイルを扱うために,2つのファイルポイン タ変数の宣言を行うこと • 読み込むべきファイルは,Zドライブに事前に作成して おくこと 31