使用 Fortran 90 将 txt 文件读入可分配数组时出现错误结果
Wrong results when reading a txt file into an allocatable array using Fortran 90
我正在尝试解决与保留值相关的问题,当我在下面显示的代码 (fortran) 中使用 de/allocate 时,制作了一个副本数组,但问题仍然存在。我已经看到与主题相关的链接:
How to get priorly-unknown array as the output of a function in Fortran
如果我知道数组维数(从 txt 文件输入),这将很容易并且没有意义(对于此代码的目的)。
可能我犯了一些错误(其中一个很明显:分钟尺寸与预期的总尺寸)。如果有人指定它们,我将不胜感激。尽管如此,我还是不明白如何制作一个副本数组来解决这个问题,因为我需要 de/allocate 临时变量和主变量。
那么,是否可以使用重新分配 (de/allocate) 读取没有“可变维度”信息的 txt?
这是代码(使用 f90):
program prueba
implicit none
integer, dimension(:), allocatable :: minuto, temp
integer :: iounit, ierr
integer :: i = 1
integer :: n = 1
open(newunit = iounit, file = 'datos.txt')
read(iounit,*)
allocate(minuto(n), temp(n))
minuto = 0; temp = 0
!-------------------------------------------
do
read(unit = iounit, fmt = '(i2)',iostat = ierr) temp(i)
if (ierr/=0) exit
if (mod(size(temp,1),5)==0) then
deallocate(minuto)
allocate(minuto(i))
minuto((i-4):i) = temp((i-4):i)
end if
i = i+1
deallocate(temp)
allocate(temp(i))
end do
close(iounit)
print*,minuto
end program prueba
(我知道实现相同目标的更好方法,那只是加深练习)
我使用此数据示例(来自 txt):
min
5
10
15
20
25
30
35
40
45
50
55
0
这是结果:
-2144186072 1 -2144186072 1 25 0 35 40 45 50
在重新分配过程中,您解除了 minuto 的分配并且不保存其旧数据。
这是一个可以为您解决的示例程序
program prueba
implicit none
integer, allocatable :: minuto(:)
integer, parameter :: n = 2
integer :: iounit, ierr, temp(n), i
open (newunit = iounit, file = 'datos.txt')
read (iounit, *)
! init minuto. needed for move_alloc in first call
allocate (minuto(0))
i = 1
do
read (unit = iounit, fmt = '(i2)', iostat = ierr) temp(i)
! exit loop. still save temp(1:i-1)
if (ierr /= 0) then
if (i > 1) call save_temp(i-1)
exit
end if
! save all of temp
if (i == n) call save_temp(n)
i = mod(i, n) +1
end do
close (iounit)
print *, minuto
contains
subroutine save_temp(n_temp)
!! append temp(1:n_temp) to minuto
integer, intent(in) :: n_temp
integer, allocatable :: temp_reloc(:)
! save old data from minuto into temp_reloc
call move_alloc(minuto, temp_reloc)
allocate (minuto(size(temp_reloc) + n_temp))
! init first part of minuto by its old data
minuto(:size(temp_reloc)) = temp_reloc
! append temp's data
minuto(size(temp_reloc)+1:) = temp(1:n_temp)
end subroutine
end program
输出
$ gfortran -g3 -Wall -fcheck=all a.f90 && ./a.out
5 10 15 20 25 30 35 40 45 50 55 0
我正在尝试解决与保留值相关的问题,当我在下面显示的代码 (fortran) 中使用 de/allocate 时,制作了一个副本数组,但问题仍然存在。我已经看到与主题相关的链接:
How to get priorly-unknown array as the output of a function in Fortran
如果我知道数组维数(从 txt 文件输入),这将很容易并且没有意义(对于此代码的目的)。
可能我犯了一些错误(其中一个很明显:分钟尺寸与预期的总尺寸)。如果有人指定它们,我将不胜感激。尽管如此,我还是不明白如何制作一个副本数组来解决这个问题,因为我需要 de/allocate 临时变量和主变量。
那么,是否可以使用重新分配 (de/allocate) 读取没有“可变维度”信息的 txt?
这是代码(使用 f90):
program prueba
implicit none
integer, dimension(:), allocatable :: minuto, temp
integer :: iounit, ierr
integer :: i = 1
integer :: n = 1
open(newunit = iounit, file = 'datos.txt')
read(iounit,*)
allocate(minuto(n), temp(n))
minuto = 0; temp = 0
!-------------------------------------------
do
read(unit = iounit, fmt = '(i2)',iostat = ierr) temp(i)
if (ierr/=0) exit
if (mod(size(temp,1),5)==0) then
deallocate(minuto)
allocate(minuto(i))
minuto((i-4):i) = temp((i-4):i)
end if
i = i+1
deallocate(temp)
allocate(temp(i))
end do
close(iounit)
print*,minuto
end program prueba
(我知道实现相同目标的更好方法,那只是加深练习)
我使用此数据示例(来自 txt):
min
5
10
15
20
25
30
35
40
45
50
55
0
这是结果:
-2144186072 1 -2144186072 1 25 0 35 40 45 50
在重新分配过程中,您解除了 minuto 的分配并且不保存其旧数据。
这是一个可以为您解决的示例程序
program prueba
implicit none
integer, allocatable :: minuto(:)
integer, parameter :: n = 2
integer :: iounit, ierr, temp(n), i
open (newunit = iounit, file = 'datos.txt')
read (iounit, *)
! init minuto. needed for move_alloc in first call
allocate (minuto(0))
i = 1
do
read (unit = iounit, fmt = '(i2)', iostat = ierr) temp(i)
! exit loop. still save temp(1:i-1)
if (ierr /= 0) then
if (i > 1) call save_temp(i-1)
exit
end if
! save all of temp
if (i == n) call save_temp(n)
i = mod(i, n) +1
end do
close (iounit)
print *, minuto
contains
subroutine save_temp(n_temp)
!! append temp(1:n_temp) to minuto
integer, intent(in) :: n_temp
integer, allocatable :: temp_reloc(:)
! save old data from minuto into temp_reloc
call move_alloc(minuto, temp_reloc)
allocate (minuto(size(temp_reloc) + n_temp))
! init first part of minuto by its old data
minuto(:size(temp_reloc)) = temp_reloc
! append temp's data
minuto(size(temp_reloc)+1:) = temp(1:n_temp)
end subroutine
end program
输出
$ gfortran -g3 -Wall -fcheck=all a.f90 && ./a.out
5 10 15 20 25 30 35 40 45 50 55 0