Cプログラミング演習 第6回 ファイル処理と配列.

Slides:



Advertisements
Similar presentations
プログラミング演習 II 2005 年 1 月 19 日(第 9 回) 理学部数学科・木村巌. 前回までの復習 共用体( union type ) 共用体( union type ) 列挙 (enumerated type ) 列挙 (enumerated type ) 構造体、構造体のポインタ、
Advertisements

10: ファイル入出力 Linux にログインし、以下の講義ページ を開いておくこと teachers/w483692/CPR1/ C プログラミング入門 総機 1 ( 月 1) 1.
オブジェクト指向言語・ オブジェクト指向言語演習 中間試験回答例. Jan. 12, 2005 情報処理技術基礎演習 II 2 オブジェクト指向言語 中間試験解説 1  (1) 円柱の体積(円柱の体積 = 底面の円の面積 x 高さ) を求めるプログラムを作成しなさい。ただし、出力結果は、入 力した底面の円の半径.
情報処理演習C2 ファイル操作について (2).
4章 制御の流れ-3.
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
基礎プログラミングおよび演習 第9回
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
第13回 プログラミングⅡ 第13回
基礎プログラミング (第五回) 担当者: 伊藤誠 (量子多体物理研究室) 内容: 1. 先週のおさらいと続き (実習)
第6章 2重ループ&配列 2重ループと配列をやります.
精密工学科プログラミング基礎 第9回資料 (12/11 実施)
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング 第11回 プロセス間通信4 仮想FTPの実現 担当:青木義満
関数 関数とスタック.
精密工学科プログラミング基礎Ⅱ 第3回資料 今回の授業で習得してほしいこと: 2次元配列の使い方 (前回の1次元配列の復習もします.)
構造体 構造体, 構造体とポインタの組み合わせ,.
10: ファイル入出力 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
第2回 Microsoft Visual Studio C++ を使ってみよう
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
Cプログラミング演習 中間まとめ2.
プログラミング 2 ファイル処理.
プログラミング論 ファイル入出力
繰り返し計算 while文, for文.
Cプログラミング演習.
プログラミング応用 printfと変数.
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第2回 ファイル処理 情報・知能工学系 山本一公
iioLoadFile()とiioMallocImageBuffer()の補足
Cプログラミング演習 第7回 メモリ内でのデータの配置.
iioLoadFile()とiioMallocImageBuffer()の補足
iioLoadFile()とiioMallocImageBuffer()の補足
プログラミング演習I 2003年6月25日(第10回) 木村巌.
知能情報工学演習I 第9回( C言語第3回) 課題の回答
岩村雅一 知能情報工学演習I 第10回(後半第4回) 岩村雅一
プログラミング論 ファイル入出力
Cの実行モデル.
四則演算,変数 入力文,出力文,代入文, ライブラリ関数
プログラミング基礎B 文字列の扱い.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
精密工学科プログラミング基礎Ⅱ 第4回資料 今回の授業で習得してほしいこと: 文字列の扱い ファイル入出力の方法 コマンドライン引数の使い方
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
第4回 ファイル入出力方法.
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
メモリとメモリアドレス, ポインタ変数,関数へのポインタ渡し
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
統計ソフトウエアRの基礎.
プログラミング演習I 2003年7月2日(第11回) 木村巌.
vc-3. ダンプリスト,配列 (Visual Studio C++ の実用知識を学ぶシリーズ)
vc-2. Visual Studio C++ のデバッガー (Visual Studio C++ の実用知識を学ぶシリーズ)
ファイルの読み込み, ファイルからのデータの取り出し, ファイルの書き出し
vc-1. Visual Studio C++ の基本操作 (Visual Studio C++ の実用知識を学ぶシリーズ)
vc-3. ダンプリスト,配列 (Visual Studio C++ の実用知識を学ぶシリーズ)
cp-15. 疑似乱数とシミュレーション (C プログラミング演習,Visual Studio 2019 対応)
cp-1. クラスとメソッド (C++ オブジェクト指向プログラミング入門)
ファイル操作について (1).
cp-3. 計算 (C プログラミング演習,Visual Studio 2019 対応)
モジュール分割.
プログラミング 4 文字列.
Cp-1. Microsoft Visual Studio 2019 C++ の使い方 (C プログラミング演習,Visual Studio 2019 対応) 金子邦彦.
C言語プログラミング・課題 ファイルを読み込んで、その内容を表示するプログラムを作成せよ。
岩村雅一 知能情報工学演習I 第10回(後半第4回) 岩村雅一
四則演算,変数 入力文,出力文,代入文, ライブラリ関数
コンピュータープログラミング (C言語)(10) 1.ファイル入出力
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
知能情報工学演習I 第9回(後半第3回) 課題の回答
= 55 課題6-1 #define _CRT_SECURE_NO_WARNINGS
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

