2012-10-08 77 views
0

我正在製作一個將十進制整數轉換爲二進制表示的程序。這裏是我的代碼:Fortran 90 - 分段錯誤

program test 
implicit none 
integer, dimension(:), allocatable :: binary 
integer :: decimalnum, i, initvalue 

print*, "Enter decimal number to convert: " 
read*,initvalue 

decimalnum = initvalue 
i = 0 

do while (decimalnum > 0) 
    if (MOD(decimalnum,2)==0) then 
     binary(i) = 0     ! this is as far as the program executes up to 
     decimalnum = decimalnum/2 
     i = i + 1 
    else if (MOD(decimalnum,2)==1) then 
     binary(i) = 1 
     decimalnum = (decimalnum -1)/2 
     i = i + 1 
    end if 
end do 
end program test 

在標記點,則返回錯誤Segmentation fault與代碼139

爲什麼會發生這種情況退出?

在此先感謝。

+0

你有訪問一個'調試'?這樣的gdb – Jack

+0

不,我不知道如何使用一個 – Progrmr

+0

我真的不太瞭解Fortran,但我只是查找'allocatable',看起來你仍然需要一個'allocate'語句來實際保留空間。 –

回答

-1

所以這可能是很糟糕的形式, 和肯定不好的運行時間(它複製陣列的每一位) ,但這是我想出的。它似乎工作。

program test 
     implicit none 
     integer, dimension(:), allocatable :: binary 
     integer :: decimalnum, i, initvalue, curSize, curBit 


     print*, "Enter decimal number to convert: " 
     read*,initvalue 

     decimalnum = initvalue 
     i = 1 
     ALLOCATE (binary(1)) 
     curSize = 1 

     DO WHILE (decimalnum > 0) 
     IF (i > curSize) THEN 
      curSize = curSize * 2 
      CALL expandArray(curSize, i-1) 
     END IF 

     IF (MOD(decimalnum,2)==0) then 
      binary(i) = 0     ! this is as far as the program executes up to 
      decimalnum = decimalnum/2 
      i = i + 1 
     ELSE IF (MOD(decimalnum,2)==1) then 
      binary(i) = 1 
      decimalnum = (decimalnum -1)/2 
      i = i + 1 
     END IF 

     end do 
     PRINT*, binary 


    CONTAINS 
     SUBROUTINE expandArray(newSize, oldSize) 
      IMPLICIT NONE 
      INTEGER, DIMENSION(:), ALLOCATABLE :: temp 
      INTEGER :: j, newSize, oldSize 
      ALLOCATE(temp(newSize)) 
      DO j=1,oldSize 
       temp(j) = binary(j) 
      END DO 
      DEALLOCATE (binary) 
      ALLOCATE(binary(newSize)) 
      DO j=1,oldSize 
       binary(j) = temp(j) 
      END DO 
      DO j=oldSize+1,newSize 
       binary(j) = 0 
      END DO 
      DEALLOCATE (temp) 
     END SUBROUTINE 

    END PROGRAM test 
+0

謝謝。你的代碼工作正常。 – Progrmr

+0

注意:剛編輯 - 我錯誤地有二進制作爲參數expandArray而不是全局變量。由於某種原因,它無論如何工作。無論如何,它現在已經修復。 –

+3

我同意作者的意見,這段代碼可能很糟糕,它會複製每一個數組的數組。它使用FORTRAN77的功能(特別是'continue'語句),這些功能已被更好的功能所取代。 –

1

根據註釋,您需要先執行一個分配語句(或在您的封面下執行分配的內容),然後才能定義binary陣列。分配語句的最簡單形式看起來像ALLOCATE(binary(10)),它將給出binary數組10個元素,使用默認值(它可以使用allocate語句對該數組進行更改)起始數組索引爲1.

其中size的分配是不容易使用數組之前已知有兩種基本方法:

  • 做兩遍,其中,在第一遍只計算多少元素是必需的,那麼該陣列被分配,則第二實際上通過了相關內容。
  • 將數組分配到初始大小(可能爲零),按需要逐漸增大數組。

在決定周圍的使用方法時,與分配和計算時每個測試的評估相關的開銷相關聯存在權衡。生長一個可分配的數組有點複雜(將原始臨時拷貝數據分配給臨時數據,釋放原始數據,將原始數據分配給新大小,複製數據從臨時恢復原始大小,暫時解除分配)。在Fortran 2003中,這個操作變得微不足道。

+0

謝謝。學習Fortran 95的時間 – Progrmr

+2

不,時間學習Fortran 2003. –

+0

爲什麼不'08呢? – Progrmr

3

下面是一個整數i轉換成其二進制表示的簡單方法:

write(*,'(b16)') i 

由於寫的,這不會寫任何前導0秒。如果你想領先0 S,嘗試

write(*,'(b16.16)') i 

當然,上面的代碼寫入二進制表示默認輸出單元,但使用Fortran語言的內部寫能力,我可以很容易地編寫位字符變量。例如:

character(len=16) :: bits 
... 
write(bits,'(b16.16)') i 

寫入的i的二進制數字到字符變量bits。現在

,如果你真正想要的是創建整數的二進制表示的每一個代表一個位,那麼像這樣

integer, dimension(16) :: bitarray 
... 
bitarray = 0 
... 
do ix = 1,len(bits) 
    if (bits(ix:ix)=='1') bitarray(ix) = 1 
end do 

可能會工作的數組。

2

1)您的崩潰發生是因爲您已經爲數組binary(:)分配了一個元素,並且While循環大概已移至i = 2,此時您的數組索引超出界限(崩潰) 。

2)Fortran有許多直接處理位的內在函數。例如,

a)Bit_Size(var)返回「var」中的位數,因此如果您必須使用allocatable,現在您已知道預先需要的數組大小。

b)BTest(iVar,pos)返回.True。如果在伊娃POS該位爲1

例如,使用,:

Integer  :: n 

n = Bit_Size(decimalnum)  

If(Allocated(Binary)) DeAllocate(Binary)   ! good practice 
Allocate(Binary(1:n))        ! in general, should get IOStat, just in case 

Binary(:) = 0 

ForAll(i=1:n, Mask = BTest(decimalnum, i-1)) ! remember, bit intrinsics index from 0 
    Binary(i) = 1 
End ForAll 

高於其他聲明......這是一個小更高效的比較做的,雖然,和可能有助於(一很少)朝smp。 Where/EndWhere結構也可以使用,但是我發現ForAll的效率更高一些。例如,如果你想創建一個「顯式」二進制表示,這可能是一種方法,IBits(var,pos,len)從var開始的pos中提取從var開始的比特。

等等等等

3)如果你「真的是」轉換DecimalNum斌,那麼你有(實質性)其他問題,如果減速也包括浮點月(即實數),因爲雷亞爾的位表示就指數而言。我認爲情況並非如此,因爲代碼/解釋涉及更多。最後,在Fortran中,Nums通常是「有符號」Num,前導位用於確定+ ve(0)或-ve(1)。因此,如果你正在進入「其他」方向(Bin2Dec),那麼會更喜歡一個額外的arg(或許是可選的),它控制結果是有符號還是無符號。如果無符號,那麼輸出變量需要比輸入變量「更大」(例如,如果將無符號1字節int轉換爲Fortran int,則必須至少使用2字節int(即輸入Integer(1)必須是輸出到一個整數(2))等