主题:fortran读写数据
gf198712
[专家分:0] 发布于 2010-08-20 14:24:00
跪求高手帮忙解决: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个回复)
沙发
jstzhurj [专家分:4680] 发布于 2010-08-21 11:20:00
将数据存为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
板凳
asymptotic [专家分:16630] 发布于 2010-08-22 10:20:00
对一楼程序的若干个人意见,在此仅说个人认为不足之处:
1。 编程风格应该引起注意,变量最好声明后再用,变量没有初始化就使用(这一点也许很“致命”)
2。 若是文件最后出现空格,1 楼程序就不能很好的处理,若是中间再出现空格,又如何呢?
3。 若是文件比较长呢?内存的使用量是不是很大?
3 楼
asymptotic [专家分:16630] 发布于 2010-08-22 10:26:00
按照 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 楼
asymptotic [专家分:16630] 发布于 2010-08-22 10:31:00
本人略作思考,写出如下程序,输入文件与上贴相同。
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 楼
asymptotic [专家分:16630] 发布于 2010-08-22 10:42:00
经如下小的修改,可以克服上述“毛病”
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 楼
jstzhurj [专家分:4680] 发布于 2010-08-22 23:44:00
恩,利用backspace就可以部分输出了,但是同样的内存问题没有很好地解决,如果一个AA下面有很长的数字串呢?极端情况下整个文件就一个AA,而且文件很大!不过这都不是大问题,能解决实际问题就行,追求完美或许会把程序弄得很复杂。
7 楼
cqo168 [专家分:180] 发布于 2010-08-30 21:55:00
算法
(1)打开原数据文件,并建立一个新的数据文件以备输出;
(2)循环读取一行字符,直至到文件末尾,并定义一个计数器变量;
(3)判别是字符(AA)行还是数字行,如果是字符行则计数器变量累加1,将计数器写入输出文件,若是数据行,直接将数据行写入输出文件即可;
(4)边读边输出,需要定义的变量是很少的,且与文件中数据的多少无关。
8 楼
jstzhurj [专家分:4680] 发布于 2010-08-31 18:34:00
你没看清题意,需要统计每个字符串下面数字的行数,你那样做是实现不了的。
9 楼
cgl_lgs [专家分:21040] 发布于 2010-08-31 19:48:00
可以这样:
将统计数量先输出到临时文件,然后再重新读入文件并与临时文件的统计数据进行合并输出到目标文件。
此法所占内存少,但需要两次读取文件:)
10 楼
jstzhurj [专家分:4680] 发布于 2010-08-31 20:14:00
[quote]可以这样:
将统计数量先输出到临时文件,然后再重新读入文件并与临时文件的统计数据进行合并输出到目标文件。
此法所占内存少,但需要两次读取文件:)[/quote]
同意你的意见,临时文件就不必了吧,一个数组就搞定了,第一遍读把每个字符下面的数字行数存入数组,第二遍就读一行字符,然后按数组记录的行数去读数字就行了!
我来回复