2010-01-23 5 views
1

J'utilise C pour un projet de classe pour la première fois après avoir appris le C++, donc la syntaxe me tue ... Fondamentalement, je dois stocker une chaîne donnée par une fonction dans un autre variable pour une utilisation ultérieure.Pointeur, problème de chaîne en C

J'ai un tableau de caractères déclaré comme celui-ci

char foo[]; 

Une fonction que je me donne attribue un tas de personnages dans ce tableau (ou des pointeurs vers des personnages?). Je peux imprimer la chaîne réelle stockée dans foo comme celui-ci

printf("%s", foo); 

Et je peux stocker son adresse dans une autre variable comme celui-ci

char *bar; 

bar = &foo[0]; 

printf("%s", foo); 

La chaîne complète est sortie très bien dans les deux cas. Cependant, comment puis-je stocker cette chaîne dans une variable différente? Si foo change, alors la barre ne tiendra plus la chaîne dont j'ai besoin puisqu'elle pointe juste vers foo. Tout ce que j'ai pensé me donne des erreurs de compilation comme

warning: initialization makes pointer from integer without a cast 

Espérons que c'est assez d'infos. Merci pour l'aide à l'avance.

+0

Merci pour les réponses rapides, je la méthode strdup et il a très bien fonctionné. Maintenant, je peux revenir à la partie réelle de la tâche et cesser de m'inquiéter de la syntaxe. Merci encore. –

Répondre

6

Vous devez copier la chaîne.

manière la plus simple est avec des allocations de tas:

char *bar = strdup(foo); 

Ne pas oublier de libérer cette allocation lorsque vous avez terminé avec elle:

free(bar); 

Si vous ne souhaitez pas utiliser les allocations de tas , vous pouvez créer un tampon sur la pile et le copier manuellement. Vous devez faire attention à ne pas déborder le buffer (et que votre buffer est terminé à 0, strncpy ne le fera pas pour vous si votre src est plus longtemps que votre dest):

char copy[SOMESIZE]; 
strncpy(copy, foo, sizeof(copy) - 1); 
copy[sizeof(copy) - 1] = '\0';  

Si vous avez le support de tableau de longueur variable, vous pouvez l'utiliser:

char copy[strlen(foo) + 1]; 
strcpy(copy, foo); 

Comme Christoph correctement indiqué dans les commentaires, strdup ne fait pas partie de la norme C. Si vous utilisez Windows, vous devez utiliser _strdup. Si vous voulez être absolument portable, vous pouvez mettre en œuvre strdup assez facilement:

char *strdup(const char *orig) 
{ 
    char *copy = (char *)malloc(strlen(orig) + 1); 
    if (copy != NULL) 
     strcpy(copy, orig); 

    return copy; 
} 
+0

+1; Gardez à l'esprit que 'strdup()' est POSIX et ne fait pas partie de la bibliothèque standard ISO-C, donc vous devrez peut-être le ré-implémenter vous-même si vous voulez une portabilité maximale – Christoph

+0

@Christoph - merci. Posix a été ma plate-forme de développement principale pendant si longtemps que j'oublie la différence. Quoi qu'il en soit, mis à jour ma réponse pour donner plus d'informations à ce sujet. –

+1

l'implémentation de la glibc (http://cvs.savannah.gnu.org/viewvc/%2Acheckout%2A/libc/string/strdup.c?root=libc&content-type=text%2Fplain) de 'strdup()' utilise ' memcpy() 'au lieu de' strcpy() ', que je m'attendais à être légèrement plus rapide car vous deviez déjà déterminer la longueur des chaînes – Christoph

-3

utiliser la fonction strcpy pour copier la chaîne à une autre variable. Allouer de la mémoire pour myStringVar si la chaîne renvoyée est hors de portée.

EDIT:

char *myStringVar = (char *)malloc(BUFFER_SIZE); 
+0

' strcpy() 'attend un buffer de taille suffisante comme cible, pas uninitialized – sth

+0

-1: comme vous avez omis d'allouer de la mémoire, cela écrase l'emplacement aléatoire de la variable non initialisée. – Christoph

+0

Toujours si je veux utiliser strcpy uniquement pour le problème ci-dessus, quelles modifications faut-il apporter pour que strcpy fonctionne correctement? –

0

Vous devez copier la chaîne en utilisant strncpy ou dupliquer à l'aide strdup:

char foo[] = "Hello World"; 
char* bar = strdup(foo); 

foo[0] = 'B'; 
printf("%s", foo); 
printf("%s", bar); 

free(bar); // Don't forget to release the memory! 

Prints:

Bello World 
Hello World 

Ou, si vous avez déjà un chaîne dans laquelle vous voulez copier:

char foo[] = "Hello World"; 
char bar[] = "Goodbye Cruel World"; 

strncpy(bar, foo, sizeof(bar)-1); 

foo[0] = 'B'; 
printf("%s", foo); 
printf("%s", bar); 

rints également:

Bello World 
Hello World 

Le troisième argument de strncpy est le nombre maximal de caractères à copier (pour éviter le débordement) Notez qu'il est un de moins que la longueur de la mémoire tampon bar de sorte que bar peut être terminé par zéro. Notez également que sizeof ne fonctionne que parce que bar est un tableau local. Il ne fonctionne pas dans ce cas sur char*, vous devez connaître la taille de l'extérieur, par exemple .:

char foo[] = "Hello World"; 
size_t bar_len = 20; 
char* bar = (char*)malloc(bar_len); 

strncpy(bar, foo, bar_len-1); // CANNOT use sizeof(bar) here! 

foo[0] = 'B'; 
printf("%s", foo); 
printf("%s", bar); 

free(bar); // Don't forget! 
+0

strncpy n'est pas un bon moyen de le faire. strncpy * always * copie n caractères, même si la chaîne copiée est plus courte, remplissage avec 0 caractère, gaspillage de cycles. De plus, strncpy ne garantit pas que la chaîne écrite est terminée à 0, si la chaîne source est plus longue que la longueur du tampon qu'il est tronqué, sans 0. Et le -1 n'aide pas ici car malloc ne garantit pas la mémoire zéro . – wich