在Fortran中获取文件分隔符

5

你能告诉我如何在Fortran运行时获取当前操作系统的文件分隔符,例如Windows中的 \ 和Unix中的 / 吗?


当前操作系统的路径分隔符是什么?那是什么意思? - Rook
编辑当前的操作系统 - 程序运行的操作系统 - Sergey Kucher
4个回答

5
据我所知,Fortran标准没有关于文件系统路径分隔符的规定。我能提供的最好建议是定义一个宏来定义适当的分隔符。例如:
#if __unix__
character(len=1), parameter :: path_sep='/'
#elif _WIN32
character(len=1), parameter :: path_sep='\'
#else
#error "path_sep not defined. Set this constant for your system."
#endif

然而,在Windows上,您可以使用/\作为路径分隔符(试试吧!),因此在大多数系统上,不需要对路径分隔符进行任何特殊处理。
请注意,您无需在运行时确定路径分隔符。由于您必须为要在其上运行代码的每个新系统重新编译Fortran源代码,因此您只需要确保在编译时为每个新系统指定正确的路径分隔符(路径分隔符不会在同一系统上运行程序的多次运行之间更改)。
使用像上面那样的预处理器宏是做到这一点的明显方法:您只需为要移植代码的每个新系统添加一个新的#elif子句。这比引入检查特定环境变量的零散解决方案要容易得多,就像其他答案建议的那样。
此外,除了指定路径分隔符之外,您还可能需要设置其他操作系统环境的参数。例如,当前和父目录字符(在Windows和POSIX系统下分别为...)。
最后,请注意,预处理器定义__unix___WIN32是广泛使用的宏,它们指示您所在的系统,并且应该由大多数编译器设置其中之一,具体取决于您所在的系统。如果它们没有设置,您通常可以在编译源代码时使用标志-D__unix__=1-D_WIN32=1来设置其中一个宏。要使用-cpp(gfortran)或-fpp(ifort)命令行选项预处理您的代码,或将源文件扩展名从.f更改为.F或从.f90更改为.F90

我没有成功。我遇到了一个错误,说这是非法的预处理器指令。我正在使用gfortran编译器。 - Sergey Kucher
你需要对文件进行预处理。可以将文件扩展名从“.f”更改为“.F”,或者从“.f90”更改为“.F90”。另外,如果你正在使用英特尔编译器,可以在使用这些预处理器编译文件时使用“-fpp”标志。 - Chris
@Sergey 抱歉,刚刚注意到你说你正在使用gfortran。要调用预处理器,请使用-cpp标志。 - Chris

5
您可以使用Fortran 2003标准内置过程GET_ENVIRONMENT_VARIABLE来实现类似的操作。例如:
CHARACTER(LEN=99999) :: path
CHARACTER(LEN=1)     :: path_separator
CALL GET_ENVIRONMENT_VARIABLE('PATH',path)
path_separator=path(1:1)
WRITE(*,*)'Path separator is ',path_separator
END

这个程序将在UNIX或Linux中输出“/”作为路径分隔符。您也可以从其他环境变量中获取这个值。请注意,此示例是为UNIX/Linux硬编码的。如果需要提取Windows中的“\”,则需要稍微不同的逻辑,但我不熟悉这个系统。我模糊地记得Win95有类似“c:\ .....”的东西,因此在Windows的情况下,您可能会在path(3:3)中查找“\”。

希望这能帮到您。


1
你需要从PATH环境变量中读取99999个字符才能提取第一个字符吗? - Chris
@Chris +1。当我不得不假设长度时(例如,我不知道在Windows中它看起来像什么),我会选择任意长。我相信长度为99就足够了。 - milancurcic
@Chris 注意,99999个字符实际上不会被读取。程序将读取路径的长度。其余部分将只是空闲在内存中。 - milancurcic
根据Fortran标准和Fortran Wiki,在get_environment_variable中,它似乎会读取与path(上面的变量)长度相同的字符,并且很乐意将环境变量截断为path的长度。因此,至少在Unix系统上,您可以使用call get_environment_variable('PATH', path_separator)来获取/ - Chris
当然,我不应该花太多时间担心一个相当长的字符数组的长度! - Chris
1
@Chris 是的,我同意。读取路径并将其转换为长字符字符串的原因是因为我不确定在 Windows 中反斜杠 '' 是否会出现在第3或103位置或其他任何位置。因此,为了安全起见,我更喜欢确保读取整个内容,并提取所需的子字符串。感谢您的评论。 - milancurcic

1
根据IRO-bot的建议,您可以创建一个新的环境变量,例如:
export DELIMITER='/'

在Unix中

现在只需使用'\'在Windows中创建相应的变量,就可以开始了。

如果您不想在Windows中设置全局变量,或者没有权限这样做,请将以下内容放入.bat文件中:

set DELIMITER=\

有关 set 的更多信息,请参见 http://www.ss64.com/nt/set.html 在使用 set 时,您可能需要从 CMD 运行 fortran 程序。

最后将以下内容放入您的 fortran 文件中

CHARACTER :: delimiter
CALL get_environment_variable('DELIMITER',delimiter)

0
我更倾向于上述第4种解决方案,但需要进行一项修改:
function delimiter_detect() result(delim)
  character(LEN=1) :: delim
  character(LEN=258) :: path
  integer :: ii, stat_out
  call GET_ENVIRONMENT_VARIABLE('HOME',path,status=stat_out)
  if (stat_out/=0) go to 999
  ! xxx path='xx\' ! alternate test
  do ii=1, 258
     delim=path(ii:ii)
     if (delim=='/'.or.delim=='\') return
     ! ... Note: emacs does not recognize the second delimiter test
  enddo
999 continue
write(*,'(1x,a/1x,a/1x,a)') 'Could not obtain home directory path.', &
     'Restart program and manually insert path', &
     'to folder/directory containing input files.'
stop
end function delimiter_detect

话虽如此,我还没有在Windows操作系统上测试过这个概念。


1
请问您能解释一下这个修改是什么吗?不确定您指的是哪个答案。 - francescalus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接