- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I used:
CHARACTER(LEN=:), ALLOCATABLE:: LINE_IN,RUNFILE
ALLOCATE (CHARACTER(LEN=5000) :: RUNFILE,LINE_IN)
which the compiler accepts, but whenLINE_IN is passed to a routine when it is defined as
COMMAND_LINE*(*), the length seems to be 1, so I get an exception when I try to put something in it.
What is the correct way to do this?
Thanks
Neal Van Eck
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, further investigation uncovers the problem, for which I don't have a good solution.
When I make the allocation and set the string to 5000 blanks, I'm ok. Later I attempt to blank it out with the statement LINE_IN=' '.
But this no longer works, as the string is shortened to one character. So maybe I need to alwaysblank it to the maximum each time I want to use it?This is awkward as I then have to continually blank it before reading line after line into the string instead of just reading a new line over the last. There may be a way around this; does reading a line into it always reallocate the string? (inefficient?). Even when read by a subroutine that takes it as an argument?
Right now, within the subroutine I'm almost always adding to the line (not wanting to change the allocated length). Does this then force a reallocation as well? The following line is typical of what causes trouble (says ILEN is beyond lenght od COMMAND_LINE.
21 ILEN=LEN_TRIM(COMMAND_LINE)+1
COMMAND_LINE(ILEN:ILEN)=' '
I don't want any reallocation; I want to allocate it once and have it remain that lenght.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So it doesn't work like allocating arrays. Are you saying there is another form I should be using? Is
CHARACTER(5000), ALLOCATABLE
legit? How do you then allocate it. Sorry to be obtuse, but the help files don't say anything about character string allocation in the evaluation version I installed (nor did they install in VS 2005), so I'm thrashing here a little trying to fgure it out. I can always just statically allocate large strings, but I wanted to go to the latest standard to take advantage of character stirng allocation, butperhaps it does me no good, and I lose facility going to V12.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok, Thanks, Steve.
That can be useful in other places for me. Another problem has cropped up, though.
It seems that one cannot use somthing like CHARACTER*32000 RECORD for a record of arbitrary length in a subroutine, where the record length is passed to the subroutine separately.It passes the compile but fails when referenced. Is there any way to accomplish this in the V12 ? I can't use an exact length vector here as the record source varies with different calling routines. Is this only a problem with bounds checking on?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok:
SUBROUTINE FPUT(DCB,RECORD,L,FATAL)
USE SPACE
IMPLICIT NONE
INTEGER(4) IO_STATUS,L
INTEGER(4), PARAMETER:: ICR=13,LF=10
TYPE (FCB) DCB
CHARACTER RECORD*32767
LOGICAL FATAL
IF (DCB%RECFM .NE. 0) THEN !RECFM=F
WRITE(DCB%HANDLE,IOSTAT=IO_STATUS) RECORD(1:DCB%LRECL)
ELSE !RECFM=U
WRITE(DCB%HANDLE,IOSTAT=IO_STATUS) RECORD(1:L),ACHAR(ICR),ACHAR(LF)
ENDIF
IF (IO_STATUS.NE.0) THEN
CALL FERROR(FILES(DCB%INDEX)%DSNAME,IO_STATUS)
FATAL=.TRUE.
ENDIF
END
The record can be anything the calling programs need to write--from a simple text line to a data output record. In the case that cropped up, the calling programmed passed string of length 512 characters with l=36. It seems to work in release mode without bounds checking on, but I haven't checked allt he output yet.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[fortran]subroutine fput (DCB,RECORD,L,FATAL) ... INTEGER, INTENT(IN) :: L INTEGER(1), INTENT(IN), DIMENSION(L) :: RECORD !DEC$ ATTRIBUTES NO_ARG_CHECK :: RECORD ... WRITE(DCB%HANDLE,IOSTAT=IO_STATUS) RECORD, ACHAR(ICR),ACHAR(LF) ...[/fortran]An alternative using only standard code is to pass C_LOC(record) to an argument that is of type C_PTR (from ISO_C_BINDING) and then use C_F_POINTER to "cast" it to something of the desired type and size.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Why don't you simply use the following declaration?
CHARACTER(*) RECORD
LEN(RECORD) gives youN if the calling programs passes a character declared with CHARACTER(N) RECORD so you also can test fort toolarge L or DCB%RECFM inside FPUT.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That's what I ended up doing....I can't remember why I had it the original way--lost in time.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page