Domanda

Un comune pezzo di codice che utilizzo per semplici sguardi stringa spaccare in questo modo:

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;
}

Qualcuno ha detto che questo sarà silenziosamente "rondine" errori che si verificano in std::getline. E, naturalmente, sono d'accordo che è il caso. Ma mi venne in mente, cosa potrebbe andare male qui in pratica che avrei avuto bisogno di cui preoccuparsi. in fondo tutto si riduce a questo:

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;
}

Un stringstream è sostenuta da un string, in modo da non devono preoccuparsi di nessuno dei problemi connessi con la lettura da un file. Non v'è alcuna conversione di tipo succedendo qui dal getline legge semplicemente fino a che non vede il delimitatore di linea o EOF. Quindi non siamo in grado di ottenere qualsiasi degli errori che qualcosa di simile boost::lexical_cast deve preoccuparsi.

Ho semplicemente non può pensare a qualcosa oltre non riuscire a allocare memoria sufficiente che poteva andare storto, ma che ti basta gettare un std::bad_alloc ben prima della std::getline ancora avviene. Che cosa mi manca?

È stato utile?

Soluzione

Non riesco a immaginare che cosa gli errori di questa persona pensa che potrebbe accadere, e si dovrebbe chiedere loro di spiegare. Nulla può andare storto, tranne gli errori di allocazione, come lei ha ricordato, che vengono gettati e non ingoiato.

L'unica cosa che vedo che si sta direttamente manca è che ss.fail() è garantito per essere vero, dopo il ciclo while, perché questa è la condizione in fase di test. (bool(stream) è equivalente a !stream.fail(), non stream.good().) Come previsto, ss.eof() sarà anche vero, indica un guasto era dovuto a EOF.

Tuttavia, ci potrebbe essere una certa confusione su ciò che sta realmente accadendo. Perché getline usi delim - terminati campi anziché delim - separato campi, ingresso dati come "a\nb\n" ha due invece di tre campi, e questo potrebbe essere sorprendente. Per le linee questo senso completo (ed è standard POSIX), ma come molti campi, con una delim di '-', ci si può aspettare di trovare in "a-b-" dopo la divisione?


Per inciso, ecco come avrei scrittura spaccatura :

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;
}

Questo evita tutti i problemi con iostreams, in primo luogo, evita copie extra (stringa di sostegno del stringstream, in più la temperatura restituito da substr può anche utilizzare un riferimento di C ++ 0x rvalue per la semantica mossa se supportata, come scritto) , ha il comportamento mi aspetto da split (diverso dal tuo), e funziona con qualsiasi contenitore.

deque<string> c;
split("a-b-", '-', back_inserter(c));
// c == {"a", "b", ""}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top