If you don’t quite understand the difference between old and new Fortran, consider the following program. This (slightly modified) program comes from a 1968 book titled “Fortran Programming”, by Fredric Stuart. Likely written in Fortran IV, it basically just counts words and sentences. The program reads the standard input (via a redirected file), storing each of the 80 characters in an array, and then examines each one by one using a loop. The first comparison tests for the end-of-text terminator “/”. The next comparison checks for a period and increases the sentence count. The third comparison checks for black characters and increments the word count. The code isn’t exactly perfect as it will count every blank as a though a word appeared before it.
C WORD AND SENTENCE COUNT DIMENSION LETT(80) DATA LPER, LBLANK, LSLASH/1H.,1H ,1H//,NWORD, NSENT/0,0/ 1 READ(*,10) LETT DO 6 K = 1,80 IF (LETT(K)-LSLASH) 2,7,2 2 IF (LETT(K)-LPER) 4,3,4 3 NSENT = NSENT + 1 GO TO 6 4 IF (LETT(K)-LBLANK) 6,5,6 5 NWORD = NWORD + 1 write(*,*) k, " " 6 CONTINUE GO TO 1 7 WRITE(*,11) NWORD, NSENT 10 FORMAT (80A1) 11 FORMAT (I16,' WORDS',10X,I16,' SENTENCES') CALL EXIT END
Now if we feed this program the following piece of text:
Cooking is a craft, I like to think, and a good cook is a craftsman -- not an artist. There's nothing wrong with that: The great cathedrals of Europe were built by craftsmen -- though not designed by them. Practicing your craft in expert fashion is noble, honorable, and satisfying. /
59 words 3 sentences
Which isn’t exactly true. Maybe the original program ran on a specific type of text? Count the words and we get 48. So why is the program not working? Because it increments the word counter when a blank character is encountered. So three blank characters at the end of a sentence implies 3 words are counted. It will work properly with simple sentences only containing periods as punctuation. So when this program gets compiled in a modern Fortran compiler, it will choke of a series of deleted or less-than-palatable features – although it will compile the program. Let’s first morph this program to a more modern Fortran 2003 (F03) version:
! Word and sentence count program wscount implicit none character, dimension(80) :: lett integer :: k, nword=0, nsent=0 10 format (80A1) 11 format (I16,' words',10X,I16,' sentences') mloop: do read(*,10) lett do k = 1, 80 if (lett(k) .eq. '/') then exit mloop elseif (lett(k) .eq. '.') then nsent = nsent + 1 elseif (lett(k) .eq. ' ') then nword = nword + 1 end if end do end do mloop write(*,11) nword, nsent end program wscount
This updated version replaces the
goto with a loop, rationalizes the
do loop, and replaces the three arithmetic
if statements with a nested
if statement. The Hollerith constants (in the
DATA statement) representing the slash, period and blank are replaced with characters within the logic statements, and all the variables are declared. The new program works exactly the same as the old one, i.e. it gives the same incorrect answer. So to fix that we have to add some functionality to deal with counting the words. Here is the modified program:
! Word and sentence count program wscount implicit none character, dimension(80) :: lett integer :: k, nword=0, nsent=0 10 format (80a) 11 format (I16,' words',10X,I16,' sentences') mloop: do read(*,10) lett do k = 1, 80 if (lett(k) .eq. '/') then exit mloop elseif (lett(k) .eq. '.') then nsent = nsent + 1 elseif (lett(k) .eq. ' ' .and. (is_alpha(lett(k-1)) & .or. is_punct(lett(k-1)))) then nword = nword + 1 end if end do end do mloop write(*,11) nword, nsent contains pure logical function is_alpha(c) character(len=1), intent(in) :: c is_alpha = (c >= 'a' .and. c <= 'z') & .or. (c >= 'A' .and. c <= 'Z') end function pure logical function is_punct(c) character(len=1), intent(in) :: c is_punct = (c == ',') .or. (c == '.') .or. (c == '?') & .or. (c == '!') .or. (c == ":") .or. (c == ';') end function end program wscount
The program now checks for a blank, and also if the character before the blank is a character (a-z, A-Z), or a punctuation mark (, . ? ! : ;). This requires the addition of two new functions
is_punct(). Now when run it gives the correct count for words. Of course this snippet of a program will still not work on everything. What happens if a sentence has a real number in it, like 3.14159? It will count as an additional sentence.
But the point of this post is not really to illustrate how well the program works, but rather the difference between a Fortran program written in 1968 and one written in 2022. They are vastly different languages, with F03 having non of the previous spaghetti-like idiosyncrasies of its predecessors.