337 votes

Comment créer un tableau de chaînes de caractères en C ?

J'essaie de créer un tableau de chaînes de caractères en C. Si j'utilise ce code :

char (*a[2])[14];
a[0]="blah";
a[1]="hmm";

gcc me donne "warning : assignment from incompatible pointer type". Quelle est la manière correcte de procéder ?

edit : Je suis curieux de savoir pourquoi cela devrait donner un avertissement du compilateur puisque si je fais printf(a[1]) ;, cela imprime correctement "hmm".

291voto

Mikael Auno Points 2699

Si vous ne voulez pas changer les chaînes de caractères, vous pourriez simplement faire

const char *a[2];
a[0] = "blah";
a[1] = "hmm";

En procédant de cette manière, vous allouerez un tableau de deux pointeurs vers const char . Ces pointeurs seront ensuite mis à l'adresse des chaînes de caractères statiques. "blah" et "hmm" .

Si vous voulez être en mesure de changer le contenu de la chaîne de caractères, vous devez faire quelque chose comme

char a[2][14];
strcpy(a[0], "blah");
strcpy(a[1], "hmm");

Cela va allouer deux tableaux consécutifs de 14 char chacun, après quoi le contenu des chaînes statiques y sera copié.

240voto

John Bode Points 33046

Il existe plusieurs façons de créer un tableau de chaînes en C. Si toutes les chaînes doivent être de la même longueur (ou du moins avoir la même longueur maximale), il suffit de déclarer un tableau 2-d de chars et de les assigner si nécessaire :

char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1];
...
strcpy(strs[0], aString); // where aString is either an array or pointer to char
strcpy(strs[1], "foo");

Vous pouvez également ajouter une liste d'initialisateurs :

char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1] = {"foo", "bar", "bletch", ...};

Cela suppose que la taille et le nombre de chaînes de l'initialisateur correspondent aux dimensions de votre tableau. Dans ce cas, le contenu de chaque chaîne littérale (qui est elle-même un tableau de caractères à terminaison zéro) est copié dans la mémoire allouée à strs. Le problème avec cette approche est la possibilité de fragmentation interne ; si vous avez 99 chaînes de 5 caractères ou moins, mais 1 chaîne de 20 caractères, 99 chaînes auront au moins 15 caractères inutilisés ; c'est un gaspillage d'espace.

Au lieu d'utiliser un tableau à 2 dimensions de chars, vous pouvez stocker un tableau à 1 dimension de pointeurs vers chars :

char *strs[NUMBER_OF_STRINGS];

Notez que dans ce cas, vous n'avez alloué de la mémoire que pour contenir les pointeurs vers les chaînes de caractères ; la mémoire pour les chaînes de caractères elles-mêmes doit être allouée ailleurs (soit sous forme de tableaux statiques, soit en utilisant malloc() ou calloc()). Vous pouvez utiliser la liste d'initialisation comme dans l'exemple précédent :

char *strs[NUMBER_OF_STRINGS] = {"foo", "bar", "bletch", ...};

Au lieu de copier le contenu des constantes de chaîne, vous stockez simplement les pointeurs vers celles-ci. Notez que les constantes de chaîne peuvent ne pas être accessibles en écriture ; vous pouvez réaffecter le pointeur, comme suit :

strs[i] = "bar";
strs[i] = "foo"; 

Mais il se peut que vous ne puissiez pas modifier le contenu de la chaîne de caractères, par exemple,

strs[i] = "bar";
strcpy(strs[i], "foo");

peut ne pas être autorisé.

Vous pouvez utiliser malloc() pour allouer dynamiquement le tampon pour chaque chaîne et copier dans ce tampon :

strs[i] = malloc(strlen("foo") + 1);
strcpy(strs[i], "foo");

BTW,

char (*a[2])[14];

Déclare que a est un tableau à 2 éléments de pointeurs vers des tableaux de chars à 14 éléments.

120voto

Mark Points 49079

Ack ! Cordes constantes :

const char *strings[] = {"one","two","three"};

Si je me souviens bien.

Oh, et vous voulez utiliser strcpy pour l'affectation, et non l'opérateur =. strcpy_s est plus sûr, mais il n'est ni dans la norme C89 ni dans la norme C99.

char arr[MAX_NUMBER_STRINGS][MAX_STRING_SIZE]; 
strcpy(arr[0], "blah");

20voto

Faisal Vali Points 10048

Voici quelques-unes de vos options :

char a1[][14] = { "blah", "hmm" };
char* a2[] = { "blah", "hmm" };
char (*a3[])[] = { &"blah", &"hmm" };  // only since you brought up the syntax -

printf(a1[0]); // prints blah
printf(a2[0]); // prints blah
printf(*a3[0]); // prints blah

L'avantage de a2 est que vous pouvez alors faire ce qui suit avec les chaînes de caractères littéraux

a2[0] = "hmm";
a2[1] = "blah";

Et pour a3, vous pouvez faire ce qui suit :

a3[0] = &"hmm";
a3[1] = &"blah";

Pour a1, vous devrez utiliser strcpy même si vous assignez des chaînes de caractères. La raison en est que a2 et a3 sont des tableaux de pointeurs et que vous pouvez faire en sorte que leurs éléments (c'est-à-dire les pointeurs) pointent vers n'importe quel stockage, alors que a1 est un tableau de "tableaux de caractères" et donc chaque élément est un tableau qui "possède" son propre stockage (ce qui signifie qu'il est détruit lorsqu'il sort de sa portée) - vous pouvez seulement copier des choses dans son stockage.

Cela nous amène également à l'inconvénient d'utiliser a2 et a3 - puisqu'ils pointent vers un stockage statique (où sont stockés les littéraux de chaînes de caractères) dont le contenu ne peut pas être modifié de manière fiable (c'est-à-dire un comportement indéfini), si vous voulez assigner des littéraux autres que des chaînes de caractères aux éléments de a2 ou a3 - vous devrez d'abord allouer dynamiquement suffisamment de mémoire et faire en sorte que leurs éléments pointent vers cette mémoire, puis copier les caractères dans celle-ci - et vous devrez ensuite vous assurer de désallouer la mémoire lorsque vous aurez terminé.

Bah - le C++ me manque déjà ;)

p.s. Faites-moi savoir si vous avez besoin d'exemples.

14voto

FutureSci Points 74

Ou vous pouvez déclarer un type struct, qui contient un caractère arry(1 string), ils créent un tableau des structs et donc un tableau de milti éléments

typedef struct name
{
   char name[100]; // 100 character array
}name;

main()
{
   name yourString[10]; // 10 strings
   printf("Enter something\n:);
   scanf("%s",yourString[0].name);
   scanf("%s",yourString[1].name);
   // maybe put a for loop and a few print ststements to simplify code
   // this is just for example 
 }

L'un des avantages de cette méthode par rapport à toute autre est qu'elle vous permet d'analyser directement la chaîne de caractères sans devoir utiliser la fonction strcpy ;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X