Cプログラミング演習 第6回 ファイル処理と配列

ファイル処理

ファイル読み込み プログラム ファイル ファイルの中身は変わらない

ファイル書き出し プログラム ファイル ファイルの中身が変わる ファイルは伸び縮みすることがある

例題1.テキストファイル形式の ファイルからのデータ読み込み 次のような名簿ファイル(テキストファイル形式)を読み込んで,1列目の氏名と,3列目の住所だけを表示するプログラムを作る 各データは,半角の空白文字(1つまたは複数)で区切られる 金子邦彦 1200/01/01 福岡市東区箱崎3丁目 392-123-8234 ○○×× 1300/12/31 福岡市東区貝塚団地 492-252-7188 ●●■■ 0800/05/31 福岡市東区香椎浜1丁目 592-824-7144 3行のテキストファイル

テキストファイル形式 行単位での読み書きに意味がある。 人間が「目で見て」読むことができるファイル。 <FF>0<FF><E0>^@^PJFIF^@^A^B^A^@<96>^@<96>^@^@<FF><E0>~JFXX^@^P<FF>00<FF>U^@^C^@^ テキストファイルでない バイナリファイルの例 (画像のファイル) MPL 40 pattern1 = 786 pattern2 = 1 pattern3 = 979 pattern4 = 0 テキストファイルの例

#include "stdafx.h" #include <math.h> #pragma warning(disable:4996) int _tmain() { char line[100]; char name[100]; char birth[100]; char address[100]; FILE *in_file; int ch; in_file = fopen("d:\\Book1.txt", "r"); if ( in_file == NULL ) { return 0; } while( fgets( line, 100, in_file ) != NULL ) { sscanf_s( line, "%s %s %s", name, birth, address ); printf( "name=%s, address=%s\n", name, address ); fclose(in_file); ch = getchar();

例題1の手順 各自で行ってください (実行結果の確認まで) 1.準備 演習用のデータファイル d:\Book1.txt を各自で作成    (本資料のページ9,10,11,12,13) 2.ビルドと実行  例題1のプログラムを各自で実行し,実行結果を確認   (本資料のページ14,15) 各自で行ってください (実行結果の確認まで)

動かないことがあるので注意してください) まず,データファイル d:\Book1.txt を準備する (テキストファイル形式) 金子邦彦 1200/01/01 福岡市東区箱崎3丁目 392-123-8234 ○○×× 1300/12/31 福岡市東区貝塚団地 492-252-7188 ●●■■ 0800/05/31 福岡市東区香椎浜1丁目 592-824-7144 半角の 空白文字 d:\Book1.txt の例 (全角の空白文字が混ざっていると  動かないことがあるので注意してください)

「メモ帳」を起動している

コピーして ・・・

貼り付ける

保存する場所は,Zドライブ ファイル名は Book1.txt 「ファイル」 →「名前を付けて保存」

ビルド後の画面 ビルドの手順: 「ビルド」→「○○のビルド」 ビルドが正常終了したことを示すメッセージ 「1.正常終了」を確認

実行中の画面 実行の手順: 「デバッグ」→「実行」 実行ウインドウが現れる

while による繰り返し部分 ファイルオープンに失敗した ときのみ実行される部分 #include "stdafx.h" #include <math.h> #pragma warning(disable:4996) int _tmain() { char line[100]; char name[100]; char birth[100]; char address[100]; FILE *in_file; int ch; in_file = fopen("d:\\Book1.txt", "r"); if ( in_file == NULL ) { return 0; } while( fgets( line, 100, in_file ) != NULL ) { sscanf_s( line, "%s %s %s", name, birth, address ); printf( "name=%s, address=%s\n", name, address ); fclose(in_file); ch = getchar(); ファイルオープンに失敗した ときのみ実行される部分 while による繰り返し部分

NULLの意味 「==」 は等しいという意味 「!=」は等しくないという意味 fopen 関数では「ファイルオープンの失敗」 #include "stdafx.h" #include <math.h> #pragma warning(disable:4996) int _tmain() { char line[100]; char name[100]; char birth[100]; char address[100]; FILE *in_file; int ch; in_file = fopen("d:\\Book1.txt", "r"); if ( in_file == NULL ) { return 0; } while( fgets( line, 100, in_file ) != NULL ) { sscanf_s( line, "%s %s %s", name, birth, address ); printf( "name=%s, address=%s\n", name, address ); fclose(in_file); ch = getchar(); NULLの意味 fopen 関数では「ファイルオープンの失敗」 fgets 関数では「ファイルの終わり」 「==」 は等しいという意味 「!=」は等しくないという意味

