Fortran 90整数数组转字符数组时遇文件结束错误排查
问题分析与修复:Fortran月份整数转字符数组错误
问题背景
有一个接收任意数量月份整数的模块,需要将这些整数转换为字符类型。在转换子程序中执行write(output_chars(idx),'(I2.2)') input_ints(idx)时,循环首次迭代后出现“end-of-file”错误;省略unit=无错误,但添加unit=会触发语法错误。
核心错误原因
字符数组未分配内存
主程序中monchar是可分配字符数组,但调用转换子程序前没有为其分配与month_int相同大小的空间。向未分配的数组元素写入时,会触发内存访问异常,表现为“end-of-file”这类错误。WRITE语句语法误用
Fortran中向字符变量写入时,不需要指定unit=参数——字符变量本身就是输出目标。unit仅用于文件/设备单元,强行添加会直接触发语法错误。格式符与数组长度匹配问题(可选优化)
若使用(I2.2)格式,要求字符变量长度至少为2,主程序中monchar定义为character(len=2)是符合要求的,但如果之前用(I0)格式,1位整数会只写1个字符,剩余位置留空格,不符合月份字符的固定格式需求。
修正后的完整代码
主程序部分
program ConvMonInt2MonCh use months_mod, only: get_months implicit none integer, allocatable :: month_int(:) character(len=2), allocatable :: monchar(:) integer :: idx call get_months(month_int) ! 关键步骤:为字符数组分配与输入整数数组相同的空间 allocate(monchar(size(month_int))) ! 调用转换子程序 call convert_monthint_to_monthchar(month_int, monchar) ! 打印转换结果验证 print *, "转换后的月份字符:" do idx = 1, size(monchar) print *, monchar(idx) enddo contains subroutine convert_monthint_to_monthchar(input_ints, output_chars) implicit none ! 哑元定义 integer, dimension(:), intent(in) :: input_ints character(len=*), dimension(:), intent(out) :: output_chars ! 局部循环变量 integer :: idx ! 前置检查:确保输入输出数组大小匹配 if (size(input_ints) /= size(output_chars)) then error stop "输入输出数组大小不匹配" endif ! 循环转换每个元素 do idx = 1, size(input_ints) ! 使用I2.2格式,确保输出两位字符(不足补前导零) write(output_chars(idx), '(I2.2)') input_ints(idx) enddo end subroutine convert_monthint_to_monthchar end program ConvMonInt2MonCh
模块部分(months_mod.f90)
module months_mod implicit none contains subroutine get_months(month_array) implicit none integer, intent(OUT), allocatable :: month_array(:) integer, allocatable :: temp_array(:) integer :: n, i, xtra_month ! 1. 提示输入月份数量 print*, 'Enter the number of months to process,' print*, '1 for one month, 2 for two months, ...:' print*, ' ' read *, n ! 2. 分配用户指定大小的数组 ALLOCATE(month_array(n)) ! 3. 提示用户输入每个月份整数 print*, 'Enter a month to process' print*, "1 for Jan, or more than one month, one by one, each followed by Enter:" print*,' ' do i = 1, n read*, month_array(i) enddo ! 分配临时数组,多一个位置存储额外月份 allocate(temp_array(n + 1)) ! 计算额外月份(12月的下一个月是1月) if(month_array(n) == 12) then xtra_month = 1 else xtra_month = month_array(n)+1 endif ! 复制原数据到临时数组 temp_array(1:n) = month_array(1:n) ! 添加额外月份 temp_array(n + 1) = xtra_month ! 重新分配原数组并复制数据 deallocate(month_array) allocate(month_array(n+1)) month_array = temp_array deallocate(temp_array) end subroutine get_months end module months_mod
额外优化说明
- 新增数组大小检查,避免因输入输出数组长度不匹配导致的隐性错误
- 使用
I2.2格式确保输出固定两位字符(如1转为"01",12转为"12"),符合月份字符的通用格式需求 - 主程序添加结果打印,方便快速验证转换是否正确
内容的提问来源于stack exchange,提问作者Zilore Mumba
相关产品推荐
相关产品推荐

