IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

executer une chaine de caractères


Sujet :

C

  1. #1
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 87
    Par défaut executer une chaine de caractères
    Bonjour!

    J'aimerais savoir si il y a une fonction en c qui traduit une chaine de caractère en commande :

    J'ai trouvé l'équivalent en scilab :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    La fonction evstr() permet de convertir une chaîne de caractères en une expression : -->c='sqrt(3)/2'
    c = sqrt(3)/2 -->d=evstr(c)
    d = .8660254
    N'y a t'il pas l'équivalent en C ?

  2. #2
    Membre émérite
    Homme Profil pro
    R&D imagerie 3D / prog embarquée
    Inscrit en
    Mars 2007
    Messages
    419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : R&D imagerie 3D / prog embarquée
    Secteur : Santé

    Informations forums :
    Inscription : Mars 2007
    Messages : 419
    Par défaut
    Salut,

    Ce que tu cherches est un interpréteur de commandes, il n'y a rien dans l'API qui te permette de faire ça directement.
    Par contre, il y a beaucoup d'interpréteurs dispo sur le net. Si tu cherches seulement à interpréter/évaluer des expressions mathématiques, tu peux essayer avec libmatheval.

  3. #3
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 87
    Par défaut
    NOn ça ne peut pas m'aider :/
    Mon problème plus exactement est le suivant :
    à partir de programmes.c toujours définit de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /*fonction.c*/
    void fonction(structure_crée_par_moi p, int n){...}
    Je suis censée proposer à l'utilisateur d'executer cette fonction (à partir d'un programme contenant le main). On doit le faire dynamiquement pour que si on rajoute une nouvelle fonction de ce type, le menu se mette à jour automatiquement.
    Pour ce faire, j'arrive à lire les noms des fonctions dans le dossier, les proposer à l'utilisateur, puis insérer dans une chaine de caractère son choix (var = fonction(p, n)) mais j'aimerais l'executer...

    Y a t'il un moyen ?

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Novembre 2010
    Messages : 5
    Par défaut
    Tout d'abord il faut que tes fonctions soit compiler. Par conséquent dans ton fichier de fonction tu dois avoir des executables. Ensuite pour les exécuter il te faut faire un execvp (ou consort http://linux.die.net/man/3/execvp).

    En fait, si j'ai bien compris tu veux faire un gestionnaire de plugin en C ?

  5. #5
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 87
    Par défaut
    oui la compilation est déjà faite.

    Si je tape dans mon main "fonction(p, n);" la fonction se lance bien, le problème est la traduction de la chaine de caractère en commande c :

    J'ai déjà essayé les execllp, vp etc. mais ça n'a pas marché (ça retourne toujours "-1" et ne lance pas le programme).
    Du coup j'avais regardé sur internet, et il m'a semblé que execlp ne lance que des scripts shell non ?
    Pour moi ce n'est pas faisable parce que les paramètres sont des chaines de caractères or moi je veux transmettre d'autres types...
    Je pense que j'ai très mal compris ces fonction "exec", le problème est que sur internet je n'ai trouvé que des exemples avec des commandes shell (par exemple ls -l)

    J'avais testé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    url = getwd(NULL); //affiche bien l'url jusqu'au bon dossier
    	if(choice>=0 && choice<=cptBis){
    		printf("CHOIX : %s\n", tabChoix[choice]); //c'est ici qu'est stocké la chaine "fonction.c"
    		totPath = (char*)malloc((strlen(url)+strlen(tabChoix[choice]))*sizeof(char));
    		for(i=0;i<strlen(url)+strlen(tabChoix[choice]+1);i++){
    			if(i<strlen(url)) totPath[i]=url[i];
    			   else if(i==strlen(url)) totPath[i] = '/';
    					   else totPath[i]=tabChoix[choice][i-strlen(url)-1];
    		}
    		printf("ecriture du path : %s\n", totPath); // ecrit tout le chemin : "~/.../programme.c"
    		tabChoix[choice][strlen(tabChoix[choice])-2]='\0';
    		printf("prog : %s\n", tabChoix[choice]); //enleve le ".c" 
    /*ici j'ai donc : 
    totpath =~/.../programme.c
    tabChoix[choice] = programme
    arg1 correspond à une structure crée par moi
    arg2 un entier
    */
    		if(execl(totpath, tabChoix[choice], arg1, arg2, NULL)==-1){	
    			puts("erreur execlp");
    		}
    	}
    ça m'affiche toujours le message d'erreur :/
    Pouvez vous me dire où je me trompe ?

  6. #6
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Salut,

    Il y a une façon de faire que j'ai quelquefois utilisée, c'est un vrai interpréteur de commande, assez rudimentaire mais efficace. En premier lieu, les données d'une fonction, c'est à dire son nom et son pointeur. Il faut ensuite un tableau de ces structures contenant les données de ces fonctions (nom et pointeur). tu remplaces bien sûr les "dummy" par les nom de tes fonctions.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    typedef struct
    {
        unsigned char Name[16];
        int ( *Run ) ( void );
    }CommandStruct;
     
     
    int dummy(void)
    {
        return 0;
    }
     
    CommandStruct COMMANDS[] =
    {
        {"add", dummy},
        {"sub", dummy},
        {"mul", dummy},
        {"div", dummy},
        {"", NULL}/* pour detecter la fin des commandes */
    };
     
    char user_buf[80];
    Il te faut aussi la saisie de l'utilisateur, on va dire que tu vas te débrouiller pour la stocker dans user_buf. prenons une exemple de ce que l'on pourrait trouver dans ce buffer:
    Il faut maintenant (et c'eszt peut-être la partie la plus délicate) un parser qui extrait les mots un à un, appelons-le
    Tu appelles getWord et tu récupères le premier mot, "add". Il n'y a plus qu'à balayer la liste de structures et comparer avec strcmp. Si tu trouves une correspondance avec un nom, tu as du même coup le pointeur de fonction à utiliser. Dans ta fonction add, tu appelles 2 fois getWord pour récupérer "33" et "45". Après les avoir transformé de chaines vers entiers ou flottants, tu fais ton addition et tu affiches ou tu stockes. Bon courage.

    A+

    Pfeuh

  7. #7
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 87
    Par défaut
    salut,

    pfeuh : j'ai pas du tout compris comment fonctionne tes fonctions :rien que la structure, qu'est ce que RUN?
    Sinon pourquoi les dummy sont des fonctions vides? Moi mes fonctions sont du types void fct(struct_cree_par_moi p, int n); donc ça peut pas être du void?

    les autres : si quelqu'un peut continuer sur la piste du "exec" j'aimerais bien savoir ou je me trompe.

    Merci de votre aide!

  8. #8
    Membre très actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2010
    Messages
    434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2010
    Messages : 434
    Par défaut
    Exec n'est pas vraiment la solution dans ton cas.

    La solution de pfeuh est la plus propre.

    En gros tu fait un parseur pour récuperer les nombres et les nom de fonction que tu veux excuter.

    Ensuite tu as un structure avec le nom de la fonction et un pointeur sur fonction.

    Tu compare le nom de fonction que tu as en parametre avec le nom de fonction de ton tableau de structure afin d'executer la fonction stocké dans ta structure.

  9. #9
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par Misaki43 Voir le message
    qu'est ce que RUN?
    RUN est le pointeur de fonction.

    Citation Envoyé par Misaki43 Voir le message
    pourquoi les dummy sont des fonctions vides?
    Parce que ce ne sont que des exemples. Tu as ci-dessous un exemple basique d'interpréteur qui marche, mais seulement pour la fonction "add". Si tu tiens absolumnet à passer une structure à tes fonctions, ce n'est clairement pas ce genre d'interpréteur qu'il te faut.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    #include <stdio.h>
    #include <string.h>
     
    char* USER_BUF;
    char PARAM[80];
    size_t USER_BUF_IDX;
    size_t PARAM_IDX;
     
    typedef struct
    {
        unsigned char name[16];
        int(*function_ptr )(void);
    }COMMANDSTRUCT;
     
    char* getWord(void)
    {
        char car;
        int parsing;
        char* strptr = PARAM;
     
        if(USER_BUF[USER_BUF_IDX] == ' ' || USER_BUF[USER_BUF_IDX] == '\0')
            strptr = NULL;
        else
        {
            parsing = 1;
            PARAM_IDX = 0;
            while(parsing != 0)
            {
                car = USER_BUF[USER_BUF_IDX++];
                switch(car)
                {
                    case ' ':
                        PARAM[PARAM_IDX] = '\0';
                        parsing = 0;
                        break;
                    case '\0':
                        PARAM[PARAM_IDX] = '\0';
                        USER_BUF_IDX--;
                        parsing = 0;
                        break;
                    default:
                        PARAM[PARAM_IDX++] = car;
                }
            }
        }
        return strptr;
    }
     
    int dummy(void)
    {
        return 0;
    }
     
    int add(void)
    {
        int result = 0;
        int value;
        char* word;
     
        while(1)
        {
            word = getWord();
            if(word == NULL)
                break;
            if(sscanf(word, "%i", &value) == 1)
                result += value;
            else
                return 1; /* erreur entree non numerique */
        }
        printf("%i\n", result);
        return 0;
    }
     
    COMMANDSTRUCT commands[] =
    {
        {"add", add},
        {"sub", dummy},
        {"mul", dummy},
        {"div", dummy},
        {"", NULL}/* pour detecter la fin des commandes */
    };
     
    int interpreter(char* text)
    {
        char* word;
        size_t index = 0;
     
        USER_BUF = text;
        USER_BUF_IDX = 0;
        PARAM_IDX = 0;
     
        word = getWord();
        while(1)
        {
            if(strcmp((const char*)word, (const char*)commands[index].name) == 0)
                return commands[index].function_ptr();
            if (commands[index].function_ptr == NULL)
                return -1; /* commande non trouvee */
            index++;
        }
    }
     
    int main(void)
    {
        interpreter("add 33 45 67");
        interpreter("add 1000 200 30 4");
        return 0;
    }

  10. #10
    Membre très actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2010
    Messages
    434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2010
    Messages : 434
    Par défaut
    par contre utiliser une global ce n'est pas très jolie pour le coup

  11. #11
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 854
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 854
    Par défaut
    Salut,

    Pour la déclaration de la structure, je ferais plutôt comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    // ************************************
    int cmd1(int argc, char *argv[]){
    	// ...
    	return 0;
    }
     
    int cmd2(int argc, char *argv[]){
    	// ...
    	return 0;
    }
     
     
    // ************************************
    typedef struct {
        char * name;
        int (*callBack)(int argc, char *argv[]);
    } CommandStruct;
     
    // liste des commandes gérée 
    CommandStruct COMMANDS[] = {
        {.name = "cmd1", .callBack = &cmd1},
        {.name = "cmd2", .callBack = &cmd2}
    };
     
     
    typedef struct {
    	int count;
    	CommandStruct * list; 
    } CommandListStruct;
     
    CommandListStruct COMMANDS_LIST = {
    	.count = sizeof(COMMANDS) / sizeof(*COMMANDS),
    	.list = COMMANDS
    };
     
     
    // ************************************
    void main(void){
     
     	char user_buf[80];
    	int len; 
     
    	while(1){
    		len = getString(user_buf, sizeof(user_buf)); // recuperation de la ligne de commande
     
    		if(len > 0){
    			#define NB_MAX_ARG 10
    			char* argv[NB_MAX_ARG];
    			int argc; 
    			argc = parseCommandeLine(user_buf, len, &argv, NB_MAX_ARG); // récupération du nom de la commande et des différents arguments
     
    			if(argc > 0){
     
    				// recherche du nom de la commande dans la liste
    				int i;
    				if(COMMANDS_LIST.count > 0){
    					CommandStruct * ptCommandStruct = &COMMANDS_LIST.list[0];
     
    					for(i=0; i<COMMANDS_LIST.count; i++){
    						if(compareString(ptCommandStruct->name, argv[0]) == TRUE){
    							ptCommandStruct->callBack(argc-1, &argv[1]); // on execute la fonction (au saute le premier argument car c'est le nom de la commande)
    							break;
    						}
    						ptCommandStruct++;
    					}
    				}
    			}
    		}
    	}
    }
    => ça me semble plus propre car il n'y a plus besoin de variable globale pour le stockage des paramètres et les noms des commandes ne sont plus de taille fixe

  12. #12
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par jouana Voir le message
    par contre utiliser une global ce n'est pas très jolie pour le coup
    Absolument, mais déjà là, il y en a pour plus de 100 lignes, concentrons nous sur l'essentiel, à savoir interpréter du texte. C'est une idée de départ, sûrement pas une solution.

  13. #13
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par boboss123 Voir le message
    ça me semble plus propre car il n'y a plus besoin de variable globale et les nom des commandes ne sont plus de taille fixe
    pour la taille des commandes fixes, il suffit de modifier le prototype de la structure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct
    {
        char* name;
        int(*function_ptr )(int argc, char** argv);
    }COMMANDSTRUCT;
    Oui d'autant plus que c'est la signature standard de la fonction main. C'est sûr que c'est plus propre. Mais pas forcément plus compréhensible par le PO.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
     
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct
    {
        char* name;
        int(*function_ptr )(int argc, char** argv);
    }COMMANDSTRUCT;
     
    int dummy(int argc, char** argv)
    {
        return -1; /* commande non implementee */
    }
     
    int add(int argc, char** argv)
    {
        int result = 0;
        int value;
        int index = 1; /* argv[0] = "add" (nom de la commande) */
     
        while(index < argc) /* tant qu'il y a des parametres */
        {
            if(argv[index] == NULL)
                break; /* fin des parametres */
            if(sscanf(argv[index], "%i", &value) == 1)
                result += value;
            else
                return -1; /* erreur entree non numerique */
            index++;
        }
        printf("%i\n", result);
        return 0;
    }
     
    COMMANDSTRUCT commands[] =
    {
        {"add", add},
        {"sub", dummy},
        {"mul", dummy},
        {"div", dummy},
        {"", NULL}/* pour detecter la fin des commandes */
    };
     
    int interpreter(char* text)
    {
        int argc = 0;
        char* argv[20];
        char buffer[80];
        char* parser = buffer;
        int index;
        int errcode;
        char car;
     
        strcpy(buffer, text);
        argv[0] = parser;
        while(1) /* construction argv[1..x] */
        {
            car = *parser++;
            switch(car)
            {
                case ' ':
                case '\0':
                    *(parser - 1) = '\0';
                    argv[++argc] = parser;
                    break;
                default:
                    break;
            }
            if(car == '\0') /* n'oublions pas de sortir */
                break;
        }
        index = 0;
        while(1) /* recherche argv[0] dans la table de commande */
        {
            if(strcmp(argv[0], commands[index].name) == 0)
            {
                errcode = commands[index].function_ptr(argc, argv);
                break;
            }
            if (commands[index].function_ptr == NULL)
            {
                errcode = -1;
                break;
            }
            index++;
        }
        return errcode;
    }
     
    int main(void)
    {
        printf ("%i\n", interpreter("add 33 45 67"));
        printf ("%i\n", interpreter("add 1000 200 30 4"));
        printf ("%i\n", interpreter("add 1000 200 30 a4"));
        printf ("%i\n", interpreter("sub 1000 200 30 4"));
        return 0;
    }
    Finalement, j'aime bien. Le principe: L'interpréteur créée une copie de la chaine en local, la tronçonne en remplaçant les espaces par le caractère de fin de chaine '\0' stocke l'adresse de chaque mot dans argv et met à jour argc. Pas besoin de malloc ni de free. Par contre la saisie n'est pas sécurisée, on peut déborder de partout. Et en plus on s'éloigne complètement de ce qui intéresse le PO.

Discussions similaires

  1. Réponses: 9
    Dernier message: 23/12/2013, 16h40
  2. [WD16] Executer formule contenu dans une chaine de caractère
    Par J0r_x dans le forum WinDev
    Réponses: 1
    Dernier message: 02/11/2011, 14h39
  3. Réponses: 2
    Dernier message: 14/12/2007, 01h11
  4. Lire Une Chaine De Caractères
    Par Jonathan_Korvitch dans le forum C
    Réponses: 12
    Dernier message: 07/01/2003, 05h37
  5. Réponses: 2
    Dernier message: 06/12/2002, 07h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo