Je travaille en C et je dois concaténer quelques choses.
En ce moment, j'ai ceci:
message = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
Maintenant, si vous avez de l'expérience en C, je suis sûr que vous vous rendez compte que cela vous donne un problème de segmentation lorsque vous essayez de l'exécuter. Alors, comment puis-je contourner cela?
c
string
concatenation
The.Anti.9
la source
la source
Réponses:
En C, les "chaînes" ne sont que des
char
tableaux simples . Par conséquent, vous ne pouvez pas les concaténer directement avec d'autres "chaînes".Vous pouvez utiliser la
strcat
fonction, qui ajoute la chaîne pointée parsrc
à la fin de la chaîne pointée pardest
:Voici un exemple de cplusplus.com :
Pour le premier paramètre, vous devez fournir le tampon de destination lui-même. Le tampon de destination doit être un tampon de tableau de caractères. Par exemple:
char buffer[1024];
Assurez-vous que le premier paramètre a suffisamment d'espace pour stocker ce que vous essayez de copier dedans. Si vous en disposez, il est plus sûr d'utiliser des fonctions telles que:
strcpy_s
etstrcat_s
où vous devez explicitement spécifier la taille du tampon de destination.Remarque : Un littéral de chaîne ne peut pas être utilisé comme tampon, car il s'agit d'une constante. Ainsi, vous devez toujours allouer un tableau de caractères pour le tampon.
La valeur de retour de
strcat
peut simplement être ignorée, elle renvoie simplement le même pointeur que celui qui a été transmis comme premier argument. Il est là pour votre commodité et vous permet de chaîner les appels en une seule ligne de code:Ainsi, votre problème pourrait être résolu comme suit:
la source
Évitez d'utiliser
strcat
en code C. Le moyen le plus propre et, surtout, le plus sûr est d'utilisersnprintf
:Certains commentateurs ont soulevé un problème selon lequel le nombre d'arguments peut ne pas correspondre à la chaîne de format et le code sera toujours compilé, mais la plupart des compilateurs émettent déjà un avertissement si tel est le cas.
la source
snprintf()
est un GRAND non non.sizeof(x)
etsizeof x
. La notation entre parenthèses fonctionne toujours et la notation non entre parenthèses ne fonctionne que parfois, utilisez donc toujours la notation entre parenthèses; c'est une règle simple à retenir et sûre. Cela entre dans un argument religieux - j'ai été impliqué dans des discussions avec ceux qui s'y opposent auparavant - mais la simplicité de `` toujours utiliser des parenthèses '' l'emporte sur tout mérite de ne pas les utiliser (IMNSHO, bien sûr). Ceci est présenté pour l'équilibre.Mes amis , utilisez str n cpy (), str n cat () ou s n printf ().
Le dépassement de votre espace tampon mettra à la poubelle tout ce qui suit en mémoire!
(Et n'oubliez pas de laisser de l'espace pour le caractère '\ 0' nul final!)
la source
strncpy()
. Ce n'est pas une version "plus sûre" destrcpy()
. Le tableau de caractères cible peut être inutilement complété avec des'\0'
caractères supplémentaires , ou pire, il peut être laissé sans terminaison (c'est-à-dire pas une chaîne). (Il a été conçu pour être utilisé avec une structure de données qui est rarement utilisée, un tableau de caractères rembourré à la fin avec zéro ou plusieurs'\0'
caractères.)Les chaînes peuvent également être concaténées au moment de la compilation.
la source
Malloc et realloc sont également utiles si vous ne savez pas à l'avance combien de chaînes sont concaténées.
la source
num_words>INT_MAX
, vous devriez peut-être utilisersize_t
pouri
N'oubliez pas d'initialiser le tampon de sortie. Le premier argument de strcat doit être une chaîne terminée par null avec suffisamment d'espace supplémentaire alloué pour la chaîne résultante:
la source
Comme les gens l'ont souligné, la gestion des chaînes s'est beaucoup améliorée. Vous souhaiterez donc peut-être apprendre à utiliser la bibliothèque de chaînes C ++ au lieu des chaînes de style C. Cependant voici une solution en C pur
Je ne suis pas sûr que ce soit correct / sûr mais pour le moment je n'ai pas pu trouver une meilleure façon de le faire dans ANSI C.
la source
<string.h>
est de style C ++. Tu veux"string.h"
. Vous calculez égalementstrlen(s1)
deux fois, ce qui n'est pas nécessaire.s3
devrait êtretotalLenght+1
long."string.h"
c'est un non-sens.#include <string.h>
est correct C. Utilisez des équerres pour les en-têtes standard et système (y compris<string.h>
), des guillemets pour les en-têtes qui font partie de votre programme. (#include "string.h"
cela fonctionnera si vous n'avez pas votre propre fichier d'en-tête sous ce nom, mais utilisez<string.h>
quand même.)C'est un comportement indéfini d'essayer de modifier les littéraux de chaîne, ce qui ressemble à quelque chose comme:
va tenter de faire. Il essaiera de clouer la
name
chaîne jusqu'à la fin du littéral de chaîne"Hello, "
, ce qui n'est pas bien défini.Essayez quelque chose comme ça. Il réalise ce que vous semblez essayer de faire:
Cela crée une zone tampon qui peut être modifiée, puis y copie à la fois le littéral de chaîne et tout autre texte. Faites juste attention aux débordements de tampon. Si vous contrôlez les données d'entrée (ou vérifiez-les au préalable), c'est bien d'utiliser des tampons de longueur fixe comme moi.
Sinon, vous devez utiliser des stratégies d'atténuation telles que l'allocation de suffisamment de mémoire à partir du tas pour vous assurer que vous pouvez le gérer. En d'autres termes, quelque chose comme:
la source
Le premier argument de strcat () doit pouvoir contenir suffisamment d'espace pour la chaîne concaténée. Allouez donc un tampon avec suffisamment d'espace pour recevoir le résultat.
strcat () concatène le deuxième argument avec le premier argument et stocke le résultat dans le premier argument, le caractère retourné * est simplement ce premier argument, et uniquement pour votre commodité.
Vous n'obtenez pas une chaîne nouvellement allouée avec le premier et le deuxième argument concaténés, ce que je suppose que vous attendiez en fonction de votre code.
la source
La meilleure façon de le faire sans avoir une taille de tampon limitée est d'utiliser asprintf ()
la source
char *
, nonconst char *
. La valeur de retour devra être transmise àfree
.asprintf
n'est malheureusement qu'une extension GNU.Si vous avez de l'expérience en C, vous remarquerez que les chaînes ne sont que des tableaux de caractères où le dernier caractère est un caractère nul.
Maintenant, c'est assez gênant car vous devez trouver le dernier caractère pour ajouter quelque chose.
strcat
fera cela pour vous.Donc, strcat recherche dans le premier argument un caractère nul. Ensuite, il remplacera cela par le contenu du deuxième argument (jusqu'à ce que cela se termine par un null).
Passons maintenant en revue votre code:
Ici, vous ajoutez quelque chose au pointeur sur le texte "TEXT" (le type de "TEXT" est const char *. A pointer.).
Cela ne fonctionnera généralement pas. La modification du tableau "TEXT" ne fonctionnera pas non plus car il est généralement placé dans un segment constant.
Cela pourrait mieux fonctionner, sauf que vous essayez à nouveau de modifier des textes statiques. strcat n'alloue pas de nouvelle mémoire pour le résultat.
Je proposerais de faire quelque chose comme ceci à la place:
Lisez la documentation de
sprintf
pour vérifier ses options.Et maintenant un point important:
Assurez-vous que le tampon a suffisamment d'espace pour contenir le texte ET le caractère nul. Il existe quelques fonctions qui peuvent vous aider, par exemple strncat et des versions spéciales de printf qui allouent le tampon pour vous. Ne pas garantir la taille de la mémoire tampon entraînera une corruption de la mémoire et des bogues exploitables à distance.
la source
"TEXT"
estchar[5]
, nonconst char*
. Il se désintègrechar*
dans la plupart des contextes. Pour des raisons de compatibilité descendante, les littéraux de chaîne ne le sont pasconst
, mais tenter de les modifier entraîne un comportement non défini. (En C ++, les littéraux de chaîne sontconst
.)Vous pouvez écrire votre propre fonction qui fait la même chose que
strcat()
mais cela ne change rien:Si les deux chaînes contiennent plus de 1 000 caractères, la chaîne sera coupée à 1 000 caractères. Vous pouvez modifier la valeur de
MAX_STRING_LENGTH
selon vos besoins.la source
strlen(str1) + strlen(str2)
, mais vous écrivez desstrlen(str1) + strlen(str2) + 1
caractères. Pouvez-vous vraiment écrire votre propre fonction?return buffer; free(buffer);
sizeof(char) == 1
(D'ailleurs, il y a d'autres erreurs plus subtiles ...) Pouvez-vous voir maintenant pourquoi vous n'avez pas à écrire votre propre fonction?free(buffer);
.free(buffer);
aprèsreturn buffer;
n'est jamais exécuté, voyez-le dans un débogueur;) Je vois maintenant: oui, vous devez libérer la mémoire dans lamain
fonctionEn supposant que vous ayez un char [fixed_size] plutôt qu'un char *, vous pouvez utiliser une seule macro créative pour tout faire en même temps avec un
<<cout<<like
ordre ("plutôt% s le disjoint% s \ n", "plutôt que", "printf format de style "). Si vous travaillez avec des systèmes embarqués, cette méthode vous permettra également de laisser de côté malloc et la grande*printf
famille de fonctions commesnprintf()
(cela empêche aussi dietlibc de se plaindre de * printf)la source
la source
Vous essayez de copier une chaîne dans une adresse allouée statiquement. Vous devez cat dans un tampon.
Plus précisément:
...couper...
destination
...couper...
http://www.cplusplus.com/reference/clibrary/cstring/strcat.html
Il y a aussi un exemple ici.
la source
C'était ma solution
mais vous devez spécifier le nombre de chaînes que vous allez concaténer
la source
Essayez quelque chose de similaire à ceci:
la source