J'ai suivi le tuto sur le langage C, d'ailleurs ce n'est pas la première fois, c'est juste que parfois j' "abandonne" plus ou moins puis je reviens plus tard quand je comprends mieux lol.
J'en suis à la partie des exercices sur les fonctions et tableaux, entre autres, faire une fonction qui renvoie la somme de toutes les valeurs d'un tableau.
J'aimerai savoir si quelqu'un peut me donner, non pas la réponse, mais des indications, parce que là je galère un peu.
Par exemple les commandes dont j'aurai besoin, est-ce qu'il faut passer par une boucle for ?
Ce n'est pas très compliquer, il faut créer une variable auquel tu ajoutera les valeurs de chaque case du tableau (à l'aide de la boucle for) et la fonction retournera la valeur de cette variable.
Pour poster ton code utilises le bouton code </> du forum !
Bon je viens d'essayer de faire une fonction qui renvoie simplement la somme de mon tableau en particulier en faisant : tableau[0] + tableau[1] + etc.. et même ça, ça fonctionne pas... génial...
En tous cas soit je suis vraiment pas doué soit malheureusement quand on arrive à ce niveau du chapitre on n'a clairement pas le niveau pour ça.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int sommeTableau(int tableau[], int tailleTableau) {
int somme;
somme = tableau[0] + + tableau[1] + tableau[2] + tableau[3];
return somme;
}
int main()
{
int somme = 0;
int tableau[4] = {1,1,1,1};
somme = sommeTableau(tableau[4],4);
printf("%d\n", somme);
return 0;
}
Normalement cela devrait renvoyer 1+1+1+1 donc 4, sauf que rien ne s'affiche puis le programme se termine.
J'ai bien fait "return somme;".
Par contre je ne sais pas si j'envoie correctement les paramètres à la fonction, je dois envoyer "tableau[4]" ?
Si je mets que "Tableau[]" le debugger me dit qu'il attends quelque chose entre les crochets.
- Edité par SébastienTellier 11 juin 2021 à 12:11:07
En effet tu ne parcours par le tableau avec une boucle.
Est-ce que tu as fait l'exercice qui demandait d'afficher les valeurs du tableau (ou bien de les saisir puis de les afficher) ? Je ne sais pas si cet exercice existe, mais ce ne serait pas étonnant vu que c'est la base pour parcourir un tableau à l'aide d'une boucle.
S'il n'existe pas, voici un énoncé précis : déclarer un tableau de taille 100 ; demander à l'utilisateur le nombre de valeurs qu'il souhaite entrer dans le tableau ; si ce nombre est compris entre 1 et 100, écrire une première boucle ('for' ou 'while') afin de saisir une à une chaque valeur du tableau, puis une deuxième boucle pour afficher toutes les valeurs saisies. Rappel : les valeurs du tableau ont des indices allant de 0 à n-1, où n est le nombre de valeurs à entrer.
-------
Attention :
somme = sommeTableau(tableau[4],4);
ici tableau[4] est l'élément d'indice 4 du tableau. Il n'existe pas, et de toute façon c'est tout le tableau que tu veux transmettre à la fonction, pas juste un élément. La bonne syntaxe est :
somme = sommeTableau(tableau,4);
C'est une syntaxe différente de la déclaration parce qu'on fait quelque chose de différent.
Je crois avoir réussi finalement donc je remodifie mon message, mais pour confirmer, est-ce que c'est correct comme ça ? :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int somme(int tableau[], int taille) {
int somme = 0, i = 0;
for (i = 0; i < taille; i++) {
somme = somme + tableau[i];
}
return somme;
}
int main()
{
int result = 0;
int tableau[8] = {1,1,1,1,1,1,1,1};
result = somme(tableau,8);
printf("\n%d\n", result);
return 0;
}
- Edité par SébastienTellier 11 juin 2021 à 12:37:37
Déjà, c'est une très mauvaise idée d'avoir une fonction et une variable du même nom ! somme dans ton code.
Ce qui fait que ce que tu affiches , ce n'est pas la somme du tableau mais l'adresse de la fonction somme !
Il faut aussi savoir que les variables déclarées dans une fonction ne sont visible que dans la fonction où elles sont déclarées.
Il faut aussi que tu fasses un retour sur le chapitre des fonctions pour te remémorer comment on exploite le retour d'une fonction.
- Edité par rouloude il y a moins de 30s
Certes ce n'est pas une bonne idée d'utiliser le même nom, mais le résultat de la dernière version est correct, ça affiche 8.
Attention au choix des exemples pour les tests. Parce que sur cet exemple, on retournerait taille au lieu de somme, ça ferait 8 aussi et on ne verrait pas qu'on s'est loupé.
On prendrait par exemple inttableau[4] = {1000, 200, 30 , 4}; // total 1234
ca permettrait d'être sur qu'on n'a pas mangé le premier ou dernier élément, ce qui est une erreur habituelle.
Mieux : écrire PLUSIEURS tests, en affichant pour chacun la valeur calculée, et la valeur attendue. Comme ça les problèmes sautent aux yeux.
C'est une bonne illustration de l’intérêt des fonctions
void tester_somme(char nom[], int tableau[], int taille, int attendu) {
printf("test %s, attendu = %d\n", nom, attendu);
int obtenu = somme(tableau, taille);
if (obtenu == attendu) {
printf("OK !\n");
} else {
printf("ERREUR, on a obtenu %d\n", obtenu);
}
}
int main() {
int t1[] = { 33 };
tester_somme("test 1", t1, 1, 33);
int t2[] = {20, 100, 3};
tester_somme("test 2", t2, 3, 123);
...
Mais du coup mon dernier exemple est juste selon vous ?
Je demande car je pense que rouloude a rédigé sa réponse avant que j'édite mon message, car en effet mon code précédent afficher l'adresse de ma variable au lieu de sa valeur.
Voici le code que j'ai maintenant et qui semble fonctionner :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int somme(int tableau[], int taille) {
int somme = 0, i = 0;
for (i = 0; i < taille; i++) {
somme = somme + tableau[i];
}
return somme;
}
int main()
{
int result = 0;
int tableau[20] = {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
result = somme(tableau,20);
printf("\n%d\n", result);
return 0;
}
Mais je vous demande quand même votre avis car j'ai cru comprendre que c'est pas parce que ça fonctionne que c'est forcément bien codé lol, ou du moins pas de la façon la plus optimale.
J'ai fait exprès de mettre un tableau de 20 "2" pour voir s'il me renvoyer bien la bonne somme et c'est le cas. Sachant que le but principal pour moi pour l'instant était vraiment de renvoyer la somme de toutes les valeurs du tableau.
- Edité par SébastienTellier 11 juin 2021 à 13:47:53
J'ai quand même réussi à faire un code plus propre, il me semblait bien que j'avais le droit de l'écrire comme ça, mais avant quand je l'avais fait ça fonctionnait pas, sûrement une erreur de syntaxe de ma part.
Voici le code maintenant, par contre je fais maintenant face à un autre problème, je n'arrive pas à afficher la moyenne exact (elle devrait être de 3,2 et mon code affiche 3,000000) : (si je met la variable "moyenne" dans la fonction en type double, j'ai une erreur)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int somme(int tableau[], int taille) {
int somme = 0, i = 0;
for (i = 0; i < taille; i++) {
somme = somme + tableau[i];
}
return somme;
}
double moyenne(int tableau[], int taille) {
int moyenne = 0, i = 0;
for (i = 0; i < taille; i++) {
moyenne = moyenne + tableau[i];
}
moyenne = moyenne / taille;
return moyenne;
}
int main()
{
int tableau[20] = {2,2,2,2,2,4,2,2,8,2,2,7,2,10,2,5,2,2,2,2};
printf("\n%d\n", somme(tableau,20));
printf("\n%f\n", moyenne(tableau,20));
return 0;
}
- Edité par SébastienTellier 11 juin 2021 à 14:15:07
(si je met la variable "moyenne" dans la fonction en type double, j'ai une erreur)
Ça ne prouve pas que c'état une mauvaise idée, tu t'y es peut-être mal pris.
Je pense qu'il faut faire quelque chose de ce genre :
double moyenne(int tableau[], int taille) {
double moyenne = 0.0; // c'est ce qu'on va retourner, il doit avoir
// le même type que la fonction
int i = 0;
/* ... ... ... ... */
return moyenne; // on retourne un 'double', là c'est OK
}
(Mais 'moyenne' est mal choisi pour nommer la variable qu'on retourne : c'est le nom de la fonction...)
PS : au lieu de refaire la somme des élément du tableau dans ta fonction, tu aurais pu utiliser la fonction somme qui fait très bien cela.
Je dirais même plus : tu DOIS utiliser la fonction somme.
Le cours n'insiste pas assez dessus (*) la programmation ne consiste à pas à réécrire du code qui fait la même chose, comme on résoudrait une série d'équations du second degré pour s’entraîner à appliquer les mêmes formules.
Ca consiste au contraire à CAPITALISER sur ce qui est déjà fait quand c'est possible. Et pour ça, à découper le travail en petits morceaux qu'on pourra réutiliser.
Et quand je dis réutiliser, c'est réutiliser tel quel, pas copier-coller en changeant un truc.
Donc la moyenne c'est la somme des éléments (qu'on obtient en appelant la fonction somme) divisée par le nombre d'éléments du tableau. Ça tient en une ligne.
(*) en fait il n'en parle pas du tout parce qu'il est un peu nul.
robun : ah oui merci c'était juste une erreur totalement bête de ma part lol.
michelbillaud : oui c'est vrai qu'il n'y a pas besoin de réécrire tout, vu que j'ai déjà la fonction "somme" qui fait une grosse partie du travail, mais comme c'est dit dans le cours, je pense que le but est de réécrire entièrement pour s'entrainer (enfin j'en sais rien).
En tous cas j'ai voulu tester un truc qui n'est pas dans le cours, justement pour m'entrainer, à savoir tester le problème 3A+1, pour l'histoire, en voici l'énoncé, bien que ça ne soit pas encore prouver actuellement :
On prend n'importe quel nombre, s'il est pair on le divise par 2 sinon on le multiplie par 3 et on ajoute 1, on recommence avec le résultat et ainsi de suite. On retombe toujours à 1.
En fait j'ai réussi à écrire un code qui le fait en demandant d'entrer un chiffre à l'utilisateur, c'est vraiment pas difficile du tout pour le coup.
Par contre j'ai voulu l'améliorer, sans demander d'intervention de l'utilisateur, mais que le programme teste de lui-même pour 1 puis pour 2 puis pour 3, jusqu'à X.
Mais visiblement, soit c'est plus compliqué que je croyais, soit j'ai pas encore le niveau nécessaire.
Là aussi il me semble qu'une boucle For est adaptée mais je ne suis pas sûr, en tous cas j'ai pas encore réussi.
- Edité par SébastienTellier 11 juin 2021 à 17:00:33
michelbillaud : oui c'est vrai qu'il n'y a pas besoin de réécrire tout, vu que j'ai déjà la fonction "somme" qui fait une grosse partie du travail, mais comme c'est dit dans le cours, je pense que le but est de réécrire entièrement pour s'entrainer (enfin j'en sais rien).
Il faut s'entraîner à
réutiliser, ce qui n'est pas facile.
et bien sûr aussi à savoir faire des boucles. Mais pas des boucles qui font exactement la même chose.
> Par contre j'ai voulu l'améliorer,
si on ne voit pas le code, on ne peut rien en dire.
> soit c'est plus compliqué que je croyais, soit j'ai pas encore le niveau nécessaire.
Personne n'a le niveau (quoique ça puisse vouloir dire) avant d'avoir passé du temps à se creuser pour essayer de trouver par lui même une solution.
Par contre j'ai voulu l'améliorer, sans demander d'intervention de l'utilisateur, mais que le programme teste de lui-même pour 1 puis pour 2 puis pour 3, jusqu'à X.
Mais visiblement, soit c'est plus compliqué que je croyais, soit j'ai pas encore le niveau nécessaire.
Là aussi il me semble qu'une boucle For est adaptée mais je ne suis pas sûr, en tous cas j'ai pas encore réussi.
Je pense que la boucle 'for' est une bonne idée. Et c'est une bonne idée, aussi, de vouloir écrire un programme plus "global" qui automatise les calculs.
Je pense qu'une bonne méthode serait de transformer le 'main' en une fonction. Mettons que ton programme ressemble à ça :
int main(void)
{ int ndep;
printf("Nombre de départ : ") ;
scanf ("%d", &ndep) ;
int n = ndep; // nombre courant
int nbiter = 0; // nombre d'itérations
while ((n > 1) && (nbiter < 1000000000))
{ nbiter += 1;
/* Calculs : si n est pair, alors...
si n est impair, alors ... */
}
printf("Au bout de %d itérations, n = %d\n", nbiter, n);
}
Eh bien tu le transformes en :
int probleme_3ap1(int ndep)
// Problème 3A+1 initialisé à ndep
// Retourne le nombre d'itérations pour tomber sur n = 1
// Si ce nombre vaut 1 milliard, c'est qu'on n'est pas tombé sur n = 1
{ int n = ndep; // nombre courant
int nbiter = 0; // nombre d'itérations
while ((n > 1) && (nbiter < 1000000000))
{ nbiter += 1;
/* Calculs : si n est pair, alors...
si n est impair, alors ... */
}
return nbiter
}
et, dans le programme principal, tu utilises cette fonction dans une boucle 'for', la variable de parcours étant ndep. À chaque itération :
int nbr_it = probleme_3ap1(ndep);
printf("Nb de départ = %d, Nb itérations = %d\n", ndep, nbr_it);
Et comme on te l'a mentionné, ce n'est pas une bonne idée que de donner le même nom à une fonction et une variable. Est-ce que sommeTableau et moyenneTableau sont si long à écrire? Et je sais que certains ne sont pas d'accord, mais il n'est pas nécessaire de tout initialiser. Si tu fais: int resultat = 0; resultat = sommeTableau(tableau, tailleTableau); Ça sert à quoi d'initialiser ici? Tu peux même écrire directement: int resultat = sommeTableau(tableau, tailleTableau);
Le Tout est souvent plus grand que la somme de ses parties.
Pour l'initialisation des variables, je suis tout simplement le cours, qui dit de faire comme ça et/ou conseille vivement de le faire.
Aussi je ne vois pas trop où j'ai écris que les fonctions étaient longues à écrire ?
Par contre, pourquoi nommer une variable de la même façon qu'une fonction est une mauvaise idée ? Dans mon cas c'est si choquant d'avoir une fonction "moyenne()" qui renvoie la valeur "moyenne" ? Ça me semble cohérent non ?
La question "est-ce qu'il faut une boucle for" a approximativement autant de sens que "est-ce que je dois utiliser la lettre z".
La boucle for, c'est une forme de boucle. Un truc qui répète un bout de code, sous certaines conditions.
La question, c'est de savoir quelle séquence d'instructions on veut répeter, et sous quelles conditions. Après on peut voir si on peut utiliser une boucle for pour traduire cette idée.
Si c'est "ajouter tous les t[i] à somme" (somme = somme + t[i]; ) à faire pour tous les i entre 0 et taille-1, la boucle for est toute indiquée pour ça, c'est même une forme idiomatique ( for (int i=0; i < taille; i++) ), c'est à dire LA formule magique habituelle que tout le monde emploie systématiquement - par tradition - pour faire varier un indice d'un bout d'un intervalle à l'autre en C.
Parce qu'on pourrait faire autrement, par exemple un parcours dans l'autre sens
int n=taille;
while(n-->0) {
...
}
si on veut faire le malin. L'embêtant de faire le malin, c'est que le lendemain on ne comprend plus ce qu'on voulait faire. Alors qu'une tournure idiomatique, on la reconnaît du premier coup d’œil et on la comprend - parce qu'on l'a vue/écrite 100 fois - sans avoir à l'analyser.
Mais on n'est JAMAIS obligé d'utiliser une boucle for, on la remplace facilement par un while (et inversement). Après, savoir si c'est une bonne idée, c'est autre chose.
---
Sur l'emploi du mot moyenne
Déjà, dans
for (i = 0; i < taille; i++) {
moyenne = moyenne + tableau[i];
}
c'est pourri. Parce que là, ta variable elle contient une somme (partielle), et pas du tout une moyenne. La moyenne, c'est le quotient de la somme et de la taille.
En plus, sur cet exercice, ça ne sert à rien de calculer une somme d'entiers dans un double. Ça entraîne des conversions inutiles. Et si on programme en C, c'est pour exprimer un certain sens de l'économie de moyens.
Ensuite, en C, il est préférable d'éviter les "collisions de nommage", c'est à dire d'employer le même nom pour deux choses distinctes (nom de fonction / identificateur de variable). Si la fonction fait la somme d'un tableau, somme_tableau, c'est bien.
Juste pour dire que le problème 3A+1 dont tu parles (la conjecture de Syracuse) n'est pas « résolu » ; on ne sait pas si on atteint 1 en partant de n'importe quel nombre. Ça fait partie des problèmes mathématiques très faciles à comprendre, mais pour lesquels on n'a pas encore de solution.
Merci pour les explication, après le but est surtout de réussir à écrire un code qui fonctionne pour l'instant, si c'est "juste" que mon code n'est pas le plus parfait du monde pour l'instant je m'en contenterai lol, c'est sûr qu'il faudra que je choisisse mieux les noms de fonctions et variable si un jour je fais un code de plusieurs centaines de lignes, ce dont je doute vu que j'arrive déjà pas à tout comprendre dans le cours.
Les remarques sur les noms de variables, c'est pas pour avoir le code le plus parfait du monde. C'est pas décoratif. C'est "de l'hygiène" pour ne pas s'embrouiller quand on écrit son programme. Pour avoir plus facilement du code qui fonctionne, justement.
Parce que justement, tu peux te demander pourquoi tu n'as pas déjà du code qui fonctionne. Tu comptes sur un "niveau" qui te tombera un jour sur la tête, envoyé par le saint esprit ?
Tu verras vite que la difficulté quand on écrit des programmes, même des tout petits de 20 lignes, c'est qu'on s'enlise les neurones très très vite dans ce qu'on fait. Un des problèmes majeurs des débutants, c'est qu'ils surestiment obstinément leur capacité à maîtriser ce qu'ils font, genre "t'inquiète je sais ce que je fais, je suis quand même pas con, je ferai le ménage après, LOL".
Mais bon, tu constateras par toi même. Tout le monde passe par là.
> Pour l'initialisation des variables, je suis tout simplement le cours, qui dit de faire comme ça et/ou conseille vivement de le faire. Ouais, une chance qu'on ne te demande pas de te jeter à l'eau ... C'est mieux de le faire en général, mais si tu as une assignation presque juste après, c'est évident que l'initialisation est inutile. > Aussi je ne vois pas trop où j'ai écris que les fonctions étaient longues à écrire ? Tu ne l'as pas dit. Mais pourquoi ne l'as-tu pas fait? > Par contre, pourquoi nommer une variable de la même façon qu'une fonction est une mauvaise idée ? Dans mon cas c'est si choquant d'avoir une fonction "moyenne()" qui renvoie la valeur "moyenne" ? Ça me semble cohérent non ? Je crois que michelbillaud a très bien répondu à cela. Si tu regardes rapidement ton code, sauras-tu si c'est de la fonction ou de la variable dont il est question? N'attends pas d'écrire des programmes de 100 lignes pour prendre de bonnes habitudes. Tu comprendrais quelque chose à ceci sans commentaires? for(m=1, p=2; p <= l; m++, p+=p);
Le Tout est souvent plus grand que la somme de ses parties.
>> Ouais, une chance qu'on ne te demande pas de te jeter à l'eau ...
Excuse-moi de débuter... juste au passage, même sans te connaitre je peux dire qu'à un moment ou un autre tu es aussi passé par là même si tu as peut-être progressé plus vite personne n'échappe à l'étape d'être débutant un jour. D'ailleurs, comme le dit michelbillaud (marrant car j'ai écrit ça avant de lire sa dernière réponse).
>>Tu comprendrais quelque chose à ceci sans commentaires? >>for(m=1, p=2; p <= l; m++, p+=p);
Non avec une seule ligne de code c'est clair que j'aurai du mal à comprendre.
>> Parce que justement, tu peux te demander pourquoi tu n'as pas déjà du code qui fonctionne. Tu comptes sur un "niveau" qui te tombera un jour sur la tête, envoyé par le saint esprit ?
Non je n'attends évidemment pas qu'un "niveau" tombe par l'opération du saint-esprit, d'ailleurs je trouve ça curieux car si on réfléchit 2 minute je ne chercherai pas des indications pour faire les exercices sur le forum, je me dirais juste "tant pis j'y arrive pas, je reviendrai demain et ça sera bon" lol.
Après je saurai pas dire si je me surestime ou non, mais en tous cas même si j'ai un programme qui fonctionne, j'essaie de réfléchir ligne par ligne à ce qu'il fait, pourquoi il fonctionne ou pourquoi il ne fonctionne pas (en général c'est plus compliqué dans ce 2ème cas).
Par contre ça ne veut pas du tout dire que je comprends toujours tout, bien au contraire, notamment si je veux faire un programme qui va faire telle action, j'ai du mal à savoir de quel fonctions je vais avoir besoin, etc... Ce qui est assez problématique car je pense que c'est la base en fait lol
C'est vrai qu'il ne faudrait pas oublier nos propres débuts et être un peu indulgent. Ne noyons pas les débutants sous les conseils : ils ont les base à apprendre et c'est déjà pas facile (surtout en C !)...
(N'empêche que donner un même nom à une variable et à une fonction, c'est un peu tordu... )
Un truc qui sert pour les débutants, et encore pour robun et moi ... est d'afficher des résultats temporaires aux endroits stratégiques. Quand tu te sentiras plus à l'aise, tu pourras utiliser les debuggeur comme gdb. Un autre truc qui peut aider, c'est de te dire qu'un bon programmeur est fainéant (pas nécessairement vrai ...). Ça t'incitera à réfléchir aux moyens d'écrire du code et des fonctions pour ne pas répéter le même code tout le temps. Je reprend ta fonction moyenne: double moyenneTableau(int tableau[], int taille) { return (double) sommeTableau(tableau, taille) / taille; }
Le Tout est souvent plus grand que la somme de ses parties.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.