¿Cómo agregar un carácter a un std :: string?

175

Lo siguiente falla con el error prog.cpp:5:13: error: invalid conversion from ‘char’ to ‘const char*’

int main()
{
  char d = 'd';
  std::string y("Hello worl");
  y.append(d); // Line 5 - this fails
  std::cout << y;
  return 0;
}

También probé lo siguiente, que se compila pero se comporta aleatoriamente en tiempo de ejecución:

int main()
{
  char d[1] = { 'd' };
  std::string y("Hello worl");
  y.append(d);
  std::cout << y;
  return 0;
}

Perdón por esta pregunta tonta, pero he buscado en google, lo que pude ver son "char array to char ptr", "char ptr to char array", etc.

ahogamiento
fuente
un error del compilador sí ... Olvidé cuál es el error, pero es razonable.
ahogado
3
A continuación tiene mejores respuestas, pero puede hacer que su segundo ejemplo funcione de esta manera char d [2] = {'d', 0}; o simplemente char d [2] = "d"; Básicamente, necesita un 0 para terminar la cadena de estilo c que pasa para
agregarla
Buena documentación aquí: sgi.com/tech/stl/basic_string.html
Martin York

Respuestas:

225
y += d;

Usaría +=operador en lugar de funciones con nombre.

AraK
fuente
2
¿Por qué considera + = mejor que push_back? ¿Es solo menos escribir o tienes otra razón?
Glen
44
Es menos escribir. En gcc, basic_string::operator+=es solo una llamada push_back.
eduffy
2
Es más natural IMO para cuerdas. push_back es la función de contenedor, y una cadena es especializada en STL :)
AraK
66
Cambiemos esa pregunta: ¿Por qué considera push_back mejor que + =? En mi opinión, + = es claro y conciso.
Jesper
34
Desea tener cuidado con esto porque si adquiere el hábito, esto se compilará bien si yes un en char*lugar de std::string. Agregaría dcaracteres al puntero y.
Zan Lynx
65

Uso push_back():

std::string y("Hello worl");
y.push_back('d')
std::cout << y;
Fernando Beyer
fuente
19

Para agregar un carácter a un std :: string var usando el método append, debe usar esta sobrecarga:

std::string::append(size_type _Count, char _Ch)

Editar: Tienes razón, no entendí el parámetro size_type, que se muestra en la ayuda contextual. Este es el número de caracteres para agregar. Entonces la llamada correcta es

s.append(1, d);

no

s.append(sizeof(char), d);

O la forma más simple:

s += d;
Patrice Bernassola
fuente
Creo que usar sizeof no es semánticamente correcto aquí (a pesar de que funciona porque sizeof (char) siempre es uno). ¡El método de agregar es naturalmente más útil si desea agregar más copias del mismo personaje!
UncleBens
1
¿Por qué estás usando en sizeof(char)lugar de 1? Desea agregar exactamente una repetición de d, así que solo dígalo. Usar sizeofaquí es engañoso ya que sugiere que uno tiene que decir appendel tamaño del byte del tipo de datos utilizado (que no es el caso).
Ferdinand Beyer
Como dijo Unclebens, el método append es realmente más útil cuando se agrega el mismo carácter muchas veces.
Patrice Bernassola
10

Además de los otros mencionados, uno de los constructores de cadenas toma un carácter y el número de repeticiones para ese carácter. Entonces puede usar eso para agregar un solo carácter.

std::string s = "hell";
s += std::string(1, 'o');
Brian R. Bondy
fuente
7

Pruebo las varias proposiciones ejecutándolas en un bucle grande. Utilicé Microsoft Visual Studio 2015 como compilador y mi procesador es un i7, 8Hz, 2GHz.

    long start = clock();
    int a = 0;
    //100000000
    std::string ret;
    for (int i = 0; i < 60000000; i++)
    {
        ret.append(1, ' ');
        //ret += ' ';
        //ret.push_back(' ');
        //ret.insert(ret.end(), 1, ' ');
        //ret.resize(ret.size() + 1, ' ');
    }
    long stop = clock();
    long test = stop - start;
    return 0;

Según esta prueba, los resultados son:

     operation             time(ms)            note
------------------------------------------------------------------------
append                     66015
+=                         67328      1.02 time slower than 'append'
resize                     83867      1.27 time slower than 'append'
push_back & insert         90000      more than 1.36 time slower than 'append'

