Prev: Software for plotting in Fortranxx?
Next: INTRINSIC STATEMENT for functions overloaded for user defined types
From: Bart Vandewoestyne on 15 Sep 2009 08:23 Hello all, After switching jobs and now mainly being programming in Octave, it is nice to be back for asking yet another questions here to good old clf :-) I would like to read a configuration file that could look like this: nb_apples 3 my_weight 68.5 elephant_weight 4.6e3 smoking_allowed true name TestName nb_apples, my_weight, elephant_weight, smoking_allowed and name are variables (of the appropriate data type) in my Fortran 95 program. During initialization of my program, I want to read the config file and assign the variables the values that are specified in the config file. Currently, I only work with integers and real numbers (no logicals or character arrays yet) and I read my datafile like this: read(unit=1, fmt=*, iostat=ios) variable_name, variable_value where variable_name is a character array and variable_value is being read as a real. Using a very long switch/case statement, I then assign the value to the variable depending on what i read in variable_name. If I have an integer variable, I simply floor the real number and then assign the value. So for now, I use 'little tricks' and can't work with strings. Now... something inside of me tells me there's a better way that would also allow me to assign logicals and strings. Therefore, I would have to be able to read *only* variable_name, then use a switch/case statement to decide what variable I'll have to assign, and once i know what variable I'm working with, I could read the second part of the line and assign it to the variable of the correct data type. My question is then: if a line in my config file consists of two things separated by whitespace, how do I read the first thing as a character array and then a bit later the second thing of the appropriate data-type? Thanks, Bart -- "Share what you know. Learn what you don't."
From: Reinhold Bader on 15 Sep 2009 08:58 Hello, It appears to me that the BACKSPACE(<unit>) statement should do the job. There is a restriction in place which says backspacing over list-directed or namelist-written output is not possible, but I assume you're not writing to your input file in one of these modes on the same unit. Here's a sample: implicit none character(len=10) :: type logical :: ll integer :: il real :: rl open(unit=22, file='BBB', form='formatted', status='OLD') do read(22, fmt=*, end=100) type backspace(22) if (adjustl(type)=='real') then read(22, fmt=*) type, rl write(*, *) 'rl = ', rl else if (adjustl(type)=='integer') then read(22, fmt=*) type, il write(*, *) 'il = ', il else if (adjustl(type)=='logical') then read(22, fmt=*) type, ll write(*, *) 'll = ', ll else read(22, fmt=*) type write(*,*) 'Not covered' end if end do 100 continue close(22) end Regards Reinhold
From: Arjen Markus on 15 Sep 2009 09:02 On 15 sep, 14:23, Bart Vandewoestyne <MyFirstName.MyLastN...(a)telenet.be> wrote: > Hello all, > > After switching jobs and now mainly being programming in Octave, > it is nice to be back for asking yet another questions here to > good old clf :-) > > I would like to read a configuration file that could look like > this: > > nb_apples 3 > my_weight 68.5 > elephant_weight 4.6e3 > smoking_allowed true > name TestName > > nb_apples, my_weight, elephant_weight, smoking_allowed and name > are variables (of the appropriate data type) in my Fortran 95 program. > During initialization of my program, I want to read the config > file and assign the variables the values that are specified in the config > file. > > Currently, I only work with integers and real numbers (no > logicals or character arrays yet) and I read my datafile like > this: > > read(unit=1, fmt=*, iostat=ios) variable_name, variable_value > > where variable_name is a character array and variable_value is > being read as a real. > > Using a very long switch/case statement, I then assign the value > to the variable depending on what i read in variable_name. If I > have an integer variable, I simply floor the real number and then > assign the value. So for now, I use 'little tricks' and can't > work with strings. > > Now... something inside of me tells me there's a better way that > would also allow me to assign logicals and strings. Therefore, I > would have to be able to read *only* variable_name, then use a > switch/case statement to decide what variable I'll have to > assign, and once i know what variable I'm working with, I could > read the second part of the line and assign it to the variable of > the correct data type. > > My question is then: if a line in my config file consists of two > things separated by whitespace, how do I read the first thing as > a character array and then a bit later the second thing of the > appropriate data-type? > > Thanks, > Bart > > -- > "Share what you know. Learn what you don't." You can read the line in a single string and then split it into the two items: integer :: ivalue character(len=100) :: line, keyword read( 10, '(a)' ) line ! ! Identify the keyword and thus the type of data ! read( line, * ) keyword if ( keyword == "nb_apples" ) then ! ! Integer value ... ! read( line, * ) keyword, ivalue endif ! And so on Regards, Arjen
From: Bart Vandewoestyne on 15 Sep 2009 09:12 On 2009-09-15, Arjen Markus <arjen.markus895(a)gmail.com> wrote: > > You can read the line in a single string and then > split it into the two items: > > integer :: ivalue > character(len=100) :: line, keyword > > read( 10, '(a)' ) line > ! > ! Identify the keyword and thus the type of data > ! > read( line, * ) keyword > > if ( keyword == "nb_apples" ) then > ! > ! Integer value ... > ! > read( line, * ) keyword, ivalue > endif > > ! And so on > > > Regards, > > Arjen Thanks Arjen. In the meanwhile, I was able to program myself my own proof of concept: program config_reader character(len=20) :: variable_name character(len=20) :: variable_value character(len=20) :: name integer :: nb_apples real :: my_weight, elephant_weight logical :: smoking_allowed integer :: mysize open(unit=1, file="test.dat", action="read") do read(unit=1, fmt=*, iostat=ios) variable_name, variable_value if (ios /= 0) then exit end if if (variable_name == "nb_apples") then read(variable_value, fmt=*) nb_apples print *, "nb_apples = ", nb_apples end if if (variable_name == "my_weight") then read(variable_value, fmt=*) my_weight print *, "my_weight = ", my_weight end if if (variable_name == "elephant_weight") then read(variable_value, fmt=*) elephant_weight print *, "elephant_weight = ", elephant_weight end if if (variable_name == "smoking_allowed") then read(variable_value, fmt=*) smoking_allowed print *, "smoking_allowed = ", smoking_allowed end if end do end program config_reader It seems like I'm doing it similar as you, but if anybody things this is a bad approach and has an even more elegant solution, i would be happy to hear! Up until now, I didn't know about the read(variable_value, fmt=*) trick! So *again*, I learned something from clf :-) Regards, Bart -- "Share what you know. Learn what you don't."
From: e p chandler on 15 Sep 2009 09:46 On Sep 15, 9:12 am, Bart Vandewoestyne <MyFirstName.MyLastN...(a)telenet.be> wrote: > On 2009-09-15, Arjen Markus <arjen.markus...(a)gmail.com> wrote: > > > You can read the line in a single string and then > > split it into the two items: > > > integer :: ivalue > > character(len=100) :: line, keyword > > character(len=20) :: variable_name > character(len=20) :: variable_value > > character(len=20) :: name > integer :: nb_apples > real :: my_weight, elephant_weight > logical :: smoking_allowed > integer :: mysize > > open(unit=1, file="test.dat", action="read") > do > read(unit=1, fmt=*, iostat=ios) variable_name, variable_value > if (ios /= 0) then > exit > end if > > if (variable_name == "nb_apples") then > read(variable_value, fmt=*) nb_apples > print *, "nb_apples = ", nb_apples > end if > if (variable_name == "my_weight") then > read(variable_value, fmt=*) my_weight > print *, "my_weight = ", my_weight > end if > if (variable_name == "elephant_weight") then > read(variable_value, fmt=*) elephant_weight > print *, "elephant_weight = ", elephant_weight > end if > if (variable_name == "smoking_allowed") then > read(variable_value, fmt=*) smoking_allowed > print *, "smoking_allowed = ", smoking_allowed > end if > > end do > > end program config_reader > > It seems like I'm doing it similar as you, but if anybody things this > is a bad approach and has an even more elegant solution, i would be happy > to hear! > > Up until now, I didn't know about the read(variable_value, fmt=*) trick! > > So *again*, I learned something from clf :-) > > Regards, > Bart Greetings. It's hard to believe that during all of the time you were an active member of this newsgroup, you never had need for "INTERNAL READ" or "INTERNAL WRITE" [smile]. It's one of the FAQs. One Fortran feature that I do not use but that might help you is a NAMELIST. Using it would involve changing the format of your config file. Essentially it sets up a group of named variables. Then you can specify name/value pairs in its particular format and Fortran takes care of the multi-way branch logic. -- Elliot
|
Next
|
Last
Pages: 1 2 3 4 5 6 7 Prev: Software for plotting in Fortranxx? Next: INTRINSIC STATEMENT for functions overloaded for user defined types |