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 :

lire valeurs séparées par point-virgule


Sujet :

Fortran

  1. #1
    Membre confirmé
    Homme Profil pro
    Chercheur - Programmeur amateur
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chercheur - Programmeur amateur
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut lire valeurs séparées par point-virgule
    Bonjour à tous

    voilà, je rencontre un problème pour lire un fichier. c'est un fichier contenant des valeurs (réelles, entières et caractères), séparées par des point-virgules, et dont le format n'est pas fixe (histoire de compliquer encore un peu la chose) (ie le même paramètre peut contenir un entier sur 1 ou 2 chiffre suivant qu'il est inférieur ou supérieur à 9 par exemple)
    Ma question est donc a la fois simple et problématique : comment lire ce foutu fichier??

    - le point-virgule n'est pas reconnu comme délimiteur par le fortran 90
    - je ne peux pas utiliser un format de lecture

    bref, I need help

    merci d'avance

  2. #2
    Membre Expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Par défaut
    petit post ressemblant a ce que tu souhaite faire.

    http://www.developpez.net/forums/d61...r/#post3655778

  3. #3
    Membre confirmé
    Homme Profil pro
    Chercheur - Programmeur amateur
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chercheur - Programmeur amateur
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut
    je viens de jeter un oeil. Effectivement ca marche, mais niveau optimisation
    pour info, les fichiers que j'ai a lire pèsent la bagatelle de 360 Mo

  4. #4
    Membre Expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Par défaut
    Citation Envoyé par iznogoud_23 Voir le message
    je viens de jeter un oeil. Effectivement ca marche, mais niveau optimisation
    pour info, les fichiers que j'ai a lire pèsent la bagatelle de 360 Mo
    ça c'est une autre histoire, tu n'avais pas donnée de volumétrie ....


    Autrement tu peux voir du coté du format pour le read.
    http://www.cs.mtu.edu/~shene/COURSES...05/format.html

  5. #5
    Membre confirmé
    Homme Profil pro
    Chercheur - Programmeur amateur
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chercheur - Programmeur amateur
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut
    Citation Envoyé par jabbounet Voir le message
    ça c'est une autre histoire, tu n'avais pas donnée de volumétrie ....
    Je sais, désolé pour ce manque de précision initial

    Citation Envoyé par jabbounet Voir le message
    Autrement tu peux voir du coté du format pour le read.
    http://www.cs.mtu.edu/~shene/COURSES...05/format.html
    Je ne peux justement malheureusement pas utiliser de format, vu que les données contenues dans les fichiers n'ont pas un format fixe

    HS : j'ai une grosse envie de pendre l'espèce d'ab****i qui a pondu ces fichiers....

    En tout cas, merci pour ton aide jabbounet

  6. #6
    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
    Par défaut
    Le format libre utilisé pour tes fichiers ne devrait pas être à ce point inefficace...

    La solution que tu utilises peut être réorganisée comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    character (100) :: Ligne
    integer :: k1,k2
    ...
    read(11,'(a)') Ligne
    k1 = 0
    do
       k2 = index(Ligne(k1+1:),';') + k1
       if (k2 == k1) exit
       Ligne(k2:k2) = ',' ou char(9) ou ' '
       k1 = k2
    enddo
    read(Ligne,*) liste de variables
    ...
    Ce qui simplifie la modification du programme. Tu peux évidemment mettre le bout de code servant à convertir le délimiteur dans une fonction...

  7. #7
    Membre émérite
    Avatar de Ladgalen
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Novembre 2007
    Messages
    466
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Enseignant Chercheur

    Informations forums :
    Inscription : Novembre 2007
    Messages : 466
    Par défaut
    Bonjour

    J'ai ressorti de mes tirroirs un début de subroutine que j'avais écris dans le but de découper une chaine de caractère. Je l'ai retravaillé un peu pour pouvoir choisir le découpage suivant un certain masque (=espace, virgule ou tout autre de longueur 1).

    Je met ici un programme qui utilise ma subroutine. Ma question est la suivante : Est ce qu'il serait possible de se passer de l'envoi dans la routine parse de la longueur de la chaine ?

    Toute suggestion autres sur le programme est bien sur plus que bienvenue !

    Merci

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
     
    program test
     
      implicit none
     
      integer :: i
      character(len=100) :: chaine =",,bonjour,,mon nom,,,est,toto,"
      character(len=100),dimension(100) :: tabchaine
      integer::n
     
      write(*,*)"*"//trim(chaine)//"*"
      write(*,*)
     
      call parse(100, chaine, n, tabchaine,",")
     
      write(*,*)"il y a",n,"mots"
      do i = 1, n
        write(*,*) i,"  *",trim(tabchaine(i)),"*"
      end do
     
    end program test
     
      subroutine parse( length, chaine, nmot, tabchaine, masque)
        ! decoupage de chaine suivant le mask
        ! par defaut le masque est un espace
     
        implicit none
     
        ! arguments :
        integer, intent(in)                    :: length
        character(len=length), intent(in)      :: chaine
        character(len=1), optional, intent(in) :: masque
        character(len=length), dimension(length), intent(out) :: tabchaine
        integer, intent(out) :: nmot
     
        ! variables locales :
        integer :: i, k, nmask
        integer :: longueurvrai
        integer, dimension(0:length) :: maskpos
        integer, dimension(length,2) :: maskborne
        character(len=length)        :: locchaine
        character(len=1)             :: mask
        logical                      :: fin, blanc
     
        tabchaine(:) = ""
        maskpos(:)   = -1
        maskpos(0)   = 0
        maskborne(:,:) = -1.d0
     
        longueurvrai = len( trim( chaine ) )
        locchaine    = adjustl( chaine )
     
        ! on decoupe suivant mask
        if( .not. present(masque) ) then
           mask = " "
           blanc = .true.
        else
           mask = masque
        end if
     
        ! nombre de masque
        k = 0
        do i = 1, longueurvrai
          if ( locchaine(i:i) == mask ) then
            k = k + 1
            maskpos(k) = i
          end if
        end do
     
        nmask = k
        nmot  = k +1
        if( nmask >= longueurvrai ) then
          write(*,"('chaine : ', a)") chaine
          write(*,"('mask   : ', a)") mask
          write(*,"('nmask  : ', i12)") nmask
          stop "erreur subroutine parse"
        end if
     
        ! calcule les bornes des mots
        do i = 1, nmask+1
          maskborne(i,1) = maskpos(i-1) + 1
          maskborne(i,2) = maskpos(i) - 1
     
          if( maskborne(i,2) < 0 ) then
            maskborne(i,2) = longueurvrai
          end if
        end do
     
        ! traite les cas ou plusieurs masques etaient present
        fin = .false.
        do while ( .not. fin )
     
          fin = .true.
     
          do k = 1, nmask + 1
            if( maskborne(k,1) > maskborne(k,2) ) then
              do i = k, nmask + 1
                maskborne(i,1) = maskborne(i+1,1)
                maskborne(i,2) = maskborne(i+1,2)
              end do
              fin = .false.
              nmot = nmot - 1
              exit
            end if
          end do
     
        end do
     
        ! decoupage
        do i = 1, nmot
          tabchaine(i)(1:) = locchaine( maskborne(i,1) : maskborne(i,2) )
        end do
     
      end subroutine parse

  8. #8
    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
    Par défaut
    Chaine devrait être déclaré character (len=*). Les autres référence à Length peuvent être remplacées par len(Chaine), incluant :

    character(len=len(Chaine)), dimension(len(Chaine)), intent(out) :: tabchaine

    Pour le reste, je n'ai pas lu à fond, mais j'ai observé :

    longueurvrai = len( trim( chaine ) )
    locchaine = adjustl( chaine )

    Si adjustl a un effet, longueurvrai ne doit plus être vrai ! De plus, len(trim()) n'est pas très efficace. Je propose donc :

    locchaine = adjustl( chaine )
    longueurvrai = len_trim( locchaine )

    Mes routines du genre arrête en général après le calcul des maskborne() et les retournent. Le programme appelant doit alors gérer le découpage. C'est une question de style...

    Finalement, des espaces consécutifs ne sont pas comptés comme autant de séparateurs lorsque le séparateur est l'espace. Je ne crois pas que ta routine traite cette situation correctement...

  9. #9
    Membre émérite
    Avatar de Ladgalen
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Novembre 2007
    Messages
    466
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Enseignant Chercheur

    Informations forums :
    Inscription : Novembre 2007
    Messages : 466
    Par défaut
    Citation Envoyé par Sylvain Bergeron Voir le message
    Chaine devrait être déclaré character (len=*). Les autres référence à Length peuvent être remplacées par len(Chaine), incluant :

    character(len=len(Chaine)), dimension(len(Chaine)), intent(out) :: tabchaine
    J'avais vu ça, mais visiblement le (len=*) est déconseillé et supprimé de la norme en 95 ... j'ai lu ça je ne sais plus où dans un cours sur le net. Du coup je l'avais remplacé par len(chaine) sauf que dans la déclaration de chaine ce n'est pas autorisé.

    Citation Envoyé par Sylvain Bergeron Voir le message
    Pour le reste, je n'ai pas lu à fond, mais j'ai observé :

    longueurvrai = len( trim( chaine ) )
    locchaine = adjustl( chaine )

    Si adjustl a un effet, longueurvrai ne doit plus être vrai ! De plus, len(trim()) n'est pas très efficace. Je propose donc :

    locchaine = adjustl( chaine )
    longueurvrai = len_trim( locchaine )
    Bien vu , ça n'a pas beaucoup d'importance pour la suite mais ça fait pas propre.

    Citation Envoyé par Sylvain Bergeron Voir le message
    Finalement, des espaces consécutifs ne sont pas comptés comme autant de séparateurs lorsque le séparateur est l'espace. Je ne crois pas que ta routine traite cette situation correctement...
    Je ne comprend pas bien ce que tu veux dire. Si j'ai plusieurs séparateurs, qu'il s'agisse d'espace ou autre je ne les comptes pas comme des mots. Si tu regardes l'exemple de mon programme test, j'ai quelque fois plusieurs virgule et il le traite correctement et ça marche aussi avec des espaces.

    Si tu as un peu de temps à l'occasion pour essayer de rendre le truc un peu robuste ça m'intéresse.

    Merci

  10. #10
    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
    Par défaut
    Je croyais avoir répondu hier, mais la réponse n'est pas là. Bizarre...

    Citation Envoyé par Ladgalen Voir le message
    J'avais vu ça, mais visiblement le (len=*) est déconseillé et supprimé de la norme en 95 ... j'ai lu ça je ne sais plus où dans un cours sur le net.
    Je ne sais pas où tu as pu voir ça, mais le code suivant est tout à fait légal et recommandé en F95 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    subroutine abc(s)
      character (*) :: s
    ...
    Citation Envoyé par Ladgalen Voir le message
    Je ne comprend pas bien ce que tu veux dire. Si j'ai plusieurs séparateurs, qu'il s'agisse d'espace ou autre je ne les comptes pas comme des mots. Si tu regardes l'exemple de mon programme test, j'ai quelque fois plusieurs virgule et il le traite correctement et ça marche aussi avec des espaces.
    Je me suis mal exprimé. Ce que je voulais dire, c'est que normalement, les espaces multiples ne comptent que pour 1 alors que les autres séparateurs, s'ils sont multiples, comptent tous. Ainsi, la chaîne " un deux" (avec 2 espaces entre un et deux) produit généralement deux éléments (un et deux) alors que ",un,,deux" produit normalement 4 éléments, dont le premier et le troisième sont vides.

  11. #11
    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
    Par défaut
    J'avais oublié un dernier truc.

    Je traite souvent des fichiers CSV séparés par des point-virgules (pour éviter le conflit avec les virgules décimales) et ayant des noms de colonne à la première ligne. Les utilisateurs produisent les données à partir d'Excel. Les dernières fois que j'ai eu besoin de lire un tel fichier, j'ai changé de stratégie et j'étais assez satisfait du résultat. Au lieu de décoder toute la ligne dans une routine comme tu fais, j'ai fait une routine qui extrait seulement l'élément demandé.

    Je peux donc lire l'entête, et trouver la position des colonnes requises :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    read(Fichier,'(a)') Ligne
    k = 1
    PosVar1 = 0
    PosVar2 = 0
    PosVar3 = 0
    do
       call Extrait(Ligne,NomCol,k)
       if (len_trim(NomCol) == 0) exit
       if (NomCol == "NomVar1") PosVar1 = k
       if (NomCol == "NomVar2") PosVar2 = k
       if (NomCol == "NomVar3") PosVar3 = k
       k = k + 1
    enddo
    Puis, je peux extraire les données :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    read(Fichier,'(a)') Ligne
    call Extrait(Ligne,StrVar,PosVar1); read(StrVar,*) Var1
    call Extrait(Ligne,StrVar,PosVar2); read(StrVar,*) Var2
    call Extrait(Ligne,StrVar,PosVar3); read(StrVar,*) Var3
    ...
    La routine extrait ressemble à :
    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
     
    subroutine Extrait(S,R,n)
       character (*), intent(in) :: S
       character (*), intent(out) :: R
       integer, intent(in) :: n
     
       integer PosDeb,PosFin
     
       if (n == 1) then
          PosDeb = 1
       else
          PosDeb = IndexN(S,';',n-1) + 1
          if (PosDeb == 1) then
             R = ''
             return
          endif
       endif
       PosFin = IndexN(S,';',n) - 1
       if (PosFin == -1) PosFin = len_trim(S)
       R = S(PosDeb:PosFin)
    contains
       integer function IndexN(S1,S2,n)
       character (*), intent(in) :: S1,S2
       integer, intent(in) :: n
       integer k,depl
       depl = 0
       k = 1
       do
          IndexN = index(S1(depl+1:),S2) + depl
          if (IndexN == depl) then
             IndexN = 0
             return
          endif
          if (k == n) return
          depl = IndexN
       enddo
       end function
    end subroutine

  12. #12
    Membre émérite
    Avatar de Ladgalen
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Novembre 2007
    Messages
    466
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Enseignant Chercheur

    Informations forums :
    Inscription : Novembre 2007
    Messages : 466
    Par défaut
    Merci pour tes conseils, j'ai adapté mon code en fonction de ce que tu as dis.

    • La routine ne demande plus la taille des chaines en entrée.
    • Le séparateur peut être une chaine de longueur quelconque.
    • Elle renvoie un tableau dimensionné au nombre d'éléments trouvé.
    • Le nombre d'élément est le nombre de mot si le séparateur est un espace où alors il est égale au nombre de séparateur.


    Par contre j'ai préféré resté sur une routine qui renvoie les éléments dans un tableau.

    Voilà un exemple de sortie :

    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
     
    > exe
     
     '  bonjour  mon nom   est toto'
     
     il y a           5 mots
               1   'bonjour'
               2   'mon'
               3   'nom'
               4   'est'
               5   'toto'
     
     ',,bonjour,mon nom,,est,toto'
     
     il y a           7 mots
               1   ''
               2   ''
               3   'bonjour'
               4   'mon nom'
               5   ''
               6   'est'
               7   'toto'
     
     'nom ### prenom ### date ### adresse'
     
     il y a           4 mots
               1   'nom'
               2   'prenom'
               3   'date'
               4   'adresse'
    Et voici le code. La subroutine est dans le module utils, le programme qui donne la sortie ci-dessus est en dessous. Si vous avez d'autres conseils, notamment sur des choses que je devrais tester pour rendre la routine robuste je vous en remercie.

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
     
    module utils
     
      implicit none
     
    !* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
     
      contains
     
    !* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
     
      subroutine parse( chaine, tabchaine, nmot, masque)
        ! decoupage de chaine suivant le masque
        ! par defaut le masque est un espace
        ! en sortie tabchaine est de dimension nmot
     
        implicit none
     
        ! arguments :
        character(len=*), intent(in)                             :: chaine
        character(len=*), dimension(:), allocatable, intent(out) :: tabchaine
        integer, intent(out)                                     :: nmot
        character(len=*), optional, intent(in)                   :: masque
     
        ! variables locales :
        integer                                :: i, j, k, nmask
        integer                                :: longueurvrai
        integer                                :: lenmask
        integer, dimension(0:len_trim(chaine)) :: maskpos
        integer, dimension(len_trim(chaine),2) :: maskborne
        character(len=len_trim(chaine))        :: locchaine
        character(len=len_trim(chaine))        :: mask
        logical                                :: fin, blanc
     
        ! initialisation
        maskpos(:)     = -1
        maskborne(:,:) = -1.d0
     
        locchaine    = adjustl( chaine )
        longueurvrai = len_trim( locchaine )
     
        ! identification du masque
        if( .not. present(masque) ) then
           mask(1:1) = " "
           blanc = .true.
           lenmask = 1
        else
           if( masque == " " ) then
             mask(1:1) = " "
             blanc = .true.
             lenmask = 1
           else
             mask = adjustl(masque)
             blanc = .false.
             lenmask = len_trim(mask)
           end if
        end if
        maskpos(0)   = 1 - lenmask
     
        ! nombre et position du masque
        k = 0
        do i = 1, longueurvrai - lenmask + 1
          if ( locchaine(i:i+lenmask-1) == mask(1:lenmask) ) then
            k = k + 1
            maskpos(k) = i
          end if
        end do
     
        ! controle
        nmask = k
        if( nmask >= longueurvrai ) then
          write(*,"('chaine : ', a)") chaine
          write(*,"('mask   : ', a)") mask
          write(*,"('nmask  : ', i12)") nmask
          stop "erreur 1 subroutine parse"
        end if
     
        ! calcule les bornes des mots
        do i = 1, nmask+1
          maskborne(i,1) = maskpos(i-1) + lenmask
          maskborne(i,2) = maskpos(i) - 1
     
          if( maskborne(i,2) < 0 ) then
            maskborne(i,2) = longueurvrai
          end if
        end do
     
        ! si mask=" ", traite les cas ou plusieurs masques etaient present
        if( blanc ) then
     
          nmot = nmask + 1
     
          fin = .false.
          j = 0
          do while ( .not. fin .and. j <= longueurvrai )
     
            j = j + 1
            fin = .true.
     
            do k = 1, nmask + 1
              if( maskborne(k,1) > maskborne(k,2) ) then
                do i = k, nmask + 1
                  maskborne(i,1) = maskborne(i+1,1)
                  maskborne(i,2) = maskborne(i+1,2)
                end do
                fin = .false.
                nmot = nmot - 1
                exit
              end if
            end do
     
          end do
     
          ! gestion erreur
          if( .not. fin ) then
            write(*,*) "position des elements"
            do i = 1, nmask
              if( maskborne(i,1) == -1 .or. maskborne(i,2) == -1 ) exit
              if( maskborne(i,1) > maskborne(i,2) ) then
                write(*,"(3i5)") i, maskborne(i,1), maskborne(i,2)
              else
                write(*,"(3i5,4x,a)") i, maskborne(i,1), maskborne(i,2), &
                            trim(locchaine( maskborne(i,1) : maskborne(i,2) ))
              end if
            end do
            write(*,"(/'erreur 2 subroutine parse'/)")
            stop ""
          end if
     
          ! alloue le tableau tabchaine a nmot
          if( allocated( tabchaine ) ) deallocate( tabchaine )
          allocate( tabchaine(1:nmot) )
     
          ! decoupage
          do i = 1, nmot
            tabchaine(i)(1:) = locchaine( maskborne(i,1) : maskborne(i,2) )
          end do
     
        else
          nmot = nmask + 1
     
          ! alloue le tableau tabchaine a nmot
          if( allocated( tabchaine ) ) deallocate( tabchaine )
          allocate( tabchaine(1:nmot) )
     
          ! decoupage
          do i = 1, nmot
            if( maskborne(i,1) > maskborne(i,2) ) then
              tabchaine(i)(1:) = ""
            else
              tabchaine(i)(1:) = adjustl(locchaine( maskborne(i,1) : maskborne(i,2) ))
            end if
          end do
     
        end if
     
      end subroutine parse
     
    end module utils
     
    !* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
    !* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
    !* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
    !* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
     
    program test
     
      use utils
     
      implicit none
     
      integer :: i
      character(len=100) :: chaine1 ="  bonjour        mon      nom        est      toto "
      character(len=100) :: chaine2 =",,bonjour,mon nom,,est,toto"
      character(len=100) :: chaine3 ="nom ### prenom ### date ### adresse"
      character(len=20),dimension(:), allocatable :: tabchaine
      integer::n
     
      write(*,*)
      write(*,*)"'"//trim(chaine1)//"'"
      write(*,*)
     
      call parse( chaine1, tabchaine, n, " ")
     
      write(*,*)"il y a",n,"mots"
      do i = 1, n
        write(*,*) i,"  '",trim(tabchaine(i)),"'"
      end do
     
      write(*,*)
      write(*,*)"'"//trim(chaine2)//"'"
      write(*,*)
      call parse( chaine2, tabchaine, n, ",")
     
      write(*,*)"il y a",n,"mots"
      do i = 1, n
        write(*,*) i,"  '",trim(tabchaine(i)),"'"
      end do
     
      write(*,*)
      write(*,*)"'"//trim(chaine3)//"'"
      write(*,*)
      call parse( chaine3, tabchaine, n, "###")
     
      write(*,*)"il y a",n,"mots"
      do i = 1, n
        write(*,*) i,"  '",trim(tabchaine(i)),"'"
      end do
     
    end program test

  13. #13
    Membre confirmé
    Homme Profil pro
    Chercheur - Programmeur amateur
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chercheur - Programmeur amateur
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut
    Désolé pour cette réponse tardive, j'étais absent..
    La réponse de Sylvain me convient parfaitement

    Merci a tous

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

Discussions similaires

  1. [VBA-E] Convertir données separées par point virgule
    Par Elstak dans le forum Macros et VBA Excel
    Réponses: 12
    Dernier message: 31/01/2018, 12h05
  2. lire valeurs séparées par virgules
    Par Infra_Red dans le forum MATLAB
    Réponses: 12
    Dernier message: 09/02/2012, 23h52
  3. Réponses: 2
    Dernier message: 02/08/2010, 21h57
  4. récupérer des valeurs séparées par un point virgule
    Par Spaccio dans le forum Requêtes
    Réponses: 9
    Dernier message: 10/04/2009, 11h22
  5. Champs contenant plusieurs valeurs séparées par ;
    Par sabine34 dans le forum Requêtes
    Réponses: 3
    Dernier message: 11/05/2007, 12h20

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