Как читать последовательную строку текстового файла на каждом этапе цикла выполнения в фортране?

У меня есть набор данных значений параметров для 30 видов, и я хочу запустить скрипт, который проводит моделирование для каждого вида. Значения параметров в настоящее время хранятся в файле .txt, где каждая строка представляет собой отдельный вид, а каждый столбец — другое значение параметра. Что я хотел бы сделать, так это настроить цикл выполнения, который считывает соответствующую строку значений параметров для каждого вида, запускает сценарий моделирования и записывает файл .txt с выходными данными для каждого вида. К сожалению, я новичок в фортране, и у меня много проблем с пониманием того, как читать последовательные строки из файла .txt на каждом этапе цикла выполнения. Я попытался сделать упрощенный скрипт, чтобы проверить, работает ли шаг чтения:

    PROGRAM DRIVER
    IMPLICIT NONE

    INTEGER :: mm ! I forgot this line in the first version of this question   
    and edited to add it in
    CHARACTER(7) :: species  !! the first column is the species name
    REAL*8    :: leaf_variable   !  The next 3 columns are variable values
    REAL*8    :: stem_variable   !  
    REAL*8    :: root_variable   !  

    OPEN (12, file = "species_parameters.txt") ! open the .txt file

    DO mm = 1,30 ! set up the do loop
        READ (12,*) species, leaf_variable, stem_variable, root_variable
        ! Read in the species-specific parameter values
        WRITE (*,*) species, leaf_variable, stem_variable, root_variable
        ! Print the values on the screen just to show the do loop runs
    ENDDO
    END PROGRAM DRIVER

Но когда я перехожу к компиляции, я получаю сообщение об ошибке: В строке XX файла XX (unit = 12, file = 'species_parameters.txt') Ошибка времени выполнения Fortran: конец файла

Что я неправильно понимаю в открытии и чтении этого файла?

Большое спасибо за любую помощь.

РЕДАКТИРОВАТЬ: я думаю, что сузил свою проблему. Насколько я понимаю, read() принимает по одной строке в файле .txt за раз, так что в этом примере:

    read(7, *) species, leaf_variable, stem_variable, root_variable
    read(7, *) species, leaf_variable, stem_variable, root_variable

Переменные должны совпадать со значениями во второй строке файла .txt. Вместо этого, независимо от того, сколько раз я ввожу функцию read(), значения переменных равны первой строке. И хотя столбцов всего 4, я могу определить столько переменных, сколько захочу, с помощью функции read():

   read(7, *) species, leaf_variable, stem_variable, root_variable, 
            fake_variable1, fake_variable2, fake_variable3, fake_variable4

где значения fake_variable равны значениям во второй строке файла .txt. Я запутался в том, что делает read(), или мне нужно что-то сделать, чтобы мой скрипт не читал весь мой .txt-файл как одну строку?

РЕДАКТИРОВАТЬ № 2: цикл do правильно читается построчно теперь, когда я сохранил свой файл .txt с кодировкой Unix с помощью TextWrangler. Исходный файл был сохранен как файл .txt с помощью Excel. Кажется, это решило проблему, но если у кого-то есть предложения по лучшему способу указания формата входного файла, я был бы признателен. Первые несколько строк входного файла выглядят так:

    species1,1.2,6.54,10.9
    species2,1.42,3.5,8.23
    species3,0.85,2.41,4.9 

