Этот код демонстрирует ошибку в GFortran? - PullRequest
3 голосов
/ 12 февраля 2020

Как вы можете видеть из приведенного ниже кода, когда он спрашивает вас, продолжать или остановить программу, нажимая другие клавиши, такие как «;» или "," читается так, как будто вы нажали клавишу "Y" или "y", но не сделали этого. Итак, я спрашиваю, это ошибка в компиляторе или проблема с кодом?

program vols

!Calculates difference in volume of 2 spheres
implicit none

real :: rad1,rad2,vol1,vol2
character :: response

do
print *, 'Please enter the two radii'
read *, rad1,rad2
call volume(rad1,vol1)
call volume(rad2,vol2)
write(*,10) 'The difference in volumes is, ',abs(vol1-vol2)
10       format(a,2f10.3)
print *, 'Any more? - hit Y for yes, otherwise hit any key'
read *, response
if (response /= 'Y' .and. response /= 'y') stop
end do

end program vols

!________________________________________________

subroutine volume(rad,vol)
implicit none
real :: rad,vol,pi
!calculates the volume of a sphere
pi=4.0*atan(1.0)
vol=4./3.*pi*rad*rad*rad
!It's a little quicker in processing to  do r*r*r than r**3!
end subroutine volume

Ответы [ 2 ]

3 голосов
/ 21 февраля 2020

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

Для получения ответа программа использует ввод, направленный на списки. Это приводит к неинтуитивным результатам. Например, для человека, пишущего калькулятор , может возникнуть удивление, что происходит, когда кто-то вводит * или /.

В примере калькулятора * участвует в повторении считает и / в разделителях записей. Для этого вопроса , также имеет особое значение. В вводе по списку , является разделителем значений, а read *, x, представленный с этим символом, не устанавливает x в значение ','.

Вместо этого оператор ввода

read *, response

при представлении с вводом

,

придет к , и увидит «ха, пользователь говорит мне, что не указано никакого значения». Это отличается от пустой строки, в которой обработка ввода продолжает ожидать значения.

Этот разделитель значений соединяется с другой функцией ввода, ориентированного на список: допускаются нулевые значения. Нулевое значение завершает оператор ввода, но оставляет соответствующее значение без изменений (не установлено пустым).

Это означает, что если ввод идет как

1 1
y
1 1
,

Вкл. На втором проходе символ response равен без изменений от значения 'y'. Точно так же для

1 1
,

response не отличается от своего неопределенного статуса: программе не разрешено сравнивать его значение с 'y '.

Как решить эту проблему? Просто используйте соответствующий формат:

read '(A)', response

Таким образом, ввод , обрабатывается как символ, а не как разделитель значений.

Хотя запятые обрабатываются особым образом в Список направленного ввода вопроса, точки с запятой нет. Если вы видите неожиданное поведение с точкой с запятой, это может стать причиной для беспокойства. Я не вижу, чтобы это случилось с доступным мне gfortran.

Однако точки с запятой могут быть особенными. Когда режим десятичного редактирования равен COMMA (вместо значения по умолчанию POINT), точка с запятой рассматривается как разделитель значений вместо запятой (которая теперь действует как десятичный разделитель в значениях, таких как 1,23). COMMA не является режимом соединения по умолчанию.

1 голос
/ 12 февраля 2020

К вашему сведению - я попробовал этот код в Intel Fortran, и он работает как положено. Когда response равен y или Y, он зацикливается, в противном случае он выходит из l oop.

program vols

!Calculates difference in volume of 2 spheres
implicit none

real :: rad1,rad2,vol1,vol2
character :: response

do
    print *, 'Please enter the two radii'
    read *, rad1,rad2
    call volume(rad1,vol1)
    call volume(rad2,vol2)
    print '(a,2f10.3)', 'The difference in volumes is, ',abs(vol1-vol2)
    print *, 'Any more? - hit Y for yes, otherwise hit any key'
    read *, response
    if (response /= 'Y' .and. response /= 'y') stop
end do

contains

subroutine volume(rad,vol)
implicit none
real :: rad,vol,pi
!calculates the volume of a sphere
pi=4.0*atan(1.0)
vol=4./3.*pi*rad*rad*rad
!It's a little quicker in processing to  do r*r*r than r**3!
end subroutine volume

end program vols

Так что, похоже, здесь могут быть проблемы c to gfortran.

PS. Я переместил функцию в блок program таким образом, чтобы она не нуждалась в интерфейсе или внешнем объявлении.

PS2. Я проверил результат компиляции и rad**3 идентичен rad*rad*rad. Современные компиляторы умнее, чем вы думаете. Лучше показывать намерение в программах, чем скрывать их микрооптимизациями.

...