Partage
  • Partager sur Facebook
  • Partager sur Twitter

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

Venez vous entraîner !

    3 septembre 2011 à 23:32:08

    Bonsoir,

    Voici ma solution pour le niveau 4, codée un peu à la va-vite. Désolé pour le style qui laisse à désirer (mélange de français / anglais, notamment). Et merci de m'informer si des bugs subsistent, svp. :)

    J'ai mis la liste d'atomes dans un tableau pour pouvoir utiliser bsearch(), mais en il aurait été plus "naturel" (de mon point de vue) d'utiliser une table de hachage, tant pis.

    Pour le parsing de l'entrée, je l'ai fait de façon un peu "hardcore". A vous de voir et dire ce que vous en pensez (fonction eval()).

    Je passe la structure Tab_Atomes aux fonctions directement au lieu d'utiliser un pointeur parce que cela ne fait pas une grosse différence ici, et j'ai donc eu la flemme. C'est plus lisible aussi (enfin bon, je ne peux pas affirmer avoir favorisé la lisibilité... :-° )

    Enfin, si j'ai bien compris, les nombres sont toujours postfixés, c'est bien ça ?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define filename        "Atomes.txt"
    #define ATOM_NAME_SZ    8
    #define INPUT_SZ        80
    
    typedef struct
    {
        char nom[ATOM_NAME_SZ];
        double masse;
    } Atome;
    
    typedef struct _ls
    {
        Atome at;
        struct _ls* next;
    } Lst_Atomes;
    
    typedef struct
    {
        size_t size;
        Atome* array;
    } Tab_Atomes;
    
    
    
    static int cmp (const void* a, const void *b)
    {
        return strcmp ( ((Atome*)a)->nom, ((Atome*)b)->nom );
    }
    
    Tab_Atomes chargement_fichier (void)
    {
        FILE* infile = NULL;
        Lst_Atomes* lst = NULL;
        size_t sz = 0;
    
        /* charge le contenu du tableau dans une liste chainee */
        if ( (infile = fopen(filename, "r")) != NULL )
        {
            Atome a;
            while ( fscanf(infile, "%s %lf\n", a.nom, &a.masse) == 2 )
            {
                Lst_Atomes* nelem = malloc(sizeof *nelem);
                nelem->at = a, nelem->next = lst, lst = nelem;
                ++sz;
            }
    
            fclose(infile);
        }
    
        /* initialise le tableau */
        Tab_Atomes tab;
        tab.size = sz;
        tab.array = malloc(sz * sizeof(Atome));
    
        /* on remplit le tableau et on vide la liste en meme temps */
        size_t i;
        for (i=0; i<tab.size; ++i)
        {
            tab.array[i] = lst->at;
            Lst_Atomes* tmp = lst;
            lst = lst->next, free(tmp), tmp = NULL;
        }
    
        /* on trie les atomes par noms, pour utiliser bsearch ulterieurement */
        qsort(tab.array, sz, sizeof* tab.array, cmp);
    
        return tab;
    }
    
    double eval (char** pinput, Tab_Atomes liste_atomes)
    {
        double retval = 0, current = 0;
        while (**pinput)
        {
            char name[ATOM_NAME_SZ] = "";
            if (isalpha(**pinput))  /* Nouvel atome */
            {
                retval += current;
    
                char* start = *pinput;
                size_t sz = 1;
                while ( islower(*++*pinput) )
                    ++sz;
                strncpy(name, start, sz);
    
                Atome* at = bsearch(name, liste_atomes.array, liste_atomes.size, sizeof(Atome), cmp);
                if (at == NULL)
                {
                    fprintf(stderr, "Atome inconnu : arret.");
                    exit(1);
                }
                current = at->masse;
            }
            else if (isdigit(**pinput))
            {
                char* end;
                unsigned factor = strtoul(*pinput, &end, 10);
                *pinput = end;
                current *= factor;
            }
            else if (**pinput == '(')
            {
                ++*pinput;
                retval += current;
                current = eval(pinput, liste_atomes);
            }
            else if (**pinput == ')')
            {
                ++*pinput;
                break;
            }
            else if (isspace(**pinput))
            {
                ++*pinput;
            }
            else
            {
                fprintf(stderr, "Entree inattendue : arret.");
                exit(1);
            }
        }
    
        return retval + current;
    }
    
    int main()
    {
        Tab_Atomes liste_atomes = chargement_fichier();
    
        char input[INPUT_SZ];
        while (1)
        {
            printf( "Entrez une molecule : \n--> " );
            if ( fgets(input, INPUT_SZ, stdin) != NULL )
            {
                char* in = input;
                printf("\nLa masse molaire de cette molecule est %lf g.mol-1\n\n", eval (&in, liste_atomes));
            }
        }
    
        free(liste_atomes.array);
    
        return 0;
    }
    
    • Partager sur Facebook
    • Partager sur Twitter
      4 septembre 2011 à 0:01:33

      J'ai juste vu une petite coquille ici je pense :
      unsigned factor = strtoul(*pinput, &end, 10);
      


      Sinon c'est pas un peu contradictoire de sortir l'artillerie lourde avec qsort et bsearch (je ne critique pas du tout ce point, au contraire), et en même temps faire un tri assez lourd directement sur le tableau de structure, sans passer par des pointeurs.
      • Partager sur Facebook
      • Partager sur Twitter
        4 septembre 2011 à 10:23:04

        Salut,

        Très intéressant ce petit exo et pas aussi facile qu'il n'y paraît.
        Voici mon code, il gère tous les niveaux proposés. Pour entrer un nouvel atome, il suffit de spécifier son nom suivit de sa masse molaire.


        #include <ctype.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        
        static double
        masse_mol(char *s, FILE *fichier)
        {
        	char atome[3];
        	double masse;
        	double ret = .0;
        
        	rewind(fichier);
        	while (fscanf(fichier, "%2s%*[ ]%lf", atome, &masse) == 2) {
        		int next = (atome[1] == '\0') ? 1 : 2;
        		char *p;
        
        		for (p = s; (p = strstr(p, atome)) != NULL; p += next)
        			if (islower(p[next]))
        				continue;
        			else if (isdigit(p[next]))
        				ret += masse * (p[next] - '0');
        			else
        				ret += masse;
        	}
        
        	return ret;
        }
        
        
        static double
        masse_mol_grp(char *s, FILE *fichier, double total, double prec)
        {
        	char *p;
        
        	if ((p = strtok(s, "|")) == NULL)
        		return total + prec;
        	else if (isdigit(p[0])) {
        		prec *= (p[0] - '0');
        		return masse_mol_grp(NULL, fichier, total, prec);
        	} else {
        		total += prec;
        		prec = masse_mol(p, fichier);
        		return masse_mol_grp(NULL, fichier, total, prec);
        	}
        }
        
        
        static void
        affiche_masse_mol(char *s, FILE *fichier)
        {
        	char *p;
        	double masse_mol;
        
        	for (p = s; (p = strpbrk(p, "()")) != NULL; p++)
        		*p = '|';
        
        	masse_mol = masse_mol_grp(s, fichier, .0, .0);
        	printf("la masse molaire est de %lf\n", masse_mol);
        }
        
        
        static void
        ecrit_atome(char const *s, FILE *fichier)
        {
        	if ((fichier = freopen("mol.txt", "a", fichier)) != NULL)
        		fputs(s, fichier);
        }
        
        
        int
        main(void)
        {
        	FILE *fichier;
        	static char tampon[BUFSIZ];
        
        	if ((fichier = fopen("mol.txt", "r")) == NULL)
        		return EXIT_FAILURE;
        
        	while (fgets(tampon, BUFSIZ, stdin) != NULL) {
        		char atome[3];
        		double masse;
        
        		if (sscanf(tampon, "%2s%*[ ]%lf", atome, &masse) == 2)
        			ecrit_atome(tampon, fichier);
        		else
        			affiche_masse_mol(tampon, fichier);
        	}
        
        	fclose(fichier);
        	return EXIT_SUCCESS;
        }
        



        Le coeur du code est une fonction récursive utilisant strtok pour diviser chaque groupe présent dans l'entrée en sous-chaîne. Il n'est pas super optimisé puisque le fichier est relu en entier chaque fois que l'on doit calculer la masse molaire d'un groupe (fonction masse_mol).

        EDIT: correction d'un problème avec fscanf et sscanf.
        EDIT2: oubli de mettre la variable ret à zéro dans la fonction masse_mol.
        EDIT3: correction dans la fonction masse_mol_grp.
        • Partager sur Facebook
        • Partager sur Twitter
          4 septembre 2011 à 11:42:11

          Hmm, petit détail que je ne comprends pas : à chaque fois, vous faîtes des tableaux atome[3] (par exemple toi Taurre), mais vous ne lisez que 2 caractères au maximum %2s.
          • 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)
            4 septembre 2011 à 11:52:03

            Citation : schadocalex


            Hmm, petit détail que je ne comprends pas : à chaque fois, vous faîtes des tableaux atome[3] (par exemple toi Taurre), mais vous ne lisez que 2 caractères au maximum %2s.



            C'est parce qu'il faut compter le caractère de fin de chaîne (ajouter automatiquement avec le format "%s") ;)
            • Partager sur Facebook
            • Partager sur Twitter
              4 septembre 2011 à 11:57:09

              Oui, mais un atome[2] suffit pour cela.
              • 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)
                4 septembre 2011 à 12:08:01

                Non, puisqu'un atome fait un ou deux caractères ;)
                • Partager sur Facebook
                • Partager sur Twitter
                  4 septembre 2011 à 12:15:46

                  atome[0] = 'A'
                  atome[1] = 'l'
                  atome[2] = '/0'

                  Non ?
                  • 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)
                    4 septembre 2011 à 12:18:32

                    Bah justement, là tu as bien trois caractère, donc il faut que la taille de atome soit au moins de 3 — et du coup les indices vont de 0 à 2, puisqu’on compte à partir de 0.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      4 septembre 2011 à 12:23:20

                      Mais je sais bien tout ça, mais si atome[2] = '/0' est la fin de la chaîne du caractère, ça sert à quoi d'en rajouter un ? (atome[3] = '/0'). Apparemment, ça viendrait du %s, mais je ne vois pas pourquoi il faudrait deux '/0' pour que %s fonctionne correctement.
                      • 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)
                        4 septembre 2011 à 12:40:42

                        Citation : schadocalex


                        Mais je sais bien tout ça, mais si atome[2] = '/0' est la fin de la chaîne du caractère, ça sert à quoi d'en rajouter un ? (atome[3] = '/0'). Apparemment, ça viendrait du %s, mais je ne vois pas pourquoi il faudrait deux '/0' pour que %s fonctionne correctement.



                        Il n'y a pas deux caractères de fin de chaîne, il n'y en a qu'un. "%2s" ne dit pas que l'on lit forcément deux caractères (ça c'est le format "%2c"), mais dit que l'on lit au maximum deux caractères ;)

                        Sinon, je me rends compte que mon implémentation est incorrecte, elle ne gère que certains cas d'imbrications... >_<
                        • Partager sur Facebook
                        • Partager sur Twitter
                          4 septembre 2011 à 13:32:32

                          Cet exercice a un parfum de rentrée…

                          Je le ferais dès que j'en aurais l'occasion. J'ai déjà mes idées en tête.

                          C'est vraiment plus compliqué que ça en a l'air ? Quand je vois des codes de 200 lignes (Taurre m'a rassuré, il n'en a fait que 93 :p )…
                          • Partager sur Facebook
                          • Partager sur Twitter
                            4 septembre 2011 à 14:45:36

                            Citation : Twisted Destiny

                            J'ai juste vu une petite coquille ici je pense :

                            unsigned factor = strtoul(*pinput, &end, 10);
                            

                            C'est quoi le souci ? pinput est de type char**, et end de type char*.

                            Citation : Twisted Destiny

                            Sinon c'est pas un peu contradictoire de sortir l'artillerie lourde avec qsort et bsearch (je ne critique pas du tout ce point, au contraire), et en même temps faire un tri assez lourd directement sur le tableau de structure, sans passer par des pointeurs.


                            Non, qsort() n'est appelé qu'une fois, ensuite c'est bsearch() qui fait le boulot, et à ce moment aucun intérêt de passer par des pointeurs, puisqu'il n'y a aucun déplacement de données.

                            Citation : Maëlan

                            C'est vraiment plus compliqué que ça en a l'air ? Quand je vois des codes de 200 lignes (Taurre m'a rassuré, il n'en a fait que 93 :p )…


                            Non, ce n'est pas particulièrement compliqué, mais je pense que 200 lignes ce n'est pas énormes pour cet exo, si tu veux avoir un code "correct" et "propre".

                            PS : ma plus belle ligne :p :
                            while ( islower(*++*pinput) ) ++sz;
                            
                            • Partager sur Facebook
                            • Partager sur Twitter
                              4 septembre 2011 à 16:20:17

                              Voilà ma participation, je l'améliorerais sans doute dans la semaine. Elle comporte les 5 niveaux.
                              Pour ajouter un atome et sa masse, il faut faire "add H 1" par exemple.

                              #include <stdio.h>
                              #include <stdlib.h>
                              #include <ctype.h>
                              #include <string.h>
                              
                              double masseMolaireAtome(char atome[3])
                              {
                                  FILE *fichier = NULL;
                                  fichier = fopen("massesmolaires", "r");
                                  if(fichier == NULL)
                                      exit(1);
                                  char atome2[3] = "";
                                  double masseMolaire;
                              
                                  while (fscanf(fichier, "%2s%*[ ]%lf", atome2, &masseMolaire) == 2)
                                  {
                                      if(strcmp(atome, atome2) == 0)
                                          return masseMolaire;
                                  }
                              
                                  fclose(fichier);
                                  exit(1);
                              }
                              
                              void ajoutMolecule(char* molecule)
                              {
                                  FILE *fichier = NULL;
                                  fichier = fopen("massesmolaires", "a");
                                  if(fichier == NULL)
                                      exit(1);
                                  char atome[3] = "";
                                  double masseMolaire;
                              
                                  sscanf(molecule, "%*[a-z]%*[ ]%2s%*[ ]%lf", atome, &masseMolaire);
                                  fprintf(fichier, "%s %lf\n", atome, masseMolaire);
                              
                                  fclose(fichier);
                              }
                              
                              double masseMolaireMolecule(char* molecule, double masseMolaireTotale)
                              {
                                  char atome[3] = "";
                                  int tailleAtome = 0, debutAtome = 0;
                              
                                  atome[0] = molecule[0];
                              
                                  if(molecule[0] == '(') // Si c'est le début d'un groupe
                                  {
                                      molecule[0] = ' ';
                                      debutAtome = 1;
                                      atome[0] = molecule[1];
                                      tailleAtome = 2;
                                  }
                                  else if(molecule[0] == '\0') // Si c'est la fin de la molécule
                                      return masseMolaireTotale;
                                  else if(molecule[0] == ')') // Si c'est la fin d'un groupe
                                  {
                                      molecule[0] = ' ';
                                      return masseMolaireTotale * strtol(molecule, &molecule, 10);
                                  }
                                  else if(islower(molecule[debutAtome+1])) // Sinon si l'atome se compose de deux lettres
                                  {
                                      molecule[debutAtome] = ' ';
                                      atome[1] = molecule[debutAtome+1];
                                      tailleAtome = 2 + debutAtome;
                                  }
                                  else // Sinon l'atome ne se compose que d'une lettre
                                      tailleAtome = 1 + debutAtome;
                              
                                  if(isdigit(molecule[tailleAtome])) // Si c'est un nombre, on le laisse à strtol en remplacant par ' '
                                      molecule[tailleAtome-1] = ' ';
                                  else // Si c'est autre chose qu'un nombre, on force strtol à lire 1 en remplacant par '1'
                                      molecule[tailleAtome-1] = '1';
                              
                                  masseMolaireTotale += masseMolaireAtome(atome) * strtol(molecule, &molecule, 10);
                              
                                  return masseMolaireMolecule(molecule, masseMolaireTotale);
                              }
                              
                              int main()
                              {
                                  char molecule[100] = "";
                              
                                  scanf("%99[a-zA-Z1-9() ]s", molecule);
                                  // TO DO : Vérifier si la molécule est valable
                                  if(strncmp(molecule, "add ", 4) == 0)
                                      ajoutMolecule(molecule);
                                  else
                                      printf("%lf", masseMolaireMolecule(molecule, 0));
                              
                                  return 0;
                              }
                              
                              • 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)
                                4 septembre 2011 à 16:53:53

                                J'en profite pour vous dire que ce code gère maintenant normalement les cinq niveaux, vu que la gestion de l'imbrication de parenthèses n'est pas demandée. :p
                                • Partager sur Facebook
                                • Partager sur Twitter
                                Staff désormais retraité.
                                  4 septembre 2011 à 18:02:52

                                  Citation : yoch

                                  PS : ma plus belle ligne :p :

                                  while ( islower(*++*pinput) ) ++sz;
                                  

                                  Rhaa, c'est beau !
                                  bave bave
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    4 septembre 2011 à 18:09:41

                                    Et en C++? Y a pas de défis?
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      4 septembre 2011 à 18:21:11

                                      Citation : NOB

                                      Et en C++? Y a pas de défis?


                                      Exercices / défis, c'est pareil. Va sur le forum C++. ;)
                                      • 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)
                                        4 septembre 2011 à 19:13:41

                                        Snif, plus je lis vos réponses (mais pas vos codes) plus je pense que je suis pas prête d'être prête pour cet exercice-là...
                                        Pensez-vous que quelqu'un étant au tutoriel de M@téo21 chapitre lire et écrire dans des fichiers, sans aucune connaissance non inscrite dans les chapitres précédents pourrait quand même s'en sortir?
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          4 septembre 2011 à 19:25:26

                                          Bonjour,

                                          J'ai décidé d'essayer ce petit défi. Voilà, bien deux ans que je n'avais pas codé en C. Ce ne fut pas forcément simple.

                                          Je modifierai mon code si j'ai le temps afin que si l'utilisateur rentre n'importe quoi, que le programme ne plante pas etc....

                                          Mais bon ca marche:

                                          #include <stdio.h>
                                          #include <stdlib.h>
                                          #include <ctype.h>
                                          
                                          double traitement(char molecule[]);
                                          double search1(char atome[]);
                                          double search2(char atome);
                                          double conversion(char chaine[]);
                                          void calcul();
                                          void ajout();
                                          void menu();
                                          int main()
                                          {
                                              menu();
                                          
                                              return 0;
                                          }
                                          void menu()
                                          {
                                              int choix=0;
                                              printf("---------------MENU----------------\n\n\n");
                                              printf("1- Calculez la molaire d une molécule\n");
                                              printf("2- Ajouter des atomes\n\n");
                                              printf("Entrez le numero que vous souhaitez: ");
                                              scanf("%d",&choix);
                                              if(choix==1)
                                              {
                                                  calcul();
                                              }
                                              else if(choix==2)
                                              {
                                                  ajout();
                                              }
                                              else
                                                  printf("Ne rentrez pas n importe quoi, ami Zero!");
                                          }
                                          void calcul()
                                          {
                                              char molecule[50];
                                              double total;
                                              printf("Entrez une molécule :\n --> ");
                                              scanf("%s",molecule);
                                              total=traitement(molecule);
                                              printf("\nLa masse molaire de cette molécule est de %f g.mol-1\n",total);
                                              int choix=0;
                                              printf("1- Recalculez une molaire d une molécule\n");
                                              printf("2- Ajouter des atomes\n\n");
                                              printf("Entrez le numero que vous souhaitez: ");
                                              scanf("%d",&choix);
                                              if(choix==1)
                                              {
                                                  calcul();
                                              }
                                              else if(choix==2)
                                              {
                                                  ajout();
                                              }
                                              else
                                                  printf("Ne rentrez pas n importe quoi, ami Zero!");
                                          }
                                          void ajout()
                                          {
                                              char atome[2];
                                              double masse;
                                              printf("Veuillez rentrer le nom de l atome\n");
                                              scanf("%s",atome);
                                              printf("Veuillez rentrer sa masse molaire\n");
                                              scanf("%lf",&masse);
                                          
                                              FILE *file= NULL;
                                              file = fopen("/home/tweesty/workspace/zMol/file.txt", "r+");
                                              if(file == NULL)
                                              {
                                                  printf("Un problème est survenu lors de l'ouverture du fichier .txt\n");
                                                  menu();
                                              }
                                              else
                                              {
                                                  fseek(file, 0, SEEK_END);
                                                  fprintf(file,"\n%s %f",atome,masse);
                                                  fclose(file);
                                              }
                                              int choix=0;
                                              printf("1- Calculez une molaire d une molécule\n");
                                              printf("2- Rajouter des atomes\n\n");
                                              printf("Entrez le numero que vous souhaitez: ");
                                              scanf("%d",&choix);
                                              if(choix==1)
                                              {
                                                  calcul();
                                              }
                                              else if(choix==2)
                                              {
                                                  ajout();
                                              }
                                              else
                                                  printf("Ne rentrez pas n importe quoi, ami Zero!");
                                          }
                                          double traitement(char molecule[])
                                          {
                                              double total=0;
                                              int curseur=0;
                                              char atome[2];
                                              int parenthese=0;
                                              double total_parenthese=0;
                                              while(curseur<strlen(molecule))
                                              {
                                                  if(molecule[curseur]=='(')
                                                  {
                                                      parenthese=1;
                                                      total_parenthese=0;
                                                      curseur++;
                                                  }
                                                  else if(molecule[curseur]==')')
                                                  {
                                                      parenthese=0;
                                                      total=total+total_parenthese*strtol(&molecule[curseur+1], NULL, 10);
                                                      curseur=curseur+2;
                                                  }
                                                  else if(islower(molecule[curseur+1]))
                                                  {
                                                      atome[0]=molecule[curseur];
                                                      atome[1]=molecule[curseur+1];
                                                      printf("%s",atome);
                                                      if(isdigit(molecule[curseur+2]))
                                                      {
                                                          if(parenthese==1)
                                                          total_parenthese=total_parenthese+search1(atome)*strtol(&molecule[curseur+2],NULL,10);
                                                          else
                                                          total=total+search1(atome)*strtol(&molecule[curseur+2],NULL,10);
                                                          curseur=curseur+3;
                                                      }
                                                      else
                                                      {
                                                          if(parenthese==1)
                                                          total_parenthese=total_parenthese+search1(atome);
                                                          else
                                                          total=total+search1(atome);
                                                          curseur=curseur+2;
                                                      }
                                                  }
                                                  else
                                                  {
                                                      atome[0]=molecule[curseur];
                                                      printf("%s",atome);
                                                      if(isdigit(molecule[curseur+1]))
                                                      {
                                                          if(parenthese==1)
                                                          total_parenthese=total_parenthese+search2(atome[0])*strtol(&molecule[curseur+1],NULL,10);
                                                          else
                                                          total=total+search2(atome[0])*strtol(&molecule[curseur+1],NULL,10);
                                                          curseur=curseur+2;
                                                      }
                                                      else
                                                      {
                                                          if(parenthese==1)
                                                          total_parenthese=total_parenthese+search2(atome[0]);
                                                          else
                                                          total=total+search2(atome[0]);
                                                          curseur++;
                                                      }
                                                  }
                                                  atome[0]=NULL;
                                                  atome[1]=NULL;
                                              }
                                              return total;
                                          
                                          }
                                          
                                          double search1(char atome[])
                                          {
                                              double resultat;
                                              FILE *file=NULL;
                                              file = fopen("/home/tweesty/workspace/zMol/file.txt", "r");
                                              if(file == NULL)
                                              {
                                                  printf("Un problème est survenu lors de l'ouverture du fichier .txt\n");
                                              }
                                              else
                                              {
                                                  int position=0;
                                                  int fini=0;
                                                  char chaine[100];
                                                  char caractereActuel;
                                                  caractereActuel = fgetc(file); 
                                                  while ((caractereActuel != EOF) || fini !=1) 
                                                      {
                                                          if(caractereActuel==atome[0])
                                                          {
                                                              caractereActuel = fgetc(file); 
                                                              if(caractereActuel==atome[1])
                                                              {
                                                                  fscanf(file, "%lf", &resultat);
                                                                  printf("=%f\n",resultat);
                                                                  fini=1;
                                                              }
                                                          }
                                                          else
                                                          {
                                                              caractereActuel = fgetc(file);
                                                          }
                                                      }
                                                  fclose(file);
                                              }
                                              return resultat;
                                          }
                                          double search2(char atome)
                                          {
                                              double resultat;
                                              FILE *file=NULL;
                                              file = fopen("/home/tweesty/workspace/zMol/file.txt", "r");
                                              if(file == NULL)
                                              {
                                                  printf("Un problème est survenu lors de l'ouverture du fichier .txt\n");
                                              }
                                              else
                                              {
                                                  int position=0;
                                                  int fini=0;
                                                  char chaine[100];
                                                  char caractereActuel;
                                                  caractereActuel = fgetc(file); 
                                                  while ((caractereActuel != EOF) || fini !=1) 
                                                  {
                                          	        if(caractereActuel==atome)
                                          	        {
                                          	            caractereActuel = fgetc(file);
                                          	            if(caractereActuel==' ')
                                          	            {
                                                              fscanf(file, "%lf", &resultat);
                                                              printf("=%f\n",resultat);
                                                              fini=1;
                                                          }
                                          	        }
                                                      else
                                                      {
                                                          caractereActuel = fgetc(file);
                                                      }
                                                  }
                                                  fclose(file);
                                              }
                                              return resultat;
                                          }
                                          


                                          Comme vous pouvez le voir, je ne me suis vraiment pas embetté... :-°
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            4 septembre 2011 à 19:37:37

                                            Citation : Ccile


                                            Snif, plus je lis vos réponses (mais pas vos codes) plus je pense que je suis pas prête d'être prête pour cet exercice-là...
                                            Pensez-vous que quelqu'un étant au tutoriel de M@téo21 chapitre lire et écrire dans des fichiers, sans aucune connaissance non inscrite dans les chapitres précédents pourrait quand même s'en sortir?



                                            Oui, tout à fait.
                                            Tu n'es pas obligé de remplir tous les niveaux d'un coup, tu peux te concentrer sur le premier et ensuite essayer d'améliorer ton programme.

                                            @yoch: pourquoi utilisé un pointeur de pointeur comme premier argument de ta fonction eval? Étant donné l'utilisation que tu en fais un pointeur n'aurait-il pas suffit?

                                            Aussi, par curiosité, dans ta fonction chargement_fichier, tu remplis une liste chaînées avec les atomes et leurs masses contenus dans le fichier pour la copier ensuite dans un tableau et la détruire. Est-ce pour éviter deux lectures dans le fichier (une pour compter le nombre de ligne et une pour remplir le tableau)?

                                            @schadocalex: attention à ce point:

                                            strtol(molecule, &molecule, 10);
                                            


                                            Les deux pointeurs utilisés par la fonction strtol sont des pointeurs restreints. Grosso modo, cela signifie qu'ils ne peuvent pas accéder à la même zone mémoire, or c'est le cas si tu passes deux fois le pointeurs molecule. ;)

                                            Ok, j'ai rien dit :-°
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Anonyme
                                              4 septembre 2011 à 19:38:42

                                              Ccile> Vu ton optimisme, j'ai des doutes.

                                              Tu peux toujours commencer à réfléchir à une solution sans te demander constamment "ES SE KE JE VÉ I ARIVAI ?". Et puis au final, si tu te rates, ce n'est pas grave, tu peux toujours ouvrir un fil sur ce forum pour obtenir de l'aide. Mais sache que le tutoriel de m@teo n'est pas une fin en soi, pour devenir un bon programmeur - puisque ça semble être une de tes grosses préoccupations - il te faudra lire des cours plus avancés et pratiquer.

                                              Donc, lance toi, et tu verras bien. Si tu n'y arrives vraiment pas, ce n'est pas grave : commence par faire des exercices plus faciles et réessaye celui-là plus tard ;) .
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                4 septembre 2011 à 19:51:01

                                                @Taurre:

                                                Le double pointeur, c'est pour pouvoir faire l'appel récursif, et récuperer les modifs réalisées sur *pinput, après l'appel récursif.
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                Zeste de Savoir, le site qui en a dans le citron !
                                                  4 septembre 2011 à 20:20:13

                                                  Citation : GurneyH

                                                  @Taurre:

                                                  Le double pointeur, c'est pour pouvoir faire l'appel récursif, et récuperer les modifs réalisées sur *pinput, après l'appel récursif.



                                                  Ah oui, je n'avais pas vu.
                                                  Merci ;)
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    4 septembre 2011 à 22:18:39

                                                    Voici mon code (niveau 5).

                                                    Il n'est sans doute pas très optimisé surtout au niveau de la gestion du calcul (je vais travailler ça prochainement, avec l'aide de vos commentaires ;) ).

                                                    Citation : Code


                                                    main.c

                                                    #include <stdio.h>
                                                    #include <string.h>
                                                    
                                                    #include "Mol.h"
                                                    
                                                    int main()
                                                    {
                                                        AtomList* tab = M_LoadFromFile("file.txt");
                                                        M_Show(tab);
                                                        char exp[50] = {0};
                                                        while (1)
                                                        {
                                                            printf("_____________________\n"
                                                                   "     - Quit\n"
                                                                   "     - Add\n"
                                                                   "_____________________\n\n");
                                                    
                                                            scanf("%s", exp);
                                                    
                                                            /* Ajout d'un atome */
                                                            if (!strcmp(exp,"Add"))
                                                            {
                                                                if (M_AddAtom("file.txt") == -1)
                                                                    printf("Erreur lors de l'ouverture du fichier\n");
                                                                else
                                                                {
                                                                    printf("Atome bien ajouté !\n");
                                                                    tab = M_LoadFromFile("file.txt");
                                                                    M_Show(tab);
                                                                }
                                                            }
                                                            else if (!strcmp(exp,"Quit"))
                                                                break;
                                                            else
                                                                printf("  --> %f\n\n", M_MolarMass(exp, tab));
                                                        }
                                                        return 0;
                                                    }
                                                    


                                                    Mol.h

                                                    #ifndef MOL_H_INCLUDED
                                                    #define MOL_H_INCLUDED
                                                    
                                                    typedef struct
                                                    {
                                                        char name[3];   // Symbole de l'atome (ex : C, Na, Cl, etc...)
                                                        float M;       // Masse molaire de l'atome
                                                    
                                                    }Atom;
                                                    
                                                    typedef struct
                                                    {
                                                        Atom* atom;      // Tableau d'atomes
                                                        size_t nbAtoms;  // Taille du tableau
                                                    
                                                    }AtomList;
                                                    
                                                    /* Alocation et libération de la liste d'atomes */
                                                        AtomList* M_LoadFromFile(const char*);
                                                        void M_Free(AtomList*);
                                                    
                                                    /* Renvoie la masse molaire correspondant à l'atome passé en paramètre */
                                                        float M_Mol(AtomList*,const char*);
                                                    
                                                    /* Affiche la liste d'atomes */
                                                        void M_Show(AtomList*);
                                                    
                                                    /* Calcule la masse molaire d'une molécule passée en paramètre */
                                                        float M_MolarMass(const char*,AtomList*);
                                                    
                                                    /* Vérifie qu'une expression est valide */
                                                        int M_Verif(const char*);
                                                    
                                                    /* Ajoute un atome dans les données */
                                                        int M_AddAtom(const char*);
                                                    
                                                    #endif
                                                    


                                                    LoadFree.c

                                                    #include <stdio.h>
                                                    #include <stdlib.h>
                                                    
                                                    #include "Mol.h"
                                                    
                                                    /* Fonction qui crée les atomes à partir du ficher dont le nom est passé en paramètre */
                                                    AtomList* M_LoadFromFile(const char* fileName)
                                                    {
                                                        /* On ouvre le fichier qui contient les données sur les atomes */
                                                        FILE* file;
                                                        if ((file = fopen(fileName, "r")) == NULL)
                                                        {
                                                            printf("Erreur lors de l'ouverture du fichier %s\n", fileName);
                                                            return NULL;
                                                        }
                                                    
                                                        /* Allocation de notre structure de données */
                                                        AtomList* atoms = NULL;
                                                        if ((atoms = malloc(sizeof(AtomList))) == NULL)
                                                        {
                                                            printf("Erreur lors de l'allocation du tableau de donnees\n");
                                                            return NULL;
                                                        }
                                                    
                                                        /* On calcule le nombre d'atomes présents dans le fichier */
                                                        atoms->nbAtoms = 0;
                                                        char s[3] = "";
                                                        float f = 0.f;
                                                        while (fscanf(file,"%s %f",s,&f) == 2)
                                                            ++atoms->nbAtoms;
                                                        rewind(file);
                                                    
                                                        /* On alloue le tableau d'atomes */
                                                        if ((atoms->atom = malloc(sizeof(Atom) * atoms->nbAtoms)) == NULL)
                                                        {
                                                            printf("Erreur lors de l'allocation du tableau de donnees\n");
                                                            return NULL;
                                                        }
                                                    
                                                        /* Enfin, on lit les informations */
                                                        int i = 0;
                                                        while (fscanf(file,"%s %f",atoms->atom[i].name,&atoms->atom[i].M) == 2)
                                                            ++i;
                                                        fclose(file);
                                                        return atoms;
                                                    }
                                                    
                                                    void M_Free(AtomList* atoms)
                                                    {
                                                        free(atoms->atom);
                                                        free(atoms);
                                                    }
                                                    


                                                    Utilitaires.c

                                                    #include <stdio.h>
                                                    
                                                    #include "Mol.h"
                                                    
                                                    /* Affiche la liste des atomes */
                                                    void M_Show(AtomList* atoms)
                                                    {
                                                        int i;
                                                        printf("\n\n_____________________\n");
                                                        for (i = 0; i < atoms->nbAtoms; ++i)
                                                            printf("%s --> %f\n", atoms->atom[i].name, atoms->atom[i].M);
                                                        printf("_____________________\n\n");
                                                    }
                                                    
                                                    /* Fonction pour ajouter un atome */
                                                    int M_AddAtom(const char* fileName)
                                                    {
                                                        FILE* file = NULL;
                                                        if ((file = fopen(fileName,"a+")) == NULL)
                                                            return -1;
                                                    
                                                        char newAtom[3] = "";
                                                        printf("\nEntre un atome :         --> ");
                                                        scanf("%2s",newAtom);
                                                    
                                                        float M = 0.f;
                                                        printf("\nEntre sa masse molaire : --> ");
                                                        scanf("%f",&M);
                                                    
                                                        fprintf(file,"%s %f\n",newAtom,M);
                                                        fclose(file);
                                                        return 0;
                                                    }
                                                    


                                                    Calcul.c

                                                    #include <string.h>
                                                    #include <stdio.h>
                                                    #include <ctype.h>
                                                    #include <stdlib.h>
                                                    
                                                    #include "Mol.h"
                                                    
                                                    /* Retourne la masse molaire de l'atome passé en paramètre */
                                                    float M_Mol(AtomList* atoms, const char* name)
                                                    {
                                                        int i;
                                                        for (i = 0; i < atoms->nbAtoms; ++i)
                                                            if (!strcmp(atoms->atom[i].name, name))
                                                                return atoms->atom[i].M;
                                                        printf("Erreur dans le calcul : atome %s inconnu\n", name);
                                                        return -1;
                                                    }
                                                    
                                                    /* Vérifie que l'expression est valide syntaxiquement */
                                                    int M_Verif(const char* exp)
                                                    {
                                                        int i;
                                                        int balance = 0;
                                                        for (i = 0; exp[i] != '\0'; ++i)
                                                        {
                                                            if (exp[i] == '(')
                                                                balance++;
                                                            else if (exp[i] == ')')
                                                            {
                                                                balance--;
                                                                if (balance < 0)
                                                                    break;
                                                            }
                                                        }
                                                        if (balance)
                                                            return -1;
                                                        return 0;
                                                    }
                                                    
                                                    
                                                    /* Renvoie la masse molaire d'une molécule passée sous forme de chaîne de caractères */
                                                    float M_MolarMass(const char* exp, AtomList* mol)
                                                    {
                                                        if (M_Verif(exp) == -1)
                                                        {
                                                            printf("Expression invalide !\n");
                                                            return 0.f;
                                                        }
                                                        int i, coeff;
                                                        double sum = 0;
                                                        char name[3] = "";
                                                    
                                                        /* On parcourt l'expression */
                                                        for (i = 0; exp[i] != '\0' && exp[i] != ')'; ++i)
                                                        {
                                                            coeff = 1;
                                                            if (isupper(exp[i]))  // Si la lettre est une majuscule, on la met dans name[0]
                                                            {
                                                                name[0] = exp[i];
                                                                if (isupper(exp[i+1]))   // On regarde si la lettre suivante est majuscule...
                                                                    name[1] = '\0';
                                                                else if (islower(exp[i+1]))    //... ou minuscule (alors on la met dans name[1] et on incrémente i).
                                                                {
                                                                    name[1] = exp[i+1];
                                                                    ++i;
                                                                }
                                                                if (isdigit(exp[i+1]))   // On regarde s'il y a un coefficient derrière.
                                                                    coeff = strtol(&exp[i+1],(char**)NULL,10);
                                                                sum += coeff * M_Mol(mol,name);
                                                            }
                                                    
                                                            /* Gestion des parenthèses */
                                                            else if (exp[i] == '(')
                                                            {
                                                                int valid = 1;
                                                                int j = i;
                                                                char exp2[50] = "";  // Sous-chaine entre les parenthèses
                                                                while(valid != 0)
                                                                {
                                                                    i++;
                                                                    /* Balance - nombre de parenthèses ouvrantes/fermantes */
                                                                        if (exp[i] == '(')
                                                                            valid++;
                                                                        else if (exp[i] == ')')
                                                                            valid--;
                                                                    if (valid)
                                                                        exp2[i-j-1] = exp[i];
                                                                }
                                                                exp2[i-j] = '\0';
                                                                if (isdigit(exp[i+1]))  // On regarde s'il y a un coefficient derrière.
                                                                    coeff = strtol(&exp[i+1],(char**)NULL,10);
                                                                sum += coeff * M_MolarMass(exp2,mol);
                                                            }
                                                        }
                                                        return sum;
                                                    }
                                                    



                                                    Code dans un seul fichier :

                                                    #include <string.h>
                                                    #include <stdio.h>
                                                    #include <ctype.h>
                                                    #include <stdlib.h>
                                                    
                                                    typedef struct
                                                    {
                                                        char name[3];   // Symbole de l'atome (ex : C, Na, Cl, etc...)
                                                        float M;       // Masse molaire de l'atome
                                                    
                                                    }Atom;
                                                    
                                                    typedef struct
                                                    {
                                                        Atom* atom;      // Tableau d'atomes
                                                        size_t nbAtoms;  // Taille du tableau
                                                    
                                                    }AtomList;
                                                    
                                                    /* Alocation et libération de la liste d'atomes */
                                                        AtomList* M_LoadFromFile(const char*);
                                                        void M_Free(AtomList*);
                                                    
                                                    /* Renvoie la masse molaire correspondant à l'atome passé en paramètre */
                                                        float M_Mol(AtomList*,const char*);
                                                    
                                                    /* Affiche la liste d'atomes */
                                                        void M_Show(AtomList*);
                                                    
                                                    /* Calcule la masse molaire d'une molécule passée en paramètre */
                                                        float M_MolarMass(const char*,AtomList*);
                                                    
                                                    /* Vérifie qu'une expression est valide */
                                                        int M_Verif(const char*);
                                                    
                                                    /* Ajoute un atome dans les données */
                                                        int M_AddAtom(const char*);
                                                    
                                                    int main()
                                                    {
                                                        AtomList* tab = M_LoadFromFile("file.txt");
                                                        M_Show(tab);
                                                        char exp[50] = {0};
                                                        while (1)
                                                        {
                                                            printf("_____________________\n"
                                                                   "     - Quit\n"
                                                                   "     - Add\n"
                                                                   "_____________________\n\n");
                                                    
                                                            scanf("%s", exp);
                                                    
                                                            /* Ajout d'un atome */
                                                            if (!strcmp(exp,"Add"))
                                                            {
                                                                if (M_AddAtom("file.txt") == -1)
                                                                    printf("Erreur lors de l'ouverture du fichier\n");
                                                                else
                                                                {
                                                                    printf("Atome bien ajouté !\n");
                                                                    tab = M_LoadFromFile("file.txt");
                                                                    M_Show(tab);
                                                                }
                                                            }
                                                            else if (!strcmp(exp,"Quit"))
                                                                break;
                                                            else
                                                                printf("  --> %f\n\n", M_MolarMass(exp, tab));
                                                        }
                                                        return 0;
                                                    }
                                                    
                                                    /* Fonction qui crée les atomes à partir du ficher dont le nom est passé en paramètre */
                                                    AtomList* M_LoadFromFile(const char* fileName)
                                                    {
                                                        /* On ouvre le fichier qui contient les données sur les atomes */
                                                        FILE* file;
                                                        if ((file = fopen(fileName, "r")) == NULL)
                                                        {
                                                            printf("Erreur lors de l'ouverture du fichier %s\n", fileName);
                                                            return NULL;
                                                        }
                                                    
                                                        /* Allocation de notre structure de données */
                                                        AtomList* atoms = NULL;
                                                        if ((atoms = malloc(sizeof(AtomList))) == NULL)
                                                        {
                                                            printf("Erreur lors de l'allocation du tableau de donnees\n");
                                                            return NULL;
                                                        }
                                                    
                                                        /* On calcule le nombre d'atomes présents dans le fichier */
                                                        atoms->nbAtoms = 0;
                                                        char s[3] = "";
                                                        float f = 0.f;
                                                        while (fscanf(file,"%s %f",s,&f) == 2)
                                                            ++atoms->nbAtoms;
                                                        rewind(file);
                                                    
                                                        /* On alloue le tableau d'atomes */
                                                        if ((atoms->atom = malloc(sizeof(Atom) * atoms->nbAtoms)) == NULL)
                                                        {
                                                            printf("Erreur lors de l'allocation du tableau de donnees\n");
                                                            return NULL;
                                                        }
                                                    
                                                        /* Enfin, on lit les informations */
                                                        int i = 0;
                                                        while (fscanf(file,"%s %f",atoms->atom[i].name,&atoms->atom[i].M) == 2)
                                                            ++i;
                                                        fclose(file);
                                                        return atoms;
                                                    }
                                                    
                                                    void M_Free(AtomList* atoms)
                                                    {
                                                        free(atoms->atom);
                                                        free(atoms);
                                                    }
                                                    
                                                    /* Affiche la liste des atomes */
                                                    void M_Show(AtomList* atoms)
                                                    {
                                                        int i;
                                                        printf("\n\n_____________________\n");
                                                        for (i = 0; i < atoms->nbAtoms; ++i)
                                                            printf("%s --> %f\n", atoms->atom[i].name, atoms->atom[i].M);
                                                        printf("_____________________\n\n");
                                                    }
                                                    
                                                    /* Fonction pour ajouter un atome */
                                                    int M_AddAtom(const char* fileName)
                                                    {
                                                        FILE* file = NULL;
                                                        if ((file = fopen(fileName,"a+")) == NULL)
                                                            return -1;
                                                    
                                                        char newAtom[3] = "";
                                                        printf("\nEntre un atome :         --> ");
                                                        scanf("%2s",newAtom);
                                                    
                                                        float M = 0.f;
                                                        printf("\nEntre sa masse molaire : --> ");
                                                        scanf("%f",&M);
                                                    
                                                        fprintf(file,"%s %f\n",newAtom,M);
                                                        fclose(file);
                                                        return 0;
                                                    }
                                                    
                                                    /* Retourne la masse molaire de l'atome passé en paramètre */
                                                    float M_Mol(AtomList* atoms, const char* name)
                                                    {
                                                        int i;
                                                        for (i = 0; i < atoms->nbAtoms; ++i)
                                                            if (!strcmp(atoms->atom[i].name, name))
                                                                return atoms->atom[i].M;
                                                        printf("Erreur dans le calcul : atome %s inconnu\n", name);
                                                        return -1;
                                                    }
                                                    
                                                    /* Vérifie que l'expression est valide syntaxiquement */
                                                    int M_Verif(const char* exp)
                                                    {
                                                        int i;
                                                        int balance = 0;
                                                        for (i = 0; exp[i] != '\0'; ++i)
                                                        {
                                                            if (exp[i] == '(')
                                                                balance++;
                                                            else if (exp[i] == ')')
                                                            {
                                                                balance--;
                                                                if (balance < 0)
                                                                    break;
                                                            }
                                                        }
                                                        if (balance)
                                                            return -1;
                                                        return 0;
                                                    }
                                                    
                                                    
                                                    /* Renvoie la masse molaire d'une molécule passée sous forme de chaîne de caractères */
                                                    float M_MolarMass(const char* exp, AtomList* mol)
                                                    {
                                                        if (M_Verif(exp) == -1)
                                                        {
                                                            printf("Expression invalide !\n");
                                                            return 0.f;
                                                        }
                                                        int i, coeff;
                                                        double sum = 0;
                                                        char name[3] = "";
                                                    
                                                        /* On parcourt l'expression */
                                                        for (i = 0; exp[i] != '\0' && exp[i] != ')'; ++i)
                                                        {
                                                            coeff = 1;
                                                            if (isupper(exp[i]))  // Si la lettre est une majuscule, on la met dans name[0]
                                                            {
                                                                name[0] = exp[i];
                                                                if (isupper(exp[i+1]))   // On regarde si la lettre suivante est majuscule...
                                                                    name[1] = '\0';
                                                                else if (islower(exp[i+1]))    //... ou minuscule (alors on la met dans name[1] et on incrémente i).
                                                                {
                                                                    name[1] = exp[i+1];
                                                                    ++i;
                                                                }
                                                                if (isdigit(exp[i+1]))   // On regarde s'il y a un coefficient derrière.
                                                                    coeff = strtol(&exp[i+1],(char**)NULL,10);
                                                                sum += coeff * M_Mol(mol,name);
                                                            }
                                                    
                                                            /* Gestion des parenthèses */
                                                            else if (exp[i] == '(')
                                                            {
                                                                int valid = 1;
                                                                int j = i;
                                                                char exp2[50] = "";  // Sous-chaine entre les parenthèses
                                                                while(valid != 0)
                                                                {
                                                                    i++;
                                                                    /* Balance - nombre de parenthèses ouvrantes/fermantes */
                                                                        if (exp[i] == '(')
                                                                            valid++;
                                                                        else if (exp[i] == ')')
                                                                            valid--;
                                                                    if (valid)
                                                                        exp2[i-j-1] = exp[i];
                                                                }
                                                                exp2[i-j] = '\0';
                                                                if (isdigit(exp[i+1]))  // On regarde s'il y a un coefficient derrière.
                                                                    coeff = strtol(&exp[i+1],(char**)NULL,10);
                                                                sum += coeff * M_MolarMass(exp2,mol);
                                                            }
                                                        }
                                                        return sum;
                                                    }
                                                    





                                                    Le code gère une imbrication de parenthèses à priori infinie, puisque il me semble que c'est tout à fait possible dans la réalité. ;)

                                                    Edit : C'est vrai que ce n'est pas précisé... Pensez-vous qu'il faudrait l'ajouter ou est-ce trop tard ?
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                    Bla bla bla
                                                      5 septembre 2011 à 1:52:42

                                                      Salut,

                                                      Voila ma version, j'aime pas ma fonction de parse mais ca marche. Elle est train bourin je me suis bien amusé avec les indices du tableau :p

                                                      Nomenclature.h
                                                      #ifndef DEF_NOMENCLATURE_H
                                                      #define DEF_NOMENCLATURE_H
                                                      
                                                      #define MAX_MOLECULE 1000
                                                      
                                                      typedef struct {
                                                          char symbole[MAX_MOLECULE][3];
                                                          float masse[MAX_MOLECULE];
                                                      
                                                          int nbElt;
                                                      }T_Nomenclature;
                                                      
                                                      /**
                                                      *   Chargement de la nomenclature a partir d'un fichier
                                                      *
                                                      *   Param:
                                                      *       T_Nomenclature : structure en charge des elements
                                                      *       char* : adresse du fichier
                                                      *   return:
                                                      *       0 : pas d'erreur
                                                      *       -1 : erreur
                                                      */
                                                      int LoadFromFile(T_Nomenclature* tn, char *fileName);
                                                      int SaveToFile(T_Nomenclature* tn, char *fileName);
                                                      
                                                      /**
                                                      *   Recherche l'element dans la nomenclature et retourne sa valeur
                                                      *
                                                      *   Param:
                                                      *       T_Nomenclature : structure en charge des elements
                                                      *       char* : element a chercher
                                                      *   return:
                                                      *       Retourne le poids
                                                      *       -1 : erreur
                                                      *
                                                      */
                                                      float GetWeight(T_Nomenclature* tn, char *search);
                                                      
                                                      void addElement(T_Nomenclature* tn, char* atome, float masse);
                                                      
                                                      void afficherNomenclature(T_Nomenclature *tn);
                                                      
                                                      
                                                      float parseMolecule(T_Nomenclature *tn, char* molecule);
                                                      #endif
                                                      

                                                      Nomenclature.c
                                                      #include <stdio.h>
                                                      #include <string.h>
                                                      #include <ctype.h>
                                                      
                                                      #include "nomenclature.h"
                                                      
                                                      int LoadFromFile(T_Nomenclature* tn, char *fileName){
                                                          FILE *f = NULL;
                                                          tn->nbElt = 0;
                                                      
                                                          if((f = fopen(fileName, "r")) != NULL){
                                                              while(tn->nbElt < MAX_MOLECULE && fscanf(f, "%s %f", tn->symbole[tn->nbElt], &tn->masse[tn->nbElt]) != EOF){
                                                                  tn->nbElt++;
                                                              }
                                                              fclose(f);
                                                              return 0;
                                                          }
                                                          else
                                                              return -1;
                                                      
                                                      }
                                                      
                                                      int SaveToFile(T_Nomenclature* tn, char *fileName){
                                                          FILE *f = NULL;
                                                          int i = 0;
                                                      
                                                          if((f = fopen(fileName, "w+")) != NULL){
                                                              for(; i < tn->nbElt; i++){
                                                                  fprintf(f, "%s %f\n", tn->symbole[i], tn->masse[i]);
                                                              }
                                                              fclose(f);
                                                              return 0;
                                                          }
                                                          else
                                                              return -1;
                                                      }
                                                      
                                                      void afficherNomenclature(T_Nomenclature *tn){
                                                          int i = 0;
                                                          for(; i < tn->nbElt; i++)
                                                              printf("[%d] : %s %f\n", i, tn->symbole[i], tn->masse[i]);
                                                      }
                                                      
                                                      float GetWeight(T_Nomenclature* tn, char *search){
                                                          int i = 0;
                                                          for(; i < tn->nbElt; i++){
                                                              if( strcmp(tn->symbole[i], search) == 0 )
                                                                  return tn->masse[i];
                                                          }
                                                      
                                                          return -1.0;
                                                      }
                                                      
                                                      void addElement(T_Nomenclature* tn, char* atome, float masse){
                                                          if(tn->nbElt < MAX_MOLECULE){
                                                              strcpy(tn->symbole[tn->nbElt], atome);
                                                              tn->masse[tn->nbElt] = masse;
                                                              tn->nbElt++;
                                                          }
                                                      }
                                                      
                                                      float parseMolecule(T_Nomenclature *tn, char* molecule){
                                                          int i = 0, coef = 1;
                                                          float total = 0, res;
                                                          char tmp[3] = "";
                                                      
                                                          for(; molecule[i] != '\0'; i++){
                                                              coef = 1;
                                                              if(molecule[i] == '('){
                                                                  int offset = 1;
                                                                  char parenthese[1024] = "";
                                                                  while(molecule[i+offset] != ')')
                                                                      offset++;
                                                                  strncpy(parenthese, &molecule[i+1], offset-1);
                                                                  coef = molecule[i+offset+1] - '0';
                                                                  res = parseMolecule(tn, parenthese);
                                                                  i += offset+1;
                                                              }
                                                      
                                                              else {
                                                                  if(islower(molecule[i+1]) != 0){
                                                                      strncpy(tmp, &molecule[i], 2);
                                                      
                                                                      if(isdigit(molecule[i+2]) != 0){
                                                                          coef = molecule[i+2] - '0';
                                                                          i++;
                                                                      }
                                                                      i++;
                                                                  }
                                                                  else{
                                                                      strncpy(tmp, &molecule[i], 1);
                                                                      tmp[1] ='\0';
                                                                      if(isdigit(molecule[i+1]) != 0){
                                                                          coef = molecule[i+1] - '0';
                                                                          i++;
                                                                      }
                                                                  }
                                                      
                                                                  if((res = GetWeight(tn, tmp)) == -1)
                                                                      return -1.0;
                                                              }
                                                              total += (res * coef);
                                                          }
                                                          return total;
                                                      }
                                                      

                                                      Main.c
                                                      #include <stdio.h>
                                                      #include <stdlib.h>
                                                      
                                                      #include "nomenclature.h"
                                                      
                                                      
                                                      int main()
                                                      {
                                                          // Init de la nomenclature
                                                          T_Nomenclature tn;
                                                          int choix = -1;
                                                      
                                                          if(LoadFromFile(&tn, "nomenclature.txt") == -1){
                                                              printf("Erreur de chargement du fichier");
                                                              exit(EXIT_FAILURE);
                                                          }
                                                      
                                                          //Le menu
                                                          while(choix != 0){
                                                              printf("\n\n\n\t\t\t1 - Calculer la masse molaire\n");
                                                              printf("\t\t\t2 - Ajouter d'un atome\n\n\n");
                                                              printf("\t\t\t0 - Quitter\n\n");
                                                              printf("Que faire ? ");
                                                      
                                                              scanf("%d", &choix);
                                                      
                                                              if(choix == 1){
                                                                  char molecule[1024];
                                                                  printf("Saisir le nom de la molecule : ");
                                                                  scanf("%s", molecule);
                                                      
                                                                  printf("La masse molaire de : %s est de %f\n\n", molecule, parseMolecule(&tn, molecule));
                                                              }
                                                              else if(choix == 2){
                                                                  char atome[3];
                                                                  float masse;
                                                                  printf("Saisir l'atome a ajouter (nom masse)");
                                                                  scanf("%s %f", atome, &masse);
                                                                  addElement(&tn, atome, masse);
                                                      
                                                              }
                                                          }
                                                      
                                                          //Et pour finir on sauvegarde le fichier pour prendre en compte les modifs eventuelles
                                                          SaveToFile(&tn, "nomenclature.txt");
                                                          return 0;
                                                      }
                                                      
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        5 septembre 2011 à 1:56:51

                                                        Voilà mon code :

                                                        #include <errno.h>
                                                        #include <ctype.h>
                                                        #include <math.h>
                                                        #include <stdio.h>
                                                        #include <stdlib.h>
                                                        #include <string.h>
                                                        
                                                        #define MOL_FILE "mols.txt"
                                                        
                                                        enum {
                                                          N_MAX = 100,
                                                          SZ_NAME = 50
                                                        };
                                                        
                                                        enum {
                                                          E_NOERR,
                                                          E_PARF,
                                                          E_PARO,
                                                          E_FCOR,
                                                          E_MOLINC,
                                                          E_WRNUM,
                                                          E_COEFF,
                                                          E_CINC,
                                                          E_AFFEC,
                                                          E_NOEX,
                                                          E_NERR
                                                        };
                                                        
                                                        char * errors[] = {
                                                          "",
                                                          "Erreur de syntaxe: Parenthèse fermante manquante.",
                                                          "Erreur de syntaxe: Parenthèse ouvrante manquante.",
                                                          "Fichier corrompu.",
                                                          "Molécule inconnue.",
                                                          "Mauvais coefficient.",
                                                          "Coefficient non précédé d'une molécule.",
                                                          "Cacactère inconnu.",
                                                          "Erreur d'affectation.",
                                                          "Erreur de syntaxe:  Epression manquante dans entre les parenthèses."
                                                        };
                                                        
                                                        typedef struct llist_val_s {
                                                          struct llist_val_s * nxt;
                                                          char name[3];
                                                          double val;
                                                        } llist_val;
                                                        
                                                        typedef struct llist_s {
                                                          llist_val * begin;
                                                          llist_val * end;
                                                        } llist;
                                                        
                                                        
                                                        int g_err = E_NOERR;
                                                        
                                                        int aprintf(char * s) {
                                                          if (s)
                                                            return fprintf(stderr, "%s\n", s);
                                                          else
                                                            return fprintf(stderr, "Erreur inconnue.\n");
                                                        }
                                                        
                                                        void eprintf(char * s) {
                                                          aprintf(s);
                                                          exit(EXIT_FAILURE);
                                                        }
                                                        
                                                        void clrErr(void) {
                                                          g_err = E_NOERR;
                                                        }
                                                        
                                                        void setErr(int err) {
                                                          if (err < E_NOERR || err >= E_NERR)
                                                            return;
                                                          g_err = err;
                                                        }
                                                        
                                                        int getErr(void) {
                                                          return g_err;
                                                        }
                                                        
                                                        void printErr(void) {
                                                          if (g_err > E_NOERR && g_err < E_NERR)
                                                            aprintf(errors[g_err]);
                                                        }
                                                        
                                                        llist_val * searchLlist(llist * l, char * name) {
                                                          llist_val * tmp;
                                                          
                                                          if (l == NULL)
                                                            return NULL;
                                                          
                                                          tmp = l->begin;
                                                          while (tmp != NULL && strcmp(tmp->name, name)) {
                                                            tmp = tmp->nxt;
                                                          }
                                                          if (tmp == NULL)
                                                            return NULL;
                                                          
                                                          return tmp;
                                                        }
                                                        
                                                        llist * pushLlist(llist * l, llist_val * val) {
                                                          llist_val * new;
                                                          
                                                          if (l == NULL)
                                                            return NULL;
                                                          
                                                          new = malloc(sizeof *new);
                                                          if (!new) {
                                                            perror("malloc");
                                                            return NULL;
                                                          }
                                                          
                                                          new->nxt = NULL;
                                                          new->val = val->val;
                                                          strncpy(new->name, val->name, 3);
                                                          
                                                          if (l->begin == NULL) {
                                                            l->begin = new;
                                                            l->end = new;
                                                          }
                                                          else {
                                                            l->end->nxt = new;
                                                            l->end = new;
                                                          }
                                                          return l;
                                                        }
                                                        
                                                        llist * popLlist(llist * l) {
                                                          llist_val * tmp;
                                                          
                                                          if (l == NULL || l->begin == NULL)
                                                            return NULL;
                                                          
                                                          tmp = l->begin->nxt;
                                                          free(l->begin);
                                                          l->begin = tmp;
                                                          return l;
                                                        }
                                                        
                                                        void popAllLlist(llist * l) {
                                                          llist * tmp;
                                                          
                                                          if (l == NULL || l->begin == NULL)
                                                            return;
                                                          
                                                          tmp = l;
                                                          while ((tmp = popLlist(tmp)))
                                                            ;
                                                          free(l);
                                                        }
                                                        
                                                        char * skipSpace(char * s) {
                                                          while (isspace(*s))
                                                            s++;
                                                          return s;
                                                        }
                                                        
                                                        void delEnter(char * s) {
                                                          char * c = strchr(s, '\n');
                                                          
                                                          if (c)
                                                            *c = '\0';
                                                        }
                                                        
                                                        double getVar(llist * mol, char ** s) {
                                                          llist_val * val;
                                                          char t[3] = "";
                                                          
                                                          if (mol == NULL || s == NULL)
                                                            return nan("");
                                                          
                                                          if (isalpha(**s) && isupper(**s)) {
                                                            t[0] = **s;
                                                            (*s)++;
                                                            if (isalpha(**s) && islower(**s)) {
                                                              t[1] = **s;
                                                              (*s)++;
                                                            }
                                                          }
                                                          else {
                                                            setErr(E_MOLINC);
                                                            return nan("");
                                                          }
                                                          
                                                          val = searchLlist(mol, t);
                                                          if (val == NULL) {
                                                            setErr(E_MOLINC);
                                                            return nan("");
                                                          }
                                                          
                                                          return val->val;
                                                        }
                                                        
                                                        double evaluate(llist * mol, char * s, char * t) {
                                                          double res = 0.0;
                                                          double tmp = 0.0;
                                                          char u[1] = { 0 };
                                                          
                                                          while (*s) {
                                                            s = skipSpace(s);
                                                            
                                                            if (getErr() != E_NOERR || *s == '\0')
                                                              break;
                                                            else if (*s == '(') {
                                                              res += tmp;
                                                              *u = '(';
                                                              tmp = evaluate(mol, s + 1, u);
                                                              
                                                              if (getErr() != E_NOERR)
                                                                return 0.0;
                                                              else if (*u != ')') {
                                                                setErr(E_PARF);
                                                                return 0.0;
                                                              }
                                                              *u = 0;
                                                              while (*s != ')')
                                                                s++;
                                                              *s = ' ';
                                                            }
                                                            else if (*s == ')') {
                                                              if (t == NULL || *t != '(') {
                                                                setErr(E_PARO);
                                                                return 0.0;
                                                              }
                                                              else if (*(s - 1) == '(') {
                                                                setErr(E_NOEX);
                                                                return 0.0;
                                                              }
                                                              *t = ')';
                                                              break;
                                                            }
                                                            else if (isalpha(*s) && isupper(*s)) {
                                                              res += tmp;
                                                              tmp = getVar(mol, &s);
                                                            }
                                                            else if (isdigit(*s)) {
                                                              double n = strtol(s, &s, 10);
                                                              
                                                              if (tmp < 1e-6) {
                                                                setErr(E_COEFF);
                                                                return 0.0;
                                                              }
                                                              
                                                              if (s == NULL) {
                                                                setErr(E_WRNUM);
                                                                return 0.0;
                                                              }
                                                              res += (n * tmp);
                                                              tmp = 0.0;
                                                            }
                                                            else if (*s == ' ') {
                                                              s++;
                                                            }
                                                            else {
                                                              setErr(E_CINC);
                                                              return 0.0;
                                                            }
                                                          }
                                                          
                                                          return res + tmp;
                                                        }
                                                        
                                                        int checkQuit(char * s) {
                                                          return strcmp(s, "q") == 0 || strcmp(s, "quit") == 0;
                                                        }
                                                        
                                                        int checkAffect(llist * mol, char * s, char * t) {
                                                          char * p = strchr(s, '=');
                                                          llist_val * val;
                                                          
                                                          if (p == NULL)
                                                            return 0;
                                                          
                                                          s = skipSpace(s);
                                                          if (isalpha(*s) && isupper(*s)) {
                                                            t[0] = *s;
                                                            t[1] = '\0';
                                                            *s = ' ';
                                                            s++;
                                                            if (isalpha(*s) && islower(*s)) {
                                                              t[1] = *s;
                                                              t[2] = '\0';
                                                              *s = ' ';
                                                              s++;
                                                            }
                                                          }
                                                          else {
                                                            setErr(E_AFFEC);
                                                            return -1;
                                                          }
                                                          
                                                          while (*s && *s != '=') {
                                                            if (*s != ' ') {
                                                              setErr(E_AFFEC);
                                                              return -1;
                                                            }
                                                            *s = ' ';
                                                            s++;
                                                          }
                                                          *s = ' ';
                                                          
                                                          val = searchLlist(mol, t);
                                                          if (val != NULL) {
                                                            setErr(E_AFFEC);
                                                            return -1;
                                                          }
                                                          
                                                          return 1;
                                                        }
                                                        
                                                        int prompt(llist * mol) {
                                                          double tmp;
                                                          int done = 0;
                                                          char s[N_MAX] = "";
                                                          char t[N_MAX] = "";
                                                          char u[3] = "";
                                                          int ret = 0;
                                                          
                                                          while (!done) {
                                                            clrErr();
                                                            
                                                            printf(">>> ");
                                                            if (fgets(s, N_MAX, stdin) == NULL) {
                                                              perror("fgets");
                                                              continue;
                                                            }
                                                            delEnter(s);
                                                            
                                                            if (checkQuit(s))
                                                              break;
                                                            
                                                            ret = checkAffect(mol, s, u);
                                                            strcpy(t, s);
                                                            if (ret == 1) {
                                                              char * p;
                                                              tmp = strtod(skipSpace(s), &p);
                                                              
                                                              if (p == NULL)
                                                                perror("strtod");
                                                              while (*p && *p == ' ')
                                                                p++;
                                                              if (*p)
                                                                setErr(E_AFFEC);
                                                            }
                                                            else if (ret == 0)
                                                              tmp = evaluate(mol, s, NULL);
                                                            
                                                            if (getErr() != E_NOERR) {
                                                              printErr();
                                                            }
                                                            else if (ret == 0) {
                                                              printf("-: %s = %f\n", skipSpace(t), tmp);
                                                            }
                                                            else if (ret == 1) {
                                                              llist_val val;
                                                              
                                                              strcpy(val.name, u);
                                                              val.val = tmp;
                                                              mol = pushLlist(mol, &val);
                                                              printf("var: %s = %f\n", u, tmp);
                                                            }
                                                          }
                                                          
                                                          return 0;
                                                        }
                                                        
                                                        llist * getMolInFile(void) {
                                                          FILE * f;
                                                          llist_val tmp = { NULL, "", 0.0 };
                                                          llist * mol;
                                                          
                                                          mol = malloc(sizeof *mol);
                                                          if (mol == NULL) {
                                                            perror("malloc");
                                                            return NULL;
                                                          }
                                                          
                                                          f = fopen(MOL_FILE, "r");
                                                          if (f == NULL) {
                                                            perror("fopen");
                                                            return mol;
                                                          }
                                                          
                                                          while (fscanf(f, "%2s %lf", tmp.name, &tmp.val) == 2)
                                                            mol = pushLlist(mol, &tmp);
                                                          
                                                          if (!feof(f))
                                                            aprintf(errors[E_FCOR]);
                                                          fclose(f);
                                                          
                                                          return mol;
                                                        }
                                                        
                                                        int writeMolInFile(llist * mol) {
                                                          FILE * f;
                                                          llist_val * tmp;
                                                          
                                                          f = fopen(MOL_FILE, "w");
                                                          if (f == NULL) {
                                                            perror("fopen");
                                                            return -1;
                                                          }
                                                          
                                                          tmp = mol->begin;
                                                          while (tmp) {
                                                            fprintf(f, "%s %f\n", tmp->name, tmp->val);
                                                            tmp = tmp->nxt;
                                                          }
                                                          fclose(f);
                                                          
                                                          return 0;
                                                        }
                                                        
                                                        int main(void) {
                                                          llist * mol = getMolInFile();
                                                          
                                                          if (mol == NULL)
                                                            return EXIT_FAILURE;
                                                          
                                                          prompt(mol);
                                                          writeMolInFile(mol);
                                                          popAllLlist(mol);
                                                          return EXIT_SUCCESS;
                                                        }
                                                        

                                                        Un exemple d'exécution :

                                                        >>> CO2
                                                        -: CO2 = 44.009000
                                                        >>> COO
                                                        -: COO = 44.009000
                                                        >>> (CO)2
                                                        -: (CO)2 = 56.020000
                                                        >>> C2O2
                                                        -: C2O2 = 56.020000
                                                        >>> (CH4)2
                                                        -: (CH4)2 = 32.085200
                                                        >>> V = 50.942
                                                        var: V = 50.942000
                                                        >>> V2
                                                        -: V2 = 101.884000
                                                        >>> q

                                                        Il gère les affectations, les parenthèses et cie. Si le fichier n'existe pas, on continue tout de même (bah oui on peut vouloir rentrer les éléments à la main non ?).
                                                        Enjoy. :)

                                                        Edit: bug de () fix'd. :)

                                                        PS: Si vous pouviez éviter d'utiliser plusieurs fichiers pour l'exo, ce serait pas mal, je n'en vois pas trop l'utilité. Ca permettrait de faciliter la lecture et la compilation pour donner des commentaires. :)
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          5 septembre 2011 à 1:59:14

                                                          Désolé d'autre langage mon corrompu :s, je crée un type et les fonctions associé par fichier
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            5 septembre 2011 à 13:08:32

                                                            Citation : Taurre

                                                            @yoch: pourquoi utilisé un pointeur de pointeur comme premier argument de ta fonction eval? Étant donné l'utilisation que tu en fais un pointeur n'aurait-il pas suffit?


                                                            grilled by GurneyH ;)

                                                            Citation : Taurre


                                                            Aussi, par curiosité, dans ta fonction chargement_fichier, tu remplis une liste chaînées avec les atomes et leurs masses contenus dans le fichier pour la copier ensuite dans un tableau et la détruire. Est-ce pour éviter deux lectures dans le fichier (une pour compter le nombre de ligne et une pour remplir le tableau)?


                                                            Oui, c'est bien ça. :)
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              5 septembre 2011 à 16:58:34

                                                              Citation : yoch

                                                              Citation : Taurre


                                                              Aussi, par curiosité, dans ta fonction chargement_fichier, tu remplis une liste chaînées avec les atomes et leurs masses contenus dans le fichier pour la copier ensuite dans un tableau et la détruire. Est-ce pour éviter deux lectures dans le fichier (une pour compter le nombre de ligne et une pour remplir le tableau)?


                                                              Oui, c'est bien ça. :)



                                                              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 ?
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter
                                                              Bla bla bla

                                                              [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