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 :

lisp lire un fichier


Sujet :

Lisp

  1. #1
    Membre à l'essai
    Femme Profil pro
    Étudiant
    Inscrit en
    Avril 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 31
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2014
    Messages : 18
    Points : 13
    Points
    13
    Par défaut lisp lire un fichier
    Bonjour désolé de revenir sur ce forum mais je rencontre un nouveau problème dans la lecture d'un fichier. J'ai un fichier de ce type:
    --------------------------
    - grille : facile
    --------------------------
    4 4
    #1#3
    #3#2
    1###
    2#44

    mon but est le suivant: sauter les ligne qui commencent par un "-" ainsi que la ligne 4 4 qui permet de connaitre la hauteur et la largeur de la grille. Voilà mon code pour lire le fichier simplifié suivant:

    4 4
    #1#3
    #3#2
    1###
    2#44

    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
     
    (with-open-file (stream "grille.txt")
      (print (read-char stream nil))
      (peek-char t stream nil)
      (print (read-char stream nil))
      (print (read-line stream nil))
      (print (read-line stream nil))
      (print (read-line stream nil)))
     
     
    """La partie suivant n'est pas correctement fonctionnelle""" 
     
     
     
    (with-open-file (stream "grille.txt")
      (defparameter x (read stream nil))
      (defparameter y (read stream nil))
      (read-line stream nil)
      """Première ligne lue avec succès, ça se gâte après"""
      """Idée : utiliser read-line, qui renvoie une chaine de caractères (plutôt que read-char qui renvoie un char ou read qui renvoie un objet) et travailler dessus)"""
    sinon pour sauter les lignes qui commencent par un tiret comme suit

    --------------------------
    - title : that one is easy
    --------------------------
    4 4

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    (defun lecture ()
      (with-open-file (str "lol.txt")
        (loop while (not(null ligne)) do
         (let (a (read-line str nil))
           (if((string-equal "-" (car a )))
              "Rien"
              (print a))))))
    comme vous voyez j'ai un problème : je ne sais pas comment faire pour ecrire la condition de passage a la ligne (j'ai mis "rien")

    cordialement

  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
    Citation Envoyé par lhareen Voir le message
    Bonjour désolé de revenir sur ce forum
    Salut ! Mais non, le forum devient un peu plus animé.

    Tout d'abord, comme ton fichier est ordonné par les lignes, il ne vaut pas la peine de le lire caractère après caractère. On peut le lire par les lignes.

    L'idée la plus simple c'est d'écrire une fonction qui renvoie la liste des lignes d'un fichier. (Je parié que tout le monde en a déjà écrit plusieurs. ) La façon traditionnelle et idiomatique de créer une liste c'est d'utiliser PUSH/NREVERSE: d'abord on collecte les éléments en les CONSant l'un après l'autre sur la liste vide (ce qui est « bon marché ») et finalement on renverse la liste à l'aide de NREVERSE (ce qui est « bon marché » aussi et en plus n'est pas dangereux, car on vient de construire la liste à zéro et par conséquent on a le droit de le détruire). Je pense que dans ce cas LOOP n'est pas beaucoup plus expressif que le bon vieux DO:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    (defun read-file-lines (f)
      (with-open-file (in f :direction :input)
        (let ((res nil))
          (do ((line (read-line in nil) (read-line in nil)))
              ((null line) (nreverse res))
            (push line res)))))
    Maintenant il ne reste que filtrer la liste pour en enlever les chaînes commençantes par un tiret et ensuite enlever aussi le premier élément qui doit representer les dimensions. La fonction de filtre en lisp est nommée REMOVE-IF-NOT. D'ailleurs, remarque qu'en lisp les chaînes sont tableaux de caractères et c'est une bonne idée de comparér les caractères à l'aide des fonctions spécialles, par exemple CHAR/=. Donc, par exemple,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (rest (remove-if-not (lambda (line)
                           (char/= (char line 0) #\-))
                         (read-file-lines "grille.txt")))
    CAR ne fonctionne pas avec les chaînes parce qu'elles ne sont pas listes. Il faut utiliser CHAR.

    Bien évidemment, on peut intégrer un test dans READ-FILE-LINES (par exemple écrire une fonction FILTER-FILE-LINES qui accepte entre outre une fonction de test).

    Mais je veux montrer une autre solution pour démonstrer des techniques plus avancées. Par exemple, on veut avoir un opérateur de boucle analogique à DOLIST qui nous permettrait parcourir les lignes d'un fichier. Donc la solution serait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    (let ((res '()))
      (do-file-lines (line "grille.txt" (rest (nreverse res)))
        (print line)
        (unless (char= (char line 0) #\-)
          (push line res))))
    Mais cette solution ne marche pas, car l'opérateur n'existe pas encore. Mais il n'est pas impossible le créer.

    DO-FILE-LINES peut avoir la syntaxe suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (do-file-lines (variable fichier &optional résultat)
      n'importe-quoi)
    ce qui équivaut à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    (with-open-file (in fichier :direction :input)
      (do ((variable (read-line in nil) (read-line in nil)))
          ((null variable) résultat)
        n'importe-quoi)
    Maintenant le TRUC. En lisp, le programme est composé de LISTES, et lisp sait très bien travailler avec les listes. Notamment, il est très facile de transformer un fragment de code en un autre fragment de code. Ça ce fait à l'aide des macros. Dans notre cas le macro est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    (defmacro do-file-lines ((line file &optional result) &body body)
      (let ((in (gensym)))
        `(with-open-file (,in ,file :direction :input)
           (do ((,line (read-line ,in nil) (read-line ,in nil)))
               ((null ,line) ,result)
             ,@body))))
    C'est vrai qu'il y a quelques notations bizarres (ou plutôt insolites) et je ne vais pas l'expliquer en détail (pourtant je l'expliquerai si tu veux), mais avec ça la solution précédente marche ! En effet, ce n'est qu'une petite publicité de lisp pour ma part. Il n'y a pas beaucoup de langages ou l'on peut créer de nouvelles boucles si facilement, eh?

    Je veux encore dire que DEFPARAMETER déclare des variables globales et dynamiques, alors que LET déclare des variables locales et lexiques. Je pourrais expliquer la signification de ces termes si tu veux, mais je pense qu'il est déjà clair qu'il ne faut pas utiliser l'un au lieu de l'autre.

Discussions similaires

  1. [Servlet][EJB]lire un fichier à partir de mon bean
    Par kimausoleil dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 13/02/2004, 14h26
  2. [MFC] lire un fichier en int
    Par Kevgeii dans le forum MFC
    Réponses: 3
    Dernier message: 23/01/2004, 09h32
  3. Réponses: 5
    Dernier message: 11/01/2004, 20h17
  4. Lire un fichier de 50 gb
    Par Maryves dans le forum MFC
    Réponses: 2
    Dernier message: 08/01/2004, 14h08
  5. Lire le fichier du port série
    Par saibe dans le forum Linux
    Réponses: 7
    Dernier message: 09/04/2003, 09h29

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