6. Text (CHARACTER)

6.0 Inledning

I detta kapitel ges en kortfattad genomgång av de viktigaste kommandona vid texthantering.

6.1 Nutida texthantering

I och med Fortran 77 infördes en speciell datatyp CHARACTER för texthantering. Denna datatyp innehåller i sin enklaste form utrymme för en bokstav eller siffra eller annat tecken. Följande enkla program skriver således ut texten kul.
        CHARACTER*1 A, B, C
        A = 'k'
        B = 'u'
        C = 'l'
        WRITE(*,*) A, B, C
        END
Ovanstående utnyttjar Fortran 77 deklationen CHARACTER*1 A för att specificiera att variabeln A är en textsträngsvariabel med längden 1. I Fortran 95 är motsvarande deklaration i stället CHARACTER(LEN=1) :: A

En intressant variant är att använda konkatenering (summation) av tecken, vilket sker med symbolen två snedstreck //. Följande modifierade program har därför samma resultat som det föregående.

        CHARACTER(LEN=1) :: A, B, C
        A = 'k'
        B = 'u'
        C = 'l'
        WRITE(*,*) A // B // C
        END
Konkateneringen blir mer värdefull då vi väljer att sätta det nya resultatet i en längre variabel, vilken jag kallar för textsträng. Andra svenska böcker föredrar ordet teckensträng.
        CHARACTER(LEN=1) :: A, B, C
        CHARACTER(LEN=3) :: D
        A = 'k'
        B = 'u'
        C = 'l'
        D = A // B // C
        WRITE(*,*) D
        END
Vi kan nu börja med en verklig textmanipulering, till exempel genom att i stället omforma textsträngen kul till ull. Vi utgår nu i stället från den direkta tilldelningen av tre bokstäver till textsträngsvariabeln D, och placerar den andra bokstaven först och därefter den tredje bokstaven på den andra platsen.
        CHARACTER(LEN=3) :: D
        D = 'kul'
        D(1:1) = D(2:2)
        D(2:2) = D(3:3)
        WRITE(*,*) D
        END
Vi kan även omforma textsträngen kul till ull på ett "tuffare" sätt, genom att kopiera de båda sista bokstäverna till de båda första positionerna. Detta förfarande är tillåtet och entydigt även i detta överlappande fall i Fortran 90, men ej i Fortran 77.
        CHARACTER(LEN=3) :: D
        D = 'kul'
        D(1:2) = D(2:3)
        WRITE(*,*) D
        END
En annan nyhet är att en tom sträng nu är tillåten, dvs "ingenting" mellan de båda "blipparna" är tillåtet och tolkas som en tom textsträng, vilket kan vara bra vid iterativa processer.

6.2 Inbyggda funktioner

En viktig uppgift vid texthantering är sortering i bokstavsordning. Under Fortran kräves att siffrorna och bokstäverna ligger i ordning så att 1 är mindre än 3, c är mindre än p, och D är mindre än Z. Däremot är inget föreskrivet om relationen mellan siffror, gemener och versaler. Under den vanliga sorteringsordningen ASCII (American Standard Code for Information Interchange) är det ordningen siffror, versaler och gemener, medan under IBM:s system EBCDIC är det i stället gemener, versaler och siffror. Hos EBCDIC ligger specialtecknen först men i ASCII ligger specialtecken både först och sist samt på båda sidor om versalerna. Detta senare passar hyfsat men ej exakt med vårt utnyttjande av vissa specialtecken för de svenska bokstäverna.

Jämförelse sker utnyttjande de gamla symbolerna

        .LT.    .LE.    .EQ.    .NE.    .GT.    .GE.
eller motsvarande nya och mer matematiska
         <       <=      ==      /=       >      >=
Notera att eftersom likhetstecknet = användes som tilldelningstecken (motsvarande := i Pascal) så måste vi välja ett annat tecken för likhet, nämligen .EQ. eller = =. Kompilatorer är ofta skrivna så att de påstår att symbolen .LT. har använts på fel sätt, även om man i själva verket använt symbolen <.

Observera att vi även har tillgång till ett antal logiska operatorer, nämligen .NOT. .AND. .OR. samt de mer ovanliga .EQV. och .NEQV. De definieras i nedanstående tabell, men de har tyvärr ingen modernare beteckning än "punktnamnen".

           A            T     T     F      F
           B            T     F     T      F
        .NOT. A         F     F     T      T
        A .AND. B       T     F     F      F
        A .OR. B        T     T     T      F
        A .EQV. B       T     F     F      T
        A .NEQV. B      F     T     T      F
I Fortran 77 infördes ett alternativ till den maskinberoende sorteringsordning som erhålles med jämförelser av typ
        IF (CHAR1 .LT. CHAR2 ) THEN 
nämligen de fyra logiska funktionerna LGE, LGT, LLE och LLT, vilka är baserade på sorteringsordning enligt ASCII och som argument har två textsträngar. Ovanstående jämförelse skrives då
  IF ( LLT(CHAR1, CHAR2) ) THEN
varvid en maskinoberoende sortering erhålles.

