
はじめてのC言語 | 第17回
はじめに
前回は、構造体の基本を学びました。
今回は、C言語でファイルを扱う方法を学びます。
これまでのプログラムでは、結果を画面に表示していました。
ファイル入出力を使うと、データをファイルに保存したり、保存済みのファイルからデータを読み込んだりできます。
この回の目的は次の5点です。
- ファイル入出力の基本的な流れを理解する
fopenでファイルを開く方法を学ぶfprintfでファイルに書き込む方法を学ぶfgetsでファイルから読み込む方法を学ぶfcloseでファイルを閉じる理由を理解する
ファイル入出力の基本的な流れ
C言語でファイルを扱う基本的な流れは次のとおりです。
- 1. ファイルを開く
- 2. 読み書きする
- 3. ファイルを閉じる
ファイルを開くには fopen を使います。
読み書きが終わったら、fclose で閉じます。
ファイルを開くときには、次のようなモードを指定します。
"w": 書き込み用に開く"r": 読み込み用に開く"a": 追記用に開く
この回では、まず "w" と "r" を使います。
ファイルに文字を書き込む
ソースコード
file_write.c という名前で保存します。
#include <stdio.h>
int main(void) {
FILE *fp;
fp = fopen("output.txt", "w");
if (fp == NULL) {
printf("file open error\n");
return 1;
}
fprintf(fp, "Hello, file!\n");
fprintf(fp, "C language\n");
fclose(fp);
return 0;
}実行手順
1. 作業ディレクトリに移動する
cd ~/Desktop2. コンパイルする
clang file_write.c -o file_write3. 実行する
./file_write実行すると、同じディレクトリに output.txt が作成されます。
4. ファイルの中身を確認する
cat output.txt実行結果:
Hello, file!
C languageコードの読み方
FILE *fp
FILE *fp;FILE は、ファイルを扱うために使う型です。FILE *fp は、開いたファイルを操作するための変数です。
この変数を通して、ファイルへの書き込みや読み込みを行います。
fopen(“output.txt”, “w”)
fp = fopen("output.txt", "w");fopen はファイルを開く関数です。
第1引数にファイル名、第2引数にモードを指定します。
ここでは、output.txt を書き込み用の "w" モードで開いています。
"w" モードでは、ファイルが存在しない場合は新しく作成されます。
すでに同じ名前のファイルがある場合は、中身が上書きされます。
fp == NULL
if (fp == NULL) {
printf("file open error\n");
return 1;
}ファイルを開けなかった場合、fopen は NULL を返します。
そのため、fopen の直後に NULL かどうかを確認します。
fprintf
fprintf(fp, "Hello, file!\n");fprintf は、指定したファイルに文字を書き込む関数です。printf は画面に出力しますが、fprintf はファイルに出力します。
fclose
fclose(fp);fclose は、開いたファイルを閉じる関数です。
ファイルを使い終わったら、必ず閉じます。
ファイルから1行ずつ読み込む
次に、ファイルから文字列を読み込むプログラムを作ります。
先ほど作成した output.txt を読み込みます。
サンプルコード
file_read.c という名前で保存します。
#include <stdio.h>
int main(void) {
FILE *fp;
char line[100];
fp = fopen("output.txt", "r");
if (fp == NULL) {
printf("file open error\n");
return 1;
}
while (fgets(line, sizeof(line), fp) != NULL) {
printf("%s", line);
}
fclose(fp);
return 0;
}コンパイル:
clang file_read.c -o file_read実行:
./file_read実行結果:
Hello, file!
C languagefgets の基本
fgets(line, sizeof(line), fp)fgets は、ファイルから1行分の文字列を読み込む関数です。
第1引数に読み込み先の配列、第2引数に配列のサイズ、第3引数にファイルを指定します。
fgets は、読み込みに成功すると読み込んだ文字列を返します。
読み込むものがなくなると NULL を返します。
そのため、次のように while と組み合わせて使えます。
while (fgets(line, sizeof(line), fp) != NULL) {
printf("%s", line);
}数値をファイルに書き込む
fprintf は、printf と同じように書式指定子を使えます。
#include <stdio.h>
int main(void) {
FILE *fp;
int score = 85;
fp = fopen("score.txt", "w");
if (fp == NULL) {
printf("file open error\n");
return 1;
}
fprintf(fp, "%d\n", score);
fclose(fp);
return 0;
}このプログラムを実行すると、score.txt に 85 が書き込まれます。
数値をファイルから読み込む
数値を読み込む場合は、fscanf を使うこともできます。
#include <stdio.h>
int main(void) {
FILE *fp;
int score;
fp = fopen("score.txt", "r");
if (fp == NULL) {
printf("file open error\n");
return 1;
}
if (fscanf(fp, "%d", &score) == 1) {
printf("%d\n", score);
}
fclose(fp);
return 0;
}実行結果:
85fscanf は、読み取りに成功した項目数を返します。
この例では、整数を1個読み取れた場合だけ表示しています。
追記モードを使う
ファイルの末尾に追加で書き込みたい場合は、"a" モードを使います。
#include <stdio.h>
int main(void) {
FILE *fp;
fp = fopen("output.txt", "a");
if (fp == NULL) {
printf("file open error\n");
return 1;
}
fprintf(fp, "append line\n");
fclose(fp);
return 0;
}"a" モードでは、既存の内容を残したまま、ファイルの末尾に書き込みます。
初心者がつまずきやすい点
fopen の失敗を確認しない
ファイルは必ず開けるとは限りません。
ファイル名が間違っている場合や、権限がない場合は失敗します。
そのため、fopen の直後に NULL チェックを入れます。
“w” モードは上書きする
"w" モードで既存ファイルを開くと、中身は消えて新しい内容に置き換わります。
既存の内容を残して末尾に追加したい場合は、"a" モードを使います。
fclose を忘れる
ファイルを開いたら、使い終わったあとに fclose で閉じます。
閉じ忘れると、書き込み内容が正しく保存されない場合があります。
読み込み用ファイルが存在しない
"r" モードでは、対象のファイルが存在しないと fopen は失敗します。
読み込み前に、ファイルが存在するかを確認します。
よくあるエラー
file open error と表示される
原因: ファイルを開けていません。
対処: ファイル名、実行しているディレクトリ、権限を確認します。
現在のディレクトリは次のコマンドで確認できます。
pwdファイル一覧は次のコマンドで確認できます。
lsファイルの中身が消えた
原因: "w" モードで開いたため、既存の内容が上書きされました。
対処: 追記したい場合は "a" モードを使います。
文字列の途中までしか読み込めない
原因: fgets に渡した配列サイズが小さい可能性があります。
対処: 読み込み先の配列サイズを確認します。
練習用コード
複数行を書き込む
#include <stdio.h>
int main(void) {
FILE *fp;
fp = fopen("memo.txt", "w");
if (fp == NULL) {
printf("file open error\n");
return 1;
}
fprintf(fp, "first line\n");
fprintf(fp, "second line\n");
fprintf(fp, "third line\n");
fclose(fp);
return 0;
}ファイルを読み込んで表示する
#include <stdio.h>
int main(void) {
FILE *fp;
char line[100];
fp = fopen("memo.txt", "r");
if (fp == NULL) {
printf("file open error\n");
return 1;
}
while (fgets(line, sizeof(line), fp) != NULL) {
printf("%s", line);
}
fclose(fp);
return 0;
}まとめ
今回のポイントは次のとおりです。
- ファイルを扱う基本は、開く、読み書きする、閉じる、という流れである
fopenはファイルを開く関数であるfprintfはファイルに書き込む関数であるfgetsはファイルから1行ずつ読み込む関数であるfscanfは書式に従ってファイルから読み込む関数であるfcloseでファイルを閉じる必要があるfopenの戻り値がNULLかどうかを確認する"w"モードは既存ファイルを上書きする
この回では、C言語でファイルを扱う基本を学びました。
ファイル入出力を使うと、プログラムの実行結果やデータを保存し、あとから読み込めるようになります。
次回予告
次は、複数ファイル構成とヘッダファイルを学びます。
プログラムを複数の .c ファイルや .h ファイルに分けることで、規模が大きくなっても管理しやすくなります。


