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

String 从包含乘法的字符串中读取子字符串,string,fortran,gfortran,String,Fortran,Gfortran,我是一个用Fortran编程的科学家,我想出了一个奇怪的行为。在我的一个程序中,我有一个包含多个“单词”的字符串,我想将所有单词作为子字符串读取。第一个单词以整数和通配符开头,如“2*something” 当我对该字符串执行内部读取时,我希望读取所有WOD,但相反,read函数会重复读取第一个子字符串。我不明白为什么,也不知道如何避免这种行为 下面是一个复制这种行为的极简主义示例程序。我希望它读取三个子字符串并在屏幕上打印“3*abc”。相反,我得到了“a” 我做错了什么?你能帮我解释一下发生了

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

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

下面是一个复制这种行为的极简主义示例程序。我希望它读取三个子字符串并在屏幕上打印“3*abc”。相反,我得到了“a”

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

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


您正在使用列表定向输入(格式说明符)。在列表定向输入中,数字(n)后跟星号表示“重复此项n次”,因此它的处理方式就像输入是
ac
。您需要输入
'3*a'bc
,才能获得所需的内容

我将借此机会指出,列表定向I/O有时是错误的选择,因为其固有的灵活性可能不是您想要的。它对重复计数、空值和不受限制的字符串都有规则,这常常让程序员感到惊讶。我还经常看到程序员抱怨列表定向输入没有在预期的时候给出错误,因为编译器有一个扩展,或者程序员不理解这个特性有多自由


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

在@SteveLionel的回答之后,这里是
列表定向顺序读取语句参考的相关部分。
(在本例中,例如,但您可以为特定的编译器找到它,并且不会有太大的不同)

如果对应的I/O列表项的类型为默认字符,且以下为真,则字符串不需要分隔撇号或引号:

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

字符串不会跨记录边界继续

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

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

未删除的字符串由遇到的第一个空格、逗号、斜杠或记录结尾终止。未删除的字符串中的撇号和引号按原样传输

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

  • 格式化顺序读取:

    要使用它,您可以将
    *
    更改为实际的格式说明符。如果您事先知道字符串的长度,这将与
    '(a3、a2、a2)
    一样简单。或者,您可以使用与数据匹配的格式说明符,但这通常要求您知道内容的长度或格式

  • 定向的格式化顺序列表:

    您当前正在使用此选项(
    *
    格式描述符)。正如我们已经向您展示的,这种I/O具有许多神奇和令人惊讶的行为。让您感到震惊的是
    n*cte
    这件事,它被解释为
    n
    重复
    cte
    文字。 正如Steve Lionel所说,你可以在有问题的单词周围加引号,这样它就可以作为一个整体进行解析。或者,正如@evets所建议的,你可以使用intrinsic或。另一个选项是将通配符从星号改为其他任何字符

  • 格式化名称列表:

    好吧,如果你的数据是(或可能是)以名单的形式呈现的话,这可能是一个选择,但我真的认为这不是你的情况

  • 未格式化:

    这可能不适用于您的情况,因为您正在读取字符变量,并且


  • 否则,您可以通过函数而不是I/O操作来拆分字符串。这没有内在的功能,但您可以轻松地使用它(请参阅以供参考)。正如您可能已经注意到的那样,在fortran中操作字符串……至少有些尴尬。有一些库()如果你在FORTRAN中做了很多字符串,这可能是有用的。

    史提夫给出了你为什么得到你观察到的结果的答案。你可以考虑使用<代码>索引>代码>内在函数将字符串拆分成子串。你可以做一些事情,比如“代码> n=index(string,'');v1=string(1:n-1))。。我将留给您去弄清楚如何获取其他子字符串。非常感谢,这就解释了我的问题。由于我不知道子字符串的长度,我无法使用格式化读取。我将把每个子字符串嵌入单引号作为一种解决方法。
    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