-2

Task / assignment

Method to insert spaces into a text and produce an evenly formatted (justified) text as a result. I wrote working Java code but it's necessary to write that in Fortran.

Working Java code I wrote

public class ProgramingLanguagesTheoryHomeWork {

public static void main(String[] args) {
    String inputString = "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.";
    String outputString = format(inputString, 50, 10);

    System.out.println(outputString);
}

private static String format(String text, int lineLength, int beginning_indent) {
    String result = "";
    String[] words = text.split(" ");
    int i = 0;
    while( i < words.length ) {
        int characterCount = 0;
        ArrayList<String> wordsForLine = new ArrayList<String>();

        int substractForInterval = i == words.length -1 ? 0:1;

        while( ( i < words.length ) && (characterCount <= lineLength - words[i].length() - substractForInterval) ) {

            if( i == 0 ) {
                String beginningIndentWord = "";

                for(int k=0;k<beginning_indent;k++) {
                    beginningIndentWord += " ";
                }

                wordsForLine.add(beginningIndentWord);
                characterCount += beginning_indent + 1;
            }

            wordsForLine.add(words[i]);
            characterCount += words[i].length() + 1; //the one is for the interval after each word
            i++;
        }

        characterCount --; //substract one character for the final interval which must not exist in the formatted text


        int numberOfSpacesToAddAfterEachWord = (lineLength - characterCount) / (wordsForLine.size() -1); //substract one word becouse the final word cant really take an inteterval
        int numberOfLeftOverSpaces = (lineLength - characterCount) % (wordsForLine.size() -1); //substract one word becouse the final word cant really take an inteterval


        int numberOfLeftOverSpacesAdded = 0;

        for(int j=0;j<wordsForLine.size();j++) {

            result += wordsForLine.get(j);

           if( j < (wordsForLine.size() - 1) ) //check to see if its the last word of the line and not add interval to it
               result += " ";

           if( i != words.length && j < (wordsForLine.size() - 1) ) { //check to see if its the last line that does not need to be converted and it its not the last character from a line which can not take intervals

               for(int p=0;p<numberOfSpacesToAddAfterEachWord;p++) {
                    result += " ";
               }


                if(numberOfLeftOverSpacesAdded < numberOfLeftOverSpaces ) {
                    result += " ";
                    numberOfLeftOverSpacesAdded++;
                }
           }
        }

        result += "\n";
    }

    return result;
}

}

Rewriting in Fortran

Initial problem

I just can`t figure out how in the world am i going to get around variable length strings and also the List variable.

Current problem

Ok 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 at least that's what I think.
  • It is not outputting what it should.
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
4
  • 7
    Just so we have this right. You want us to re-write this in FORTRAN for you? For free? Good one... Show us what you have tried and we might try to help you...
    – MoonKnight
    Commented May 2, 2013 at 9:39
  • I just don`t know how to work with variable length strings whenever i use something like this: function func(text, lineLenght, beginningIndent) result(result) CHARACTER(LEN=*) :: text !input integer, intent(in) :: lineLenght, beginningIndent ! input CHARACTER(LEN=*) :: result ! output result = "aaabbvv" end function func It gives me an error becouse of the string. Also i have no idea how to later specify the length or how to split thw string into an array of words. Any help on any of these would be greatly appreciated
    – taghack
    Commented May 2, 2013 at 9:41
  • Read this, it should be of help to you. www-solar.mcs.st-and.ac.uk/~steveb/course/notes/set4.pdf
    – MoonKnight
    Commented May 2, 2013 at 9:45
  • Thank you. Seems right on the money. I`ll get right to it.
    – taghack
    Commented May 2, 2013 at 9:50

2 Answers 2

0
      CHARACTER*1000 TEXT,TEXTOUT
      TEXTOUT=""
      L=0
      TEXT=" your Latin text, split over n lines using the continuation charactaer &...."
      I=1
   99 TEXTOUT(L+1:L+1)=TEXT(I,I)
      L=L+1
      IF(TEXT(I:I).NE." ")THEN
      I=I+1
      IF(I.LE.LEN_TRIM(TEXT))GO TO 99
      ELSE     
      J=I
      ISPACE=0 
   98 IF(TEXT(J:J).EQ." ")THEN
      J=J+1
      IF(J.LE.LEN_TRIM(TEXT))GO TO 98
      ELSE
      I=J
      GO TO 99
      ENDIF
      ENDIF   
0

Fortran now has variable length strings. There was an module adding those, which wasn't very popular. They have been added to Fortran 2003 as allocatable scalers. See, e.g., Fortran: Syntax error in CHARACTER declaration

Not the answer you're looking for? Browse other questions tagged or ask your own question.