Retour valeur d'une fonction

Thiers89 Messages postés 7 Date d'inscription vendredi 15 janvier 2016 Statut Membre Dernière intervention 16 février 2022 - Modifié le 16 févr. 2022 à 20:34
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 - 17 févr. 2022 à 11:10
Bonjour,


Je suis en train d'écrire un programme en vb dans lequel j'ai une fonction avec différentes conditions.
Celle-ci fonctionne mais quand je fais appel à la fonction la valeur n'est pas retournée.


La fonction :
Function ConvFormat(ByVal imageformat As String) As String

        '1ère MessageBox (valeur trouvée dans le fichier)
        MessageBox.Show(imageformat)

        If imageformat = "4x5" Then
            imageformat = FindAndReplace(imageformat, "4x5", "10x13")
           
             '2ème MessageBox (valeur remplacée)
            MessageBox.Show(imageformat)
        End If

        If imageformat = "4x6" Then
            imageformat = FindAndReplace(imageformat, "4x6", "10x15")
           
            '2ème MessageBox (valeur remplacée)
            MessageBox.Show(imageformat)
        End If

        If imageformat = "5x5" Then
            imageformat = FindAndReplace(imageformat, "5x5", "13x13")

            '2ème MessageBox (valeur remplacée)
            MessageBox.Show(imageformat)
        End If

.........

End Function



Appel de la fonction :

