Langage C

Discutez d'informatique ici !
Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 28 Sep 2013, 18:47

Le corps d'une fonction peut être placé n'importe où, mais bien-sûr hors d'une autre fonction. Quand je dis n'importe où, ça peut être avant, ou après le main, ou dans un autre module.
Par contre le prototype doit être placé avant l'appel, c'est pour ça que les include sont en début de module.
Le compilateur attend une fonction qui s'appelle main. Il ne doit y en avoir qu'une seule.
Un module C comporte forcément des #include.
Il y en a de 2 types, soit #include soit #include "MesEntetes.h".
Dans le premier cas, ce sont des fonctions des librairies que le compilateur connait, dans le second cas, ce sont des fichiers d'entête perso.
Si on a un programme court, c'est pas utile de faire des tas de modules, mais dans le cas général, se sera indispensable. J'ai un programme qui en comporte une centaine. On reparlera plus tard des modules supplémentaire.
Dans tous les cas, les fichiers d'entête contiennent les prototypes des fonctions. C'est EXACTEMENT la même ligne que la première ligne de la fonction, et elle est terminée par un point-virgule. Exemple
bool verif(char c);



Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 28 Sep 2013, 19:02

fatal_error a écrit:Donc pour la définition de ta fonction verif:
avant toute utilisation de ta fonction verif, il faut que celle-ci soit déclarée
c'est à dire qu'au moins sa signature ai été écrite:
Code: Tout sélectionner
bool verif();//declaration
int main(){
 verif()
}...
bool verif(){
 //implementation plus tard
}



Ah d'accord je comprends mieux; je compile bien maintenant; en revanche; l'exe me saute toujours la réponse au Voulez vous continuez; il semblerait donc que la fonction de purge soit bel et bien obligatoire.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 28 Sep 2013, 22:23

Bonsoir, juste un petit mot concernant la description d'une fonction à l'intérieur d'une autre. Avec le Fortran 77 (après, je ne sais pas), c'était une pratique normale. Par contre, la récursivité était impossible. L'organisation du code et la gestion de la mémoire explique que l'une des technique est possible, mais pas les deux ensemble.
Concernant la répétition, il faut comprendre le code donné par Ampholyte et tout ira bien.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 28 Sep 2013, 22:46

Le blem c'est que tout ce qui est caractère "caché" dans stdin ou autre, on ne l'a pas vu du tout en cours; donc j'arrive à comprendre le code mais en toute honnêteté je ne suis pas du tout censé être capable de sortir ça, ou alors les prof attendent qu'on apprenne toutes les syntaxes seul de notre coté; ce qui ne serait pas pour me gêner mais bon...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 28 Sep 2013, 23:00

Alors, mon conseil, tu prends les codes de Amphodyte, les deux derniers de mémoire et tu essayes de comprendre ce qui se passe, ligne à ligne. Ce que tu ne comprends pas, tu demandes.
En informatique, il n'y a rien de caché (au moins en C). Il me parait indispensable de tout comprendre, et surtout pas essayer de réécrire un code de mémoire.
stdin, c'est un flux, c'est à dire que c'est une suite de caractères mis les uns après les autre, comme, d'ailleurs, n'importe quel fichier.
Je précise un terme important, le nom d'une fonction, avec ses paramètres et le type de valeur renvoyé s'appelle un prototype.
Un prototype peut être dans le module qui appelle la fonction, ou dans le fichier header (.h), et avant l'appel. Le corps de la fonction peut être n'importe où.

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 08:03

par ampholyte » 29 Sep 2013, 11:22

Bonjour,

Il ne faut pas oublier que lorsque que l'on commence à apprendre un langage, il y a de nombreux réflexes à acquérir. Ces réflexes ne sont très souvent pas expliqués par les professeurs (je ne sais pour quelles raisons).

Personnellement voici les quelques conseils que je peux te donner :

* Lorsque tu ne connais pas une fonction en C, fais une recherche en tapant man ma_commande (sur une console ou directement sur google).

Ex : je souhaite plus d'informations sur la commande fgets ?
Code: Tout sélectionner
man fgets

(essaye de voir ce que ça te donne)

* Si tu as un problème, une erreur, fouille un peu sur les différents sites, ta question a déjà été sûrement posée =).
Par exemple en entrant simplement sur google "boucle scanf" je tombe sur le site suivant : http://xrenault.developpez.com/tutoriels/c/scanf/ ou encore http://www.developpez.net/forums/d755818/c-cpp/c/boucle-infinie-lors-saisie-lettre-ld-scanf/

Ce sont certainement les deux points les plus importants à acquérir car cela te permettra de progresser très rapidement =).

