Tengo un vector<int>
contenedor que tiene números enteros (por ejemplo, {1,2,3,4}) y me gustaría convertir a una cadena de la forma
"1,2,3,4"
¿Cuál es la forma más limpia de hacer eso en C ++? En Python así es como lo haría:
>>> array = [1,2,3,4]
>>> ",".join(map(str,array))
'1,2,3,4'
Respuestas:
Definitivamente no es tan elegante como Python, pero nada es tan elegante como Python en C ++.
Podrías usar un
stringstream
...También puede utilizar en su
std::for_each
lugar.fuente
std::string s = ss.str()
. Si quieresconst char*
, usas.c_str()
. (Tenga en cuenta que, si bien es sintácticamente correcto,ss.str().c_str()
le dará unconst char*
que apunta a un temporal que dejará de existir al final de la expresión completa. Eso duele.)#include <sstream>
Usando std :: for_each y lambda puedes hacer algo interesante.
Vea esta pregunta para una pequeña clase que escribí. Esto no imprimirá la coma final. Además, si asumimos que C ++ 14 continuará dándonos equivalentes basados en rangos de algoritmos como este:
fuente
Puede usar std :: acumular. Considere el siguiente ejemplo
fuente
','
debería ser","
string
clase tiene una sobrecarga para el+
operador que también puede aceptar caracteres. Entonces','
está bien.Otra alternativa es el uso de
std::copy
y laostream_iterator
clase:Tampoco es tan agradable como Python. Para este propósito, creé una
join
función:Luego lo usó así:
Podrías preguntar por qué pasé los iteradores. Bueno, en realidad quería revertir la matriz, así que la usé así:
Idealmente, me gustaría hacer una plantilla hasta el punto en que pueda inferir el tipo de char y usar cadenas de secuencias, pero aún no pude entenderlo.
fuente
join
función también se puede utilizar con vectores? ¿Podría dar un ejemplo? Soy nuevo en C ++.Con Boost y C ++ 11 esto podría lograrse así:
Bueno, casi. Aquí está el ejemplo completo:
Crédito a Praetorian .
Puede manejar cualquier tipo de valor como este:
fuente
Esto es solo un intento de resolver el acertijo dado por el comentario de 1800 INFORMATION sobre su segunda solución que carece de genérico, no un intento de responder la pregunta:
Funciona en mi máquina (TM).
fuente
operator<<
sobrecargado). Por supuesto, un tipo sinoperator<<
puede causar mensajes de error muy confusos.join(v.begin(), v.end(), ",")
. La deducción del argumento de plantilla no produce el resultado correcto si elsep
argumento es un literal de cadena. Mi intento de solucionar este problema . También proporciona una sobrecarga basada en rango más moderna.Muchas plantillas / ideas. El mío no es tan genérico o eficiente, pero simplemente tuve el mismo problema y quería incluir esto en la mezcla como algo corto y dulce. Gana en el menor número de líneas ... :)
fuente
substr(...)
, usepop_back()
para eliminar el último carácter, se vuelve mucho más claro y limpio.Si quieres hacerlo
std::cout << join(myVector, ",") << std::endl;
, puedes hacer algo como:Tenga en cuenta que esta solución realiza la unión directamente en el flujo de salida en lugar de crear un búfer secundario y funcionará con cualquier tipo que tenga un operador << en un ostream.
Esto también funciona donde
boost::algorithm::join()
falla, cuando tiene un envector<char*>
lugar de unvector<string>
.fuente
fuente
std::stringstream
para matrices grandes porquestringstream
podrá asignar memoria de manera optimista, lo que conducirá a un rendimiento de O (n.log (n)) en lugar de O (n²) para una matriz de tamañon
para esta respuesta. Además, esstringstream
posible que no cree cadenas temporales parato_string(i)
.Me gusta la respuesta de 1800. Sin embargo, movería la primera iteración fuera del ciclo como resultado de la instrucción if solo cambia una vez después de la primera iteración
Por supuesto, esto se puede reducir a menos declaraciones si lo desea:
fuente
++i
excepto donde realmente lo necesitabani++
porque esa era la única forma en que no olvidaban esto cuando marcaba la diferencia. (A mí me pasó lo mismo, por cierto). Habían aprendido Java antes, donde todo tipo de C-ismos están de moda y les tomó unos meses (1 conferencia + trabajo de laboratorio por semana), pero al final la mayoría de aprendieron el hábito de utilizar el preincremento.Hay algunos intentos interesantes de proporcionar una solución elegante al problema. Tuve la idea de usar secuencias con plantillas para responder de manera efectiva al dilema original del OP. Aunque esta es una publicación antigua, espero que los futuros usuarios que se encuentren con esto encuentren que mi solución es beneficiosa.
Primero, algunas respuestas (incluida la respuesta aceptada) no promueven la reutilización. Dado que C ++ no proporciona una forma elegante de unir cadenas en la biblioteca estándar (que he visto), es importante crear una que sea flexible y reutilizable. Aquí está mi oportunidad:
Ahora, para usar esto, simplemente podría hacer algo como lo siguiente:
Observe cómo el uso de flujos hace que esta solución sea increíblemente flexible, ya que podemos almacenar nuestro resultado en un flujo de cadenas para recuperarlo más tarde, o podemos escribir directamente en la salida estándar, un archivo o incluso en una conexión de red implementada como flujo. El tipo que se imprime debe ser simplemente iterable y compatible con el flujo de origen. STL proporciona varios flujos que son compatibles con una amplia gama de tipos. Así que realmente podrías ir a la ciudad con esto. En la parte superior de mi cabeza, su vector puede ser de int, float, double, string, unsigned int, SomeObject * y más.
fuente
Creé un archivo de encabezado auxiliar para agregar un soporte de unión extendido.
Simplemente agregue el código a continuación a su archivo de encabezado general e inclúyalo cuando sea necesario.
Ejemplos de uso:
El código detrás de escena:
fuente
Aquí hay una solución genérica de C ++ 11 que le permitirá hacer
El codigo es:
fuente
La siguiente es una forma sencilla y práctica de convertir elementos de a en
vector
astring
:Necesitas
#include <sstream>
paraostringstream
.fuente
Ampliando el intento de @sbi en una solución genérica que no está restringida
std::vector<int>
o un tipo de cadena de retorno específico. El código que se presenta a continuación se puede utilizar así:En el código original, la deducción del argumento de la plantilla no funciona para producir el tipo de cadena de retorno correcto si el separador es un literal de cadena (como en los ejemplos anteriores). En este caso, las definiciones de tipo como
Str::value_type
en el cuerpo de la función son incorrectas. El código asume queStr
siempre es un tipo comostd::basic_string
, por lo que obviamente falla para los literales de cadena.Para solucionar este problema, el siguiente código intenta deducir solo el tipo de carácter del argumento separador y lo usa para producir un tipo de cadena de retorno predeterminado. Esto se logra usando
boost::range_value
, que extrae el tipo de elemento del tipo de rango dado .Ahora podemos proporcionar fácilmente una sobrecarga basada en rango que simplemente se reenvía a la sobrecarga basada en iteradores:
Demo en vivo en Coliru
fuente
como lo hizo @capone,
Entonces podemos llamar como sigue:
al igual que Python:
fuente
Yo uso algo como esto
fuente
Comencé con la respuesta de @ sbi, pero la mayoría de las veces terminé conectando la cadena resultante a una secuencia, por lo que creé la siguiente solución que se puede canalizar a una secuencia sin la sobrecarga de crear la cadena completa en la memoria.
Se utiliza de la siguiente manera:
Donde string_join.h es:
fuente
He escrito el siguiente código. Está basado en C # string.join. Funciona con std :: string y std :: wstring y muchos tipos de vectores. (ejemplos en comentarios)
Llámalo así:
Código:
fuente
A continuación, se muestra una forma sencilla de convertir un vector de números enteros en cadenas.
fuente
unirse usando la función de plantilla
Utilicé un
template
function
para unir losvector
elementos y eliminé laif
declaración innecesaria iterando solo del primero al penúltimo elemento en elvector
y luego uniéndome al último elemento después delfor
ciclo. Esto también evita la necesidad de código adicional para eliminar el separador adicional al final de la cadena unida. Por lo tanto, no hayif
declaraciones que ralenticen la iteración ni separadores superfluos que necesiten arreglarse.Esto produce un elegante llamada de función para unirse a una
vector
destring
,integer
odouble
, etc.Escribí dos versiones: una devuelve una cadena; el otro escribe directamente en una secuencia.
Salida
fuente