はじめに
この記事について
「C言語の基礎を学ぼう」をテーマに、自身の知識 + α をアドベントカレンダーにまとめます。
25日間でC言語をマスターしよう - Qiita Advent Calendar 2025 - Qiita
こんな方を対象としています
-
コンピュータがプログラムをどのように動かしているか知りたい/知らない方
-
プログラミングをしてみたい方
-
C言語初心者の方
キーワード
- FILE型(構造体)
説明
ファイルの扱い方
ファイルを扱いたい場合、 FILE 型(構造体)を使用します。
次のプログラムは 現在のフォルダ/resource/test.txt の内容を1行表示します。
#include <stdio.h>
int main(void) {
char *path = "./resource/test.txt";
FILE *test_file;
char *line;
test_file = fopen(path, "r"); // ファイルオープン
if (test_file == NULL) {
printf("ファイルオープン失敗\n");
return 0;
}
fscanf(test_file, "%s", line); // ファイル読み込み
fclose(test_file); // ファイルクローズ
printf("%s", line);
return 0;
}
testfile
ファイルを扱う際の流れは下記のようになります。
- FILE型のポインタを宣言
-
fopen()でFILE取得- 失敗した場合、
fopen()の戻り値はNULL(何も指さないポインタ)
- 失敗した場合、
- ファイルの読み取り、書き込み
-
fclose()でFILEを解放
fopen() の第2引数にはモードを指定します。
| モード | 説明 |
|---|---|
| r | 読み取り専用。 ファイルが無ければ失敗。 |
| w | 書き込み専用。 既存のファイルは上書きする。 ファイルが無ければ新規作成。 |
| a | 追記用。 既存のファイルの末尾に追記する。 ファイルが無ければ新規作成。 |
| r+ | 読み書き用。 ファイルが無ければ失敗。 |
| w+ | 読み書き用。 既存のファイルは上書きする。 ファイルが無ければ新規作成。 |
| a+ | 追記と読み込み用。 既存のファイルの末尾に追記する。 ファイルが無ければ新規作成。 |
テキストファイルでなく、バイナリファイルを読み込む場合は各モードの末尾に b をつけます。
ファイル読み込み
ファイル読み込みに使用される関数に fscanf() fgets() fgetc() があります。
-
fscanf(): スペースまたは改行まで読み込む。読み込んだデータにスペースおよび改行は含まれない。 -
fgets(): 改行まで読み込む。読み込んだデータに改行が含まれる。 -
fgetc(): 1文字読み込む。
test file
#include <stdio.h>
int main(void) {
char *path = "./resource/test.txt";
FILE *test_file;
char *a, *b, c;
// fscanf
test_file = fopen(path, "r");
fscanf(test_file, "%s", a);
fclose(test_file);
// fgets
test_file = fopen(path, "r");
fgets(b, 100, test_file); // 最大100バイト
fclose(test_file);
// fgetc
test_file = fopen(path, "r");
c = fgetc(test_file);
fclose(test_file);
// 結果
printf("%s\n", a);
printf("%s\n", b);
printf("%c\n", c);
return 0;
}
test
test file
t
ファイル書き込み
ファイル書き込みに使用される関数に fprintf() fputs() fputc() があります。
-
fprintf():printf()と同様の形式で書き込む。 -
fgets(): 複数文字書き込む。 -
fgetc(): 1文字書き込む。
test file
#include <stdio.h>
int main(void) {
char *path = "./resource/test.txt";
FILE *test_file;
char *a = "fprintf", *b = "fputs\n", c = 'c';
// fprintf
test_file = fopen(path, "a");
fprintf(test_file, "%s\n", a);
fclose(test_file);
// fputs
test_file = fopen(path, "a");
fputs(b, test_file);
fclose(test_file);
// fputc
test_file = fopen(path, "a");
fputc(c, test_file);
fclose(test_file);
return 0;
}
test file
fprintf
fputs
c
練習
1. ファイルプレビュー
ファイルのプレビューを表示しよう。
- ユーザーがファイル名を入力する。
- ファイルの先頭から2行を標準出力に表示する。
- 3行目以降が存在する場合は、3行目に
...を表示する。 - ログを
./log/log.txtに記録する。 - ログの形式 :
{ファイル名} をプレビューしました。\n
apple
banana
lemon
coffee
PS C:\workspace\c> .\example
ファイル名:fruit.txt
apple
banana
...
PS C:\workspace\c> .\example
ファイル名:drink.txt
coffee
PS C:\workspace\c>
./resource/fruit.txt をプレビューしました。
./resource/drink.txt をプレビューしました。
ポイント
読み取り専用で開いたファイルを fgets() で1行ずつ読み込みます。
行の読み込みに失敗した場合、 fgets() の戻り値が NULL になります。(ファイル終端)
ログファイルが文字化けする場合は、Shift JISで開きましょう。
解答例
#include <stdio.h>
int main(void) {
char resource_path[100] = "./resource/";
char *log_path = "log.txt";
FILE *fp;
char line0_buf[100], line1_buf[100], line2_buf[100];
char *line[3] = {line0_buf, line1_buf, line2_buf};
// resource_pathのヌル文字以降に、
// 入力されたファイル名を結合する
char *path;
path = &resource_path[11];
printf("ファイル名:");
scanf("%s", path);
// ファイル読み込み
int i = 0;
fp = fopen(resource_path, "r");
for (i = 0; i < 3; i++) {
if(NULL == fgets(line[i], 100, fp)) {
// 読み込み失敗(ファイル終端)
break;
}
}
fclose(fp);
// プレビュー表示
if (i >= 1) fputs(line[0], stdout);
if (i >= 2) fputs(line[1], stdout);
if (i >= 3) fputs("...\n", stdout);
// ログ追記
fp = fopen(log_path, "a");
fprintf(fp, "%s をプレビューしました。\n", resource_path);
fclose(fp);
return 0;
}
PS C:\workspace\c> .\example
ファイル名:fruit.txt
apple
banana
...
PS C:\workspace\c> .\example
ファイル名:drink.txt
coffee
PS C:\workspace\c>
./resource/fruit.txt をプレビューしました。
./resource/drink.txt をプレビューしました。
ファイルポインタの代わりに stdin stdout を指定すると、標準入出力に対してファイルと同様の操作が可能です。
おわりに
ファイルを開いた後、閉じるのを忘れないようにしましょう。
ファイル自体の操作より、書き込む値や読み込む値の管理が複雑になりやすいかもしれません。
参考文献
↓↓↓ はじめてプログラミングを学んだときに読んだ本です ↓↓↓
詳細(プログラミング入門 C言語)|プログラミング|情報|実教出版