Index

HOME > プログラムTOP > C++



C++の壺・ファイル篇1

 C++の基本テクニックのTipsです。ファイル篇1では、C言語のファイルの読み込みと書き出しの方法を扱います。オブジェクトを利用したC++のファイル入出力は2で扱います。
ページ項 目内 容
ファイル篇1 Cのファイル処理: FILE構造体、fopen関数、fclose関数
入出力関数: fgets関数、fputs関数、fprintf関数、fscanf関数
更新モード: rewind関数
バイナリモード: テキストモードとバイナリモード
ファイル篇2 C++のファイル処理: ifstreamクラス、ofstreamクラス、openメンバ、closeメンバ
入出力処理: putメンバ、getメンバ、is_openメンバ、getlineメンバ
モードフラグ: オープンモードフラグ
ファイル篇3 バイナリ・アクセス: fwriteとfread関数 / writeとreadメンバ
ランダム・アクセス: fseekとftell / fgetposとfsetpos / seekp,seekg,tellp,tellg
エラー/EOF検知: feofとferror関数 / perrorとclearerr関数 / iostateフラグ

sasaraan programming

Exposition

●Cのファイル処理

 C言語では、ファイルを扱う時は、"ファイルポインタ" という特殊な型を利用します。これは、ファイルにアクセスした際、その時々のアクセス情報を格納する構造体(FILE構造体)で、ポインタ宣言をしてから使用します。
@ ファイルポインタの宣言: FILE構造体
A ファイルを開く: fopen関数
B データの入出力: 読み込み(fgets, fgetc, fscanf)/ 書き出し(fputs, fputc, fprintf)
C ファイルを閉じる: fclose関数
 また、ファイルポインタを使う時は必ず fopen関数で開き、使い終わったら fclose関数で閉じる必要があります。fopen と fclose 関数の仕様は次のようになっています。
fopen function
・書式FILE *fopen(const char *file, const char *mode)
・機能: ファイルを開く
・引数: file...ファイル名、 mode...アクセスモード
・戻り値: 成功時...FILE構造体へのポインタ, 失敗時...NULL
・要件: stdio.h のインクルード
fclose function
・書式int fclose(FILE *fp)
・機能: ファイルを閉じる
・引数: fp...FILE構造体へのポインタ
・戻り値: 成功時...0, 失敗時...EOF
・要件: stdio.h のインクルード
 fopen関数の引数にあるアクセスモードでは、ファイルのアクセス制限を指定します。これには以下のようなものがあります。また、fclose関数の戻り値の EOF は、本来はファイルの終端 (End Of File) を表す値ですが、今回のようにエラー値としても用いられることがあります。
モード機 能 ファイルがある時ファイルがない時
r 読み込み(read)正常処理エラー(NULL)
w 書き出し(write)既存データを破棄新規作成
a 追加書き出し(append)既存データに追加新規作成
r+ 読み込みと書き出し正常処理エラー(NULL)
w+ 読み込みと書き出し既存データを破棄新規作成
a+ 読み込みと追加書き出し既存データに追加新規作成
#include <stdio.h>

// Cのファイル処理の手順
void main()
{
    FILE *fp;                                // ファイルポインタの宣言
    fp = fopen("sample.txt", "w");  // ファイルを開く
    ...                                         // ファイル入出力
    fclose(fp);                              // ファイルを閉じる
}	

●入出力関数

 実際にファイルの読み書きを行う関数には様々なものが用意されています。その中に、fputs と fgets関数があります。
 fgets関数は、指定した文字数(バイト数)をファイルから読み出して変数に格納します。fgets関数を使用すると、ファイルポインタは次の文字へ移動しますので、連続して使用することにより、ファイルの中身すべてを読み取ることができます。一度の読み込みは、改行文字 ('\n') が現れるか、ファイルの終端に達するか、あるいは読み込んだ文字数が n -1 になるまで続きます。なお、取得した文字列には NULL文字が付加されます。
 一方、fputs関数は、指定した文字列をまとめてファイルに書き出す機能を持ちます。
fgets function
・書式char *fgets(char *str, int n, FILE *fp)
・機能文字列を指定文字数分ファイルから読み込む
・引数str...格納場所, n...最大文字数, fp...FILE構造体へのポインタ
・戻り値文字列へのポインタ(ファイル終端かエラー時はNULL)
・要件stdio.h のインクルード
fputs function
・書式int fputs( const char *str, FILE *fp)
・機能文字列をファイルへ書き出す
・引数str...出力する文字列, fp...FILE構造体へのポインタ
・戻り値成功時...0以上、失敗時...EOF
・要件stdio.h のインクルード
#include <stdio.h>
#include <stdlib.h>    // exit使用
#include <conio.h>   // getch使用

// ファイルへの書き出し
void main() 
{
    char fname[256] = "sample.txt";
    char s[256] = "Hello World !";

    FILE *fp;
    fp = fopen(fname, "w");
    if (fp == NULL) {
        printf("ファイルを開けません!");
        exit(1);      // プログラム終了
    }

    fputs(s, fp);
    fclose(fp);

    if (getch()) return 0;
}	
#include <stdio.h>
#include <stdlib.h>    // exit使用
#include <conio.h>   // getch使用

