字符串串联在Fortran中不起作用



我有一个子程序,它连接字符串以创建文件名,这样我就可以在非线性迭代中跟踪解决方案的变化。然而,它似乎不起作用。我以前使用过这个代码片段,没有遇到任何问题,所以我想知道这是否依赖于某些编译器标志?字符串连接部分在底部,我返回以下内容:

output_name:PLT/Res文件名1:PLT/Res
文件名2:PLT/Res
正在写入文件。。。0

这清楚地表明我的字符串没有连接。我用调用子程序

IF (MOD(counter, plot_freq) == 0) call plotSolution(2, counter, 'PLT/Solution', Mesh, W)

下面是例行程序。

subroutine plot_nodal_field(opt, iter, output_file, Mesh, Q)
use Globals_module,  only : c_in
use inputs_module,   only : p_in, gamma, rho_in, M_inf
!--------------------------------------------end of use--------------------------------------------!
integer(i4),     intent(in) :: iter, opt
type(Mesh_Type), intent(in) :: Mesh
character(*),    intent(in) :: output_file
real(dp),        intent(in) :: Q(Mesh%numFields, Mesh%numNodes)
!------------------------------------------end of intents------------------------------------------!
integer(i4)   :: elem_id,n1,n2,n3
character(80) :: filename, file_num
integer(i4)   :: iunit
integer(i4)   :: n,io, i
real(dp)      :: x, y, rho, rhoU, rhoV, rhoE, u, v, P, CP, c, MachNum, s
!------------------------------------------end of declare------------------------------------------!

iunit = 2
write(file_num,'(I6.6)') iter
write(*,*) 'output_name:', output_file
filename = adjustl(trim(output_file)) // '_' // adjustl(trim(file_num)) // '.plt'
write(*,'(A)') 'filename1:', filename
filename = adjustl(trim(filename))
write(*,'(A)') 'filename2:', filename
print*,'# Writing to File...', iter
open(unit = iunit, file = filename, status = 'replace', iostat = io)
if( io /= 0) then
print*,'ERROR: Opening 2nd order plt file'
else
if (opt == 1) then 
write(iunit,'(A)')  'VARIABLES = "x","y","rho","U","V","P","MachNum","entropy"'
elseif(opt == 2) then
write(iunit,'(A)')  'VARIABLES = "x","y","rho","U","V","P"'
end if
write(iunit,'(A7, I, A3, I, A41)')  'ZONE N=', Mesh%numNodes, ' E=', Mesh%numTri, ' DATAPACKING=POINT ZONETYPE=FETRIANGLE'
do i = 1, Mesh%numNodes
x    = Mesh%nodeCoords(1, i)
y    = Mesh%nodeCoords(2, i)
if (opt == 1) then
rho  = Q(1, i)
U = Q(2, i)
V = Q(3, i)
P = Q(4, i)
c = sqrt(gamma*P/Q(1,i))
MachNum = sqrt(Q(2,i)**2 + Q(3,i)**2)/c
s = P/Q(1,i)**gamma - P_in/rho_in**gamma
write(iunit,'(8ES)') Real(x), Real(y), Real(Q(1,i)), Real(Q(2,i)), Real(Q(3,i)), Real(Q(4,i)), &
& Real(MachNum), Real(s)
elseif (opt == 2) then
write(iunit,'(6ES)') Real(x), Real(y), Real(Q(1,i)), Real(Q(2,i)), Real(Q(3,i)), Real(Q(4,i))
end if

end do
do i = 1, Mesh%numTri
write(iunit,'(3I)') Mesh%trilist(1,i), Mesh%trilist(2,i), Mesh%trilist(3,i) 
end do
end if
close(iunit)
end subroutine

编辑:

我试着做一个最低限度的可验证的例子:

program plotSolution                                                                                                        
!--------------------------------------------end of use--------------------------------------------!
integer       :: iter
character(80) :: filename
!------------------------------------------end of intents------------------------------------------!
filename = 'PLT/Solution'
iter = 1
call plot_nodal_field(iter, filename)
contains

subroutine plot_nodal_field(iter, output_file)
!--------------------------------------------end of use--------------------------------------------!
integer,      intent(in) :: iter
character(*), intent(in) :: output_file
!------------------------------------------end of intents------------------------------------------!
character(80) :: filename, file_num
integer       :: iunit
!------------------------------------------end of declare------------------------------------------!

