c++ string boost stl adapter

c++ - Puede impulsar: algorithm:: join() concat un contenedor de flotadores?



string boost (2)

Boost join se puede utilizar para concatenar un contenedor de cadenas opcionalmente separadas por una cadena separadora como se muestra en este ejemplo: Un buen ejemplo para boost :: algorithm :: join

Mis habilidades STL son débiles. Me pregunto si hay alguna forma de usar la misma función para un contenedor de números (flotantes, dobles, enteros). Simplemente parece que debería haber una o dos líneas para adaptarlo a otros tipos.

También hay una función de copia stl con un buen ejemplo que se encuentra aquí: ¿Cómo imprimir el contenido de un vector?

Pero no me gusta cómo agrega la cadena de separación después de cada elemento. Me gustaría usar boost.


Mis habilidades STL son débiles. Me pregunto si de todos modos hay que usar la misma función para un contenedor de números (flotantes, dobles, enteros). Simplemente parece que debería haber una o dos líneas para adaptarlo a otros tipos.

std::accumulate permite doblar sobre cualquier rango de iterador (entrada), usando una función binaria que puede tomar diferentes tipos para el "acumulador" y el siguiente ítem. En su caso: una función que toma un std::string y un double (o lo que sea) que concatena el std::string dado con el resultado de std::to_string en el segundo parámetro.

template<typename Container> std::string contents_as_string(Container const & c, std::string const & separator) { if (c.size() == 0) return ""; auto fold_operation = [&separator] (std::string const & accum, auto const & item) { return accum + separator + std::to_string(item);}; return std::accumulate(std::next(std::begin(c)), std::end(c), std::to_string(*std::begin(c)), fold_operation); }

Como puede ver, esto es completamente independiente del tipo de valor del contenedor. Mientras puedas pasarlo a std::to_string estás bien. En realidad, el código anterior es una pequeña variación del ejemplo presentado para std::accumulate .

Demo de la función anterior :

int main() { std::vector<double> v(4); std::iota(std::begin(v), std::end(v), 0.1); std::cout << contents_as_string(v, ", ") << std::endl; std::vector<int> w(5); std::iota(std::begin(w), std::end(w), 1); std::cout << contents_as_string(w, " x ") << " = " << std::accumulate(std::begin(w), std::end(w), 1, std::multiplies<int>{}) << std::endl; }

0.100000, 1.100000, 2.100000, 3.100000
1 x 2 x 3 x 4 x 5 = 120


Claro, puede combinar boost::algorithm::join y boost::adaptors::transformed para convertir los dobles en cadenas y luego unirlos.

#include <iostream> #include <vector> #include <string> #include <boost/algorithm/string/join.hpp> #include <boost/range/adaptor/transformed.hpp> int main() { using boost::adaptors::transformed; using boost::algorithm::join; std::vector<double> v{1.1, 2.2, 3.3, 4.4}; std::cout << join( v | transformed( static_cast<std::string(*)(double)>(std::to_string) ), ", " ); }

Salida:

1.100000, 2.200000, 3.300000, 4.400000

También puedes usar una lambda para evitar el reparto feo

join(v | transformed([](double d) { return std::to_string(d); }), ", ")