This commit is contained in:
2025-09-25 16:33:13 +08:00
commit 88fdb762e0
15 changed files with 7983 additions and 0 deletions

298
第12章习题.f90 Normal file
View File

@ -0,0 +1,298 @@
! ==============================================================================
! 通过 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