第17回|C言語でファイル入出力の基本を学ぶ:ファイルに書き込み、ファイルから読み込む

当サイトでは、コンテンツの一部に広告を掲載しています。
第17回|C言語でファイル入出力の基本を学ぶ:ファイルに書き込み、ファイルから読み込む

はじめての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 ~/Desktop

2. コンパイルする

clang file_write.c -o file_write

3. 実行する

./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;
}

ファイルを開けなかった場合、fopenNULL を返します。
そのため、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 language

fgets の基本

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.txt85 が書き込まれます。

数値をファイルから読み込む

数値を読み込む場合は、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;
}

実行結果:

85

fscanf は、読み取りに成功した項目数を返します。
この例では、整数を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 ファイルに分けることで、規模が大きくなっても管理しやすくなります。

あわせて読みたい
第18回|C言語で複数ファイル構成とヘッダファイルを学ぶ:プログラムを分けて管理する はじめてのC言語 | 第18回 はじめに 前回は、ファイル入出力の基本を学びました。今回は、C言語のプログラムを複数のファイルに分ける方法を学びます。 これまでのサ...

さらに学びたいあなたへ

用途ごとに選ぶ Linux のおすすめ本

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

のいのアバター のい UNIX Cafe マスター

Macintosh Color Classicから始まった旅は、長いWindows時代を経て、Windows10のサポート終了をきっかけにUNIXの世界へ戻ってきました。UNIX Cafeでは、UNIX・Linux・そしてMacな世界を、むずかしい言葉を使わず、物語のように書いています。プログラミングは、アイデアをコンピューターに伝えるための言葉です。簡単な単語と文法を覚えれば、誰でもコマンドを使えます。ぜひ一度、やさしいプログラミングの世界をのぞいてみてください。

Created by UNIX Cafe

目次