プログラミング演習 土曜日 (Q 組 ) 主なテーマ 標準入出力とファイル処理 (8 章 ) 1
ストリームの概念 8.1 標準入出力 (C++) C++ では データの入出力を ストリーム という概念で操作する ストリームはデータを入出力処理し また 入出力に伴う 状態 を設定 / 保持する 例 : 現在 ファイルの何文字目を読み書きしているか などの情報 論理デバイス 物理デバイス 入力ストリーム プログラム cin cout 出力ストリーム 5
書式の状態 C++ でデータを出力するとき 何も指定しないとデフォルトルールによって 無難な形で表示される 特別な形式で出力したい場合 ( 例 : 整数を 16 進数で表示したい ) 書式フラグを指定し データを書式化する 書式フラグは マニピュレータ ( 標準演算子 ) として 利用する 6
基本操作 マニピュレータ (p.63 の表 8.3) 基本的な書式制御をするもの 数値に関する書式制御をするもの 入出力に関する書式制御をするもの 分類 引数を必要とするもの #include <iomanip> 引数を必要としないもの を宣言する必要がある 7
マニピュレータ showbase noshowbase showpoint noshowpoint uppercase nouppercase dec hex oct left right fixed scientific flush ends endl unitbuf nounitbuf skipws noskipws 表 8.3 良く利用されるマニピュレータ 説明 基数を表す接頭語を表示する 基数を表す接頭語を表示しない 常に小数点を表示する 小数部があるときだけ小数点を表示する 16 進数表示や科学的表示に大文字を使う 16 進数表示や科学的表示に小文字を使う 基数を 10 進にする 基数を 16 進にする 基数を 8 進にする 左寄せして右には埋め草する 右寄せして左には埋め草する 浮動小数点を 10 進記法で表示する 浮動小数点を科学的記法で表示する バッファをフラッシュする ナルを出力し, バッファをフラッシュする 改行を出力し, バッファをフラッシュする 出力操作毎にバッファをフラッシュする 通常のバッファフラッシュ操作に戻す 入力オペレータで空白類文字を読み飛ばす 入力オペレータで空白類文字を読み飛ばさない マニピュレータ setfill(int) setprecision(int) setw(int) setbase(int) ws 空白類文字を食う 8 説明 埋め草の文字を指定する 有効桁数を指定する 全体の文字数を指定する 整数表示の基数を指定する 引数を必要とするもの #include <iomanip> を宣言する必要がある
ソースコード 23 001 002 003 004 005 006 007 #include <iostream> #include <iomanip> int main ( void ) { std:: cout << std:: hex << std:: setw(8) << std:: setfill ( # ) << 1234 << std:: endl; return 0; 1iostreamをインクルード 2iomanipをインクルード 3 出力演算子 (<<) を用いる 4 改行 1 ストリームを使うためには ストリームオブジェクトを宣言しなければならない #include <iostream> を宣言することで下記の標準ストリームを使用可能 標準ストリーム istream cin; 標準入力 ( 通常はキーボード ) istream cout; 標準出力 ( 通常はディスプレイ ) istream cerr; 標準エラー出力 ( バッファリングなし ) istream clog; 標準エラー出力 ( バッファリングあり ) 9
ストリームの状態 ストリームは現在の自身の状態を表現するエラー状態値をもっている エラー状態は メンバ関数で知ることができる メンバ関数説明 eof() fail() bad() good() clear() 利用例 if (cin.fail()) ~ ストリームが EOF(end of file) を検出したら true I/O 操作が失敗したら true ストリームが破損したら true ストリームが良好なら true ストリームの全ての状態を良好状態に設定する 10
8.2 ファイル入出力 (C++) ファイルとの入出力を行うときは ファイルストリームを用いる #include <fstream> を宣言する 必要に応じて3つのファイルストリームオブジェクトを宣言する ifstream fin; ofstream fout; fstream fboth; ifstream 入力 プログラム ofstream 出力 ファイル fstream 入出力 11
ソースコード 24 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 #include <fstream> #include <string> int main (void) { std :: ifstream infile; std :: ofstream outfile; infile.open( file1 ); outfile.open( file2 ); std :: string s; while( getline(infile,s)){ outfile << s << std :: endl; infile.close( ); outfile.close( ); return 0; 1fstream をインクルード 2 入力ストリームを宣言 3 出力ストリームを宣言 4 入力ストリームをオープン 5 出力ストリームをオープン 6 入力ストリームから文字列を入力して string 型の s に格納 7 入力ストリームをクローズ 8 出力ストリームをクローズ 課題 : ソースコード 24 を実行して 11 行目の処理を確認しなさい 12
モードの設定 ファイルを開く際には, 第二引数にモードを指定する モードはファイル毎の値であり, ファイルを開くたびにセットする モード 説明 in out app ate trunc binary 入力用に開く出力用に開く書き出しのたびにファイルの終りまで進んで書き出す開くときにファイルの終りまで進む開くときに既存のファイル内容を破棄するバイナリモードで開く 利用例 std :: ofstream outfile; outfile2.open ( filename, ofstream:: out ofstream :: app); 13
ソースコード 25 001 002 003 004 005 006 007 008 009 010 011 012 #include <fstream> int main (void){ std :: ifstream file; file.open( file1 ); // file1について, ある処理を行う file.close( ); file.clear( ); file.open( file2 ); //file2について, 別の処理を行う file.close( ); return 0; 課題 : 内容の異なるテキストファイ ルを2つ準備し 画面に出力するとともに ファイルにも出力するプログラムを作成しなさい 1fstream をインクルード 2 ストリームの状態をクリア 14
8.3 string 入出力 (C++) 文字列の入出力を行うときは 文字列ストリームを用いる #include <sstream> を宣言する 文字列ストリームを使うときは 次のクラスを用いる クラス名 istringstream ostringstream stringstream 説明 string からの入力用,istream の派生クラス string への出力用,ostream の派生クラス string 入出力用,iostream の派生クラス データ ( 変数 ) istringstream 入力 ostringstream 出力 stringstream 入出力 string オブジェクト 15
8.4 標準入出力 (C) printf 関数による書式変換標準出力 記述例 :printf( 書式文字列, 変換対象引数... ); 書式文字列 % フラグフィールド幅精度長さ修飾子変換指定子 使用例 出力結果 printf("%d %f %c", 2*10, 10.0/5.0, '1'); 20 2.000000 1 printf("%+5.2f", 10.0/5.0); +2.00 printf("%a", 1.0/10); 0x1.999999999999ap-4 printf("system %s Engineering", "Design"); System Design Engineering 16
8.4 標準入出力 (C) scanf 関数による書式変換標準入力 記述例 :scanf( 書式文字列, 変換対象引数... ); 注意事項 引数には変数へのポインタを与える 浮動小数点の基本型はfloat 型である 入力文字列 使用例 20 2.000000 1 scanf("%d %f %c", &i, &f, &c); +2.00 scanf("%+5.2lf", &d); 0x1.999999999999ap-4 scanf("%la", &d); System Design Engineering scanf("system %s Engineering", s); 17
8.4 標準入出力 (C) 書式変換を伴わない出力関数 puts, fputs 関数による標準出力 puts( 出力文字列 ); 記述例 fputs( 出力文字列, 出力先ファイル識別子 ); 使用例 puts("hello n"); fputs("hello n", stdout); 書式変換を伴わない入力関数 fgets, fgets 関数による標準入力 gets( 文字列変数 ); 記述例 fgets( 文字列変数, 最大文字数, 入力元ファイル識別子 ); 使用例 char s[100]; gets(s); fgets(s, 100, stdin); 18
8.5 ファイル入出力 (C) ファイルをFILE 構造体として取り扱う関数を用いる ファイル構造体の型は <stdio.h> 内で宣言されている ファイルポインタの定義例 FILE fp ; 操作手順 1. ファイル処理のオープン 2. ファイルの読み書き 3. ファイル処理のクローズ 19
ファイル処理のオープン 関数の型定義 FILE *fopen(char *filename, char *mode) モード 記述例 ファイル処理のクローズ 関数の型定義 記述例 ファイルの読み書き w: 新規作成,a: 新規追加,r: データ読み出し r+, w+, a+ : ランダムアクセス rb, wb, ab: バイナリアクセス fp=fopen( data.txt, r ); int fclose(file *fp) i = fclose(fp); 関数の型定義 int fprintf(file *fp,char *format,..... ) 記述例 fprintf(fp, Hello %d n,i); 関数の型定義 int fscanf(file *fp,char *format,..... ) 記述例 fscanf(fp, %d,&i);
ソースコード 26 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 #include <stdio.h> int main(void) { int age; float height; char name[40]; FILE *fp; if ((fp = fopen("personal.txt","w")) == NULL){ fprintf(stderr, File open failed. n"); return 1; while(1){ printf( Input age height name: n"); if (scanf("%d %f %s",&age,&height,name)<3) break; fprintf(fp,"%d %f %s n",age,height,name); fclose(fp); return (0);
ソースコード 26 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 #include <stdio.h> int main(void) { int age; float height; char name[40]; FILE *fp; if ((fp = fopen("personal.txt","w")) == NULL){ fprintf(stderr, File open failed. n"); return 1; while(1){ printf( Input age height name: n"); if (scanf("%d %f %s",&age,&height,name)<3) break; fprintf(fp,"%d %f %s n",age,height,name); fclose(fp); return (0);
ソースコード 26 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 #include <stdio.h> int main(void) { int age; float height; char name[40]; FILE *fp; if ((fp = fopen("personal.txt","w")) == NULL){ fprintf(stderr, File open failed. n"); return 1; while(1){ printf( Input age height name: n"); if (scanf("%d %f %s",&age,&height,name)<3) break; fprintf(fp,"%d %f %s n",age,height,name); fclose(fp); return (0); 1stdio.h をインクルード 2 ファイルポインタを定義 5 ファイルをクローズ 3 ファイルをオープン 4 ファイルにデータを書き込む
8.6 文字列入出力 文字列を対象として書式指定入出力を行う関数も用意されている 第一引数に文字配列へのポインタを渡すこと以外, 使い方は同じである 関数の型定義 int sprintf(char *sp, char *format,...) 記述例 sprintf(sp, "Hello %d n", i); 関数の型定義 int sscanf(char *sp, char *format,...) 記述例 sscanf(sp, "%d", &i); 24
練習問題 8.1~8.7 演習問題 以上は自習も含めてすべて行っておくこと 提出 : 演習問題 1. 入力ファイル名と出力ファイル名を指定し 入力ファイルの内容を出力ファイルにコピーするプログラムを作成しなさい このとき 入力ファイル名に関してエラー処理を加えなさい 2. 入力ファイルに氏名 年齢 性別を複数人分入力し 入力ファイルの内容を年齢順に並び変えて出力ファイルにコピーするプログラムを作成しなさい 25