Comment ajouter un caractère à une chaîne std :: string?

175

Ce qui suit échoue avec l'erreur 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;
}

J'ai également essayé ce qui suit, qui compile mais se comporte de manière aléatoire au moment de l'exécution:

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

Désolé pour cette question stupide, mais j'ai cherché dans google, ce que je pouvais voir sont juste "char array to char ptr", "char ptr to char array", etc.

noyade
la source
une erreur du compilateur oui..J'ai oublié quelle est l'erreur, mais c'est raisonnable.
noyade le
3
Vous avez de meilleures réponses ci-dessous, mais vous pouvez faire de votre deuxième exemple fonctionnant comme ceci char d [2] = {'d', 0}; ou simplement char d [2] = "d"; Fondamentalement, vous avez besoin d'un 0 pour terminer votre chaîne de style c que vous passez à ajouter
sbk
Bonne documentation ici: sgi.com/tech/stl/basic_string.html
Martin York

Réponses:

225
y += d;

J'utiliserais un +=opérateur au lieu de fonctions nommées.

AraK
la source
2
pourquoi considérez-vous + = mieux que push_back? Est-ce simplement moins de frappe ou avez-vous une autre raison?
Glen
4
C'est moins tapant. In gcc, basic_string::operator+=est juste un appel push_back.
eduffy
2
Il est plus naturel IMO pour les cordes. push_back est une fonction de conteneur, et une chaîne est une fonction spécialisée dans STL :)
AraK
6
Retournons cette question: pourquoi considérez-vous push_back mieux que + =? À mon avis, + = est clair et concis.
Jesper
34
Vous devez être prudent avec cela car si vous en prenez l'habitude, cela se compilera très bien si yc'est un char*au lieu de std::string. Cela ajouterait des dcaractères au pointeur y.
Zan Lynx
65

Utilisez push_back():

std::string y("Hello worl");
y.push_back('d')
std::cout << y;
Ferdinand Beyer
la source
19

Pour ajouter un caractère à un var std :: string à l'aide de la méthode append, vous devez utiliser cette surcharge:

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

Edit: Vous avez raison, j'ai mal compris le paramètre size_type, affiché dans l'aide contextuelle. Il s'agit du nombre de caractères à ajouter. Donc le bon appel est

s.append(1, d);

ne pas

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

Ou de la manière la plus simple:

s += d;
Patrice Bernassola
la source
Je pense que l'utilisation de sizeof n'est pas sémantiquement correcte ici (même si cela fonctionne car sizeof (char) est toujours un). La méthode append est naturellement plus utile si vous souhaitez ajouter plus de copies du même caractère !!!!!!!!!!
UncleBens
1
Pourquoi utilisez-vous sizeof(char)au lieu de 1? Vous voulez ajouter exactement une répétition de d, alors dites-le simplement. L'utilisation sizeofici est trompeuse car elle suggère que l'on doit indiquer appendla taille en octets du type de données utilisé (ce qui n'est pas le cas).
Ferdinand Beyer
Comme l'a dit Unclebens, la méthode append est vraiment plus utile lors de l'ajout du même caractère plusieurs fois.
Patrice Bernassola
10

En plus des autres mentionnés, l'un des constructeurs de chaînes prend un char et le nombre de répétitions pour ce char. Vous pouvez donc l'utiliser pour ajouter un seul caractère.

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

Je teste les différentes propositions en les exécutant dans une grande boucle. J'ai utilisé Microsoft Visual Studio 2015 comme compilateur et mon processeur est 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;

Selon ce test, les résultats sont:

     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'

Conclusion

+= semble plus compréhensible, mais si la vitesse vous préoccupe, utilisez append

Hugo Zevetel
la source
Pour qu'une telle réponse soit significative, vous devriez au moins dire quel compilateur vous utilisez, car de telles choses peuvent varier beaucoup. Parler de votre processeur peut également être très utile, pour obtenir une estimation approximative de l'impact réel que cela pourrait avoir.
akaltar
J'ai utilisé visual studio 2015. Je chercherai gcc pour faire d'autres tests. Mon processeur est i7, 8 coeurs, 2,20 Ghz .... Mais quel que soit mon processeur il n'aura aucun impact sur l'implémentation std :: string ... sauf si certaines de ces méthodes sont multithread et d'autres non.
Hugo Zevetel
Parfois, cela a un impact, surtout si vous affichez les durées en millisecondes. Au lieu de cela, vous pouvez afficher en pourcentage par rapport à la méthode la plus rapide (la vitesse réelle du processeur n'est donc pas pertinente). Déplacez également ces données du commentaire vers votre réponse, il ne s'agit que de l'étiquette générale de StackExchange. Sinon belle réponse.
akaltar le
6

Essayez l'opérateur + = texte du lien , méthode append () le texte du lien , ou méthode push_back () texte du lien

Les liens de cet article contiennent également des exemples d'utilisation des API respectives.

Michael Berg
la source
2

le problème avec:

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

est que vous devez avoir le 'd' par opposition à l'utilisation d'un nom de caractère, comme char d = 'd'; Ou ai-je tort?

Alex Spencer
la source
Je viens de l'essayer et cela a bien fonctionné. J'ai char c = 'd'et je peux le faire y.push_back(c)sans problème. Il n'y a donc pas de problème avec std::string::push_back()(sauf que c'est plus long 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
}

Notez que dans tous ces exemples que vous auriez pu utiliser un littéral de caractère directement: y += 'd';.

Votre deuxième exemple aurait presque fonctionné, pour des raisons indépendantes. char d[1] = { 'd'};n'a pas fonctionné, mais char d[2] = { 'd'};(note du tableau est de taille deux) aurait été travaillé à peu près la même que const char* d = "d";, et un littéral de chaîne peut être jointe: y.append(d);.

Canard meunier
la source
1

Essayez d'utiliser le d comme pointeur y.append (* d)

2èmeless
la source
C'est dangereux car un single charn'est pas une chaîne et n'a pas de terminateur nul. Cela provoque un comportement indéfini.
Simon Kraemer le
C'est tout simplement faux. *dsignifie un pointeur de dé-référence dqui est une erreur de syntaxe car dn'est pas un pointeur.
Franklin Yu
0
str.append(10u,'d'); //appends character d 10 times

Remarquez que j'ai écrit 10u et non 10 pour le nombre de fois où j'aimerais ajouter le caractère; remplacez 10 par n'importe quel nombre.

Ioan Stef
la source
0

J'ai trouvé un moyen simple ... J'avais besoin de clouer un charsur une corde qui était construite à la volée. J'avais besoin d'un char list;car je donnais un choix à l'utilisateur et en utilisant ce choix dans unswitch() déclaration.

J'ai simplement ajouté une autre std::string Slist;et défini la nouvelle chaîne égale au caractère, "liste" - a, b, c ou tout ce que l'utilisateur final choisit comme ceci:

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 complexité peut être cool mais la simplicité est plus cool. A mon humble avis

Charles H
la source
0

Ajout également une option d'insertion, comme pas encore mentionné.

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
la source
-1

Si vous utilisez le push_back, il n'y a pas d'appel pour le constructeur de chaîne. Sinon, il créera un objet chaîne via la conversion, puis il ajoutera le caractère de cette chaîne à l'autre chaîne. Trop de problèmes pour un petit personnage;)

progicien
la source
1
opérateur + = (car c); est surchargé pour les chaînes. En fait, le constructeur de chaîne n'accepte pas un caractère, voir la réponse de Brian;)
AraK