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

WinDev Discussion :

Fonction récursive et nombre de paramètres indéfini [Généralités]


Sujet :

WinDev

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2009
    Messages
    1 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 278
    Par défaut Fonction récursive et nombre de paramètres indéfini
    Bonjour à tous,

    Une question qui me turlupine bien que j'en ai pas vraiment besoin mais que, dans l'absolu, j'aurais du mettre en place.

    Comment faire pour gérer une fonction récursive avec un nombre de paramètre indéfini ?

    Je m'explique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    PROCEDURE Toto(p1,p2,*)
    ...
    Toto(p1,p2, ????)
    Tu vois ?

    Faut-il obligatoirement passer par la compilation dynamique ?

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : Laos

    Informations forums :
    Inscription : Mars 2003
    Messages : 557
    Par défaut
    Bonjour,

    Windev sait gérer les paramètres variables pour des cas simples. Après dans une fonction récursive je n'ai jamais testé.

    Extrait de la doc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    FONCTION SupprimeCaractere(LOCALE sChaineComplète est une chaîne, *) 
     
    sChaineNettoyée est une chaîne = sChaineComplète 
    POUR IndiceParamètre = 2 _A_ MesParamètres..Occurrence - 1 
    sChaineNettoyée = Remplace(sChaineNettoyée, MesParamètres[IndiceParamètre], "") 
    FIN
     
    RENVOYER sChaineNettoyée
    Cette uniquement fonction permettra de supprimer par exemple les sauts de lignes et tabulation d'une chaine :
    SupprimeCaractère(ChaineANettoyer, RC, TAB)

    De supprimer des caractères spéciaux :
    SupprimeCaractère(ChaineANettoyer, Caract(13), Caract(10) ...)

    Donc a testé dans des conditions plus complexe en espérant que PCSOFT à fait ce qu'il faut de ce côté

  3. #3
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2009
    Messages
    1 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 278
    Par défaut
    Merci pour ta réponse.

    Voici la fonction dans laquelle j'ai besoin de ç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
     
    // Résumé : permet de gérer l'affichage d'une chaine entre 2 champs multilignes (si la chaine est trop longue pour le chp_source, une partie sera basculée sur chp_cible)
    //			si la chaine est trop longue pour être affiché dans les champs alors la taille de la typo sera réduite
    PROCEDURE DecoupageChaineMultiligne(chp_source,chp_cible,str_a_gerer={chp_source,indChamp})
     
    str_origine est une chaîne =str_a_gerer
    position_temp est une entier
    str_temp est une chaîne
     
     
    //on stocke dans mention_temp l'intégralité de la chaine
    str_temp = str_a_gerer
    //on force l'affichage de la chaine dans son intégralité dans le champ 1
    {chp_source,indChamp}=str_a_gerer
     
    //tant que la hauteur future du champ (après extension si chaine trop longue) est supérieur à la hauteur intiale du champ
    WHILE {chp_source,indChamp}..HauteurFuture>{chp_source,indChamp}..Hauteur _AND_ str_temp<>EOT
    	//on repère le dernier espace
    	position_temp=Position(str_temp," ",Taille(str_temp),DepuisFin)
    	//si il y a un saut de ligne avant l'espace on prend le saut de ligne comme sépateur
    	IF Position(str_temp,RC,Taille(str_temp),DepuisFin)>position_temp THEN
    		position_temp=Position(str_temp,RC,Taille(str_temp),DepuisFin)
    	END
    	//on enlève le dernier mot de la chaine
    	str_temp=Gauche(str_temp,position_temp-1)
    	//on l'affecte au champ 1 avant de retester la hauteur future
    	{chp_source,indChamp}=str_temp
    END
     
    //quand on est sorti du WHILE mention_temp correspond au "reliquat" qui n'a pas pu être affiché
    {chp_cible,indChamp}=Remplace(str_a_gerer,str_temp,"")
     
    //si la chaine "reliquat" basculé dans le champ 2 est trop importante
    IF {chp_cible,indChamp}..HauteurFuture>{chp_cible,indChamp}..Hauteur THEN
    	//on diminue la taille de la police de 2 champs
    	{chp_source,indChamp}..PoliceTaille--
    	{chp_cible,indChamp}..PoliceTaille--
    	//et on relance la procédure !
    	DecoupageChaineMultiligne(chp_source,chp_cible,str_origine) 
    END
    J'utilise cette fonction dans pour les états sur formulaire pré-imprimé... relativement statique donc je réduit la taille des typos si nécessaire.
    J'aimerais pouvoir gérer plus de 2 champs.
    Par exemple je fais ça pour les champs "monoligne" :
    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
     
    PROCEDURE DecoupageChaine(chpSource, chpCible, *)
     
    position_temp is int
    str_temp is string
     
    FOR i = 1 _TO_ MesParamètres..Occurrence-1
    	IF iLargeurTexte(iPolice({MesParamètres[i],indChamp}..Police)+{MesParamètres[i],indChamp})>{MesParamètres[i+1],indChamp}..Largeur-2 THEN
    		position_temp=0
    		str_temp={MesParamètres[i],indChamp}
    		//tant que la chaine est trop longue pour être affiché dans le champs
    		WHILE iLargeurTexte(iPolice({MesParamètres[i],indChamp}..Police)+str_temp)>{MesParamètres[i],indChamp}..Largeur-2
    			//on enlève un mot
    			position_temp=Position(str_temp," ",Taille(str_temp),DepuisFin)
    			str_temp=Gauche(str_temp,position_temp-1)
    		END
    		{MesParamètres[i+1],indChamp}=Remplace({MesParamètres[i],indChamp},str_temp,"")
    		{MesParamètres[i],indChamp}=str_temp
    	END
     
    END

  4. #4
    Membre Expert Avatar de laurent30s
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    889
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 889
    Par défaut
    Citation Envoyé par michel.souris Voir le message
    Comment faire pour gérer une fonction récursive avec un nombre de paramètre indéfini ?
    Pour la récursivité faisons une procédure de calcul de factorielle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    PROCEDURE nFactorielle(xNum)
     
    SI xNum=0 ALORS RENVOYER 1
    RENVOYER xNum*nFactorielle(xNum-1)
    On teste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    --- Clic sur BRN_SansNom1
     
    LIB_SansNom1 = nFactorielle(7)
    ça affiche 5040 ce qui est bien la factorielle de 7, donc la récursivité ça marche (C'est limité en profondeur, jusqu'à 20 c'est bon, à 21 c'est abérrant)

    Maintenant ce que tu veux faire : une fonction récursive avec un nombre de paramètre indéfini
    Ça devient bougrement tordu, donc c'est intéressant...


    On va rester sur des calculs factoriels pour la récursivité mais pour corser la chose on va faire la somme des factorielles d'un nombre indéfini de paramètre ça commence à piquer les yeux...

    Ce qui donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    PROCEDURE nFactorielleAddition(xNum,*)
     
    nCumul est un entier
     
    POUR nIndiceParamètre = 1 _A_ MesParamètres..Occurrence 
    	SI MesParamètres[nIndiceParamètre] = 0 ALORS 
    		nCumul += 1
    		SORTIR
    	FIN 
    	nCumul += MesParamètres[nIndiceParamètre]*nFactorielleAddition(MesParamètres[nIndiceParamètre]-1)
    FIN
     
    RENVOYER nCumul
    On teste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    --- Clic sur BRN_SansNom1
     
    LIB_SansNom1 = nFactorielleAddition(7,5)
    LIB_SansNom1 = nFactorielleAddition(7,5,8)
    ça affiche 5160 et 45480 c'est tout bon
    CQFD (Ce que fait Denise...)

  5. #5
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2009
    Messages
    1 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 278
    Par défaut
    Alors déjà chapeau car ta démonstration est très intelligible ce qui n'est pas évident avec ce genre de problème.

    Si j'avais pu mettre 2 pouces (ou 3) en l'air je l'aurais fait !

    Sinon ça ne répond pas entièrement à ma question... et oui je suis vraiment tordu ! je veux que le nombre de paramètre balancer à ma fonction lors de l'appel récursif soit variable... et en le repensant (grâce en partie à ta démo) je crois que je ne peux pas faire autrement que par compilation dynamique.....

    A moins que le mot clé MesParamètres désigne un ensemble de variable qu'on peut exploiter mais je ne crois pas... je vais tester !

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : Laos

    Informations forums :
    Inscription : Mars 2003
    Messages : 557
    Par défaut
    Dans votre cas, vous pouvez très bien contourner ce pb en créant un tableau ou une chaine avec séparateur contenant les paramètres.

    Et donc de ne pas passer les paramètres mais le tableau de paramètres à la fonction.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Procedure toto(psTest est une chaine)
     
    sSousChaine est une chaine
     
    POUR TOUTE sChaine DE psTest SEPAREE PAR ;
         {sChaine,indChamp} = ....
         ...
         toto(sSousChaine)     
    FIN
    Ca devrait répondre à vos attentes.

  7. #7
    Membre Expert Avatar de laurent30s
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    889
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 889
    Par défaut
    Citation Envoyé par michel.souris Voir le message
    je veux que le nombre de paramètre balancer à ma fonction lors de l'appel récursif soit variable...
    Si tu regardes bien dans la PROCEDURE nFactorielleAddition(xNum,*)

    Prenons le cas ou on fait la somme des factorielle de 3 nombres
    Lors du 1er appel nFactorielleAddition() 3 paramètres sont passés

    Après quand on est sur le 1er paramètre tous les appels récursifs de nFactorielleAddition() se font avec 1 seul paramètre (calcul de la factorielle du paramètre en cours).
    Jusqu'à ce qu'on passe au paramètre suivant ainsi de suite...

    On est bien dans un cas où le nombre de paramètre balancer à la fonction lors de l'appel récursif est variable...

    Ceci dit je pense que l'exemple s'y prête facilement puisque faire la somme d'une factorielle ou de plusieurs ça reste une somme...

    Au début j'avais juste vu ton besoin de passer un nombre variable de paramètre (pas la récursivité) et j'avais pensé comme Ry_Yo que tu pouvais contourner en passant un tableau ou un tableau de structure en paramètre. Puis d'utiliser les indirections pour récupérer les valeurs. Exactement ce que te propose Ry_Yo...

  8. #8
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2009
    Messages
    1 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 278
    Par défaut
    Bon déjà merci à vous deux de participer à cette réflexion...

    Laurent je me suis peut être mal exprimé je voulais dire que lors de tous mes appel récursif le nombre de paramètres soient variables. Ceci étant ce que tu expliques fonctionne bien pour une addition entre les paramètres, une soustraction ou autre opérateur mathématique ! (du moins d'intuition il me semble )

    La solution de Ry_Yo répond au besoin mais, et c'est subjectif, je la trouve pas très élégante à l'appel (ouais je suis bien casse couille)... disons que l'obligation de déclarer un tableau et de le remplir me plait pas... mais c'est un bon contournement, je le garde sous le coude !

    [LECTURE OPTIONNELLE]
    Si vous prenez le temps de lire mon code (j'avoue que moi aussi ça me casse les couilles de lire le code des autres, surtout sorti du contexte) il s'agit de gérer dans un état le fait que la chaine dépasse du champs sans le redimensionner...
    L'idée est de basculer (autant que faire se peut) les infos dans n champs et au besoin de diminuer la police des n champs et de retenter la "bascule" d'où le besoin de récursivité.
    Je dois donc passer en paramètre n champs... franchement le problème est bateau, c'est même pas pour envoyer des fusées sur la lune.... donc je comprends qu'on puisse se dire que je me prends la tête pour rien.

    donc voilà si quelqu'un a une idée d'un autre moyen de faire ça (avec un appel élégant si possible), je veux bien lui piquer !
    [/LECTURE OPTIONNELLE]

    Je vais faire un test : compilation dynamique VS et je vous dirais...

    PS : pas eu le temps de tester MesParamètres comme étant un ensemble de variable et j'y crois pas trop... ceci dit on y accède comme au élément d'un tableau... peut-être que c'est juste la coloration syntaxique qui change

  9. #9
    Membre Expert
    Avatar de DelphiManiac
    Homme Profil pro
    Homme à tout faire
    Inscrit en
    Mars 2002
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Homme à tout faire
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 147
    Par défaut
    Question tordue ça, j'aime bien les questions tordues ^^

    Pas sur de bien avoir compris la demande, mais je vais répondre en fonction de ce que j'ai compris en espérant ne pas être trop à coté de la plaque.

    Question : Peut t'on appeler une fonction récursive avec un nombre différents de paramètres lors de la récursivité.

    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
    PROCEDURE _recurse(nbr est un entier, *)
    SI nbr >= 0 ALORS
    	nbr--
    	SELON nbr
    		CAS 5
    			_recurse(nbr, 6, 5, 4, 3, 2, 1)
    		CAS 4
    			_recurse(nbr, 15, 14, 13, 12, 11)
    		CAS 3
    			_recurse(nbr, 24, 23, 22, 21)
    		CAS 2
    			_recurse(nbr, 33, 32, 31)
    		CAS 1
    			_recurse(nbr, 42, 41)
    		CAS 0
    			_recurse(nbr, 51)
    		AUTRE CAS
    	FIN
     
    	res est une chaîne
    	POUR i = 2 _A_ MesParamètres..Occurrence
    		res += [", "] + NumériqueVersChaîne(MesParamètres[i], "02d")
    	FIN
    	Trace(res)
    FIN
    qui donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    51
    42, 41
    33, 32, 31
    24, 23, 22, 21
    15, 14, 13, 12, 11
    06, 05, 04, 03, 02, 01
    Donc je dirais, toujours si j'ai bien compris, oui.

    P.S.: Le code est vraiment moche, mais le but de ce code étais juste de démontrer.

    [edit]Tout compte fait, j'ai peut être rien compris, en relisant le thread, d'autres ont déjà répondu à l'identique :/ Ça m'apprendra à lire un peu mieux les sujets la prochaine fois.

    Donc la subtilité, c'est que tu voudrais construire la liste des paramètres à passer par code ?

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

Discussions similaires

  1. Nombre de paramètres indéfinis
    Par Gothor dans le forum PL/SQL
    Réponses: 2
    Dernier message: 09/05/2012, 10h59
  2. [POO] Fonction à nombre de paramètres dynamique
    Par Digimag dans le forum Langage
    Réponses: 13
    Dernier message: 14/02/2008, 22h32
  3. Réponses: 2
    Dernier message: 05/09/2007, 09h22
  4. Réponses: 7
    Dernier message: 19/05/2006, 16h47
  5. Réponses: 11
    Dernier message: 30/03/2006, 15h39

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