IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Des questions de débutante en vrac


Sujet :

C

  1. #1
    Membre Expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 60
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Billets dans le blog
    8
    Par défaut Des questions de débutante en vrac
    Heu je relis mon titre, ce n'est pas la débutante qui est en vrac, ce sont les questions.

    Je n'ai encore travaillé qu'un tuto en C, tuto assez poussé, mais je ne l'ai pas encore fini...

    Alors je me permets de poser ici mes questions en vrac comme elles viennent :

    1) Quand on utilise plusieurs fois une boucle for avec i, faut-il réinitialiser i à zéro entre deux boucles ?

    2) Existe-t-il une sorte de manuel des librairies standard de C ?

    3) Quand j'utilise une variable qui est affectée directement (par retour d'une fonction par exemple), puis-je sans danger ne pas l'initialiser dans la déclaration ? Il me semblait logique que oui, mais bon...
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

  2. #2
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Bonjour,

    1) Ca depend, en fait la structure d'une boucle for est comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for (initialisation ; condition ; pas)
    {
    }
    En general, on rempli ces trois champ, donc l'initialisation est faite. Dans ce cas, il est inutile de remettre i à 0.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    for (i=0 ; i<5 ; i++)
    {
        ...
    }
     
    /* Inutile */
    i = 10;
     
    for (i=10 ; i<25 ; i++)
    {
        ...
    }

    Cependant, il est possible de ne pas mettre l'initialisation, condition et pas.
    Ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    /* Boucle infini */
    for (;;)
    {
        ...
    }


    2) Une sorte de "manuel" ? Oui, il existe les page "man" qui decrive les fonction des librairie usuelle. Apres, pour une librairie importé style SDL, il y a la doc fourni avec.

    3) Oui, et non. En fait, c'est encore une question de gout. Si tu ne l'initialise pas avant, tu risque de faire une betise.

    Sinon, pourquoi ne pas affecter, quand c'est possible, directement le resultat de la fonction dès la declaration de la variable ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int moyenne = Moyenne (TouteLesNotes, nombreDeNote);

  3. #3
    Membre Expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 60
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Billets dans le blog
    8
    Par défaut
    Merci de tes 3 réponses, elles me vont impec.

    Heu, pour la 2, t'as un lien ? Ou faut que je passe absolument par la commande man sous unix ?

    Oops, j'ai trouvé via Google. Sur ma console, man 3 nom-de-la-fonction

    Une question qui rebondit sur la 3, mais qui touche à l'épineux problème des pointeurs (qui eux, ont vaguement tendance à vouloir me mettre en vrac, mais je me laisse pas faire... )

    Comment déclarer une valeur qui dit

    Je veux l'adresse de ce tableau de 26 lettres ???

    Le compilateur n'aime pas trop la ligne ci-dessous.

    int *mottire[26]=tireMot(pif);
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

  4. #4
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Pour le pointeur de tableau :


    En realité, ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int NomTableau[20];
    on aurait dit que NomTableau est un tableau de 20 int.
    En fait, non.
    NomTableau est un pointeur vers le premier element (en l'occurence NomTableau[0]).

    C'est pour cette raison que lors d'un scanf avec un tableau, on ne rajoute pas & puisque c'est deja un pointeur.


    NomTableau[3] == *(NomTableau + 3)
    Si je ne m'abuse.

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    Ce n'est pas exact.

    NomTableau est bel et bien un tableau de 20 int et non un pointeur. La preuve, c'est que ceci ne compile pas:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int NomTableau[20];
    int **pp = &NomTableau;
    Alors que ceci compile:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int NomTableau[20];
    int (*pt)[20] = &NomTableau;
    (Comme tu peux le voir, la syntaxe "pointeur sur tableau" est un peu contre-intuitive: traduit en langage clair, ça donnerait int[20]* pt, mais le compilo n'accepte pas ça).

    En fait, NomTableau peut être converti implicitement en pointeur sur le premier élément. Et là où c'est traitre, c'est que c'est fait automatiquement lors de l'appel d'une fonction.
    Si tu déclares une fonction ainsi:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    void UneFonction(int unTableau[20])
    tu te fais avoir, car en réalité le compilateur ignore le 20, voyant ceci:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    void UneFonction(int unTableau[])
    qu'il considère équivalent à ceci:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    void UneFonction(int *unTableau)

    Donc en fait, un tableau n'est jamais passé directement par valeur à une fonction: Il y a conversion implicite en pointeur à la place. C'est l'une des choses contre-intuitives du C.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Dendrite Voir le message
    Heu, pour la 2, t'as un lien ? Ou faut que je passe absolument par la commande man sous unix ?
    Par exemple: http://man.developpez.com

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  7. #7
    Membre Expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 60
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Billets dans le blog
    8
    Par défaut
    Merci à tous.

    Concrètement, sur les problèmes de pointeur, je vous mets mon code, vous allez voir où j'achoppe.

    J'ai construit cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //copie le mot du fichier à la ligne passée en paramètre
    //retourne le pointeur sur le mot copié
     
    int tireMot(ligneAleatoire){
        char ligne[26]={0}, mottire[26]={0};
        int i=0;
     
        FILE *fichier = fopen("liste.txt","r");;
        if (fichier == NULL){
            printf("Le fichier ne peut etre ouvert.");
            return 1;
        }
        while (fgets(ligne,26,fichier)!=NULL){
            i++;
            if(i==ligneAleatoire){
                strcpy(mottire,ligne);
            }
     
        }
        fclose(fichier);
        return *mottire;
    }
    1) Cette façon de renvoyer le pointeur est-elle bonne ?

    2) Par quel code je récupère dans le main le "mot tiré" du coup ?
    Pour l'instant, je parviens au mieux à en récupérer la première lettre... pour les raisons que vous dites bien sûr.

    Suis-je obligée de refaire une boucle ou y a-t-il une syntaxe directe ?
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

  8. #8
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Tu fais un return de mottire qui est un char[].

    Or, le return de ta fonction est ... int.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int tireMot(ligneAleatoire);
    ligneAleatoire est un type ?

    Bref, tu as plusieurs possiblité, mais celle la n'est pas bonne.
    Soit tu passe un tableau de caractere en argument a ta fonction, soit tu fais un return d'un tableau de caractere, retour que tu assignera.

  9. #9
    Membre Expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 60
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Billets dans le blog
    8
    Par défaut
    Ben en fait, je pensais faire un return du pointeur de mottire (j'ai mis l'étoile devant non ?) qui est un int...

    Mais bon... Quand je vous dis que je me mélange les pinceaux avec les pointeurs...

    ligneAleatoire est un paramètre, de type int... (le numéro de la ligne à copier).
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

  10. #10
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    En écrivant return *mottire; tu retourne le char (promu en int) situé à l'adresse mottire, soit le premier caractère du tableau mottire.

    Apparemment, tu voudrais plutôt renvoyer le tableau mottire contenant le mot (soit écrire quelque chose comme return mottire;)
    C'est simple, ce n'est pas possible : tu ne peux pas renvoyer le tableau (c'est à dire l'adresse de son début) ni accèder à ses éléments une fois sorti de la fonction parce que le tableau n'existe plus : C'est une variable locale et comme toute variable locale (non static) elle est détruite en sortie de fonction.

    On peut envisager 3 solutions :

    - mettre mottire en global. Naturellement les variables globales sont des pestes néfastes et tu ne voudras pas utiliser cette possibilité ce dont je te félicite d'avance.

    - Procéder par allocation dynamique (malloc) du tableau dans la fonction. Là, le tableau survivra à la sortie de fonction et on pourra le récupérer (mais il faudra penser à le détruire (free) quand on n'en aura plus besoin).

    - Créer le tableau avant l'appel de la fonction et le passer en argument à la fonction

  11. #11
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Pour ton tableau je te conseil vivement de le faire par allocation dynamique. En considérant la taille de 26 char ca donnerait pour créer le tableau:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char * mottire = malloc (26);
    Ce que je te conseil si tu utilises plusieurs fois le même chiffre comme ici 26, c'est d'utiliser une constante symbolique soit avant toutes fonctions:

    Puis le malloc donnerais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    char * mottire = NULL;
    /* ... plus loin dans ton code ... */
    mottire = malloc (BUFF_SIZE);
     
    /*
       Il faut toujours verifier le retour des malloc pour prevenir d'un echec eventuel.
       Ne pas oublier de librer avec free mottire avant la reinitialisation du mot pour
       une autre partie
     */
    if (mottire != NULL)
    {
       /* Le reste du code ... */
    }
    Le nom de la constante serait à remplacer partout où tu utilise la même valeur ! Le retour de la fonction est toute simple et comme d'habitude:


    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  12. #12
    Membre Expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 60
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Billets dans le blog
    8
    Par défaut
    Je suis bien embêtée. Quand j'essaie d'appliquer cela, ça ne tourne pas, sans pour autant me dire d'où vient le bug.

    Alors pardon, mais je récapépètte :

    Dans fonctions.h, j'ai ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define BUFF_SIZE 26
     
    char tireMot(ligneAleatoire);
    dans fonctions.c, j'ai ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <ctype.h>
    //copie le mot du fichier à la ligne passee en parametre
    char tireMot(ligneAleatoire){
     
        char *mottire=NULL,ligne[BUFF_SIZE]={0};
        int i=0;
     
        FILE *fichier = fopen("liste.txt","r");;
        if (fichier == NULL){
            printf("Le fichier ne peut etre ouvert.");
            return 1;
        }
     
        if(mottire!=NULL){
     
            mottire=malloc(BUFF_SIZE);
     
            while (fgets(ligne,BUFF_SIZE,fichier)!=NULL){
                i++;
                if(i==ligneAleatoire){
                    strcpy(mottire,ligne);
                }
     
            }
            fclose(fichier);
        }
        return mottire;
    }
    et enfin dans le main.c, ceci :
    Ne pas tout lire, juste le début, et la fin (la libération de la mémoire quand on sort de la boucle while en demandant à rejouer)...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "fonctions.h"
     
    int main(void){
        char s='s';
        char temp[26]={0}, curlet=0, rejoue='O';
        int vies, i, flag=0, pif, total=0, score=0;
     
     
     
        do{
            s='s';
            vies=5;
            total++;
     
            //Retourne un nombre aleatoire de 1 à 20
            pif=alea();
     
            //Retourne une copie du mot tire à la ligne pif de la liste de 20 mots
            char *mottire=NULL;
            mottire=tireMot(pif);
     
            printf("%s => %d lettres",mottire,strlen(mottire));
            for(i=0;i<(strlen(mottire)-1);i++){
                temp[i]='*';
            }
            temp[i]='\n';
     
     
            //tant que ni gagne ni perdu
            //boucle do while (faut bien rentrer d'abord)
            do{
                printf("\n\nMOT A TROUVER : %s\n",temp);
                printf("Il vous reste %d vie%c\n",vies,s);
                printf("Proposez une lettre (pas d'accent) : ");
     
                flag=0;
                curlet=lirelettre();
     
                for(i=0;i<strlen(temp);i++){
                    if (curlet==mottire[i]){
                        temp[i]=curlet;
                        flag=1;
                    }
                }
                if(flag==0){
                    vies--;
                }
                if(vies==1){
                    s=' ';
                }
     
            }
            while((strcmp(temp,mottire)!=0)&&(vies>0));
     
            if(vies<=0){
                printf("\n\nDommage, vous avez perdu.\n");
                printf("Il fallait trouver %s\n\n",mottire);
                printf("\nVotre score : %d/%d\n",score,total);
                printf("\n\nVoulez-vous rejouer ? (o/n)");
                rejoue=lirelettre();
            }
            if(strcmp(temp,mottire)==0){
                score++;
                printf("\n\nBravo ! Le mot etait : %s",mottire);
                printf("\nVotre score : %d/%d\n",score,total);
                printf("Voulez-vous rejouer ? (o/n)");
                rejoue=lirelettre();
            }
            if(rejoue=='N'){
                printf("\nVotre score : %d/%d\n",score,total);
                printf("Au revoir et a bientot !!!\n\n");
            }
            else{
                memset (temp, 0, sizeof (temp));
                free(mottire);
            }
        }
     
        while (rejoue=='O');
        return 0;
    }
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

  13. #13
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Il y a une anomalie ici puisque le test donnera toujours mottire== NULL et on n'entre jamais dans le if.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char tireMot(ligneAleatoire){
        char *mottire=NULL,ligne[BUFF_SIZE]={0};
        int i=0;
    ....
        if(mottire!=NULL){ 
            mottire=malloc(BUFF_SIZE);
    On attend plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char tireMot(ligneAleatoire){
        char *mottire=NULL,ligne[BUFF_SIZE]={0};
        int i=0;
    ....
        mottire=malloc(BUFF_SIZE);
        if(mottire!=NULL){
    ....
    et dans le main
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ....
            char *mottire=tireMot(pif)
            if(mottire!=NULL){
    ....

  14. #14
    Membre Expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 60
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Billets dans le blog
    8
    Par défaut
    Merci à vous 3 en tout cas.

    C'est corrigé Diogène.

    Mais ça ne fait rien de mieux.

    Je continue de voir ce qui peut coincer...

    Je corrige des trucs... mais ça n'est toujours pas le bon grain de sable...

    Voici mon dernier code, qui tente de tenir compte de toutes les remarques...

    Peut-être les entêtes posent-ils problème ?

    Une autre question : maintenant que je libère le malloc avec un free, faut-il conserver le memset pour réinitialiser le tableau mottire ?

    dans fonctions.h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #define TAILLE_MAX 1000
    #define BUFF_SIZE 26
    char lirelettre();
    int alea();
    char tireMot(int ligneAleatoire);
    dans fonctions.c

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <ctype.h>
     
    #include "fonctions.h"
    //scanf nous creerait des pblemes
    //il faut construire un truc a la main
    char lirelettre(){
        char lettre = 0;
     
        lettre = getchar();
        lettre = toupper(lettre);
        while (getchar() != '\n') ;
        return lettre;
    }
    //genere un nb au pif entre 1 et 20
    int alea(){
        int nb=0;
        srand(time(NULL));
        nb = (rand() % (20 - 1 + 1)) + 1;
        return nb;
    }
     
    //copie le mot du fichier à la ligne passe en parametre
    char tireMot(int ligneAleatoire){
        char *mottire=NULL,ligne[BUFF_SIZE]={0};
        int i=0;
     
        FILE *fichier = fopen("liste.txt","r");;
        if (fichier == NULL){
            printf("Le fichier ne peut etre ouvert.");
            return 1;
        }
     
        mottire=malloc(BUFF_SIZE);
        if(mottire!=NULL){
            while (fgets(ligne,BUFF_SIZE,fichier)!=NULL){
                i++;
                if(i==ligneAleatoire){
                    strcpy(mottire,ligne);
                }
            }
            fclose(fichier);
        }
        return mottire;
    }
    et enfin dans main.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "fonctions.h"
     
     
    int main(void){
        char s='s';
        char temp[26]={0}, curlet=0, rejoue='O';
        int vies, i, flag=0, pif, total=0, score=0;
     
     
     
        do{
            s='s';
            vies=5;
            total++;
     
            //Retourne un nombre aleatoire de 1 à 20
            pif=alea();
     
            //Retourne une copie du mot tire à la ligne pif de la liste de 20 mots
     
            char *mottire=tireMot(pif);
     
            if(mottire!=NULL){
     
                printf("%s => %d lettres",mottire,strlen(mottire));
     
            }
     
            for(i=0;i<(strlen(mottire)-1);i++){
                temp[i]='*';
            }
            temp[i]='\n';
     
     
            //tant que ni gagne ni perdu
            //boucle do while (faut bien rentrer d'abord)
            do{
                printf("\n\nMOT A TROUVER : %s\n",temp);
                printf("Il vous reste %d vie%c\n",vies,s);
                printf("Proposez une lettre (pas d'accent) : ");
     
                flag=0;
                curlet=lirelettre();
     
                for(i=0;i<strlen(temp);i++){
                    if (curlet==mottire[i]){
                        temp[i]=curlet;
                        flag=1;
                    }
                }
                if(flag==0){
                    vies--;
                }
                if(vies==1){
                    s=' ';
                }
     
            }
            while((strcmp(temp,mottire)!=0)&&(vies>0));
     
            if(vies<=0){
                printf("\n\nDommage, vous avez perdu.\n");
                printf("Il fallait trouver %s\n\n",mottire);
                printf("\nVotre score : %d/%d\n",score,total);
                printf("\n\nVoulez-vous rejouer ? (o/n)");
                rejoue=lirelettre();
            }
            if(strcmp(temp,mottire)==0){
                score++;
                printf("\n\nBravo ! Le mot etait : %s",mottire);
                printf("\nVotre score : %d/%d\n",score,total);
                printf("Voulez-vous rejouer ? (o/n)");
                rejoue=lirelettre();
            }
            if(rejoue=='N'){
                printf("\nVotre score : %d/%d\n",score,total);
                printf("Au revoir et a bientot !!!\n\n");
            }
            else{
                memset (temp, 0, sizeof (temp));
                free(mottire);
                memset (mottire, 0, sizeof (mottire));
            }
        }
     
     
        while (rejoue=='O');
        return 0;
    }
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

  15. #15
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int alea(){
        int nb=0;
        srand(time(NULL));
        nb = (rand() % (20 - 1 + 1)) + 1;
        return nb;
    }
    srand ne doit être utilisé qu'une fois pour initialiser le générateur aléatoire. Sa meilleure place est au début du programme dans main().
    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char tireMot(int ligneAleatoire){
    ....
                if(i==ligneAleatoire){
                    strcpy(mottire,ligne);
                }
    Comme fgets() conserve le '\n', il vaut mieux l'enlever pour cette application en le remplaçant par le caractère de fin de chaine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                if(i==ligneAleatoire){
                    char * p = strchr(ligne,'\n');
                    if(p!= NULL) *p = '\0';                   
                    strcpy(mottire,ligne);
                }
    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main(void){
    ....
            if(mottire!=NULL){
                printf("%s => %d lettres",mottire,strlen(mottire));
            }
    cette condition devrait englober tout le code qui utilise mottire puisque l'allocation a échoué et que le code ne peut plus être exécuté.

    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            for(i=0;i<(strlen(mottire)-1);i++){
                temp[i]='*';
            }
            temp[i]='\n';
    Le caractère terminant une chaine est '\0', pas '\n'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            for(i=0;i<(strlen(mottire);i++){
                temp[i]='*';
            }
            temp[i]='\0';
    - Le dernier memset est illégal : on ne peut mettre quelque chose dans une zone mémoire désallouée (par le free())
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
                memset (temp, 0, sizeof (temp));
                free(mottire);
                memset (mottire, 0, sizeof (mottire));

  16. #16
    Membre Expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 60
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Billets dans le blog
    8
    Par défaut
    D'avance merci pour tout Diogène. Je regarde tout ça demain.

    Juste un truc : pour le '\n', oui je savais...
    Simplement comme j'avais repéré que fgets conservait le \n, je bidouillais un truc sur temp (le tableau qui met les petites étoiles au départ et affiche ensuite les lettres trouvées) pour rattraper le coup... Mais ta méthode (remplacer le retour chariot par un \0 dès le départ) est bien plus propre...

    Quant à l'affichage (conditionnel mal cadré) de ce que retourne la fonction, c'était un ajout de dernière minute... Pour tester le retour...

    Merci encore... Je te donne des nouvelles demain.
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

Discussions similaires

  1. [W3C] Question de débutant pour remplacement des frames
    Par Grizzzly dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 24/07/2009, 16h44
  2. [Débutant] Des questions pour débutants
    Par Mo_Poly dans le forum ASP
    Réponses: 13
    Dernier message: 12/10/2008, 13h31
  3. Question de débutant au sujet des guillemets
    Par Evocatii dans le forum Langage SQL
    Réponses: 2
    Dernier message: 25/03/2008, 13h09
  4. Réponses: 2
    Dernier message: 14/01/2008, 07h32
  5. Débutant se posant des questions sur son futur
    Par Maxi-môme dans le forum Emploi
    Réponses: 25
    Dernier message: 31/08/2007, 23h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo