57

ファイルの各行を各単語ではなく文字列として返す istream_iterator スタイルの反復子を取得したいと考えています。これは可能ですか?

4

8 に答える 8

36

編集:この同じトリックは、前のスレッドで他の誰かによって既に投稿されています。

std::istream_iteratorあなたが望むことをするのは簡単です:

namespace detail 
{
    class Line : std::string 
    { 
        friend std::istream & operator>>(std::istream & is, Line & line)
        {   
            return std::getline(is, line);
        }
    };
}

template<class OutIt>
void read_lines(std::istream& is, OutIt dest)
{
    typedef std::istream_iterator<detail::Line> InIt;
    std::copy(InIt(is), InIt(), dest);
}

int main()
{
    std::vector<std::string> v;
    read_lines(std::cin, std::back_inserter(v));

    return 0;
}
于 2010-02-18T20:10:58.580 に答える
25

標準ライブラリはこれを行うためのイテレータを提供していませんが (独自にそのようなものを実装することはできます)、単純にgetline関数(istream メソッドではなく) を使用して、入力ストリームから C++ 文字列への行全体を読み取ることができます。 .

例:

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

using namespace std;

int main()
{
    ifstream is("test.txt");
    string str;
    while(getline(is, str))
    {
        cout<<str<<endl;
    }
    return 0;
}
于 2010-02-18T20:09:57.633 に答える
7

これが解決策です。この例では、各行の終わりに @@ を付けて入力ファイルを出力します。

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

using namespace std;

class line : public string {};

std::istream &operator>>(std::istream &is, line &l)
{
    std::getline(is, l);
    return is;
}

int main()
{
    std::ifstream inputFile("input.txt");

    istream_iterator<line> begin(inputFile);
    istream_iterator<line> end;

    for(istream_iterator<line> it = begin; it != end; ++it)
    {
        cout << *it << "@@\n";
    }

    getchar();
}

編集:マヌエルはより速くなりました。

于 2010-02-18T21:58:02.860 に答える
3

独自のイテレータを作成できます。それほど難しくありません。イテレータは、(簡単に言えば) インクリメント演算子と * 演算子が定義されている単なるクラスです。

http://www.drdobbs.com/cpp/184401417を見て、独自のイテレータを書き始めてください。

于 2010-02-18T20:11:32.153 に答える
1

istream_iterator の代わりに istreambuf_iterator を使用できます。istream_iterator のような制御文字は無視されません。

コード.cpp:

#include <iterator>
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ifstream file("input.txt");

    istreambuf_iterator<char> i_file(file);

    istreambuf_iterator<char> eof;

    std::string buffer;
    while(i_file != eof)
    {
        buffer += *i_file;
        if(*i_file == '\n')
        {
            std::cout << buffer;
            buffer.clear();
        }
        ++i_file;
    }

    return 0;
}

入力.txt:

ahhhh test *<-- There is a line feed here*
bhhhh second test *<-- There is a line feed here*

出力:

ahhhh test
bhhhh second test
于 2010-02-18T21:57:48.693 に答える
1

範囲ベースの for ループを使用することも可能です:

// Read from file.
std::ifstream f("test.txt");
for (auto& line : lines(f))
  std::cout << "=> " << line << std::endl;

// Read from string.
std::stringstream s("line1\nline2\nline3\n\n\nline4\n\n\n");
for (auto& line : lines(s))
  std::cout << "=> " << line << std::endl;

lines次のように定義されます。

#include <string>
#include <iterator>
#include <istream>

struct line_iterator {
  using iterator_category = std::input_iterator_tag;
  using value_type = std::string;
  using difference_type = std::ptrdiff_t;
  using reference = const value_type&;
  using pointer = const value_type*;

  line_iterator(): input_(nullptr) {}
  line_iterator(std::istream& input): input_(&input) { ++*this; }

  reference operator*() const { return s_; }
  pointer operator->() const { return &**this; }

  line_iterator& operator++() {
    if (!std::getline(*input_, s_)) input_ = nullptr;
    return *this;
  }

  line_iterator operator++(int) {
    auto copy(*this);
    ++*this;
    return copy;
  }

  friend bool operator==(const line_iterator& x, const line_iterator& y) {
    return x.input_ == y.input_;
  }

  friend bool operator!=(const line_iterator& x, const line_iterator& y) {
    return !(x == y);
  }

 private:
  std::istream* input_;
  std::string s_;
};

struct lines {
  lines(std::istream& input): input_(input) {}

  line_iterator begin() const { return line_iterator(input_); }
  line_iterator end() const { return line_iterator(); }

 private:
  std::istream& input_;
};
于 2021-12-18T01:51:11.183 に答える