1. ファイルの開閉
1.1fopen
FILE * fopen ( const char * filename, const char * mode );
- fopen の機能は、ファイルを開くことです。
- fopenのヘッダファイルは<stdio.h>、第1引数はファイル名、第2引数はメソッド(ファイルの開き方)で、ファイルのオープンに成功するとファイル情報へのポインタを返します。オープンに失敗した場合は NULL を返します。
- ファイルは次のように開かれます。
ファイルの使用 | 意味 | 指定したファイルが存在しない場合 |
---|---|---|
"r" (読み取り専用) | データを入力するには、既存のテキスト ファイルを開きます | うまくいかない |
"w" (書き込みのみ) | データを出力するには、テキスト ファイルを開きます | 新しいファイルを作成する |
“a”(追加) | テキスト ファイルの末尾にデータを追加する | 新しいファイルを作成する |
"rb" (読み取り専用) | データを入力するには、バイナリ ファイルを開きます | うまくいかない |
"wb" (書き込みのみ) | データを出力するには、バイナリ ファイルを開きます | 新しいファイルを作成する |
“ab”(追加) | バイナリ ファイルの最後にデータを追加する | うまくいかない |
"r+" (読み書き) | 読み書き用にテキスト ファイルを開く | うまくいかない |
"w+" (読み書き) | 読み書き用の新しいファイルを作成する | 新しいファイルを作成する |
"a+" (読み書き) | ファイルの末尾で読み書きできるようにファイルを開きます | 新しいファイルを作成する |
"rb+" (読み取りと書き込み) | 読み書き用にバイナリファイルを開く | うまくいかない |
"wb+" (読み書き) | 読み書き用の新しいバイナリ ファイルを作成する | 新しいファイルを作成する |
"ab+" (読み取りと書き込み) | ファイルの最後で読み書きするためにバイナリ ファイルを開きます | 新しいファイルを作成する |
(1) ここでの入出力はメモリの観点からのものであり、入力はファイルからメモリへ、出力はメモリからファイルへです。
(2) テキストファイルとは?再びバイナリファイルとは何ですか?
データはバイナリ形式でメモリに格納され、変換せずに外部ストレージ (ファイル) に出力すると、バイナリ ファイルになります。外部ストレージ(ファイル)にASCIIコードで保存する必要がある場合は、変換してから保存する必要があります。ASCII 文字の形式で保存されたファイルは、テキスト ファイルです。
(3) 非常に多くの開始メソッドを見ないでください。C で一般的に使用されるのは "r"、"w"、"rb"、および "wb" だけです。
1.2閉じる
int fclose ( FILE * stream );
- fclose の機能は、ファイルを閉じることです。
- (1) ストリームとは データの入出力の媒体だと思います。画面へのデータの出力、ファイルへの出力、およびファイルまたはキーボードからのデータの入力には、すべてストリームの助けが必要です。
(2) 通常、ストリーミングせずにデータを印刷してデータを入力するのはなぜですか? C 言語プログラムが実行されている場合、デフォルトで次の 3 つのストリームが開かれます: stdin: 標準入力ストリーム (キーボード); stdout: 標準出力ストリーム (画面); stderr: 標準エラー ストリーム (画面)。
(3) したがって、ファイルの入出力を使用する場合はストリームが必要です。ファイルからデータを読み書きするときは、ストリームを経由する必要があるため、ストリームから直接読み書きできます。ストリームはファイル ポインターで、型は FILE* です。このストリームを介して、データをメモリに入力し、データをファイルに出力できます。 - ファイルが正常に閉じられた場合は 0 を返し、失敗した場合は EOF を返します。また、ポインターを NULL に設定することも忘れないでください。
例子
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}
结果
2. ファイルの順次読み書き
2.1 fgetc と fputc
2.1.1fputc
int fputc ( int character, FILE * stream );
- fputc の機能は、ストリームに文字を出力することです。fputc は、すべての出力ストリーム (stdout やファイルなどを含む) で機能します。
- fputc のヘッダファイルは <stdio.h> です。最初のパラメーターは入力する文字で、2 番目のパラメーターは出力ストリームへのポインターです。出力が成功した場合は出力文字が返され、失敗した場合は EOF が返されます。
例子
まずファイルを作成します。
int main()
{
FILE* pf = fopen("test.txt", "w");//我们要写入文件,以写的形式打开
if (NULL == pf)
{
perror("fopen");
return 1;
}
int i = 0;
for (i = 'a'; i <= 'z'; i++)
{
fputc(i, pf);//文件里面有指示器,当输入一个字符时,指示器指示下一个位置。
}
fclose(pf);
pf = NULL;
return 0;
}
结果
2.1.2fgetc
int fgetc ( FILE * stream );
- fgetc の役割は、ストリームから文字を読み取ることです。fgetc は、すべての入力ストリーム (stdin やファイルなどを含む) で機能します。
- fgetc のヘッダー ファイルは <stdio.h> です。パラメータは、入力ストリームへのポインタです。読み取りに成功した場合は読み取った文字の ASCII コード値を返し、読み取りが終了または失敗した場合は EOF を返します。
例子
int main()
{
FILE* pf = fopen("test.txt", "r");//以读的形式打开文件
if (NULL == pf)
{
perror("fopen");
return 1;
}
//读取文件
int ch = 0;
while (ch = fgetc(pf))//当读取一个字符后,指示器指向下一个字符
{
printf("%c ", ch);
}
fclose(pf);
pf = NULL;
return 0;
}
结果
2.2 fget と fput
2.2.1fputs
int fputs (const char * str, FILE * stream);
- fputs が行うことは、文字列をストリームに書き込むことです。fputs はすべての出力ストリームに適用されます。
- fputs のヘッダファイルは <stdio.h> です。最初の引数はストリームに書き込まれる文字列へのポインターで、2 番目の引数は出力ストリームへのポインターです。書き込みが成功した場合は負でない数値を返し、失敗した場合は EOF を返します。
- fputs は文字列をストリームに書き込み、'\0' に遭遇すると停止しますが、最後の '\0' は書き込まれません。
例子
int main()
{
FILE* pf = fopen("test.txt", "w");//以"w"的形式打开,如果先前文件有内容就会被初始化
if (NULL == pf)
{
perror("fopen");
}
fputs("hello world\n", pf);
fputs("welcome", pf);
fclose(pf);
pf = NULL;
return 0;
}
结果
2.2.2fgets
char * fgets ( char * str, int num, FILE * stream );
- fgets の役割は、ストリームから文字列を読み取ることです。fgets は、すべての入力ストリームで機能します。
- fgets のヘッダー ファイルは <stdio.h> です。最初のパラメーターは配列へのポインターで、ストリームから読み取った文字列を格納するために使用され、2 番目のパラメーターはストリームから読み取った文字数です (実際には num-1 文字を読み取り、最後の文字は \ のために残されます)。 0)、3 番目のパラメーターは入力ストリームへのポインターです。読み込みに成功した場合は str を返し、ファイルの最後まで読み込むか読み込みに失敗した場合は NULL を返します。(読み込み失敗とファイルの最後までの読み込みの見分け方は後述)
- fgets は、num-1 文字の終わりまで、または改行文字 (改行文字も num 文字としてカウントされます) の終わりまで、またはファイルの終わりまで、ストリームから文字列を読み取ります。
例子
int main()
{
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
char arr[20] = { 0 };
fgets(arr, 5, pf);
printf("%s", arr);
//fgets(arr, 8, pf);
//printf("%s", arr);
return 0;
}
结果
2.3 fscanf と fprintf
2.3.1fprintf
int fprintf ( FILE * stream, const char * format, ... );
- fprintf の機能は、データ出力をストリームにフォーマットすることです。fprintf は、すべての出力ストリームで機能します。
- fprintf のヘッダファイルは <stdio.h> です。最初のパラメーターは出力ストリームへのポインターであり、2 番目のパラメーターは可変パラメーターのリストです。つまり、固定されていない複数のパラメーターが存在する可能性があります。出力が成功した場合は出力されたアイテムの数を返し、失敗した場合は負の数を返します。
例子
struct Stu
{
char name[20];
int age;
float score;
};
int main()
{
struct Stu s = { "zhangsan",18,99.5 };
FILE* pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("fopen");
return 1;
}
fprintf(pf, "%s %d %f", s.name, s.age, s.score);
fclose(pf);
pf = NULL;
return 0;
}
结果
2.3.2fscanf
int fscanf ( FILE * stream, const char * format, ... );
- fscanf の機能は、ストリームからパラメーター リストの項目にデータをフォーマットどおりに読み取ることです。fscanf は、すべての入力ストリームで機能します。
- fscanf のヘッダファイルは <stdio.h> です。最初のパラメーターは入力ストリームへのポインターで、2 番目のパラメーターは可変パラメーター リストです。この関数は、読み取りが成功した場合は引数リストに正常に入力されたアイテムの数を返し、読み取りが失敗したかファイルの最後に達した場合は EOF を返します。
例子
struct Stu
{
char name[20];
int age;
float score;
};
int main()
{
struct Stu s = { 0 };
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
fscanf(pf, "%s %d %f", s.name, &s.age, &s.score);
printf("%s %d %f", s.name, s.age, s.score);
return 0;
}
结果
2.4 fread と fwrite
2.4.1fwrite
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
- fwrite の機能は、データのブロックをストリームに書き込むことです。fwirte はファイルに対してのみ機能します。
- fwirte のヘッダー ファイルは <stdio.h> です。最初の引数はストリームに書き込む配列へのポインター、2 番目の引数は配列要素のサイズ、3 番目の引数は配列要素の数、4 番目の引数は出力ストリームへのポインターです。出力が成功した場合、ストリームに書き込まれた要素の総数を返します。size と count の両方が 0 の場合は 0 を返します。
例子
struct Stu
{
char name[20];
int age;
float score;
};
int main()
{
FILE* pf = fopen("test.txt", "wb");//前面的函数读写文件都是文本信息,都可以看懂
//fread和fwrite读写文件都是二进制信息
if (NULL == pf)
{
perror("fopen");
return 1;
}
struct Stu s = { "zhangsan",20,99.5 };
fwrite(&s, sizeof(struct Stu), 1, pf);
fclose(pf);
pf = NULL;
return 0;
}
结果
2.4.2fread
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
- fread の機能は、ストリームからデータを読み取り、それをメモリ ブロックに入れることです。fread はファイルに対してのみ機能します。
- fread のヘッダファイルは <stdio.h> です。最初のパラメーターは、ストリームから読み取ったデータを格納するためにサイズが少なくとも size*count である配列へのポインターであり、2 番目のパラメーターは配列要素のサイズであり、3 番目のパラメーターは配列要素の数です。 4 番目のパラメーターは、入力ストリームへのポインターです。読み取りが成功した場合, 読み取られた要素の総数が返されます. 読み取りが失敗した場合, またはファイルの最後が読み取られた場合, それぞれのインジケータが設定されます. これらのインジケータは, feror および feof とともに使用して, 読み取りが成功したかどうかを判断できます.失敗または読み取り ファイルの最後まで取得 (後述)、カウントまたはサイズが 0 の場合は 0 を返します。
例子
struct Stu
{
char name[20];
int age;
float score;
};
int main()
{
FILE* pf = fopen("test.txt", "rb");
if (NULL == pf)
{
perror("fopen");
return 1;
}
struct Stu s = { 0 };
fread(&s, sizeof(struct Stu), 1, pf);
printf("%s %d %f", s.name, s.age, s.score);
fclose(pf);
pf = NULL;
return 0;
}
结果
2.5 まとめ
関数 | 関数名 | に適用する |
---|---|---|
文字入力機能 | fgetc | すべての入力ストリーム |
文字出力機能 | fputc | すべての出力ストリーム |
テキスト行入力機能 | fgets | すべての入力ストリーム |
テキスト行出力機能 | fput | すべての出力ストリーム |
フォーマット入力機能 | fscanf | すべての入力ストリーム |
フォーマット出力関数 | fprintf | すべての出力ストリーム |
バイナリ入力 | 恐れる | 書類 |
バイナリ出力 | 書き込み | 書類 |
2.6 拡張機能 (sscanf および sprintf)
- scanf はフォーマットされたデータをキーボードから読み取り (入力ストリーム: キーボード標準入力)、printf はデータを画面に出力します (出力ストリーム: 画面標準出力)。
- すべての入力ストリーム (入力ストリーム: stdin、開いているファイル) の fscanf 形式の入力、すべての出力ストリーム (出力ストリーム: stdout、開いているファイル) の fprintf 形式の出力。
- sscanf は文字列から書式設定されたデータを復元し、sprintf は書式設定されたデータを文字列に格納します。
例子
struct Stu
{
char name[20];
int age;
float score;
};
int main()
{
struct Stu s = { "zhangsan",18,99.5 };
char buf[100] = { 0 };
sprintf(buf, "%s %d %f", s.name, s.age, s.score);
printf("%s\n", buf);
printf("-------分割线---------\n");
struct Stu tmp = { 0 };
sscanf(buf, "%s %d %f", tmp.name, &tmp.age, &tmp.score);
printf("%s %d %f", tmp.name, tmp.age, tmp.score);
return 0;
}
结果
3. ファイルのランダムな読み書き
3.1fseek
int fseek ( FILE * stream, long int offset, int origin );
- fseek の機能は、ストリーム内の位置インジケータが指す位置を再配置することです。ファイル ポインターの位置とオフセットに基づいて、ファイル ポインターを特定します。
- ヘッダー ファイルは <stdio.h> です。最初のパラメーターはストリームへのポインター、2 番目のパラメーターはオフセット、3 番目のパラメーターはオフセットの参照位置である開始位置で、SEEK_SET (ファイルの先頭) 、SEEK_CUR の 3 つの固定値があります。 (ファイルポインタの現在位置)、SEEK_END (ファイルの終わり)。成功するとゼロを返し、失敗するとゼロ以外を返します。
例子
int main()
{
FILE* pf = fopen("test.txt", "r");//先在文件内写好abcdef,现在用读的形式打开
if (NULL == pf)
{
perror("fopen");
return 1;
}
//文件的顺序读写,读完一个字符后,文件指针指向下一个字符
printf("%c\n", fgetc(pf));//a
printf("%c\n", fgetc(pf));//b
printf("%c\n", fgetc(pf));//c
//按照顺序读写,接下来打印的是d,但我想要打印b
fseek(pf, -2, SEEK_CUR);//当前位置是文件指针(位置指示器)指向d,后前偏移2就指向b
printf("%c\n", fgetc(pf));
//法2: fseek(pf,1,SEEK_SET);从开头开始偏移
// printf("%c\n",fgetc(pf));
//法3: fseek(pf,-4,SEEK_END);//从末尾开始偏移
// printf("%c\n", fgetc(pf));
fclose(pf);
pf = NULL;
return 0;
}
结果
3.2ftell
long int ftell ( FILE * stream );
- ftell の機能は、開始位置に対するファイル ポインターのオフセットを返すことです。
- ヘッダー ファイルは <stdio.h> で、パラメーターはストリームへのポインターであり、戻り値は開始位置に対する現在のファイル ポインターのオフセットです。
例子
int main()
{
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
printf("%c\n", fgetc(pf));//a
printf("%c\n", fgetc(pf));//b
printf("%d\n", ftell(pf));
return 0;
}
结果
3.3巻き戻し
void rewind ( FILE * stream );
- 巻き戻しの機能は、ファイル ポインタの位置をファイルの先頭に戻すことです。
- ヘッダー ファイルは <stdio.h> で、パラメーターはストリームへのポインターであり、戻り値はありません。
例子
int main()
{
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
printf("%c\n", fgetc(pf));//a
printf("%c\n", fgetc(pf));//b
printf("%d\n", ftell(pf));//2
rewind(pf);
printf("%c\n", fgetc(pf));//a
return 0;
}
结果
4. ファイル読み込み終了判定
4.1 ファイルが終了しているかどうか
- テキストファイルの読み込みが終了したかどうか、戻り値が EOF か ( fgetc )、NULL か ( fgets ) を判断します例: fgetc は
EOF
かどうかを判断します
fgets は戻り値が NULL かどうかを判断します - バイナリファイルの読み込み終了判定と、戻り値が実際に読み込む数値より小さいかどうかを判定します。
例:
fread は、戻り値が実際に読み取る数値よりも小さいかどうかを判断します。
4.2 フィーフとフェラー
- ファイルの読み込み処理中、feof 関数の戻り値を使用して、ファイルが終了したかどうかを直接判断することはできません。
代わりに、ファイルの読み取りが終了したときに、読み取りが終了に失敗したか、ファイルの終わりに遭遇したかを判断して適用されます。 - feof は true を返します。これは、終了フラグが検出されたときにファイルの通常の読み取りが終了したことを示します。
- ferror は true を返します。これは、ファイルの読み取りプロセス中にエラーが発生し、終了したことを示します。
例子
int main(void)
{
int c; // 注意:int,非char,要求处理EOF
FILE* fp = fopen("test.txt", "r");
if(!fp) {
perror("File opening failed");
return EXIT_FAILURE;
}
//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
{
putchar(c);
}
//判断是什么原因结束的
if (ferror(fp))
puts("I/O error when reading");
else if (feof(fp))
puts("End of file reached successfully");
fclose(fp);
}