从包含乘法的字符串中读取子字符串

时间:2019-01-21 14:48:41

标签: string fortran gfortran

我是Fortran的一名编程科学家,但是我想到了一个奇怪的行为。在我的一个程序中,我有一个包含多个“单词”的字符串,并且我想将所有单词作为子字符串读取。第一个单词以整数和通配符开头,例如“ 2 * something”。

当我对该字符串执行内部读取时,我希望读取所有wod,但是READ函数会重复读取第一个子字符串。我不明白为什么,也不知道如何避免这种行为。

下面是一个极简示例程序,它再现了这种行为。我希望它能够读取三个子字符串并在屏幕上打印“ 3 * a b c”。相反,我得到“ a a a”。

我在做什么错?您能帮我解释一下发生了什么吗?

我正在使用Gfortran 7.3(7.3.0-27ubuntu1〜18.04)在GNU / Linux x64下编译程序。

PROGRAM testread

IMPLICIT NONE
CHARACTER(LEN=1024):: string
CHARACTER(LEN=16):: v1, v2, v3

string="3*a b c"

READ(string,*) v1, v2, v3

PRINT*, v1, v2, v3

END PROGRAM testread

2 个答案:

答案 0 :(得分:5)

您正在使用列表定向输入(*格式说明符)。在列表控制的输入中,数字(n)后跟星号表示“将此项重复n次”,因此将其视为输入为<app-room-card *ngIf="categories" [categories]="categories"></app-room-card> 处理。您需要输入a a a b c作为输入。

我将以此为契机指出列表导向的I / O有时是错误的选择,因为其固有的灵活性可能不是您想要的。它为重复计数,空值和无界字符串之类的规则制定规则通常令程序员感到惊讶。我还经常看到程序员抱怨,在预期的情况下,列表导向的输入没有给出错误,因为编译器具有扩展名,或者程序员不了解该功能的自由度。

我建议您选择Fortran语言参考,并仔细阅读有关列表导向I / O的部分。您可能会发现需要使用显式格式或更改程序的期望。

答案 1 :(得分:3)

在@SteveLionel的答案之后,这是list-directed sequential READ statements上参考的相关部分(在这种情况下,对于Intel Fortran,但是您可以为您的特定编译器找到它,但不会找到它会大不相同)。

  

如果相应的I / O列表项的类型为default字符,并且字符串为真,则字符串不需要用撇号或引号引起来:

     

字符串不包含空格,逗号(,)或斜杠(/)。

     

字符串不能跨记录边界继续。

     

字符串中的第一个非空白字符不是撇号或引号。

     

前导字符不是一串数字,后跟一个星号。

     

一个无界的字符串以遇到的第一个空白,逗号,斜杠或记录结尾结尾。未定界字符串中的撇号和引号按原样传输。

Fortran中总共有4 forms个顺序读取语句,您可以选择最适合您的选项:

  1. 格式化顺序读取:

    要使用此功能,请将*更改为实际的格式说明符。如果您事先知道字符串的长度,这将像'(a3,a2,a2)'一样容易。或者,您可能会附带一个与您的数据匹配的格式说明符,但这通常要求您知道素材的长度或格式。

  2. 按顺序列出的格式化顺序:

    您当前正在使用此选项(*格式描述符)。正如我们已经向您展示的那样,这种I / O带有很多魔术和令人惊讶的行为。击中您的是n*cte事物,它被解释为n文字的cte重复。 正如史蒂夫·莱昂内尔(Steve Lionel)所说,您可以在有问题的单词周围加上引号,以便将其解析为一个整体。或者,如@evets所建议的,您可以使用内在函数indexscan来拆分或破坏字符串。另一种选择是将通配符从星号更改为其他任何内容。

  3. 格式化名称列表:

    好吧,如果您的数据以(或可以)名称列表格式显示,则可以选择,但我确实认为情况并非如此。

  4. 未格式化:

    这可能不适用于您的情况,因为您正在从字符变量和an internal READ statement can only be formatted中读取内容。

否则,您可以通过函数而不是I / O操作来分割字符串。这没有内在的要求,但是您可以轻松解决其中的麻烦(请参阅this thread作为参考)。您可能已经注意到,至少在fortran中操作字符串很麻烦。如果您在Fortran中做很多字符串工作,那么有一些库(like this)可能会有用。