Tableaux, pointeurs en C
Forum Programmation : Tableaux, pointeurs en C
Salut,
Voici un code simple provenant du site du zéro :
| Citation : // Prototype de la fonction d'affichage
|
Je me pose quelques questions qui provoquent la confusion dans mon esprit.
J'ai assez bien compris le système des pointeurs je pense.
Ici, avec le pointeur *tableau on récupère l'adresse de la variable (pointeur) tableau qui est donc tableau.
1. Je ne vois pas l'intérêt de mettre le pointeur *tableau ici.
2. On dit que la variable tableau eset aussi un pointeur, donc pourquoi ne pas mettre long **tableau ?
3. Si j'ai bien compris, avec la boucle for, on va parcourir toutes les adresses du tableau et en retirer les valeurs grâce aux nombre dans les crochets qui augmentent avec la boucle ?
Je ne vois toujours pas l'utilité du pointeur, vu que tableau lui même est un pointeur et tableau = une adresse.
Non ?
On aurait pas pu mettre juste
void affiche(long tableau, long tailleTableau)
Ou alors le * est indispensable pour dire qu'on reçoit un pointeur ..? ça commence à confuser
Merci pour les futures réponses !
+++++++++
Sinon j'ai un deuxième petit problème, donc autant le poser en même temps :
J'ai fait un petit truc tout court :
| Citation : #include <stdio.h>
|
Le programme marche bien sauf pour une chose.
Le programme tourne en boucle, pourtant j'ai bien spécifié ça à la fin :
}while ( nombre != 1 || nombre!=2 || nombre!=3 || nombre!=4)
Ai-je fait une erreur ?
Sinon pour faire moins moche
Si je voulais retourner au début pour ne pas répéter le menu à chaque fois qu'on tape quelque chose de faux,
un goto conviendrait comme en batch ?
Thks
On veut passer un tableau d'entiers (long) à la fonction affiche : le type est donc long *. En C un tableau est un pointeur = l'adresse du premier élément = l'adresse de l'élément d'indice 0.
On accède au ième élément du tableau par cette syntaxe tableau[i]. C'est équivalent à *(tableau + i).
Si le type était long** alors cela représenterait un tableau de pointeurs sur des entiers et non pas un tableau d'entiers.
En ce qui concerne la condition :
nombre != 1 || nombre!=2 || nombre!=3 || nombre!=4
je te laisse réfléchir et te rendre compte qu'elle sera toujours vraie...
Ce code n'est pas terrible, car 2 variables avec le même nom existe (tableau dans le main, et tableau dans affiche).
| Citation : 1. Je ne vois pas l'intérêt de mettre le pointeur *tableau ici. |
le passage par paramètre doit se faire avec un pointeur que ce soit de type long* ou long[], c'est la même chose, puisque un tableau c'est une adresse mémoire comme un pointeur.
| Citation : 2. On dit que la variable tableau eset aussi un pointeur, donc pourquoi ne pas mettre long **tableau ? |
ça ferait un pointeur qui pointe sur un pointeur, ou un pointeur qui pointe sur un tableau, ou encore un tableau de pointeurs.
| Citation : 3. Si j'ai bien compris, avec la boucle for, on va parcourir toutes les adresses du tableau et en retirer les valeurs grâce aux nombre dans les crochets qui augmentent avec la boucle ? |
En mémoire un tableau c'est un pointeur sur le premier élément. Les éléments suivant se suivent toujours en mémoire, donc les adresses sont toujours l'adresse du premier + 1, puis +2 etc.
| Citation : Je ne vois toujours pas l'utilité du pointeur, vu que tableau lui même est un pointeur et tableau = une adresse.
|
ça fonctionne aussi avec ça:
void affiche(long tableau[], long tailleTableau)
mais c'est la même chose. Dans les 2 cas on fait passer l'adresse mémoire du premier élément du tableau.
| Citation : Le programme tourne en boucle, pourtant j'ai bien spécifié ça à la fin :
|
Oui,
c'est équivalent à ça boucle tant que nombre != 1 ou nombre !=2 ou...
Comme ce sont des OU, il suffit qu'une des conditions soit vérifiée pour que la boucle continue.
J'imagine que tu veux continuer à boucler lorsque nombre est différent de tous les chiffres, donc différent de 1, différent de 2, différent de 3 ET différent de 4.
Sinon on peut voir la logique inverse. Tu veux que la boucle s'arrête lorsque nombre == 1 OU nombre == 2 OU nombre ==3 OU nombre == 4. Comme on veux prendre l'opposé, les == deviennent != (et inversement), et les || deviennent && (et inversement).
| Citation : Sinon pour faire moins moche |
Non le goto toto; est à bannir !
parce que si tu en fais plusieurs, un lecteur ne comprendrait plus grand chose, au pire on peut faire un break;, mais à éviter si on peut simplement faire un while comme ici.
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky
Re,
Merci à vous deux pour vos réponses claires.
Je crois avoir compris
(Erreur en effet très bête de ma part pour les conditions que j'avais mise
)
Juste une dernière question ;
Je ne vois pas l'utilité de le pratique rmais bon.
Si je voulais savoir l'adresse par exemple de tableau[3]
Un &tableau[3] marcherait ? Ou il faut procéder autrement pour les tableaux qui est un cas plus particulier de pointeurs.?
Répondre à XmichouX
C'est vrai que les pointeurs c'est pas faciles, mais obligatoire si tu veux programmer.
Message édité par yoda2a le 20-01-2008 à 16:19:04
Répondre à yoda2a
| Citation : Je ne vois pas l'utilité de le pratique rmais bon. |
C'est surtout utilise pour tout ce qui est dynamique. Dans ton cas, le tableau a une taille fixe, mais si tu veux faire un tableau à taille variable selon certains cas, les pointeurs sont très utiles
| Citation : Si je voulais savoir l'adresse par exemple de tableau[3]
|
oui ça marche, et c'est exactement la même chose que (tableau + 3).
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky
Tiens ouais j'y avais même pas pensé.
Pour l'utilité de la pratique, je parlais de ma question sur l'adresse du tableau[3]
A peine ai-je voulu commencer un exo là dessus que ça veut pas compiler
Consigne : créer une fonction sommeTableau qui renvoie la somme des valeurs contenues dans le tableau (utilisez un return pour renvoyer la valeur).
Pour vous aider, voici le prototype de la fonction à créer :
long sommeTableau(long tableau[], long tailleTableau)
Peut-on m'aiguiller sans donner la réponse ?
D'ailleurs j'ai fait ça qui est nul évidemment mais bon :
| Citation : #include <stdio.h>
|
Et ya un message d'erreur :
1>Édition des liens en cours...
1>tableau.obj : error LNK2005: _main déjà défini(e) dans main.obj
1>C:\Users\Antoine\Documents\Visual Studio 2005\Projects\Test\Debug\Test.exe : fatal error LNK1169: un ou plusieurs symboles définis à différentes reprises ont été rencontrés.
C'est pas une faute dans le script apparemment et j'utilise visual c++
Répondre à XmichouX
A oui cet exercice, je l'ai déjà fait aussi.
dans ta fonction main, tu fait appel 2 fois à la fonction sommeTableau.
Ensuite l'exercice dit qu'il faut que la fonction sommeTableau retourne la somme des valeurs du tableau et je vois aucune addition dans ta seconde fonction ?
Pour t'aider sur cet exercice voici à quoi doit ressembler ta fonction main :
Code :
|
Ensuite faut que ta seconde fonction fasse la somme des valeurs du tableau et renvoie cette somme.
Message édité par yoda2a le 20-01-2008 à 17:49:07
Répondre à yoda2a
Oui, en effet, je n'ai pas trouvé comment faire, là je l'ai exposé surtout pour montrer le message d'erreur qui m'étonne .. d'habitude, c'est des erreurs de script mais là non apparemment.
En fait je vois comment obtenir les valeurs du tableau, mais après les aditionner, je vois pas comment faire ça dans une boucle en tout cas.
Et je ne vois pas non plus comment récupérer chaque valeur du tableau individuellement ou séparément. Car là, la fonction me mettrait toutes les valeurs à la suite.
Répondre à XmichouX
Oui il faut utiliser une boucle, et voici la formulle utiliser dans la boucle :
somme=somme+tableau[i];
Message édité par yoda2a le 20-01-2008 à 17:54:06
Répondre à yoda2a
Je vais passer vraiment pour un idiot mais je ne vois toujours pas
en fait je ne vois pas par quoi remplacer le deuxième somme ici.
Si je pouvais récupérer chaque valeur séparément, je pourrais les aditionner et retourner la valeur au final, mais là ..
Répondre à XmichouX
JE vais te donner le programme :
Code :
|
regarde bien la fonction sommeTableau.
Cette formule, ce répète tant que i<taille du tableau :
somme=somme+tableau[i];
Donc ça fait :
0=0+5; i=0
5=5+6; i=1
11=11+9; i=2
20=20+4; i=3
24=24+5; i=4
29=29+3; i=5 la fonction s'arrète ici car i>tailleTableau
Donc la somme (32) est renvoyer dans la fonction main. Je sais pas si c'était bien expliquer. ^^
Message édité par yoda2a le 20-01-2008 à 19:00:07
Répondre à yoda2a
| Citation : Pour l'utilité de la pratique, je parlais de ma question sur l'adresse du tableau[3] |
Regarde ta fonction somme tableau.
Si tu ne veux l'appliquer qu'à partir du 3ème avec les 5 suivants, tu fais croire que ton tableau commence à partir du 3ème:
sommeTableau(tableau + 3, 5);
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky
Merci, c'est très bien expliqué, je ne l'aurais en effet pas trouvé.
Si maintenant javais voulu multiplié toutes les valeurs entre elles, j'aurais juste eu à remplacer le + par * ?
++++++
Si j'avais voulu faire une moyenne de toutes les valeurs aditionnées (exercice 2).
ça aurait été bon ça ? :
return somme/(i + 1)
Et en mettant des doubles à la place des longs dans les variable et déclaration de fonction.
++++++++++++
| Citation : sommeTableau(tableau + 3, 5); |
ça aurait commencé à l'adresse [3] du tableau? en ayant dit que le tableau faisait 5 cases ?
++++++
J'ai essayé pour la moyenne ça marche pas ![]()
| Citation : #include <stdio.h> } |
Message édité par XmichouX le 20-01-2008 à 20:01:37
Répondre à XmichouX
Heu tu sais comment on calcule une moyenne ? ^^
Tu doit diviser la somme par la taille du tableau. Et ton calcule de moyenne n'a rien à faire dans la boucle, justement elle doit être après la boucle.
et ici :
printf ("La moyenne des valeurs du tableau est egale a %ld\n", somme);
C'est la moyenne que tu veut afficher et pas la somme.
PS : Une moyenne est un double et pas long.
Message édité par yoda2a le 20-01-2008 à 20:00:05
Répondre à yoda2a
Ben c'est bien ce que j'ai fait non ?
J'ai divisé la somme par i+1 <- la longueur du tableau non ?
Par contre oui en effet je me suis trompé pour la boucle
J'ai oublié d'éditer pour le somme désolé
Répondre à XmichouX
| XmichouX a écrit : Ben c'est bien ce que j'ai fait non ?
|
mais ta formule va faire 32/7; et ton programme te diras :
La moyenne des valeurs du tableau est egale a 4.
C'est bien ça ? Alors que c'est faux.
Au lieu de ça :
moyenne= somme/(i+1);
Remplace^par :
moyenne=somme/tailleTableau;
C'est plus compréhensible et au moin c'est juste.
PS : N'oublie pas qu'une moyenne est un nombre décimale en règle générale.
Message édité par yoda2a le 20-01-2008 à 20:15:47
Répondre à yoda2a
Re,
Oui en effet, c'est exactement ça qu'il m'affichait, mais je ne comprends pas le I après la boucle ne fait pas 5 ?
Ce qui aurait fait i+1 = 6 , ou alors il fait 6 .. la boucle est réexécutée mais cette fois, rien n'es fait c'est ça? en voyant que la condition n'est plus remplie?
DOnc ce que tu m'as dit est tout à fait correct mais je pourrais aussi mettre i tout court ?
et oui je vais mettre des double ![]()
Je vous mets mon script final :
| Citation : #include <stdio.h> double sommeTableau(doubletableau[], double tailleTableau); int main (int argc, char *argv[]) return 0; |
Est-ce que ce code peut marcher ou je dois mettre .0 après chaque nombre ?
Message édité par XmichouX le 20-01-2008 à 20:25:18
Répondre à XmichouX
Je corrige :
" 0=0+5; i=0
5=5+6; i=1
11=11+9; i=2
20=20+4; i=3
24=24+5; i=4
29=29+3; la fonction s'arrète ici sinon i>tailleTableau "
Ca c'était pour le premier dans le cas ou la taille du tableau = 4 donc i=4, mais la tout change car la taille de ton tableau=6 donc a la fin de la boucle i=6.
Donc oui tu peut mettre moyenne= somme/i ; ou bien
moyenne= somme/tailleTableau; c'est la même chose, mais je te conseille la seconde formulle (Plus claire).
Sinon pour ton programme ta 2 problèmes, i n'est pas un double mais bien un long. Et ici regarde bien :
printf ("La moyenne des valeurs du tableau est egale a %ld\n", moyenne);
Ton programme risque de t'afficher n'importenawak, je te laisse deviner pourquoi.
Sinon le .0 tu peut le mettre mais c'est inutile vue que c'est déjà un double.
Message édité par yoda2a le 20-01-2008 à 20:52:25
Répondre à yoda2a
Re)
j'ai corrigé mais ça me met toujours 4
![]()
| Citation : #include <stdio.h> int main (int argc, char *argv[]) return 0; |
Message édité par XmichouX le 20-01-2008 à 21:24:07
Répondre à XmichouX
Voila j'ai tout corrigé, à toi de voir ou tu à fait faux.
Code :
|
Message édité par yoda2a le 20-01-2008 à 21:56:39
Répondre à yoda2a
Je vois pas mon erreur ..
Je suis pas obligé d'appeler la variable tableau non ? ou si ?
Parce que si j'en fais plusieurs ...
Merci pour le corrigé en tout cas
Répondre à XmichouX
Code :
|
Voila, la correction est en verre, maintenant modifie tes printf car c'est pas correct, et change aussi le nom de ta fonction.
Message édité par yoda2a le 21-01-2008 à 00:01:09
Répondre à yoda2a
Merci pour la correction, j'avais modifié après
Une fois rentré chez moi, je verrai les erreurs que j'ai faite.
Répondre à XmichouX
ça marche bien, merrci beaucoup.
JUste un dernier truc qui m'étonne, je croyais avoir lu sur le site du zéro
que le type de la fonction devait être le même que ceux des variables se trouvant à l'intérieur, or ce n'est pas le cas, en tout cas, ça marche
Je vais tenter les autres exercices
Répondre à XmichouX
| XmichouX a écrit :
|
on pourrait pas faire grand chose dans ce cas
Penser à voir les tutos, ca peut aider!
Répondre à coca25
Tant mieux alors ![]()
Je voulais être sûr. merci !
+++++++
J'ai essayé l'autre exercice : créer une fonction maximumTableau qui aura pour rôle de remettre à 0 toutes les cases du tableau ayant une valeur supérieure à un maximum. Cette fonction prendra en paramètre le tableau ainsi que le nombre maximum autorisé (valeurMax). Toutes les cases qui contiennent un nombre supérieur à valeurMax doivent être mises à 0.
Mais rien ne s'affiche pour le printf qui concerne justement cette nouvelle fonction:
| Citation : #include <stdio.h> int main (int argc, char *argv[]) long youpi[5] = {4, 19, 26, 3, 5}; maximumTableau (youpi, 5, 6); return 0; void maximumTableau(long tableau[], long tailleTableau, long valeurMax) |
Message édité par XmichouX le 22-01-2008 à 13:22:34
Répondre à XmichouX
peut etre parce que le code vient après le pause!
Penser à voir les tutos, ca peut aider!
Répondre à coca25
Oui je l'ai mis avant pour que ça fasse une pause avant de continuer.
Et normalement Visual C++ (que j'utilise) fait une pause automatiquement avant le return 0;
Je viens d'essayer en décalant le pause après, ça met toujours rien entre les deux pauses (celui mis par le code et celui mis automatiquement par visual)
Répondre à XmichouX
ajoute un printf ("\n" ); avant le return 0, ca doit etre le cache.
Penser à voir les tutos, ca peut aider!
Répondre à coca25
ça ne change rien.
J'ai sûrement du faire un erreur.
Voici les erreurs données :
1>c:\users\antoine\documents\visual studio 2005\projects\tableau\tableau\dfdf.c(17) : error C2143: erreur de syntaxe : absence de ';' avant 'type'
1>c:\users\antoine\documents\visual studio 2005\projects\tableau\tableau\dfdf.c(19) : error C2065: 'youpi' : identificateur non déclaré
1>c:\users\antoine\documents\visual studio 2005\projects\tableau\tableau\dfdf.c(19) : warning C4047: 'fonction' : 'long *' diffère de 'int' dans les niveaux d'indirection
1>c:\users\antoine\documents\visual studio 2005\projects\tableau\tableau\dfdf.c(19) : warning C4024: 'maximumTableau' : types différents pour le paramètre formel et réel 1
1>c:\users\antoine\documents\visual studio 2005\projects\tableau\tableau\dfdf.c(20) : error C2143: erreur de syntaxe : absence de ';' avant 'type'
1>c:\users\antoine\documents\visual studio 2005\projects\tableau\tableau\dfdf.c(21) : error C2065: 'i' : identificateur non déclaré
1>c:\users\antoine\documents\visual studio 2005\projects\tableau\tableau\dfdf.c(23) : error C2109: un indice requiert un type tableau ou pointeur
Répondre à XmichouX
ces erreurs ne proviennent pas du code que tu as posté, ce dernier est bon.
Penser à voir les tutos, ca peut aider!
Répondre à coca25
Comprends pas alors ![]()
J'avais déjà eu pareil précédemment enfin .. ^^
Sinon en même temps, je viens de voir les char, les chaînes de caractère.
(siteduzero). Il répète que les chaînes de caractères sont des tableaux de char , pourtant la va "variable" stockée dans un scan f et dans un print f sont les mêmes.
Pour moi c'est comme si on disait adresse = valeur,
puisqu'on peut faire :
scanf ("%s", prenom);
et printf ("%s", prenom);
Le %s fait-il donc une sorte d'adaptation au scanf et printf ?
Je ne comprends pas pourquoi ce n'est pas plutôt:
printf ("%s, *prenom).
Pour les tableaux par exemple, on bien on faisait :
- &tableau[3]
- (tableau +3)
pour les adresse
et
- tableau[3]
- *(tableau + 3)
Or ici, c'est le nom du tableau tout seul qui donne toutes les valeurs de la variable. Si ça avait été un tableau tout court, ça aurait affiché l'adresse de la case "0", non ?
Message édité par XmichouX le 22-01-2008 à 15:12:10
Répondre à XmichouX
prenons une chaine:
Code :
|
c'est un table de char, si on y met une chaine "toto":
Code :
|
tu auras en fait:
Code :
|
le '\0' sert à marquer la fin d'une chaine de caractère.
str représente un pointeur, donc:
Code :
|
est juste, et vu qu'on a passé un "%s" comme format, scanf s'attend à une chaine, qu'il va stocker dans str, str+1, str+2, etc...
pour le printf, c'est pareil, le "%s" lui indique qu'il faut attendre un tableau de char, et un tableau est par définition (en C) un pointeur.
Penser à voir les tutos, ca peut aider!
Répondre à coca25
Ouais ok
Donc tout se joue sur le %s en fait.
Pas besoin de se prendre sur la tête sur ça alors pour les chaînes de caractère lorsqu'on utilise %s.
Merci
Répondre à XmichouX
Re,
Désolé d'encore vous ennuyer mais encore un problème avec visual ou c'est moi qui suis vraiment nul ? ..
J'ai fait quelque chose de tout simple juste pour tester des nouvelles choses apprises et à mon grand étonnement ça ne marche pas; pas pratique pour s'exercer ![]()
Voilà le c :
| Citation : #include <stdio.h> int main ( int argc, char*argv[]) { printf ("Salut Joueur1, quel est ton prenom ?" ); |
Voilà le h :
| Citation : typedef struct personne personne; |
Alors ça ne lance pas mon fichier (met encore plein d'erreurs) et ce qui est énervant c'est que ça lance un fichier que j'avais mis avant mais que j'ai supprimé puisque je l'ai remplacé par ce script là ^^
Message édité par XmichouX le 24-01-2008 à 14:02:53
Répondre à XmichouX
c'est bien de vouloir apprendre, mais vouloir du pré maché, ca n'aide pas à apprendre.
si tu ne sais pas lire l'anglais, il suffit de copier coller l'erreur pour la comprendre.
tu utilises print au lieu de printf, struc au lieu de struct, tu oublies un ; etc...
Penser à voir les tutos, ca peut aider!
Répondre à coca25
Re,
En effet, j'ai édité mon script et cette fois, ça marche.
Merci ![]()
Au fait, a-t-on le droit comme on crée une variable de créer un tableau ou une chaine de caractères comme ça ?
char chaine[];
long tab[];
Message édité par XmichouX le 24-01-2008 à 14:07:46
Répondre à XmichouX
Oui, mais tu dois l'initialiser à la création car le compilateur ne peut pas deviner la taille si tu ne donnes rien. Bref, ça sert à faire des chaines constantes.
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky
Ok
Je viens de remarquant en faisant des tests, que si je tapais des espaces dans la console (dans le programme que j'ai posté juste là),
par exemple, quel est votre prénom ?
Je m'appelle Thierry
Il va prendre je pour le prénom puis m'appelle pour le nom et ainsi de suite.
S'pas cool ça
Répondre à XmichouX
extrait du manuel de scanf correspondant au convertisseur %s:
| Citation : séquence de caractères différents d'un caractère d'espacement.
|
Penser à voir les tutos, ca peut aider!
Répondre à coca25
Ouais ok
Donc c'est tout simplement pas possible alors.
Répondre à XmichouX
Faut le faire soi même avec par exemple un getchar() et une boucle while: tant que le caractère lu et retourné par getchar(); n'est pas '\n' (saut de ligne), on continue de lire.
Connais pas encore getchar()
Merci pour l'info
Je regarderai.
Répondre à XmichouX
Re
Désolé de vous embêter encore mais bon ^^
J'ai commencé un autre chapitre en C assez important, l'ouverture fermeture de fichier..
Hepdéjà un petit problème au début ..
J'ai testé ça :
| Citation : #include <stdio.h>
|
Donc c'est tout simple.
Mais le compilateur m'affiche une erreur, le programme doit fermer etc ..
Note : J'ai volontairement appelé un fichier qui n'existe pas pour que le mesage d'erreur s'affiche.
Or, même quand j'enlève le Fclose (cette fois-ci plus de message d'erreur), mais le message ne s'affiche pas
Aurais-je fait une erreur ?
Merci et bonne soirée
Répondre à XmichouX
le test d'égalité se fait avec 2 =
fichier == NULL
Penser à voir les tutos, ca peut aider!
Répondre à coca25
Ah oui juste, encore une erreur bête de ma part, désolé et merci dela réponse
Répondre à XmichouX
Désolé d'encore vous réenbêter pour la même chose en plus, mais ..
En ayant le même code, en ayant créé le fichier test.txt et en ayant bien mis les 2 =;
Le compilateur me met encore une fenêtre que le programme va se fermer, et il m'affiche le message alors que le fichier existe
Répondre à XmichouX
fclose prend comme argument un pointeur FILE * et non une chaine de caractère.
et il faudrait l'inclure dans le if, car si l'ouverture retourne une erreur, il ne faut pas utiliser le pointeur pour fermer.
Penser à voir les tutos, ca peut aider!
Répondre à coca25
Ah oui d'accord.
Merci beaucoup
Répondre à XmichouX
Il y a 2391 utilisateurs connus et inconnus. Pour voir la liste des connectés connus, cliquez ici.
