2017-07-18 47 views
1

當使用命令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 
+1

對於第11行,t(j)是否小於零? – francescalus

+0

請不要將代碼等重要信息用於外部託管。鏈接隨時間而腐爛。 –

回答

4

在行if語句的條件保證9只j不僅是循環位於第10行開始在第11行,即循環中的第一次迭代負,我們可以看到,j需要由t(j)給出的值。如果這個if語句沒有檢查這是否定的。

也就是說,假設j是正數。然後第9行通過.TRUE.,並且從第10行開始的循環檢查其條件。 while條件表達式的左邊是.TRUE.,讓我們假設右邊也是。以便循環迭代。

在某些情況下,或許j(t)變爲負值。然後我們回到第10行並檢查一下情況。此時,我們看到x的出界誤差:回想起if語句未被命中,並且.AND.的表達式未被短路。 [也就是說,左邊的j>-1不能保證右邊的評估爲j非負數。]

3

添加一些打印語句,你會看到它如何去與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 = "" 
    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