Je ne mets pas tout le code mais il y a une analyse d'un dossier, dans ce dossier il ouvre un fichier dans lequel on trouve puis retourne la valeur "imageformat"

 imageformat = FindAndReplace(imageformat, """", "")

ConvFormat(imageformat)

 '3ème MessageBox (valeur retournée de la fonction "ConvFormat")
MessageBox.Show(imageformat)


Actuellement, lorsqu'il trouve par exemple la valeur "4x5" dans le fichier, il m'affiche la 1ère MessageBox "4x5", puis il m'indique la valeur remplacée dans une 2ème MessageBox "10x13" puis à la fin de la fonction il m'indique la valeur retournée de la fonction "ConvFormat" dans une 3ème MessageBox "4x5" mais du coup il ne m'a pas retournée la bonne valeur ("4x5 au lieu de "10x13").


Le but est qu'il remplace par exemple la valeur "4x5" trouvée par "10x13".

Je tourne en rond et ne trouve pas l'erreur pour qu'il me retourne la bonne valeur de remplacement.

Merci par avance pour votre aide.


Thiers

10 réponses

JeuDuTaquin Messages postés 249 Date d'inscription mardi 4 juillet 2017 Statut Membre Dernière intervention 31 mai 2023 7
16 févr. 2022 à 01:02
Function ConvFormat(ByVal imageformat As String) As String


Salut,
Même si la fonction est sensée traiter et passer une variable de même nom, cette methode est à proscrire.
"ByVal" est utilisé pour les tableaux et ConvFormat est defini comme variable string sans attribution de variable à l'appel (Ret= ConvFormat("")).

Soit tu déclares imageformat en PUBLIC dans ta form principale, soit tu utilises ConvFormat comme prévu dans ta déclaration de fonction.


Private Function ConvFormat( imageformat As String) As String
...
ConvFormat=imageformat
End function

Puis tu l'appelle avec
 '3ème MessageBox (valeur retournée de la fonction "ConvFormat")
MessageBox.Show(ConvFormat(imageformat))


Amuse-toi bien.
0
JeuDuTaquin Messages postés 249 Date d'inscription mardi 4 juillet 2017 Statut Membre Dernière intervention 31 mai 2023 7
16 févr. 2022 à 01:21
Autre problème sur ton code, si tu ne déclares pas "imageformat" en "String" dans ta routine d'appel, il sera pris par défaut pour un "Variant" et sera une variable de nature différente. D'où l'incompatibilité de transfert de données.

Pour plus d'infos, configure ton compilateur au niveau de débogage haut, pour afficher toutes les incohérence du code.
0
Thiers89 Messages postés 7 Date d'inscription vendredi 15 janvier 2016 Statut Membre Dernière intervention 16 février 2022
16 févr. 2022 à 01:38
Je ne l'ai pas indiqué mais effectivement "imageformat" est bien déclaré en "String" au niveau de ma procédure qui fait ensuite appel à la fonction "ConvertFormat".
0
Thiers89 Messages postés 7 Date d'inscription vendredi 15 janvier 2016 Statut Membre Dernière intervention 16 février 2022
Modifié le 16 févr. 2022 à 01:26
Merci infiniment. Effectivement je vois l'erreur... !

Donc ma fonction
Function ConvFormat(imageformat As String) As String

        '1ère MessageBox (valeur trouvée dans le fichier)
        MessageBox.Show(imageformat)

        If imageformat = "4x5" Then
            imageformat = FindAndReplace(imageformat, "4x5", "10x13")
           
             '2ème MessageBox (valeur remplacée)
            MessageBox.Show(imageformat)
        End If

        If imageformat = "4x6" Then
            imageformat = FindAndReplace(imageformat, "4x6", "10x15")
           
            '2ème MessageBox (valeur remplacée)
            MessageBox.Show(imageformat)
        End If

        ConvFormat = imageformat

End Function



Mon appel de fonction :


imageformat = FindAndReplace(imageformat, """", "")

'récupération de la valeur
imageformat = ConvFormat(imageformat)
'3ème MessageBox (valeur retournée de la fonction "ConvFormat")
MessageBox.Show(imageformat)



Et ça fonctionne !

Un grand merci pour ton aide rapide.
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
16 févr. 2022 à 07:57
Bonjour

Même si la fonction est sensée traiter et passer une variable de même nom, cette methode est à proscrire.
n'importe quoi, une sub ou une fonction peut très bien traiter un passage de résultat via ses paramètres, d'ailleurs en C les résultats ne passe que de cette façon.

"ByVal" est utilisé pour les tableaux
et aussi pour n'importe quelle type de données. Mais c'est bien là où était une erreur.

Soit tu déclares imageformat en PUBLIC dans ta form principale
cela va à l'encontre de la protection de la donnée. Cette solution ne doit être utilisée qu'en dernier recours et en connaissance de cause.

Thiers, reprenons depuis le début, dans la majorité des langages sub et function c'est la même chose.
La seule différence est de savoir si elle retourne un résultat d'elle même ou pas.
En basic (pas essence sensé être plus simple à apprendre) il a été choisi de différencier.

Donc comme te l'as indiqué jeuDuTaquin, une écrire Function indique au compilateur qu'à la fin elle retournera un résultat et ce résultat a un type
Function Mot() as String
    '.. plein de code
    Mot = "bonjour" ' c'est donc là que tu indiques quel résultat est transmis
End Function


Mais supposons que ta function (ou une sub) doivent retourner 2 résultats.
  • on peut utiliser un tableau comme type de sortie, à condition que les 2 résultats soient du même type
  • on peut écrire une classe ou une structure, mais juste pour un résultat c'est peut-être un peu riche.
  • on peut se servir des paramètres, mais là, il faut bien comprendre byval et byref.


Dans un premier temps, il faut savoir qu'une variable c'est 2 emplacements mémoire.
Dans un emplacement il y a la donnée pure.
Dans le second il y a les métadatas
  • l'adresse de début de la données pures
  • son type (par exemple Integer, qui fait 4 octets, donc avec le type et l'adresse on sait lire la valeur)

Ce second emplacement dispose lui aussi d'une adresse.

Cette adresse c'est la référence, et l'adresse de la donnée pure c'est la "valeur"

Quand on passe un paramètre byval, on crée une copie de l'emplacement de la valeur et on lui associe une nouvelle référence.
Ainsi dans cet exemple
Sub Test(ByVal A as string)


End Sub

'...
Dim B as String
B = "Bonjour"
Test B

Quand on exécute la sub Test, il y a un emplacement mémoire qui contient Bonjour à la référence B et un emplacement qui contient "Bonjour" à la référence A. Donc toute manipulation sur A laissera B intègre.
A la fin de la Sub, le contenu et la référence A seront "supprimés" .

A l'inverse
Sub Test(ByRef A as string)


End Sub

'...
Dim B as String
B = "Bonjour"
Test B

Dans ce cas A est une copie de la référence B, les 2 pointent sur le même emplacement.
A la fin de la sub toute modification apportée à A affecte forcément le contenu de B, même si la référence A est supprimée.

Quand on ne mets pas d'indication, il y a un comportement par défaut (byavl ou byref) qui dépend de quel vb et pour certains vb du type de la donnée. Je ne fais plus de VB6 depuis longtemps car ce langage est obsolète depuis 2003.
Donc je ne sais plus quel est le comportement pas défaut.
Tu peux essayer avec
Sub Inverser(A as String, B as String)
    Dim C as String
    C = A
    A = B
    B = C
End Sub



En utilisant, les functions, byval et byref, il n'y a jamais besoin de rendre une variable publique, la donnée reste donc maitrisée.

A l'inverse, une variable "trop" publique peut être accessible depuis un autre programme et là c'est la porte ouverte à la détérioration (volontaire ou non) de l'intégrité des tes données.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Bonjour,
En VB6 par défaut le passage de parrametres ce fait en ByRef, mais ici vue que nous sommes sur un compilateur VB.net le passage par défaut ce fait en Byval.

Pour la lisibilité et la maintenance de ton code je t'inviterai à utiliser un Select case en lieu et place de ta quirel de if!
Function ConvFormat(imageformat As String) As String

     Select case imageformat 
                 Case  "4x5" : Return FindAndReplace(imageformat, "4x5", "10x13")
                 Case "4x6" : Return FindAndReplace(imageformat, "4x6", "10x15")
           
  End Select

End Function
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
16 févr. 2022 à 11:48
Bonjour

Il n’y a rien qui indique que le compilateur est VB.Net.

Et non en VB.Net ce n’est pas systématiquement ByVal, ça dépend du type de la donnée.
0
Thiers89 Messages postés 7 Date d'inscription vendredi 15 janvier 2016 Statut Membre Dernière intervention 16 février 2022 > Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024
16 févr. 2022 à 13:08
Je pense effectivement être en VB.NET, à vrai dire je ne suis pas sûr car je reprends seulement un bout de code d'un collègue qui est parti.
J'utilise Visual Studio 2017 et dans les paramètres de l'application il y a des références à .NET et .NET Framework 4.6.1.
0
Thiers89 Messages postés 7 Date d'inscription vendredi 15 janvier 2016 Statut Membre Dernière intervention 16 février 2022
16 févr. 2022 à 21:23
Super, fonctionne également mais code beaucoup moins lourd et beaucoup plus lisible effectivement ! 3x moins de ligne du coup.

Merci beaucoup
0
En VB6 on écrirais
Msgbox imageformat

Pas
MessageBox.Show(imageformat)
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
16 févr. 2022 à 12:48
Ha exact, je n'avais pas fait attention.

Du coup Thiers ne sait même pas dans quel langage il code....
0
Thiers89 Messages postés 7 Date d'inscription vendredi 15 janvier 2016 Statut Membre Dernière intervention 16 février 2022 > Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024
16 févr. 2022 à 13:14
oui ;p effectivement, désolé d'avoir posté dans le mauvais forum
0
dysorthographie Messages postés 92 Date d'inscription jeudi 27 janvier 2022 Statut Membre Dernière intervention 3 avril 2024 5
Modifié le 16 févr. 2022 à 12:37
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
16 févr. 2022 à 12:53
Ok pour la doc, mais c'est incomplet, il faut ajouter celle ci
https://docs.microsoft.com/fr-fr/dotnet/visual-basic/programming-guide/language-features/data-types/value-types-and-reference-types

Du coup, seuls les types de "base", les enums et les structures sont passées par défaut byval.

Attention, une string, un tableau ou une collection ne sont pas des types "de base".
0
Thiers89 Messages postés 7 Date d'inscription vendredi 15 janvier 2016 Statut Membre Dernière intervention 16 février 2022
16 févr. 2022 à 13:01
Merci pour toutes ces précisions.

Pour le moment cela fonctionne comme je l'ai indiqué mais je vais regarder plus en détails.

Pour info la fonction ConvertFormat est appelée dans une procédure Private sub dans laquelle est déclaré "imageformat" en tant que "String".

Cette procédure fait différente chose dont l'appel de cette fonction car il y a plusieurs chemins de dossiers qui sont vérifiés. Donc pour chaque chemin vérifié je fais appel à la fonction "ConvertForma"t au lieu de dupliquer le code (qui fait une 60aine de lignes) dans la procédure en elle même.
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
Modifié le 16 févr. 2022 à 13:04
Thiers, maintenant qu'il est établi que tu codes en Vb.Net et non pas en VB6, j'ai déplacé ta question dans le bon forum.

Comme démontré au commentaire 11, une string est un type référence donc sans indication contraire, elle est passée par référence.

D'autre par en .Net il est conseillé d'indiquer le résultat d'une fonction avec le mot clé Return (comme l'a signalé dysorthographie) pour 2 raisons
  • c'est plus lisible, clair
  • cette instruction retourne le résultat et sort de la fonction


Par exemple

Function Exemple(OuiOuNon as Boolean) as String
     If OuiOuNon = False Then Return "Je ne fais rien" 'et ça n'exécutera rien au delà

    'plein de code à exécuter sans erreur
    Return "J'ai tout fait"  'et ça n'exécutera rien au delà

    'traitement des erreurs (Avec Try / Catch en .Net, surtout pas On Error. ! )
    Return "J'ai eu un problème"  'et ça c'est la fin de toute façon
End Function


0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
17 févr. 2022 à 11:10
Bonjour

Si ton but est aussi de clarifier ton code, alors il y a encore à redire.

Je te cite
Actuellement, lorsqu'il trouve par exemple la valeur "4x5" dans le fichier, il m'affiche la 1ère MessageBox "4x5", puis il m'indique la valeur remplacée dans une 2ème MessageBox "10x13


A la lecture de ça on peut imaginer que si "4x5" apparait quelque part dans le texte alors cette partie du texte est remplacée par "10x13" mais dans ton code
If imageformat = "4x5" Then
ce qui veut dire que "4x5" c'est le texte entier.
Donc à aucun moment tu n'as besoin d'une autre fonction ceci
        If imageformat = "4x5" Then
            imageformat = "10x13"
           
             '2ème MessageBox (valeur remplacée)
            MessageBox.Show(imageformat)
        End If

Ou avec le select case
     Select case imageformat 
                 Case  "4x5" :
                              Return "10x13"

                 Case "4x6" :
                              Return  "10x15"    
'pour des raisons de lisibilité, je préfère cette présentation plutôt que sur une ligne, d'autant que si tu veux écrire plusieurs instruction pour un case, il faudra y passer
  End Select


Encore plus concis et en plus rapide d'exécution car on ne pas appeler une autre fonction.

Cette fonction d'ailleurs, dont tu n'as pas montré le code, mais je pressens que tu as réinventé la rue.
Teste ceci
Dim texte as String  = "Bonjour le monde!"
MessageBox.Show(texte.Replace(" monde", "s gens"))



Allons plus loin avec une supposition basée sur tes 2 exemples
  • 4x => 10x
  • x5 => x13
  • x6 => x15


imageFormat = imageFormat.Replace("4x", "10x").Replace("x5", "x13").Replace("x6", "x15")


Là tu vois, avec ces 2 exemples une seule ligne qui en l'état est encore largement compréhensible.
Tu pourrais presque te passer complètement de la fonction ConvFormat
Mais quelque part, tu laisses entendre qu'en réalité tu as beaucoup plus de cas et de fait il n'est peut-être pas aussi simple de généraliser et surtout la ligne pourrait devenir énorme, illisible => contre productif.

Il y a peut-être moyen de faire avec des regex, mais pour te le dire, il me faut tous les cas de substitutions.

Il y a encore une autre méthode : utiliser une collection de substitutions. Dans ce cas un dictionnaire est pas mal, car il y a une clé unique (le texte à trouver) et sa valeur (le texte de substitution)
Pour cet exemple, j'ai ajouté un cas qui empêcherait la généralisation.
Attention à bien définir le dictionnaire pour la classe, ça évite de le refaire à chaque exécution de la sub (gain de temps, de mémoire etc...)
    Private dictionnaire As Dictionary(Of String, String) = New Dictionary(Of String, String) From {
        {"4x5", "10x13"},
        {"4x6", "10x15"},
        {"4x7", "11x17"}
    }

    Private Sub TestThiers89()
        Dim imageFormat As String = "3x5"

        If dictionnaire.ContainsKey(imageFormat) Then imageFormat = dictionnaire(imageFormat)

        Dim imageFormat2 As String = "4x5"

        If dictionnaire.ContainsKey(imageFormat2) Then imageFormat2 = dictionnaire(imageFormat2)


    End Sub

Dans un cas la clé n'existe pas, il ne se passe rien. Dans l'autre c'est changé.

Un avantage éventuel à cette méthode, c'est que le dictionnaire peut être constitué à partir d'un fichier externe, ce qui peut permettre aux utilisateurs d'ajouter/modifier/supprimer une substitution sans te faire tout recompiler.

0
Rejoignez-nous