update file date
This commit is contained in:
641
20210510-第10章习题.f90
Normal file
641
20210510-第10章习题.f90
Normal file
@ -0,0 +1,641 @@
|
||||
! ==============================================================================
|
||||
! 通过 gfortran ./test.f90 -o ./run && ./run 运行
|
||||
! 程序名:
|
||||
! 第10章习题,及书上例题
|
||||
! 目的:
|
||||
!
|
||||
! 修订记录:
|
||||
! 日期 编程者 改动描述
|
||||
! =================== ============= =====================================
|
||||
! 2021-05-10 17:15:53 Sola 测验10-1 4 判断星期几
|
||||
! 2021-05-10 17:22:01 Sola 测验10-1 5 字符串反序
|
||||
! 2021-05-10 17:33:13 Sola 测验10-1 6-8 测试字符
|
||||
! 2021-05-10 18:14:05 Sola 例题10-3 转换输出数值格式
|
||||
! 2021-05-10 21:58:38 Sola 测验10-2 3
|
||||
! 2021-05-11 14:30:07 Sola 习题10-4 字符串转大写
|
||||
! 2021-05-11 15:00:14 Sola 习题10-5 字符串转小写
|
||||
! 2021-05-11 16:03:39 Sola 习题10-8 首字母大写
|
||||
! 2021-05-11 17:39:18 Sola 习题10-9 10-8可变函数版(话说直接写的就是可变函数版本的...)
|
||||
! 2021-05-11 17:39:48 Sola 习题10-10 检测字符中实际字符数
|
||||
! 2021-05-11 18:16:41 Sola 习题10-11 检测第一个和最后一个非空字符位置(话说上一题的函数改一改不就是了)
|
||||
! 2021-05-11 19:10:54 Sola 习题10-12 输入参数文件
|
||||
! 2021-05-11 21:51:02 Sola 习题10-13 直方图 ??? 这是什么鬼需求
|
||||
! 2021-05-12 11:28:44 Sola 习题10-14 随机数直方图
|
||||
! 2021-05-12 13:18:26 Sola 习题10-15 拷贝文件去除注释
|
||||
! 程序结构:
|
||||
!
|
||||
! ==============================================================================
|
||||
! 模块:
|
||||
module Chapter10
|
||||
implicit none
|
||||
! 数据字典
|
||||
! 声明常数
|
||||
REAL, PARAMETER :: PI=3.14159265 ! PI值
|
||||
REAL, PARAMETER :: e=2.718281828459 ! 自然对数
|
||||
INTEGER, PARAMETER :: arrayLength=20 ! 数组基准长度
|
||||
! 声明变量
|
||||
! 创建显式接口
|
||||
contains
|
||||
end module Chapter10
|
||||
! ==============================================================================
|
||||
! 主程序:
|
||||
program ProName
|
||||
! use ModName
|
||||
implicit none
|
||||
! 数据字典
|
||||
! 声明常量
|
||||
! 声明变量
|
||||
! 变量初始化
|
||||
! 数据输入
|
||||
! 运算过程
|
||||
! 结果输出
|
||||
! call Exercises10_1_4
|
||||
! call Exercises10_1_5
|
||||
! call Exercises10_1_6_8
|
||||
! call Example10_3
|
||||
! call Exercises10_2_3
|
||||
! call Exercises10_4
|
||||
! call Exercises10_10
|
||||
! call Exercises10_12
|
||||
! call Exercises10_13
|
||||
! call Exercises10_14
|
||||
call Exercises10_15
|
||||
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
|
||||
! ==============================================================================
|
||||
! 测试10-1 4 判断星期几
|
||||
subroutine Exercises10_1_4
|
||||
implicit none
|
||||
integer :: i
|
||||
write(*,*) (day(i), i = 7, 1, -1)
|
||||
contains
|
||||
function day(iday)
|
||||
integer, intent(in) :: iday
|
||||
character(len=3) :: day
|
||||
character(len=3), dimension(7) :: days=(/'SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'/)
|
||||
if ( (iday>=1) .and. (iday<=7) ) then
|
||||
day = days(iday)
|
||||
end if
|
||||
end function day
|
||||
end subroutine Exercises10_1_4
|
||||
! 测试10-1 5 字符串反序
|
||||
subroutine Exercises10_1_5
|
||||
implicit none
|
||||
write(*,*) swap_string('Hello World!')
|
||||
contains
|
||||
function swap_string(string)
|
||||
character(len=*), intent(in) :: string
|
||||
character(len=len(string)) :: swap_string
|
||||
integer :: length, i
|
||||
length = len(string)
|
||||
do i = 1, length
|
||||
swap_string(length-i+1: length-i+1) = string(i: i)
|
||||
end do
|
||||
end function swap_string
|
||||
end subroutine Exercises10_1_5
|
||||
! 测验10-1 6-8
|
||||
subroutine Exercises10_1_6_8
|
||||
implicit none
|
||||
call sub1
|
||||
call sub2
|
||||
call sub3
|
||||
contains
|
||||
subroutine sub1
|
||||
character(len=20) :: last='JOHNSON'
|
||||
character(len=20) :: first='JAMES'
|
||||
character :: middle_initial='R'
|
||||
character(len=42) :: name
|
||||
write(*,*) middle_initial
|
||||
name = last //', '//first//middle_initial
|
||||
write(*,*) name
|
||||
end subroutine sub1
|
||||
subroutine sub2
|
||||
character(len=4) :: a='123'
|
||||
character(len=12) :: b
|
||||
b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
write(*,*) a, ', ', b
|
||||
b(5: 8) = a(2: 3)
|
||||
write(*,*) a, ', ', b
|
||||
end subroutine sub2
|
||||
subroutine sub3
|
||||
character(len=80) :: line
|
||||
integer :: ipos1, ipos2, ipos3, ipos4
|
||||
line = 'This is a test line containing some input data!'
|
||||
ipos1 = index(line, 'in')
|
||||
ipos2 = index(line, 'Test')
|
||||
ipos3 = index(line, 't l')
|
||||
ipos4 = index(line, 'in', .TRUE.)
|
||||
write(*,*) ipos1, ipos2, ipos3, ipos4
|
||||
end subroutine sub3
|
||||
end subroutine Exercises10_1_6_8
|
||||
! 例题10-3 转换输出数值格式
|
||||
subroutine Example10_3
|
||||
implicit none
|
||||
real :: input
|
||||
character(len=1) :: runLevel
|
||||
outer:do
|
||||
write(*, *) '请输入数值:'
|
||||
read(*, *) input
|
||||
write(*, *) '输出的结果为:', num2str(input)
|
||||
inner:do
|
||||
write(*, *) '是否接着输入下一个数值? 继续(Y)/结束(N)'
|
||||
read(*, *) runLevel
|
||||
if ( runLevel == 'Y' .or. runLevel == 'y' ) then
|
||||
exit inner
|
||||
else if ( runLevel == 'N' .or. runLevel == 'n' ) then
|
||||
exit outer
|
||||
else
|
||||
write(*,*) '非法输入! 请重新输入!'
|
||||
end if
|
||||
end do inner
|
||||
end do outer
|
||||
contains
|
||||
function num2str(num)
|
||||
character(len=12) :: num2str ! 函数输出类型
|
||||
real, intent(in) :: num ! 输入实数
|
||||
if ( abs(num) <= 9999999. .and. abs(num) >= 0.01 .or. num == 0 ) then
|
||||
write(num2str, '(F12.4)') num
|
||||
else
|
||||
write(num2str, '(ES12.5)') num
|
||||
end if
|
||||
end function num2str
|
||||
end subroutine Example10_3
|
||||
! 测验10-2 3
|
||||
subroutine Exercises10_2_3
|
||||
implicit none
|
||||
character(len=30) :: line = '123456789012345678901234567890'
|
||||
character(len=30) :: fmt = '(3X, I6, 12X, I3, F6.2)'
|
||||
integer :: ival1, ival2
|
||||
real :: rval3
|
||||
read (line, fmt) ival1, ival2, rval3
|
||||
write(*,*) ival1, ival2, rval3
|
||||
end subroutine Exercises10_2_3
|
||||
! 习题10-4 字符串转大写
|
||||
subroutine Exercises10_4
|
||||
implicit none
|
||||
character(len=132) :: input
|
||||
character :: runLevel
|
||||
outer:do
|
||||
write(*, *) '请输入一段字符(小于132字,包含空格字符请用引号括起)'
|
||||
read(*, *) input
|
||||
write(*, *) '转换大写结果为:', Ucase(input)
|
||||
write(*, *) '转换小写结果为:', Lcase(input)
|
||||
write(*, *) '首字符大写结果为:', Caps(input)
|
||||
inner:do
|
||||
write(*, *) '是否接着转换下一个字符串? 继续(Y)/结束(N)'
|
||||
read(*, *) runLevel
|
||||
if ( runLevel == 'Y' .or. runLevel == 'y' ) then
|
||||
exit inner
|
||||
else if ( runLevel == 'N' .or. runLevel == 'n' ) then
|
||||
exit outer
|
||||
else
|
||||
write(*,*) '非法输入! 请重新输入!'
|
||||
end if
|
||||
end do inner
|
||||
end do outer
|
||||
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
|
||||
! 转换为小写
|
||||
function Lcase(str)
|
||||
character(len=*), intent(in) :: str ! 定义输入字符串
|
||||
character(len=len(str)) :: Lcase ! 定义函数类型
|
||||
integer :: i ! 循环参数
|
||||
do i = 1, len(str) ! 对每个输入字符循环
|
||||
if ( lge(str(i: i), 'A') .and. lle(str(i: i), 'Z') ) then ! 如果字符在A~Z中
|
||||
Lcase(i: i) = achar( iachar(str(i: i)) + 32 ) ! 输出小写
|
||||
else
|
||||
Lcase(i: i) = str(i: i) ! 如果不再, 输出原字符
|
||||
end if
|
||||
end do
|
||||
end function Lcase
|
||||
! 首字符大写
|
||||
! 情况可能如下:
|
||||
! 1. 小写字母, runLevel .eqv. .TRUE. 转换为大写, runLevel = .FALSE.
|
||||
! 2. 小写字母, runLevel .eqv. .FALSE. 不变
|
||||
! 3. 大写字母, runLevel .eqv. .TRUE. 不变, runLevel = .FALSE.
|
||||
! 4. 大写字母, runLevel .eqv. .FALSE. 转换为小写
|
||||
! 5. 非字符, runLevel = .TRUE.
|
||||
function Caps(str)
|
||||
character(len=*), intent(in) :: str ! 输入字符
|
||||
character(len=len(str)) :: Caps ! 定义函数类型
|
||||
integer :: i ! 循环参数
|
||||
logical :: runLevel ! 运行级别(判断是否为首字母)
|
||||
runLevel = .TRUE. ! 初始化运行级别
|
||||
do i = 1, len(str) ! 遍历每个字符
|
||||
if ( lge(str(i: i), 'a') .and. lle(str(i: i), 'z') .and. ( runLevel .eqv. .TRUE. ) ) then ! 小写字母为首字母
|
||||
Caps(i: i) = achar( iachar(str(i: i)) - 32 ) ! 转换为大写字母
|
||||
runLevel = .FALSE. ! 下一个字符非首字母
|
||||
elseif ( lge(str(i: i), 'a') .and. lle(str(i: i), 'z') .and. ( runLevel .eqv. .FALSE. ) ) then ! 小写字母非首字母
|
||||
Caps(i: i) = str(i: i) ! 不改变字符
|
||||
elseif ( lge(str(i: i), 'A') .and. lle(str(i: i), 'Z') .and. ( runLevel .eqv. .TRUE. ) ) then ! 大写字母为首字母
|
||||
Caps(i: i) = str(i: i) ! 不改变字符
|
||||
runLevel = .FALSE. ! 下一个字符非首字母
|
||||
elseif ( lge(str(i: i), 'A') .and. lle(str(i: i), 'Z') .and. ( runLevel .eqv. .FALSE. ) ) then ! 大写字母非首字母
|
||||
Caps(i: i) = achar( iachar(str(i: i)) + 32 ) ! 转换为小写字母
|
||||
elseif ( lge(str(i: i), '0') .and. lle(str(i: i), '9') ) then ! 如果是数字
|
||||
Caps(i: i) = str(i: i) ! 不改变字符
|
||||
runLevel = .FALSE. ! 下一个字符不是首字母
|
||||
else ! 非字母
|
||||
Caps(i: i) = str(i: i) ! 不改变字符
|
||||
runLevel = .TRUE. ! 下一个字符是首字母(如果是字母)
|
||||
end if
|
||||
end do
|
||||
end function Caps
|
||||
end subroutine Exercises10_4
|
||||
! 习题10-10 检测字符串中实际字符数量
|
||||
subroutine Exercises10_10
|
||||
implicit none
|
||||
character(len=132) :: input
|
||||
character :: runLevel
|
||||
integer :: errorLevel
|
||||
integer :: firstNonBlank, lastNonBlank
|
||||
outer:do
|
||||
write(*, *) '请输入一段字符(小于132字,包含空格字符请用引号括起)'
|
||||
read(*, *) input
|
||||
write(*, *) '该字符的长度为:', LenUsed(input)
|
||||
write(*, *) '该字符的允许长度为:', len(input)
|
||||
write(*, *) '该字符除去尾部空格的长度为:', len_trim(input)
|
||||
call NonBlank(input, firstNonBlank, lastNonBlank, errorLevel)
|
||||
if ( errorLevel /= 0 ) then
|
||||
write(*, *) '错误! 没有输入字符或输入字符为空!'
|
||||
else
|
||||
write(*, *) '第一个非空字符在第', firstNonBlank, '位, 最后一个非空字符在第', lastNonBlank, '位。'
|
||||
end if
|
||||
inner:do
|
||||
write(*, *) '是否接着计算下一个字符串? 继续(Y)/结束(N)'
|
||||
read(*, *) runLevel
|
||||
if ( runLevel == 'Y' .or. runLevel == 'y' ) then
|
||||
exit inner
|
||||
else if ( runLevel == 'N' .or. runLevel == 'n' ) then
|
||||
exit outer
|
||||
else
|
||||
write(*,*) '非法输入! 请重新输入!'
|
||||
end if
|
||||
end do inner
|
||||
end do outer
|
||||
contains
|
||||
! 习题10-10 判断字符串中有多少字符
|
||||
function LenUsed(str)
|
||||
character(len=*), intent(in) :: str ! 输入字符串
|
||||
integer :: LenUsed ! 定义函数返回类型
|
||||
integer :: i ! 循环参数
|
||||
integer :: firstSpace, lastSpace ! 首位空白字符位置
|
||||
firstSpace = 0 ! 初始化变量
|
||||
lastSpace = len(str)
|
||||
do i = 1, lastSpace ! 判断字符串首最后一个空白字符位置
|
||||
if ( str(i:i) == ' ' ) then
|
||||
firstSpace = i
|
||||
else
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
if ( firstSpace /= lastSpace ) then ! 如果不是全部都是空白字符
|
||||
do i = lastSpace, firstSpace+1, -1 ! 判断字符串尾第一个空白字符位置
|
||||
if ( str(i:i) == ' ' ) then
|
||||
lastSpace = i
|
||||
else
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
LenUsed = lastSpace - firstSpace - 1 ! 判断字符串实际使用长度
|
||||
else
|
||||
LenUsed = 0 ! 如果全部都是空白字符, 则长度为0
|
||||
end if
|
||||
end function LenUsed
|
||||
! 习题10-11 判断字符串第一个和最后一个空白字符位置
|
||||
subroutine NonBlank(str, firstNonBlank, lastNonBlank, errorLevel)
|
||||
character(len=*), intent(in) :: str ! 输入字符串
|
||||
integer :: i ! 循环参数
|
||||
integer, intent(out) :: firstNonBlank, lastNonBlank ! 首位空白字符位置
|
||||
integer, intent(out) :: errorLevel
|
||||
firstNonBlank = len(str) ! 初始化变量
|
||||
lastNonBlank = 0
|
||||
do i = firstNonBlank, 1, -1 ! 判断字符串最后一个非空白位置
|
||||
if ( .not. str(i:i) == ' ' ) then
|
||||
lastNonBlank = i
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
if ( lastNonBlank /= 0 ) then ! 如果不是全部都是空白字符
|
||||
do i = 1, lastNonBlank ! 判断字符串第一个空白字符位置
|
||||
if ( .not. str(i:i) == ' ' ) then
|
||||
firstNonBlank = i
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
errorLevel = 0
|
||||
else
|
||||
firstNonBlank = 0 ! 如果全部都是空白字符, 则位置为0
|
||||
errorLevel = 1
|
||||
end if
|
||||
end subroutine NonBlank
|
||||
end subroutine Exercises10_10
|
||||
! 习题10-12 输入参数文件
|
||||
subroutine Exercises10_12
|
||||
implicit none
|
||||
character(len=132) :: str
|
||||
real :: start, stop, dt
|
||||
logical :: plot
|
||||
integer :: errorLevel
|
||||
open(unit=1, status='scratch', iostat=errorLevel) ! 打开文件并输入数据
|
||||
if ( errorLevel /= 0 ) stop "打开临时文件失败"
|
||||
write(1, '(A)') &
|
||||
&"start=0.0",&
|
||||
&"stop=10.0",&
|
||||
&"dt=0.2",&
|
||||
&"plot on",&
|
||||
&" ",&
|
||||
&" "
|
||||
rewind(unit=1, iostat=errorLevel) ! 回到第一行
|
||||
if ( errorLevel /= 0 ) stop "操作临时文件失败"
|
||||
do ! 读取文件知道文件末尾
|
||||
read(1, '(A)', iostat=errorLevel) str ! 将内容赋值给字符串
|
||||
if ( errorLevel /= 0 ) exit ! 判断是否到达文件末尾
|
||||
call InputData(str, start, stop, dt, plot) ! 读取值
|
||||
end do
|
||||
write(*, *) start, stop, dt, plot ! 显示当前读取到的值
|
||||
close(unit=1, iostat=errorLevel) ! 关闭临时文件
|
||||
if ( errorLevel /= 0 ) stop "关闭临时文件失败" ! 检测关闭状态
|
||||
contains
|
||||
subroutine InputData(str, start, stop, dt, plot) ! 读取值子程序
|
||||
character(len=*), intent(inout) :: str ! 输入的字符串
|
||||
real, intent(out) :: start, stop, dt ! 输出数值
|
||||
integer :: tempLoc ! 临时保存位置的变量
|
||||
integer :: equLoc, length ! 等号位置及字符串长度
|
||||
logical :: plot ! 输出逻辑值
|
||||
equLoc = index(str, '=') ! 得到等号位置
|
||||
length = len(str) ! 得到字符串长度
|
||||
if ( equLoc == 0 ) then ! 如果没有等号
|
||||
tempLoc = index( Ucase(str), 'PLOT') ! 检测全大写字符串中是否有PLOT字符
|
||||
if ( tempLoc /= 0 ) then ! 如果有
|
||||
if ( index(Ucase(str(1: length)), 'ON') /= 0 ) then ! 判断PLOT状态并赋值
|
||||
plot = .TRUE.
|
||||
elseif ( index(Ucase(str(1: length)), 'OFF') /= 0) then
|
||||
plot = .FALSE.
|
||||
end if
|
||||
end if
|
||||
return
|
||||
end if
|
||||
tempLoc = index( Ucase(str), 'START') ! 判断是否是START变量
|
||||
if ( tempLoc /= 0 .and. tempLoc < equLoc ) then ! 如果是
|
||||
write(str, '(A)') str(equLoc+1: length) ! 将值部分读入字符串
|
||||
read(str, *) start ! 读取值, 接下来相同
|
||||
return
|
||||
end if
|
||||
tempLoc = index( Ucase(str), 'STOP')
|
||||
if ( tempLoc /= 0 .and. tempLoc < equLoc ) then
|
||||
write(str, '(A)') str(equLoc+1: length)
|
||||
read(str, *) stop
|
||||
return
|
||||
end if
|
||||
tempLoc = index( Ucase(str), 'DT')
|
||||
if ( tempLoc /= 0 .and. tempLoc < equLoc ) then
|
||||
write(str, '(A)') str(equLoc+1: length)
|
||||
read(str, *) dt
|
||||
return
|
||||
end if
|
||||
end subroutine InputData
|
||||
! 转换为大写
|
||||
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 subroutine Exercises10_12
|
||||
! 习题10-13 直方图 ??? 这是什么鬼需求
|
||||
! 基本逻辑如下:
|
||||
! 1. 首先打开一个临时文件, 并向其中输入数据
|
||||
! 2. 读取数据, 并向数组中填入相关值
|
||||
! 3. 依据数据, 构建一个二维数组, 并模拟图表构成
|
||||
! 4. 打印这个数组, 模拟直方图的形式
|
||||
subroutine Exercises10_13
|
||||
implicit none
|
||||
integer :: errorLevel
|
||||
character(len=6), dimension(7) :: arrayName ! 类名
|
||||
integer, dimension(7) :: arrayValue ! 类值
|
||||
arrayName = (/'100~95', '94~90 ', '89~85 ', '84~80 ', '79~75 ', '74~70 ', '69~65 '/) ! 定义类名
|
||||
arrayValue = (/3, 6, 9, 7, 4, 2, 1/) ! 定义类值
|
||||
write(*,*) ' Form 10.13 学生成绩分布直方图' ! 输出标题
|
||||
call DrawHistogram(arrayName, arrayValue, errorLevel) ! 绘图
|
||||
contains
|
||||
! 直方图绘制
|
||||
subroutine DrawHistogram(arrayName, arrayValue, errorLevel)
|
||||
character(len=*), dimension(:), intent(in) :: arrayName ! 输入类名
|
||||
integer, dimension(:), intent(in) :: arrayValue ! 输入类值
|
||||
integer, intent(out) :: errorLevel ! 错误码
|
||||
character(len=max(maxval(len_trim(arrayName))+1, 6)), allocatable, dimension(:, :) :: arrayDraw ! 绘图矩阵
|
||||
integer :: temp, length ! 范围边界
|
||||
character(len=max(maxval(len_trim(arrayName))+1, 6)) :: bar, line ! 绘制形状
|
||||
integer :: i ! 循环参数
|
||||
if ( size(arrayName, 1) /= size(arrayValue, 1) ) then ! 如果类名和值数量不匹配, 报错并返回
|
||||
errorLevel = 1
|
||||
return
|
||||
end if
|
||||
length = size(arrayValue, 1) ! 获取图表类数目
|
||||
! temp = 1 ! 初始化类值最大值位置
|
||||
! do i = 2, length ! 获取类值最大值位置
|
||||
! if ( arrayValue(i) > arrayValue(temp) ) then
|
||||
! temp = i
|
||||
! end if
|
||||
! end do
|
||||
! temp = arrayValue(temp) ! 获取最大类值(话说为啥不直接用maxval函数)
|
||||
temp = maxval(arrayValue) ! 获取最大类值
|
||||
bar = '' ! 初始化形状
|
||||
do i = 1, len(bar)-2
|
||||
bar(i: i) = '%' ! 形成形状(用于表示直方图)
|
||||
end do
|
||||
do i = 1, len(line)
|
||||
line(i: i) = '_' ! 用于显示图表下边界
|
||||
end do
|
||||
allocate(arrayDraw(temp+4, length+1), stat=errorLevel) ! 定义数组
|
||||
if (errorLevel /= 0) print *, "arrayDraw: Allocation request denied"
|
||||
arrayDraw = '' ! 初始化绘制数组
|
||||
do i = 1, temp + 3
|
||||
write(arrayDraw(i, 1)(1: 3), '(I3)') temp + 3 - i ! 绘制数组坐标轴纵轴值
|
||||
end do
|
||||
do i = 1, temp + 3
|
||||
arrayDraw(i, 1)(len(bar)-1:len(bar)) = '| ' ! 绘制数组坐标轴纵轴边界
|
||||
end do
|
||||
arrayDraw(temp+3, 1)(len(bar)-1:len(bar)) = '|_' ! 绘制数组坐标轴零点边界
|
||||
do i = temp-2, 1, -5
|
||||
arrayDraw(i, 1)(len(bar)-1:len(bar)) = '|-' ! 绘制数组坐标轴纵轴刻度
|
||||
end do
|
||||
arrayDraw(temp+3, 2: length+1) = line ! 绘制数组坐标轴横轴
|
||||
write(arrayDraw(temp+4, 2:size(arrayName, 1)+1), '(A)') (trim(arrayName(i)), i = 1, size(arrayName, 1)) ! 绘制数组坐标轴横轴类名
|
||||
do i = 1, size(arrayName, 1)
|
||||
arrayDraw(temp+3-arrayValue(i):temp+2, i+1) = bar ! 绘制数组直方图
|
||||
end do
|
||||
do i = 1, temp + 4
|
||||
write(*, '(100A)') arrayDraw(i, :) ! 打印绘制数组
|
||||
end do
|
||||
if (allocated(arrayDraw)) deallocate(arrayDraw, stat=errorLevel) ! 释放数组
|
||||
if (errorLevel /= 0) print *, "arrayDraw: Deallocation request denied"
|
||||
errorLevel = 0 ! 设定错误等级为0
|
||||
end subroutine DrawHistogram
|
||||
end subroutine Exercises10_13
|
||||
! 习题10-14 随机数直方图
|
||||
module ran001
|
||||
implicit none
|
||||
integer :: n = 12345
|
||||
end module ran001
|
||||
subroutine Exercises10_14
|
||||
implicit none
|
||||
integer :: i
|
||||
integer :: errorLevel
|
||||
real :: randomValue
|
||||
character(len=9), dimension(20) :: arrayName ! 类名
|
||||
integer, dimension(20) :: arrayValue ! 类值
|
||||
write(*,*) ' Form 10.14 随机数分布直方图' ! 输出标题
|
||||
arrayName = (/&
|
||||
&'0.00~0.05', '0.05~0.10', '0.10~0.15', '0.15~0.20', &
|
||||
&'0.20~0.25', '0.25~0.30', '0.30~0.35', '0.35~0.40', &
|
||||
&'0.40~0.45', '0.45~0.50', '0.50~0.55', '0.55~0.60', &
|
||||
&'0.60~0.65', '0.65~0.70', '0.70~0.75', '0.75~0.80', &
|
||||
&'0.80~0.85', '0.85~0.90', '0.90~0.95', '0.95~1.00'/) ! 定义类名
|
||||
call seed0(12346.)
|
||||
arrayValue = 0
|
||||
do i = 1, 20000
|
||||
call random(randomValue)
|
||||
arrayValue(int(randomValue*20+1)) = arrayValue(int(randomValue*20+1)) + 1
|
||||
end do
|
||||
call DrawHistogram(arrayName, arrayValue, errorLevel) ! 绘图
|
||||
contains
|
||||
! 直方图绘制
|
||||
subroutine DrawHistogram(arrayName, arrayValue, errorLevel)
|
||||
character(len=*), dimension(:), intent(in) :: arrayName ! 输入类名
|
||||
integer, dimension(:), intent(in) :: arrayValue ! 输入类值
|
||||
integer, intent(out) :: errorLevel ! 错误码
|
||||
character(len=max(maxval(len_trim(arrayName))+1, 7)), allocatable, dimension(:, :) :: arrayDraw ! 绘图矩阵
|
||||
integer :: temp, length ! 范围边界
|
||||
character(len=max(maxval(len_trim(arrayName))+1, 7)) :: bar, line ! 绘制形状
|
||||
integer :: i ! 循环参数
|
||||
integer :: maxValue ! 最大值
|
||||
if ( size(arrayName, 1) /= size(arrayValue, 1) ) then ! 如果类名和值数量不匹配, 报错并返回
|
||||
errorLevel = 1
|
||||
return
|
||||
end if
|
||||
length = size(arrayValue, 1) ! 获取图表类数目
|
||||
temp = maxval(arrayValue) ! 获取最大类值
|
||||
bar = '' ! 初始化形状
|
||||
do i = 1, len(bar)-2
|
||||
bar(i: i) = '%' ! 形成形状(用于表示直方图)
|
||||
end do
|
||||
do i = 1, len(line)
|
||||
line(i: i) = '_' ! 用于显示图表下边界
|
||||
end do
|
||||
allocate(arrayDraw(14, length+1), stat=errorLevel) ! 定义数组
|
||||
if (errorLevel /= 0) print *, "arrayDraw: Allocation request denied"
|
||||
arrayDraw = '' ! 初始化绘制数组
|
||||
maxValue = maxval(arrayValue)
|
||||
do i = 1, 13
|
||||
write(arrayDraw(i, 1)(1: 4), '(I4)') nint(real(maxValue)*(13. - real(i))/10.) ! 绘制数组坐标轴纵轴值
|
||||
end do
|
||||
do i = 1, 12
|
||||
arrayDraw(i, 1)(len(bar)-2:len(bar)) = '| ' ! 绘制数组坐标轴纵轴边界
|
||||
end do
|
||||
arrayDraw(13, 1)(len(bar)-2:len(bar)) = '|__' ! 绘制数组坐标轴零点边界
|
||||
do i = 8, 1, -5
|
||||
arrayDraw(i, 1)(len(bar)-2:len(bar)) = '|- ' ! 绘制数组坐标轴纵轴刻度
|
||||
end do
|
||||
arrayDraw(13, 2: length+1) = line ! 绘制数组坐标轴横轴
|
||||
write(arrayDraw(14, 2:size(arrayName, 1)+1), '(A)') (trim(arrayName(i)), i = 1, size(arrayName, 1)) ! 绘制数组坐标轴横轴类名
|
||||
do i = 1, size(arrayName, 1)
|
||||
arrayDraw(13-nint(real(arrayValue(i))*10./real(maxValue)):12, i+1) = bar ! 绘制数组直方图
|
||||
end do
|
||||
do i = 1, 14
|
||||
write(*, '(100A)') arrayDraw(i, :) ! 打印绘制数组
|
||||
end do
|
||||
if (allocated(arrayDraw)) deallocate(arrayDraw, stat=errorLevel) ! 释放数组
|
||||
if (errorLevel /= 0) print *, "arrayDraw: Deallocation request denied"
|
||||
errorLevel = 0 ! 设定错误等级为0
|
||||
end subroutine DrawHistogram
|
||||
subroutine seed0(iseed)
|
||||
use ran001
|
||||
real, intent(in) :: iseed
|
||||
n = abs(iseed)
|
||||
end subroutine seed0
|
||||
subroutine random(ran)
|
||||
use ran001
|
||||
real, intent(inout) :: ran
|
||||
n = mod(8121*n+28411,134456)
|
||||
ran = real(n)/134456
|
||||
end subroutine random
|
||||
end subroutine Exercises10_14
|
||||
! 习题10-15 拷贝文件去除注释
|
||||
subroutine Exercises10_15
|
||||
implicit none
|
||||
character(len=132) :: str
|
||||
integer :: errorLevel
|
||||
open(unit=1, status='scratch', iostat=errorLevel)
|
||||
if ( errorLevel /= 0 ) stop ""
|
||||
write(1, '(A)') &
|
||||
&"subroutine DrawHistogram(arrayName, arrayValue, errorLevel)'!'", &
|
||||
&"character(len=*), dimension(:), intent(in) :: arrayName ! 输入类名", &
|
||||
&"integer, dimension(:), intent(in) :: arrayValue ! 输入类值", &
|
||||
&"integer, intent(out) :: errorLevel ! 错误码", &
|
||||
&"character(len=max(maxval(len_trim(arrayName))+1, 7)), allocatable, dimension(:, :) :: arrayDraw ! 绘图矩阵", &
|
||||
&"integer :: temp, length ! 范围边界", &
|
||||
&"character(len=max(maxval(len_trim(arrayName))+1, 7)) :: bar, line ! 绘制形状"
|
||||
rewind(unit=1, iostat=errorLevel)
|
||||
if ( errorLevel /= 0 ) stop ""
|
||||
do
|
||||
read(1, '(A)', iostat=errorLevel) str
|
||||
if ( errorLevel /= 0 ) exit
|
||||
write(*, *) Uncomment(str)
|
||||
end do
|
||||
contains
|
||||
function Uncomment(str)
|
||||
character(len=*), intent(in) :: str
|
||||
character(len=len(str)) :: Uncomment
|
||||
integer :: i
|
||||
integer :: runLevel
|
||||
runLevel = 0
|
||||
do i = 1, len(str)
|
||||
if ( str(i: i) == '!' .and. (runLevel == 0) ) then ! 将感叹号转换为空格
|
||||
Uncomment(i: i) = ' '
|
||||
else
|
||||
Uncomment(i: i) = str(i: i)
|
||||
end if
|
||||
if ( str(i: i) == '"' .and. runLevel == 0 ) then ! 判断不转换感叹号的场景
|
||||
runLevel = 1
|
||||
elseif ( str(i: i) == '"' .and. runLevel == 1 ) then
|
||||
runLevel = 0
|
||||
elseif ( str(i: i) == "'" .and. runLevel == 0 ) then
|
||||
runLevel = 2
|
||||
elseif ( str(i: i) == "'" .and. runLevel == 2 ) then
|
||||
runLevel = 0
|
||||
end if
|
||||
end do
|
||||
end function Uncomment
|
||||
end subroutine Exercises10_15
|
Reference in New Issue
Block a user