Annonce

Réduire
Aucune annonce.

Cours langage C n°10 - Interface utilisateur console

Réduire
Ceci est une discussion importante.
X
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Cours langage C n°10 - Interface utilisateur console

    Interface utilisateur console


    Imaginons que vous vouliez calculer votre moyenne générale, vous pourriez mettre les moyennes de chacune de vos matières dans le programme. Cela implique que vous rentriez en dur (dans le code) toutes vos moyennes avec les étapes suivantes:
    1. Exécuter code::blocks
    2. Éditer votre programme
    3. Entrer vos moyennes

      Code:
      float moyennes[] = {12.5, 15, 7, 9.5, 18, 10, 5.5};
    4. Exécuter le programme


    T'as pas plus simple Fred, car rien que lire toutes ces étapes ça me fatigue déjà ?

    Euh, attendez que je réfléchisse... Si c'est possible, regardez plus bas
    1. Exécuter votre programe
    2. Entrer vos moyennes


    Mieux non?

    Ok c'est mieux, mais on fait comment ? Nous allons voir deux fonctions faîtes pour cela
    • scanf (pour récupération des entiers, flottants, ...)
    • fgets (pour des chaînes de caractères)


    Scanf mon sauveur !

    Grâce à scanf, vous pourrez récupérer la valeur inscrite par l'utilisateur dans la console pour l'enregistrer dans une variable...

    C'est cool ça, mais je connais pas scanf ! Eh bien on va analyser son prototype

    int scanf ( const char * format, ... );

    Que remarque-t-on ? Cette fonction
    • retourne un entier (il permettra de vérifier que la fonction s'est exécutée correctement)
    • prend plusieurs paramètres, une chaîne de caractère format ("%d, %s, %f, ...) et ... (autant de paramètres que l'on souhaite)


    Les ... on verra plus tard, pour l'instant on considérera que scanf prend une chaîne de formatage et une variable dont le type correspond au formatage

    ok, ok, d'accord ! Bon je met quoi comme type d'argument, que dit la documentation ?

    Envoyé par documentation
    These arguments are expected to be pointers: to store the result of a scanf operation on a regular variable, its name should be preceded by the reference operator (&)
    Non, mais ça me poursuit, une variable pointeur, je suis mort ! Mais non un pointeur est une variable contenant une adresse. Pour avoir cette adresse nous aurons besoin de l'opérateur &, d'ailleurs c'est indiqué dans la partie anglaise ci-dessus...

    Exemple d'utilisation:

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        int retour;
        int valeur; /* déclaration de mes variables retour et valeur */
    
        printf("Entrer un entier: ");
        retour = scanf("%d", &valeur); /* demande entier à utilisateur */
    
        if (retour == 1) /* on vérifie qu'on a bien 1 conversion qui s'est passé */
        {
            printf("\nta valeur entrée est %d\n", valeur); /* on affiche valeur */
        }
    
        return 0;
    }
    Testez ce code ! Entrer des types différents
    • un entier (exemple 12)
    • un flottant (exemple 12.5)
    • un caractère (exemple a)
    • une chaîne de caractère (exemple abc)


    que remarquez-vous ?

    Bien, mais si je reviens à mon problème, j'ai plusieurs valeurs à entrer, je fais comment ?

    Avec des boucles, non?

    Voici un exemple:

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        int i;
        int retour;
    
        int mesValeurs[3];
    
        int valeur; /* déclaration de mes variables retour et valeur */
    
        for (i=0; i<3; i++) /* 3 valeurs à entrer */
        {
            printf("Entrer l'entier n°%d: ", i+1);
            retour = scanf("%d", &valeur); /* demande entier à utilisateur */
    
            if (retour == 1) /* on vérifie qu'on a bien 1 conversion qui s'est passé */
            {
                mesValeurs[i] = valeur; /* enregistrement de valeur n°i dans mesValeurs[i] */
            }
    
            else /* si erreur de conversion, scanf s'est mal passé */
            {
                puts("\nErreur de conversion");
                return -1;
            }
        }
    
        for (i=0; i<3; i++) /* affichage des valeurs de mon tableau */
        {
            printf("\nvaleur n°%d vaut %d\n", i+1, mesValeurs[i]);
        }
    
        return 0;
    }
    Testez le programme, et dites ce que vous ne comprenez pas dans ce même topic

    Si on veut faire cela avec des flottants, on fait comment ?

    On change de formatage en remplaçant %d par %f, vu dans la partie fonctions d'affichage

    ok, d'ac, c'est parti, refaire le même programme en remplaçant %d par %f au bon endroit et vérifier que cela fonctionne tout aussi bien qu'avec des entiers...

    fgets mon sauveur

    Comme scanf, fgets nous permettra de récupérer la valeur entrer par l'utilisateur et l'enregistrer dans une variable, pour là traiter par la suite.

    Analysons cette fonction à l'aide de son prototype

    char * fgets ( char * str, int num, FILE * stream );

    Ouffff, balèze celle-là !

    Non paniquez pas, je vous explique, la fonction fgets
    • retourne une variable (pointeur) contenant une adresse de type char (permettra de vérifier que la fonction s'est correctement exécutée)

      Envoyé par documentation
      If a read error occurs, the error indicator (ferror) is set and a null pointer is also returned
      En gros on va vérifier que l'enregistrement de la valeur utilisateur est bien dans la variable str, en testant si on a une valeur NULL en retour de fonction
    • prend comme 1er paramètre l'adresse (pointeur) du 1er caractère de la variable str
    • prend comme 2ème paramètre un entier représentant la taille de la chaîne str
    • prend comme 3ème paramètre un type FILE (on connaît pas, chez nous ça sera toujours stdin (console))


    exemple d'utilisation:

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        char result[100]; /* déclaration variable contenant la valeur utilisateur, 99 caractères maxi + 1 caractère fin de chaîne '\0' fait 100 caractères */
        char *p; /* déclaration variable contenant valeur de retour pour fgets */
    
        printf("Entrer votre nom: ");
        p = fgets(result, 100, stdin); /* enregistrer valeur console dans result */
        if (p != NULL) /* Si ça s'est bien passé pour fgets */
        {
            printf("\nVotre nom est %s\n", result); /* Afficher résultat */
        }
    
        return 0;
    }
    Testez le code ci-dessus, et faîtes des remarques, des questions sur ce que vous voyez, ne comprenez pas, ...

    Après cela, j'aimerais entrer plusieurs chaînes de caractères, et les afficher ensuite...

    Ah... alors attention, on le fait, mais on le fait bien !

    Une chaîne de caractères est un tableau de caractères en C
    Un tableau de chaînes de caractères est donc un tableau de tableaux de caractères (pas de fautes d'orthographe, tableau avec un x, il y en a plusieurs)

    On va limiter le travail ! On veut entrer 3 chaînes de caractères avec 99 caractères maxi

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        int i;
        char result[3][100]; /* variable contenant 3 chaînes de 100 caractères ('\0' compris) */
        char *p; /* valeur de retour pour fgets */
    
        for (i=0; i<3; i++)
        {
            printf("Entrer le nom n°%d: ", i+1);
            p = fgets(result[i], 100, stdin); /* enregistrer valeur n°i console dans result */
    
            if (p == NULL) /* Si ça s'est mal passé pour fgets */
            {
                return -1; /* on sort du programme avec code -1 */
            }
        }
    
        for (i=0; i<3; i++)
        {
            printf("\nchaine n°1: %s", result[i]); /* affichage de chaine n°i */
        }
    
        return 0;
    }
    Testez le code ci-dessus, et faîtes des remarques, des questions sur ce que vous voyez, ne comprenez pas, ...

    EXERCICES

    Exercice n°1:

    Complétez le code ci-dessous

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int compteur(char *chaine);
    
    int main(void)
    {
        int i; /* déclaration index, nombre de demandes utilisateur */
        char *p; /* déclaration retour de fgets */
        char maChaine[100]; /* déclaration variable contenant valeur console par utilisateur */
    
        for (i=0; i<5; i++)
        {
            printf("\nEntrer la chaine pour compter son nombre de voyelles: ");
    
            /* à compléter, utilisation de fgets */
    
            if (p != NULL)
            {
    
                p = strchr(maChaine, '\n'); /* pas de préoccuper */
                if (p != NULL) /* pas se préoccuper */
                    *p = '\0'; /* pas se préoccuper */
    
                printf("\nma chaine %s contient %d voyelles\n", maChaine, compteur(maChaine)); /* affichage du résultat */
            }
        }
    
        return 0;
    }
    
    int compteur(char *chaine)
    {
        /* fonction permettant de compter les voyelles */
    
        int i; /* déclaration index pour lire caractère par caractère chaine */
        int j; /* déclaration index pour lire caractère par caractère voyelles */
    
        int resultat = 0; /* valeur contenant le nombre de voyelles dans valeur de la variable chaine */
        char voyelles[] = {'a', 'e', 'i', 'o', 'u', '\0'}; /* déclaration de toutes les voyelles dans tableau voyelles */
    
        for (i=0; chaine[i]!='\0'; i++) /* pour chaque caractère de la variable chaine */
        {
            for (j=0; voyelles[j]!='\0'; j++) /* pour chaque caractère du tableau voyelles */
            {
                /* compléter */
            }
        }
    
        return resultat;
    }
    L'objectif est de déterminer le nombre de voyelles dans une chaîne de caractères, exemple bonjour aura 3 voyelles, coucou en aura 4...

    Écrire la suite du code aux endroits indiqués par le commentaire /* à compléter */

    Exercice n°2:

    Compléter le code ci-dessous

    Code:
    #include <stdio.h>
    
    float moyenne(float *moyennes, int taille);
    
    int main(void)
    {
        int i; /* index nombre de demandes pour chaque matière */
        int retour; /* déclaration variable valeur de retour de scanf */
    
        float moy; /* déclaration variable contenant la moyenne de chaque matière */
        float mesMoyennes[4]; /* tableau contenant toutes les moyennes */
    
        const char matieres[][50] = {
                                      "Français",
                                      "Mathématiques",
                                      "Physiques",
                                      "Anglais"
                                    }; /* tableau des matières */
    
        for (i=0; i<4; i++)
        {
            printf("Entrer la moyenne pour la matière %s: ", matieres[i]);
    
            /* à compléter - utilisation de scanf, attention au type de formatage */
    
            if (retour == 1) /* si fonction scanf se passe bien */
            {
                /* à compléter - affecter valeurs dans tableau mesMoyennes */
            }
        }
    
        for (i=0; i<4; i++)
        {
            printf("Moyenne de %s: %.1f\n", matieres[i], mesMoyennes[i]); /* affichage de chaque moyenne */
        }
    
        printf("\nMa moyenne est de: %.2f\n", moyenne(mesMoyennes, 4)); /* affichage moyenne générale */
    
        return 0;
    }
    
    float moyenne(float *moyennes, int taille)
    {
        float somme = 0; /* déclaration variable contenant valeur somme du tableau moyennes */
        int i; /* index gérant taille tableau moyennes */
    
        for (i=0; i<taille; i++)
        {
            /* à compléter, calcul de somme du tableau moyennes */
        }
    
        return somme/taille; /* retourne la moyenne */
    }
    L'objectif est de déterminer la moyenne générale et l'afficher

    Compléter les endroits où il est indiqué le commentaire /* à compléter ... */

    Merci de m'avoir lu et à bientôt pour le prochain cours
    Dernière modification par fred, 09 juillet 2014, 10h10.

  • #2
    Bien le bonjour fred,

    Je viens juste de m'inscrire sur le forum et j'ai parcouru tes tutos cette soirée, et j'ai eu un problème pour ce cour. En effet quand j'utilise la fonction fgets() en seconde fois elle ne fonctionne pas.

    Code:
    int main(void)
    {
       int age;
       char prenom[100];
    
       printf("Bienvenue sur le site ultra securise de la NSA ! Quel age as-tu ?");
       scanf("%d", &age);
    
       if(age < 18) {
            printf("Desole mais tu es mineur");
       }
    
       else {
        printf("\nTu es majeur c'est bien, quel est ton prenom ?");
        fgets(prenom, 100, stdin);
    
        printf("\nBienvenue a toi %s ", prenom);
       }
    
        return 0;
    }
    Alors que si je l'utilise en première cela fonctionne.

    Code:
    int main(void)
    {
        int age;
        char prenom[100];
    
        printf("Bienvenue sur le site ultra securise de la NSA ! Quel est ton prenom ?");
        fgets(prenom, 100, stdin);
    
        printf("\nTu as un prenom c'est bien, quel est ton age ?");
        scanf("%d", &age);
    
        if(age < 18) {
            printf("Desole mais tu es mineur");
        }
    
        else {
    
            printf("\nBienvenue a toi %s ", prenom);
        }
    
        return 0;
    }
    Sinon j'ai parcouru vite fait la doc, et j'ai utilisé un scanf pour faire rentrer du texte, bonne ou mauvaise pratique ?

    Code:
    int main(void)
    {
       int age;
       char prenom[100];
    
       printf("Bienvenue sur le site ultra securise de la NSA ! Qui es-tu ?");
       scanf("%d", &age);
    
       if(age < 18) {
            printf("Desole mais tu es mineur");
       }
    
       else {
        printf("\nTu es majeur c'est bien, quel age as-tu ?");
        scanf("%99s", &prenom);
    
        printf("\nBienvenue a toi %s ", prenom);
       }
    
        return 0;
    }
    Sinon félicitation pour tes tutos, ils se mangent facilement !
    Dernière modification par new_unknow, 04 septembre 2014, 21h57.

    Commentaire


    • #3
      Bonjour,

      Alors petite remarque, j'ai testé ton code il me manquait l'inclusion des librairies. Évidemment je le savais, je devais juste le rajouter, hors, si je pouvais juste faire un copier coller et tester, ça me simplifierait la vie

      Passons au problème, qui est un problème de buffer, il faut vider le buffer où tu as écris, en l’occurrence stdin, pour cela on va utiliser une boucle détectant le caractère de fin de ligne et de fichier (EOF). On peut créer une fonction spécifique à cela

      Code:
      void vider()
      {
          char c = getchar();
          while (c != '\n' && c != EOF)
              c = getchar();
      }
      Mais dans ton cas c'est pas utile, on le rajoute dans le bloc conditionnel else.

      Code:
      #include <stdio.h>
      
      int main(void)
      {
          int age;
          char prenom[100];
          char c; /* déclaration à ajouter pour vider le buffer */
      
          printf("Bienvenue sur le site ultra securise de la NSA ! Quel age as-tu ?");
          scanf("%d", &age);
      
          if(age < 18)
          {
              printf("Desole mais tu es mineur");
          }
      
      
      
          else
          {
              c = getchar();
              while (c != '\n' && c != EOF) /* boucle vidant le buffer jusqu'à rencontrer le caractère de fin de ligne et de fichier*/
                  c = getchar();
              printf("\nTu es majeur c'est bien, quel est ton prenom ?");
              fgets(prenom, 100, stdin);
      
              printf("\nBienvenue a toi %s ", prenom);
          }
      
          return 0;
      }
      Sinon j'ai parcouru vite fait la doc, et j'ai utilisé un scanf pour faire rentrer du texte, bonne ou mauvaise pratique ?
      Tout dépend, tu as essayé avec des prénoms composés ? Tu verras pourquoi ne pas l'utiliser.

      Maintenant on peut, mais l'utilisation de cette fonction pour faire l'équivalent de fgets, est syntaxiquement plus complexe.

      Donc je dirais au final, mauvaise pratique...
      Dernière modification par fred, 05 septembre 2014, 08h34.

      Commentaire


      • #4
        Très bien merci, je ne savais pas qu'il fallait vider le buffer à chaque fois.

        Commentaire


        • #5
          Salut,

          Code:
          #include <stdio.h>
          #include <string.h>
          
          int compteur(char *chaine);
          
          int main(void)
          {
              int i;
              char *p;
              char maChaine[100];
          
              for (i=0; i<5; i++)
              {
                  printf("\nEntrer la chaine pour compter son nombre de voyelles: ");
          
                  p = fgets(maChaine,100,stdin);
          
                  if (p != NULL)
                  {
          
                      p = strchr(maChaine, '\n');
          
                      if (p != NULL)
                      {
                          *p = '\0';
                      }
          
                      printf("\nma chaine %s contient %d voyelles\n", maChaine, compteur(maChaine));
                  }
              }
          
              return 0;
          }
          
          int compteur(char *chaine)
          {
          
              int i;
              int j;
          
              int resultat = 0;
              char voyelles[] = {'a', 'e', 'i', 'o', 'u', '\0'};
          
              for (i=0; chaine[i]!='\0'; i++)
              {
                  for (j=0; voyelles[j]!='\0'; j++)
                  {
                      if (chaine[i] == voyelles[j])
                      {
                          resultat++;
                      }
                  }
              }
          
              return resultat;
          }
          Code:
          #include <stdio.h>
          
          float moyenne(float *moyennes, int taille);
          
          int main(void)
          {
              int i; 
              int retour; 
          
              float moy; 
              float mesMoyennes[4]; 
              const char matieres[][50] = {
                                            "Français",
                                            "Mathématiques",
                                            "Physiques",
                                            "Anglais"
                                          };
          
              for (i=0; i<4; i++)
              {
                  printf("Entrer la moyenne pour la matière %s: ", matieres[i]);
          
                  retour = scanf("%f", &moy);
          
                  if (retour == 1) 
                  {
                      mesMoyennes[i] = moy;
                  }
              }
          
              for (i=0; i<4; i++)
              {
                  printf("Moyenne de %s: %.1f\n", matieres[i], mesMoyennes[i]);
              }
          
              printf("\nMa moyenne est de: %.2f\n", moyenne(mesMoyennes, 4)); 
          
              return 0;
          }
          
          float moyenne(float *moyennes, int taille)
          {
              float somme = 0; 
              int i; 
          
              for (i=0; i<taille; i++)
              {
                  somme = somme + moyennes[i];
              }
          
              return somme/taille; 
          }


          Juste une petite question fred, tu pourrais expliquer plus en détail la chaine : "chaine[3][100]" ?

          C'est un tableau a deux dimensions ?

          chaine[0][0-99]..chaine[1][0-99]..chaine[2][0-99] ?

          EDIT : J'ai corrigé le code
          Dernière modification par shirocen, 16 janvier 2015, 00h14.
          deux et deux font cinq

          Commentaire


          • #6
            Dans l'exercice 1, on demande à utiliser fgets et non scanf.

            Juste une petite question fred, tu pourrais expliquer plus en détail la chaine : "chaine[3][100]" ?
            C'est un tableau de chaînes de caractères, en l'occurrence ici 3 chaînes

            Commentaire


            • #7
              Donc on aura 3 chaines de 100 char maximum ?

              chaine[0][0] pour accéder au premier, chaine[1][0] pour accéder au second..?

              EDIT : chaine[0] suffit pour accéder à la première chaine de caractère, cependant

              si je voulais accéder au troisième caractère de la première chaine, comment dois-je m'y prendre ?
              Dernière modification par shirocen, 16 janvier 2015, 00h26.
              deux et deux font cinq

              Commentaire


              • #8
                Donc on aura 3 chaines de 100 char maximum ?
                Oui, et dans les 100 on comprend le caractère '\0'

                chaine[0][0]
                1er caractère de la 1ère chaîne

                si je voulais accéder au troisième caractère de la première chaine, comment dois-je m'y prendre ?
                Maintenant tu devrais le savoir

                Commentaire


                • #9
                  En effet, chaine[0][2] !

                  Encore merci Fred' !
                  deux et deux font cinq

                  Commentaire


                  • #10
                    Exercice n°1:

                    Code:
                    #include <stdio.h>
                    #include <string.h>
                    
                    int compteur(char *chaine);
                    
                    int main(void)
                    {
                        int i; /* déclaration index, nombre de demandes utilisateur */
                        char *p; /* déclaration retour de fgets */
                        char maChaine[100]; /* déclaration variable contenant valeur console par utilisateur */
                    
                        for (i=0; i<5; i++)
                        {
                            printf("\nEntrer la chaine pour compter son nombre de voyelles: ");
                    
                            /* à compléter, utilisation de fgets */
                            fgets(maChaine, 100, stdin);
                            if (p != NULL)
                            {
                    
                                p = strchr(maChaine, '\n'); /* pas de préoccuper */
                                if (p != NULL) /* pas se préoccuper */
                                    *p = '\0'; /* pas se préoccuper */
                    
                                printf("\nma chaine %s contient %d voyelles\n", maChaine, compteur(maChaine)); /* affichage du résultat */
                            }
                        }
                    
                        return 0;
                    }
                    
                    int compteur(char *chaine)
                    {
                        /* fonction permettant de compter les voyelles */
                    
                        int i; /* déclaration index pour lire caractère par caractère chaine */
                        int j; /* déclaration index pour lire caractère par caractère voyelles */
                    
                        int resultat = 0; /* valeur contenant le nombre de voyelles dans valeur de la variable chaine */
                        char voyelles[] = {'a', 'e', 'i', 'o', 'u', '\0'}; /* déclaration de toutes les voyelles dans tableau voyelles */
                    
                        for (i=0; chaine[i]!='\0'; i++) /* pour chaque caractère de la variable chaine */
                        {
                            for (j=0; voyelles[j]!='\0'; j++) /* pour chaque caractère du tableau voyelles */
                            {
                                if (chaine[i] == voyelles[j])
                                    resultat++;
                            }
                        }
                    
                        return resultat;
                    }
                    Exercice n°2:
                    Code:
                    #include <stdio.h>
                    
                    float moyenne(float *moyennes, int taille);
                    
                    int main(void)
                    {
                        int i; /* index nombre de demandes pour chaque matière */
                        int retour; /* déclaration variable valeur de retour de scanf */
                    
                        float moy; /* déclaration variable contenant la moyenne de chaque matière */
                        float mesMoyennes[4]; /* tableau contenant toutes les moyennes */
                    
                        const char matieres[][50] = {
                                                      "Français",
                                                      "Mathématiques",
                                                      "Physiques",
                                                      "Anglais"
                                                    }; /* tableau des matières */
                    
                        for (i=0; i<4; i++)
                        {
                            printf("Entrer la moyenne pour la matière %s: ", matieres[i]);
                            retour = scanf("%f", &moy);
                    
                            if (retour == 1) /* si fonction scanf se passe bien */
                            {
                                mesMoyennes[i] = moy;
                            }
                        }
                    
                        for (i=0; i<4; i++)
                        {
                            printf("Moyenne de %s: %.1f\n", matieres[i], mesMoyennes[i]); /* affichage de chaque moyenne */
                        }
                    
                        printf("\nMa moyenne est de: %.2f\n", moyenne(mesMoyennes, 4)); /* affichage moyenne générale */
                    
                        return 0;
                    }
                    
                    float moyenne(float *moyennes, int taille)
                    {
                        float somme = 0; /* déclaration variable contenant valeur somme du tableau moyennes */
                        int i; /* index gérant taille tableau moyennes */
                    
                        for (i=0; i<taille; i++)
                        {
                            somme += moyennes[i];
                            /* à compléter, calcul de somme du tableau moyennes */
                        }
                    
                        return somme/taille; /* retourne la moyenne */
                    }
                    Mon blog : http://rootsheep.info

                    Commentaire


                    • #11
                      @Sadik,

                      Tu n'as pas lu correctement le cours, fgets renvoie un pointeur sur char, il y a un exemple d'utilisation dans ce même cours, c'est pour cela qu'on le contrôle via

                      Code:
                      if (p != NULL){...}
                      Je ne regarde pour l'instant pas l'exercice n°2

                      Commentaire


                      • #12
                        Ah oui effectivement ! C'est plutôt

                        Code:
                        p = fgets(maChaine, 100, stdin);
                        ?

                        Merci !
                        Mon blog : http://rootsheep.info

                        Commentaire


                        • #13
                          Tout est bon maintenant, y compris l'exercice 2.

                          Commentaire

                          Chargement...
                          X