fopen 関数では「ファイルオープンの失敗」 #include "stdafx.h" #include <math.h> #pragma warning(disable:4996) int _tmain() { char line[100]; char name[100]; char birth[100]; char address[100]; FILE *in_file; int ch; in_file = fopen("d:\\Book1.txt", "r"); if ( in_file == NULL ) { return 0; } while( fgets( line, 100, in_file ) != NULL ) { sscanf_s( line, "%s %s %s", name, birth, address ); printf( "name=%s, address=%s\n", name, address ); fclose(in_file); ch = getchar(); ファイルオープンに失敗したら, プログラムが終わる fopen 関数では「ファイルオープンの失敗」 fgets 関数では「ファイルの終わり」 ファイルの終わりになるまで, fgets, sscanf, printf を繰り返す

ファイル操作 ファイルのオープンとクローズ ファイルの読み込み ファイルの書き出し fopen ファイルの読み書きを行う前に、ファイルはオープンされねばならない fclose ファイルの読み書きが終わったら、ファイルはクローズされねばならない ファイルの読み込み fgets 1行単位の読み込み fread バイト単位での読み込み(1バイト,複数バイト) ファイルの書き出し fputs 1行単位での書き出し fwrite バイト単位での書き出し(1バイト,複数バイト) fprintf 整形しての書き出し

オープンモード “r” モード “w” モード in_file = fopen("d:\\Book1.txt", "r"); ファイル名 (文字列) オープンモード (文字列) “r” モード 読み込みモード 引数fileで指定したファイルが存在しないか,読み込み不可能な場合には,オープンすることができない. “w” モード 書き出しモード 引数fileで指定したファイルが存在しない場合には,ファイルが新たに作成される.ファイルがすでに存在した場合,ファイル中のデータはすべて捨てられる(ファイルの長さは0になる).

while による繰り返し部分 ファイルポインタ ファイルのオープン ファイルの読み込み(1行単位) ファイルのクローズ #include "stdafx.h" #include <math.h> #pragma warning(disable:4996) int _tmain() { char line[100]; char name[100]; char birth[100]; char address[100]; FILE *in_file; int ch; in_file = fopen("d:\\Book1.txt", "r"); if ( in_file == NULL ) { return 0; } while( fgets( line, 100, in_file ) != NULL ) { sscanf_s( line, "%s %s %s", name, birth, address ); printf( "name=%s, address=%s\n", name, address ); fclose(in_file); ch = getchar(); ファイルポインタ ファイルのオープン ファイルの読み込み(1行単位) ファイルのクローズ while による繰り返し部分

char 型の配列(サイズ100) を4つ宣言している (配列についての詳細は後述) #include "stdafx.h" #include <math.h> #pragma warning(disable:4996) int _tmain() { char line[100]; char name[100]; char birth[100]; char address[100]; FILE *in_file; int ch; in_file = fopen("d:\\Book1.txt", "r"); if ( in_file == NULL ) { return 0; } while( fgets( line, 100, in_file ) != NULL ) { sscanf_s( line, "%s %s %s", name, birth, address ); printf( "name=%s, address=%s\n", name, address ); fclose(in_file); ch = getchar(); char 型の配列(サイズ100) を4つ宣言している (配列についての詳細は後述)

例題1のプログラムが 行っていること プログラムが使う メモリ空間 line 100バイトの メモリエリア name 100バイトの birth 100バイトの メモリエリア address 100バイトの メモリエリア

例題1のプログラムが 行っていること プログラムが使う メモリ空間 データファイル line 100バイトの メモリエリア name 金子邦彦 ・・・ 金子邦彦 1200/01/01 福岡市東区箱崎3丁目 392-123-8234 ○○×× 1300/12/31 福岡市東区貝塚団地 492-252-7188 ●●■■ 0800/05/31 福岡市東区香椎浜1丁目 592-824-7144 name 100バイトの メモリエリア fgets で 読み出し (1行分) birth 100バイトの メモリエリア address 100バイトの メモリエリア

