简体   繁体   English

Fortran用*读取数据以表示类似的数据

[英]Fortran read of data with * to signify similar data

My data looks like this 我的数据看起来像这样

-3442.77 -16749.64 893.08 -3442.77 -16749.64 1487.35 -3231.45 -16622.36 902.29 

..... .....

159*2539.87 10*0.00 162*2539.87 10*0.00 

which means I start with either 7 or 8 reals per line and then (towards the end) have 159 values of 2539.87 followed by 10 values of 0 followed by 162 of 2539.87 etc. This seems to be a space-saving method as previous versions of this file format were regular 6 reals per line. 这意味着我从每行7或8个实数开始,然后(到最后)有159个值2539.87,接着是10个值0,接着是162个2539.87等。这似乎是一个节省空间的方法,因为以前的版本这种文件格式是每行6个实际常规。

I am already reading the data into a string because of not knowing whether there are 7 or 8 numbers per line. 我已经将数据读入字符串,因为不知道每行是否有7或8个数字。 I can therefore easily spot lines that contain *. 因此,我可以轻松找到包含*的行。 But what then? 那么呢? I suppose I have to identify the location of each * and then identify the integer number before and real value after before assigning to an array. 我想我必须确定每个*的位置,然后在分配给数组之前识别之前的整数和实数值。 Am I missing anything? 我错过了什么吗?

Read the line. 阅读该行。 Split it into tokens delimited by whitespace(s). 将其拆分为由空格分隔的标记。 Replace the * in tokens that have it with space. 用空格替换带有它的标记中的* Then read from the string one or two values, depending on wheather there was an asterisk or not. 然后从字符串中读取一个或两个值,具体取决于是否有星号。 Sample code follows: 示例代码如下:

REAL, DIMENSION(big) :: data
CHARACTER(LEN=40) :: token
INTEGER :: iptr, count, idx
REAL :: val

iptr = 1
DO WHILE (there_are_tokens_left)
  ... ! Get the next token into "token"
  idx = INDEX(token, "*")
  IF (idx == 0) THEN
    READ(token, *) val
    count = 1
  ELSE
    ! Replace "*" with space and read two values from the string
    token(idx:idx) = " "
    READ(token, *) count, val
  END IF
  data(iptr:iptr+count-1) = val  ! Add "val" "count" times to the list of values
  iptr = iptr + count
END DO

Here I have arbitrarily set the length of the token to be 40 characters. 在这里,我可以任意设置令牌的长度为40个字符。 Adjust it according to what you expect to find in your input files. 根据您在输入文件中找到的内容进行调整。

BTW, for the sake of completeness, this method of compressing something by replacing repeating values with value/repetition-count pairs is called run-length encoding (RLE). 顺便说一句,为了完整起见,这种通过用值/重复计数对替换重复值来压缩某些东西的方法称为行程编码 (RLE)。

Your input data may have been written in a form suitable for list directed input (where the format specification in the READ statement is simply ''*''). 您的输入数据可能已经以适合列表定向输入的形式写入(其中READ语句中的格式规范只是''*'')。 List directed input supports the r*c form that you see, where r is a repeat count and c is the constant to be repeated. 列表定向输入支持您看到的r * c形式,其中r是重复计数,c是要重复的常量。

If the total number of input items is known in advance (perhaps it is fixed for that program, perhaps it is defined by earlier entries in the file) then reading the file is as simple as: 如果事先知道输入项的总数(可能它对于该程序是固定的,也许它是由文件中的早期条目定义的)那么读取文件就像这样简单:

REAL :: data(size_of_data)
READ (unit, *) data

For example, for the last line shown in your example on its own ''size_of_data'' would need to be 341, from 159+10+162+10. 例如,对于您自己的''size_of_data'中示例中显示的最后一行,则需要为341,从159 + 10 + 162 + 10。

With list directed input the data can span across multiple records (multiple lines) - you don't need to know how many items are on each line in advance - just how many appear in the next "block" of data. 使用列表定向输入,数据可以跨越多个记录(多行) - 您不需要事先知道每行上有多少项 - 只需要在下一个“块”数据中出现多少项。

List directed input has a few other "features" like this, which is why it is generally not a good idea to use it to parse "arbitrary" input that hasn't been written with it in mind - use an explicit format specification instead (which may require creating the format specification on the fly to match the width of the input field if that is not know ahead of time). 列表定向输入有一些像这样的其他“特性”,这就是为什么用它来解析没有用它写的“任意”输入通常不是一个好主意 - 使用显式格式规范(这可能需要动态创建格式规范以匹配输入字段的宽度(如果事先不知道)。

If you don't know (or cannot calculate) the number of items in advance of the READ statement then you will need to do the parsing of the line yourself. 如果您不知道(或无法计算)READ语句之前的项目数,那么您将需要自己解析该行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM