ファイル処理 解答ページ | Programming Place Plus 新C++編

トップページ新C++編ファイル処理

このページの概要 🔗

このページは、練習問題の解答例や解説のページです。



解答・解説 🔗

問題1 (確認★) 🔗

出力先のファイルのパスを、絶対パスで指定した場合と、相対パスで指定した場合とで、実際にファイルが作られる場所がどのように変わるか試してください。

ビルドして得られた実行ファイルをさまざまな場所にコピーして、そこで実行してみましょう。


たとえば次のようなプログラムを用意します。

#include <fstream>

int main()
{
    std::ofstream ofs("../test.txt");
    ofs << "Hello.\n";
}

オープンするファイルとして "../test.txt" を指定しました。これは相対パスで表記されたものであり、「カレントディレクトリの1つ上のディレクトリの test.txt」を意味しています(本編解説)。

このプログラムをビルドして、実行ファイル(.exe という拡張子のファイル)を作ったら、そのファイルを Windows のエクスプローラーの側から実行してみましょう(【導入】「初めての C++ プログラミング」のページを参照)。すると、実行ファイルがある場所よりも1つ上のディレクトリに test.txt が作られるはずです。ほかの場所に実行ファイルを持っていって、そこで実行してみても、やはりその位置からみた1つ上のディレクトリに test.txt が作られます。これが相対パスで指定した結果です。

次に絶対パスの場合を試してみます。次のようなプログラムを用意します。

#include <fstream>

int main()
{
    std::ofstream ofs("C:\\program\\test.txt");
    ofs << "Hello.\n";
}

パスの内容は自身の環境に合わせて変更してください。エクスプローラーで適当なディレクトリを開いて、そのパスをコピーアンドペーストすればいいですが、区切り文字 \ は2つ重ねて \\ としないといけないことに注意してください(\ はエスケープシーケンスの開始を意味してしまうからです。「文字」のページを参照)。

Windows でファイルの絶対パスを取得する方法は、「Windows編>ファイルやフォルダの絶対パスを取得する」を参照してください。

絶対パス表記の場合は、実行ファイルをどこに置こうとも、指定したとおりの場所に test.txt が作られます。

問題2 (基本★★) 🔗

標準入力から入力された文字列を、ファイルへ書き出していくプログラムを作成してください。“exit” が入力されるまで繰り返すものとします。


たとえば、次のようなプログラムになります。

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ofstream ofs("test.txt");

    while (true) {

        // 標準入力から文字列を受け取る("exit" が入力されたら終わり)
        std::cout << "Please enter the string.\n";
        std::string input_string {};
        std::getline(std::cin, input_string);
        if (input_string == "exit") {
            break;
        }

        // ファイルへ書き出す
        ofs << input_string << "\n";
    }
}

実行結果(標準出力):

Please enter the string.
test  <-- 入力した文字列
Please enter the string.
hello world.  <-- 入力した文字列
Please enter the string.
exit  <-- 入力した文字列

実行結果(test.txt):

test
hello world.

標準入力からの入力を繰り返し受け取るので、ループの内側で処理します。“exit” が入力されたらループから抜け出します。

ファイルへ書き出すために、std::ofstream型の変数を宣言しておきます。これはループの内側に入れないことに注意してください。ループの内側で宣言すると、ループが1周するごとに、新たにファイルをオープンし直すことになります。出力のためのオープンはファイルの中身を空の状態に戻してしまうので(本編解説)、これではうまくいきません。

問題3 (応用★★) 🔗

ファイルの行数をカウントするプログラムを作成してください。


たとえば次のように書けます。

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ifstream ifs("test.txt");
    int lineCount {0};

    while (ifs.eof() == false) {
        std::string s {};
        std::getline(ifs, s);
        ++lineCount;
    }

    std::cout << lineCount << "\n";
}

test.txt の内容:

1st line.
2nd line.
3rd line.

実行結果(標準出力):

3

ファイルの終わりまで1行ずつ読み込みを繰り返す基本形のコードを使います(本編解説)。あとは、行数カウントのための変数を追加して、1行読み込むたびにインクリメントしていけばいいだけです。

問題4 (応用★★) 🔗

次のように、各行に3つの整数が、空白で区切られながら記述されているファイルを読み込み、各行の整数の合計値を標準出力へ出力するプログラムを作成してください。

203 1100 95
635 55 300
1400 2 16
80 65 54


たとえば次のように書けます。

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

int main()
{
    std::ifstream ifs("test.txt");

    while (ifs.eof() == false) {
        std::string s {};
        std::getline(ifs, s);

        std::istringstream iss {s};
        int value1 {};
        int value2 {};
        int value3 {};
        iss >> value1 >> value2 >> value3;
        std::cout << value1 + value2 + value3 << "\n";
    }
}

test.txt の内容:

203 1100 95
635 55 300
1400 2 16
80 65 54

実行結果(標準出力):

1398
990
1418
199

この問題も、ファイルの終わりまで1行ずつ読み込みを繰り返す基本形のコードを使います(本編解説)。

各行には3つの整数が書き込まれていることは分かっていますが、std::getline関数で読み取れるのは1つの文字列になったものです。1行目でいうと、"203 1100 95" という文字列が読み込まれます。整数の合計値を計算したいので、文字列のままでは困ります。そこで、std::istringstream を使って、文字列を3つの整数に分解します(「stringstream」のページを参照)。3つの整数に分解できたら、単純にそれらを加算したものを出力すればいいだけです。


参考リンク 🔗



更新履歴 🔗




はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る