Bien entendu, tu peux poser tes questions sur des forums afin d'avoir de meilleurs explications ou des conseils. Mais le meilleur moyen est de commencer par chercher un peu par soi-même.

En programmation, on ne t'apprendra que les bases, c'est à toi de te perfectionner et de t'adapter au langage.

@fatal_error : on a déjà débattu il me semble sur les tests à faire lorsque l'on doit faire un exercice. Qui est responsable et pourquoi ? Chacun à sa manière de voir les choses, mais rien n'empêche de commencer à faire les choses le plus rigoureusement possible pour après se permettre (ou non) de faire des raccourcit.

Est-ce que je teste le retour d'un malloc ? Oui (même si je préfère utiliser calloc), au début. Pourquoi peut-on "s'en passer" ? Car les PC actuelles sont beaucoup plus performant et une erreur sur un malloc est assez rare.

Personnellement, je teste toujours pour éviter les segfaults et autres joyeusetés car pour moi, même si les risques sont minimums ils ne sont pas nuls.

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 29 Sep 2013, 11:49

Bonjour Ampholyte,
Concernant les tests, pour moi, la seule question qui se pose, c'est où les faire. Je me place dans le cas de l'appel à une fonction, faut-il le faire avant l'appel ou au début de la fonction. Evidemment ça dépend des cas, mais naturellement il n'est pas question de ne pas le faire.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 29 Sep 2013, 12:31

Un autre petit soucis; je pense que cela est du à mon utilisation des tableaux et non à mon algorithme.

le programme est censé donné la liste de nombre parfait entre deux valeurs; mais en sortie il me donne une liste de valeur ahurissante et surtout beaucoup plus grande que la taille qu'il est censé respecter.

Code: Tout sélectionner
int main()
{
    int n1,n2;
    do
        {
    printf("Tapez un nombre:");scanf("%d",&n1);
        }
        while (n1<0);
    do
        {
    printf("\nTapez un nombre:");scanf("%d",&n2);
    }
    while (n2<0);
    int mini;
    int maxi;
    if (n1<=n2)
    {
        mini=n1;
        maxi=n2;
    }
    else
    {
        mini=n2;
        maxi=n1;
    }
/* a priori jusqu'à cette partie tout se passe bien vu que mon affichage final du min et max se fait dans le bon ordre*/

    int k;
    int parfait[maxi-mini];
    int cpt=0;
    for (k=mini;k<maxi;k++)
    {
        int s=0;
        int i;
        for (i=1;i<k/2;i++)
        {
            if (k%i==0)
            {
                s=s+i;
            }
        }
        if (k==s)
        {
            parfait[cpt]=k;
        }
        cpt=cpt+1;
    }
    printf("Les nombres parfaits entre %d et %d sont: ",mini,maxi);
    int i;
    for (i=0;i<=cpt;i++)
    {
        printf("%d \n",parfait[i]);
    }
    return 0;
}

Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 29 Sep 2013, 12:50

Bonjour,
Moi, je vois plusieurs fautes.
D'abord, il n'y a pas le moindre commentaire. Ca, c'est une faute grave.
Puis, à mon avis, il y a des incohérences en matière de comptage, de limite etc.
La seule façon de vérifier et/ou corriger cela est de mettre des impressions intermédiaires.
Enfin, un conseil : au lieu d'écrire
Code: Tout sélectionner
int i;
for (i=0; i<MAX; i++)
{
...
}
il vaut mieux écrire
for (int i=0; i<MAX; i++)
{
...
}

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 29 Sep 2013, 13:32

Je ne savais pas que l'on pouvait déclarer la variable de compteur directement dans le for; je trouve ça effectivement beaucoup mieux pour la lisibilité générale.

Pour les commentaire; oui je te l'accorde sur celui ci j'aurais pu en mettre sur la seconde partie; j'aurais du devrais je dire. Je vais m'empresser d'aller en placer et de faire les modification au niveau des déclarations de i,k etc etc

Je suppose avant de tester que si je déclare le i par exemple dans la boucle for il ne sera pas utilisable en dehors de cette boucle comme c'était le cas en ada ? Auquel cas je trouve cela bien mieux pour limiter le nombre d'erreur !
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 29 Sep 2013, 13:50

Je ne connais pas l'ADA, donc je ne peux pas faire de comparaison.
Je vais faire un aveu, je viens d'apprendre ce qu'est un nombre parfait.
"limiter le nombre d'erreurs" : quelle expression horrible : il faut ZERO erreurs.

