0

したがって、定義が与えられた場合:

typedef char Task;

struct Tache {
    char step;
    int duration;
    list<Task> precedentTask;
};

の抽出演算子を作成しましたTache:

istream& operator>>(istream& lhs, Tache& rhs) {
    string line;

    getline(lhs, line, '\n');

    stringstream ss(line);

    ss >> rhs.step;
    ss.ignore(numeric_limits<streamsize>::max(), '(');
    ss >> rhs.duration;
    ss.ignore(numeric_limits<streamsize>::max(), ')');

    const regex re("\\s*,\\s*([a-zA-Z])");
    string precedentTasks;

    getline(ss, precedentTasks);

    transform(sregex_token_iterator(cbegin(precedentTasks), cend(precedentTasks), re, 1), sregex_token_iterator(), back_insert_iterator<list<Task>>(rhs.precedentTask), [](const string& i) {
        return i.front();
    });

    return lhs;
}

ただし、この抽出演算子をメンバーで使用しようとするとistream_iteratorprecedentTask次の要素に出血しているようです。たとえば、次のようになります。

stringstream seq("A(3)\nB(4),A\nC(2),A\nE(5),A\nG(3),A\nJ(8),B,H\nH(7),C,E,G\nI(6),G\nF(5),H");

list<Tache> allTaches{ istream_iterator<Tache>(seq), istream_iterator<Tache>() };

for (const auto& i : allTaches) {
    cout << i.step << ' ' << i.duration << ' ';
    copy(cbegin(i.precedentTask), cend(i.precedentTask), ostream_iterator<Task>(cout, " "));
    cout << endl;
}

Live Example

私は得ています:

A 3
B 4 A
C 2 AA
E 5 AAA
G 3 AAAA
J 8 AAAABH
H 7 AAAABHCEG
I 6 AAAABHCEGG
F 5 AAAABHCEGGH

私の予想ではなく:

A 3
B 4 A
C 2 A
E 5 A
G 3 A
J 8 BH
H 7 CEG
I 6 G
F 5 H

を誤用していsregex_token_iteratorますか?

4

1 に答える 1

3

これは正規表現とは何の関係もありません。すべては内部で行われていることと関係があります。インクリメントしたときに読み込まれる要素istream_iteratorは 1 つだけです。T

istream_iterator& operator++();
3必要なもの: in_stream != 0.
4つの効果*in_stream >> value
5戻り値: *this.

ストリーム演算子は に追加するだけですrhs.precedentTaskが、最初から空である必要はありません。まずはクリアするだけ。これもistream_iterator問題ではありませんoperator>>。この状況でも機能する必要があります。

Tache foo;
while (std::cin >> foo) {
    // ...
}

を追加するだけの場合、最初のものの後に続くすべてTacheが間違っています。オブジェクトのすべてのメンバーを初期化するのは完全にユーザーの責任であり、以前の値について何も仮定しないでください。


transform()ループだけに置き換えることをお勧めします:

sregex_token_iterator it(cbegin(precedentTasks), cend(precedentTasks), re, 1), end;
for (; it != end; ++it) {
    rhs.precedentTask.push_back(it->front());
}

またはそれを範囲でラップします:

for (std::string match : sregex_matches(precedentTasks, re, 1)) {
    rhs.precedentTask.push_back(match.front());
}
于 2016-06-06T19:47:56.003 に答える