Pregunta

Una pieza común de código que utilizo para simples miradas cadena de división de la siguiente manera:

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

Alguien mencionó que este silencio se "golondrina" errores que ocurren en std::getline. Y, por supuesto, estoy de acuerdo que es el caso. Pero se me ocurrió, lo que podría salir mal aquí en la práctica que yo tendría que preocuparse. Básicamente todo se reduce a esto:

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

A stringstream está respaldado por una string, por lo que no tiene que preocuparse por ninguno de los problemas asociados con la lectura de un archivo. No hay ningún tipo de conversión pasando aquí desde getline simplemente lee hasta que ve el delimitador de línea o EOF. Así que no podemos obtener cualquiera de los errores que algo como boost::lexical_cast tiene que preocuparse.

Yo simplemente no puede pensar en algo además de no asignar suficiente memoria que podía salir mal, pero eso sólo va a lanzar una std::bad_alloc mucho antes de la std::getline incluso se lleva a cabo. ¿Qué me falta?

¿Fue útil?

Solución

No se puede imaginar lo que los errores de esta persona piensa que podría suceder, y usted debe pedirle que le explique. Nada puede salir mal, salvo errores de asignación, como usted ha mencionado, que sea derribado y no se ingiere.

La única cosa que veo que está directamente faltante es que ss.fail() está garantizada para ser verdad después de que el bucle while, porque esa es la condición que está siendo probado. (bool(stream) es equivalente a !stream.fail(), no stream.good().) Como se esperaba, ss.eof() también será cierto, lo que indica el fracaso se debió a EOF.

Sin embargo, puede haber cierta confusión sobre lo que realmente está sucediendo. Debido getline usos delim - terminados campos en lugar de delim - separados campos, de entrada datos tales como "a\nb\n" tiene dos en lugar de tres campos, y esto podría ser sorprendente. Para las líneas que esto tenga sentido completo (y es estándar POSIX), pero la forma en muchos campos, con un delim de '-', habría que esperar encontrar en "a-b-" después de dividir?


Por cierto, aquí está cómo había escribir dividida :

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

Esto evita todos los problemas con iostreams en primer lugar, evita copias adicionales (cadena respaldo del stringstream; más la temp devuelto por substr puede incluso utilizar una referencia C ++ 0x rvalue para la semántica de movimiento si es compatible, tal como está escrita) , tiene el comportamiento que espero de división (diferente a la suya), y funciona con cualquier contenedor.

deque<string> c;
split("a-b-", '-', back_inserter(c));
// c == {"a", "b", ""}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top