[EDIT] Ben, y'en a pas beaucoup. :lol3: J'en ai trouvé que 2 entre 1 et 100 :id:

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 29 Sep 2013, 14:20

[quote="Dlzlogic"]Bonjour,
Moi, je vois plusieurs fautes.
D'abord, il n'y a pas le moindre commentaire. Ca, c'est une faute grave.
Puis, à mon avis, il y a des incohérences en matière de comptage, de limite etc.
La seule façon de vérifier et/ou corriger cela est de mettre des impressions intermédiaires.
Enfin, un conseil : au lieu d'écrire
[CODE]int i;
for (i=0; i<
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 29 Sep 2013, 14:24

Bon, alors laisse la déclaration à l'extérieur.
Windows a toujours été à part, c'est comme ça :mur:

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 29 Sep 2013, 14:35

Dlzlogic a écrit:Je ne connais pas l'ADA, donc je ne peux pas faire de comparaison.
Je vais faire un aveu, je viens d'apprendre ce qu'est un nombre parfait.
"limiter le nombre d'erreurs" : quelle expression horrible : il faut ZERO erreurs.

[EDIT] Ben, y'en a pas beaucoup. :lol3: J'en ai trouvé que 2 entre 1 et 100 :id:


TU t'es planté alors le seul entre 10 et 100 est 28 :lol3:

EDIT: en fait non j'ai lu trop vite j'ai cru que tu avais écris 10...effectivement entre 1 et 100 il y a 6 aussi

Entre 10 et 500 les seuls sont 28 et 496


Pour ma part; j'ai placé les commentaires; et cela m'a permis de trouver l'erreur qui rendait mes nombres absurdes; j'incrémentais le compteur à l'extérieur de mon if...au final je l'incrémentais 490 fois entre 10 et 500 --'

Problème réglé...cela dis je ne trouve toujours pas le bon résultat vu qu'entre 10 et 500 le seul nombre qu'il me trouve est 24; qui n'est toujours pas bon^^

Cela dit il s'agit donc d'une erreur d'algorithme et je vais essayer de le repasser à la main pour voir ce qui cloche !

Code: Tout sélectionner
int main()
{
    int n1,n2;
    do
        {
    printf("Tapez un nombre:");scanf("%d",&n1);
        }
        while (n1<0);
    do
        {
    printf("\nTapez un nombre:");scanf("%d",&n2);
    }
    while (n2<0);
    int mini;
    int maxi;
    if (n1<=n2)
    {
        mini=n1;
        maxi=n2;
    }
    else
    {
        mini=n2;
        maxi=n1;
    }
    int parfait[(maxi-mini)]; /*Etendu de valeur parfaite possible au maximum*/
    int cpt=0;
    int k;
    for (k=mini;k<maxi;k++) /*k devient le min et parcourt l'étendu*/
    {
        int s=0;
        int i;
        for (i=1;i<k/2;i++)
        {
            if (k%i==0)
            {
                s=s+i; /*on somme les diviseurs de k dont le reste est 0*/
            }
        }
        if (k==s)
        {
            parfait[cpt]=k; /*si la somme s et le nbre k sont identique; on stocke le
            nbre k dans le tableau parfait qui s'indice de 0 à cpt*/
            cpt=cpt+1;
        }
    }
    printf("Les nombres parfaits entre %d et %d sont: ",mini,maxi);
    int z;
    for (z=0;z<cpt;z++)
    {
        printf("%d \n",parfait[z]);
    }
    return 0;


EDIT 2 : Là encore l'erreur a été vite vu, j'avais simplement mis un < au lieu d'un <= ...



ce que je trouve bien dans le C pour le coup c'ets le fait de ne pas forcément définir un tableau avec une taille constante dès le départ. Si je devais comparer avec l'ada; j’aurais du créer une taille effective peut être de 10 000 et après seulement réaliser une taille réelle de N données de l'utilisateur...hors si l'étendue passe au dessus des 10 000 on tape forcément en dehors des bornes; à priori en C ce genre de soucis ne peut pas arriver. :zen:
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 29 Sep 2013, 14:46

Oui, y'en a bien 3 entre 1 et 1000, mais dis-moi comment tu sais que c'est 6, 28 et 496 si ton programme ne marche pas ?

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 29 Sep 2013, 14:50

D'abord, il n'y a pas le moindre commentaire. Ca, c'est une faute grave.

Non c'est pas une faute grave. Pour toi peut-être, mais n'en fais pas une généralité.
Un algo ca se décrit certes, mais pas de préférence en plein milieu de la fonction au fur et à mesure qu'on lit...

"limiter le nombre d'erreurs" : quelle expression horrible : il faut ZERO erreurs.

et allez continuons à débiter des énormités.

Pour ce qui est du programme, je suis assez surpris par
int parfait[(maxi-mini)];

Ton compilateur t'autorises la compilation? :D
Tu ne devrais pas pouvoir étant donné que tu ne connais pas la taille de ton tableau à la compilation...
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 29 Sep 2013, 14:58

Ton compilateur t'autorises la compilation? :D
Tu ne devrais pas pouvoir étant donné que tu ne connais pas la taille de ton tableau à la compilation...


Je suis aussi surpris que toi; d'où la dernière partie de mon message.

Mais à priori il compile et s’exécute bien comme ça. Après tout, si on regarde en toute logique; maxi-mini c'est bien une valeur, cependant c’est vrai qu'elle n'est pas connu à la compilation; peut être est ce du au fait que je force au départ le fait que maxi et mini soit positif; d'où l'assurance que ces variables donneront un nombre positif dans le tableau.


Oui, y'en a bien 3 entre 1 et 1000, mais dis-moi comment tu sais que c'est 6, 28 et 496 si ton programme ne marche pas ?


J'avais réalisé le même en ada l'an dernier; puis mon programme marche, j'ai édité entre temps =)
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 29 Sep 2013, 15:18

et allez continuons à débiter des énormités.
Je pense qu'il vaut mieux éviter ce genre de commentaire.

Le problème de la dimension du tableau non précisée équivaut à mon avis à une dimension nulle, mais ce n'est qu'un hypothèse. A l'évidence ceci est une faute grave qui aurait dû être détectée à la compilation.
Pour moi, le problème se situe à un autre niveau : pourquoi prévoir un tableau énorme pour n'utiliser que 2 ou 3 positions ?

Donc, j'avais pas lu le rajout.
En C on peut réserver un espace pour un tableau alors qu'on ne connait pas sa dimension à la compilation, mais c'est certainement pas comme ça.
Va voir malloc, c'est la fonction qui fait cela.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 29 Sep 2013, 15:35

En C on peut réserver un espace pour un tableau alors qu'on ne connait pas sa dimension à la compilation, mais c'est certainement pas comme ça.


Comment explique tu que cela fonctionne donc ? C'est pas une critique hein je cherche juste à comprendre...le compilateur a bien pris cette ligne et le programme tourne correctement c'ets qu'il y a bien une raison.


Pour moi, le problème se situe à un autre niveau : pourquoi prévoir un tableau énorme pour n'utiliser que 2 ou 3 positions ?


Il y a à mon sens deux problèmes différent; le codage qui est le travail du programmeur et l'analyse qui est le travail de l'analyste ou de la personne pour laquelle travaille le programmeur; bien que l'on trouve de plus en plus de programmeurs qui fassent ces deux fonctions simultanément je pense.

Si je me place dans le cas similaire au tien en fait au début de ce problème, je ne sais pas combien de nombre parfait il existe; mais je sais qu'il ne peut pas y en avoir plus que l'étendu donné par le mini et le maxi.

Alors certes, sachant qu'il n'y en a beaucoup j'aurais pu mettre parfait [30] et j'aurais été tranquille pour un nombre exponentiel je pense; mais ça n'a pour moi pas de sens à ce moment là; tout du moins pas dans un exercice.

Je peux me tromper mais ce n’est que mon avis.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 29 Sep 2013, 15:54

Difficile de répondre.
D'abord, tu apprends 2 choses, l'analyse et la programmation. Je suppose que ce calcul de nombre parfait est un exercice proposé pour apprendre. Et je suppose aussi que le prof veut vous faire comprendre certaines notions fondamentales.
Il est sûr et certain que le C ne peut pas réserver de l'espace mémoire pour un tableau dont il ne connait pas la dimension.
Il peut y avoir plusieurs explications possibles
1- l'outil avec lequel tu travailles est en fait un interpréteur de langage C. C'est très facile et très amusant à développer, mais ce sera jamais un compilateur.
2- l'outil avec lequel tu travailles a prévu certaines libertés, par exemple dans le cas du tableau, en l'absence d'information, il réserve un tableau de 16 positions.
Bien sûr, on peut faire des tests pour vérifier cela, mais comme je n'ai pas cet outil, je ne peux pas le faire.
Moi, j'ai fait le calcul et je n'ai pas prévu de tableau.
Tu pourrais faire un petit test simple : tu écris une fonction qui fait ce calcul. C'est à dire que le main ne sert qu'à lire les 2 limites.
Tu passes n1 et n2 en paramètre, et tu déclares le tableau dans la fonction.
Et tu racontes ce qui se passe.

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 26 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite