! ============================================================================== ! 通过 gfortran ./test.f90 -o ./run && ./run 运行 ! 程序名: ! 第12章习题 ! 目的: ! ! 修订记录: ! 日期 编程者 改动描述 ! =================== ============= ===================================== ! 2021-05-16 16:04:01 Sola 习题12-1 改进例题程序 ! 2021-05-16 20:45:49 Sola 习题12-2 复数坐标系转换 ! 2021-05-16 20:46:28 Sola 习题12-3 复数极坐标乘法 ! 2021-05-16 20:46:40 Sola 习题12-4 复数极坐标除法 ! 2021-05-16 20:56:15 Sola 习题12-5 建立过了,跳过 ! 2021-05-16 20:59:10 Sola 习题12-6 卡笛尔坐标系下点位和直线 ! 2021-05-16 21:04:08 Sola 习题12-7 两点间距离 ! 2021-05-16 21:14:41 Sola 习题12-8 通过两点计算直线参数 ! 2021-05-16 21:36:52 Sola 习题12-9 追踪雷达目标,莫得数据,跳过 ! 程序结构: ! ! ============================================================================== ! 模块: module Chapter12 implicit none ! 数据字典 ! 声明常数 REAL, PARAMETER :: PI=3.14159265 ! PI值 REAL, PARAMETER :: e=2.718281828459 ! 自然对数 INTEGER, PARAMETER :: arrayLength=20 ! 数组基准长度 integer, parameter :: sgl = selected_real_kind(p=1) ! 单精度类型 type :: complexChange real(sgl) :: var1 ! 参数1 real(sgl) :: var2 ! 参数2 contains procedure, pass :: Car2Pol ! 直角坐标系转化为极坐标系 procedure, pass :: Pol2Car ! 极坐标系转化为直角坐标系 procedure, pass :: PolProduct ! 极坐标系乘法 procedure, pass :: PolDivision ! 极坐标系乘法 end type complexChange type :: point ! 点位的派生数据 real(sgl) :: x ! X坐标 real(sgl) :: y ! Y坐标 contains procedure, pass :: Distance ! 两点间距离 procedure, pass :: Point2line ! 计算两点间直线方程 end type point type :: line ! 直线的派生数据 real(sgl) :: m ! 斜率 real(sgl) :: b ! 截距 end type line type :: radarInfo real(sgl) :: length ! 距离 real(sgl) :: theta ! 角度 real(sgl) :: time ! 扫描时间 end type radarInfo ! 声明变量 ! 创建显式接口 contains ! subroutine SubName(varName1,varName2) ! implicit none ! ! 数据字典 ! end subroutine SubName ! 直角坐标系转化为极坐标系 type(complexChange) function Car2Pol(this) class(complexChange) :: this Car2Pol%var1 = sqrt(this%var1**2 + this%var2**2) Car2Pol%var2 = atan(this%var2, this%var1) end function Car2Pol ! 极坐标系转化为直角坐标系 type(complexChange) function Pol2Car(this) class(complexChange) :: this Pol2Car%var1 = this%var1*cos(this%var2) Pol2Car%var2 = this%var1*sin(this%var2) end function Pol2Car ! 复数的极坐标系乘法 type(complexChange) function PolProduct(this, input) class(complexChange) :: this, input PolProduct%var1 = this%var1*input%var1 PolProduct%var2 = mod(this%var2 + input%var2 + PI, 2*PI) - PI end function PolProduct ! 复数的极坐标除法 type(complexChange) function PolDivision(this, input) class(complexChange) :: this, input PolDivision%var1 = this%var1/input%var1 PolDivision%var2 = mod(this%var2 - input%var2 + PI, 2*PI) - PI end function PolDivision ! 计算两点间距离 real function Distance(pointA, pointB) class(point) :: pointA, pointB Distance = sqrt((pointB%x - pointA%x)**2 + (pointB%y - pointA%y)**2) end function Distance type(line) function Point2line(pointA, pointB) class(point) :: pointA, pointB if ( abs(pointA%x - pointB%x) < 1E-30 ) then stop "所求直线无斜率(与Y轴平行)" end if Point2line%m = (pointA%y - pointB%y)/(pointA%x - pointB%x) Point2line%b = pointA%y - Point2line%m*pointA%x end function Point2line end module Chapter12 ! ============================================================================== ! 主程序: program ProName implicit none ! 数据字典 ! 声明常量 ! 声明变量 ! 变量初始化 ! 数据输入 ! 运算过程 ! 结果输出 ! call customer_database ! call Exercises12_2 ! call Exercises12_7 end program ProName ! ============================================================================== ! 子程序 ! subroutine SubName(varName1,varName2) ! use MouName ! implicit none ! Type, intent(inout) :: varName ! end subroutine SubName ! ============================================================================== ! 函数 ! function FunName(varName1,varName2) ! use MouName ! implicit none ! end function FunName ! ============================================================================== ! 习题12-1 修改例题 ! 定义了公共模块用来读取数据 module types implicit none type :: presonal_info character(len=12) :: first character :: mi character(len=12) :: last character(len=26) :: street character(len=12) :: city character(len=2) :: state integer :: zip end type presonal_info end module types ! 输入数据以及排序的主函数 subroutine customer_database use types implicit none integer, parameter :: MAX_SIZE = 100 logical, external :: lt_last logical, external :: lt_city logical, external :: lt_zip type(presonal_info), dimension(MAX_SIZE) :: customers integer :: choice logical :: exceed = .FALSE. character(len=20) :: filename integer :: i integer :: nvals = 0 integer :: status type(presonal_info) :: temp open(unit=1, status='scratch', iostat=status) if ( status /= 0 ) stop "" write(1, '(A)') & &"John Q Public 123 Sesame Street Anywhere NY 10035", & &"James R Johnson Rt. 5 Box 207C West Monroe LA 71291", & &"Joseph P Ziskend P. O. Box 433 APO AP 96555", & &"Andrew D Jackson Jackson Square New Orleans LA 70003", & &"Jane X Doe 12 Lakeside Drive Glenview IL 60025", & &"Colin A Jeffries 11 Main Street Chicago IL 60003" rewind(unit=1, iostat=status) if ( status /= 0 ) stop "" do read(1, 1010, iostat=status) temp 1010 format(A12, 1X, A1, 1X, A12, 1X, A26, 1X, A12, 1X, A2, 1X, I5) if ( status /= 0 ) exit nvals = nvals + 1 if ( nvals <= MAX_SIZE ) then customers(nvals) = temp else exceed = .TRUE. end if end do if ( exceed ) then write(*, 1020) nvals, MAX_SIZE 1020 format(' Maximum array size exceeded: ', I6, ' > ', I6) else write(*, 1030) 1030 format(& 1X, 'Enter way to sort database:', /& 1X, ' 1 -- By last name ', /& 1X, ' 2 -- By city ', /& 1X, ' 3 -- By zip code ') read(*, *) choice select case (choice) case(1) call sort_database(customers, nvals, lt_last) case(2) call sort_database(customers, nvals, lt_city) case(3) call sort_database(customers, nvals, lt_zip) case default write(*, *) 'Invalid choice entered!' end select write(*, '(A)') 'The sorted database values are: ' write(*, 1040) (customers(i), i = 1, nvals) 1040 format(A12, 1X, A1, 1X, A12, 1X, A26, 1X, A12, 1X, A2, 1X, I5) end if end subroutine customer_database ! 排序对应数据子程序 subroutine sort_database(array, n, lt_fun) use types implicit none integer, intent(in) :: n type(presonal_info), dimension(n), intent(inout) :: array logical, external :: lt_fun integer :: i integer :: iptr integer :: j type(presonal_info) :: temp do i = 1, n-1 iptr = i do j = i+1, n if ( lt_fun(array(j),array(iptr)) ) then iptr = j end if end do if ( i /= iptr ) then temp = array(i) array(i) = array(iptr) array(iptr) = temp end if end do end subroutine sort_database ! 排序函数 logical function lt_last(a, b) use types implicit none type(presonal_info), intent(in) :: a, b lt_last = LLT(a%last, b%last) end function lt_last ! 主要在这里修改,全部检测大写即可,如果需要继续改进的话,名称可能也要改?倒是也没必要,名字只有首字母大写 logical function lt_city(a, b) use types implicit none type(presonal_info), intent(in) :: a, b lt_city = LLT(Ucase(a%city), Ucase(b%city)) contains function Ucase(str) character(len=*), intent(in) :: str ! 定义输入字符串 character(len=len(str)) :: ucase ! 定义函数类型 integer :: i ! 循环参数 do i = 1, len(str) ! 对输入每个字符循环 if ( lge(str(i: i), 'a') .and. lle(str(i: i), 'z') ) then ! 如果字符在a~z中 Ucase(i: i) = achar( iachar(str(i: i)) - 32 ) ! 输出大写 else Ucase(i: i) = str(i: i) ! 如果不在, 输出原字符 end if end do end function Ucase end function lt_city logical function lt_zip(a, b) use types implicit none type(presonal_info), intent(in) :: a, b lt_zip = a%zip < b%zip end function lt_zip ! 习题12-2 具体函数参考派生数据在模块中的定义 ! 习题12-3 极坐标表示复数乘法 ! 习题12-4 极坐标表示复数出发 subroutine Exercises12_2 use Chapter12 implicit none type(complexChange) :: POLAR, a, b ! 习题12-2 POLAR = complexChange(123., 456.) write(*, *) 'POLAR为: ', POLAR write(*, *) 'POLAR转化为极坐标系为: ', POLAR%Car2Pol() write(*, *) 'POLAR转化为直角坐标系为: ', POLAR%Pol2Car() ! 习题12-3 POLAR = POLAR%Car2Pol() a = POLAR b = POLAR%PolProduct(a) write(*, *) 'POLAR之间的乘积为: ', b ! 习题12-4 b = b%PolDivision(a) write(*, *) '其乘积除以POLAR为: ', b contains end subroutine Exercises12_2 ! 习题12-7 两点间距离,两点间建立直线 subroutine Exercises12_7 use Chapter12 implicit none type(point) :: pointA, pointB pointA = point(1., 3.) pointB = point(3., 1.) write(*, *) '点A与点B之间的距离为: ', pointA%Distance(pointB) write(*, *) '点A与点B之间的直线的斜率和截距为: ', pointA%Point2line(pointB) contains end subroutine Exercises12_7