开发者

Fortran: How do I read the first character from each line of a text file?

this is my first time trying to program in Fortran. I'm trying to write a program that prints the first 1476 terms of the Fibonacci sequence, then examines the first digit of each term and stores the number of 1s, 2s, 3s, ..., 9s that occur in an array.

The problem that I can't seem to figure out is how to read the first digit of each term. I've tried several things but am having difficulty with my limited knowledge of Fortran techniques. I write the terms to a text file and the idea is to read the first digit of each line and accumulate the respective number in the array. Does anyone have any suggestions of how to do this?

Here is my code so far:

(edit: I included the code I have for reading the file. Right now it just prints out 3.60772951994415996E-313, which seems like an address of some sort, because it's not one of the Fibonacci numbers. Also, it is the only thing printed, I expected that it would print out every line of the file...)

(edit edit: After considering this, perhaps there's a way to format the writing to the text file to just the first digit. Is there a way to set the number of significant digits of a real number to one? :P)

subroutine writeFib(n)
  integer ::  i
  real*8 :: prev, current, newFib
  prev = 0
  current = 1
  do i = 1, n
     newFib = prev + current
     prev = current
     current = newFib
     write(7,*) newFib
  end do
  return
end subroutine

subroutine rec开发者_开发百科ordFirstDigits(a)
  integer :: openStat, inputStat
  real*8 :: fibNum
  open(7, file = "fort.7", iostat = openStat)
  if (openStat > 0) stop "*** Cannot open the file ***"
  do
     read(7, *, iostat = inputStat) fibNum
     print *,fibNum
     if (inputStat > 0) stop "*** input error ***"
     if (inputStat < 0) exit ! end of file
  end do
  close(7)
end subroutine

program test
  integer :: k, a(9)
  k = 1476
  call writeFib(k)
  call recordFirstDigits(a)
end program


Although the suggestions were in place, there were also several things that were forgotten. Range of the REAL kind, and some formatting problems.

Anyways, here's one patched up solution, compiled and working, so try to see if this will work for you. I've took the liberty of choosing my own method for fibonacci numbers calculation.

  program SO1658805
  implicit none

  integer, parameter :: iwp = selected_real_kind(15,310)
  real(iwp) :: fi, fib
  integer :: i
  character(60) :: line
  character(1) :: digit
  integer :: n0=0, n1=0, n2=0, n3=0, n4=0, n5=0, n6=0, n7=0, n8=0, n9=0

  open(unit=1, file='temp.txt', status='replace')
  rewind(1)
  !-------- calculating fibonacci numbers -------
  fi = (1+5**0.5)/2.
  do i=0,1477
    fib = (fi**i - (1-fi)**i)/5**0.5
    write(1,*)fib,i  
  end do
  !----------------------------------------------
  rewind(1)

  do i=0,1477
    read(1,'(a)')line
    line = adjustl(line)
    write(*,'(a)')line


    read(line,'(a1)')digit

     if(digit.eq.' ') n0=n0+1
     if(digit.eq.'1') n1=n1+1
     if(digit.eq.'2') n2=n2+1
     if(digit.eq.'3') n3=n3+1
     if(digit.eq.'4') n4=n4+1
     if(digit.eq.'5') n5=n5+1
     if(digit.eq.'6') n6=n6+1
     if(digit.eq.'7') n7=n7+1
     if(digit.eq.'8') n8=n8+1
     if(digit.eq.'9') n9=n9+1
  end do
  close(1)

  write(*,'("Total number of different digits")')
  write(*,'("Number of digits 0: ",i5)')n0
  write(*,'("Number of digits 1: ",i5)')n1
  write(*,'("Number of digits 2: ",i5)')n2
  write(*,'("Number of digits 3: ",i5)')n3
  write(*,'("Number of digits 4: ",i5)')n4
  write(*,'("Number of digits 5: ",i5)')n5
  write(*,'("Number of digits 6: ",i5)')n6
  write(*,'("Number of digits 7: ",i5)')n7
  write(*,'("Number of digits 8: ",i5)')n8
  write(*,'("Number of digits 9: ",i5)')n9

  read(*,*)

  end program SO1658805

Aw, ... I just read you need the number of digits stored in to an array. While I just counted them.

Oh well, ... "left as an exercise for the reader ..." :-)


Can you read with a FORMAT(A1)? It's been 20 years so I don't remember the exact syntax.


I wonder why the open statement succeeds when file 7 hasn't been closed. I think you need an endfile statement and/or a rewind statement in between writing and reading.

Paul Tomblin posted what you have to do after you solve your problem in getting reads to work in the first place.


I am getting an 'end of line' runtime error

You don't show the ! code to read here... which makes it kind of difficult to guess what you are doing wrong :-)

Perhaps you need a loop to read each line and then jump out of the loop to a continue statement when there are no more lines.

Something like this:

   do
      read(7,*,end=10) fibNumber
   end do
   10 continue

Better still - look at the more modern style used in this revcomp program.


here are some hints:

  1. You don't need to use characters, much less file i/o for this problem (unless you forgot to state that a file must be created).
  2. Therefore, use math to find your statistics. There are lots of resources on Fibonacci numbers that might provide a simplifying insight or at least a way to independently spot check your answers.
    • Here is a complicated hint in non-Fortran lingo:
      floor(10^(frac(log_10(7214989861293412))))
      (Put this in Wolfram Alpha to see what it does.)
    • A simpler hint (for a different approach) is that you can do very well in Fortran with simple arithmetic inside of looping constructs--at least for a first pass at the solution.
  3. Accumulate your statistics as you go. This advice would even apply to your character-driven approach. (This problem is ideally suited for coming up with a cute indexing scheme for your statistics, but some people hate cute schemes in programming. If you don't fear cuteness ... then you can have associative arrays in Fortran as long as your keys are integers ;-)
  4. The most important aspect of this problem is the data type you will use to calculate your answers. For example, here's the last number you will have to print.

Cheers, --Jared

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