|
|
 |
 |
 |
 |
Fortran Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
newbie question for reading input file
Hi, I don't know a lot about Fortran. The following really puzzled me: My code below reads an input file <fortran_code> READ(IN,900) ANAME,ELEV,ALAT,PRC,ODS,OSS,SS,UPS,RDCOS,AEC 900 FORMAT(5A4,2F5.0,1X,A4,2X,A3,2X,A3,1X,A4,4X,A4,A2,1X,A4,1X,A4) WRITE(*,*) 'ANAME=',ANAME WRITE(*,*) 'ELEV=',ELEV WRITE(*,*) 'ALAT=',ALAT WRITE(*,*) 'PRC=',PRC WRITE(*,*) 'ODS=',ODS WRITE(*,*) 'OSS=',OSS WRITE(*,*) 'SS=',SS WRITE(*,*) 'UPS=',UPS WRITE(*,*) 'RDCOS=',RDCOS WRITE(*,*) 'AEC=',AEC </fortran_code> <input_file> S. PRAIRIE CRK UPR 1158. 47.1 NONE YES SUMS AVSE </input_file> The output from those WRITE statements above are like this: <output> ANAME= 1.0749562E+10 2.1609608E+11 160.2706 1.1015335E+13 1.3579762E-19 ELEV= 1158.000 ALAT= 47.10000 PRC= 3300.957 ODS= 1.3563156E-19 OSS= 1.7895340E-19 SS= 8.8189980E+11 UPS= 1.3563156E-19 1.3563156E-19 RDCOS= 1.3563156E-19 AEC= 3381.391 </output> The whole program runs successfully. But I really have several questions: 1. ANAME should be "S. PRAIRIE CRK UPR", why output is not? Similar question with variable SS, which should be "SUMS". 2. READ(IN, 900) has 10 variables, but 900 FORMAT(11 variables here). Does that mean last one ("1x, A4") is ignored? Thank you for your help.
www wrote: > My code below reads an input file > READ(IN,900) ANAME,ELEV,ALAT,PRC,ODS,OSS,SS,UPS,RDCOS,AEC > 900 FORMAT(5A4,2F5.0,1X,A4,2X,A3,2X,A3,1X,A4,4X,A4,A2,1X,A4,1X,A4) > WRITE(*,*) 'ANAME=',ANAME
(snip) This is Fortran 66 code, from before CHARACTER variables. You should change ANAME to CHARACTER*20 ANAME and read it with A20 format. That is better than continuing the Fortran 66 method, which would write it out with 5A4 format. Also, the other items with A format should also be changed to CHARACTER. Your FORMAT statement seems to have 15 items, I don't know which variables are arrays and might use more than one format descriptor. -- glen
www <w @nospam.com> wrote: > READ(IN,900) ANAME,ELEV,ALAT,PRC,ODS,OSS,SS,UPS,RDCOS,AEC > 900 FORMAT(5A4,2F5.0,1X,A4,2X,A3,2X,A3,1X,A4,4X,A4,A2,1X,A4,1X,A4) > WRITE(*,*) 'ANAME=',ANAME ... > <output> > ANAME= 1.0749562E+10 2.1609608E+11 160.2706 1.1015335E+13 > 1.3579762E-19 ... > The whole program runs successfully. But I really have several questions: > 1. ANAME should be "S. PRAIRIE CRK UPR", why output is not? Similar > question with variable SS, which should be "SUMS". You don't show the declarations. Declarations are *VERY* important. It is fairly common for people to seek help for problems that turn out to be in the declarations, which aren't shown. That appears to be the case here. Fortunately, this is a simple enough case that I can guess the important part. But for future reference, be aware that declarations are important. ANAME and SS are of type real (either by default or explicit declaration). That's why they print out as real values. You should ideally declare them to be character strings instead. This code uses a mixture of very old and newer features. The very old feature is using a real variable to store character values. That was the only way to do character data in Fortran 66 and earlier; there wasn't a character type. It became nonstandard in Fortran 77 (30 years ago), even though most f77 compilers, and many later ones as well, continued to support the old option. Using an "A" (character) format edit descriptor with a real variable is technically nonstandard. Anyway, even if you are using a compiler that supports the old Hollerith usage (that's what putting character data in noncharacter variables is called), that won't go well with using the newer feature of list-directed output formatting. (That's the second * in your write (*,*)). List-directed output formatting just sees a real variable, so it uses formatting appropriate for reals - not characters. If you are using Hollerith, you can't output it meaningfully with list-directed output. You have to use an explicit format with an appropriate "A" edit descriptor, just like you did for the input. Using character variables is better, though. > 2. READ(IN, 900) has 10 variables, but 900 FORMAT(11 variables here). > Does that mean last one ("1x, A4") is ignored?
First, a correction. The FORMAT doesn't have anything that corresponds directly to variables. It has edit descriptors that define fields that correspond to individual data items. For example, your first edit descriptor is 5A4. That defines 5 fields. It does *NOT* necessarily correspond to a single variable. Apparently your ANAME variable is dimensioned with size 5, so it uses all 5 fields. But that isn't so in general. The 5 fields could correspond to 5 separate variables. So, counting fields defined by your FORMAT, I see 15 fields, 5 from the 5a4, 2 from the 2f10.5, and 8 more. The X edit descriptrs don't count as defining field; they just skip columns. I see 15 values to go with these 15 fields. You have 10 variables; one is an array of 5 elements, one an array of 2 elements, and 8 are scalars (at least that's what I deduce, though you don't show the declarations). That seems to match. Hmm. Where did you get a count of 11 of anything from. I was assuming that you were just calling the 5a4 and 2f10.5 one thing each, but doing that I only come up with 10. Did you just miscount? (Easy to do). Anyway, the answer, after rephrasing in the right terms, is yes, that unused data edit descriptors at the end of the format are ignored, even though it doesn't look like you have that situation. -- Richard Maine | Good judgement comes from experience; email: last name at domain . net | experience comes from bad judgement. domain: summertriangle | -- Mark Twain
Richard Maine wrote: > You have to use an explicit format with an appropriate "A" edit > descriptor, just like you did for the input.
I see. Following outputs the string correctly: WRITE(*,"(5A4)") ANAME >> 2. READ(IN, 900) has 10 variables, but 900 FORMAT(11 variables here). >> Does that mean last one ("1x, A4") is ignored? > I see 15 values to go with > these 15 fields. You have 10 variables; one is an array of 5 elements, > one an array of 2 elements, and 8 are scalars (at least that's what I > deduce, though you don't show the declarations). That seems to match.
You are right. I have another question: <fortran_code> READ(IN,900) ANAME,ELEV,ALAT,PRC,ODS,OSS,SS,UPS,RDCOS,AEC 900 FORMAT(5A4,2F5.0,1X,A4,2X,A3,2X,A3,1X,A4,4X,A4,A2,1X,A4,1X,A4) WRITE(*,*) 'ALAT=',ALAT !!outputs "ALAT= 47.10000" WRITE(*,"(F5.0)") ALAT !!outputs "47." </fortran_code> <input_file> S. PRAIRIE CRK UPR 1158. 47.1 NONE YES SUMS AVSE </input_file> During READ, the descriptor for ELEV is F5.0, but the value stored in it after reading is 47.1. It seems F5.0 during READ does not have an effect, while during WRITE does. Could you kindly explain a little more? I think this is very important. It is "47.1", not "47.", used in the following computation. If it is "47.", the final computation result could be different.
www wrote: > READ(IN,900) ANAME,ELEV,ALAT,PRC,ODS,OSS,SS,UPS,RDCOS,AEC > 900 FORMAT(5A4,2F5.0,1X,A4,2X,A3,2X,A3,1X,A4,4X,A4,A2,1X,A4,1X,A4) > WRITE(*,*) 'ALAT=',ALAT !!outputs "ALAT= 47.10000" > WRITE(*,"(F5.0)") ALAT !!outputs "47." > </fortran_code> > <input_file> > S. PRAIRIE CRK UPR 1158. 47.1 NONE YES SUMS AVSE > </input_file> > During READ, the descriptor for ELEV is F5.0, but the value stored in it > after reading is 47.1. It seems F5.0 during READ does not have an > effect, while during WRITE does. Could you kindly explain a little more? > I think this is very important. It is "47.1", not "47.", used in the > following computation. If it is "47.", the final computation result > could be different.
The F5.0 descriptor specifies that the decimal point will be inserted effectively at the right of the data field, if it is not supplied. An explicit decimal point in the data over-rides the decimal point specification in th descriptor.
"www" <w @nospam.com> wrote in message news:f36nbv$ups$1@news.nems.noaa.gov... > During READ, the descriptor for ELEV is F5.0, but the value stored in it > after reading is 47.1. It seems F5.0 during READ does not have an effect, > while during WRITE does. Could you kindly explain a little more? > I think this is very important. It is "47.1", not "47.", used in the > following computation. If it is "47.", the final computation result could > be different.
On input with Fw.d, if the value in the record contains a decimal point, the value of d, the number of digits after the point, is ignored. This is not so on output ("Fortran 95/2003 Explained", Section 9.12.2). Regards, Mike Metcalf
In a previous article, www <w@nospam.com> wrote: <snip> >During READ, the descriptor for ELEV is F5.0, but the value stored in it >after reading is 47.1. It seems F5.0 during READ does not have an >effect, while during WRITE does. Could you kindly explain a little more? >I think this is very important. It is "47.1", not "47.", used in the >following computation. If it is "47.", the final computation result >could be different.
Decimal points in inpout have priority over specified format. If there is always 1 dp and you want to get rid of it, specify f4.0,1x instead of f5.0 Chris
www wrote:
(snip) > I see. Following outputs the string correctly: > WRITE(*,"(5A4)") ANAME
I had thought about writing this, but using Fortran 66 A format descriptors with a string constant format. It seems that the string constant arrived with Fortran 77, but I don't remember seeing it used until much later. > I have another question:
(snip) > During READ, the descriptor for ELEV is F5.0, but the value stored in it > after reading is 47.1. It seems F5.0 during READ does not have an > effect, while during WRITE does. Could you kindly explain a little more?
In the days of punched cards is was often used to save one column on the card. Input data in, for example, F5.2 format could be punched in five columns with an implied decimal point. CHARACTER*5 IN IN="12345" READ(IN,"(F5.2)") X will read 123.45 into X. It still might be used in disk files, but I don't know that anyone uses it for terminal input. (Why is it that you can't put character constants into READ statements?) -- glen
> (Why is it that you can't put character constants > into READ statements?)
Because you can't have any in internal WRITE statements, and thus allowing them in internal READs would have been an exception to a rule that was already complicated enough? Of course, not only can't you have character constants in such places, any non-assignable value (e.g., PARAMETERs, expressions, ...) is not admissable. Jan
Jan Vorbrggen wrote: >> (Why is it that you can't put character constants >> into READ statements?) > Because you can't have any in internal WRITE statements, and thus > allowing them in internal READs would have been an exception to a rule > that was already complicated enough? > Of course, not only can't you have character constants in such places, > any non-assignable value (e.g., PARAMETERs, expressions, ...) is not > admissable.
With that argument, you would also expect no expressions in I/O lists as in Fortran 66, which was changed in Fortran 77. It would seem about time to fix this one. -- glen
"Richard Maine" <nos @see.signature> wrote in message news:1hymcnm.1wsth4i3iw8l5N%nospam@see.signature... > If you are using > Hollerith, you can't output it meaningfully with list-directed output.
[?] -- write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, & 6.0134700243160014d-154/),(/'x'/)); end
James Van Buskirk <not_va@comcast.net> wrote: I'm not 100% certain how to interpret the "?". It occurred to me briefly that you might be offerring your signature as a counter-example. I'll play that game by saying that your signature doesn't strictly speaking use Hollerith, though I'll admit it has some relationship. On the theory that the "?" was instead a serious question about what I meant, I'll try to explain, though I'm not sure I can come up with a better explanation than the OP's example. This is really going to be little more than a repeat of that example, but with possibly confusing extraneous things omitted, and other bits elaborated. I apologize in advance for aiming the explanation a bit low. I'm sure that you know most (if not all?) of this, but I'm not sure which piece you might be missing, so I'm putting them all in. Hollerith is the practice of storing character data in non-character variables. Strictly speaking, it became nonstandard in f77. One simple example of defining a variable with a Hollerith value is real x data x/4halas/ Another example, much like that of the OP, is real x read (lun,'(a4)') x where the file might contain "alas" without the quotes. Neither of these are strictly standard in f77 or later.(Ok, the code isn't standard f66 either, but for unrelated reasons. I hate typing in all caps, and I didn't feel like making a separate format statement). In either case, the variable x has a Hollerith value "alas" (without the quotes). This makes the nonportable assumption that a real can contain 4 Hollerith characters; assumptions like that were one of the problems of Hollerith, but that's not the current point. If we now go to output x using list-directed output as in write (*,*) x then there is no reasonable way for the compiler to know that x contains a Hollerith value. (Sure, it is possible in theory, with a flag indicating whether the value is Hollerith or not, but I'll stick with my "no reasonable way"; I've never heard of a compiler doing anything even vaguely close.) So instead of printing anything like "alas", it will, alas, print some strange real value depending on the internal representations. If you want it to print "alas", you need something to tell the compiler to ingterpret the value in x as Hollerith. Using an explicit "a" edit descriptor will do that, as in write (*,'(a4)') x -- Richard Maine | Good judgement comes from experience; email: last name at domain . net | experience comes from bad judgement. domain: summertriangle | -- Mark Twain
James Van Buskirk wrote: > [?]
Welcome back, James. I had been wondering where you had gotten to. :o) cheers, paulv -- Paul van Delst Ride lots. CIMSS @ NOAA/NCEP/EMC Eddy Merckx
|
 |
 |
 |
 |
|