2012-10-08 55 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))等