sk8terg1rl wrote:
> Hi Dick, thanks for replying,
>
> On 8 Apr, 19:28, Dick Hendrickson att.net> wrote:
>> sk8terg1rl wrote:
>>> Hi group, Happy Easter! :-)
>>> I've been trying to read a line in an input file that has a mix of
>>> characters & integers. The format can be assumed to be characters for
>>> 15 columns and a binary string of unknown/variable length.
>>> The format of the input file 'test.txt':
>>> |-CHARAC15-------|-----------INTEGER-----------.....
>>> Binary string = 010101010 ....
>>> The following test program fails:
>>> Program test_format
>>> Implicit None
>>> Integer:: buffer
>>> Integer, allocatable:: vector(:)
>>> Character:: a15*15
>>> buffer=1000
>>> Allocate (vector(buffer))
>>> Open (1,file='test.txt')
>>> Read (1,*) a15, vector(1:10)
>>> Print *, a15
>>> print *, vector(1:10)
>>> End program test_format
>>> Some questions...
>>> - If I change the Read statement to Read (1,'(a15,10000i1)') it works.
>>> However I want to read it in as free format if possible, so that if
>>> the binary string is longer than 10000 bits, my program won't cause
>>> problems.
>> It's not directly possible in free format because something like
>> 010101 is an integer and there is no way for the processor to know
>> that you mean 6 "1 bit" numbers, rather than a 6 digit decimal
>> number. There are two general approaches to consider.
>
> Yes. I was having an "engineering moment" ;-)
>
> I originally posed the question as delimited binary bits (space-bit-
> space format). I would prefer a concatenated binary string for
> compactness with simple text editors like vi, hence me rephrasing it
> to bit-bit-bit format :-)
>
>> 1) declare a huge character string, bigger than you will ever need
>> and "read" through it character by character.
>> something like
>> character (len=1000000000000000000) :: x !or maybe smaller ;)
>> x=' '
>> read(...) x
>> do i = 1,10000000000000000000000
>> if(x(I:I) == '1') vector(i) = 1
>> if(x(I:I) == '0') vector(i) = 0
>> if(x(I:I) == ' ') exit
>> enddo
>> here, I will be the actual length
>
> Why did you do x(I:I) instead of x(I)?
Because I choose to make X be a single character string with a
length of 100000000000000000 characters. Fortran character
variables are very different from C character strings. Each
Fortran character variable can have its own length, and it doesn't
have to be 1. It's not an array of 100000000000000000000 elements.
(I should have used a length that is easier to type, ;() The
X(I:I) notation means the Ith character. In general, you can
use X(I:J) to mean all of the characters from position I through
J and that is treated as a single thing (with a length of J-I+1).
You could also write an array or elements of any length. For this
problem, a character length of 1 would be the best choice.
Something like
character(len=1), dimension(10000000) :: X
[there's other syntax for this that is somewhat terser, but
spelling out all of the words makes it easier to understand.]
Then, you would refer to an element of the array as X(I),
which is a character thing of length 1. With the array
notation there is no direct way to make a longer thing than a
single character. The major drawback to using an array for this
problem (as I originally understood it) is that when you try to
read an array with something like
read(...) x
the processor will attempt to read in the entire array and generate
an error when it comes to the end of the actual data line (unless
it happens to be 10000000 "bits" long). If you try to read in
a single character variable (the len=1000000000000000 case) the
processor will blank fill the variable if it comes to the end of
the data line.
>
>> 2) use non advancing I/O and read each digit with an I1 format.
>> You'll need to add ADVANCE='NO' to the read. If you can't find
>> out about non-advancing I/O, ask here and several people will
>> explain it.
>
> I will Google it up as something potentially useful to keep in mind. I
> need to code and (grr...inevitably!) debug a working program quite
> soon so I will go for the easy explicit format for now. As I hope to
> expand its flexibility in the future, this will become handy to
> know...
>
>> With either one, you'll need to make VECTOR be big enough before you start.
>>
>>> - Similarly for writing out large arrays...I don't want to have to
>>> specify "Write (1,'(a15,10000i1)')" as arrays larger than 10000 would
>>> get truncated.
>> Formats revert when they come to their end and there are still
>> items in the I/o list. You could do something like
>> write (1, '(a15, 100i1, (15x,100i1)) title, vector
>> that will write out the title and first 100 digits one the first
>> line and then 15 blanks and the next 100 digits on the second and
>> third and ... nth line. It will use as many lines as necessary
>> and write out the odd number one the last line.
>>
>>> - Is there an easy way to get the program to initially parse test.txt,
>>> look for the widest binary string length, and automatically allocate
>>> "buffer" to match that size?
>> No easy, if there are many lines you need to read them in one at a time
>> into a huge string and look for the longest line. you can probably do
>> something like
>> lentrim(x)-15
>> which will tell you how many digits there are on one line and then
>> find the max of this over all of the lines.
>
> Linux's wc would work too. My code is written for Linux systems, and
> makes use of some Linux-specific commands. I program it in a Windows
> box for aesthetic reasons and scp it over - I'm quite comfortable with
> Compaq Visual Fortran's editor (I haven't found an editor that is very
> Fortran-friendly in Linux yet).
>
> In my Windows compiler's manual, it is len_trim(x). Still, another
> handy intrinsic function to know.
Oops, I'm off playing with my granddaughgter, so I guess I had
a senior moment. It should be len_trim.
Dick hendrickson
>
>
>> Hope this helps
>
> It does, thanks again :-)
>
> skate xx
>