在fortran95中读取和写入文件
我正在尝试用Fortran执行以下操作:在fortran95中读取和写入文件,fortran,fortran95,Fortran,Fortran95,我正在尝试用Fortran执行以下操作: 逐行阅读文本文档 通过“交换”每个字母,逐字对每行进行编码 在字母表中,一个字母在它后面的l处,l=字母的长度 话 将编码行写入新的输出文档 我的循环似乎无限期地运行,输出文档中没有任何文字 我的测试输入文档只有两行: 一些东西 再来点东西 第一行正在正确读取和编码 PROGRAM zeichen USE PufferMod IMPLICIT NONE CHARACTER(LEN=132) :: z CHARACTER(maxlen):: x IN
- 一些东西
- 再来点东西
PROGRAM zeichen
USE PufferMod
IMPLICIT NONE
CHARACTER(LEN=132) :: z
CHARACTER(maxlen):: x
INTEGER:: a,e,i,l
OPEN(UNIT=39,FILE="intext.txt",ACTION="READ", STATUS="OLD")
OPEN(UNIT=40, FILE="outext.txt", ACTION="WRITE")
DO
2 READ(39,"(A)", end=10) z
a=1;
DO WHILE(a<133)
WRITE(*,*) z
WRITE(*,*) a
CALL Suche_Wort(z,a,e)
l=e-a+1
WRITE(*,*) a,e,l
DO i=a,e
IF(z(i:i)/="") THEN
CALL Codiere(z(i:i),l)
END IF
END DO
a=e+1
END DO
WRITE(40,*) z
END DO
10 CLOSE(UNIT=39)
CLOSE(UNIT=40)
END PROGRAM zeichen
MODULE PufferMod
IMPLICIT NONE
PRIVATE
PUBLIC :: maxlen, Codiere, Suche_Wort
INTEGER, PARAMETER :: maxlen = 132
CONTAINS
FUNCTION Kleinbuchstabe(z)
CHARACTER(LEN=1) :: z
LOGICAL :: Kleinbuchstabe
Kleinbuchstabe= "a" <= z .AND. z <= "z"
END FUNCTION Kleinbuchstabe
FUNCTION Grossbuchstabe(z)
CHARACTER(LEN=1) :: z
LOGICAL :: Grossbuchstabe
Grossbuchstabe= "A" <= z .AND. z <= "Z"
END FUNCTION Grossbuchstabe
FUNCTION Buchstabe(z)
CHARACTER(LEN=1) :: z
LOGICAL :: Buchstabe
Buchstabe= (("a" <= z .AND. z <= "z") .OR. ("A" <= z .AND. z <= "Z"))
END FUNCTION Buchstabe
SUBROUTINE Codiere(z, Verschiebung)
CHARACTER(LEN=1) :: z
INTEGER, INTENT(IN) :: Verschiebung
INTEGER :: CodevonA
IF ( Kleinbuchstabe(z) ) THEN
CodevonA= ICHAR("a")
ELSE IF ( Grossbuchstabe(z) ) THEN
CodevonA= ICHAR("A")
END IF
z= CHAR( CodevonA + MOD( ICHAR(z) - CodevonA + Verschiebung, 26 ) )
END SUBROUTINE Codiere
SUBROUTINE Suche_Wort(z,a,e)
CHARACTER(LEN=maxlen), INTENT(in):: z
INTEGER, INTENT(inout):: a
INTEGER, INTENT(out):: e
CHARACTER:: x, temp*1
INTEGER:: i
i=1
temp=z(a:a)
!WRITE(*,*) "a before loop",a, "temp", temp
DO WHILE(temp == " ") !Find start of next word
temp=z(a+i:a+i)
i=i+1
a=a+1
END DO
!WRITE(*,*) "a after loop", a
e=a+1
i=1
temp=z(e:e)
DO WHILE(temp/= "") !find where the word ends by finding a space
temp=z(e+i:e+i)
i=i+1
e=e+1
IF(temp == " ") EXIT
END DO
END SUBROUTINE Suche_Wort
END MODULE PufferMod
程序zeichen
使用烟粉虱
隐式无
字符(LEN=132)::z
字符(maxlen)::x
整数::a,e,i,l
打开(单位=39,FILE=“intext.txt”,ACTION=“READ”,STATUS=“OLD”)
打开(单位=40,FILE=“outext.txt”,ACTION=“WRITE”)
做
2读(39,“(A)”,结束=10)z
a=1;
执行WHILE(a您的子例程至少有三个问题:
- 它从不检查
z
变量的索引是否在范围内
- 它假定结束索引严格大于开始索引,因此不允许使用单字符单词
- 在它的每个循环中,它以一个
i
和另一个整数变量(第一个循环中的a
,第二个循环中的e
)的增量递增,在每次迭代中有效地将z的索引递增2
我建议对zeichen
程序应用两个更改,以便通过使用内在函数trim
(删除尾随空间)和len_trim
(计算修剪变量的长度)去除尾随空格:
为什么你需要考虑单词?
只需转换A:Z或A:Z即可
PROGRAM zeichen
CHARACTER(LEN=132) :: z
INTEGER :: iostat, Verschiebung = 1
OPEN (UNIT=39, FILE="ziechen.f90", ACTION="READ", STATUS="OLD")
OPEN (UNIT=40, FILE="outext.txt", STATUS="UNKNOWN")
DO
READ (39,fmt="(A)", iostat=iostat) z
if ( iostat /= 0 ) exit
call convert_line ( z, Verschiebung )
WRITE (40,fmt="(A)") trim (z)
WRITE ( *,fmt="(A)") trim (z)
END DO
END PROGRAM zeichen
Subroutine convert_line ( z, inc )
character*(*) z
integer inc, i
do i = 1, len_trim (z)
call convert_character ( z(i:i), inc )
end do
end Subroutine convert_line
Subroutine convert_character ( z, inc )
character z
integer inc, ia, ic
!
if ( z >= 'A' .and. z <= 'Z' ) then
ia = ichar ('A')
else if ( z >= 'a' .and. z <= 'z' ) then
ia = ichar ('a')
else
return
end if
ic = mod ( ichar (z) - ia + inc + 26, 26 )
z = char (ia + ic )
!
end Subroutine convert_character
程序zeichen
字符(LEN=132)::z
整数::iostat,Verschiebung=1
打开(UNIT=39,FILE=“ziechen.f90”,ACTION=“READ”,STATUS=“OLD”)
打开(单位=40,文件=“outext.txt”,状态=“未知”)
做
读取(39,fmt=“(A)”,iostat=iostat)z
如果(iostat/=0)退出
呼叫转换线(z,Verschiebung)
写入(40,fmt=“(A)”)微调(z)
写入(*,fmt=“(A)”)修剪(z)
结束
结束程序zeichen
子程序转换线(z,inc)
字符*(*)z
整数公司
i=1,透镜微调(z)
调用转换字符(z(i:i),inc)
结束
结束子例程转换_行
子例程转换字符(z,inc)
字符z
integer公司,ia,ic
!
如果(z>='A'。和.z='A'。和.z我认为它将在读取最后一行时结束;当输入文档结束时。当输入文档被完全读取时,10是应该去的地方。当我运行您的代码时,我会遇到一个分段错误,当代码离开z
的末尾时。尝试在打开错误边界检查的情况下重新编译,然后再进行一次。H我该怎么做呢?您可以查阅编译器文档,搜索短语数组边界或边界检查。或者在此处查看其他问题。因此,本主题大约每周讨论一次。在应用更改和更多更改后,它几乎工作得很好。唯一剩下的问题是输出在同一行上。抱歉,这个问题只发生在记事本中,而不发生在记事本++中。因为我根据每个单词的长度而不是固定数量来更改它们,所以我取了“l”在阅读代码时,我对convert_字符所做的更改可能有一定的相关性,这取决于单词可用的字符集。无论如何,我很感激;任何编写得更好的代码对我都很有用。如果您有一个字符数组z
包含该单词,您可以通过z=merge(achar(iachar(z))转换它+模(iand(iachar(z),NOT(32))-65+size(z),26)-(iand(iachar(z),NOT(32))-65)),z,BLT(iand(iachar(z),NOT(32))-65,26))
@user5713492我真的不明白为什么这么复杂的解决方案很吸引人。我总是建议将问题分解成更容易理解的小部分。
SUBROUTINE Suche_Wort(z,a,e)
CHARACTER(LEN=*), INTENT(in):: z ! Dummy argument has length of actual argument
INTEGER, INTENT(inout):: a
INTEGER, INTENT(out):: e
CHARACTER(len=1):: temp
temp=z(a:a)
DO WHILE((temp == " ").and.(a<len(z))) !Find start of next word
temp=z(a+1:a+1)
a=a+1
END DO
e=a ! Allows 1-character words
DO WHILE((temp/= " ").and.(e<len(z))) !find where the word ends by finding a space
temp=z(e+1:e+1)
e=e+1
END DO
END SUBROUTINE Suche_Wort
PROGRAM zeichen
CHARACTER(LEN=132) :: z
INTEGER :: iostat, Verschiebung = 1
OPEN (UNIT=39, FILE="ziechen.f90", ACTION="READ", STATUS="OLD")
OPEN (UNIT=40, FILE="outext.txt", STATUS="UNKNOWN")
DO
READ (39,fmt="(A)", iostat=iostat) z
if ( iostat /= 0 ) exit
call convert_line ( z, Verschiebung )
WRITE (40,fmt="(A)") trim (z)
WRITE ( *,fmt="(A)") trim (z)
END DO
END PROGRAM zeichen
Subroutine convert_line ( z, inc )
character*(*) z
integer inc, i
do i = 1, len_trim (z)
call convert_character ( z(i:i), inc )
end do
end Subroutine convert_line
Subroutine convert_character ( z, inc )
character z
integer inc, ia, ic
!
if ( z >= 'A' .and. z <= 'Z' ) then
ia = ichar ('A')
else if ( z >= 'a' .and. z <= 'z' ) then
ia = ichar ('a')
else
return
end if
ic = mod ( ichar (z) - ia + inc + 26, 26 )
z = char (ia + ic )
!
end Subroutine convert_character