Partage
  • Partager sur Facebook
  • Partager sur Twitter

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

Venez vous entraîner !

    5 septembre 2011 à 18:12:42

    Citation : _Fender_

    A ce sujet, j'ai beaucoup hésité entre la solution de yoch, une lecture du fichier préalable pour voir le nombre d'atomes, et une réallocation de mémoire à chaque tour de boucle/lecture dans le fichier.

    Selon vous, quelle est la méthode préférable au niveau de la lisibilité / logique / vitesse d'exécution ?


    Hum, difficile de trancher. Un realloc() est en fait l'utilisation la plus "naturelle" pour faire l'équivalent des vectors en C++. Sauf que:
    • Si tu fais un realloc par élément, c'est n'importe quoi d'un point de vue algo.
    • Sinon, pour simuler correctement le comportement d'un vector (progression géométrique), ça introduit un peu de complexité en plus dans le code.

    Pour éviter de trop me prendre la tête, j'ai opté pour la solution liste chainée vers tableau, mais ce n'est pas forcément le mieux.

    Sinon, lire un fichier deux fois, je considère ça presque comme un crime. :-° Blocage psychologique, sans doute...
    • Partager sur Facebook
    • Partager sur Twitter
      5 septembre 2011 à 18:22:04

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <ctype.h>
      #include <stdarg.h>
      
      #define FILENAME "atoms"
      
      struct Atom
      {
          char atom_str[16];
          float mass;
      };
      
      struct Atom *atom_list;
      size_t nb_atoms;
      
      void die(const char *format, ...)
      {
          va_list vargs;
      
          va_start(vargs, format);
          fprintf(stderr, "zMol: ");
          vfprintf(stderr, format, vargs);
          fprintf(stderr, ".\n");
      
          exit(EXIT_FAILURE);
      }
      
      size_t nb_lines(FILE *file)
      {
          char buff[32];
          size_t cpt = 0;
      
          while(fgets(buff, sizeof(buff), file))
              cpt++;
      
          rewind(file);
      
          return cpt;
      }
      
      void mklist(void)
      {
          size_t i = 0;
          FILE *file;
          char buff[32];
      
          if(!(file = fopen(FILENAME, "r")))
              die("couldn't open %s for reading. Make sure it's next to the program", FILENAME);
      
          nb_atoms = nb_lines(file);
          
          if(!(atom_list = malloc(nb_atoms * sizeof(struct Atom))))
          	die("couldn't allocate %d bytes", nb_atoms * sizeof(struct Atom));
      
          for(; i < nb_atoms; i++)
          {
              fgets(buff, sizeof(buff), file);
              sscanf(buff, "%s %f", atom_list[i].atom_str, &atom_list[i].mass);
          }
      
          fclose(file);
      }
      
      float mass_from_atom(char *str)
      {
          size_t i = 0;
      
          for(; i < nb_atoms; i++)
              if(!strcmp(str, atom_list[i].atom_str))
                  return atom_list[i].mass;
      
          die("couldn't find atom %s in file %s", str, FILENAME);
      
          return 0.;
      }
      
      float eval(char *str)
      {
          size_t i = 0;
          size_t sz = strlen(str);
          float retmass = 0., tmpmass = 0.;
      
          for(; i < sz; i++)
          {
              /* When an uppercase is encountered, it's time to add the currently stored mass to the returned one. */
              if(isupper(str[i]))
              {
                  size_t k = 0;
                  char at[4] = {0};
      
                  retmass += tmpmass;
      
                  at[k++] = str[i++];
      
                  while(islower(str[i]))
                      at[k++] = str[i++];
      
                  --i;
                  tmpmass = mass_from_atom(at); /* tmpmass now contains the mass of the newly found atom */
              }
      
              /* If it's a digit, then convert the coefficient into an integer and multiply the currently stored mass by it */
              else if(isdigit(str[i]))
              {
                  size_t num, k = 0;
                  char coeff[8] = {0};
      
                  while(isdigit((num = str[i])))
                      coeff[k++] = str[i++];
      
                  --i;
                  tmpmass *= strtol(coeff, NULL, 10);
              }
      
              /* If it's a parenthesis, recursively call eval in order to evaluate the formula that't inside */
              else if(str[i] == '(')
              {
                  char *end, *strtmp;
      
                  retmass += tmpmass;
      
                  if(!(end = strrchr(str, ')')))
                      die("parenthesis not closed");
      
                  tmpmass = eval((strtmp = strndup(str + i + 1, (size_t)(end - (str + i + 1)))));
                  i += strlen(strtmp);
                  free(strtmp);
              }
          }
      
          return retmass + tmpmass;
      }
      
      int main(void)
      {
          char input_molecule[128];
          char *ptr;
      
          mklist();
      
          printf(">> "); /* Eye candy stuff */
      
          while(fgets(input_molecule, sizeof(input_molecule), stdin))
          {
              if((ptr = strchr(input_molecule, '\n')))
                  *ptr = 0;
      
              if(!strcmp(input_molecule, "q"))
                  break;
      
              printf("Molar mass of %s is %f g.mol⁻¹.\n\n>> ", input_molecule, eval(input_molecule));
          }
      
          free(atom_list);
          return EXIT_SUCCESS;
      }
      


      Ma solution, pour le 4 (le 5 n'est pas vraiment intéressant selon moi).
      Ça consiste en une fonction eval qui évalue la chaîne qu'on lui passe en paramètres. Ça permet de calculer élégamment le contenu des parenthèses.
      J'espère pas m'être planté, et tout commentaire est apprécié :)

      Et sinon, ce serait sympa qu'on nous fournisse une batterie de tests (en l'occurrence une flopée de molécules) à faire exécuter par le programme pour savoir s'il marche. C'est pas toujours évident de calculer de tête, avec des molécules de 50 caractères de long et 5 parenthèses imbriquées.

      EDIT : corrigé une erreur minime.
      • Partager sur Facebook
      • Partager sur Twitter
        5 septembre 2011 à 18:45:32

        Citation

        Et sinon, ce serait sympa qu'on nous fournisse une batterie de tests (en l'occurrence une flopée de molécules) à faire exécuter par le programme pour savoir s'il marche. C'est pas toujours évident de calculer de tête, avec des molécules de 50 caractères de long et 5 parenthèses imbriquées.



        +1... ;)
        • Partager sur Facebook
        • Partager sur Twitter
        Staff désormais retraité.
          5 septembre 2011 à 19:31:40

          Merci pour la suggestion, c'est une bonne idée.

          J'ai ajouté un tableau de molécules avec quelques informations complémentaires, pour la culture. ;)

          N'hésitez pas à me signaler toute erreur.
          • Partager sur Facebook
          • Partager sur Twitter
          Bla bla bla
            5 septembre 2011 à 19:35:43

            Le sujet est résolu ? :o

            Il est déjà finit ?


            Edit : Ah ba oui, ça fait une semaine. >_<
            Je vais quand même poster un truc dans les deux jours, si je peux.
            • Partager sur Facebook
            • Partager sur Twitter
              5 septembre 2011 à 19:38:41

              Citation : paraze


              Edit : Ah ba oui, ça fait une semaine. >_<



              Non, ça fait que trois jours. ^^

              Je pense que c'était une fausse manip' de ma part (en mettant en vert la réponse de Kyron). C'est corrigé. ;)
              • Partager sur Facebook
              • Partager sur Twitter
              Bla bla bla
                5 septembre 2011 à 19:40:32

                On est pas le 5 ?

                A si... waw, 5 - 2 = 3... j'ai perdu la notion du temps pendant ces vacances (c'est fini demain :'(:'(:'( ).
                • Partager sur Facebook
                • Partager sur Twitter
                  5 septembre 2011 à 20:43:46

                  Kyron > T'as un problème ligne 97, si ta variable a plusieurs caractères minuscules. Pareil ligne 110. :)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 septembre 2011 à 9:06:12

                    Bon, j'édite le tableau, j'ai dépassé le niveau 3 depuis deux jours. ^^
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Staff désormais retraité.
                    Anonyme
                      6 septembre 2011 à 13:28:16

                      J'aimerais poser une question à ceux qui ont réussi : avez-vous eu du mal, et en combien de temps l'avez vous fait ?

                      Parce que moi là, je galère un peu, et je me demande même si je suis capable de faire cet exo...
                      • Partager sur Facebook
                      • Partager sur Twitter
                        6 septembre 2011 à 14:02:08

                        Citation : informaticienzero

                        J'aimerais poser une question à ceux qui ont réussi : avez-vous eu du mal, et en combien de temps l'avez vous fait ?


                        Du mal, non. Mais je m'appuie sur mon expérience: la première fois que j'ai codé un parseur mathématique, là oui, j'en ai eu du mal. D'ailleurs, cet exo est tout de même plus "doux".

                        Citation : informaticienzero

                        Parce que moi là, je galère un peu, et je me demande même si je suis capable de faire cet exo...


                        C'est le signe que tu es en progression : accroche toi, et tu va réussir. ;)

                        Commence par le premier niveau, ensuite le deuxième, etc.
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Anonyme
                          6 septembre 2011 à 14:07:45

                          Merci yoch, ça me rassure. :)

                          Je vais continuer alors.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            6 septembre 2011 à 17:55:52

                            Citation : informaticienzero

                            J'aimerais poser une question à ceux qui ont réussi : avez-vous eu du mal, et en combien de temps l'avez vous fait ?

                            Parce que moi là, je galère un peu, et je me demande même si je suis capable de faire cet exo...



                            Environ 1h30 une première fois (il y a plusieurs semaines) plus à peu près 1h avant-hier pour corriger mon code (le temps de me relire pour comprendre ce que j'avais fait inclus). Mais je pense pas que mon code soit vraiment de qualité, je manque de recul, de retours et d'exprérience. ;)

                            Je n'ai pas un meilleur niveau que toi donc tu devrais y arriver ya pas de raison. ;)
                            • Partager sur Facebook
                            • Partager sur Twitter
                            Bla bla bla
                              6 septembre 2011 à 18:02:23

                              Citation : Pouet_forever

                              Kyron > T'as un problème ligne 97, si ta variable a plusieurs caractères minuscules. Pareil ligne 110. :)


                              Pas le temps de corriger dans l'immédiat, je verrai ça dans les jours à venir.

                              Citation : informaticienzero

                              J'aimerais poser une question à ceux qui ont réussi : avez-vous eu du mal, et en combien de temps l'avez vous fait ?


                              Alors ouais j'ai eu un peu de mal, et il m'a fallu environ 2 heures. C'était la première fois que je codais un truc comme ça aussi.
                              • Partager sur Facebook
                              • Partager sur Twitter
                              Anonyme
                                6 septembre 2011 à 18:55:56

                                Ça y est, j'y suis arrivé, j'ai fait le niveau 1. Malheureusement ... c'est nul. Je n'ai pas votre logique, pas votre expérience, et je dois avouer que j'ai du copier... :euh:

                                Ceci dit, voici quand même ce que j'ai fait (reste à le convertir en TI-Basic et je suis tranquille en physique ^^ (je plaisante)).

                                main.c

                                #include "constante.h"
                                #include "masse.h"
                                
                                /* main presque inutile */
                                
                                int main(void)
                                {
                                    Masse * c;
                                    double resultat = 0.0;
                                    char mol[PATH_MAX] = {'\0'};
                                    Masse masse[200];
                                
                                    c = Constructeur();
                                
                                    printf("Donnez la molecule :\n");
                                    printf(": ");
                                    scanf("%s", mol);
                                    printf("\n");
                                
                                    Open(masse, "masse.txt");
                                    resultat = calcul(masse, mol);
                                
                                    printf("\nVoici la masse molaire de %s : %lf g/mol\n\n", mol, resultat);
                                
                                    return 0;
                                }
                                


                                constante.h

                                #ifndef CONSTANTE_H_050920112211_BV
                                #define CONSTANTE_H_050920112211_BV
                                
                                #include <stdio.h>
                                #include <stdlib.h>
                                #include <string.h>
                                #include <limits.h>
                                #include <ctype.h>
                                
                                #endif
                                


                                masse.c

                                #include "masse.h"
                                #include "test.h"
                                
                                #define NB_MOL 7
                                
                                /* le "constructeur", qui s'occupe d'initialiser les membres de la structure */
                                
                                Masse * Constructeur(void)
                                {
                                    Masse * masse = my_malloc(sizeof(*masse), __FILE__,  __LINE__);
                                
                                    masse->nombre = 0;
                                    masse->name[PATH_MAX] = "";
                                
                                    return masse;
                                }
                                
                                /* il faut que je sépare l'ouverture du calcul */
                                
                                void Open(Masse * masse, char * fichier)
                                {
                                    FILE * file = NULL;
                                    int i = 0;
                                
                                    file = my_fopen(fichier, "r", __FILE__, __LINE__);
                                
                                    fflush(stdout);
                                
                                    while (!feof(file))
                                    {
                                        fscanf(file, "%s %lf\n", masse[i].name, &masse[i].nombre);
                                        i++;
                                    }
                                
                                    fclose(file);
                                }
                                
                                /* recherche d'un élément dans une chaine donnée */
                                
                                int recherche(char * str, Masse * masse, int nombre)
                                {
                                    int i = 0;
                                
                                    for (; i < nombre; i++)
                                    {
                                        if(strcmp(masse[i].name, str) == 0)
                                        {
                                            return i;
                                        }
                                    }
                                
                                    printf("Molecule %s inconnue !\n", str);
                                        exit(EXIT_FAILURE);
                                
                                    return -1;
                                }
                                
                                double calcul(Masse * masse, const char * mol)
                                {
                                    char tab[3] = {'\0'};
                                    int i = 0; /* i pour l'itération */
                                    int r = 0; /* r pour la recherche */
                                    double resultat = 0.0; /* résulat intermédiaire */
                                    long a = 0;
                                    int nb_coeff = 1;
                                
                                   do // while (i < strlen(mol))
                                    {
                                        a = 1;
                                         /* une seule lettre */
                                        if (isupper(mol[i]))
                                        {
                                            tab[0] = mol[i];
                                
                                            /* si y'a une majuscule à la suite, on la remplace par un '\0' */
                                            if (isupper(mol[i+1]))
                                                tab[i+1] = '\0';
                                
                                            /* lettre majuscule puis lettre minuscule */
                                            else if (islower(mol[i+1]))
                                            {
                                                tab[i+1] = mol[i+1];
                                                r = recherche(tab, masse, NB_MOL);
                                                ++i;
                                                a = 1;
                                            }
                                
                                            else if (isdigit(mol[i+1]))
                                            {
                                                for(; isdigit(mol[i+1]); i++)
                                                {
                                                    nb_coeff++;
                                                }
                                
                                                a = strtol(mol + (i - nb_coeff + 2), NULL, 10);
                                                i--;
                                            }
                                
                                            r = recherche(tab, masse, NB_MOL);
                                            i++;
                                
                                            if (r != -1)
                                            {
                                                resultat += masse[r].nombre * a;
                                            }
                                
                                        }
                                
                                    } while (*mol++);
                                
                                    return resultat;
                                }
                                


                                masse.h

                                #ifndef MASSE_H_050920112211_BV
                                #define MASSE_H_050920112211_BV
                                
                                #include "constante.h"
                                
                                /* la structure et les prototypes */
                                
                                typedef struct Masse
                                {
                                    char name[PATH_MAX];
                                    double nombre;
                                } Masse;
                                
                                Masse * Constructeur(void);
                                void Open(Masse * masse, char * fichier);
                                int recherche(char * str, Masse * masse, int nombre);
                                double calcul (Masse * masse, char * mol);
                                
                                #endif
                                


                                test.c

                                #include "test.h"
                                
                                /*  pour éviter de surcharger les autres fichiers, sert à vérifier malloc et fopen */
                                
                                void* my_malloc(size_t size, char* file, int line)
                                {
                                    void* ptr = NULL;
                                
                                    ptr = (malloc)(size);
                                
                                    if (size <= 0)
                                    {
                                        fprintf(stderr, "Erreur lors d'un malloc : la taille doit etre superieure a 0\nLigne %d du fichier %s\n", line, file);
                                        exit(EXIT_FAILURE);
                                    }
                                
                                    if (!ptr)
                                    {
                                        fprintf(stderr, "Erreur lors d'un malloc : ligne %d du fichier %s\n", line, file);
                                        exit(EXIT_FAILURE);
                                    }
                                
                                    return (ptr);
                                }
                                
                                FILE* my_fopen(const char* filename, const char* mode, char* file, int line)
                                {
                                    FILE* openfile = NULL;
                                
                                    openfile = (fopen)(filename, mode);
                                    if(!openfile)
                                    {
                                        fprintf(stderr, "Erreur lors d'un fopen de '%s' en mode '%s' ", filename, mode);
                                        perror("");
                                        fprintf(stderr, "Ligne %d du fichier %s.\n", line, file);
                                        exit(EXIT_FAILURE);
                                    }
                                
                                    return (openfile);
                                }
                                


                                test.h

                                #ifndef H_TEST_060920111217_BE
                                #define H_TEST_060920111217_BE
                                
                                #include "constante.h"
                                
                                #define malloc(size) my_malloc(size, __FILE__, __LINE__)
                                    void* my_malloc(size_t size, char* file, int line);
                                
                                #define fopen(filename, mode) my_fopen(filename, mode, __FILE__, __LINE__)
                                    FILE* my_fopen(const char* filename, const char* mode, char* file, int line);
                                
                                #endif
                                


                                Voilà j'espère que vous me conprendrez ; si jamais vous avez des astuces, des conseils, je suis prenant.

                                Merci d'avance.

                                EDIT 2 : niveau 2 géré, avec théoriquement un nombre infini de molécules.
                                EDIT 3 : niveau 3 géré à moitié (on peut rentrer des coefficients, mais seulement de 1 à 9).
                                EDIT 4 : coefficient théoriquement infini.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  6 septembre 2011 à 18:58:40

                                  Tu sais, c'est pas si horrible que ça pour le moment, quand tu vois mon code il n'est pas mieux... :-°
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Staff désormais retraité.
                                  Anonyme
                                    6 septembre 2011 à 18:59:19

                                    Ouais mais toi t'as réussi tout seul, moi je n'en suis même pas capable..
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      6 septembre 2011 à 19:23:18

                                      Citation : informaticienzero

                                      Ça y est, j'y suis arrivé, j'ai fait le niveau 1. Malheureusement ... c'est nul. Je n'ai pas votre logique, pas votre expérience, et je dois avouer que j'ai du copier... :euh:


                                      Une question simple : quel est le titre du topic (bon pas celui-là, mais l'autre) ? ça s'intitule 'exercices pour débutants'.
                                      Si tu es débutant et que tu galères : C'EST NORMAL !!!!!! mais, même si tu n'as pas réussi tout seul, tu as fait quelque chose et tu as progressé (même si tu ne le vois pas forcément). C'est normal de galérer, faut pas se leurrer, c'est comme ça qu'on progresse ! ;)

                                      Encore une fois, si c'est pas les débutants qui font les exos, quel intérêt de proposer des exercices ?
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      Anonyme
                                        6 septembre 2011 à 19:32:04

                                        Merci Pouet_forever, ça me rassure beaucoup. :)

                                        J'étais découragé parce que vous sembliez tous y arriver très facilement, et puis finalement je me suis rendu compte (grâce à toi et aux autres), que c'était normal que je galère. Merci à tous. ;)

                                        EDIT : j'ai édité mon post précédant avec le code, il gère le niveau 2, et théoriquement un nombre infini de combinaisons (genre CHeNaLiHO).
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          7 septembre 2011 à 9:37:52

                                          Bonjour à tous.

                                          J'ai trouvé le sujet sympa donc je me lance. Je suis pas super fier de mon code avec ses variables globales mais bon...pour ce que j'ai pu testé ça a l'air de marcher. Par contre comme j'utilise une fonction de hash complètement bidon il se pourrait qu'il y ait une collision (que je n'ai pas géré) si on ajoute plus d'atomes.
                                          Bref, voici le code en question. Je pense remplir tous les niveaux mais par contre si on rentre n'importe quoi ça risque de pas donner grand chose étant donné que je traite quasiment pas les erreurs.
                                          #include <stdio.h>
                                          #include <stdlib.h>
                                          #include <ctype.h>
                                          
                                          #define MAXSIZE 101
                                          #define FILENAME "mol_values"
                                          
                                          double atoms[MAXSIZE] = {0};
                                          int c;
                                          
                                          double parse_atom(void);
                                          
                                          /* pseudo-fonction de hachage */
                                          unsigned int hash(char *s)
                                          {
                                            unsigned int h = 0;
                                            for(; *s; s++)
                                              h = *s + h*31;
                                            return h % MAXSIZE;
                                          }
                                          
                                          /* renvoie le charactère actuel et stock le prochain dans c */
                                          int next_char(void)
                                          {
                                            int tmp = c;
                                            c = getchar();
                                            return tmp;
                                          }
                                          
                                          /* Lit le fichier et initialise la "table" de hachage */
                                          void load_hash(void)
                                          {
                                            FILE *file = fopen(FILENAME, "r");
                                            char name[3] = "";
                                            double val;
                                            if(!file)
                                            {
                                              printf("Erreur (de chargement du fichier)\n");
                                              exit(EXIT_FAILURE);
                                            }
                                            while(fscanf(file, "%s %lf", name, &val) != EOF)
                                              atoms[hash(name)] = val;
                                            fclose(file);
                                          }
                                          
                                          /* écrit un atome et sa masse dans un fichier */
                                          void write_atom(char *name, double val)
                                          {
                                            FILE *file;
                                            if((file = fopen(FILENAME, "a")) != NULL)
                                              fprintf(file, "%s %f\n", name, val);
                                            fclose(file);
                                            load_hash();
                                          }
                                          
                                          /* parse une molécule  : 
                                             <molécule> ::= <atome> <molécule> | <atome>{<chiffre>} */
                                          double parse_molecule(double cur_val)
                                          {
                                            double val, factor = 0;
                                            if(c == EOF || c == '\n')
                                              return cur_val;
                                            if(!(val = parse_atom()))
                                              return 0;
                                            while(isdigit(c))
                                              factor = next_char() - '0' + factor * 10;
                                            if(factor)
                                              val *= factor;
                                            cur_val += val;
                                            if(c == ')')
                                              return cur_val;
                                            return parse_molecule(cur_val);
                                          }
                                          
                                          /* parse un "atome" : 
                                             <atome> ::= <lettre majuscule> [<lettre minuscule>] | '(' <molecule> ')' */
                                          double parse_atom(void)
                                          {
                                            double val;
                                            char name[3] = {'\0','\0','\0'};
                                            if(c == '(')
                                            {
                                              next_char();
                                              val = parse_molecule(0);
                                              if(next_char() != ')')
                                                printf("Erreur (parenthèse manquante)\n");
                                              return val;
                                            }
                                            else if(isupper(c))
                                            {
                                              name[0] = next_char();
                                              if(islower(c))
                                                name[1] = next_char();
                                              return atoms[hash(name)];
                                            }
                                            return 0;
                                          }
                                          
                                          /* lit un atome et sa masse molaire pour l'ajouter au fichier */
                                          void read_atom(void)
                                          {
                                            char name[3];
                                            double val;
                                            if(scanf("dd %s %lf", name, &val))
                                              write_atom(name, val);
                                            else
                                              printf("Commande inconnue\n");
                                            while((c = getchar()) != '\n' && c != EOF);
                                          }
                                          
                                          int main(void)
                                          {
                                            load_hash();
                                            while(1) 
                                            {
                                              printf("> ");
                                              next_char();
                                              if(c == '\n')
                                                break;
                                              if(islower(c))
                                                read_atom();
                                              else
                                              {
                                                double val = parse_molecule(0);
                                                if(!((int)val))
                                                  printf("Atome inconnu\n");
                                                else
                                                  printf("Masse molaire : %.2fg/mol\n", val);
                                              }
                                            }
                                          
                                            return EXIT_SUCCESS;
                                          }
                                          

                                          Pour expliquer très vite fait ce que je fais :
                                          En gros, je me base juste sur la syntaxe suivante (je suis conscient que les noms de collent pas vraiment à la définition d'atome et de molécule, mes excuses aux amateurs de chimie):
                                          <atome> ::= <lettre majuscule> [<lettre minuscule>]
                                                    | '(' <molécule> ')'
                                          <molécule> ::= <atome> <molécule>
                                                       | <atome> {<chiffre>}


                                          Un petit exemple d'utilisation :
                                          ~/Dropbox/Programming/C/mol$ ./a.out 
                                          > H2O
                                          Masse molaire : 18.01g/mol
                                          > CH3COOH
                                          Masse molaire : 60.05g/mol
                                          > Mg
                                          Atome inconnu
                                          > add Mg 24.305
                                          > Mg(OH)2
                                          Masse molaire : 58.32g/mol
                                          >


                                          Je suis évidemment ouvert à tout commentaire.

                                          Edit: Petite correction dans parse_molecule pour traiter les "coefficients" à plus d'un chiffre.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            7 septembre 2011 à 12:37:37

                                            @informaticienzero : je ne l'ai pas dit, mais si tu savais le temps que j'ai passé pour mon code tout ridicule... :-°
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Staff désormais retraité.
                                              7 septembre 2011 à 14:15:26

                                              Je réitère la demande de Pouet_Forever : pouvez vous tout mettre dans un seul fichier ? Je pense que pour un programme aussi court ce ne soit pas très grand ( :lol: ). Merci. :)
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              "If debbugging is the process of removing bugs, then programming must be the process of putting them in." (Edsger Dijkstra)
                                                7 septembre 2011 à 18:18:02

                                                Citation : lucas-84

                                                @informaticienzero : je ne l'ai pas dit, mais si tu savais le temps que j'ai passé pour mon code tout ridicule... :-°


                                                C'est bizarre, pour quelqu'un ayant programmé plusieurs mini-OS ça devrait se faire les doigts dans le nez. :-°
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                Anonyme
                                                  7 septembre 2011 à 22:44:48

                                                  Ça y est, j'ai réussi le niveau 3 ... à moitié : il ne gère que les coefficients de 1 à 9. Je réecrirais sans doute ça demain ou vendredi (j'ai l'algorithme) pour qu'il gère un nombre infini de coefficients.
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    7 septembre 2011 à 23:43:40

                                                    Citation : informaticienzero

                                                    Ça y est, j'ai réussi le niveau 3 ... à moitié : il ne gère que les coefficients de 1 à 9.



                                                    Oups, tu viens de mettre en lumière un bug dans mon code. :-°
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                    Bla bla bla
                                                      8 septembre 2011 à 7:50:09

                                                      Bonjour,

                                                      Voilà ma solution pour le niveau 4 :

                                                      #include <stdio.h>
                                                      #include <stdlib.h>
                                                      #include <ctype.h>
                                                      #include <string.h>
                                                      
                                                      #define IN_FILE 7
                                                      #define SIZE 156
                                                      
                                                      typedef struct
                                                      {
                                                          char name[3];
                                                          double mM;
                                                      } Atom;
                                                      
                                                      void init(Atom *atoms, FILE *file)
                                                      {
                                                          int i;
                                                          for (i = 0 ; i < IN_FILE ; i++)
                                                              fscanf(file, "%s %lf", atoms[i].name, &atoms[i].mM);
                                                      }
                                                      
                                                      int getIndex(char *str, int i)
                                                      {
                                                          int c = 1;
                                                          for (--i ; i >= 0 && c ; i--)
                                                              if (str[i] == ')')
                                                                  c++;
                                                              else if (str[i] == '(')
                                                                  c--;
                                                          return i+1;
                                                      }
                                                      
                                                      void restore(char *str, char *from, int begin, int end)
                                                      {
                                                          strncpy(str+begin, from+begin, (unsigned)end-begin+1);
                                                      }
                                                      
                                                      int main(void)
                                                      {
                                                          Atom atoms[IN_FILE];
                                                          FILE *file = NULL;
                                                          char realStr[SIZE] = "", str[SIZE] = "", atomName[3] = "";
                                                          int i, j, d = 0;
                                                          double sum = 0;
                                                      
                                                          if ((file = fopen("atoms.txt", "r")) == NULL)
                                                              exit(EXIT_FAILURE);
                                                          init(atoms, file);
                                                          fclose(file);
                                                      
                                                          printf("Entrez une molecule :\n--> ");
                                                          scanf("%s", realStr);
                                                          strcpy(str, realStr);
                                                      
                                                          for (i = 0 ; i < (signed)strlen(str) ; i++)
                                                          {
                                                              memset(atomName, 0, 3);
                                                              d = 0;
                                                              if (isupper(str[i]))
                                                              {
                                                                  atomName[0] = str[i];
                                                                  if (islower(str[i+1]))
                                                                      atomName[1] = str[i+1], d = 1;
                                                                  if (isdigit(str[i+1+d]) && str[i+1+d] > '1')
                                                                      str[i+1+d]--, i--;
                                                                  for (j = 0 ; j < IN_FILE ; j++)
                                                                      if (!strcmp(atomName, atoms[j].name))
                                                                          sum += atoms[j].mM;
                                                              }
                                                              else if (str[i] == ')' && isdigit(str[i+1]) && str[i+1] > '1')
                                                              {
                                                                  str[i+1]--;
                                                                  j = getIndex(str, i);
                                                                  restore(str, realStr, j+1, i-1);
                                                                  i = j;
                                                              }
                                                          }
                                                          printf("La masse molaire de cette molecule est %f g.mol-1\n", sum);
                                                      
                                                          return 0;
                                                      }
                                                      

                                                      Ça fait très longtemps que je n'ai pas touché à la programmation :) .

                                                      P.S : La masse molaire de l'Acétone est de 58,08 g.mol-1 et non 57,08 g.mol-1.
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        8 septembre 2011 à 10:42:20

                                                        Citation : _Fender_

                                                        Citation : informaticienzero

                                                        Ça y est, j'ai réussi le niveau 3 ... à moitié : il ne gère que les coefficients de 1 à 9.


                                                        Oups, tu viens de mettre en lumière un bug dans mon code. :-°



                                                        Idem :-°
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          8 septembre 2011 à 15:03:04

                                                          Il y'a pas des exemples pour tester l'imbrication des accolades parenthèse ?
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            8 septembre 2011 à 18:31:25

                                                            Citation : HighTam

                                                            P.S : La masse molaire de l'Acétone est de 58,08 g.mol-1 et non 57,08 g.mol-1.



                                                            Merci, c'est corrigé. ;)

                                                            Citation : kaka551

                                                            Il y'a pas des exemples pour tester l'imbrication des accolades ?



                                                            Des parenthèses plutôt ? Si tu arrives à en trouver, je suis preneur ! :lol:
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                            Bla bla bla
                                                              8 septembre 2011 à 18:45:52

                                                              Citation : _Fender_

                                                              Citation : kaka551

                                                              Il y'a pas des exemples pour tester l'imbrication des accolades ?



                                                              Des parenthèses plutôt ? Si tu arrives à en trouver, je suis preneur ! :lol:


                                                              :honte: Oui je suis désolé .
                                                              Je vais en chercher
                                                              • 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