0

ファイルからの読み取り中に getline に関して奇妙な問題があります。

以下はコードです。

#include <fstream>
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;

struct call {
    string l;
            string k;
};

int main () {
    ifstream read;
    string fn = "in.txt";
    string temp;
    call mc;
    vector<call> vcall;

    read.open (fn.c_str ());

    while (getline (read, temp)) {

        temp.erase (temp.end () - 1);

        if (temp.substr (0,1).compare ("L") == 0) {
            temp = temp.substr (7);
            stringstream ss (temp);
            while (ss) {
                getline (ss, mc.l, ':');
                getline (ss, mc.k, ':');
                vcall.push_back (mc);
            }
        }
    }
    for (int i = 0; i < vcall.size (); i++) {
        cout << vcall [i].i << vcall [i].k << endl;
    }

}

テキスト ファイル in.txt には行が含まれています。

Los:0:A:1:B:2:C:3:D:4:E:

プログラムからの出力は私に与えます。

0A
1B
2C
3D
4E
4E

なぜそうなのかはわかりません。出力に最後の (別の) 4 があってはなりません。

テキストファイルを再作成し、コードを別のファイルに書き直してコンパイルしようとしました。Ubuntu (g++) と Windows (mingw) で試してみましたが、まだ同じ問題が発生しています。

アップデート:

while (getline (ss, mc.l, ':')) を使用しなかった理由は、複数の部分が必要だからです。上記のコードにわずかな変更を加え、構造体に 2 つの文字列を格納しました。また、変更を反映するためにテキスト ファイルに変更を加えました。

では、どうすればよいのでしょうか。ありがとう。

4

2 に答える 2

1

これを変える:

 while (ss) {
     getline (ss, mc.l, ':');
     vcall.push_back (mc);
 }

これに:

while (getline(ss, mc.l, ':')) {
    vcall.push_back(mc);
}

問題は、アイテムをベクターに追加するまで、読み取りが失敗したかどうかをチェックしないことです。したがって、最後の読み取りが失敗すると、前回のgetlineの呼び出しから変更されていないアイテムが、再びベクターにプッシュバックされます。変更されたバージョンは、読み取りが失敗するとすぐに無効になります。このイディオムは、ファイルから行を読み取るプライマリforループで使用しました。それで、なぜあなたはそれをstringstreamで使用しなかったのだろうか。

更新に応じて:

while (getline(ss, mc.l, ':') && getline(ss, mc.k, ':')) {
    vcall.push_back(mc);
}

whileステートメントの条件が扱いにくくなっていることに気付いた場合は、いつでも次のようなことを行うことができます。

while (true) {
    getline(ss, mc.l, ':');
    getline(ss, mc.k, ':');
    if (!ss)
        break;
    vcall.push_back(mc);
}
于 2012-11-19T18:38:52.443 に答える
1

内側のループ:

while (ss)
{
  getline (ss, mc.l, ':');
  vcall.push_back (mc);
}

次のように書く必要があります:

while (getline (ss, mc.l, ':'))
{
  vcall.push_back (mc);
}

外側のループ用にこの慣用的なループをすでに作成しました。

于 2012-11-19T18:39:21.487 に答える