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!

Linked List algorithm

Status
Not open for further replies.

turnerdaniet

Programmer
May 3, 2012
3
US
I am learning linked lists in fortran and I am working on a program now that reads from a file. Inside the file is a name followed by an age on the next line. the program reads all of the names, and ages until it reaches the end of file. it then prints the names and ages from head to tail. my linked list is not storing information properly. any help or guidance will be appreciated. below is my code


PROGRAM MAIN
*STRUCTURES
TYPE NODE
TYPE(NODE), POINTER :: NEXT, PREV
CHARACTER PERSON*30
INTEGER AGE
END TYPE NODE
*Declarations

CHARACTER INFILE *30, OUTFILE*30, NAMEIN*30
INTEGER MORE, INCOUNT, TOPRINT, AGEIN
LOGICAL EXISTS
TYPE(NODE), POINTER :: TEMP, HEAD, TAIL, CURRENT

*initializations
MORE = 1
EXISTS = .TRUE.
ALLOCATE(HEAD)
ALLOCATE(TAIL)
ALLOCATE(CURRENT)
NULLIFY(HEAD%NEXT,HEAD%PREV)
NULLIFY(TAIL%NEXT,TAIL%PREV)
NULLIFY(CURRENT%NEXT,CURRENT%PREV)
*MAIN
*PROMPT FOR USER INPUT FILENAME
DO WHILE(MORE.EQ.1)
PRINT *,'PLEASE ENTER AN INPUT FILENAME'
READ (*,*) INFILE
IF(INFILE.EQ.'QUIT'.OR.INFILE.EQ.'quit')THEN
MORE = 0


*CHECK FOR EXISTENCE OF INPUT FILE
ELSE
INQUIRE(FILE=INFILE,EXIST=EXISTS)
IF(.NOT.EXISTS)THEN
PRINT*,'THE FILENAME GIVEN DOES NOT EXIST'
PRINT*,'THE PROGRAM HAS TERMINATED'
MORE = 0

*IF IT EXISTS, OPEN THE FILE
ELSE
OPEN(UNIT=1,FILE=INFILE,STATUS='OLD')
MORE = 0
END IF

END IF

END DO

MORE = 1
*PROMPT FOR USER OUTPUT FILENAME
DO WHILE(MORE.EQ.1)
PRINT*,'PLEASE ENTER AN OUTPUT FILENAME'
READ (*,*) OUTFILE
IF(INFILE.EQ.'QUIT'.OR.INFILE.EQ.'quit')THEN
MORE = 0

*CHECK FOR EXISTENCE OF OUTPUT FILE
ELSE
INQUIRE(FILE=OUTFILE,EXIST=EXISTS)
IF(.NOT.EXISTS)THEN
*IF IT DOESN'T EXIST, OPEN AS NEW
OPEN(UNIT=2,FILE=OUTFILE,STATUS='NEW')
MORE = 0
ELSE
*OTHERWISE OPEN AS OLD
OPEN(UNIT=2,FILE=OUTFILE,STATUS ='OLD')
MORE = 0
END IF

END IF

END DO

*INPUT UP TO EOF
DO WHILE(.TRUE.)
READ(1,*,END=999)NAMEIN
READ(1,*,END=999)AGEIN
NULLIFY(CURRENT,HEAD,TAIL)

ALLOCATE(CURRENT)
IF(ASSOCIATED(HEAD))THEN
TAIL%NEXT=>CURRENT
CURRENT%PREV=>TAIL
NULLIFY(CURRENT%NEXT)
TAIL=>CURRENT
NULLIFY(CURRENT%NEXT)
NULLIFY(CURRENT%PREV)
ELSE
*EMPTY LINKED LIST
HEAD=>CURRENT
TAIL=>CURRENT
NULLIFY(HEAD%NEXT)
NULLIFY(HEAD%PREV)
END IF
CURRENT%PERSON = NAMEIN
CURRENT%AGE = AGEIN

END DO
999 CONTINUE
*PRINT FROM HEAD TO TAIL
*POINT TO THE BEGINNING
PRINT EACH NODE
PRINT *,'PRINTING OUTPUT FILE'


DO WHILE(ASSOCIATED(CURRENT%NEXT))
PRINT *,CURRENT%PERSON
PRINT *,CURRENT%AGE
CURRENT => CURRENT%NEXT
END DO

*END OF PROGRAM

STOP
END
 
As far as I can see, your linked list is not linked from head to tail completely. One reason seems to me that you nullify HEAD and TAIL inside your input loop. And when you come to printout your data, CURRENT seems to point to the end of the list from the last input.

I would build the list the following way using your variables declarations:
Code:
nullify (HEAD)
nullify (TAIL)
nullify (CURRENT)
nullify (TEMP)
!-------- input structure
do while (.true.)
    read (1, *, iostat = irslt) NAMEIN
    if (iostat .eq. 0) read (1, *, iostat = irslt) AGEIN
    if (iostat .ne. 0) exit