Conclusión

+= parece más comprensible, pero si te importa la velocidad, usa append

Hugo Zevetel
fuente
Para que tal respuesta sea significativa, al menos debe decir qué compilador está utilizando, porque tales cosas pueden variar MUCHO. También puede ser bueno contarle sobre su procesador, para obtener una estimación aproximada del impacto real que esto podría tener.
akaltar
Usé Visual Studio 2015. Buscaré gcc para hacer otras pruebas. Mi procesador es i7, 8 corazones, 2.20 Ghz ... Pero cualquiera que sea mi procesador, no tendrá impacto en la implementación de std :: string ... excepto si algunos de estos métodos son multiproceso y otros no.
Hugo Zevetel
A veces tiene un impacto, especialmente si muestra tiempos en milisegundos. En su lugar, puede mostrar en porcentaje en relación con el método más rápido (por lo que la velocidad real del procesador es irrelevante). También mueva esos datos del comentario a su respuesta, esto es solo la etiqueta general de StackExchange. De lo contrario, buena respuesta.
akaltar
2

El problema con:

std::string y("Hello worl");
y.push_back('d')
std::cout << y;

es que tienes que tener la 'd' en lugar de usar el nombre de un char, como char d = 'd'; ¿O estoy equivocado?

Alex Spencer
fuente
Lo intenté y funcionó bien. Tengo char c = 'd'y puedo hacerlo y.push_back(c)sin problema. Entonces no hay problema con std::string::push_back()(excepto que es más largo que +=).
Franklin Yu
1
int main()
{
  char d = 'd';
  std::string y("Hello worl");

  y += d;
  y.push_back(d);
  y.append(1, d); //appending the character 1 time
  y.insert(y.end(), 1, d); //appending the character 1 time
  y.resize(y.size()+1, d); //appending the character 1 time
  y += std::string(1, d); //appending the character 1 time
}

Tenga en cuenta que en todos estos ejemplos se podría haber utilizado un literal de caracteres directamente: y += 'd';.

Su segundo ejemplo casi habría funcionado, por razones no relacionadas. char d[1] = { 'd'};No funcionó, pero char d[2] = { 'd'};habría sido trabajado más o menos lo mismo que (nota la matriz es de tamaño dos) const char* d = "d";, y una literal de cadena puede ser anexado: y.append(d);.

Pato mugido
fuente
1

Intente usar la d como puntero y.append (* d)

2do
fuente
Eso es peligroso ya que un single charno es una cadena y no tiene un terminador nulo. Hacer esto provoca un comportamiento indefinido.
Simon Kraemer
Esto es simplemente incorrecto. *dsignifica puntero de desreferencia dque es un error de sintaxis ya dque no es un puntero.
Franklin Yu
0
str.append(10u,'d'); //appends character d 10 times

Tenga en cuenta que he escrito 10u y no 10 para la cantidad de veces que me gustaría agregar el carácter; reemplace 10 con cualquier número.

Ioan Stef
fuente
0

Encontré una manera simple ... necesitaba unir charuna cuerda que se estaba construyendo sobre la marcha. Necesitaba un char list;porque le estaba dando una opción al usuario y estaba usando esa opción en unswitch() declaración.

Simplemente agregué otro std::string Slist;y configuré la nueva cadena igual al carácter, "lista" - a, b, co lo que el usuario final elija así:

char list;
std::string cmd, state[], Slist;
Slist = list; //set this string to the chosen char;
cmd = Slist + state[x] + "whatever";
system(cmd.c_str());

La complejidad puede ser genial, pero la simplicidad es más fría. En mi humilde opinión

Charles H
fuente
0

También se agrega la opción de inserción, como no se ha mencionado todavía.

std::string str("Hello World");
char ch;

str.push_back(ch);  //ch is the character to be added
OR
str.append(sizeof(ch),ch);
OR
str.insert(str.length(),sizeof(ch),ch) //not mentioned above
Gopesh Bharadwaj
fuente
-1

Si está utilizando push_back, no hay llamada para el constructor de cadenas. De lo contrario, creará un objeto de cadena mediante la conversión, luego agregará el carácter de esta cadena a la otra cadena. Demasiados problemas para un personaje pequeño;)

progician
fuente
1
operador + = (char c); está sobrecargado para cadenas. De hecho, el constructor de cadena no acepta un carácter, ver a Brian respuesta;)
Arak