#file-io #fortran #gfortran
#файл-ввод-вывод #fortran #gfortran
Вопрос:
Предположим, у меня есть файл, каждая строка которого содержит индекс массива, за которым следует значение массива
i array(i)
Могу ли я читать данные просто наивно read(unit=10, *) i, array(i)
? Будет ли Fortran всегда i
сначала считывать, а затем использовать это i
значение для присвоения array(i)
? Будут ли определенные read
спецификации или флаги компилятора влиять на поведение?
Ответ №1:
Инструкция передачи данных
read(unit=10,*) i, array(i)
является допустимой, и ее поведение соответствует желаемому: из записи i
сначала считывается значение for , затем это значение используется для идентификации элемента массива array(i)
для второго считанного значения.
Это требование спецификации Fortran, например, с (Fortran 2018, 12.6.4.5.1):
Все значения, необходимые для определения того, какие объекты указаны элементом списка ввода / вывода, определяются в начале обработки этого элемента.
Конечно, хотя эта инструкция передачи данных потенциально работает, это не означает, что она желательна во всех случаях, кроме самых простых, когда вы доверяете входным данным. В частности, невозможно выполнить какую-либо проверку границ во время этого оператора чтения. Если i
прочитанное значение соответствует недопустимой спецификации элемента массива, программа не работает. Возможно, вы захотите использовать промежуточное значение для элемента массива просто для решения потенциальных проблем с входным файлом.
Комментарии:
1. Я бы даже сказал, что такой код предоставляет большую уязвимость, но это не имеет значения, если это одноразовый код, используемый только автором. Настоятельно рекомендуется использовать флаги компилятора для проверки границ.
2. «невозможно выполнить какую-либо проверку границ во время этого оператора чтения» — не уверен, что я понимаю это, особенно почему это невозможно, разве это не проблема качества реализации, а не совершенно невозможно? Или вы имеете в виду «ручную» проверку программистом? Если это так, это имеет смысл.
3. Да, @IanBush, проверка ввода программистом. Доступна обычная проверка границ во время выполнения компилятора, но обычная в смысле «Я заметил, что ваша программа сломана, но я не позволю вам продолжать думать, что все в порядке».
4. Чтобы проверить границы, я бы просто использовал временную переменную для хранения элемента массива :
read(unit=10,*) i, temp
. Затем проверьте границы на ошибку, затем присвоите элементу массива значение temp:array(i) = temp
.