ランダムアクセス 解答ページ | Programming Place Plus C言語編 第41章

トップページC言語編第41章

問題① 🔗

問題① オープンモードが “w” の場合と、“a” の場合との挙動の違いを確かめてください。


“w” は通常の書き込みモード、“a” は追記モードです。 挙動の違いを確かめるには、何度か実行を繰り返す必要があります。 まずはテストプログラムを用意しましょう。

#include <stdio.h>
#include <stdlib.h>

#define APPEND_MODE     // 定義すると "a"。定義しないと "w"

int main(void)
{
#ifdef APPEND_MODE
    FILE* fp = fopen("hello.txt", "a");
#else
    FILE* fp = fopen("hello.txt", "w");
#endif
    if (fp == NULL) {
        fputs("ファイルオープンに失敗しました。\n", stderr);
        exit(EXIT_FAILURE);
    }

    if (fputs("Hello, World\n", fp) == EOF) {
        fputs("ファイルへの書き込みに失敗しました。\n", stderr);
        exit(EXIT_FAILURE);
    }

    if (fclose(fp) == EOF) {
        fputs("ファイルクローズに失敗しました。\n", stderr);
        exit(EXIT_FAILURE);
    }
}

“a” を使って、1度実行すると、hello.txt は次のようになります。

実行結果(hello.txt):

Hello, World

続けてもう1度実行すると、次のようになります。

実行結果(hello.txt):

Hello, World
Hello, World

このように、“a” を使うと、以前のファイルの内容を保持したままで新しいデータが書き込まれていきます。 本当は、出力するメッセージも変えて確かめてみるとより良いと思いますので、試してみてください。

一方、“w” を使った場合には、以前のファイルの内容は失われて、新規のデータとして書き込まれます。 そのため、何度実行しても、次の状態にしかなりません。

実行結果(hello.txt):

Hello, World

問題② 🔗

問題② オープンモードの “a+” を使い、ファイルへの追記を行った後、ファイル全体を標準出力へ出力するプログラムを作成してください。


適当に中身を書き込んである test.txt があるとします。

実行前のファイル(test.txt)

aaa
bbb
ccc

プログラムは次のようになります。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    FILE* fp = fopen("test.txt", "a+");
    if (fp == NULL) {
        fputs("ファイルオープンに失敗しました。\n", stderr);
        exit(EXIT_FAILURE);
    }

    // ファイルの末尾へ追記
    if (fputs("xyz\n", fp) == EOF) {
        fputs("ファイルへの書き込みに失敗しました。\n", stderr);
        exit(EXIT_FAILURE);
    }

    // ファイルポジションを先頭に戻す
    if (fseek(fp, 0L, SEEK_SET) != 0) {
        fputs("ファイルポジションの移動に失敗しました。\n", stderr);
        exit(EXIT_FAILURE);
    }

    // ファイル全体を標準出力へ出力する
    for (;;) {
        int c = fgetc(fp);
        if (c == EOF) {
            if (feof(fp)) {
                break;
            }
            else if (ferror(fp)) {
                fputs("読み込み中にエラーが発生しました。\n", stderr);
                exit(EXIT_FAILURE);
            }
            else {
                // 有効な文字なので、そのまま続行
            }
        }
        printf("%c", (char)c);
    }
    printf("\n");

    if (fclose(fp) == EOF) {
        fputs("ファイルクローズに失敗しました。\n", stderr);
        exit(EXIT_FAILURE);
    }
}

実行後のファイル(test.txt)

aaa
bbb
ccc
xyz

実行結果(標準出力):

aaa
bbb
ccc
xyz



参考リンク 🔗


更新履歴 🔗

≪さらに古い更新履歴≫
    • 解説のベースを C99 に上げる対応
      • ローカル変数の宣言を、ブロックの先頭以外の位置でも行う
    • 解説のベースを C99 に上げる対応
      • コメントを // 形式で統一
    • 章のタイトルを変更(テキストファイルの読み書き② -> ランダムアクセス)
      練習問題を変更。元あった①を削除、②③を第40章へ移動。
      第39章にあった②を①として持ってきた。 ②を新規で作成。
    • Xcode 8.3.3 を clang 5.0.0 に置き換え。
    • clang 3.7 (Xcode 7.3) を、Xcode 8.3.3 に置き換え。
    • VisualC++ 2017 に対応。
    • clang の対応バージョンを 3.7 に更新。
    • clang の対応バージョンを 3.4 に更新。
    • VisualC++ 2012 の対応終了。
    • flose関数の戻り値もチェックするようにした。
    • VisualC++ 2010 の対応終了。
    • VisualC++ 2015 に対応。
    • clang 3.2 に対応。
    • VisualC++ 2013 に対応。
    • clang 3.0 に対応。
    • 標準ヘッダの定義を VisualC++ 2012 付属のライブラリで確認。
    • 新規作成。



第41章のメインページへ

C言語編のトップページへ

Programming Place Plus のトップページへ


先頭へ戻る