Interpreteur de calcul intégré à la saisie au clavier

Soyez le premier à donner votre avis sur cette source.

Snippet vu 7 056 fois - Téléchargée 30 fois

Contenu du snippet

Cette fonction n'est pas une calculatrice en soi, elle se contente d'interpréter un calcul dans le cadre d'une saisie de valeur numérique par l'utilisateur

Source / Exemple :


#define NA 12345678 /*Valeur d'erreur renvoyée pour les calculs*/
#define defo 1111111 /*Valeur indiquant une saisi par défaut pour les calculs*/

float interpret_calc()
{
    char *chaine, *signes;
    float *nombres;
    int i,j,k,b1=0,b2=0,b3,nbparo=0,nbparf=0,nbmuldiv=0,nbt=0,index=0;
    int *indexparo, *indexparf, *indexmuldiv;
    float temp,nb1,nb2;
    chaine = chaine_din();    /*Saisi le calcul*/
    if (strstr(chaine,"q") != NULL || strstr(chaine,"Q") != NULL)
    {    /*Quitte si q*/
        free(chaine);
        exit(0);
    }
    i = strlen(chaine);    /*i = taille complète du calcul*/
    if (!i)    /*Si la chaine est vide, renvoi une erreur*/
        return (defo);
    ER = nombres = calloc(i,sizeof(float));
    Erreur(1);
    ER = signes = calloc(i,sizeof(char));
    Erreur(1);
    ER = indexparo = calloc((int)i/2,sizeof(int));
    Erreur(1);
    ER = indexparf = calloc((int)i/2,sizeof(int));
    Erreur(1);
    ER = indexmuldiv = calloc((int)i/2,sizeof(int));
    Erreur(1);
    for (i=0;i<strlen(chaine);i++)
    {    /*Change , en .*/
        if (chaine[i] == ',')
            chaine[i] = '.';
    }
    while (strlen(chaine))
    {
        if (isdigit(chaine[0]) > 0)
        {        /*Si le premier caractère est un chiffre*/
            b1=1;        /*indique nombres*/
            nombres[index] = atof(chaine);    /*Saisi valeur et stocke dans le tableau 1*/
            if (b2==1)            /*Valeur négative*/
                nombres[index]*=-1;
            b2=0;
            signes[index++] = '0';      /*Met 0 dans le tableau 2*/
            nbt++;
            while (isdigit(chaine[0]) || chaine[0] == '.')
            {            /*retire la valeur saisie de la string*/
                for (i=0;i<strlen(chaine);i++)
                    chaine[i] = chaine[i+1];
            }
        }
        else
        {        /*Donc si signe de calcul*/
            if (chaine[0] == '-' && b1 == 0)
            {            /*Si un - se trouve apres un autre signe*/
                b2=1;            /*Nombre négatif*/
                nombres[index] = 0;     /*Place 0 et # dans les tableaux*/
                signes[index++] = '#';
                nbt++;
            }
            else
            {    /*Si c'est pas un nb négatif*/
                b1=0;      /*Indique signe*/
                signes[index] = chaine[0];   /*Place 0 dans le tableau 1 et le signe dans le tableau 2*/
                nombres[index++] = 0;
                nbt++;
                switch (signes[index-1])
                {        /*reperage du signe utilisé*/
                    case '*':
                    case '/':
                        indexmuldiv[nbmuldiv] = index-1;
                        nbmuldiv+=1;
                        break;
                    case '(':
                        indexparo[nbparo] = index-1;
                        nbparo+=1;
                        break;
                    case ')':
                        indexparf[nbparf] = index-1;
                        nbparf+=1;
                        break;
                    case '+':
                    case '-':
                        break;
                    default:   /*Si aucun signe n'est reconnu*/
                        printf("Erreur: le symbole %c n'est pas reconnu", signes[index-1]);
                        free(nombres);free(signes);free(indexparo);free(indexparf);free(indexmuldiv);free(chaine);
                        Pause();
                        return NA;
                }
            }
            for (i=0;i<strlen(chaine);i++)
                chaine[i] = chaine[i+1]; /*Retire le signe de la string*/
        }
    }
    if (nbparo != nbparf)
    {    /*Si ya pa autant de parenthèses ouvrantes et fermantes*/
        printf("Erreur: %d parenth%cses ouvertes, %d parenth%cses fermees", nbparo, accchar('è') ,nbparf, accchar('è'));
        free(nombres);free(signes);free(indexparo);free(indexparf);free(indexmuldiv);free(chaine);
        Pause();
        return NA;
    }
    do
    {
        if (nbparo) /*Si ya des parentheses*/
        {
            b2 = indexparf[0];     /*borne 2 à la 1ere parenthèse fermante*/
            for (i=0;i<nbparo;i++)
            {
                if (indexparo[i] < b2)  /*Si la parenthese ouvrante est avant la fermante*/
                    b1 = indexparo[i];  /*borne 1 à la parenthese*/
            }                    /*Donc les 2 bornes se resserrent sur les plus profondes parenthèses*/
            signes[b1] = '#';   /*Place des # à la place des parenthèses utilisées*/
            signes[b2] = '#';
            nbparo--;
            for (i=b1;i<nbparo;i++)     /*Supprime les index des parenthèses utilisées*/
                indexparo[i] = indexparo[i+1];
            for (i=0;i<nbparo;i++)
                indexparf[i] = indexparf[i+1];
        }
        else
        {        /*Si ya pas de parenthèses, ou plus de parenthèses*/
            b1 = -1;     /*Bornes à -1 et max*/
            b2 = nbt;
        }
        for (i=0;i<nbmuldiv;i++)
        {        /*Boucle sur le nombre de signes * ou / */
            if (indexmuldiv[i] > b1 && indexmuldiv[i] < b2)
            {            /*Si le signe se trouve entre les 2 bornes*/
                b3 = indexmuldiv[i];    /*Borne 3 à l'emplacement du signe*/
                indexmuldiv[i] = -1;    /*index du signes à -1*/
            }
            else
                b3 = -1;  /*sinon borne 3 à -1*/
            if (b3 != -1)
            {    /*Si la borne 3 est utilisée*/
                for(j=b3-1;j>b1;j--)
                {       /*Saisi valeur 1*/
                    if (nombres[j] || (!nombres[j] && signes[j] == '0'))
                    {      /*Si le nombre est différent de 0 ou qu'il est égal à 0 et que le tab 2 contient aussi 0*/
                        nb1 = nombres[j];
                        signes[j] = '#';   /*Place 0 et # dans les tableaux*/
                        nombres[j] = 0;
                        break;
                    }
                }
                for(k=b3+1;k<b2;k++)
                {       /*Saisi valeur 2... idem*/
                    if (nombres[k] || (!nombres[k] && signes[k] == '0'))
                    {
                        nb2 = nombres[k];
                        signes[k] = '#';
                        nombres[k] = 0;
                        break;
                    }
                }
                if (k==b2)
                {   /*Si aucune valeur n'est trouvée pour nb2*/
                    nombres[j] = nb1;   /*Replace nb1 dans le tableau 1, puis met 0 dans le tableau 2*/
                    signes[j] = '0';
                }
                if (signes[b3] == '*')
                    temp = nb1*nb2;      /*Multiplication*/
                if (signes[b3] == '/')
                {
                    if (nb2 == 0)
                    {
                        puts("Erreur: Division par 0 !!!");
                        free(nombres);free(signes);free(indexparo);free(indexparf);free(indexmuldiv);free(chaine);
                        Pause();
                        return NA;
                    }
                    temp = nb1/nb2;     /*Division*/
                }
                signes[b3] = '0';    /*Met 0 dans le tableau 2*/
                nombres[b3] = temp;  /*Place le résultat du calcul dans le tableau 1*/
            }
        }
        for(i=b1+1;i<b2;i++)
        {
            for(j=b1+1;j<b2;j++)
            {         /*Saisi valeur 1*/
                if (nombres[j] != 0 || (!nombres[j] && signes[j] == '0'))
                {
                    nb1 = nombres[j];
                    signes[j] = '#';
                    nombres[j] = 0;
                    break;
                }
            }
            for(k=b1+1;k<b2;k++)
            {        /*Saisi valeur 2*/
                if (nombres[k] || (!nombres[k] && signes[k] == '0'))
                {
                    nb2 = nombres[k];
                    signes[k] = '#';
                    nombres[k] = 0;
                    break;
                }
            }
            if (k==b2)
            {
                nombres[j] = nb1;
                signes[j] = '0';
            }
            for(j=b1+1;j<b2;j++)
            {
                switch (signes[j])
                {
                    case '+':
                        temp = nb1+nb2;     /*Addition*/
                        break;
                    case '-':
                        temp = nb1-nb2;     /*Soustraction*/
                        break;
                }
                if (signes[j] == '+' || signes[j] == '-')
                {      /*Si addition ou soustraction*/
                    signes[j] = '0';     /*Met 0 dans le tableau 2*/
                    nombres[j] = temp;   /*Et le resultat du calcul dans le tableau 1*/
                    break;
                }
            }
        }
    } while (b1 != -1 || b2 != nbt); /*Fin du calcul si les bornes sont maximum*/
    i=0;
    do
    {
        temp = nombres[i];    /*Prend comme résultat la seule valeur restant dans le tableau*/
    } while (!temp && ++i<nbt);
    free(nombres);free(signes);free(indexparo);free(indexparf);free(indexmuldiv);free(chaine);
    return temp; /*Renvoi le résultat du calcul*/
}

A voir également

Ajouter un commentaire Commentaires
Messages postés
71
Date d'inscription
mercredi 14 avril 2004
Statut
Membre
Dernière intervention
14 septembre 2007

Ca serait encore plus intéressant si ton parseur utilisait une syntaxe (et un analyseur syntaxique). Tu pourrais alors (en modifiant légérement la grammaire) ajouter des expressions exp, sin, cos... En utilisant ta méthode (analyse cas par cas), tu seras vite limiter par un code qui devient de plus en plus illisible au fur et à mesure que tu ajoutes des cas.
Messages postés
536
Date d'inscription
mercredi 27 avril 2005
Statut
Membre
Dernière intervention
22 août 2008

Ah ! intéréssant !
Un debut de parseur d'expression !
Mais ce serais bien de dire ce que ton prog peu parser et pas parser

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.