我有一个文本文件,其中包含逗号分隔的数字,如:
757.76019287, 759.72045898, 760.97259521, 763.45477295, 765.99475098, 770.2713623
目前还不知道这个文件中有多少这样的数字;它各不相同,但仅限于几百个数字。
目标是:
打开这个文件(比如
customwav.txt
(,找出这个文件中有多少数字-->将它们放入一个整数n
中。将这些数字的内存分配到一个数组中-->我已经有了为我做这件事的子程序
将一行数字读入这个已分配的数组。
在Fortran中执行1和3的最佳方法是什么?
假设您的文件只有一行,如下所示:
-
如果你知道数字的格式,你可以进行非前进I/O;例如,如果所有数字都是使用12个空格的浮点数,其中8个是小数位数,并且它们由逗号和空格分隔,没有最后的逗号&最后一个数字后的空格:
integer, parameter :: DP = selected_real_kind(15,300) real(kind=DP) :: x real(kind=DP), allocatable :: xall(:) integer :: u integer :: n character(len=2) :: c open(newunit=u, file='customwav.txt',status='old',action='read') n = 0 do read(u, '(f12.8)', advance='no') x n = n + 1 read(u, '(2a)', advance='no', eor=100) c if (c .ne. ', ') STOP 'unknown format' end do 100 write(*,*) n allocate(xall(n)) rewind(u) read(u, *) xall close(u) write(*,*) xall
-
如果您不知道格式,或者格式以非常规的方式更改,则一种懒惰(且效率低下(的方法是尝试一次读取整个数组。下面的愚蠢代码通过逐个增加大小来尝试这一点,但您可以进行平分。
integer, parameter :: DP = selected_real_kind(15,300) integer, parameter :: MaxN = 1000 real(kind=DP), dimension(MaxN) :: x integer :: u integer :: n integer :: error open(newunit=u, file='customwav.txt',status='old',action='read') error = 0 n = 0 do while (error.eq.0) read(u, *, iostat=error) x(1:n+1) if (error .eq. 0) then n = n + 1 rewind(u) end if end do write(*,*) n rewind(u) read(u, *) x(1:n) close(u) write(*,*) x(1:n)
-
如果允许使用非Fortran工具,则可以使用以下shell命令计算(单行(文件中的逗号数
$ grep -o ',' customwav.txt | wc -l
所以浮点数可能是这个数字加一(取决于格式(。对于多行文件,您可以使用获得每行逗号计数的列表
$ f=customwav.txt $ for lin in $(seq $(cat $f | wc -l)) > do > sed -n ${lin}'p' $f | grep -o ',' | wc -l > done
对于未知文件,我的方法是首先使用流I/O打开它,一次读取1个字符,并计算文件中所有字符的出现次数:count_characters(0:255(。
这可以告诉你很多关于预期的信息,例如:
LF indicates number of lines in file
CR indicates DOS file rather than unix file format
. can indicate real numbers
, can indicate csv file format
; / : can indicate other delimiters
presence of non-numeric characters indicates non-numeric information
E or e can indicate scientific format
/ or : can indicate date/time info
The count_<lf> + count_, is an estimate of numbers in the file.
这种方法的优点是,它可以识别可能要恢复的异常数据。作为一个独立的实用程序,它可能是最好的,因为解释可能很难编码。
OP>告诉我们该文件包含几百个实数,用逗号整齐地分隔。这里有一个简单的方法,可以将它们读取到合适大小的数组中。这与文件中的行数无关。
首先,声明一个可分配数组和一个整数,用于处理稍后发生的文件结尾
real, dimension(:), allocatable :: numbers
integer :: ios
分配数组,但需要一些开销。是的,我只是想一口气阅读文件中的数字,我不会试图弄清楚有多少。
allocate(numbers(1000))
将每个值设置为一个保护值,其效用稍后会很明显;这确实假设文件不会包含所选的保护值
numbers = -huge(1.0)
读取数字;我认为inunit
单元上的文件已经打开
read(inunit,*,iostat=ios) numbers
在这一点上,ios
有一个非零值,但对于问题中概述的简单情况,没有必要对它做任何事情,我们被告知只有几百个。最后是
numbers = pack(numbers, numbers>-huge(1.0))
以将CCD_ 5重新分配到合适的大小。