Jump to content

Update a configuration file: Difference between revisions

(→‎{{header|Fortran}}: Approach the exclusion of SeedsRemoved.)
Line 574:
WRITE (6,FRUIT)
END</lang>
Most of which is support stuff. The requirement is to declare a NAMELIST naming the variables of interest, then READ or WRITE using just the name of the NAMELIST. JustOnly three statements, four if the file OPEN is counted. The result is a file in a standard layout.
<pre>
&FRUIT
Line 587:
Input allows for a comma-separated list of assignments and the names may appear in any order. If a name appears more than once, each assignment will be accepted so that the last one counts. Names can be omitted - if so, the corresponding variable will be unaffected by a READ. It would be nice if, the variable having been declared in CamelStyle, the name would be printed that way, but alas. F90 introduces the ! character as an "escape" comment and this is recognised in the NAMELIST input, outside of text literals of course.
 
To remove the SeedsRemoved entry is straightforward, depending on context. If its name is removed from the NAMELIST then it will no longer be written. The parameter file could of course be edited before being read back in, perhaps by a human, or by the installation process of the new version, or by the new version first finding the unwanted line, backspacing the file one record and writing the right number of spaces to wipe it without changing the length of a record - though this ploy may not be available if the filesystem offersprovides limited support. If however a new version of the programme is expected to read the old version's parameter file, then there will be trouble asbecause an unknown name (or an array index out of bounds, but not a CHARACTER variable being shorter than the supplied text) will provoke an I/O error and the run will crash. This can be avoided via the ERR = ''label'' option in the READ statement, however entries after the erroneous one will not be processed.
 
In a more general situation, it is helpful to have a routine that reads the NAMELIST style input and isolates the assignments so that each can individually be written to a scratch file in the NAMELIST style (i.e. providing the block head and tail lines, though some Fortrans allow NAMELIST input from a text variable and without this requirement) whereupon if ERR is provoked during the READ, the troublesome entry can be displayed for user appreciation before continuing with any remaining assignments.
 
Otherwise, the old NAMELIST could be used for input, with the undesired value simply ignored within the new version of the programme. For output, a new NAMELIST would be devised omitting the unwanted name - the same variables can be named in more than one NAMELIST. However, every NAMELIST's name must be unique within a routine and this would be the new block header name. So, read the parameter file in one routine which declares the old NAMELIST, complete with the now unwanted name, but write it via another routine which declares the new NAMELIST using the same name but omitting the names of undesired variables. The wanted variables would be in COMMON, or with F90 onwards be common names in a MODULE, or one could mess with parameter lists. <lang Fortran> MODULE MONKEYFODDER
INTEGER FIELD !An I/O unit number.
CHARACTER*28 FAVOURITEFRUIT
LOGICAL NEEDSPEELING
INTEGER NUMBEROFBANANAS
CONTAINS
SUBROUTINE GETVALS(FNAME) !Reads values from some file.
CHARACTER*(*) FNAME !The file name.
LOGICAL SEEDSREMOVED !This variable is no longer wanted.
NAMELIST /FRUIT/ FAVOURITEFRUIT,NEEDSPEELING,SEEDSREMOVED, !But still appears in this list.
1 NUMBEROFBANANAS
OPEN(FIELD,FILE=FNAME,STATUS="OLD",ACTION="READ", !Hopefully, the file exists.
1 DELIM="QUOTE") !Expect quoting for CHARACTER variables.
READ (FIELD,FRUIT,ERR = 666) !Read who knows what.
666 CLOSE (FIELD) !Ignoring any misformats.
END SUBROUTINE GETVALS !A proper routine would offer error messages.
 
SUBROUTINE PUTVALS(FNAME) !Writes values to some file.
Naturally, a parameter file could contain data in whatever format desired: such a file could be read and its components extracted via suitable code then written in the NAMELIST style to a scratch file and read back for the actual internalisation of values. The point of this is that a text name of a variable is associated with the actual computer variable via the NAMELIST facility, the programmer need not slog through some endless CASE statement on the names of the variables. This process would be reversed for output.
CHARACTER*(*) FNAME !The file name.
NAMELIST /FRUIT/ FAVOURITEFRUIT,NEEDSPEELING,NUMBEROFBANANAS
OPEN(FIELD,FILE=FNAME,STATUS="REPLACE",ACTION="WRITE", !Prepare a recipient file.
1 DELIM="QUOTE") !CHARACTER variables will be enquoted.
WRITE (FIELD,FRUIT) !Write however much is needed.
CLOSE (FIELD) !Finished for now.
END SUBROUTINE PUTVALS
END MODULE MONKEYFODDER
 
PROGRAM TEST !Updates the file created by an earlier version.
USE MONKEYFODDER
FIELD = 10 !This will do.
CALL GETVALS("Basket.txt") !Read the values, allowing for the previous version.
CALL PUTVALS("Basket.txt") !Save the values, as per the new version.
END</lang>
Whereupon the file now has
<pre>
&FRUIT
FAVOURITEFRUIT = "Banana ",
NEEDSPEELING = T,
NUMBEROFBANANAS = 48
/
</pre>
 
Naturally, a parameter file could contain data in whatever format desired, and might even recognise a semicolon (of all things!) as a comment starter: such a file could be read and its components extracted via suitable code then written in the NAMELIST style to a scratch file and read back for the actual internalisation of values. The point of this is that a text name of a variable is associated with the actual computer variable via the NAMELIST facility, the programmer need not slog through some endless CASE statement on the names of the variables. This process would be reversed for output.
 
But given that the NAMELIST protocol is available without difficulty, why would a hard-core fortranner bother for a Fortran programme?
1,220

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.