721

file.txt の内容は次のとおりです。

5 3
6 4
7 1
10 5
11 6
12 3
12 4

は座標5 3ペアです。このデータを C++ で 1 行ずつ処理するにはどうすればよいですか?

最初の行は取得できましたが、ファイルの次の行を取得するにはどうすればよいですか?

ifstream myfile;
myfile.open ("file.txt");
4

8 に答える 8

116

C++ でファイルを 1 行ずつ読み取るには、いくつかの方法があります。

[高速] std::getline() でループ

最も簡単な方法は、std::ifstream を開いて、std::getline() 呼び出しを使用してループすることです。コードはクリーンで理解しやすいです。

#include <fstream>

std::ifstream file(FILENAME);
if (file.is_open()) {
    std::string line;
    while (std::getline(file, line)) {
        // using printf() in all tests for consistency
        printf("%s", line.c_str());
    }
    file.close();
}

[高速] Boost の file_description_source を使用

もう 1 つの可能性は Boost ライブラリを使用することですが、コードはもう少し冗長になります。パフォーマンスは上記のコード (std::getline() でループ) と非常によく似ています。

#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>

namespace io = boost::iostreams;

void readLineByLineBoost() {
    int fdr = open(FILENAME, O_RDONLY);
    if (fdr >= 0) {
        io::file_descriptor_source fdDevice(fdr, io::file_descriptor_flags::close_handle);
        io::stream <io::file_descriptor_source> in(fdDevice);
        if (fdDevice.is_open()) {
            std::string line;
            while (std::getline(in, line)) {
                // using printf() in all tests for consistency
                printf("%s", line.c_str());
            }
            fdDevice.close();
        }
    }
}

【最速】Cコードを使用

ソフトウェアのパフォーマンスが重要な場合は、C 言語の使用を検討してください。このコードは、上記の C++ バージョンよりも 4 ~ 5 倍高速です。以下のベンチマークを参照してください。

FILE* fp = fopen(FILENAME, "r");
if (fp == NULL)
    exit(EXIT_FAILURE);

char* line = NULL;
size_t len = 0;
while ((getline(&line, &len, fp)) != -1) {
    // using printf() in all tests for consistency
    printf("%s", line);
}
fclose(fp);
if (line)
    free(line);

ベンチマーク -- どちらが速いですか?

上記のコードを使用していくつかのパフォーマンス ベンチマークを行ったところ、興味深い結果が得られました。100,000 行、1,000,000 行、10,000,000 行のテキストを含む ASCII ファイルでコードをテストしました。テキストの各行には、平均で 10 語が含まれています。-O3プログラムは最適化されてコンパイルされ、その出力は/dev/null測定からロギング時間変数を削除するために転送されます。printf()最後になりましたが、一貫性を保つために、コードの各部分が関数を使用して各行をログに記録します。

結果は、コードの各部分がファイルを読み取るのにかかった時間 (ミリ秒) を示しています。

2 つの C++ アプローチのパフォーマンスの違いは最小限であり、実際には違いはありません。C コードのパフォーマンスは、ベンチマークを印象的なものにし、速度の点でゲームチェンジャーになる可能性があります。

                             10K lines     100K lines     1000K lines
Loop with std::getline()         105ms          894ms          9773ms
Boost code                       106ms          968ms          9561ms
C code                            23ms          243ms          2397ms

ここに画像の説明を入力

于 2018-07-28T14:35:01.380 に答える
17

あなたの座標はペアとして一緒に属しているので、構造体を書いてみませんか?

struct CoordinatePair
{
    int x;
    int y;
};

次に、istream のオーバーロードされた抽出演算子を記述できます。

std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
    is >> coordinates.x >> coordinates.y;

    return is;
}

そして、次のように、座標のファイルをベクトルに直接読み取ることができます。

#include <fstream>
#include <iterator>
#include <vector>

int main()
{
    char filename[] = "coordinates.txt";
    std::vector<CoordinatePair> v;
    std::ifstream ifs(filename);
    if (ifs) {
        std::copy(std::istream_iterator<CoordinatePair>(ifs), 
                std::istream_iterator<CoordinatePair>(),
                std::back_inserter(v));
    }
    else {
        std::cerr << "Couldn't open " << filename << " for reading\n";
    }
    // Now you can work with the contents of v
}
于 2016-08-20T16:58:07.590 に答える