sume - resta c++




Una forma sencilla de dividir una secuencia de cadenas separadas por nulos en C++ (5)

Tengo una serie de cadenas almacenadas en una sola matriz, separadas por nulos (por ejemplo, ['f', 'o', 'o', '\ 0', 'b', 'a', 'r', '\ 0 '...]), y necesito dividir esto en un std::vector<std::string> o similar.

Podría escribir un bucle de 10 líneas para hacer esto usando std::find o strlen (de hecho, acabo de hacerlo), pero me pregunto si hay una forma más simple / elegante de hacerlo, por ejemplo, algún algoritmo STL. Lo he pasado por alto, lo que puede ser persuadido para hacer esto.

Es una tarea bastante simple, y no me sorprendería si hubiera algún truco STL inteligente que se pueda aplicar para hacerlo aún más simple.

¿Ningún arrendatario?


Aquí está la solución que se me ocurrió, asumiendo que el búfer termina inmediatamente después de la última cadena:

std::vector<std::string> split(const std::vector<char>& buf) {
    auto cur = buf.begin();
    while (cur != buf.end()) {
        auto next = std::find(cur, buf.end(), '\0');
        drives.push_back(std::string(cur, next));
        cur = next + 1;
    }
    return drives;
}

En C, string.h tiene este chico:

char * strtok ( char * str, const char * delimiters );

el ejemplo en cplusplus.com:

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

No es C ++, pero funcionará.


Mis dos centavos :

const char* p = str;
std::vector<std::string> vector;

do {
  vector.push_back(std::string(p));
  p += vector.back().size() + 1;
} while ( // whatever condition applies );

Solución de impulso:

#include <boost/algorithm/string.hpp>
std::vector<std::string> strs;
//input_array must be a Range containing the input.
boost::split(
    strs,
    input_array,
    boost::is_any_of(boost::as_array("\0")));

Una solución más elegante y real (en comparación con mi otra respuesta) utiliza getline y se reduce a 2 líneas con solo C ++ 2003, y no se requiere una contabilidad y acondicionamiento de bucles manuales:

#include <iostream>
#include <sstream>
#include <string>

int main() {
    const char foo[] = "meh\0heh\0foo\0bar\0frob";

    std::istringstream ss (std::string(foo, foo + sizeof foo));
    std::string str;

    while (getline (ss, str, '\0'))
        std::cout << str << '\n';
}

Sin embargo, tenga en cuenta que el constructor de cadenas basado en rango ya indica un problema inherente con la división en - '\ 0's: debe saber el tamaño exacto, o encontrar otro char-combo para el Ultimate Terminator.





std