在fortran95中读取和写入文件

在fortran95中读取和写入文件,fortran,fortran95,Fortran,Fortran95,我正在尝试用Fortran执行以下操作: 逐行阅读文本文档 通过“交换”每个字母,逐字对每行进行编码 在字母表中,一个字母在它后面的l处,l=字母的长度 话 将编码行写入新的输出文档 我的循环似乎无限期地运行,输出文档中没有任何文字 我的测试输入文档只有两行: 一些东西 再来点东西 第一行正在正确读取和编码 PROGRAM zeichen USE PufferMod IMPLICIT NONE CHARACTER(LEN=132) :: z CHARACTER(maxlen):: x IN

我正在尝试用Fortran执行以下操作:

  • 逐行阅读文本文档
  • 通过“交换”每个字母,逐字对每行进行编码 在字母表中,一个字母在它后面的l处,l=字母的长度 话
  • 将编码行写入新的输出文档
  • 我的循环似乎无限期地运行,输出文档中没有任何文字

    我的测试输入文档只有两行:

    • 一些东西
    • 再来点东西
    第一行正在正确读取和编码

    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