使用命令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
答案 0 :(得分:4)
第9行的if语句中的条件仅保证j
仅对于从第10行开始的循环的第一次迭代不是否定的。在第11行,在该循环内,我们可以看到{{ 1}}取j
给出的值。 if语句不会检查是否为负数。
即,假设t(j)
为正。然后第9行以j
传递,从第10行开始的循环检查其条件。 while条件表达式的左侧是.TRUE.
,让我们假设右侧也是。这样循环就会迭代。
在某些时候,也许.TRUE.
会变为负面。然后我们回到第10行并检查while条件。此时,我们看到x的出界错误:回想一下if语句没有被命中,而j(t)
的表达式没有被短路。 [也就是说,左侧.AND.
无法确保右侧评估为j>-1
非负面。]
答案 1 :(得分:3)
添加一些打印语句,当您处于内循环中时,您将看到它与t(0)=-1
的关系。接下来就是用((j>-1).and.(ichar(x((i+1):(i+1)))/=ichar(x((j+1):(j+1)))))
测试j=0
,这会产生你现在不理解的东西。
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