例題1のプログラムが 行っていること プログラムが使う メモリ空間 データファイル line 100バイトの メモリエリア name sscanf での 処理 line データファイル 100バイトの メモリエリア 金子邦彦 ・・・ 金子邦彦 1200/01/01 福岡市東区箱崎3丁目 392-123-8234 ○○×× 1300/12/31 福岡市東区貝塚団地 492-252-7188 ●●■■ 0800/05/31 福岡市東区香椎浜1丁目 592-824-7144 name 100バイトの メモリエリア 金子邦彦 fgets で 読み出し (1行分) birth 100バイトの メモリエリア 1200/01/01 address 100バイトの メモリエリア 2行目以降も 同様の処理が続く 福岡市東区箱崎3丁目

実際のメモリの中身 メモリの中身を画面表示したもの

実際のメモリの中身 ここでは,16バイトごとに 区切って,1行で表示 メモリの中身を画面表示したもの

「バイト」は,データの基本単位 1バイト 16進数2桁 (00からFF) 2進数では8桁 (00000000 から 11111111) 実際のメモリの中身 1バイト   16進数2桁 (00からFF)   2進数では8桁 (00000000 から 11111111)   10進数では 0 から 255 までの256通り 「バイト」は,データの基本単位 メモリの中身を画面表示したもの

実際のメモリの中身 address (100バイト) birth (100バイト) name (100バイト) line (100バイト)

プログラムとデータ ① ファイルの 読み込み (1行単位) ② データの取り出し ③ 1行分の表示 プログラムが使うメモリ空間 line[0] line[1] fgets( line, 100, in_file ) ファイルの 読み込み (1行単位) line[99] ② sscanf_s( line, "%s %s %s", name, birth, address ); データの取り出し name birth address ③ printf( "name=%s, ... 1行分の表示

変数は3種類使っている 整数を扱う int 型 文字を扱う char 型 ファイルポインタ #include "stdafx.h" #include <math.h> #pragma warning(disable:4996) int _tmain() { char line[100]; char name[100]; char birth[100]; char address[100]; FILE *in_file; int ch; in_file = fopen("d:\\Book1.txt", "r"); if ( in_file == NULL ) { return 0; } while( fgets( line, 100, in_file ) != NULL ) { sscanf_s( line, "%s %s %s", name, birth, address ); printf( "name=%s, address=%s\n", name, address ); fclose(in_file); ch = getchar(); 変数は3種類使っている 整数を扱う int 型 文字を扱う char 型 ファイルポインタ

fgetsの振る舞い ファイル 文字の配列 line M a r k ファイルの1行読み込み ファイルの一行分を読み込んで、末端の\0を付ける ファイルには、各行の終わりに、改行文字(\n)が付いている(目には見えない) 読み込み先(文字の配列)のサイズが、ファイルの1行の長さより長いときは、「残りの部分」は変化しない ファイル Mark\n 1行読み込むと・・・ 変化しない 文字の配列 line M a r k 16進数 の「0A」 16進数 の「00」 改行文字 文字列の末端

fgets での「100」 fgets( line, 100, in_file ) ファイル 文字の配列 100バイトに達したら 行末になっていなくても読み込み終了せよ ファイル 改行文字 文字の配列 16進数 の「0A」 16進数 の「00」 文字列の末端 配列のサイズが100ならば、読み込めるデータの 本体(「改行文字」を除く)は,最大で98文字まで

それぞれ対応 それぞれ対応 char 型の配列については, sscanf, printf , fprintf #include "stdafx.h" #include <math.h> #pragma warning(disable:4996) int _tmain() { char line[100]; char name[100]; char birth[100]; char address[100]; FILE *in_file; int ch; in_file = fopen("d:\\Book1.txt", "r"); if ( in_file == NULL ) { return 0; } while( fgets( line, 100, in_file ) != NULL ) { sscanf_s( line, "%s %s %s", name, birth, address ); printf( "name=%s, address=%s\n", name, address ); fclose(in_file); ch = getchar(); char 型の配列については, sscanf, printf , fprintf では「%s」を,使う決まりになっている それぞれ対応 それぞれ対応

配列

一次元配列 0から始まる番号がついたデータの並び 配列の要素には型がある 例) int, char, double など 0から開始 1 2 サイズは3

例題2.ベクトルの内積 ベクトル(1.9, 2.8, 3.7)と,ベクトル(4.6, 5.5, 6.4)の内積を表示するプログラムを作る 2つのベクトルの内積の計算のために,サイズ3の一次元配列を2つ使う

