程序报告显然不存在的错误



使用命令编译程序后运行程序时gfortran -g -fcheck=all -Wall -Wextra myprogram.f95出现以下错误

Fortran runtime error: Substring out of bounds: lower bound (0) of 'x' is less than one

另据报道,错误位于以下子例程的第 10 行。

01 subroutine create_table_MP (x, m, t)
02   implicit none
03   character(len=*), intent(in) :: x
04   integer, dimension(0:), intent(inout) :: t
05   integer, intent(in) :: m
06   integer :: i, j
07   i=0; t(0)=-1; j=-1
08   do while (i < m)
09       if (j > -1) then
10           do while ((j>-1).and.(ichar(x((i+1):(i+1)))/=ichar(x((j+1):(j+1)))))
11               j = t(j)
12           end do
13       end if
14       i=i+1; j=j+1; t(i)=j
15   end do
16 end subroutine create_table_MP

但是if(j > -1)命令保证第 10 行的下标都不为零,所以我不明白为什么会发生此错误。 我在第 10 行之前放了一个print *, j+1,正如预期的那样,j+1 永远不会假设零值。 我不知道错误在哪里。有人可以帮我吗?

使用此子例程的整个程序的代码是

module search
implicit none
contains
subroutine MP (x, y, m, n)
implicit none
character(len=*), intent(in) :: x, y
integer, intent(in) :: m, n
integer, dimension(0:m-1) :: table
integer :: i, j
call create_table_MP(x, m, table)
i=0; j=0
do while (j<n)
do while ((i>-1).and.(ichar(x((i+1):(i+1)))/=ichar(y((j+1):(j+1)))))
i = table(i)
end do
i=i+1; j=j+1
! if (i >= m) then
!     print *, j-i
!     i = table(i)
! end if
end do
end subroutine MP
subroutine KMP (x, y, m, n)
implicit none
character(len=*), intent(in) :: x, y
integer, intent(in) :: m, n
integer, dimension(0:m-1) :: table
integer :: i, j
call create_table_KMP(x, m, table)
i=0; j=0
do while(j<n)
do while((i>-1).and.(ichar(x((i+1):(i+1)))/=ichar(y((j+1):(j+1)))))
i = table(i)
end do
i=i+1; j=j+1
! if (i >= m) then
!     print *, j-i
!     i = table(i)
! end if
end do
end subroutine KMP
subroutine create_table_MP (x, m, t)
implicit none
character(len=*), intent(in) :: x
integer, dimension(0:), intent(inout) :: t
integer, intent(in) :: m
integer :: i, j
i=0; t(0)=-1; j=-1
do while (i < m)
if (j > -1) then
do while ((j>-1).and.(ichar(x((i+1):(i+1)))/=ichar(x((j+1):(j+1)))))
j = t(j)
end do
end if
i=i+1; j=j+1; t(i)=j
end do
end subroutine create_table_MP
subroutine create_table_KMP (x, m, t)
implicit none
character(len=*), intent(in) :: x
integer, dimension(0:), intent(inout) :: t
integer, intent(in) :: m
integer :: i, j
i=0; t(0)=-1; j=-1
do while (i < m)
if (j > -1) then
do while ((j>-1).and.(ichar(x((i+1):(i+1)))/=ichar(x((j+1):(j+1)))))
j = t(j)
end do
end if
i=i+1; j=j+1
if ((i<m).and.(ichar(x((i+1):(i+1)))==ichar(x((j+1):(j+1))))) then
t(i) = t(j)
else
t(i) = j
end if
end do
end subroutine create_table_KMP
end module search
program test
use search
implicit none
character(len=*), parameter :: string1 = 'gga', file1 = 'file.txt'
call search_1(string1, file1)
contains
subroutine search_1 (string,name_file)
implicit none
character(len=*), intent(in) :: string, name_file
character(len=200) :: message
integer :: l_character
logical :: exist1 = .false., iend = .true.
inquire(FILE=name_file, EXIST=exist1)
if(.not.(exist1)) then
print *,'The file ',name_file,' doesnt exist.'
print *,'Press ENTER to finish the program.'
read (*,*)
stop
end if
open(UNIT=10, FILE=name_file, STATUS='OLD')
do
read(UNIT=10, FMT='(A)', END=1000) message; iend=.false.
1000 if(iend) then
exit
end if
call remove(message,l_character)
iend = .true.
if (l_character < 1) cycle
call MP(string, message(1:l_character),len_trim(string), len_trim(message(1:l_character)))
call KMP(string, message(1:l_character),len_trim(string),len_trim(message(1:l_character)))
end do
close(UNIT=10)
end subroutine search_1
subroutine remove (message, j)
implicit none
character(len=*), intent(inout) :: message
integer, intent(inout) :: j
integer :: i
i=1; j=1
do
if (i>len_trim(message)) exit
! ichar(a) = 97 and ichar(t) = 116
if ((ichar(message(i:i))>=97).and.(ichar(message(i:i))<=116)) then
message(j:j) = message(i:i)
j = j + 1
end if
i = i + 1
end do
j = j - 1
end subroutine remove
end program test

第 9 行的if 语句中的条件仅保证j仅在从第 10 行开始的循环的第一次迭代中不是负数。 在第 11 行,在该循环中,我们可以看到j取一个由t(j)给出的值。 这是否为负数不会通过 if 语句进行检查。

也就是说,假设j是正数。 然后 9 号线以.TRUE.通过,从 10 号线开始的循环检查其状况。 while 条件表达式的左侧是.TRUE.,让我们假设右侧也是。 以便循环迭代。

在某些时候,也许j(t)变得消极。 然后我们回到第 10 行并检查 while 条件。 此时,我们看到了 x 的越界错误:回想一下,if 语句没有被命中,带有.AND.的表达式没有短路。 [也就是说,左侧j>-1不能确保右侧的评估j非负数。

添加一些 print 语句,当你在内部循环中时,你会看到它是如何与t(0)=-1一起使用的。接下来是用j=0测试((j>-1).and.(ichar(x((i+1):(i+1)))/=ichar(x((j+1):(j+1))))),这会生成您目前不理解的内容。

program myprogram
integer, parameter :: M = 11
character(M-1) :: x = "0123456789"
integer, dimension(M) :: t
call create_table_MP (x, m, t)
contains
subroutine create_table_MP (x, m, t)
implicit none
character(len=*), intent(in) :: x
integer, dimension(0:), intent(inout) :: t
integer, intent(in) :: m
integer :: i, j
i=0; t(0)=-1; j=-1
do while (i < m)
if (j > -1) then
write(*,*), "outer j = ", j
do while ((j>-1).and.(ichar(x((i+1):(i+1)))/=ichar(x((j+1):(j+1)))))
j = t(j)
write(*,*), "  innerj = ", j
end do
end if
i=i+1; j=j+1; t(i)=j
end do
end subroutine create_table_MP
end program myprogram

最新更新