Fyra andra funktioner i Fortran 77 ger det nummer som svarar mot ett visst tecken, och tvärtom. Funktionen ICHAR(A) ger numret för tecknet i textsträngsvariabeln A, medan CHAR(I) ger tecknet som svarar mot numret I, utgående från intern (maskinberoende) representation. De båda funktionerna IACHAR(A) och ACHAR(I) arbetar däremot med ASCII-koden.

I Fortran 90 tillkom ytterligare ett antal användbara funktioner för texthantering. Dessa finns, tillsammans med ovan nämnda, uppräknade i Appendix 5, avsnitten 4 och 5. De båda ADJUSTL och ADJUSTR vänster- respektive högerjusterar en sträng (dvs flyttar eventuella inledande respektive avslutande blanka men behåller längden), medan TRIM kortar av strängen genom att ta bort avslutande blanka. Längden av en sträng erhålles med LEN, medan LEN_TRIM ger längden utan avslutande blanka. Observera att LEN kan tillämpas på en deklarerad sträng som ej har tilldelats ett värde, i det fallet blir naturligtvis LEN_TRIM noll. Funktionen REPEAT användes för att upprepa en sträng, medan funktionerna INDEX, SCAN och VERIFY ger positionen för ett visst element, se Appendix 5 för detaljer.

Litet ytterligare om texthantering ges i det nytillkomna avsnittet om funktioner med textsträng av antagen längd som resultat.

6.3 Forntida texthantering

Som tidigare nämnts så infördes CHARACTER i och med Fortran 77. Även tidigare fanns behov av att skriva ut text som lagrats i variabler. Detta skedde då genom att man lagrade text i vanliga heltalsvariabler INTEGER (eller i flyttalsvariabler REAL). Ett exempel följer, men det kan ej köras med NAG:s Fortran 90 system, eftersom detta ej innehåller tilldelning av textsträngar med Hollerith-konstruktionen nHtext, där n är en siffra med antalet tecken (bokstäver) som ryms i variabeln. Denna möjlighet, som motsvara den nutida varianten med textsträng 'text', försvann med Fortran 77, men många implementationer innehåller den som en utvidgning. Exemplet fungerade därför med Sun:s Fortran 77 och gav utskriften Karl Johan.
            INTEGER A, B, C
            A = 4HKarl
            B = 4H Joh
            C = 4Han 
            WRITE(*,10) A, B, C
 10         FORMAT(3A4)
            END      
Metoden var inte speciellt flyttbar (portabel) eftersom antalet bokstäver som ryms i ett ord varierar mellan olika datorsystem. Vid utmatningen ovan måste ett explicit FORMAT användas för att få textutmatning, annars presenteras innehållet i de tre heltalsvariablerna A, B och C som tre heltal, dvs om WRITE(*,*) användes i stället för WRITE(*,10). Mer om Format följer i nästa kapitel.

Man kan tilldela nya värden till ovanstående variabler med satser som

      IF (X) 20, 30, 40
 20   C = A
        GO TO 50
 30   C = 4HBo
        GO TO 50
 40   C = B
 50   CONTINUE
Det är dock mycket väsentligt här att man bara gör text-tilldelningar mellan variabler av samma datatyp, annars sker en omvandling mellan olika numeriska typer, varvid texten blir helt oläslig. I nedanstående fall erhålles på Sun utmatningen Karl JohNÂÜ@, eftersom jag nu infört flyttalsvariabeln D, som sedan satts lika med heltalsvariabeln C. Satsen D = C kommer därför att medföra en automatisk konvertering av bitmönstret i C.
            INTEGER A, B, C
            REAL D
            A = 4HKarl
            B = 4H Joh
            C = 4Han
            D = C
            WRITE(*,10) A, B, D
 10         FORMAT(3A4)
            END      
Däremot fungerar det om samtliga variabler är flyttal av samma precision, men ej om jag blandar enkel och dubbel precision.

6.4 Några in- och utmatningsproblem vid texthantering

Om textformatet An inte stämmer med CHARACTER(LEN=n) kan litet förvillande resultat erhållas.

Inläsning av CHARACTER(LEN=1) med A5

     ABCDE     blir      E   (dvs sista tecknet vinner)
Inläsning av CHARACTER(LEN=5) med A5
     ABCDE     blir  ABCDE
     A         blir      A
     A C       blir  A C
Inläsning av CHARACTER(LEN=5) med A1
     ABCDE     blir  A     (dvs första tecknet vinner)

6.5 Textsträngar med variabel längd

Ett speciellt tillägg till standarden finns för detta, se ISO/IEC 1539-2. Jag kommer senare att komplettera detta avsnitt med en kort sammanfattning.

Den fullständiga texten till standarden, liksom implementering i standard Fortran 90 och två exempel, finns tillgängliga elektroniskt.

Programmen i exemplen ovan definierar ord såsom åtskilda av blank (mellanslag), komma, punkt, utropstecken, frågetecken eller postslut (radslut). De bör därför kunna fungera även på svenska texter.

Ett liknande ämne är funktioner med textsträng av antagen längd som resultat, men detta begrepp försvinner vid revisionen nästa årtusende.

Funktioner och subrutiner Innehåll Avancerad in- och utmatning (FORMAT)


Senast modifierad: 18 februari 2007
boein@nsc.liu.se