GNU Fortran编译器的GNU扩展提供了子程序GETCWD() ,它获取当前工作目录。 但是,我的代码也必须可移植到ifortnagfor编译器,并且我使用F2003功能。

那么,F2003及更高版本的GETCWD()有替代品吗?

我在这里有标准,但它相当大,我现在已经经历了一段时间并且没有找到任何有用的东西......

===============>>#1 票数:6

如评论中所述,您可以使用标准Fortran的get_environment_variable (例如F2008 13.7.67)。 此示例程序查询$PWD的值,该值应包含shell在调用可执行文件时所在的目录。

program test
 implicit none
 character(len=128) :: pwd
 call get_environment_variable('PWD',pwd)
 print *, "The current working directory is: ",trim(pwd)
end program

它的输出:

casey@convect code % pwd
/home/casey/code
casey@convect code % so/getpwd 
 The current working directory is: /home/casey/code

这是标准的Fortran,但它的可移植性将仅限于设置此变量的Unix和类Unix shell。

另一种选择虽然标准但丑陋(在我看来)是使用execute_command_line来运行一个命令,可以将工作目录输出到临时文件(例如pwd > /tmp/mypwd ),然后读取该文件。

===============>>#2 票数:5 已采纳

您还可以使用ISO_C_Binding并调用相应的C函数:

cwd.c:

#ifdef _WIN32
/* Windows */
#include <direct.h>
#define GETCWD _getcwd

#else
/* Unix */
#include <unistd.h>
#define GETCWD getcwd

#endif

void getCurrentWorkDir( char *str, int *stat )
{
  if ( GETCWD(str, sizeof(str)) == str ) {
    *stat = 0;
  } else {
    *stat = 1;
  }
}

test.F90:

program test
 use ISO_C_Binding, only: C_CHAR, C_INT
 interface
   subroutine getCurrentWorkDir(str, stat) bind(C, name="getCurrentWorkDir")
     use ISO_C_Binding, only: C_CHAR, C_INT
     character(kind=C_CHAR),intent(out) :: str(*)
     integer(C_INT),intent(out)         :: stat
    end subroutine
  end interface
  character(len=30)   :: str
  integer(C_INT)      :: stat

  str=''
  call getCurrentWorkDir(str, stat)
  print *, stat, trim(str)

end program

此代码适用于Windows和Unix派生(Linux,OSX,BSD等)

===============>>#3 票数:0

接受的答案包含两个错误(它将错误的值作为字符串的长度传递给GETCWD ,并留在C_NULL_CHAR )。 这个答案纠正了这些错误,使界面更易于从Fortran中使用。

基本思路是一样的:使用C调用getcwd_getcwd ,并使用Fortran的C互操作性功能调用C包装器。 在Fortran端,包装器子例程用于处理字符串长度,因此不必显式传递。

此外, C_INTC_CHAR不必与Fortran端需要的默认整数和默认字符相同(尽管在实践中我不知道任何C_CHAR和默认字符不同的系统)。 包装器也可以转换它们。 此外,从C返回的字符串包含终止C_NULL_CHAR ,必须删除该字符串才能使字符串在Fortran端可用。

C代码:

#ifdef _WIN32
#include <direct.h>
#define GETCWD _getcwd
#else
#include <unistd.h>
#define GETCWD getcwd
#endif

/* Return 0 on success, 1 on error. */
int getCWDHelper(char *str, int len)
{
    return GETCWD(str, len) != str;
}

Fortran代码:

module cwd
    use iso_c_binding, only: C_INT, C_CHAR, C_NULL_CHAR
    implicit none
    private
    public :: getCWD

    interface
        function getCWDHelper(str, len) bind(C, name="getCWDHelper")
            use iso_c_binding, only: C_INT, C_CHAR
            integer(kind=C_INT) :: getCWDHelper
            character(kind=C_CHAR), intent(out) :: str(*)
            integer(kind=C_INT), value :: len
        end function getCWDHelper
    end interface

