本帖最后由 weixing1531 于 2024-5-13 18:18 编辑
学习Fortran已有近20年,收集了一些编程技巧。
(1)修改老程序goto语句
先构造一个只执行一次的命名循环,再使用exit退出命名循环从而避免使用goto语句
老程序
[Fortran] 纯文本查看 复制代码 if(...)then
语句A
goto 99
end if
if(...)then
语句B
goto 99
end if
语句C
99 语句D
等价于新程序
[Fortran] 纯文本查看 复制代码 out:do i=1,1
if(...)then
语句A
exit out
end if
if(...)then
语句B
exit out
end if
语句C
end do out
语句D
(2)整数转换为字符串
[Fortran] 纯文本查看 复制代码 !整数转换为字符串
pure function int2str(i) result(f_string) !摘自fpm源代码
integer,intent(in)::i !i为要转换的整数
character(len=str_int_len(i))::f_string !自动字符串 调用已有函数str_int_len 7.3Automatic objects《Mordern Fortran Explained 2018》P120
write(f_string,"(i0)")i !f_string长度必须明确
end function int2str
!> Returns the length of the string representation of 'i'
pure integer function str_int_len(i) result(sz) !摘自fpm源代码
integer, intent(in) :: i
integer, parameter :: MAX_STR = 255 !字符串最大长度
character(MAX_STR) :: s
! If 's' is too short (MAX_STR too small), Fortran will abort with:
! "Fortran runtime error: End of record"
write(s, '(i0)') i !左对齐 F202X标准才支持s为递延字符串
sz = len_trim(s) !删除尾部空格后的字符串长度
end function str_int_len
(3)浮点数转换为字符串[Fortran] 纯文本查看 复制代码 pure function real2str(MXS,ld) result(res) !浮点数转换为字符串 调用str_int_len、int2str函数
real(real64),intent(in)::MXS !浮点数
integer,intent(in)::ld !小数保留位数
character(len=:),allocatable::res,ft !递延长度字符串
character(len=255)::str
select case(ld)
case(0) !浮点数四舍五入取整
res=int2str(nint(MXS)) !不需要ft
case(1:4) !小数保留1-4位
ft="(f"//int2str(str_int_len(int(MSX))+ld+1)//"."//int2str(ld)//")" !"(fX.Y)" 浮点数格式 Y为小数点保留位数 X为总字符串长度(整数部分+小数点+小数部分)
write(str,ft)MXS !浮点数转换为字符串 左对齐 只能用str而不能用res F202X标准才支持str为递延字符串
res=trim(str) !删除尾部空格
deallocate(ft) !释放递延字符串内存 不能放在函数尾部 否则浮点数四舍五入取整无法计算
case default
error stop "小数保留位数超出范围!"
end select
end function real2str
(4)C字符串指针转换Fortran字符串
[Fortran] 纯文本查看 复制代码 FUNCTION C_to_F_string(c_string_pointer) RESULT(f_string) !C字符串指针转换Fortran字符串
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_F_POINTER, C_CHAR, C_NULL_CHAR
type(C_PTR), INTENT(IN) :: c_string_pointer !C字符串指针
CHARACTER(LEN=:), ALLOCATABLE :: f_string !延迟长度字符串
CHARACTER(KIND=C_CHAR), DIMENSION(:), POINTER :: char_array_pointer => NULL() !Fortran字符数组指针
CHARACTER(LEN=255) :: aux_string
INTEGER :: i, length=0
CALL C_F_POINTER(c_string_pointer, char_array_pointer, [255]) !C字符串指针转换为Fortran字符数组指针
IF (.NOT.ASSOCIATED(char_array_pointer)) THEN !char_array_pointer为空指针
ALLOCATE(CHARACTER(LEN=4)::f_string)
f_string="NULL"
return
END IF
aux_string=" "
DO i=1,255
IF (char_array_pointer(i)==c_null_char) THEN !达到字符串尾部
length=i-1
EXIT
END IF
aux_string(i:i)=char_array_pointer(i) !逐个元素复制字符
END DO
ALLOCATE(CHARACTER(LEN=length)::f_string)
f_string=aux_string(1:length)
END FUNCTION C_to_F_string
(5)读写Excel数据
方法一:商业库Libxl提供了Fortran函数接口,序列号需要破解
https://www.libxl.com/
方法二:先读写csv文件,然后手动另存为xls格式
Github网上有现成的csv模块,作者:Jacob Williams
(6)日期与时间操作
Github网上有现成的datetime模块
https://github.com/wavebitscientific/datetime-fortran
(7)常用数值计算算法原代码
Numerical Recipe、宋叶志、何光渝、徐士良
(8)生成随着时间与日期变动的动态密码
[Fortran] 纯文本查看 复制代码 impure function GetPassword(PasswordLen,IsDay) !获得动态密码及长度
integer,intent(out)::PasswordLen
logical,intent(in),optional::IsDay !动态密码是否日变化
character(len=:),allocatable::GetPassword !递延长度字符串
character(8) :: date,temp !CCYYMMDD
character(10) :: time !HHMMSS.SSS
call date_and_time(date,time) !返回当前日期与时间
temp=date(3:8)//time(1:2) !界面进入原始密码 为与时间有关的动态密码YYMMDDHH 两位年月日时
if(present(IsDay))then
if(IsDay)temp=date(1:8) !界面进入密码 为与日期有关的动态密码CCYYMMDD 四位年月日
end if
GetPassword="Wx"
GetPassword=GetPassword//temp(2:8)//temp(1:1) !加工后密码
PasswordLen=len(GetPassword) !输出密码字符串长度
end function
(9)判断整数变量b的值是否与一维整数数组a的任意元素相等
方法一:
[Fortran] 纯文本查看 复制代码 Any(a(:)==b) !T相等F不相等
方法二:
[Fortran] 纯文本查看 复制代码 FindLoc(a(:),b)==[0] !F相等T不相等 (10)如何判断两个字符串完全相等
[Fortran] 纯文本查看 复制代码 character(:),allocatable::a,b
a="A"
b="A " !A后面加一个空格
write(*,*)a==b !你以为打印F 其实打印T
write(*,*)(a==b .AND. (len(a)==len(b))) !打印F
(11)如何在主程序中修改模块protected属性变量?将该变量修改包裹在模块方法之中,然后在主程序调用模块方法
(12)常用参考网站
https://fortranwiki.org/fortran/show/HomePage
https://fortran-lang.org/
https://jblevins.org/mirror/amiller/
|