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

Fortran Discussion :

Lecture ligne fichier avec séparateur espace ou virgule


Sujet :

Fortran

  1. #1
    Membre régulier Avatar de sly078
    Inscrit en
    Avril 2008
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 116
    Points : 116
    Points
    116
    Par défaut Lecture ligne fichier avec séparateur espace ou virgule
    Bonjour,

    Tout d'abord j'ai vu les topics suivants qui s'approchaient de mon problème mais qui ne m'ont pas permis de trouver une solution :
    http://www.developpez.net/forums/d61...90-advance-no/
    http://www.developpez.net/forums/d58...s-long-record/
    http://www.developpez.net/forums/d61...cture-fichier/
    J'espère ne pas avoir loupé quelque chose...

    J'ai un fichier de données contenant des ensembles de plages de numéros. Par exemple une ligne de ce fichier peut être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SET 10 = 1000 THRU 1100, 1200, 1300 THRU 1400
    Ce qui signifie que l'ensemble 10 contient les numéros 1000 à 1100, le numéro 1200 et les numéros 1300 à 1400.

    Je veux lire ce fichier sachant que les nombres sont compris entre 0 et 9 999 999 (cad sur 1 à 7 caractères), sachant qu'il peut y avoir un nombre quelconque d'espaces entre deux records sauf pour les virgules ou il peut ne pas y avoir d'espace du tout. La même ligne pourrait donc être écrite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SET 10   =   1000 THRU 1100   ,  1200,1300 THRU   1400
    Pour l'instant j'ai utilisé des read("un format",advance='no') qui me permettent de lire les informations ensemble de caractères par ensemble de caractères. C'est le seul moyen que j'ai trouvé pour pouvoir continuer à lire sur une même ligne après un read. Mais si la ligne n'est pas formatée toujours de la même manière cela ne marche plus.

    Le plus simple serait d'utiliser le format * mais d'après mon compilateur il est incompatible avec advance='no'. Est-il possible d'utiliser le format * et de continuer à lire sur une même ligne ?

    Dans ce cas, il resterait le problème des virgules qui sont, dans ces fichiers, des séparateurs au même titre que les espaces (enfin, ce sont les plages de numéros successives d'un même ensemble de numéros qui sont séparées par des virgules). Comment travailler avec ces deux séparateurs ?

    Le seul moyen est-il de lire une ligne entière dans une variable caractère puis de parcourir cette variable ?

    Merci d'avance à ceux qui voudront bien essayer de m'aider...

    Sly

  2. #2
    Rédacteur

    Homme Profil pro
    Comme retraité, des masses
    Inscrit en
    Avril 2007
    Messages
    2 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : Suisse

    Informations professionnelles :
    Activité : Comme retraité, des masses
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 2 978
    Points : 5 179
    Points
    5 179
    Par défaut
    Salut!
    J'ai proposé une solution pour un problème analogue dans la discussion Separation de charactères (F77) (le 14/08/2009). Tu peux t'en inspirer.
    Jean-Marc Blanc

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    Si j'ai bien compris, il te faut un décodeur / interpréteur. Et la solution n'est pas simple.

    Tu dois d'abord définir une représentation interne du résultat. Ça peut être un vecteur logique (Vrai/Faux) indiquant si le nombre est dans la suite ou non. Ça peut aussi être une suite de de binômes (début, fin).

    Ensuite, pour le décodage, tu devrais utiliser un algorithme à peu près comme le suivant :
    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
     
    read(unit,'(a)') Ligne
    LngTot = len_trim(Ligne)
    PosDeb = index(Ligne,'SET') + 3 ! pour obtenir la première position après SET
    if (PosDeb < 4) erreur...
    PosFin = index(Ligne,'=') - 1 ! soit la position juste avant le =
    if (PosFin < PosDeb) erreur...
    read(Ligne(PosDeb:PosFin),*,iostat=k) NumSet
    if (k /= 0) erreur...
    Numeros(:) = .false.
    do
       PosDeb = PosFin + 2 ! soit la position juste après = ou ,
       if (PosDeb > LngTot) exit
       PosFin = index(Ligne(PosDeb:),',') + PosDeb - 2 ! soit la position juste avant ,
       if (PosFin < PosDeb) PosFin = LngTot
       PosThru = index(Ligne(PosDeb:PosFin),'THRU') + PosDeb - 1 ! soit debut de THRU
       if (PosThru < PosDeb) then ! il n'y a pas de THRU
          read(Ligne(PosDeb:PosFin),*,iostat=k) NumDeb
          if (k...)
          NumFin = NumDeb
       else   
          read(Ligne(PosDeb:PosThru-1),*,iostat=k) NumDeb
          if (k...)
          read(Ligne(PosThru+4:PosFin),*,iostat=k) NumFin
          if (k...)
       endif
       Numeros(NumDeb:NumFin) = .true.
    enddo
    Ce code devra en pratique être amélioré pour couvrir les minuscules/majuscules, les cas où NumFin < NumDeb, ou NumDeb < NumFin du bloc précédent, ...

  4. #4
    Membre régulier Avatar de sly078
    Inscrit en
    Avril 2008
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 116
    Points : 116
    Points
    116
    Par défaut
    Merci à tous les deux pour vos réponses.

    J'avais commencé à appliquer une méthode plus proche de celle de Sylvain Bergeron que de celle de FR119492 qui consistait à lire les caractères un par un.

    Sylvain Bergeron, ton code m'a permis de corriger quelques unes de mes erreurs. Pour l'instant, je n'arrive pas au bon résultat. Je repasserai rapidement par ici, soit pour copier mon code, soit pour reprendre le tien qui a l'air pas mal du tout.

    Merci encore

  5. #5
    Membre régulier Avatar de sly078
    Inscrit en
    Avril 2008
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 116
    Points : 116
    Points
    116
    Par défaut
    Bon, je bloque sur une erreur (scrogneugneu)

    Voici comment je lis la ligne :
    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
          read(11, '(A)') ligne 
          print*, ligne ! donne SET 1010 =  1104001 THRU 1104014,1104096 THRU 1104099,2300001,2310000 THRU 2310010,2310020
          nbcar = len_trim(ligne)
          jfin = index(ligne,',',back=.true.)
          print*, jfin ! jfin = 83 OK
    
          do while (ch1.ne.'=')
            read(ligne(i:),*) ch1
            i=i+1		
          end do
          print*, i ! i=10 OK
          read(ligne(1:i-1),*)ch4, numSet
          print*,ch4, numSet ! numSet = 1010 OK
    	  
          do while (j2.le.jfin)
            print*,j,j2	! j = 0 ; j2 = 0 OK
            j = index (ligne(j2+1:),',',back=.false.)
            print*,j,j2	! j = 33 ; j2 = 0 OK	
            j2 = index (ligne(j+1:),',',back=.false.)
            print*,j,j2   ! j = 33 ; j2 = 21 FAUX
            read(ligne(j+1:j2-1),*)plage !Plante parce que j2 < j
    
            read(plage,*)numElemMin
            do while (ch1.eq.' ')
              read(plage,*)ch1
            end do
            if (ch1.eq.'T') then
              read(plage,*)numElemMax
              write(12,1050) numElemMin,numElemMax,numSet
            else
              write(12,1050) numElemMin,numElemMin,numSet
            end if
          end do
    Je cherche les paires de ',' successives et je mets ce qu'il y a entre ces deux ',' dans une autre variable caractère plage. J'ai mis en commentaire dans le code les premières valeurs que j'obtiens à côté des print. J'ai mis en rouge là où ca pose problème : la fonction index trouve bien la première virgule à la 33e colonne. Mais la seconde est trouvée à la colonne 21 (c'est la position du T du premier THRU).

    Je comprends pas ce qu'il se passe. Si je n'arrive pas à corriger, je passerai par la solution de Sylvain Bergeron qui n'utilise la position que d'une virgule à la fois.

  6. #6
    Membre régulier Avatar de sly078
    Inscrit en
    Avril 2008
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 116
    Points : 116
    Points
    116
    Par défaut
    Erreur (à deux balles) trouvée !

    Il faut que je fasse
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    j2 = index (ligne(j+1:),',') + j
    Au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    j2 = index (ligne(j+1:),',')

  7. #7
    Membre régulier Avatar de sly078
    Inscrit en
    Avril 2008
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 116
    Points : 116
    Points
    116
    Par défaut
    Je suis parvenu à une solution :
    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
          read(11, '(A)') ligne 
          print*, ligne
          nbcar = len_trim(ligne)
          jfin = index(ligne,',',back=.true.)
          print*, jfin
     
          do while (ch1.ne.'=')
            read(ligne(i:),*) ch1
            i=i+1		
          end do
     
          read(ligne(1:i-1),*)ch4, numSet
          j2=i+1
     
          do while (j2.lt.jfin)
            j = j2
            j2 = index (ligne(j+1:),',') + j
            read(ligne(j+1:j2-1),'(A)')plage
            read(plage,*)numElemMin
     
            posThru = index(plage(1:),'THRU')	
            if (posThru.gt.0) then
              read(plage(posThru+4:),*)numElemMax
              write(12,1050) numElemMin,numElemMax,numSet
            else
              write(12,1050) numElemMin,numElemMin,numSet
            end if	
          end do
     
          read(ligne(jfin+1:nbcar),'(A)')plage
          read(plage,*)numElemMin
          posThru = index(plage(1:),'THRU')	
          if (posThru.gt.0) then
            read(plage(posThru+4:),*)numElemMax
            write(12,1050) numElemMin,numElemMax,numSet
          else
            write(12,1050) numElemMin,numElemMin,numSet
          end if
    C'est pas très propre mais pour l'instant cela va rester comme ça. J'ai continué à utiliser ma chaine plage et comme je veux juste écrire ce que contient cette chaîne avec une autre mise en forme dans un autre fichier cela me convient très bien.

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

Discussions similaires

  1. Lecture de fichier avec séparateur décimal ","
    Par noir_desir dans le forum Scilab
    Réponses: 2
    Dernier message: 04/02/2014, 10h28
  2. Lecture d'un fichier avec des espaces
    Par davasm dans le forum Linux
    Réponses: 6
    Dernier message: 02/04/2009, 11h26
  3. lecture de fichier avec ftplib
    Par yggdrazil dans le forum Réseau/Web
    Réponses: 2
    Dernier message: 14/10/2006, 21h47
  4. Téléchargement de fichier avec un espace
    Par nicotine002 dans le forum Langage
    Réponses: 3
    Dernier message: 06/08/2006, 19h25
  5. [LG]Lecture de fichier avec une adresse internet
    Par forbin dans le forum Langage
    Réponses: 8
    Dernier message: 09/02/2005, 19h00

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