person UCLAEeb    schedule 24.08.2016    source источник
comment
Я не вижу объявления типа для mm — индексной переменной цикла do. Попробуйте показать несколько строк из входного файла. Предполагая, что отсутствие объявления типа является проблемой транскрипции - общая проблема заключается в том, что оператор open открывает новый пустой файл в другом каталоге, где файл находится на самом деле. Убедитесь, что вы не создали файл с именем species_parameters.txt в другом неожиданном месте, добавьте спецификатор STATUS='OLD' в оператор open (для которого требуется, чтобы файл уже существовал) и повторите попытку.   -  person IanH    schedule 24.08.2016
comment
Я не понимаю - вы говорите, что получаете ошибку времени выполнения при компиляции? В коде, который на самом деле не должен компилироваться.   -  person talonmies    schedule 24.08.2016
comment
Извините, моя ошибка - объявление переменной для mm находится в первой строке моего скрипта, и я как-то пропустил его. Я отредактировал свой вопрос, чтобы добавить это. Таким образом, мой код компилируется, и я все еще получаю ту же ошибку времени выполнения, когда пробовал STATUS = 'OLD'.   -  person UCLAEeb    schedule 24.08.2016
comment
Ваше понимание поведения инструкции чтения является неточным. Направленное чтение по списку — где у вас есть * для второго спецификатора, указывающего спецификацию формата, как и у вас — считывает столько полных записей из файла, сколько необходимо для обработки всех элементов входного списка. Если ваши входные данные (которых мы еще не видели — следовательно, все догадываются!) содержат данные только для четырех элементов в записи, а во входном списке в операторе восемь элементов, то чтение будет читать две записи. Покажите свой фактический код и ваш фактический ввод !!!!   -  person IanH    schedule 25.08.2016
comment
Спасибо за помощь, @IanH. Я заставил скрипт работать, используя TextWrangler для сохранения входного файла .txt, который я изначально сохранил в Excel, с кодировкой Unix. Есть ли какой-то конкретный формат, который я должен использовать вместо *? Я отредактировал вопрос, включив в него пример моего входного файла.   -  person UCLAEeb    schedule 25.08.2016
comment
Используете ли вы компилятор Fortran, который [думает, что] работает в системе unix? Если это так, вам нужно предоставить ему текстовые файлы, которые используют соглашение об окончании строки, которое ожидает компилятор. Это не проблема языка Fortran.   -  person IanH    schedule 25.08.2016


Ответы (1)


Ошибка времени выполнения — это когда у вас есть исполняемый файл, вы запускаете его, и он падает. Ошибка времени компиляции — это когда компилятору не удается создать исполняемый файл.

Этот код не должен компилироваться, потому что у вас есть IMPLICIT NONE, но вы не объявили целое число mm.

Я бы порекомендовал получить больше информации:

program driver
    use iso_fortran_env
    implicit none
    character(len=7) :: species
    real(kind=real64) :: leaf_variable, stem_variable, root_variable
    integer :: u, ioerr
    character(len=120) :: iomsg

    open(newunit=u, file='species_parameters.txt', action='read', status='old', iostat=ioerr, iomsg=iomsg)
    if (ioerr /= 0) then
        print *, "Error opening file"
        print *, trim(iomsg)
        stop 1
    end if
    do
        read(u, *, iostat=ioerr, iomsg=iomsg) species, leaf_variable, stem_variable, root_variable
        if (ioerr /= 0) exit  ! exits the loop
        write(*, *) species, leaf_variable, stem_variable, root_variable
    end do
    print *, trim(iomsg)
    close(u)
end program driver

При этом всегда будет выводиться сообщение об ошибке "прочитано за концом файла", но это просто проверка того, как запрограммировать чтение в любом случае.

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

person chw21    schedule 24.08.2016
comment
Для подобных тестовых программ лучший способ получить больше информации — просто исключить iostat из таких вещей, как операторы ввода/вывода. Если возникает состояние ошибки, процессор Fortran обычно выдает довольно информативное сообщение как часть устранения ошибки. Посмотрите на логику оператора чтения в вашем примере - если во время чтения возникает ошибка, все, что делает ваша программа, - это тихо завершает работу, и пользователь не будет знать, что что-то пошло не так. Если вы собираетесь предоставить IOSTAT, то также укажите (и сообщите, когда iostat > 0) IOMSG. - person IanH; 24.08.2016
comment
Спасибо за ваше предложение! Я забыл включить в свой вопрос строку кода, которая объявляла mm, поэтому я отредактировал ее, чтобы добавить это. Ваш код скомпилирован и напечатал первую строку значений переменных без возврата ошибки. Но когда я попытался запустить его по всем строкам (с do mm =1,22), ничего не было напечатано, и он записал пустой файл с именем fort.1... знаете, что это значит? - person UCLAEeb; 24.08.2016
comment
Извините, так и должно быть (сделать мм = 1, 30) - person UCLAEeb; 24.08.2016
comment
Я заметил, что написал fortran_iso_env вместо правильного iso_fortran_env. Я также включил сообщения об ошибках, как предложил @IanH. - person chw21; 25.08.2016