Merci Fender.
J'ai supprimé le return 0 (tellement gros que je ne voyais rien).
J'ai trouvé pourquoi mon tableau ne se remplissait pas bien, j'avais fais un while(fgetc(pfichier) != EOF) au lieu d'un do while. J'avais déjà fais cette erreur dans le TP du pendu!!! Maintenant ça fonctionne bien.
J'ai donc fini mon niveau 1, temps passé 1 journée après un premier programme fonctionnel mais catastrophique à lire et à modifier.
Voici le code:
/*********************************************************************
* *
* Ce programme permet le calcul des masses molaires moléculaires *
* *
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "fonction.h"
int main(int argc, char *argv[])
{
char molecule[100] = "";
char c_molecule[100] = {0};
char atome[3] = {0};
int nbElement = 0;
int len = 0;
int i = 0;
double masseAtome = 0;
double masseMolaire = 0;
Element ElementTab[112]; // creation d'un tableau d'elements de 112 elements
/************************************************************
* *
* Recuperation de la molecule saisie par l'utilisateur *
* *
************************************************************/
printf("entrez une molecule:\n\n");
printf("--> ");
scanf("%s", molecule);
printf("\n\n");
//printf("la molecule choisie vaut: %s\n\n", molecule);
nbElement = get_Tab(ElementTab);
//printf("la table est composee de %d elements\n\n", nbElement);
/************************************************************
* *
* Structure de la molecule *
* *
************************************************************/
len = strlen(molecule);
strcpy(c_molecule, molecule);
while(i < len){
if(isupper(c_molecule[i]) && islower(c_molecule[i+1])){ // Si l'atome a deux caracteres
atome[0] = c_molecule[i];
atome[1] = c_molecule[i+1];
//printf("atome vaut %s\n\n", atome);
masseAtome = validAtome(atome, ElementTab, nbElement);
masseMolaire = masseMolaire + masseAtome;
i += 2;
}
else{ // si l'atome a qu'un seul caractere
atome[0] = c_molecule[i];
//printf("atome vaut %s\n\n", atome);
masseAtome = validAtome(atome, ElementTab, nbElement);
masseMolaire = masseMolaire + masseAtome;
i++;
}
}
if(masseAtome == -1){
printf("Impossible de calculer la masse molaire moleculaire\n\n");
}
else{
printf("---> La masse molaire moleculaire de %s est %f g.mol-1.\n\n", molecule, masseMolaire);
}
return 0;
}
/*******************************************************************
* *
* Recuperation des donnees du fichier fileElement dans un tableau *
* La fonction retourne le nombre d'element: nbElementTab *
* *
*******************************************************************/
int get_Tab(Element *pElementTab) //int get_Tab(Element ElementTab[])
{
int nbElementTab = 0;
FILE *pfichier = fopen("fileElement.txt", "r");
if(pfichier != NULL){
//printf("ouverture reussi\n\n");
do{
fscanf(pfichier, "%s %lf", pElementTab[nbElementTab].nom_Atome, &pElementTab[nbElementTab].masse_Atome);
nbElementTab++;
}
while(fgetc(pfichier) != EOF);
rewind(pfichier);
fclose(pfichier);
//printf("Premier element %s a une masse de %f\n\n", pElementTab[0].nom_Atome, pElementTab[0].masse_Atome);
}
else{
printf("Fichier fileElement.txt introuvable\n\n");
return 0;
}
return nbElementTab;
}
/*******************************************************************
* *
* Verification de l'existance des atomes dans TabElement *
* Elle renvoie la masse de l'atome s'il est présent *
* *
*******************************************************************/
double validAtome(char *patome, Element *pElementTab, int nb)
{
double atomeTab = 0;
int i = 0;
while(strcmp(patome, pElementTab[i].nom_Atome) != 0 && i < nb){
i++;
}
if(strcmp(patome, pElementTab[i].nom_Atome) == 0){
atomeTab = pElementTab[i].masse_Atome;
}
else{
printf("L'atome %s n'est pas dans la table d'elements entree\n\n", patome);
atomeTab = -1;
}
return atomeTab;
}
Ma participation pour le niveau 4 (je ne vois pas vraiment l'intérêt du niveau 5).
/* zmol.c - C99 */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Nom du fichier de configuration. Il contient en theorie, sur chaque *
* nouvelle ligne, une chaine de la forme : *
* symbole masse *
* Le nombre de lignes doit etre specifie par la constante NB_ATOMS */
#define FILE_NAME "mol.txt"
/* Nombre d'atomes existants. Le nombre d'atomes du fichier de *
* configuration ne doit pas etre superieur a cette constante. Sinon, les*
* derniers atomes du fichier seront consideres comme inconnus. La *
* classification contient actuellement 118 atomes, donc merci de ne pas *
* inventer d'atomes... */
#define NB_ATOMS 118
/* Taille maximale d'un atome. Dans notre cas, les symboles des atomes *
* ne depasseront pas trois caracteres (plus le '\0' final) */
#define ATOM_MAX_LEN 4
/* Classification periodique des elements, qui indique pour chaque atome *
* son symbole et sa masse. Il est preferable que le nombre d'atomes du *
* fichier soit egal a la constante symbolique NB_ATOMS. */
static struct Atom {
char name[ATOM_MAX_LEN];
double mass;
} ptable[NB_ATOMS];
/* Enumeration de constantes representant les differentes erreurs pouvant*
* se produire lors de l'execution du programme */
enum error_e {
ERROR_BRACKETS,
ERROR_UNKNATOM,
ERROR_LONGATOM,
ERROR_UNKNSYMB,
ERROR_MEMALLOC,
ERROR_CLOSEFIL,
ERROR_OPENFILE
};
/* Nombre d'atomes effectivement lus dans le fichier de configuration. *
* Doit etre inferieur a la constante NB_ATOMS */
static size_t ptable_size;
/* Charge la classification periodique des elements dans la structure *
* d'atomes ptable. Retourne le nombre d'elements contenus dans le *
* fichier. */
static size_t load_ptable(const char *filename);
/* Retourne la masse moleculaire de l'atome courant de la molecule passee*
* sous forme de chaine de caractere en parametre. */
static double get_atommass(char **molecule);
/* Retourne la masse moleculaire de la molecule passee sous forme de *
* chaine de caractere en parametre. */
static double get_molmass(char **molecule);
/* Recupere la molecule entree par l'utilisateur. Retourne le nombre *
* d'octets effectivement lus. */
static size_t get_molecule(char **molecule);
/* Teste le parenthesage de la chaine de caractere representant la *
* molecule passee en parametre. Renvoie 1 si l'expression est *
* correctement parenthesee, ou 0 sinon. */
static int test_bracks(const char *molecule);
/* Affiche la description de l'erreur, correspondant a une serie *
* d'enumeration de type enum error_e. */
static void print_error(enum error_e error);
int main(void) {
int ret = EXIT_FAILURE;
ptable_size = load_ptable(FILE_NAME);
if (ptable_size) {
size_t ret_alloc;
char *molecule = NULL;
do {
ret_alloc = get_molecule(&molecule);
if (ret_alloc) {
char *p = molecule;
if (!test_bracks(molecule))
print_error(ERROR_BRACKETS);
else
printf("%f g/mol\n", get_molmass(&p));
free(molecule);
molecule = NULL;
}
} while (ret_alloc != 0);
}
return ret;
}
static double get_atommass(char **molecule) {
size_t n = 1;
const char *p = *molecule;
while (islower(*++*molecule))
++n;
if (n < ATOM_MAX_LEN) {
size_t i = 0;
char atom[ATOM_MAX_LEN] = "";
strncpy(atom, p, n);
for (i = 0; i < ptable_size; i++)
if (!strncmp(atom, ptable[i].name, n))
return ptable[i].mass;
print_error(ERROR_UNKNATOM);
}
else
print_error(ERROR_LONGATOM);
return 0;
}
static double get_molmass(char **molecule) {
double ret = 0.0;
double tmp = 0.0;
while (**molecule) {
if (isupper(**molecule))
ret += tmp = get_atommass(molecule);
else if (isdigit(**molecule))
ret += tmp *= strtol(*molecule, molecule, 10) - 1;
else if (**molecule == '(') {
++*molecule;
tmp = get_molmass(molecule);
ret += tmp;
}
else if (**molecule == ')') {
++*molecule;
break;
}
else {
if (!isspace(**molecule))
print_error(ERROR_UNKNSYMB);
++*molecule;
}
}
return ret;
}
static size_t get_molecule(char **molecule) {
size_t i = 0;
size_t n = 0;
int c;
fprintf(stdout, "> ");
do {
c = getchar();
if (i + 1 >= n) {
char *p = NULL;
n += 512;
p = realloc(*molecule, n);
if (!p) {
print_error(ERROR_MEMALLOC);
free(molecule);
return i;
}
*molecule = p;
}
(*molecule)[i++] = (char)c;
} while (c != '\n' && c != EOF);
(*molecule)[i - 1] = '\0';
return i;
}
static size_t load_ptable(const char *filename) {
size_t i = 0;
FILE *f;
if ((f = fopen(filename, "r"))) {
while (fscanf(f, "%s %lf", ptable[i].name, &ptable[i].mass) == 2 &&
i < NB_ATOMS) {
++i;
}
if (fclose(f) == EOF)
print_error(ERROR_CLOSEFIL);
}
else
print_error(ERROR_OPENFILE);
return i;
}
static int test_bracks(const char *molecule) {
int b = 0;
for (; *molecule; ++molecule) {
if (*molecule == '(')
++b;
else if (*molecule == ')') {
if (--b < 0)
return 0;
}
}
return !b;
}
static void print_error(enum error_e error) {
fprintf(stderr, "Erreur - ");
switch (error) {
case ERROR_BRACKETS:
fprintf(stderr, "expression mal parenthésée.");
break;
case ERROR_UNKNATOM:
fprintf(stderr, "atome inconnu");
break;
case ERROR_LONGATOM:
fprintf(stderr, "atome trop long");
break;
case ERROR_UNKNSYMB:
fprintf(stderr, "symbole inconnu");
break;
case ERROR_MEMALLOC:
fprintf(stderr, "allocation mémoire");
break;
case ERROR_CLOSEFIL:
fprintf(stderr, "fermeture fichier");
break;
case ERROR_OPENFILE:
fprintf(stderr, "ouverture fichier");
break;
default:
fprintf(stderr, "Inconnu");
break;
}
putchar('\n');
}
Je suis ouvert à vos commentaires.
Edit 1 : petite correction au niveau de la fonction get_molmass.
Edit 2 : suppression des fprintf(stdout, /* ... */); pour des printf, car cela peut surprendre plus qu'autre chose dans ce cas précis.
× 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.
" Celui qui aime à apprendre est bien près du savoir " Confucius