Partage
  • Partager sur Facebook
  • Partager sur Twitter

[FAIT][Défis] #1 : zMol, la chimie pour tous

Venez vous entraîner !

    15 janvier 2012 à 16:38:56

    Salut ! :)

    Pas sur que ça vienne de là, mais je suis pas sur qu'appeler 'Element' ta variable de type 'Element' fonctionne (où alors c'est pas très judicieux).

    Pour ton "La table est composée de 0 éléments", c'est parce que tu as un return 0 qui traine dans ta fonction get_Tab : à enlever donc.

    Sinon, ton fichier correspond bien au format que tu attends dans fscanf ?

    Et aussi, tu peux colorer ton code en le mettant entre les balises de code :

    <code type="c"> /* Ton code ici */ </code>
    

    ;)
    • Partager sur Facebook
    • Partager sur Twitter
    Bla bla bla
      16 janvier 2012 à 20:01:46

      Merci Fender.
      J'ai supprimé le return 0 (tellement gros que je ne voyais rien).

      J'ai trouvé pourquoi mon tableau ne se remplissait pas bien, j'avais fais un while(fgetc(pfichier) != EOF) au lieu d'un do while. J'avais déjà fais cette erreur dans le TP du pendu!!! Maintenant ça fonctionne bien.

      J'ai donc fini mon niveau 1, temps passé 1 journée après un premier programme fonctionnel mais catastrophique à lire et à modifier.

      Voici le code:

      /*********************************************************************
      *                                                                    *
      *   Ce programme permet le calcul des masses molaires moléculaires   *
      *                                                                    *
      **********************************************************************/
      
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <ctype.h>
      #include "fonction.h"
      
      
      int main(int argc, char *argv[])
      {
          char molecule[100] = "";
          char c_molecule[100] = {0};
          char atome[3] = {0};
      
          int nbElement = 0;
          int len = 0;
          int i = 0;
      
          double masseAtome = 0;
          double masseMolaire = 0;
      
          Element ElementTab[112]; // creation d'un tableau d'elements de 112 elements
      
      
      
          /************************************************************
          *                                                           *
          * Recuperation de la molecule saisie par l'utilisateur      *
          *                                                           *
          ************************************************************/
      
          printf("entrez une molecule:\n\n");
          printf("--> ");
          scanf("%s", molecule);
          printf("\n\n");
          //printf("la molecule choisie vaut: %s\n\n", molecule);
      
          nbElement = get_Tab(ElementTab);
          //printf("la table est composee de %d elements\n\n", nbElement);
      
      
          /************************************************************
          *                                                           *
          * Structure de la molecule                                  *
          *                                                           *
          ************************************************************/
      
          len = strlen(molecule);
      
          strcpy(c_molecule, molecule);
      
          while(i < len){
              if(isupper(c_molecule[i]) && islower(c_molecule[i+1])){ // Si l'atome a deux caracteres
                  atome[0] = c_molecule[i];
                  atome[1] = c_molecule[i+1];
                  //printf("atome vaut %s\n\n", atome);
      
                  masseAtome = validAtome(atome, ElementTab, nbElement);
                  masseMolaire = masseMolaire + masseAtome;
                  i += 2;
              }
              else{ // si l'atome a qu'un seul caractere
                  atome[0] = c_molecule[i];
                  //printf("atome vaut %s\n\n", atome);
      
                  masseAtome = validAtome(atome, ElementTab, nbElement);
                  masseMolaire = masseMolaire + masseAtome;
                  i++;
              }
      
          }
      
          if(masseAtome == -1){
              printf("Impossible de calculer la masse molaire moleculaire\n\n");
          }
          else{
              printf("---> La masse molaire moleculaire de %s est %f g.mol-1.\n\n", molecule, masseMolaire);
          }
      
          return 0;
      }
      
      
          /*******************************************************************
          *                                                                  *
          * Recuperation des donnees du fichier fileElement dans un tableau  *
          * La fonction retourne le nombre d'element: nbElementTab           *
          *                                                                  *
          *******************************************************************/
          int get_Tab(Element *pElementTab) //int get_Tab(Element ElementTab[])
          {
              int nbElementTab = 0;
      
              FILE *pfichier = fopen("fileElement.txt", "r");
      
              if(pfichier != NULL){
                  //printf("ouverture reussi\n\n");
                  do{
                      fscanf(pfichier, "%s %lf", pElementTab[nbElementTab].nom_Atome, &pElementTab[nbElementTab].masse_Atome);
                      nbElementTab++;
                  }
                  while(fgetc(pfichier) != EOF);
                  rewind(pfichier);
                  fclose(pfichier);
                  //printf("Premier element %s a une masse de %f\n\n", pElementTab[0].nom_Atome, pElementTab[0].masse_Atome);
              }
              else{
                  printf("Fichier fileElement.txt introuvable\n\n");
                  return 0;
              }
      
              return nbElementTab;
          }
      
      
          /*******************************************************************
          *                                                                  *
          * Verification de l'existance des atomes dans TabElement           *
          * Elle renvoie la masse de l'atome s'il est présent                *
          *                                                                  *
          *******************************************************************/
          double validAtome(char *patome, Element *pElementTab, int nb)
          {
              double atomeTab = 0;
              int i = 0;
      
              while(strcmp(patome, pElementTab[i].nom_Atome) != 0 && i < nb){
                  i++;
              }
      
              if(strcmp(patome, pElementTab[i].nom_Atome) == 0){
                  atomeTab = pElementTab[i].masse_Atome;
              }
              else{
                  printf("L'atome %s n'est pas dans la table d'elements entree\n\n", patome);
                  atomeTab = -1;
              }
      
              return atomeTab;
          }
      


      <code type="h" titre="TabElement.h> #ifndef TABELEMENT_H_INCLUDED
      #define TABELEMENT_H_INCLUDED

      typedef struct Element Element;
      struct Element
      {
      char nom_Atome[3];
      double masse_Atome;
      };

      #endif // TABELEMENT_H_INCLUDED
      </code>


      #ifndef FONCTION_H_INCLUDED
      #define FONCTION_H_INCLUDED
      
      #include "TabElement.h"
      
      int get_Tab(Element *pElementTab); //int get_Tab(Element ElementTab[]);
      double validAtome(char *patome, Element *pElementTab, int nb);
      
      #endif // FONCTION_H_INCLUDED


      J'attends vos commentaires!

      Bon courage à tous les débutants comme moi qui galère pour faire leur défit!!!
      • Partager sur Facebook
      • Partager sur Twitter

      Celui qui aime à apprendre est bien près du savoir " Confucius

      Anonyme
        21 janvier 2012 à 15:01:28

        Ma participation pour le niveau 4 (je ne vois pas vraiment l'intérêt du niveau 5).

        /* zmol.c - C99 */
        
        #include <ctype.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        
        /* Nom du fichier de configuration. Il contient en theorie, sur chaque   *
         * nouvelle ligne, une chaine de la forme :                              *
         * symbole masse                                                         *
         * Le nombre de lignes doit etre specifie par la constante NB_ATOMS      */
        #define FILE_NAME       "mol.txt"  
        
        /* Nombre d'atomes existants. Le nombre d'atomes du fichier de           *
         * configuration ne doit pas etre superieur a cette constante. Sinon, les*
         * derniers atomes du fichier seront consideres comme inconnus. La       *
         * classification contient actuellement 118 atomes, donc merci de ne pas *
         * inventer d'atomes...                                                  */
        #define NB_ATOMS        118
        
        /* Taille maximale d'un atome. Dans notre cas, les symboles des atomes   *
         * ne depasseront pas trois caracteres (plus le '\0' final)              */
        #define ATOM_MAX_LEN    4
        
        
        /* Classification periodique des elements, qui indique pour chaque atome *
         * son symbole et sa masse. Il est preferable que le nombre d'atomes du  *
         * fichier soit egal a la constante symbolique NB_ATOMS.                 */
        static struct Atom {
          char name[ATOM_MAX_LEN];
          double mass;
        } ptable[NB_ATOMS];
        
        
        /* Enumeration de constantes representant les differentes erreurs pouvant*
         * se produire lors de l'execution du programme                          */
        enum error_e {
          ERROR_BRACKETS,
          ERROR_UNKNATOM,
          ERROR_LONGATOM,
          ERROR_UNKNSYMB,
          ERROR_MEMALLOC,
          ERROR_CLOSEFIL,
          ERROR_OPENFILE
        };
        
        
        /* Nombre d'atomes effectivement lus dans le fichier de configuration.   *
         * Doit etre inferieur a la constante NB_ATOMS                           */
        static size_t ptable_size;
        
        
        /* Charge la classification periodique des elements dans la structure    *
         * d'atomes ptable. Retourne le nombre d'elements contenus dans le       *
         * fichier.                                                              */           
        static size_t load_ptable(const char *filename);
        
        /* Retourne la masse moleculaire de l'atome courant de la molecule passee*
         * sous forme de chaine de caractere en parametre.                       */
        static double get_atommass(char **molecule);
        
        /* Retourne la masse moleculaire de la molecule passee sous forme de     *
         * chaine de caractere en parametre.                                     */
        static double get_molmass(char **molecule);
        
        /* Recupere la molecule entree par l'utilisateur. Retourne le nombre     *
         * d'octets effectivement lus.                                           */
        static size_t get_molecule(char **molecule);
        
        /* Teste le parenthesage de la chaine de caractere representant la       *
         * molecule passee en parametre. Renvoie 1 si l'expression est           * 
         * correctement parenthesee, ou 0 sinon.                                 */
        static int test_bracks(const char *molecule);
        
        /* Affiche la description de l'erreur, correspondant a une serie         *
         * d'enumeration de type enum error_e.                                   */
        static void print_error(enum error_e error);
        
        
        int main(void) {
          int ret = EXIT_FAILURE;
        
          ptable_size = load_ptable(FILE_NAME);
          
          if (ptable_size) {
            size_t ret_alloc;
            char *molecule = NULL;
        
            do {
              ret_alloc = get_molecule(&molecule);
        
              if (ret_alloc) {  
                char *p = molecule;
        
                if (!test_bracks(molecule))
                  print_error(ERROR_BRACKETS);
                else
                  printf("%f g/mol\n", get_molmass(&p));
        
                free(molecule);
                molecule = NULL;   
              }
            } while (ret_alloc != 0);
          }
        
          return ret;
        }
        
        static double get_atommass(char **molecule) {
          size_t n = 1;
          const char *p = *molecule;
        
          while (islower(*++*molecule))
            ++n;
        
          if (n < ATOM_MAX_LEN) {
            size_t i = 0;
            char atom[ATOM_MAX_LEN] = "";
        
            strncpy(atom, p, n);
        
            for (i = 0; i < ptable_size; i++)
              if (!strncmp(atom, ptable[i].name, n))
                return ptable[i].mass;
           
            print_error(ERROR_UNKNATOM);
          } 
          else
            print_error(ERROR_LONGATOM);
        
          return 0;
        }
        
        static double get_molmass(char **molecule) {
          double ret = 0.0;
          double tmp = 0.0;
          
          while (**molecule) {
            if (isupper(**molecule))
              ret += tmp = get_atommass(molecule);
            else if (isdigit(**molecule))
              ret += tmp *= strtol(*molecule, molecule, 10) - 1;
            else if (**molecule == '(') {
              ++*molecule;
              tmp = get_molmass(molecule);
              ret += tmp;
            } 
            else if (**molecule == ')') {
              ++*molecule;
              break;
            } 
            else {
              if (!isspace(**molecule))
                print_error(ERROR_UNKNSYMB);
              ++*molecule;
            }
          }
        
          return ret;
        }
        
        static size_t get_molecule(char **molecule) {
          size_t i = 0;
          size_t n = 0;
          int c;
        
          fprintf(stdout, "> ");
        
          do {
            c = getchar();
        
            if (i + 1 >= n) {
              char *p = NULL;
              n += 512;
              p = realloc(*molecule, n);
        
              if (!p) {
                print_error(ERROR_MEMALLOC);
                free(molecule);
                return i;
              }
        
              *molecule = p;
            }
        
            (*molecule)[i++] = (char)c;
          } while (c != '\n' && c != EOF);
        
          (*molecule)[i - 1] = '\0';
        
          return i;
        }
        
        static size_t load_ptable(const char *filename) {
          size_t i = 0;
          FILE *f;
        
          if ((f = fopen(filename, "r"))) {
            while (fscanf(f, "%s %lf", ptable[i].name, &ptable[i].mass) == 2 &&
                   i < NB_ATOMS) {
              ++i;
            }
        
            if (fclose(f) == EOF)
              print_error(ERROR_CLOSEFIL);
          } 
          else
            print_error(ERROR_OPENFILE);
        
          return i;
        }
        
        static int test_bracks(const char *molecule) {
          int b = 0;
        
          for (; *molecule; ++molecule) {
            if (*molecule == '(')
              ++b;
            else if (*molecule == ')') {
              if (--b < 0)
                return 0;
            }
          }
          return !b;
        }
        
        static void print_error(enum error_e error) {
          fprintf(stderr, "Erreur - ");
        
          switch (error) {
          case ERROR_BRACKETS:
            fprintf(stderr, "expression mal parenthésée.");
            break;
          case ERROR_UNKNATOM:
            fprintf(stderr, "atome inconnu");
            break;
          case ERROR_LONGATOM:
            fprintf(stderr, "atome trop long");
            break;
          case ERROR_UNKNSYMB:
            fprintf(stderr, "symbole inconnu");
            break;
          case ERROR_MEMALLOC:
            fprintf(stderr, "allocation mémoire");
            break;
          case ERROR_CLOSEFIL:
            fprintf(stderr, "fermeture fichier");
            break;
          case ERROR_OPENFILE:
            fprintf(stderr, "ouverture fichier");
            break;
          default:
            fprintf(stderr, "Inconnu");
            break;
          }
        
          putchar('\n');
        }
        


        Je suis ouvert à vos commentaires.

        Edit 1 : petite correction au niveau de la fonction get_molmass.
        Edit 2 : suppression des fprintf(stdout, /* ... */); pour des printf, car cela peut surprendre plus qu'autre chose dans ce cas précis.
        • Partager sur Facebook
        • Partager sur Twitter

        [FAIT][Défis] #1 : zMol, la chimie pour tous

        × 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.
        • Editeur
        • Markdown