Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

String Formatting with Fortran

Status
Not open for further replies.

taghack

Programmer
May 2, 2013
3
I have a weird assignment that I am struggling with. I have written a very simple method to insert spaces into a text and produce an evenly formatted (justified) text as a result. The coding in Java was fairly straightforward, but I now have to rewrite it in Fortran ... After a lot of efforts i finally rolled out this ugly code. However it seems that I am missing some key point when it comes to concatenating spaces to a string or atleast thats what i think. Anyway it is not outputting what it should. Could somebody please take a look at it. I would be very grateful. Here is the code:
Code:
program xfunc
implicit none
CHARACTER(LEN=682) :: text
CHARACTER(100) :: words(100)
CHARACTER(2000) :: result
integer :: lineLenght
integer :: beginningIndent
integer :: pos1
integer :: pos2
integer :: n
integer :: i
integer :: characterCount
CHARACTER(100) :: wordsForLine(100)
integer :: wordsForLinePointer
integer :: substractForInterval
CHARACTER(20) :: beginningIndentWord
integer :: k
integer :: numberOfSpacesToAddAfterEachWord
integer :: numberOfLeftOverSpaces
integer :: numberOfLeftOverSpacesAdded
integer :: j
integer :: p

text = 'Lorem ipsum dolor sit amet, &
consectetur adipiscing elit. Duis et &
ante at eros euismod molestie eu &
varius ipsum. Aenean gravida pharetra &
magna quis auctor. Nullam est leo, &
dictum ac luctus quis, aliquet eu &
neque. Donec in nisl enim, et &
malesuada odio. Nulla scelerisque &
tortor id justo porttitor et &
vulputate urna pharetra. Pellentesque &
mollis condimentum elementum. Cras &
tempor, turpis hendrerit adipiscing &
lacinia, dolor metus egestas velit, &
venenatis vulputate leo eros elementum &
tellus. Vivamus id dui erat. Sed &
dictum consequat nulla, sed gravida &
eros mattis in. Suspendisse ac lorem &
lorem, ut molestie justo. Quisque &
suscipit velit ut odio euismod &
elementum. Vestibulum tempus.'
lineLenght = 50
beginningIndent = 10
pos1 = 1
n = 0

DO
  pos2 = INDEX(text(pos1:), " ")
  IF (pos2 == 0) THEN
     n = n + 1
     words(n) = text(pos1:)
     EXIT
  END IF
  n = n + 1
  words(n) = text(pos1:pos1+pos2-2)
  pos1 = pos2+pos1
END DO

print*, LEN(words)

i = 0

DO
IF( i >= LEN(words) ) THEN
    EXIT
END IF

characterCount = 0

wordsForLinePointer = 0

DO
  IF( wordsForLinePointer >= LEN(wordsForLine) ) THEN
      EXIT
  END IF

    wordsForLine(wordsForLinePointer) = ''
    wordsForLinePointer = wordsForLinePointer + 1
END DO

wordsForLinePointer = 0

substractForInterval = 1

IF( i == (LEN(wordsForLine) -1) ) THEN
    substractForInterval = 0
END IF

DO
  IF( (i >= LEN(words)) .AND. (characterCount > lineLenght - LEN(words(i)) - substractForInterval) ) THEN
      EXIT
  END IF

  IF( i == 0 ) THEN
    beginningIndentWord = ''

    k=0

    DO
     IF( k >= beginningIndent ) THEN
        EXIT
     END IF

     beginningIndentWord = beginningIndentWord//' '
     k = k + 1
    END DO

    wordsForLine(wordsForLinePointer) = beginningIndentWord
    wordsForLinePointer = wordsForLinePointer + 1
    characterCount = characterCount + beginningIndent + 1

  END IF

  wordsForLine(wordsForLinePointer) = words(i)
  wordsForLinePointer = wordsForLinePointer + 1
  characterCount = characterCount + LEN(words(i)) + 1
  i = i + 1

END DO

characterCount = characterCount - 1

numberOfSpacesToAddAfterEachWord = (lineLenght - characterCount) / (LEN(wordsForLine) - 1)
numberOfLeftOverSpaces = MOD((lineLenght - characterCount),(LEN(wordsForLine) - 1))
numberOfLeftOverSpacesAdded = 0

j = 0

DO
    IF( j >= (wordsForLinePointer + 1) ) THEN
        EXIT
    END IF

    result = result//wordsForLine(j)

    IF( j < wordsForLinePointer ) THEN
        result = result//' '
    END IF

    IF( i /= LEN(words) .AND. j < wordsForLinePointer ) THEN

        p = 0

        DO
          IF( p >= numberOfSpacesToAddAfterEachWord ) THEN
              EXIT
          END IF

          result = result//' '
          p = p + 1

        END DO

        IF( numberOfLeftOverSpacesAdded < numberOfLeftOverSpaces ) THEN
             result = result//' '
             numberOfLeftOverSpacesAdded = numberOfLeftOverSpacesAdded + 1
        END IF

    END IF

    j = j + 1

END DO

result = result//'\n'

END DO


print*, result

end program xfunc
 
The output has to be the input string formatted evenly (justified).
 
1) Which compiler are you using? Just wondering because long strings have to begin with & on the next line. eg
Code:
text = 'Lorem ipsum dolor sit amet, &
&consectetur adipiscing elit. Duis et &
&ante at eros euismod molestie eu &
...
&elementum. Vestibulum tempus.'

2) Some comments in the code would be nice. We don't do this professionally and not everyone can figure out what the code is doing just by looking at it.

3) len of a character variable will only tell you the size: not how long the string is. If you declare a character variable as

character(len=20)::x

len(x) will always give you 20. If you wish to know how long the string is within x excluding trailing spaces, you need something like len(trim(x))

4) Were you using vectors of some sort in Java - you seem to be using len of arrays a lot. If you fill up 10 words, len will still give you 100: not 10.

5) If you want a newline, use char(10). \n will just give you \n. If you are using windows, you need char(10) // char(13)
 
Also, in Fortran, arrays begin at 1: not 0. If they are required to start at 0 then they have to be declared as such
Code:
character(len=100)::wordsforline(0:99)
The problem with this is that len will still be 100.
 
I agree...it is ugly [tongue]

There are some fundamental mistakes.

First, as xwb mentioned, the arrays as declared start at 1, but the variables that you are using as indices start at a value of zero...you need to fix this...either start your indices at 1 or re-declare your arrays and specify the index range to start at zero.

Also, you do LEN(vname) on '2-dimensional' arrays; for example, 'words' is an array 100 items long and each item is supposed to be a 100-character long string...what are you after when you do LEN(words)?...could it be that you mean LEN(words(i)) instead? or more appropriately LEN(TRIM(words(i))) ?

If you do not know fortran well, I would program just a few lines of code at a time and test as you go. You may even want to write 5-line long program just to find out how things like LEN(), LEN(TRIM()) work and stuff like that...when I don't quite get something, that's what I do...I ask the compiler!







 
Thank you all very much for the advice. I definitely do not know what I`m doing when it comes to Fortran. I will try to fix the problems you pointed out, but unfortunately when I have more time. However thank you all very much!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top