爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 6321|回复: 7

[经验总结] Fortran字符串的故事

[复制链接]

新浪微博达人勋

发表于 2016-3-2 17:46:20 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
本帖最后由 woyaofeixiang 于 2016-3-3 11:00 编辑

转载自http://fcode.cn/guide-48-1.html

一. Fortran 字符串与 C 字符串的区别

Fortran的字符串处理能力其实很弱,关于字符串的语法还很落后。它与 C 字符串最大的区别就是:Fortran字符串是固定长度的,没有 \0 结束符。另外,Fortran 也不区分字符和字符串。即 'abc' 与 "abc" 是没有差别的。

二. Fortran 字符串的定义

Fortran字符串是固定长度的。因此,在声明时,就必须指定长度。(如不指定,大多数编译器认为是长度为 1 的字符串)


声明时,可以按照这些格式进行:
  1. integer , parameter :: L = 20
  2. character :: s1*20 = "fcode.cn"
  3. character*20 :: s2 = "fcode.cn"
  4. character(20) :: s3 = "fcode.cn"
  5. character( len = 20 ) :: s4 = "fcode.cn"
  6. character( len = L ) :: s5 = "fcode.cn"
复制代码

不建议使用第2行和第3行的方式。第4行的方式还算凑合。建议最好是使用第5行的方式,第6行演示了长度可以使用 parameter 常数,这样适合于需要大量定义相同长度的字符串。

三. Fortran字符串的长度问题

需要注意的是,字符串的长度一旦确定了,就无法改变

例如上例:

  1. character( Len = 20 ) :: s4 = "fcode.cn"
复制代码

尽管后面的值 "fcode.cn" 只有 8 个字符,但是定义了变量是 20 长度,所以,实际 s4 的内容为 "fcode.cn            "(后面有12个空格)

如果我们要输出或使用字符串,往往需要去掉后面的空格,此时可使用 trim 函数。

  1. write(*,*) trim(s4)
复制代码
这样,就只会输出有内容的 8 个字符,后面的 12 个空格就不会输出。

特别需要注意的是,s4 = trim(s4) 这样的句子是没有任何意义的。因为虽然这个式子的右侧,trim(s4) 的结果是 8 个字符,但赋值给式子左侧的字符串,它依然是 20 长度。它等效于 s4 = "fcode.cn",所以 s4 的内容依然是 “fcode.cn            ”

这让我们很犯难。因此,trim 语句必须出现在每一次使用这个字符串的时候

四. Fortran 字符串的连接(append)


我们经常会挂靠字符串,比如 "fcode.cn" 在后面挂靠一个 "/bbs",很多初学者就会使用这样的代码:
  1. character( Len = 20 ) :: s4 = "fcode.cn"
  2. s4 = s4 // "/bbs"
复制代码


输出以后,发现 s4 的内容依然没有改变。并没有变成期望中的 "fcode.cn/bbs"。究其原因,其实就是第三个问题导致的。我们来观察上面的等式:s4 = s4 // "/bbs",
等号左边 s4 有 20 长度等号右边 s4 的 20 长度加上 "/bbs" 的 4 长度,一共 24 个长度。左边20个长度根本容纳不下右边的24个长度,于是,s4 依然是 s4,后面挂靠的 "/bbs" 由于存储不下而被丢弃。

正确的挂靠方式是:

  1. s4 = trim(s4) // "/bbs"
复制代码

而反之,s4 = "http://" // s4 就不需要写 trim。

五. 字符串的左右对齐(AdjustL,AdjustR)


我们经常会遇到这样的问题,除了后面的空格外,有时候字符串前面也有空格。例如 s4 = "    FortranCoder  ",单一的 trim 结果会是 "     FortranCoder"。


此时我们就需要 AdjustL 函数,我们可以这样写: trim(AdjustL(s4)) , 或者 AdjustL(trim(s4)) 这两者的顺序无所谓,结果都是一样的。



AdjustR 函数使用的情况非常少,通常不用。它可以把 "  abc  " 变为 "    abc"

六. 字符串与整型,实型的相互转换

Fortran 的字符串与整型实现转换,是个很有意思的事情。它不像其他语言那样,提供一个函数来进行。而使用 read 和 write 读写来实现。