// ファイルの読み込み
void main() 
{
    char fname[256] = "sample.txt";
    char s[256];

    FILE *fp;
    if ((fp=fopen(fname,"r"))==NULL) {
        printf("ファイルを開けません!");
        exit(1);        // プログラム終了
    }
    while (fgets(s, 256, fp) != NULL) {
        printf("%s", s);    // 画面出力
    }
    fclose(fp);

    if (getch()) return 0;
}	
 ファイル入出力には、これ以外にも、fgetc (一文字づつ読み込み)、fputc (一文字づつ書き出し)、fscanf (書式付きで読込)、fprintf (書式付で書き出し)などがあります。いずれも、使用すると、ファイルポインタが移動します。
fprintf function
・書式int fprintf(FILE *fp, const char *format [ , arg, ... ] )
・機能文字列に書式を付けてファイルに書き出す
・引数fp...FILE構造体へのポインタ、format...書式付き文字列、arg...引数
・戻り値出力したバイト数 (エラー時は負の値を返す)
・要件stdio.h のインクルード
fscanf function
・書式int fscanf(FILE *fp, const char *format [ , arg, ... ] )
・機能文字列に書式を付けてファイルから読み込む
・引数fp...FILE構造体へのポインタ、format...書式付き文字列、arg...引数
・戻り値出力したバイト数 (エラー時・終端時は EOF を返す)
・要件stdio.h のインクルード
 fprintf関数と fscanf関数で用いられる書式付文字列 (format) は、printf関数の仕様に準じています。以下に仕様の主要部分を掲載しておきます。fscanf の引数は格納場所を示すアドレスとなりますので注意してください。
【printf / scanf format spec】
format [flags][width][precision]['h' | 'l']type ([]は省略可)
・flags'-'...左詰め / '+'...符号付 / '0'...0詰め / ' '(空白)...正数に空白を付加 /
'#'...typeが 'o' の時は 0を、'x' の時は 0xを、'f' 'e' の時は小数点を付加
・width桁数(文字数)を数字で指定 ('*' : 引数で指定)
・precision小数点以下の桁数(精度)を '.' と数字で指定 ('*' : 引数で指定)
・'h' or 'l''h'...short型として解釈 / 'l'...long型として解釈
・type'd'...十進値 / 'o'...八進値 / 'x'...十六進値 / 'u'...符号なし十進値 /
'f'...浮動小数点(float, double) / 'e'...指数値 / 'p'...ポインタ(アドレス) /
'c'...文字(char) / 's'...文字列 / '%'...'%' 自身

●更新モード

 ファイルのアクセスモードで、r+, w+ a+ など、"+" が付いているもの(更新モード)は読み書きの両方が可能ですが、どちらかの操作を行うと、ファイルポインタが移動している可能性があり、次に使用する時に思った位置に読み込み、または書き出しができません。そのため、操作を行う前に、ファイルポインタを先頭に戻しておく必要があります。これには、rewind関数を利用することができます。他にも、fflush、fseek, fsetpos などの関数を使用することができます。
rewind function
・書式void rewind(FILE *fp);
・機能ファイルポインタを先頭に戻す (エラー情報とEOF情報もクリアする)
・引数fp...FILE構造体へのポインタ
・戻り値なし
・要件stdio.h のインクルード
#include <stdio.h>
#include <conio.h>   // getch使用

// ファイルの更新モード
void main() 
{
    FILE *fp;
    char fname[256] = "sample.txt";
    char s1[100] = "Hello World !";
    char s2[100] = "Hello C++ !!";
    char s3[256];

    fp = fopen(fname, "w+");                    // ファイルを "w+"モード で開く
    if (fp != NULL) {
        fprintf(fp, "%s\n%s\n", s1, s2);      // 改行を付けてファイルへ書き出し
        rewind(fp);                                   // ファイルポインタを先頭に戻す
        while (fgets(s3, 256, fp) != NULL) { 
            printf("%s", s3);                         // ファイルを読み込んで画面出力
        }
        fclose(fp);
   }

    if (getch()) return 0;
}	

●バイナリモード

 Cのファイル操作では、特に指定がなければテキストモードでファイルを扱うことになります。それとは別に、バイナリモードというモードも存在します。両者の違いは次のようなものです。
モード cr+lf の読み込み '\n' の書き出し '1a' の処理
テキストモード'\n' に自動変換cr+lf に自動変換ファイルの終端
バイナリモードそのまま読み込むそのまま書き出しそのまま処理
 通常、ファイルでは改行は cr + lf (0d : キャリッジリターン + 0a : ラインフィード) で表現します。テキストモードでは、C言語の改行表現である '\n' を、読み書き時に自動的にこれらに変換します。一方、バイナリモードではこれらのコードをそのまま扱います。
テキストモードバイナリモード
r, w, a rb, wb, ab  (読み / 書き / 追加 +バイナリモード)
r+ r+b, rb+  (読み込み+更新+バイナリモード)
w+ w+b, wb+  (書き出し+更新+バイナリモード)
a+ a+b, ab+  (追加書き出し+更新+バイナリモード)
 バイナリモードにするには、アクセスモードに "b" を付加します。(バイナリモードの指定は、OS が Windows の時のみ有効です。)

www.sasaraan.net

(c) morijoh