iunit = 2
write(file_num,'(I6.6)') iter
write(*,*) 'output_name:', output_file
filename = adjustl(trim(output_file)) // '_' // adjustl(trim(file_num)) // '.plt'
write(*,'(A)') 'filename1:', filename
filename = adjustl(trim(filename))
write(*,'(A)') 'filename2:', filename
print*,'# Writing to File...', iter
open(unit = iunit, file = filename, status = 'replace', iostat = io)
if( io /= 0) then
print*,'ERROR: Opening 2nd order plt file'
else
end if
close(iunit)
end subroutine
end program

但这是有效的:并返回:

输出名称:PLT/溶液

文件名1:PLT/解决方案_ 000001。PLT
文件名2:PLT/Solution_ 000001.PLT
正在写入文件。。。1.错误:打开二阶plt文件

这表明我在主代码中可能有一些奇怪的内存错误。我不确定。感谢所有的建议和帮助!

我使用这个测试程序尝试了发布的例程:

  • 我找不到gfortran的问题>5.3.0,但根据我的经验,gfortran的字符串处理在过去的版本中非常有缺陷
  • 每当我有可变大小的字符串时,我的编码实践是有一个固定长度的字符串缓冲区(比如character(len=BUFFER_SIZE) :: buffer(,进行所有临时剪切和粘贴,然后在函数末尾将相关部分分配给可变长度的变量(用盐粒选择最大长度!(
  • 在所附的示例中,我发布了一个示例路径创建函数。为了更灵活的使用(选择文件夹名称等(,可以对其进行通用化
program test_string
implicit none

integer :: counter
character(len=:), allocatable :: fileName

counter = 2

! Original routine   
call create_string_orig(counter,'PLT/Solution')

! With path function
fileName = output_fileName('PLT',counter)
write(*,*) 'filename with function: ', fileName

contains

function output_fileName(folder,iter) result(fileName)
character(*), intent(in) :: folder      
integer, intent(in) :: iter
character(len=:), allocatable :: fileName

! Local variables 
character(*), parameter :: prefix = 'Solution'
character(*), parameter :: ext    = '.plt'
character(len=1024) :: buffer
character(len=6)    :: fileID
integer :: fullLen

write(fileID,'(I6.6)') iter

buffer = trim(adjustl(folder)) // filesep() // prefix // '_' // fileID // ext

fullLen = len_trim(buffer)

allocate(character(len=fullLen) :: fileName)
fileName(1:fullLen) = buffer(1:fullLen)

end function output_fileName

! Get current system's folder separator
character function filesep()
character(len=9999) :: system_path
integer             :: i
system_path = repeat(' ',len(system_path))
call get_environment_variable('PATH',system_path)
do i = 1, len(system_path)
if (system_path(i:i) == '/') then
filesep = '/'
return
elseif (system_path(i:i) == '') then
filesep = ''
return
endif
end do
! Use default if unable to find a separator
filesep = '/'
return
end function filesep   


subroutine create_string_orig(iter,output_file)
integer, intent(in) :: iter
character(*), intent(in) :: output_file

character(80) :: filename,file_num

write(file_num,'(I6.6)') iter
write(*,*) 'output_name: ', output_file
filename = adjustl(trim(output_file)) // '_' // adjustl(trim(file_num)) // '.plt'
write(*,*) 'filename1: ', filename
filename = adjustl(trim(filename))
write(*,*) 'filename2: ', filename
print*,'# Writing to File...', iter

end subroutine create_string_orig
end program  

这会产生以下输出(在Windows上工作(:

$ a.exe
output_name: PLT/Solution
filename1: PLT/Solution_000002.plt
filename2: PLT/Solution_000002.plt
# Writing to File...           2
filename with function: PLTSolution_000002.plt

我很感谢你们给我的帮助,今天我决定回到这里,发现了这个问题。据我所知,这是一个编译器标志问题,编译器/预处理器将连接运算符(//(作为c++注释,预处理器在连接后对所有内容进行注释。我不得不使用continuation&符号来拼凑一个修复程序,但它目前有效,然后我可以下次查看这些标志。如果有人有任何见解,我将不胜感激。

最新更新