Frage

Ein gemeinsames Stück Code, den ich für einfaches String-Splitting sieht wie folgt verwendet werden:

inline std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

Jemand erwähnte, dass dies leise „schlucken“ Fehler in std::getline auftreten. Und natürlich stimme ich das der Fall ist. Aber es fiel mir ein, was möglicherweise schief gehen könnte in der Praxis , dass ich zu kümmern braucht. im Grunde ist es läuft alles auf diese nach unten:

inline std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }

    if(/* what error can I catch here? */) {
        // *** How did we get here!? ***
    }

    return elems;
}

Ein stringstream wird von einem string gesichert, so dass wir zu Sorgen über jede der Fragen, nicht im Zusammenhang mit aus einer Datei zu lesen. Es gibt keine Typumwandlung geht hier vor, da getline liest einfach, bis sie die Linie delimeter oder EOF sieht. Also haben wir eine der Fehler, dass so etwas wie boost::lexical_cast etwa muss sich keine Sorgen bekommen.

Ich kann einfach nicht glauben, etwas anderes als Fehler genügend Speicher zuweisen, die schief gehen könnten, aber das wird nur wirft einen std::bad_alloc gut, bevor die std::getline selbst stattfindet. Was bin ich?

War es hilfreich?

Lösung

Ich kann mir nicht vorstellen, welche Fehler diese Person könnte passieren, denkt, und Sie sollten sie bitten, zu erklären. Nichts kann außer Zuordnungsfehler schief gehen, wie Sie bereits erwähnt, die geworfen werden und nicht geschluckt.

Das einzige, was ich sehe, dass Sie direkt ist fehlt, ist, dass ss.fail() garantiert wird nach der while-Schleife um wahr zu sein, denn das ist die Bedingung geprüft wird. (bool(stream) entspricht !stream.fail(), nicht stream.good().) Wie erwartet, ss.eof() wird auch wahr sein, was auf das Scheitern zu EOF zurückzuführen ist.

Es könnte jedoch einige Verwirrung über das, was tatsächlich geschieht. Da getline verwendet delim - beendet Felder anstatt delim - getrennt Felder, Eingabe Daten wie "a\nb\n" haben zwei statt drei Felder, und das überraschend sein könnte. Für Linien macht dies durchaus Sinn (und ist POSIX-Standard), aber wie viele Felder mit einem delim von '-', würden Sie in "a-b-" nach der Trennung zu erwarten dürfen


Im übrigen ist hier, wie ich würde schreiben Split :

template<class OutIter>
OutIter split(std::string const& s, char delim, OutIter dest) {
  std::string::size_type begin = 0, end;
  while ((end = s.find(delim, begin)) != s.npos) {
    *dest++ = s.substr(begin, end - begin);
    begin = end + 1;
  }
  *dest++ = s.substr(begin);
  return dest;
}

Diese all Probleme mit iostreams in erster Linie verhindern, vermeidet zusätzliche Kopien (die Trägersaite von string; plus die Temperatur von substr zurückgegeben wird, kann auch eine C ++ 0x rvalue Referenz für Bewegung Semantik verwenden, wenn unterstützt, wie geschrieben) , hat das Verhalten, das ich von Split (anders verkauft) erwarten, und arbeitet mit jedem Behälter.

deque<string> c;
split("a-b-", '-', back_inserter(c));
// c == {"a", "b", ""}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top