書き込み


ファイルに書き込む

前回、標準入出力について学習しました
この章では、いよいよデータをファイルに保存したいと思います

といっても、前回に「標準出力に書き込み」ということをやっています
前回でやったfputc()関数などで、stdoutをファイルポインタに変えればよいだけです

ファイルを開くときに、書き込みモードで開くには"w"でしたね
foepn()関数のファイルモードを"w"で開き
そのファイルポインタに対してデータを出力すればよいのです
#include <stdio.h>
#include <stdlib.h>

int main() {
        char FileName[124];
        FILE *save;

        printf("ファイル名を入力してください>");
        scanf("%s" , FileName);

        if ((save = fopen(FileName , "w")) == NULL) {
                printf("ファイルが開けませんでした");
                exit(1);
        }
        fputs("Kitty on your lap" , save);
        fclose(save);

        return 0;
}
これが、簡単にまとめたファイルへの書き込みプログラムです
入力したファイル名でストリームにファイルを読み込みます
書き込みモードで開くのでファイルが無ければ作成され、あれば内容が破壊されます

ファイルに書き込まれるのは、fputs()関数でしたいされている文字列です
文字定数として、一文字づつ書き込みたい場合はfputc()関数を使えば良いですね

前回までの内容と組み合わせれば、ファイルのコピーを取るプログラムも作成できます
まず、読み込みモードでファイルを開き、変数にその内容を保存します
次に書き込みモードでファイルを開き、変数の内容を保存するという流れになります
#include <stdio.h>
#include <stdlib.h>

int main() {
	char fileName[128] , saveName[128];
	int text;
	FILE *load , *save;

	printf("ファイルをコピーします\nファイル名を入力してください>");
	scanf("%s" , fileName);

	if ((load = fopen(fileName , "r")) == NULL) {
		printf("ファイルを開けませんでした");
		exit(1);
	}

	printf("コピーファイル名を入力してください\n存在する場合は内容を破壊します>");
	scanf("%s" , saveName);
	
	if ((save = fopen(saveName , "w")) == NULL) {
		printf("書き込みに失敗しました");
		exit(1);
	}

	while(1) {
		text = fgetc(load);
		if(!feof(load)) fputc(text , save);
		else break;
	}

	fclose(load);
	fclose(save);
	return 0;
}
前回stdoutに出力していた部分を、書き込みようで開いたファイルに出力することによって
簡単にファイルに保存することができますね
上書きではなく、追加したければファイルモードを"a"で開けば良いだけです


fprintf()とfscanf()

これまで学習してきたファイル関数は、やや低レベルの操作が中心でした
ですがC言語では、さらに一括したファイル操作が可能な関数があります

これまで、コンソールに対してprintf()関数やscanf()関数で入出力を行ってきました
この作業は、もうすでに自信があると思います
コンソールとファイルの読み書きの操作が類似していることも前回学習しましたね
ではコンソールの入出力のようにファイルを操作できれば便利だと思いませんか?

じつは、まさにprintf()とscanf()関数のストリーム版があるのです
それがfprintf()とfscanf()関数です

int fptinf(FILE *ストリーム , const char *フォーマット , ...);

fprintf()は第一引数に有効なストリームを指定します
第二引数以降はprintf()関数と同様です
標準出力の代わりに、データをストリームに書き出す関数です

int fscanf(FILE *ストリーム , const char *フォーマット , ...);

fprintf()関数と同様に、ストリームには有効なファイルストリームを指定します
以降はscanf()関数と同じです
標準入力の代わりに、ストリームからデータを読み出す関数です

この二つの関数を使うことで、これまでコンソールに行ってきた処理と同じ感覚で
ファイル操作を行うことが可能です
#include <stdio.h>
#include <stdlib.h>

int main() {
        char fileName[128] , text[1024];
        FILE *load;

        printf("ファイル名を入力してください>");
        scanf("%s" , fileName);

        if ((load = fopen(fileName , "r")) == NULL) {
                printf("ファイルが開けませんでした");
                exit(1);
        }

        while (fscanf(load , "%s" , text) != EOF) printf(text);

        fclose(load);
        return 0;
}
fscanf()関数はエラーが発生するか、最初の変換の前にファイルストリームの終端を検出するとEOFを返します
scanf()関数と同じ動作をするので、スペースや改行を発見するとそこで読み込みを止めてしまいます
さらに、このプログラムを実行するとわかると思いますが
こうして、whileで繰り返してファイルを読み込んでもやはり改行などは表示されません

fprintf()関数はストリームにデータを出力します
この関数も、fscanf()同様にprintf()関数のストリーム版です
#include <stdio.h>
#include <stdlib.h>

int main() {
	char fileName[128] , *text = "Kitty on your lap";
	FILE *save;

	printf("ファイル名を入力してください\n");
	printf("ファイルが存在する場合は内容を破壊します>");
	scanf("%s" , fileName);

	if ((save = fopen(fileName , "w")) == NULL) {
		printf("ファイルが開けませんでした");
		exit(1);
	}

	fprintf(save , text);

	fclose(save);
	return 0;
}
fprintf()やfscanf()関数で、ストリームを標準入出力に変えることによって
printf()やscanf()関数と同様に働きを持たせることができます
つまり、printf()やscanf()の対象がストリームになっただけの関数なのです

次のプログラムは、ストリームを標準入出力に指定しています
#include <stdio.h>

int main() {
        char str[1024];

        fprintf(stdout , "入力してください>");
        fscanf(stdin , "%s" , str);

        printf(str);
        return 0;
}
ファイル操作時に、どの関数がもっとも効果的か判断してください


int fprintf( FILE *stream, const char *format [, argument ]...);

書式化したデータをストリームに出力します

ヘッダ - stdio.h
stream - 出力するFILE構造体のポインタ
format - 書式制御文字列を指定します
argument - 引数オプション、値のリストを指定します

戻り値 - 出力したバイト数を返します

int fscanf( FILE *stream, const char *format [, argument ]... );

ストリームから書式化したデータを読み込みます

ヘッダ - stdio.h
strean - 有効なFILE構造体のポインタを指定します
format - 読み出すデータの書式制御文字列を指定します
argument - 読み込んだデータを保存するためのポインタを指定します

戻り値 - 入力されたデータの個数。エラーが発生するか、最初の変換の前にファイルストリームの終端を検出するとEOF



前のページへ戻る次のページへ