contains

    ! Writes the current working directory path into str.
    ! Returns 0 on success, or 1 on error.
    function getCWD(str)
        integer :: getCWD
        character(*), intent(out) :: str

        integer :: i, length
        character(len=len(str), kind=C_CHAR) :: str_copy

        ! Call the C helper, passing the length as the correct int kind
        getCWD = getCWDHelper(str_copy, len(str_copy, kind=C_INT))

        if (getCWD /= 0) then
            str = '' ! Error, clear the string
            return
        end if

        ! Copy the C_CHAR string to the output string,
        ! removing the C_NULL_CHAR and clearing the rest.
        length = index(str_copy, C_NULL_CHAR) - 1
        do i = 1, length
            str(i:i) = char(ichar(str_copy(i:i)))
        end do
        str(length+1:) = ''
    end function getCWD

end module

测试代码:

program test
    use cwd, only: getCWD
    implicit none

    character(len=255) :: path
    integer :: error

    error = getCWD(path)

    print *, error
    if (error == 0) print *, path
end program

使返回值可分配和循环以获得足够的大小留给读者练习。

  ask by LienM translate from so

未解决问题?本站智能推荐:

2回复

Fortran 2003中的常量函数指针数组

亲爱的Fortran程序员, 有人知道,是否可以在Fortran 2003或更高版本中声明一个常量(参数)过程指针数组? 如下所示,我有一个切换器函数,它根据传入的整数参数调用不同的函数。 它使用一组过程指针(包含在派生中)类型。 在运行之前,必须通过init()例程初始化此数组
1回复

在Fortran中是否有用于将数组初始化为零的内在函数?

有没有办法在Fortran中将数组(向量,矩阵,甚至标量)设置为零? 2003/2008似乎将Fortran提升到了一个非常现代的水平,我想知道它们是否包含一种无需设置即可将数组值设置为零的简便方法。 其中X是2维矩阵中的行数,Y是2维矩阵中的列数。 可以将其概括为任意多个维度,但是
1回复

适用于现代Fortran的Scalapack包装器

我正在寻找一个Fortran库,该库可以使在我的项目中更轻松地使用Scalapack。 似乎在没有任何内容的情况下使用Scalapack非常冗长,我想知道是否有人将其打包到Fortran 2003对象中。 对于C ++或Python,我也见过类似的事情。 这种尝试似乎已经死了一段时间:
1回复

默认情况下访问Fortran自定义类型属性

现代Fortran(90、2003甚至2008)是否有可能具有自定义类型,默认情况下将访问其中一个属性:
1回复

以下Fortran“并发”循环是否有效?

我不认为下面的do concurrent Fortran循环是有效的,因为在每次迭代中都会修改acc 。 但是,gfortran没有给出任何警告,并且acc的结果值正确为55。它是否有效?
1回复

在Fortran 2003中参数化派生类型的问题

我正在自学Fortran 2003,可用于我目前正在从事的研究项目。 我曾经使用过Fortran 90,但是该项目需要使用参数化类型,因此我将继续进行到2003年。 我遵循了该网站关于如何定义参数化类型的描述,并根据该网站的示例编写了一个非常简单的示例程序来对其进行测试: 当我用
1回复

编写时出现“ Fortran运行时错误:文件结尾”

我编写了一段代码,尝试在Arch Linux上使用GNU Fortran(GCC)7.2.1 20171128进行编译,该代码试图写入文件。 该单元以newunit=...打开newunit=... 2008功能 尝试写入文件时,代码崩溃,从而引发错误Fortran runtime er
1回复

在Fortran 2003中键入绑定过程重载

我已经用Java编程了几年; 但是,我现在正在学习一门使用Fortran作为示例代码(77标准)的课程。 虽然我一直认为Fortran是一种古老的语言,但我决定使用gfortran编译器试用2003标准的最新实现来看看它的优点。 到目前为止,我对现代功能感到惊讶,但我遇到了一个问题,下面的
2回复

Fortran派生类型赋值

假设我有一个Fortran派生类型 我有两个这种类型的实例 当我做以下任务时到底发生了什么? 我对此感兴趣因为我想正确地创建派生类型变量的副本意味着,标量组件应该相等,数组组件的每个元素应该相等,并且可分配的数组应该具有相同的分配大小,并且元素应该相等。 目前我只想写一
1回复

Fortran语言; 遍历具有共同属性的文件名

我是Fortran的新手,我的文件名有问题,我在simuln#.res(其中1 <#<20)中有一堆数据,我有多个具有相同simuln#.res的不同目录名称,但它们具有不同的输入参数。 代码如下: 该代码在我的Mac上使用gfortran编译器进行编译,但是当我将路径放入