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. /
We get:
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_alpha()
, and 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.