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 :

Retour d'une fonction imbriquée


Sujet :

C

  1. #1
    Candidat au Club
    Inscrit en
    Mai 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 6
    Points : 3
    Points
    3
    Par défaut Retour d'une fonction imbriquée
    Bonjour à tous,


    J'ai actuellement un problème.
    J'aimerais créer une fonction (callback_func) qui en retourne une autre (callback) (selon les arguments de la première) pour la passer à une autre fonction (get) qui l'utilisera en tant que fonction de callback.

    Je ne sais pas si c'est très parlant pour vous, alors que je vais tâchez de vous donner un exemple, que j'espère simple à comprendre.

    • J'utilise GCC (et donc son extension pour les nested functions)
    • J'ai omis les déclarations de prototypes

    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
     
    #include <stdlib.h>
    #include <stdbool.h>
     
    bool get_first_int(int * ptr, const int list[], const size_t size, bool (*func)(const int))
    {
    	bool found;
    	unsigned int i;
     
    	for(found = false, i = 0; !found && i < size; i++)
    	{
    		if(func(list[i]))
    		{
    			*ptr = list[i], found = true;
    		}
    	}
     
    	return found;
    }
     
    bool is_odd(const int i)
    {
    	return i & 1;
    }
     
    bool multiple_of_3(const int i)
    {
    	return multiple_of(3)(i);
    }
     
    bool (*multiple_of(const int multiple))(const int)
    {
    	bool func(const int i)
    	{
    		div_t d = div(i, multiple);
     
    		return d.quot != 0 && d.rem == 0;
    	}
     
    	return func;
    }
    Ici, la fonction callback_func est multiple_of, les fonctions callback sont is_odd ou encore multiple_of_3 et la fonction get est get_first_int.

    Ainsi j'aimerais pouvoir écrire :

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
     
    int main(void)
    {
    	int res, list[7] = {0, -6, 2, 3, 6, 1, 5};
    	bool found;
     
    	found = get_first_int(&res, list, sizeof(list) / sizeof(*list), multiple_of(3));
     
    	if(found)
    	{
    		printf("La Première Correspondance est '%i'\n", res);
    	}
    	else
    	{
    		puts("Aucune Correspondance Trouvée...");
    	}
     
    	return EXIT_SUCCESS;
    }
    C'est à dire fournir en tant que fonction de callback, à get_first_int, directement la fonction retournée par callback_func, et non une fonction globale (comme multiple_of_3).

    Or, le problème, c'est que cela ne va pas marcher, étant donné que la fonction retournée par callback_func est locale et donc la zone mémoire est inaccessible dans ma fonction get.
    J'aimerais donc savoir comment contourner le problème, de façon propre.

    Merci d'avance à vous !


    Cordialement,
    Hiz0

  2. #2
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Ici, je ne vois pas vraiment l'intérêt d'avoir des fonctions imbriquées étant donné qu'on peut tout simplement faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    bool multiple_of(const int multiple, const int i)
    {
        div_t d = div(i, multiple);
     
        return d.quot != 0 && d.rem == 0;
    }
    Mais d'habitude, quand je dois écrire une fonction f qui doit retourner une "sous fonction", j'isole f et ses fonctions internes dans un fichier à part et limite la visibilité de ces fonctions à ce fichier ce qui les rendent virtuellement locales à f.

    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
    static int f1(int a, int b);
     
    PFONCTION f(const int i)
    {
        PFONCTION func;
     
        switch(i)
        {
        case 1:
            func = f1;
            break;
     
        default:
            func = NULL;
        }
     
        return func;
    }
     
    int f1(int a, int b)
    {
        return a + b;
    }

  3. #3
    Candidat au Club
    Inscrit en
    Mai 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Melem Voir le message
    Ici, je ne vois pas vraiment l'intérêt d'avoir des fonctions imbriquées étant donné qu'on peut tout simplement faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    bool multiple_of(const int multiple, const int i)
    {
        div_t d = div(i, multiple);
     
        return d.quot != 0 && d.rem == 0;
    }
    Si, puisque je dois passer ma fonction à celle-ci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool get_first_int(int * ptr, const int list[], const size_t size, bool (*func)(const int))

  4. #4
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Pas du tout.

    Fichier : multiple.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    typedef bool (*PFONCTION)(const int);
     
    PFONCTION multiple_of_func(const int multiple);
    Fichier : multiple.c :
    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
    #include "multiple.h"
    #include <stdlib.h>
     
    static bool multiple_of_3(const int i);
    static bool multiple_of(const int multiple, const int i);
     
    PFONCTION multiple_of_func(const int multiple)
    {
        PFONCTION func;
     
        switch(multiple)
        {
        case 3:
            func = multiple_of_3;
            break;
     
        default:
            func = NULL;
        }
     
        return func;
    }
     
    bool multiple_of_3(const int i)
    {
        return multiple_of(3, i);
    }
     
    bool multiple_of(const int multiple, const int i)
    {
        div_t d = div(i, multiple);
     
        return d.quot != 0 && d.rem == 0;
    }
    Inclure multiple.h pour utiliser multiple_of_func.

  5. #5
    Candidat au Club
    Inscrit en
    Mai 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Désolé, j'ai du mal me faire comprendre .

    La fonction multiple_of_func est une fonction moule pas du tout une fonction de sélection de fonction existante.

    La fonction multiple_of_3 est juste un exemple du type de fonction que devrait me sortir multiple_of_func.

    Je voudrais pouvoir écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    PFONCTION callback = NULL;
     
    callback = multiple_of(multiple_variable);

  6. #6
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    OK. Et ceci :
    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
    static int _multiple;
    static bool multiple_of_multiple(const int i); /* Teste si i est multiple de _multiple */
     
    PFONCTION multiple_of(const int multiple)
    {
        _multiple = multiple;
     
        return multiple_of_multiple;
    }
     
    bool multiple_of_multiple(const int i)
    {
        div_t d = div(i, _multiple);
     
        return d.quot != 0 && d.rem == 0;
    }
    Ca te convient ?

  7. #7
    Candidat au Club
    Inscrit en
    Mai 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Oui merci, la technique fonctionne.

    M'enfin, on m'avait toujours dit d'éviter les globales (même static)

    Enfin, tan pis s'il n'existe pas d'autres moyens de contourner le problème.

    Un grand merci pour toutes tes réponses

  8. #8
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Pas qu'il faut éviter les globales, il faut s'interdire de mettre en global une variable qu'on aurait pu mettre en local à une fonction. Il ne faut pas non plus avoir plusieurs variables globales, même si on ne peut pas faire autrement. Si cela devait venir, plutôt créer une structure globale (donc on n'a plus qu'une seule variable globale : la structure) contenant toutes les variables (globales) nécessaires.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. retour d'une fonction
    Par papy_tergnier dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 15/05/2006, 18h21
  2. [XML][XSLT][debutant]retour d'une fonction
    Par maxvador dans le forum XSL/XSLT/XPATH
    Réponses: 7
    Dernier message: 30/03/2006, 15h12
  3. recuperer en php le retour d'une fonction plsql
    Par gismoblue dans le forum Langage SQL
    Réponses: 1
    Dernier message: 14/03/2006, 17h39
  4. PL/SQL retour d'une fonction
    Par aaronw dans le forum PL/SQL
    Réponses: 2
    Dernier message: 13/12/2005, 14h25
  5. [Oracle 9.1] Types de retour d'une fonction PL/SQL
    Par ftrifiro dans le forum PL/SQL
    Réponses: 8
    Dernier message: 12/10/2005, 17h54

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