!-------- allocate memory
    if (.not. associated (HEAD)) then    ! start new linked list
        allocate (HEAD, stat = irslt)
        if (irslt .ne. 0) then
            write (*,*) 'not enough memory'
            goto 9000   ! to end the program
        endif
        nullify (HEAD%NEXT)
        nullify (HEAD%PREV)
        TAIL => HEAD
    else        ! add element to linked list
        allocate (TAIL%NEXT, stat = irslt)
        if (irslt .ne. 0) then
            write (*,*) 'not enough memory'
            goto 9000   ! to end the program
        endif
        TEMP => TAIL
        TAIL => TAIL%NEXT
        nullify (TAIL%NEXT)
        TAIL%LAST => TEMP
        nullify (TEMP)
    endif
    TAIL%AGE = AGEIN    ! with the above allocations TAIL is allways the one to get input
    TAIL%NAME = NAMEIN
enddo
!----------------- printout
if (associated (HEAD)) then
    TEMP => HEAD
    do while (associated (TEMP)
        print *, TEMP%NAME
        print *, TEMP%AGE
        TEMP => TEMP%NEXT
    enddo
endif
!---------------- clear linked list
if (associated (HEAD)) then
    TEMP => HEAD
    do while (associated (TEMP))
        TEMP => TEMP.NEXT
        deallocate (HEAD)
        HEAD => TEMP
    enddo
    nullify (TAIL)
endif

I do not see that you would need the PREV-pointer in your structure. You could skip it if you do not sort your data in a tree structure and you do not want to work through your list backwards.

Usually three pointers (HEAD, TAIL, TEMP) are sufficient. You need a fourth only when you work through your list in two points at the same time, e.g. for searching through the list while you work on one of its items.

Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
WHY DOES EVERYTHING NEEDS TO BE UPPERCASE? I HATE UPPER CASE, IT'S SO ANNOYING AND DIFFICULT TO READ, MAKES THE LINES SEEM CLOSER TOGETHER, MORE CROWDED, TOTALLY NOT ERGONOMIC ENOUGH FOR ME; BESIDES, IT LIMITS YOU IN NAMING VARIABLES TAKING ADVANTAGE OF CAMELCASE, ETC. IF UPPERCASE WAS GOOD FOR YOU, ALL TEXTBOOKS WOULD BE WRITTEN IN UPPERCASE BEGINNING TO END.
 
That is because Fortran started life in a 5 or 6 bit character set which only had room for uppercase and no lowercase characters. If you're learning from a book, all the programs will still be in uppercase because they were traditionally in uppercase. Unless they tell you, you won't know that lowercase works as well.

The strange thing about Fortran is that you can put spaces in words and it is case agnostic. Fortran does not have reserved words. You don't really need camel casing so
Code:
Not Ice = NO TICE = notice
Leg End = legend
mId = MID
Do10inc = do 10 inc
The last one used to cause lots of problems in F66 and F77 if the coder did not use implicit none and declare all their variables.
 
xwb:

thanks....but it was a rhetorical rant...I know all of what you have said.

I am just complaining that it is 2012 and over 50 years later...nobody should be still using all uppercase.

Oh wait, maybe your one of your points would be that the source the OP may be learning Fortran from show code all in uppercase? I guess that's a possibility.

cheers

Germán
 
Germán,

I would doubt this. Pointers are possible in Fortran versions only, where the need for capital characters was a thing of the past for a long time allready.

Capital letters in code is one thing, but there are forums around where the use of capital letters in the post's text would be considered as shouting.

Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
Norbert:

This happens to me often...I am trying to be funny but something gets lost in the written form alone.

If it was I who read what I wrote and the form (all uppercase and a single paragraph) I would have gotten the joke and understood that the poster was simply trying to make a point along with a little demo of uppercase writing.

Hopefully, nobody got offended; if so, please accept my apology.

Germán
 
Germán,
seems, I should use smileys too. My post was not meant for you, because it is clear you know what you are doing. I perfectly understood your post as an example of how difficult this is to read.

I wanted to add just another aspect of using capital letters.

:)

Norbert

The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
I thing, uppercase is very often used in FORTRAN. For example look at these LAPACK sources - language keywords and variable names - everything is in uppercase except comments:

I'm working in shop where Cobol is still used for business logic and it's our internal standard to write COBOL programs in uppercase. Maybe it's a tradition, because it's legacy language or maybe it's better readable for the software reviewer. IMO with Fortran it's similar case - it's very old language too.

When I started programming in Basic and dBase II I got a programming book where language reserved words were written in uppercase and variables in lowercase and I used this method
Code:
DO WHILE condition
  myvar = ...
  ...
ENDDO
then later with using Pascal I changed to inverse method, i.e.:
Code:
while CONDITION do
begin
  MYVAR := ...
  ...
end
In that time there vere not editors with syntax highlighting available and this was good method to distinguish language symbols from other symbols. Now editors with syntax highlighting are used and it's not necessary.

When I started to use C /which is case sensitive/ everything changed and I used mostly lowecase to avoid errors.

Now I don't have problem to write in COBOL in uppercase and in other languages in lowercase, but I'm unhappy when I don't have editor with synax highlighting for that language :)

But for example I'm not using camelCase and I don't like it in variabe names like
Code:
myOwnVariable
I'm rather using simply lower_case
Code:
my_own_variable
For me it's better readable and I'm avoiding problems with case sensitive languages with accidentally changing lowercase to uppercase and vice versa.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top