回 帖 发 新 帖 刷新版面

主题:fortran读写数据

跪求高手帮忙解决:Fortran读取数据  数据夹杂着重复的字母  
例: A A 
     1 2
     A A
     2 2
     1 3
     A A
     1 1
     2 2
     3 3
要求读出 (A A) 的总共个数 3个   每两个 (A A) 之间的数字行数  前两个是1行   2、3(A A)之间是2行
写成 3
     1
     1 2
     2
     2 2
     1 3
     3
     1 1
     2 2
     3 3
谢谢啦!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

回复列表 (共16个回复)

沙发


将数据存为1.dat  
      program main
     parameter N=1000 
       character*256 str(N)
       integer counts(N)

     open(10,file='1.dat',status='old')
   20  continue
       iline=iline+1    
     read(10,'(a)',end=30) str(iline)
     if(adjustl(trim(str(iline))) =='A A') then 
      k=k+1
     else
      counts(k)=counts(k)+1
     endif
       goto 20

   30  continue

     do i=1,k
       l=l+1
       write(*,'(i2)') counts(i)
      do j=1,counts(i)
       l=l+1
         write(*,*) adjustl(trim(str(l)))
      enddo
     enddo

    end

板凳

对一楼程序的若干个人意见,在此仅说个人认为不足之处:
1。 编程风格应该引起注意,变量最好声明后再用,变量没有初始化就使用(这一点也许很“致命”)
2。 若是文件最后出现空格,1 楼程序就不能很好的处理,若是中间再出现空格,又如何呢?
3。 若是文件比较长呢?内存的使用量是不是很大?

3 楼

按照 1 楼的编程思想,形成程序如下:

subroutine ABC
  implicit none
 
  integer, parameter:: N = 50
  character(len = 256):: str(N)
  integer:: counts(N)
  integer:: iLine
  integer:: i, j, k, l
  
  open(5, file='In05.txt', status='old')
  iLine = 1
  k = 0
  counts = 0
  Do While (.true.)   
    read(5, '(a)', end = 30) str(iline)
    if(adjustl(trim(str(iline))) == 'A A') then 
      k = k + 1
    else
      counts(k) = counts(k) + 1
    endif
    iline = iline + 1 
  End Do
 
30 close(5)

  l = 0
  do i = 1, k, 1
    l = l + 1
    write(*,'(i2)') counts(i)
    do j = 1, counts(i), 1
      l = l + 1
      write(*, *) adjustl(trim(str(l)))
    end do
  end do   ! i

  return
end subroutine 

输入文件: In05.txt
A A 
1 2
A A
2 2
1 3

A A
1 1
2 2
3 3


A A
1 1
2 2
1 1
2 2
3 3


A A
1 1
2 2
1 1
2 2
3 5
1 3
2 4
1 65
2 2
3 5

4 楼

本人略作思考,写出如下程序,输入文件与上贴相同。

subroutine ABCD
  implicit none
 
  character(len = 1):: str 
  integer:: IArr(2, 15)
  integer:: icount
  integer:: i   ! for loop 
  
  open(5, file='In05.txt', status='old')
  icount = 0
  Do While (.true.)   
    read(unit = 5, fmt = '(a)', end = 30) str 
    if( (str /= 'A') .and. (str /= " ") ) then 
      backspace( unit = 5 )
      icount = icount + 1      
      read(unit = 5, fmt = *, end = 30) IArr(1 : 2, icount)
    else if ( icount /= 0 ) then 
      write(*, *) icount
      do i = 1, icount, 1
        write(*, *) IArr(1 : 2, i)
      end do   ! i      
      icount = 0
    end if
  End Do
 
30 close(5)

  return
end subroutine 

不足之处,就是数据要从第一格开始,不过,这个可以修改 if 语句,有兴趣的同志,自己试试。

5 楼

经如下小的修改,可以克服上述“毛病”

subroutine ABCD
  implicit none
 
  character(len = 8):: str 
  integer:: IArr(2, 15)
  integer:: icount
  integer:: i   ! for loop 
  
  open(5, file='In05.txt', status='old')
  icount = 0
  Do While (.true.)   
    read(unit = 5, fmt = '(a)', end = 30) str
    str = adjustl( str ) 
    if( (str(1 : 1) /= 'A') .and. (str(1 : 1) /= " ") ) then 
      backspace( unit = 5 )
      icount = icount + 1      
      read(unit = 5, fmt = *, end = 30) IArr(1 : 2, icount)
    else if ( icount /= 0 ) then 
      write(*, *) icount
      do i = 1, icount, 1
        write(*, *) IArr(1 : 2, i)
      end do   ! i      
      icount = 0
    end if
  End Do
 
30 close(5)

  return
end subroutine

6 楼

恩,利用backspace就可以部分输出了,但是同样的内存问题没有很好地解决,如果一个AA下面有很长的数字串呢?极端情况下整个文件就一个AA,而且文件很大!不过这都不是大问题,能解决实际问题就行,追求完美或许会把程序弄得很复杂。

7 楼

算法
(1)打开原数据文件,并建立一个新的数据文件以备输出;
(2)循环读取一行字符,直至到文件末尾,并定义一个计数器变量;
(3)判别是字符(AA)行还是数字行,如果是字符行则计数器变量累加1,将计数器写入输出文件,若是数据行,直接将数据行写入输出文件即可;
(4)边读边输出,需要定义的变量是很少的,且与文件中数据的多少无关。

8 楼

你没看清题意,需要统计每个字符串下面数字的行数,你那样做是实现不了的。

9 楼

可以这样:
将统计数量先输出到临时文件,然后再重新读入文件并与临时文件的统计数据进行合并输出到目标文件。
此法所占内存少,但需要两次读取文件:)

10 楼

[quote]可以这样:
将统计数量先输出到临时文件,然后再重新读入文件并与临时文件的统计数据进行合并输出到目标文件。
此法所占内存少,但需要两次读取文件:)[/quote]

同意你的意见,临时文件就不必了吧,一个数组就搞定了,第一遍读把每个字符下面的数字行数存入数组,第二遍就读一行字符,然后按数组记录的行数去读数字就行了!

我来回复

您尚未登录,请登录后再回复。点此登录或注册