看下面的例子:
  1. Program www_fcode_cn
  2.   Implicit None
  3.   Real :: r
  4.   Integer :: i
  5.   Character( Len = 20 ) :: c
  6.   c = "3.1415926"
  7.   read( c , * ) r !// 将 字符串c 转换为实数 r
  8.   write( * , * ) r + 1.0
  9.   i = int( r - 2.0 ) !// 给 i 一个值
  10.   write( c , '(i0)' ) i !// 把整型i 转换为字符串 c
  11.   c = AdjustL(trim(c)) // "st"
  12.   write( * , * ) Trim( c )
  13. End Program www_fcode_cn
复制代码

这里的第 7 行,看起来是一个 read 语句,它其实是转换。意思是:从字符串 c 中读取 r 的值。读者可以把此时的字符串 c 想成是一个虚拟的文件。

这里的第 10 行,看起来是一个 write 语句,其实它还是转换。意思是:把 i 的值,写入字符串 c 中,读者依然可以想象成 c 是一个虚拟的文件。


简单的说,就是
read 和 write 语句,可以直接对字符串进行操作字符串可以被认为是虚拟的文件,从字符串中获得数值,就是read;把值写入到字符串中,就是write。

七. 一个实例

这里,我们列举一个实际字符串使用的例子。


假设现在有一个文件,其内容如下:

// This is a sample file
// There may be some comment text
Time:13:23:42 RecordID:18 Weather:Sunny
Fcode.cn Date:2014-02-38


前两行是注释,而且有可能不是两行,不确定有多少行。


然后是一些数据组合在一起。我们需要找到 RecordID: 后面的数字,即,18。我们事先不能确定 RecordID 在第几行的什么位置里。

找到之后,我们需要给它加上 2014,即,2014+18=2032。


最后我们打开 File2031.dat 文件,开始读取其中的数据。


上面的一系列操作,如果不使用字符串,恐怕会很难。下面我们来看看如何书写代码来完成。利用本文所提到的各种内容。

  1. Program www_fcode_cn
  2.   Implicit None
  3.   Integer , parameter :: MAX_PATH = 512
  4.   Character( Len = MAX_PATH ) :: c
  5.   Character( Len = * ) , parameter :: STR_FIND = "RecordID:"
  6.   integer :: ID , i , iErr
  7.   Open( 12 , File = "fcode.txt" )
  8.   Do
  9.     Read( 12 , '(a512)' , ioStat = iErr ) c !必须a512格式,否则遇到空格会终止
  10.     if ( iErr /= 0 ) Exit !// 如果读错了,比如遇到文件结束,则退出循环
  11.     if ( c(1:2) == "//" ) cycle !// 如果读取的是注释行,则直接读下一行
  12.     i = index( c , STR_FIND ) !// 在 c 中搜索 RecordID: 的位置
  13.     if ( i > 0 ) then !// 如果找到
  14.       i = i + Len(STR_FIND) !// 将位置移到RecordID:后面
  15.       c = c(i:) !// 使得 c 的内容为 i 位置之后的内容,即放弃i位置之前的内容
  16.       read( c , * ) ID !// 读取 ID 编号
  17.       write( c , * ) ID + 2014 !// ID 编号加上2014,再写回c中
  18.       c = "File" // Trim(AdjustL(c)) // ".dat" !组合成File2032.dat,注意trim
  19.       write( * , * ) Trim( c ) !// 输出看看对不对
  20.       !// Open( 13 , File = Trim( c ) )
  21.       Exit
  22.     end if
  23.   End Do
  24.   Close( 12 )
  25. End Program www_fcode_cn
复制代码



密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2016-3-2 18:35:06 | 显示全部楼层
学长这个很6,可见对Fortran的研究至深,能否讲下讲解下关于二进制文件的有关类容以及生成二进制的原理?非常感谢
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2016-3-2 18:35:10 | 显示全部楼层
学长这个很6,可见对Fortran的研究至深,能否讲下讲解下关于二进制文件的有关类容以及生成二进制的原理?非常感谢
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 19710
发表于 2016-3-3 00:05:08 | 显示全部楼层
这个是转载http://fcode.cn/guide-48-1.html上的吧,如果楼主是本文的原创作者请注明,如果不是,请注明出处~谢谢合作~
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2016-3-3 07:58:50 | 显示全部楼层
楼主厉害!不知fortran可不可以读nc或者grib格式的数据呢?
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2016-3-3 08:41:39 | 显示全部楼层
{:eb502:}Fortran博大精深
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2016-3-3 08:42:34 | 显示全部楼层
很好,学习了
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2019-9-18 12:29:05 | 显示全部楼层
求教一下,字符串数组如何赋值,我的字符串数组是站名,程序运行时出现以下提示:invalid character kind parameter.no underscore
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表