- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hopefully an easy question, consider the code snip:
character(20) :: gbuf write(gbuf,1) flt,char(0) 1 format(f10.3,A)
Given format 1 is used many times it would be neater if the null character termination was in the format rather than the write. I just spend a few minutes scratching my head and googleing.... Any ideas?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Answering my own question.....
1 format(f10.3,'\0')
Seems to do the trick......
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
app4619 wrote:
Answering my own question.....
1 format(f10.3,'\0')Seems to do the trick......
I think the above may be a bug. However
1 format(f10.3, '\0'C)
would be correct.
as well as
1 format(f10.3, ''C)
(two ' characters)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A good spot Jim but we are both wrong the '\0' literally a \ and a 0 whilst if you make it a C string with the \0'C the complier throws its teddy out of the pram - error #6186: This character is not valid in a format list.
Any more ideas anyone????
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You left us in the dark as to what the purpose of the null is, but here is my attempt:
character(7) :: fmt = '(f10.3)' character(20) :: gbuf real :: flt = 3.142 integer :: i gbuf(11:11)=char(0) write(gbuf(1:10),fmt)flt write(*,'(20(1x,Z2))')(gbuf(i:i),i=1,len(gbuf)) end
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What I was doing was putting numeric data into strings to throw at Windows sdk routines for dialog boxes. Generally these must be null terminated as the sdk is setup for C++. I was looking for a neater way rather than writing a char(0) or concatenating to the string gchar(1:n)//char(0). My earlier post is wrong - see below
1 format(f10.3,'\0'C)
write(gchar,1) flt ! works
write(gchar,"(f10.3,'\0'C)") flt !fails-error #6186: This character is not valid in a format list.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As you may have noted, I placed the null into gbuf(11:11) and exposed only the substring gbuf(:10) to the Fortran I/O runtime; this was intended to keep the null out of reach of any format string checking code in the runtime.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes I noted that, for my purposes the 1 format.... style works fine and suits my purposes for being short and clear.
thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
app4619 wrote:
A good spot Jim but we are both wrong the '\0' literally a \ and a 0 whilst if you make it a C string with the \0'C the complier throws its teddy out of the pram - error #6186: This character is not valid in a format list.
Any more ideas anyone????
program NULL implicit none character(10) :: funk funk='abc\0def' print *,funk funk='abc\0def'C print *,funk end program NULL abc\0def abc def
I see no teddy
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Curious:
program NULL implicit none character(10) :: funk funk='abc\0def' print *,funk funk='abc\0def'C print *,funk print 1,'abc', 'def' 1 format(a3,'\0',a3) print 2,'abc', 'def' 2 format(a3,'\0'C,a3) end program NULL abc\0def abc def abc\0def abcdef
Space between in 2nd line, not in 4th line
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
I see no teddy
Jim Dempsey
My post was misleading I corrected myself at #6
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
program Console3 implicit none integer :: ival, l1 character(len=8) :: gbuf1, gbuf2 1 format(i4,'\0'C) 2 format(i4,A) do l1=1,len(gbuf1) ! fill strings with something gbuf1(l1:l1)='@' gbuf2(l1:l1)='@' enddo ival=1234 write(gbuf1,1) ival write(gbuf2,2) ival,char(0) !now check the results open(1,file='test.txt',status='unknown') write(1,*) iachar('@') do l1=1,len(gbuf1) write(1,*) l1,iachar(gbuf1(l1:l1)),iachar(gbuf2(l1:l1)) enddo ! 64 ! 1 49 49 ! 2 50 50 ! 3 51 51 ! 4 52 52 ! 5 32 0 space char, null char ! 6 32 32 ! 7 32 32 ! 8 32 32 end program Console3
So the Gbuf2 version works and the Gbuf1 version fails. Is there a valid/working option for format 1? To me it is better to have the null char in the format rather then remembering at add a char(0) to the end of every buffer write in this instance.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Do you have to use a format statement? Format specifications in character strings are much better, in that they can be built using constant expressions (that ultimately result in something of character type) and can be given a name that is a bit more descriptive.
Unfortunately, I think the compiler is being a bit overly critical of character edit descriptors that have NULL's in them (I think this is a compiler bug - because it is useful to do this occasionally - your use case for example. But you can work around that.
PROGRAM FormatSpecWithNull IMPLICIT NONE ! You should be able to do this, but the compiler (erroneously, IMHO) ! incorrectly complains. Note the ACHAR putting a NULL in the ! character string edit desscriptor. CHARACTER(*), PARAMETER :: fmt_spec_ = "(F10.3,'" // ACHAR(0) // "')" ! So we'll obsfuscate the format spec such that the compiler can't see ! what we are doing at compile time. CHARACTER(:), ALLOCATABLE :: fmt_spec ! For testing. CHARACTER(11) :: string !***************************************************************************** fmt_spec = fmt_spec_ ! Just for checking - note the NULL won't show properly. PRINT "('The format spec is ""',A,'""')", fmt_spec ! Define string so that we can see what it changes to. string = REPEAT('x', LEN(string)) WRITE (string, fmt_spec) 9.0 ! 6661 ! Is there a NULL where we expect? PRINT "('The character at position 11 has IACHAR of ',I0)", & IACHAR(string(11:11)) END PROGRAM FormatSpecWithNull
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No I do not need to have a format statement, I did some examples using formats built into strings but they all failed. Your sample is quite interesting, I think the key in your example is the allocate, to cheat the compile time behaviour.
This seems like a sledge hammer to crack a nut though, I am not sure that the Intel compiler is being very friendly in this instance.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
App4619,
Experimenting with your program a bit more yields
program NULL implicit none integer :: ival, l1,ival2 character(len=8) :: gbuf1, gbuf2 1 format(i4,'A\0A'C,i1) 2 format(i4,A) do l1=1,len(gbuf1) ! fill strings with something gbuf1(l1:l1)='@' gbuf2(l1:l1)='@' enddo ival=1234 ival2 = 5 write(gbuf1,1) ival, ival2 write(gbuf2,2) ival,char(0) !now check the results open(1,file='test.txt',status='unknown') write(1,*) iachar('@') do l1=1,len(gbuf1) write(1,*) l1,iachar(gbuf1(l1:l1)),iachar(gbuf2(l1:l1)) enddo end program NULL 64 1 49 49 2 50 50 3 51 51 4 52 52 5 65 0 6 53 32 7 32 32 8 32 32
Note, that not only is the null omitted (2nd character of embedded text), but also the 3rd character of the embedded text of the format is omitted. It would seem that the code writer of the affected piece of code is using the string as if it were a C string. I guess one could argue that "you said it was a C string", and took that to interpret the string is terminated by non-inclusive NULL. Changing 1 format to..., yields
... 1 format(i4,'A'\\''C\\'A',i1) ... 64 1 49 49 2 50 50 3 51 51 4 52 52 5 65 0 6 65 32 7 53 32 8 32 32
In the above, the NULL is stripped (but 2nd A is present).
It mat be time for someone familiar with the standards with respect to the edit descriptors containing unusual characters, such as NULL, TAB, Escape Sequences, other...
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't recommend trying to force a NUL into a format string. Find another solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm not sure if somewhere above is the suggestion to initialize your
format with CHAR(0), but that would appear to work only if you specify the
exact number of characters to write to, or else the unwritten-to storage
bytes finish up filled with codes for blank characters. It would appear much
simpler to bite the bullet and just concatenate the CHAR(0) when needed.
CHARACTER(256) MYSTRING REAL*8 NUMBER INTEGER(4) I DO I=1,256 MYSTRING(I:I)=CHAR(0) END DO NUMBER=1234.567D+89 WRITE(MYSTRING(1:12),'(D12.3)') NUMBER PAUSE ! at this point, MYSTRING still has CHAR(0) in all places except the first 12 DO I=1,256 MYSTRING(I:I)=CHAR(0) END DO NUMBER=1234.567D+89 WRITE(MYSTRING,'(D12.3)') NUMBER PAUSE ! At this point, MYSTRING has code for blank (02) in all places after the first 12
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Anthony:
You are correct! The 2 methods I already use are //char(0) or to write char(0) to an A format as the last i/o item for an internal write. It just happens I am converting some window dialogs from IFLOGM to using the Windows sdk direct and there were many strings created with formatted writes of real data. Adding a terminator NUL to the format would seem a logical step i.e. the change in one place rather than many. The reality is that adding a NUL within a format is not practical and indeed the Ifort compiler does not seem to work in a consistent way IMO.
@Steve "I don't recommend trying to force a NUL into a format string. Find another solution."
Based on the results above it is clearly foolish to try!!! Other solutions do exist, however, looking at the range of examples from a number of contributors, is the compiler behaving correctly and/or in a useful manner in this respect?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, it should not be allowing a format item that looks like a C string. I'll file a bug report about that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'd suggest creating a generic function call to the sdk library functions. One taking CHARACTER*(*) arguments, and the other taking C_PTR arguments. The C_PTR one need only have the attribute declarations to match the signature of the sdk library function.
The CHARACTER*(*) functions can make a copy, LENTRIM and append the null, then"call" the library function using the LOC of the temporary copy(s) of the arg(s).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Intel) wrote:
I don't recommend trying to force a NUL into a format string. Find another solution.
:(
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page