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

Lisp Discussion :

découper un fichier en 2 fichiers


Sujet :

Lisp

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2016
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Bâtiment

    Informations forums :
    Inscription : Août 2016
    Messages : 26
    Points : 15
    Points
    15
    Par défaut découper un fichier en 2 fichiers
    bonjour,

    je suis complètement bloqué depuis plusieurs jours sur un exercice.

    Il s'agit de découper un fichier nommé alphabet.txt qui contient tous les caractères utilisés en français sous différentes représentation en 2 fichiers , l'un comprenant les codes numériques correspondants et l'autre les caractères en représentation lisp.

    voici mon code :

    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
    (defun alphabet (fichier)
       (setq f (open fichier :direction :input :if-does-not-exist :error))
       (setq code "")
       (setq char "")
          (loop
             (cond
                ((null code)) )
             (setq code (open "alphabet_code.txt" :direction :output :if-does-not-exist :create :if-exists :append))
             (prin1 (read-from-string (read-line f nil nil) nil nil) code) (terpri code) (close code) )
       (close f)
       (setq f (open fichier :direction :input :if-does-not-exist :error))
          (loop
             (cond
                ((null char)) )
             (setq char (open "alphabet_char.txt" :direction :output :if-does-not-exist :create :if-exists :append))
             (prin1 (code-char (read-from-string (read-line f nil nil) nil nil)) char) (terpri char) (close char) )
       (close f) )
    le problème est sur la gestion de fin de fichier.
    le premier fichier (alphabet_code.txt) se fait correctement mais l'erreur qui est générée a la fin de la première boucle empêche la suivante de se faire.

    les options pour gérer ceci dans les fonctions read-from-string et read-line semblent inactives.
    j'ai essayé différentes combinaisons avec nil dans l'expression (read-from-string (read-line f nil nil) nil nil) , mais rien n'y fait.

    Suivant ces combinaisons , soit c'est une erreur qui dit que le stream d'entrée est épuisé soit que nil n'est pas string


    Pouvez vous n'aider car je ne peut plus avancer.

    merci

  2. #2
    Membre actif
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Mai 2013
    Messages : 152
    Points : 275
    Points
    275
    Par défaut
    Bonjour !

    Tout d’abord, je ne comprends pas très bien ni le problème, ni ce que fait le code. Comment ça, « tous les caractères... sous différentes représentations »? Donc, il ne s’agit pas d’un simple fichier de texte ? Quelles sont les « représentations »? Bref, pourrais-tu montrer un example d’un fichier donné et des fichiers correspondents qu’il faut obtenir ?

    Ce que je ne comprends pas dans le code, c’est surtout pour quelle raison on utilise cette combinaison de READ-LINE et READ-FROM-STRING. Cela semble inutile, mais ça a quelque chose à faire, peut-être, avec les « répresentation » dont on ne sait rien ?

    Cela dit, quelques défauts se manifestent déjà dans le code.

    Tout d’abord, il faut absolument déclarer les variables ! C’est pas Python, un simple setq ne déclare pas une variable ! Les operateurs d’affectation (il vaut mieux employer SETF tout le temps) changent la valeur d’une variable déjà existente, ils ne la déclarent pas ! Pour déclarer une variable locale en lui attribuant une valeur, on utilise LET et d’autres constructions, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    (let ((x 1)
          (y 2))
      (+ x y))
    ==> 3
    Qui plus est, dans un code plus fonctionnelle, on a tendance de ne pas changer la valeur d’une variable, donc on peut souvent se passer des operateurs d’affectation.

    Quant’aux fichiers, la règle générale dit qu’il faut fermer les fichiers ouverts. Il faut fermer un fichier même si une erreur se passe quand il est ouvert. Il y a un operateur qui effectue les « nettoyages » de ce sorte (unwind-protect), mais tout est plus facile dans le cas de fichiers. Notamment, on n’emploie presque jamais OPEN et CLOSE, mais on ouvre les fichiers à l’aide de WITH-OPEN-FILE. Les premier argument de WITH-OPEN-FILE est le nom du flux et les suivants sont identiques à ceux de OPEN, et il est important que WITH-OPEN-FILE tient à fermer le fichier à la fin, quoi que se passe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (with-open-file (f fichier :direction :input :if-does-not-exist :error)
      (ceci f)
      (cela f))
    Enfin, ça ne vaut pas la peine de lire le fichier deux fois et, bien sûr, de ouvrir et fermer un fichier toutes les fois qu’un veut y écrire quelque chose. Il vaut mieux ouvrir d’abord tous les fichiers en obtenant trois flux et ensuite travailler avec les flux dans une boucle.

    Donc, pour discuter le problème, je pense qu’il est nécessaire que tu donnes plus de renseignements, surtout des examples des donnés et du résultat correspondent.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2016
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Bâtiment

    Informations forums :
    Inscription : Août 2016
    Messages : 26
    Points : 15
    Points
    15
    Par défaut
    Bonjour,

    tout d'abord merci de m'avoir répondu et pour tous tes conseils.
    alors le but de l'exercice est de créer 2 fichiers texte à l'aide d'une seule fonction qui contient pour l'un les codes numériques des caractères français (de 33 à 255) et pour l'autre les mêmes caractères mais en représentation lisp.
    ces fichiers doivent êtres créés à partir d'un autre fichier texte que j'ai créé dans un exercice précédent et qui a la forme suivante :
    code du caractère ; tabulation ; sa représentation réelle ; tabulation ; sa représentation lisp

    voici une partie du fichier :

    33 ! #\!
    34 " #\"
    35 # #\#
    36 $ #\$
    37 % #\%
    38 & #\&

    l'idée était de récupérer dans une première boucle le premier élément de chaque ligne (code) , d' où les fonctions READ-FROM-STRING et READ-LINE ensemble.
    et ensuite dans une deuxième boucle de récupérer la même chose mais en le convertissant en code-char.

    Mon premier problème rencontré est que si je mets dans la condition d'arrêt de la boucle une expression qui contient READ-LINE , la première ligne ne se trouve pas le fichier de sortie.
    Mon deuxième est que si je fais l'ouverture du fichier dès le départ avant la boucle comme tu le préconise et ce qui été mon intention de départ , je ne sais pas pourquoi mais le premier élément de la ligne qui est récupéré n'est pas le code mais celui d'après , la tabulation et je me retrouve donc avec un fichier vide.
    Voilà pourquoi j'ai choisi d'ouvrir et fermer le fichier à chaque tour de boucle avec l'option APPEND. Il n'y que comme ça que j'ai réussi à avoir quelque chose , le premier fichier est bien créé conformément à ce que j' attend mais mon incapacité à gérer la fin de fichier me crée toujours une erreur qui empêche la fonction de continuer et de créer le deuxième fichier.

    Et pour les affectations je ne savais pas car dans mon cours je n'ai vu que SETQ , tout comme WITH-OPEN-FILE , j'ai appris que OPEN.
    .
    je vais essayé avec WITH-OPEN-FILE.

    Voilà , j'espère que c'est plus clair , si tu as d'autre conseils .

    merci

  4. #4
    Membre actif
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Mai 2013
    Messages : 152
    Points : 275
    Points
    275
    Par défaut
    Je pense que si tu écriras
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (with-open-file (code-out "alphabet_code" :direction :output :if-exists :supersede)
      (with-open-file (char-out "alphabet_code" :direction :output :if-exists :supersede)
        boucle))
    tout va fonctionner à merveille. C’est-à-dire, si la boucle sera correcte.

    Qu’est-ce que tu dois faire dans la boucle ?

    D’abord, tu lis une ligne du flux F à l’aide de READ-LINE. Par défaut, cette fonction produit une erreur à la fin du fichier, mais on peut l’éviter en fournissant NIL comme le troisième argument, donc (read-line f nil) renvoie NIL à la fin du fichier. En tout cas, tu vois que tu ne peux pas appliquer READ-FROM-STRING au résultat, parce qu’il n’est pas nécessairement une chaîne.

    Donc, ça vaut le peine de introduire une variable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (let ((line (read-line f nil)))
      ...)
    Maintenant il faut vérifier si LINE est NIL ou pas. On peut employer, par exemple, la fonction NULL: (null ligne), et l’opérateur conditionnel IF.

    Si LINE est NIL, nous sommes à la fin du fichier, donc il n’y a plus rien à faire. Il est le temps de sortir de la boucle. La forme simple de LOOP que tu emploies est si simple, qu’elle n’offre même pas de façon d’en sortir. À ce fin on peut employer la forme (return):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (if (null line)
        (return)
        ...)
    Voilà la condition de sortie. Dans ton code, il n’y a pas de (return) et en plus, tu testes si le flux est NIL, ce qui est absurde.

    Le cas général est quand LINE est en effet une chaîne. Je vois que dans ton code, tu essaies de lire le fichier deux temps seulement pour extraire le nombre en tête de chaque ligne en ignorant le reste de la ligne (ce qui n’est pas fameux). Maintenant, on ne le fait qu’une fois ; d’ailleurs, si tu n’est pas intéressé que dans le nombre, ça vaut la peine d’utiliser la fonction PARSE-INTEGER qui fait exactement cela : lit un nombre écrit dans une chaîne. En effet, les fonctions du type READ sont « hackish » et non sans danger, donc il faut ce rendre compte de ce que l’on est en traîn de faire. En revanche, PARSE-INTEGER est simple et acceptable. Donc, dans la branche « else » on écrit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (let ((code (parse-integer line :junk-allowed t)))
      ...)
    On ajoute :JUNK-ALLOWED T parce que le contenu de la ligne ne se borne pas au nombre.

    À propos, dans ton code la variable CODE est d’abord une chaîne vide en ensuite, un flux ; chez moi, c’est un integer (en effet, le code d’un caractère), ce qui me semble plus intuitif.

    Tu as donc ton code et tu l’écris dans le flux CODE-OUT et tu écris le caractère correspondant dans CHAR-OUT. Il y a plusieures façons de le faire, mais c’est peut-être plus claire d’employer FORMAT:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (format code-out "~D~%" code)
    (format char-out "~C~%" (code-char code))
    FORMAT, c’est comme printf, mais meilleur. Dans le cas plus simple, la chaîne de format est un modèle avec des « troux » marques par tildes. ~D signifie « insérer un nombre », ~C veut dire « insérer un caractère », et ~% signifie la fin de ligne.

    Si tes manuels ne t’apprennent pas à déclarer les variables, ils ne valent rien. Je t’ai démontré comment ça s’écrit dans un lisp assez idiomatique. Il te reste que d’assembler les morceaux.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2016
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Bâtiment

    Informations forums :
    Inscription : Août 2016
    Messages : 26
    Points : 15
    Points
    15
    Par défaut
    Salut,

    ça marche nickel

    voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    (defun alphabet (fichier)
       (with-open-file  (f fichier :direction :input :if-does-not-exist :error)
          (with-open-file (code-out "alphabet_code" :direction :output :if-exists :supersede)
             (with-open-file (char-out "alphabet_char" :direction :output :if-exists :supersede)
                (loop
                   (let ((line (read-line f nil)))
                      (cond
                         ((null line) (return))
                         ((let ((code (parse-integer line :junk-allowed t)))
                            (format code-out "~D~%" code)
                            (format char-out "~C~%" (code-char code)) ) ) ) ) ) ) ) ) )
    Merci beaucoup pour ton aide

  6. #6
    Membre actif
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Mai 2013
    Messages : 152
    Points : 275
    Points
    275
    Par défaut
    Très bien !

    Je pense que ça vaut la peine de ne pas coder en dur les noms des fichiers, il vaut mieux les fournir comme arguments. Et moi, j’utiliserais IF au lieu du COND, mais ce n’est pas important.

    Je suis content d’avoir pu t’aider.

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

Discussions similaires

  1. [2.x] Découper la traduction en plusieurs fichiers mais un seul domaine
    Par khayyam90 dans le forum Symfony
    Réponses: 0
    Dernier message: 05/02/2015, 09h28
  2. [ZF2.x] translator - découper sa traduction en plusieurs fichiers
    Par narmataru dans le forum Zend Framework
    Réponses: 4
    Dernier message: 19/03/2013, 22h12
  3. Réponses: 15
    Dernier message: 28/11/2008, 17h57
  4. Découper le contenu d'un fichier texte
    Par Vil'Coyote dans le forum Applications et environnements graphiques
    Réponses: 6
    Dernier message: 17/11/2008, 08h45
  5. Découper une classe en plusieurs fichiers de code
    Par Christophe_ dans le forum Visual Studio
    Réponses: 1
    Dernier message: 21/06/2007, 20h54

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