Task: Align columns








VB: Dim MText as QMemorystream
    MText.WriteLine "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
    MText.WriteLine "are$delineated$by$a$single$
    MText.WriteLine "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
    MText.WriteLine "column$are$separated$by$at$least$one$space."
    MText.WriteLine "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
    MText.WriteLine "justified,$right$justified,$or$center$justified$within$its$column."

DefStr TextLeft, TextRight, TextCenter
DefStr MLine, LWord, Newline = chr$(13)+chr$(10)
DefInt ColWidth(100), ColCount
DefSng NrSpaces 


MText.position = 0
for x = 0 to MText.linecount -1
    MLine = MText.ReadLine
    for y = 0 to Tally(MLine, "$")
        LWord = Field$(MLine, "$", y+1)
        ColWidth(y) = iif (ColWidth(y) < len(LWord), len(LWord), ColWidth(y))
    next
next


MText.position = 0
for x = 0 to MText.linecount -1
    MLine = MText.ReadLine
    for y = 0 to Tally(MLine, "$")
        LWord = Field$(MLine, "$", y+1)
        NrSpaces = ColWidth(y) - len(LWord)
        
        TextLeft = TextLeft + LWord + Space$(NrSpaces+1)
        
        TextRight = TextRight + Space$(NrSpaces+1) + LWord
        
        TextCenter = TextCenter + Space$(floor((NrSpaces)/2)+1) + LWord + Space$(Ceil((NrSpaces)/2))
    next
    TextLeft = TextLeft + Newline 
    TextRight = TextRight + Newline 
    TextCenter = TextCenter + Newline 
next



Fortran:       SUBROUTINE RAKE(IN,M,X,WAY)	
Collates column widths so that each column is wide enough for its widest member.
       INTEGER IN		
       INTEGER M		
       CHARACTER*1 X		
       INTEGER WAY		
       INTEGER W(M + 1)		
       INTEGER C(0:M + 1)	
       CHARACTER*(M) ACARD	
       CHARACTER*(28 + 4*M) FORMAT	
       INTEGER I		
       INTEGER L,LF		
       INTEGER NF,MF		
       CHARACTER*6 WAYNESS(-1:+1)	
       PARAMETER (WAYNESS = (/"Left","Centre","Right"/))	
       INTEGER LINPR	
       COMMON LINPR	
        W = 0		
        MF = 0		
        C(0) = 0	
        WRITE (LINPR,*)	
        WRITE (LINPR,*) "Align ",WAYNESS(MIN(MAX(WAY,-1),+1))	

Chase through the file assessing the lengths of each field.
   10   READ (IN,11,END = 20) L,ACARD(1:L)	
   11   FORMAT (Q,A)				
        CALL LIZZIEBORDEN	
        W(1:NF) = MAX(W(1:NF),C(1:NF) - C(0:NF - 1) - 1)	
        MF = MAX(MF,NF)		
        GO TO 10		

Concoct a FORMAT based on the maximum size of each field. Plus one.
   20   REWIND(IN)		
        WRITE (FORMAT,21) W(1:MF) + 1	
   21   FORMAT ("(",<MF>("A",I0,","))	
        LF = INDEX(FORMAT,", ")		
        IF (LF.LE.0) STOP "Format trouble
        FORMAT(LF:LF) = ")"			
        WRITE (LINPR,*) "Format",FORMAT(1:LF)	

Chug afresh, this time knowing the maximum length of each field.
   30   READ (IN,11,END = 40) L,ACARD(1:L)	
        CALL LIZZIEBORDEN		
        SELECT CASE(WAY)	
         CASE(-1)		
          WRITE (LINPR,FORMAT) (ACARD(C(I - 1) + 1:C(I) - 1)//	
     1     REPEAT(" ",W(I) - C(I) + C(I - 1) + 1),I = 1,NF)	
         CASE( 0)		
          WRITE (LINPR,FORMAT) (ACARD(C(I - 1) + 1:C(I) - 1)//	
     1     REPEAT(" ",(W(I) - C(I) + C(I - 1) + 1)/2),I = 1,NF)	
         CASE(+1)		
          WRITE (LINPR,FORMAT) (ACARD(C(I - 1) + 1:C(I) - 1),I = 1,NF)	
         CASE DEFAULT		
         WRITE (LINPR,*) "Huh? WAY=",WAY	
         STOP "Unanticipated value for WAY
        END SELECT		
        GO TO 30		
Closedown
   40   REWIND(IN)		
       CONTAINS	
        SUBROUTINE LIZZIEBORDEN	
          NF = 0		
          DO I = 1,L		
            IF (ICHAR(ACARD(I:I)).EQ.ICHAR(X)) THEN	
              NF = NF + 1		
              C(NF) = I		
            END IF		
          END DO		
          NF = NF + 1		
          C(NF) = L + 1		
        END SUBROUTINE LIZZIEBORDEN	
      END SUBROUTINE RAKE	

      INTEGER L,M,N	
      INTEGER LINPR,IN	
      COMMON LINPR	
      LINPR = 6		
      IN = 10		
      OPEN (IN,FILE="Rake.txt",STATUS="OLD",ACTION="READ")	
      N = 0		
      M = 0		

    1 READ (IN,2,END = 10) L	
    2 FORMAT (Q)	
      N = N + 1		
      M = MAX(M,L)	
      GO TO 1		

   10 REWIND (IN)	
      WRITE (LINPR,*) N,"Recs, longest rec. length is ",M
      CALL RAKE(IN,M,"$",-1)	
      CALL RAKE(IN,M,"$", 0)	
      CALL RAKE(IN,M,"$",+1)	
      END