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

Langage Perl Discussion :

probleme avec un return


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mai 2007
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 33
    Par défaut probleme avec un return
    bonjour,

    Je suis débutant en perl et j'ai créé un programme comportant plusieurs fonctions.
    Dans une de mes fonctions j'ai utilisé un return. En effet, quand une certaine condition est remplie je dois quitter ma fonction pour eviter qu'elle continu d'écrire des lignes dans un fichier.
    Jusque là tout se passe pour le mieux et je n'ai aucun problème.
    Le problème survient quand j'essai d'exécuter une autre fonction après celle comportant le return.
    En effet je n'arrive plus à executer quoi que ce soit apres cette fonction
    j'ai meme essayé de faire un print dans mon programme apres la fonction et rien ne s'affiche.
    Est ce que quelqu'un peut me donner un conseil?
    Le return ne devrait il pas uniquement me quitter ma fonction?
    Merci d'avance pour vos reponses

  2. #2
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Le return; sort de la fonction dans laquelle il se trouve, mais le code après l'appel de cette fonction est exécuté normalement. Donc ton code a un autre problème que nous ne risquons pas de trouver si tu ne nous le montre pas.

    Voici un petit exemple, peut-être t'aidera-t-il à comprendre ce que tu fais de façon incorrecte.
    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
    #!/usr/bin/env perl
    use strict; use warnings;
     
    sub pHello {
      # cette ligne est exécutée :
      print "Hello ";
      return;
      #cette ligne ne l'est jamais :
      print "Never printed\n";
    }
     
    pHello();
    # cette ligne-ci est également exécutée :
    print "World !\n";
     
    __END__
    Ce code affichera "Hello World !" et un retour à la ligne.

    --
    Jedaï

  3. #3
    Membre averti
    Inscrit en
    Mai 2007
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 33
    Par défaut mon code
    je vous met mon code de la fonction qui me pose probleme peut etre que vous pourrez me trouver une erreur.

    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
    #utilise le fichier .alignment pour sortir un fichier .txt avec les blocs des différents génomes
    sub tableau_texte{#nom de fonction
        	my $fichier=$_[0];#ARGV[0] stocké dans $_[0]
            my $fich= "essai.txt";#fichier essai.txt déjà existant mais réécri par dessus
            sysopen(BOB, $fich, O_RDWR | O_TRUNC| O_APPEND);
    	open YEAST, "$fichier";#ouvre le fichier en parametre
    	while (<YEAST>){#tant qu'il reste des lignes dans le parametre
    		if(($_=~/^>\s(\d)\:(\d+)-(\d+)\s(\W)/) and ($ligneprecedente==1)){#recherche des lignes souhaitées
    			if($1!=1){
    				close $fichier;
    				close (BOB);
    				return;
    			}
    		}
    		if($_=~/^>\s(\d)\:(\d+)-(\d+)\s(\W)/){
    			if($1==1){@ligne=($4.$2,$4.$3);}
    			if($1<$nbGenome && $1!=1){push(@ligne,$4.$2,$4.$3);}
    			if($1==$nbGenome){
    				push(@ligne,$4.$2,$4.$3);
             			select(BOB);
    				print  ("@ligne\n");
       			}
    		}
    		if($_=~/^=/){$ligneprecedente=1;}
    		else{$ligneprecedente=0;}
        	}
     
    	close $fichier;#ferme le fichier en parametre
      	close (BOB);
    }
    Je l'ai regardé dans tous les sens et je ne trouve pas pourquoi la fonction ne rend pas la main a mon programme.
    merci de bien vouloir essayer de me sortir de cette galère

  4. #4
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    La prochaine fois mets les balises codes autour de ton code (bouton #) sinon le forum ne conserve pas l'indentation, et c'est illisible...

    Citation Envoyé par Kobe70
    je vous met mon code de la fonction qui me pose probleme peut etre que vous pourrez me trouver une erreur.
    Je peux en tout cas te trouver un certain nombre de constructions "douteuses" et trouver ton bug en passant :
    1. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      sysopen(BOB, $fich, O_RDWR | O_TRUNC| O_APPEND);
      Pourquoi sysopen() ? On ouvre un fichier avec open() en Perl sauf si on a des besoins très particuliers... En plus : O_TRUNC | O_APPEND signifie "écraser le fichier et écrire à la fin du fichier en mode ajout", ce sont deux options qui ne vont pas vraiment ensemble logiquement. Pourquoi O_RDWR : Tu ne fais qu'écrire dans ce fichier, il devrait être ouvert en écriture O_WRONLY.
      En bref tu devrais utiliser :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      open BOB, '>', $fich
        or die "Couldn't open $fich : $!\n";
      (remarque le contrôle d'erreur, tous tes open devrait vérifier s'ils ont réussit, à moins que tu n'utilise le module "Fatal").
    2. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      if(($_=~/^>\s(\d)\:(\d+)-(\d+)\s(\W)/) and ($ligneprecedente==1)){#recherche des lignes souhaitées
      Cette ligne est trop longue... Mais en dehors de ce facteur stylistique légèrement subjectif (quoique...), il y a trois problèmes dans cette ligne :
      • Si tu ne veux pas explicitement lire les lignes de ton fichier dans une variable, tu restes implicite pour tes tests aussi, autrement dit tu ne mets pas de $_ inutiles.
      • Plus grave : $ligneprecedente n'a pas été déclarée, c'est une variable globale, probablement jamais déclarée, autrement dit tu n'utilises pas le pragma "strict". Va voir mon sujet pour plus d'informations à ce propos, et quelques autres conseil qui pourront te servir. Comme tu utilises cette variable avant de l'avoir affectée une seule fois, ça signifie que tu peux avoir des bugs si tu appelles plusieurs fois de suite ta fonction (et pire, tu peux avoir des bugs si tu utilises une variable nommée de la même façon ailleurs...).
      • De plus 1 est vrai, 0 est faux, si $ligneprecedente ne prend que ces valeurs, il est inutile de tester pour une égalité, la variable suffit.

      Correction : D'une part déclarer $ligneprecedente avant la boucle avec un my(), d'autre part :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      # recherche des lignes souhaitées
      if( m/^>\s(\d)\:(\d+)-(\d+)\s(\W)/ and $ligneprecedente ){
      Même remarque à propos des autres lignes où tu testes explicitement $_ contre une regex.
    3. ?? On ne ferme pas un nom de fichier, on ferme un handle de fichier, comme YEAST.
    4. @ligne n'est jamais déclarée non plus... Encore une source possible de désagrément, surtout avec un nom aussi commun.
    5. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      select(BOB);
      print  ("@ligne\n");

      Et voici la source du bug : le reste de ton code est bien exécuté, mais tu ne t'en aperçois pas parce que les print() essaient d'écrire sur BOB, qui a été refermé (et bien sûr, comme tu n'avais pas activé les warnings, Perl ne se plaint pas).
      select() change le handle par défaut, si on l'utilise il faut toujours remettre le handle précédemment par défaut avec un code comme :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      my $old = select(NEW)
      # travail avec NEW
      select($old);
      Bien sûr ici tu n'as même pas besoin du select, tu peux écrire sur BOB aussi bien avec :


    Pas mal de problème donc... Lis bien mon sujet sur une méthode pour écrire du Perl plus propre, évite de recopier du code que tu ne comprends pas (tu ne me feras pas croire que le sysopen() était de toi, enfin que c'était autre chose qu'un recollage semi-aléatoire d'éléments extérieurs), apprends à faire des Entrées/Sorties correcte (mais d'où as-tu sorti ce select() ?) et tu devrais avoir moins de problèmes.

    --
    Jedaï

  5. #5
    Membre chevronné
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Par défaut
    Quelques questions qui n'ont probablement rien à voir avec ton problème :
    C'est quoi ce caractère "\:" qui apparaît dans tes regex ?
    Où ta variable @ligne est-elle déclarée ? J'ai bien l'impression que tu n'utilises pas le pragma "strict", tu devrais.
    Où remets-tu le handle par défaut à STDOUT ? Est-ce vraiment une bonne idée d'utiliser "select" pour simplifier l'écriture d'un seul "print" ?

    Une question qui a peut-être à voir avec ton problème :
    Où fermes-tu ton handle YEAST ?

    Deux remarques en passant :
    Tu peux simplifier ($_=~/ta_regex/) en if(/ta_regex/), par défaut c'est $_ qui est testé.
    Plus important, tu devrais tester le succès de l'ouverture des fichiers, au cas où.

    Enfin, les if à l'intérieur de ta boucle while sont un peu bizarres, tu devrais utiliser des elsif pour organiser tout ça un peu mieux, et éviter de tester plusieurs fois la même chose.
    Ça pourrait donner :
    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
     
      	if($_=~/^>\s(\d):(\d+)-(\d+)\s(\W)/){
    		if(($ligneprecedente==1)and($1!=1)){
    			close $fichier;
    			close (BOB);
    			return;
    		}
    		elsif($1==1){@ligne=($4.$2,$4.$3);}
    		elsif($1<$nbGenome){push(@ligne,$4.$2,$4.$3);}
    		elsif($1==$nbGenome){
    			push(@ligne,$4.$2,$4.$3);
           			select(BOB);
    			print  ("@ligne\n");
    		}
    	}
    	elsif($_=~/^=/){$ligneprecedente=1;}
    	else{$ligneprecedente=0;}
    À moins que $nbgenome puisse avoir la valeur 1, c'est équivalent et beaucoup plus lisible.
    Si $nbgenome peut avoir la valeur 1, il y a un problème un peu moins simple à résoudre.

    EDIT : ah, ninja'd par Jedaï, ça m'apprendra à me faire du thé.

  6. #6
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Citation Envoyé par Schmorgluck
    À moins que $nbgenome puisse avoir la valeur 1, c'est équivalent et beaucoup plus lisible.
    Si $nbgenome peut avoir la valeur 1, il y a un problème un peu moins simple à résoudre.
    D'ailleurs ce $nbGenome est une autre variable non-déclarée, pour le coup il ne s'agit pas vraiment d'une erreur, puisque cette variable doit effectivement venir de l'extérieur de la fonction. Je te conseillerais néanmoins de changer ceci de façon à ce que $nbGenome devienne plutôt un paramètre de la fonction, ça pourra t'éviter des erreurs gênantes et difficiles à débuguer par la suite.
    De façon générale, il faut chercher à limiter les interdépendances entre une fonction et son environnement, ça réduit les sources potentielles de bug.

    --
    Jedaï

  7. #7
    Membre chevronné
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Par défaut
    Comme je pense avoir compris ce que tu cherches à faire avec ces $push et ces if successifs, je suis en mesure de t'indiquer quelques simplifications possibles (et à la fois plus correctes et plus "Perl way"), appliquant de plus certaines remarques de Jedaï :
    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
     
    my @ligne = ();
    my $ligneprecedente = 0;
    while (<YEAST>){
      	if($_=~/^>\s(\d):(\d+)-(\d+)\s(\W)/){
    		if(($ligneprecedente)and($1!=1)){
    			close $fichier;
    			close (BOB);
    			return;
    		}
    		elsif($1<$nbGenome){push(@ligne,$4.$2,$4.$3);}
    		elsif($1==$nbGenome){
    			push(@ligne,$4.$2,$4.$3);
     			print  BOB "@ligne\n";
     			@ligne=();
    		}
     		$ligneprecedente=0;
    	}
    	elsif($_=~/^=/){$ligneprecedente=1;}
     	else{$ligneprecedente=0;}
    }
    J'ai corrigé au passage une erreur de ma version précédente qui risquait d'empêcher $ligneprecedente d'être remis à 0 . Maintenant, si je ne m'abuse, c'est vraiment équivalent, et même mieux puisque le cas où $nbGenome vaut 1 est traité correctement. Manque plus qu'à fermer YEAST quelque part.

    Une remarque supplémentaire : le nom de ta variable $ligneprecedente n'a rien pour séparer les mots qui le constituent, alors que pour $nbGenome tu as utilisé une majuscule. Bref, tu n'as pas de convention de nommage consistante, ça peut être source de confusion.
    En Perl, la coutume est plutôt de séparer les mots par un '_', mais c'est juste une coutume, l'important est d'avoir une convention et de s'y tenir. D'ailleurs, Jedaï en fait mention dans son post Comment écrire du bon code en Perl, dont il a déjà indiqué le lien plus haut : va le lire avant toute chose, tu as tout à y gagner. Souvent, écrire du bon code en Perl (comme dans tout autre langage, mais en particulier en Perl, dont une des devises est "Making Easy Things Easy & Hard Things Possible") revient à ne pas se casser le tronc pour rien : accorde à tes efforts la valeur qu'ils méritent, ne les gaspille pas.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 21/06/2011, 13h32
  2. probleme avec un return
    Par chamco dans le forum Débuter
    Réponses: 4
    Dernier message: 22/02/2008, 09h24
  3. probleme avec la touche F10
    Par b.grellee dans le forum Langage
    Réponses: 2
    Dernier message: 15/09/2002, 22h04
  4. Probleme avec fseek
    Par Bjorn dans le forum C
    Réponses: 5
    Dernier message: 04/08/2002, 07h17
  5. [Kylix] probleme avec un imagelist
    Par NicoLinux dans le forum EDI
    Réponses: 4
    Dernier message: 08/06/2002, 23h06

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