例題2:ベクトルの内積 整数を扱う int 型 #include "stdafx.h" #include <math.h> int _tmain() { int i; double ip = 0.0; double u[]={1.9, 2.8, 3.7}; double v[]={4.6, 5.5, 6.4}; int ch; for (i=0; i<3; i++) { ip = ip + u[i]*v[i]; } printf("内積=%f\n", ip); ch = getchar(); return 0; 変数の宣言 および初期化 整数を扱う int 型 浮動小数を扱う double 型

#include "stdafx.h" #include <math.h> int _tmain() { int i; double ip = 0.0; double u[]={1.9, 2.8, 3.7}; double v[]={4.6, 5.5, 6.4}; int ch; for (i=0; i<3; i++) { ip = ip + u[i]*v[i]; } printf("内積=%f\n", ip); ch = getchar(); return 0; メモリ確保および初期化が行われる。 変数 u, v は,浮動小数 を要素とする配列で, サイズは3 u v 1.9 4.6 1 1 2.8 5.5 2 2 3.7 6.4

0 + 1.9 * 4.6 ip i i = 0, 1, 2 での繰り返し for (i=0; i<3; i++) { ip = ip + u[i]*v[i]; } ip i i = 0, 1, 2 での繰り返し (3回繰り返し) 最初は i = 0 0 + 1.9 * 4.6 u v 1.9 4.6 i = 0 のときは ip + u[0]*v[0] 1 1 2.8 5.5 2 2 3.7 6.4

for (i=0; i<3; i++) { ip = ip + u[i]*v[i]; } ip i 8.74 1 i = 0, 1, 2 での繰り返し (3回繰り返し) 次は i = 1 8.74 + 2.8 * 5.5 u v 1.9 4.6 i = 1 のときは ip + u[1]*v[1] 1 1 2.8 5.5 2 2 3.7 6.4

for (i=0; i<3; i++) { ip = ip + u[i]*v[i]; } ip i 24.14 2 i = 0, 1, 2 での繰り返し (3回繰り返し) 次は i = 2 24.14 + 3.7 * 6.4 u v 1.9 4.6 i = 2 のときは ip + u[2]*v[2] 1 1 2.8 5.5 2 2 3.7 6.4

つまり ip の値は u[0]*v[0] + u[1]*v[1] ベクトルの内積 for (i=0; i<3; i++) { ip = ip + u[i]*v[i]; } 繰り返し条件式 が成り立つか i の値 ip の値 繰り返し 1回目 i = 0 i < 3 が成り立つ ip = ip + u[0] * v[0]; つまり ip の値は u[0]*v[0] 繰り返し 2回目 i = 1 i < 3 が成り立つ ip = ip + u[1] * v[1]; つまり ip の値は u[0]*v[0] + u[1]*v[1] 繰り返し 3回目 i = 2 i < 3 が成り立つ ip = ip + u[2] * v[2]; つまり ip の値は u[0]*v[0] + u[1]*v[1] +u[2]*v[2] 繰り返し 4回目 i = 3 i < 3 が成り立たない

配列の使い方 添字をつけて、普通の変数のように使う。 配列 a 添字 int a[3]; a[0] = i; a[1] = 5; fscanf(“%d”,&a[2]); j = a[2]; printf(“%d %d\n”,a[0],a[1]); a[0] 1 a[1] 2 a[2]

次のプログラムを実行してみなさい #include "stdafx.h" #include <math.h> int _tmain() { int i; double ip = 0.0; double u[]={1.9, 2.8, 3.7}; double v[]={4.6, 5.5, 6.4}; int ch; for (i=0; i<3; i++) { ip = ip + u[i]*v[i]; } printf("内積=%f\n", ip); ch = getchar(); return 0; 各自で行ってください(実行結果の確認まで) 終わったら,例題3を各自で行ってください

例題3.棒グラフを描く 整数の配列から,その棒グラフを表示するプログラムを作る. ループの入れ子で,棒グラフの表示を行う

例題3:棒グラフ #include "stdafx.h" #include <math.h> int _tmain() { int i; int j; int ch; int a[]={6,4,7,1,5,3,2}; for (i=0; i<7; i++) { for (j=0; j<a[i]; j++) { printf("*"); } printf("\n"); ch = getchar(); return 0; 配列の宣言 配列からの 読み出し

棒グラフを書く 実行結果の例 ****** **** ******* * ***** *** **

多重ループ ループを入れ子構造にする。 外側のループ 内側のループ i j 1 2 m-1 n-1 i=0 1 2 m-1 n-1 ループを入れ子構造にする。 i=0 外側のループ for (i=0 ; i < n ;i++) { } 内側のループ for (j=0 ; j < m ;j++) { } i=1 i=n-1