C言語ファイルの読み書き-バイト、行+読み書きによる最後の行の2パスの解決方法

3743 ワード

テキスト・フロー
テキストストリーム、すなわち、ファイルをテキストモードで読み込むとよく言われていますが、テキストストリームのいくつかの特徴は、異なるシステムで異なる可能性があります.その1つがテキスト行の最大長です.標準規定では、少なくとも254文字が許可されています.別の異なる特性は、テキスト行の終了方法です.たとえば、Windowsシステムでは、テキストファイルの規則は1つの戻り文字と1つの改行文字で終わります.ただし、Linuxでは改行文字の末尾は1つしか使用されません.
標準Cは、テキストを0文字以上に配置し、後に終了を表す改行記号()を付けます.これらのテキスト行の外在的な表現形式とこの定義とは異なるシステムでは、ライブラリ関数は外部形式と内部形式の間の翻訳を担当します.例えば、Windowsシステムでは、出力時にテキストの改行記号が1対のリターン/改行記号に書かれます.入力時にテキストのリターンキャラクタが破棄されます.このようなテキストの外部形式を考慮せずにテキストを操作する能力は、移植可能なプログラムの作成を簡素化する.
バイナリフロー
バイナリ・ストリームのバイトは、プログラムに基づいて作成された形式でファイルに完全に書き込まれ、ファイルまたはデバイスから読み込まれた形式でプログラムに完全に読み込まれ、変更されません.このタイプのストリームは非テキストデータに適していますが、I/O関数でテキストファイルの行末文字を変更したくない場合は、テキストファイルに使用することもできます.
C言語はこの2つのファイルを扱う際に区別されず,いずれも文字ストリームとしてバイトで処理する.
我々のプログラムでよく見られるテキスト方式でファイルを開くこととバイナリ方式でファイルを開くことは改行文字の処理にのみ現れる.
たとえば、Windowsではファイルの改行はr、Linuxでは改行は
ファイルをテキストで開くと、読み書きしたWindowsファイルの改行文字rがメモリに読み替えられ、Windowsの下にファイルを書き込むと、rに置き換えられてファイルに書き込まれます.ファイルをバイナリで開く場合、rとの間の変換は行われません.Linuxの下の改行文字があるので、テキストファイルとバイナリファイルの違いはありません.
ファイル読み書き関数
1.文字によるファイルの読み書き:fgetc()、fputc()
2.行に従ってファイルを読み書きする:fputs(),fgets()
3.ブロックに従ってファイルを読み書きする:fread()、fwrite()
4.フォーマットに従ってファイルを読み書きする:fprintf()、fscanf()
5.ランダムな場所でファイルを読み書きする:fseek()、ftell()、rewind()
文字でファイルを読み書きする
#include
#include
#pragma pack(show)



void test01()
{
	int i;
	char ch;
	char buff[] = "hello world";
	FILE* f_read;
	//   
	FILE* f_write = fopen("./test1.txt","w");


	if(f_write == NULL)
		return;

	
	for(i = 0;i < strlen(buff);i++)
	{
		fputc(buff[i],f_write);
	}
	fclose(f_write);

	//   
	//FILE* f_read = fopen("./test1.txt","r");
	f_read = fopen("./test1.txt","r");
	if(f_read == NULL)
		return;
	while((ch = fgetc(f_read)) != EOF)
	{
		printf("%c",ch);
	}
	fclose(f_read);
}


int main()
{
	test01();

	return 0;
}
実行結果:
hello world
同时にcファイルの兄弟ディレクトリの下にtest 1が表示されます.txtのファイル
行ごとにファイルを読み書きする
#include
#include
#pragma pack(show)



void test01()
{
	int i;
	char ch;
	char temp[1024] = {0};
	
	FILE* f_read;
	//   
	FILE* f_write = fopen("./test2.txt","w+");
	char* buff[]=
	{
		"     
", "
", "
", "
" }; if(f_write == NULL) return; for(i = 0;i < 4;i++) { fputs(buff[i],f_write); } fclose(f_write); // //FILE* f_read = fopen("./test1.txt","r"); f_read = fopen("./test2.txt","r"); if(f_read == NULL) return; while(!feof(f_read)) { fgets(temp,1024,f_read); printf("%s",temp); } fclose(f_read); } int main() { test01(); return 0; }
実行結果:
日当午汗滴禾下土谁知盘中华粒皆辛苦粒皆辛苦粒皆辛苦请按任意钥匙继续.
最後の行が2回読み込まれたことに気づきました.どうしたんですか.
 
ここでhには、以下の定義が見られる.
1 2 3 4 5 6 7 8 9 #define EOF (-1) #define _IOEOF 0x0010 #define feof(_stream) ((_stream)->_flag & _IOEOF) int   c; while (! feof (fp)) {      c =  fgetc (fp);      printf ( "%X
"
, c); }
なぜなら、最後の文字を読んだ後もfp->flagは_に設定されていないからです.IOEOFなので、feof()はファイルの最後を検出しませんでした.fgetc()を再呼び出して読み取り操作を実行するまで、feof()はファイルの最後を検出できません.
参照先:https://baike.baidu.com/item/feof/10942186?fr=aladdin
次のように改善されました.
fgets(temp,1024,f_read);     while(!feof(f_read))     {         printf("%s",temp);         fgets(temp,1024,f_read);              }