Je suis nouveau en C et les choses sont différentes en C que dans toute autre langue que j'ai apprise. Dans mes devoirs, je veux créer un tableau de caractères qui pointe vers un tableau de caractères, mais plutôt que de créer un tableau de caractères multidimensionnel, je suppose que j’aurais plus de contrôle, je créerais des tableaux de caractères et placerais chacun d’eux dans les index du tableau de caractères d'origine:
char keywords[10];
keywords[0] = "float";
L'exemple ci-dessus est de clarifier et un cas simple. Mais ma question est due aux recherches que je fais, et je suis confus à propos de quelque chose. Normalement, cela fonctionnerait dans d'autres langues, mais en C, ce serait:
char *keyword[10];
keywords[0] = "float";
Mais quand je veux l'envoyer à travers une fonction, pourquoi est-ce nécessaire:
void function(char **keyword); //function prototype
Ne serait-il pas suffisant de passer le pointeur du tableau?
On dirait que vous êtes confus par les étoiles doubles de
void function(char ** keyword);
Les étoiles doubles signifie simplement que cette fonction s'attend à ce que vous passiez un pointeur à un pointeur à un caractère . Cette syntaxe n'inclut aucune information sur le fait que vous utilisez un tableau ou que le caractère est en fait le premier caractère d'un grand nombre dans une chaîne. En tant que programmeur, il vous appartient de savoir à quel type de structure de données correspond ce char **
.
Par exemple, supposons que le début de votre tableau soit stocké à l'adresse 0x1000. L'argument keyword
de la fonction doit avoir la valeur 0x1000. Si vous déréférenciez keyword
, vous obtenez la première entrée du tableau, qui est un char *
qui pointe vers le premier caractère de la chaîne "float". Si vous déréférenciez le char *
, vous obtenez le caractère "f".
Le code (artificiel) pour cela ressemblerait à ceci:
void function(char **keyword)
{
char * first_string = *keyword; // *keyword is equivalent to keyword[0]
char first_char = *first_string; // *first_string is equivalent to first_string[0]
}
Il y avait deux pointeurs dans l'exemple ci-dessus. En ajoutant un décalage au premier pointeur avant de le déréférencer, vous pouvez accéder à différentes chaînes du tableau. En ajoutant un décalage au second pointeur avant de le déréférencer, vous pouvez accéder à différents caractères dans la chaîne.
char *keyword[10];
keyword
est un tableau 10 de char *
. Dans un contexte de valeur, il est converti en un pointeur en char *
.
Cette conversion fait partie de ce que Chris Torek appelle "The Rule" :
"Comme noté ailleurs, C a une règle très importante sur les tableaux et les pointeurs. Cette règle - La règle - dit que, dans un contexte de valeur, un objet de type 'tableau de T' devient une valeur de type 'pointeur sur T ', pointant sur le premier élément de ce tableau "
Voir ici pour plus d'informations: http://web.torek.net/torek/c/pa.html
La C-FAQ a également une entrée sur ce tableau pour la conversion de pointeur:
Question 6.3: Qu'entend-on par "équivalence de pointeurs et de tableaux" en C?
Voici la réponse.
#include<stdio.h>
int main(void)
{
char *CharPtr[3];
char a[4]="abc";
char b[4]="def";
char c[4]="ghi";
CharPtr[0]=a;
CharPtr[1]=b;
CharPtr[2]=c;
printf("\n content of CharPtr[0] =%s",CharPtr[0]);
printf("\n content of CharPtr[1] =%s",CharPtr[1]);
printf("\n content of CharPtr[2] =%s\n",CharPtr[2]);
printf(" \n content of char a[4]=%s",a);
printf(" \n content of char b[4]=%s",b);
printf(" \n content of char c[4]=%s\n",c);
}
Si tu veux
void function(char **keyword);
Andy, pensez qu'un tableau est juste un pointeur (au début du tableau), c'est pourquoi vous écrivez:
void function(char **keyword);
Parce que vous avez créé un tableau pour les pointeurs de caractères.
Si c'est plus facile à comprendre, essayez:
void function(char *keyword[]);
Mais utiliser le premier est plus standard que C, mais si vous utilisez un compilateur C++, cela n’a aucune importance.
Je suppose que vous assignez votre première chaîne:
"float"
à la première position d'index du mot clé [0]
char keyword[0] = "float";
qui est la première position d'index du tableau:
char keyword[10];
Si le précédent est le cas, dans un sens, vous créez essentiellement une structure de données contenant une structure de données. Le tableau de n'importe quel type est la plus petite structure de données de ce type en C. Considérant que dans votre exemple, vous créez un tableau de caractères, vous utilisez en fait le plus petit type de données (char = 1bit) à chaque position d'index du la plus petite structure de données intégrée (le tableau).
Cela dit, si dans votre exemple, vous essayez de créer un tableau de tableaux; votre tableau de caractères
/* Hold ten characters total */
char keyword[10];
a été conçu pour contenir 10 caractères. Un à chaque position d'index (que vous connaissez probablement déjà). Ainsi, après avoir déclaré le tableau intitulé mot-clé, vous essayez ensuite d'initialiser la première position d'index du tableau avec un autre (le deuxième) tableau de caractères:
/* I believe this is what you had stated */
char keywords[0] = "float";
Avec le second tableau de caractères ayant un index de 5 positions en taille.
Pour atteindre votre objectif souhaité, vous créez essentiellement un tableau qui émule essentiellement l’effet d’une structure de données qui «contient» d’autres structures de données.
REMARQUE: Si vous aviez/envisagez de créer une structure de données contenant une structure de données contenant une structure de données. ALIAS. une structure de données triple imbriquée et dans ce cas, je pense que ce serait une matrice, ce que je ne recommanderais pas!
Néanmoins, la structure de la matrice serait sous la forme de la première position d'index du mot-clé, étant assigné à l'ensemble du tableau de mots-clés, ce qui inclurait toutes les données stockées dans chaque position d'index du tableau de mots-clés. Ensuite, il y aurait probablement quelque chose comme: keywords1, keywords2, ... keywords9,
qui imiterait essentiellement la forme de:
char *keyword[10] = {
char *keywords0[10] = {"float", etc, etc, etc.};
char *keywords1[10] = {"keyword1", "secondIndexOfThisArray", etc, etc, etc.};
and so
};
Donc, fondamentalement, de droite à gauche, le tableau de mots-clés est un tableau de pointeurs qui pointe vers un tableau de pointeurs qui pointe vers des tableaux de caractères.
Si c'est ce que vous représentez, il serait préférable de définir un type de données personnalisé struct/record. Dans cette structure personnalisée, vous souhaitez définir un niveau subordonné ou un niveau enfant de structures. Vous pouvez également les pré-déclarer puis les initialiser.
par exemple.
typedef *nestedDataStructures {
struct keyWords[];
struct keyWords1[];
struct keyWords2[];
... and so on.
}; nestedDataStructures
Au lieu d'ajouter dix structures à une structure personnalisée, je me divisais en 3 ou 4 (quel que soit le nombre de structures et d'utilisation) et créais un module afin de générer des couches d'abstraction symétriques lorsque vous manipulez votre ensemble de données.
Néanmoins, vous ne pouvez pas créer le tableau de caractères et potentiellement affecter le tableau de caractères de la même manière que vous avez fait (ou qui sait peut-être que vous le pouvez), mais la façon dont vous souhaitez émuler le tableau qui contient des tableaux consiste à créer un tableau de pointeurs de caractères à l’avant, de positions d’index de nombre X, puis initialiser, puis utiliser les tableaux de caractères sous la forme de chaînes déclarées avec lors de l’initialisation de la déclaration originale.
Donc, en gros, vous pouvez déclarer tout votre tableau à l’avance, puis dans votre conception de programme, déréférencer chaque position d’index, utiliser une affectation ou imprimer/écrire la position d’index.
Comme par exemple, vous pouvez toujours faire quelque chose comme ceci:
/* Example of the program and declaration with out a function */
#include <stdio.h>
int main(){
/*
* A character pointer array that contains multiple
* character arrays.
*/
char *grewMe[2] = {"I want to ", "grow to be bigger"};
int w = 0;
for(; w < 2;) {
printf("%s", grewMe[w]);
++w;
}
printf(" :-)\n");
w = 0;
return 0;
}
// Output:
// I want to grow to be bigger :-)
Ou quelque chose comme ça:
/* Example of program: function passed arguments
* of a pointer to the array of pointers
*/
#include <stdio.h>
void mygrowth(char *growMe[]);
int main(){
char *growMe[2] = {"I want to ", "grow to be bigger"};
mygrowth(growMe);
printf(" :-)\n");
return 0;
}
void mygrowth(char *growMe[])
{
int w = 0;
for (; w < 2;) {
printf("%s", growMe[w]);
++w;
}
}
L'affectation de chaque position d'index telle qu'elle est passée en argument:
/*
* This program compiles, runs and outputs properly
* Example of a program with a function of
* arguments pnt2pnter
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
thoughtAsAFunction(iThink);
printf(":-)\n");
return 0;
}
void thoughtAsAFunction(char **iThink) {
int andy = 0;
for (; andy < 10;) {
char * pntThroughPnt = iThink[andy];
printf("%s", pntThroughPnt);
++andy;
}
andy = 0;
}
Ou passez par référence, avec un incrément de la variable de nombre de boucles:
/*
* This program compiles, runs, and outputs all of the character
* arrays.
*
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine, then I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
int andy = 0;
for (; andy < 10;) {
// pass by reference and increment.
thoughtAsAFunction(&iThink[andy]);
++andy;
}
printf(":-)\n");
andy = 0;
return 0;
}
void thoughtAsAFunction(char **iThink) {
char * pntThroughPnt = *iThink;
printf("%s", pntThroughPnt);
}
N'oubliez pas que c'est le cas si vous déclarez le tableau de pointeurs (char * array [10];) et que chaque pointeur pointe vers un tableau de caractères.
char *keywords[10]
est un tableau de pointeurs de caractères. Donc, keywords[0]
, keywords[1]
.. et ainsi de suite auront les adresses de tableaux de caractères différents.
Dans printf
, vous pouvez utiliser %s
et keywords[0]
pour imprimer le tableau de caractères entier dont l'adresse (c'est-à-dire l'adresse du premier octet du tableau) est stockée à keywords[0]
.
En passant à une fonction, si vous donnez *keywords
, vous vous référez à la valeur de (adresse stockée à keywords[0]
) qui est encore une adresse. Donc, pour obtenir la valeur au lieu de l'adresse, vous pouvez ajouter un autre *
... J'espère que cela clarifie un peu ..
En C, vous ne pouvez pas vraiment passer tableau à une fonction. Au lieu de cela, vous passez un pointeur au début du tableau. Puisque vous avez un tableau de char*
, la fonction obtiendra un pointeur sur char*
, qui est char**
.
Si vous le souhaitez, vous pouvez écrire (dans le prototype) char *keyword[]
au lieu de char **keyword
. Le compilateur le convertira automatiquement.
De plus, en C, vous pouvez déréférencer les pointeurs comme des tableaux, vous ne perdez donc presque rien avec cette "conversion en pointeur".