【问题标题】:How to get command line arguments of unknown length in Fortran?如何在 Fortran 中获取未知长度的命令行参数?
【发布时间】:2016-02-02 22:35:57
【问题描述】:

我想从用于运行程序的命令行中读取一些文本字符串。我在一个基本上类似于以下内容的程序中使用了内部子程序GET_COMMAND_ARGUMENT

program test
character(len=100) :: argument
call GET_COMMAND_ARGUMENT(1,argument)
print*, argument
end program test

这里的问题是我觉得在编译时设置字符串的最大长度有点危险。一些参数通常是带有路径的文件,因此它们可能很长。将长度静态设置为 1000 的解决方案听起来很丑陋。

难道在 Fortran 中没有更优雅的方式来定义能够包含长度仅在运行时才知道的字符链的字符串吗?

【问题讨论】:

    标签: arrays string fortran


    【解决方案1】:

    可以使用所谓的延迟长度字符变量。这些不是固定不变的长度,它们的使用可以在诸如a related one about data input之类的问题中找到。

    但是,即使使用了延迟长度变量(因为这是语法)

    character(len=:), allocatable :: argument
    allocate(character(some_length) :: argument)  ! For integer some_length
    call GET_COMMAND_ARGUMENT(1,argument)
    print*, argument
    end
    

    仍然需要担心some_length 应该是什么。如果我们只选择 100,我们就会回到原来的位置。

    我们不得不担心这一点,因为get_command_argument 没有采用这样的延迟长度参数并将其分配给所需的长度。那是

    character(len=:), allocatable :: argument
    call GET_COMMAND_ARGUMENT(1,argument)  ! Will argument be allocated in the subroutine?
    print*, argument
    end
    

    提供“不”的答案。

    接下来,我们来看看get_command_argument 的其他(可选)参数。特别是有一个叫length

    character(len=:), allocatable :: argument
    integer arglen
    call GET_COMMAND_ARGUMENT(1,length=arglen)
    allocate(character(arglen) :: argument)
    call GET_COMMAND_ARGUMENT(1,value=argument)
    print*, argument
    end
    

    当然,可以创建一个包装子例程,它确实采用可分配的延迟长度字符变量并完成所有工作。

    【讨论】:

    • 你的方法好多了,不知怎的我忘记了这个论点。
    • 也许还值得注意的是,这种方法也适用于get_environment_variable
    • 谢谢,这很有帮助,确实解决了这个问题。我有一个小问题,为什么需要相当复杂的allocate(character(some_length) :: argument) 而不是更简单的allocate(argument(some_length))
    • @Onturenio 后一种语法用于数组。考虑一个字符数组allocate(character(char_len) :: argument(array_len))
    • @Onturenio 添加到 Vladimir F 的评论中,allocate( type-spec :: ...) 表单用于设置分配的类型和类型参数。字符变量的长度是一个类型参数。您也可以看到这种语法用于多态变量设置动态类型或参数化派生类型。
    【解决方案2】:

    为了完整起见,我将保留此内容,它可能对某人有用,但 francescalus 的回答要好得多。

    基本上,只需使用一些默认长度读取它,检查STATUS 变量,如果它不适合,再试一次。

    来自 gcc 手册:

    如果参数检索失败,STATUS 为正数;如果值 包含截断的命令行参数,STATUS 为 -1;和 否则 STATUS 为零。

    所以:

    character(len=:), allocatable :: argument
    integer :: stat, n
    
    n = 100
    allocate(character(n) :: argument)
    
    do
      call GET_COMMAND_ARGUMENT(1,argument, status=stat)
      if (stat>=0) exit
      deallocate(argument)
      n = n * 2
      allocate(character(n) :: argument)
    end do
    
    if (stat>0) error...
    
    argument = trim(argument)
    
    print*, argument
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-30
      • 2012-10-04
      • 2013-02-06
      • 2016-06-22
      • 2012-10-21
      • 1970-01-01
      • 2019-06-09
      • 1970-01-01
      相关资源
      最近更新 更多