2
votes

Comment lire les données d'un fichier avec une colonne différente dans une ligne

Je veux lire des données à partir d'un fichier dans lequel chaque ligne a un nombre différent de données, par exemple

         15 format(T8,CV(i,1)(I7))
                      1
Error: Unexpected element ‘C’ in format string at (1)

et j'ai besoin d'avoir un format comme ce format (T8, (I7)) quel est un spécificateur de format dynamique déterminé au moment de l'exécution qui spécifie le nombre de colonnes dans une ligne du fichier d'entrée. C'est le code que je souhaite modifier. Le code fonctionnait dans Intel fortran, mais dans gfortran j'ai eu une erreur.

 do i=1,N
    read(20,'(I7)') CV(i,1)

    backspace(20)
    15 format(T8,CV(i,1)(I7))
    read(20,15) CV(i,2:CV(i,1)+1)
 end do

Le message d'erreur est

a b c d
e f 
h g k


1 commentaires

@francescalus format 15 (T8, CV (i, 1) (I7)) Erreur: élément «C» inattendu dans la chaîne de format à (1)


3 Réponses :


0
votes

Vous n'avez pas besoin d'un format de variable pour ce faire.

Lors du traitement d'une liste d'entrée, toutes les valeurs requises pour traiter un élément d'entrée sont déterminées au début du traitement de cet élément. Dans ce cas, il est possible d'utiliser le premier élément d'une ligne pour déterminer les éléments du tableau à lire:

read(20, '(*(I7))') CV(i,1), CV(i,2:CV(i,1)+1) 

Le spécificateur de répétition ("nombre d'éléments à lire" aspect) du format, dans ce cas ce que signifie la tentative d'utilisation de CV (i, 1) , n'a pas besoin de correspondre au nombre d'éléments: il doit juste être plus grand (dans ce case * signifiant "illimité"). Lorsque tous les éléments de la liste ont été lus, le traitement s'arrête.


0 commentaires

0
votes

Cela peut être fait en construisant un format via une écriture interne comme suit:

character(Len=30) :: form
do i=1,N
    read(20,'(I7)') CV(i,1)
    write( form, '(a,i0,a)' )  '(', CV(i,1), 'i7)'
    backspace(20)
    read(20,form) CV(i,2:CV(i,1)+1)
end do


0 commentaires

0
votes

Afin d'éviter le RETOUR ARRIÈRE, qui peut prendre beaucoup de temps, je préfère souvent lire l'entrée dans une ligne de caractères, que je peux ensuite analyser rapidement. Dans votre cas spécifique, comme le nombre de données d'entrée est toujours donné comme élément de données 1, la réponse donnée par @francescalus est parfaitement correcte. Si les lignes varient plus radicalement, vous pouvez développer le code suivant (qui ne fait actuellement que votre exemple)

program read_data
! 
integer, parameter :: MAX_DATA=10
integer, parameter :: MAX_ROWS=4
integer :: ios
integer :: i
character(len=18+7*MAX_DATA) :: line
integer, dimension(MAX_ROWS, MAX_DATA) :: cv
!
cv(:,:) = 0
open(unit=20, file='data.txt')
main_loop: do i=1, 4
  read(20, '(a)', iostat=ios) line
  if(is_iostat_end(ios)) exit main_loop
  read(line(1:len_trim(line)),'(*(i2))', iostat=ios) cv(i,1), cv(i,2:cv(i,1)+1)
  if(.not.(ios==0 .or. is_iostat_end(ios))) exit main_loop
  write(*,*) i,cv(i,1), cv(i,1:6)
enddo main_loop
!
end program read_data


0 commentaires