2013-11-28 28 views
3

關於堆棧的問題,最後!我所有的生活都讓我意識到這一點。fortran:試圖製作一個最小堆棧數據結構

所以我需要將一些相當大的自定義數據結構合併到一個堆棧中。我決定寫一個只包含一個整數值的最小堆棧結構。這裏是 -

MODULE STACK_MODULE 
IMPLICIT NONE 

TYPE ELEMENT_TYPE 
    INTEGER(4) :: VAL 
    TYPE(ELEMENT_TYPE), POINTER :: PREV 
END TYPE ELEMENT_TYPE 

TYPE STACK_TYPE 
    INTEGER(4) :: SIZE=0 
    TYPE(ELEMENT_TYPE), POINTER :: LASTIN 
END TYPE STACK_TYPE 

CONTAINS 
    SUBROUTINE PUSH(VAL_,STACK) 
    IMPLICIT NONE 
    INTEGER(4), INTENT(IN) :: VAL_ 
    TYPE(STACK_TYPE), INTENT(INOUT) :: STACK 
    TYPE(ELEMENT_TYPE),TARGET  :: CURRENT 
    ! INIT CURRENT 
    CURRENT%VAL = VAL_ 
    CURRENT%PREV => STACK%LASTIN 
    ! ADD CURRENT TO STACK 
    STACK%LASTIN => CURRENT 
    STACK%SIZE = STACK%SIZE+1 
    RETURN 
    END SUBROUTINE PUSH 

    SUBROUTINE POP(STACK,VAL_) 
    IMPLICIT NONE 
    TYPE(STACK_TYPE), INTENT(INOUT) :: STACK 
    INTEGER(4)  , INTENT(OUT) :: VAL_ 
    TYPE(ELEMENT_TYPE), POINTER  :: B4LASTIN 
    !WRITE TO VAL_ 
    IF (ASSOCIATED(STACK%LASTIN)) THEN 
    VAL_ = STACK%LASTIN%VAL 
    !TAKE OUT THE LAST-IN ELEMENT 
    B4LASTIN => STACK%LASTIN%PREV 
    STACK%LASTIN => B4LASTIN 
    STACK%SIZE = STACK%SIZE-1 
    ELSE 
    IF (STACK%SIZE.NE.0) THEN 
    PRINT*, STACK%SIZE 
    STOP 'MISMATCH BETWEEN STACKSIZE AND POINTER: BAD BOOK KEEPING!' 
    END IF 
    END IF 
    RETURN 
    END SUBROUTINE POP 
END MODULE STACK_MODULE 

PROGRAM MAIN 
USE STACK_MODULE 
IMPLICIT NONE 
INTEGER(4) :: I,J 
TYPE(STACK_TYPE) :: STACK1 
DO I = 1,10 
    CALL PUSH(I,STACK1) 
END DO 
DO WHILE (ASSOCIATED(STACK1%LASTIN)) 
    CALL POP(STACK1,J) 
    PRINT*, J 
END DO 
END PROGRAM 

結果讓我大吃一驚!我懷疑SIZE計數器是否會跟上..但不是這樣。

  10 
-1076898780 
    1752444 
-1219604480 
    1651076143 
stderr 
Program received signal SIGSEGV: Segmentation fault - invalid memory reference. 

Backtrace for this error: 
#0 0xB777FD63 
#1 0xB77803F0 
#2 0xB78713FF 
#3 0x8048666 in __stack_module_MOD_pop 
#4 0x80487A3 in MAIN__ at prog.f95:? 

任何指針(暫停而咯咯地笑失控)在哪裏出了錯? Here is the link to the code on IDEONE.
編輯:The IDEONE link現在包含代碼的更新版本,並將解決方案合併到它!希望它可以作爲堆棧的通用模板重用!

回答

3

幾個小問題

1)當推退出時,電流也跟着消失了。你需要像

TYPE(ELEMENT_TYPE),POINTER  :: CURRENT 
! INIT CURRENT 
ALLOCATE(CURRENT) 

2)同樣,當POP完成,它需要刪除數據,因此

B4LASTIN => STACK%LASTIN%PREV 
DEALLOCATE(STACK%LASTIN) 
STACK%LASTIN => B4LASTIN 

3)相關工程,但只有當指針正確初始化。

TYPE(STACK_TYPE) :: STACK1 
STACK1%LASTIN => NULL() 

而你應該準備好運行。

+0

你建議的編輯#1似乎有伎倆。爲什麼重要的是有另外兩個? 我已經更改了IDEONE網站上的代碼 - 您可能會看看! –

+1

#2所以你沒有得到內存泄漏,#3,以便當你到達列表的末尾時,關聯失敗。 – cup

+0

哇! +1。 您認爲在#3關聯的'=> null()可以在聲明期間完成嗎?\\ 'TYPE STACK_TYPE' 'INTEGER(4):: SIZE = 0' 'TYPE(ELEMENT_TYPE),POINTER :: LASTIN => NULL()' 'END TYPE STACK_TYPE' \\ 編譯器似乎沒有給出任何錯誤..但我不知道指針關聯是否可以在聲明過程中完成。 –