Читайте числа после ключевого слова в массив в Fortran 90 из текстового файла - PullRequest
2 голосов
/ 07 июня 2011

У меня есть много текстовых файлов этого формата

....
<snip>
'FOP' 0.19 1 24 1 25 7 8  /
'FOP' 0.18 1 24 1 25 9 11 /
/ 

TURX
560231
300244
70029
200250
645257
800191
900333
600334
770291
300335
220287
110262 /

SUBTRACT
'TURX' 'TURY'/
</snip>
......

, где оторванные части содержат другие различные данные в различных форматах.Формат файла несовместим (генерируется машиной), единственное, в чем он уверен, это ключевое слово TURX, которое может появляться более одного раза.Если он отображается один на одной строке, то следующие несколько строк будут содержать числа, которые мне нужно извлечь в массив.У последнего числа будет пробел, затем косая черта (/).После этого я смогу использовать этот массив в других операциях.

Как мне "искать" или анализировать файл неизвестного формата на фортране и как получить цикл для извлечения остальных данных, пожалуйста?Я действительно новичок в этом, и я должен использовать Фортран.Спасибо.

Ответы [ 3 ]

4 голосов
/ 07 июня 2011

Fortran 95/2003 имеет множество функций обработки строк и файлов, которые делают это проще.

Например, этот фрагмент кода для обработки файла неизвестной длины:

   use iso_fortran_env


  character (len=100) :: line
   integer :: ReadCode


ReadLoop: do
  read (75, '(A)', iostat=ReadCode )  line

  if ( ReadCode /= 0 ) then
     if ( ReadCode == iostat_end ) then
        exit ReadLoop
     else
        write ( *, '( / "Error reading file: ", I0 )' )  ReadCode
        stop
     end if
  end if

  ! code to process the line ....

end do ReadLoop

Тогда код «обработать строку» может содержать несколько разделов в зависимости от логической переменной «Have_TURX». Если Have_TRUX имеет значение false, вы «ищете» ... проверьте, содержит ли строка «TURX». Вы можете использовать простое «==», если TURX всегда находится в начале строки, или для большей общности вы можете использовать встроенную функцию «index», чтобы проверить, содержит ли строка «line» TURX.

Когда программа находится в режиме Have_TRUX со значением true, вы используете «внутренний ввод / вывод» для считывания числового значения из строки. Поскольку целые числа имеют различную длину и выровнены по левому краю, самый простой способ - использовать «ввод-вывод по списку»: объединить их:

read (line, *) integer_variable

Затем вы могли бы снова использовать встроенную функцию «index», чтобы проверить, содержит ли строка также косую черту, и в этом случае вы меняете Have_TRUX на false и завершаете режим чтения.

Если вам нужно поместить числа в массив, может потребоваться дважды прочитать файл или вернуть его назад, потому что вам придется выделять массив, и вы не сможете сделать это, пока не узнаете размер массива. Или вы можете вставить цифры в связанный список, а затем, когда вы нажмете косую черту, выделить массив и заполнить его из связанного списка. Или, если существует известное максимальное количество значений, которые вы можете использовать во временном массиве, затем перенесите числа в выделяемый выходной массив. Это предполагает, что вы хотите, чтобы выходной аргумент подпрограммы был размещаемым массивом правильной длины, и он возвращает одну группу чисел за вызов:

integer, dimension (:), allocatable, intent (out) :: numbers
allocate (numbers (1: HowMany) )

P.S. Краткое описание возможностей языка приведено в http://en.wikipedia.org/wiki/Fortran_95_language_features, а в руководстве gfortran содержится краткое описание внутренних процедур, из которых вы можете узнать, какие встроенные функции доступны для обработки строк.

1 голос
/ 10 июня 2011

Вот мой последний путь.

PROGRAM fetchnumbers
    implicit none
    character (len=50) ::line, numdata
    logical ::is_numeric        
    integer ::I,iost,iost2,counter=0,number
    integer, parameter :: long = selected_int_kind(10)
    integer, dimension(1000)::numbers !Can the number of numbers be up to 1000?

    open(20,file='inputfile.txt') !assuming file is in the same location as program
    ReadLoop: do
        read(20,*,iostat=iost) line !read data line by line
        if (iost .LT. 0) exit !end of file reached before TURX was found
        if (len_trim(line)==0) cycle ReadLoop !ignore empty lines
        if (index(line, 'TURX').EQ.1) then !prepare to begin capturing
            GetNumbers: do
                read(20, *,iostat=iost2)numdata !read in the numbers one by one
                if (.NOT.is_numeric(numdata)) exit !no more numbers to read             
                if (iost2 .LT. 0) exit !end of file reached while fetching numbers
                read (numdata,*) number !read string value into a number
                counter = counter + 1
                Storeloop: do I =1,counter
                    if (I<counter) cycle StoreLoop
                    numbers(counter)=number !storing data into array
                end do StoreLoop
            end do GetNumbers
        end if
    end do ReadLoop

    write(*,*) "Numbers are:"
    do I=1,counter
      write(*,'(I14)') numbers(I)
    end do

END PROGRAM fetchnumbers

FUNCTION is_numeric(string)
  IMPLICIT NONE
  CHARACTER(len=*), INTENT(IN) :: string
  LOGICAL :: is_numeric
  REAL :: x
  INTEGER :: e
  is_numeric = .FALSE.
  READ(string,*,IOSTAT=e) x
  IF (e == 0) is_numeric = .TRUE.
END FUNCTION is_numeric
1 голос
/ 07 июня 2011

Я подтолкну вас в правильном направлении, чтобы вы могли закончить свой проект.

Некоторые основы:

  • Делать / Пока , так как вам понадобится какая-то структура петель, чтобы пройти через файл, а затем по числам.В Fortran нет цикла for, поэтому используйте этот тип.

  • Чтение для чтения строк.

Для началавам нужно что-то вроде этого:

  program readlines
  implicit none
  character (len=30) :: rdline
  integer,dimension(1000) :: array
  !  This sets up a character array with 30 positions and an integer array with 1000
  !
  open(18,file='fileread.txt')
  do
     read(18,*) rdline
     if (trim(rdline).eq.'TURX') exit  !loop until the trimmed off portion matches TURX
  end do

См. этот поток , чтобы узнать, как превратить ваши строки в целые числа.

Окончательное редактирование: похоже, MSB получил большую частьЯ только что узнал.iostat аргумент чтения является ключом к нему.См. этот сайт для примера программы.

...