- 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
Re: Anthony's post (#17):
This is exactly the behaviour that we would expect - writing to a string without specifying the length should blank pad any unused characters. To leave them unchanged would cause other undesirable consequences.
After writing to the string, if the length is not known, why not use TRIM and concatenate CHAR(0)?
David
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
David White wrote:
After writing to the string, if the length is not known, why not use TRIM and concatenate CHAR(0)?
Indeed that is the option but my point was that I fancied just changing the format (not happening :-( ! ) in one place rather than adding two operations in several places.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
How about this:
module foo contains function C_STR(F_STR) result (ret) character*(*) :: F_STR character(len=MIN(LEN_TRIM(F_STR)+1,LEN(F_STR))) :: ret integer :: I I = LEN_TRIM(F_STR) if(I .lt. LEN(F_STR)) then I = I + 1 else write(*,*) "Insufficient room in string - truncating last character" endif F_STR(I:I) = CHAR(0) ret = F_STR end function C_STR integer(4) function Win32function(gbuf) character*(*) :: gbuf write(1,*) iachar('@') do l1=1,len(gbuf) write(1,*) l1,iachar(gbuf(l1:l1)) enddo Win32function = 0 end function Win32function end module foo program NULL use foo implicit none integer :: ival, l1 character(len=8) :: gbuf 1 format(i4,A) do l1=1,len(gbuf) ! fill string with something gbuf(l1:l1)='@' enddo ival=1234 write(gbuf,1) ival !now check the results open(1,file='test.txt',status='unknown') ! without NULL if(Win32function(gbuf) .ne. 0) then write(*,*) 'Error' endif ! with NULL if(Win32function(C_STR(gbuf)) .ne. 0) then write(*,*) 'Error' endif close(1) end program NULL 64 1 49 2 50 3 51 4 52 5 32 6 32 7 32 8 32 64 1 49 2 50 3 51 4 52 5 0
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1 |
1 format (f10.3, '\0' ) |
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Vidura D. wrote:
1 1 format(f10.3,'\0')
That doesn't work. '\0' is simply those two characters. This isn't C. While you can, at present, put '\0'C in a FORMAT statement, that's a bug that will be fixed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Im sorry could you please tell me the language in the problem. I havent used c in this way.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ramith, what is your question?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Now that this old thread is revived, note that a NUL character is ''C, not '\0'C -- the latter is two NULs. But the solution has been found:
program p implicit none character(20) gbuf character(11) fmt real flt integer i 1 format(f10.3,1H1) fmt = '1234567890'//achar(0) read(fmt,1) flt flt = 1234.567 write(gbuf,1) flt do i = 1, len(gbuf) write(*,'(i2,1x,a1,1x,i2)') i, merge(gbuf(i:i),'.', & iachar(gbuf(i:i))>=32),iachar(gbuf(i:i)) end do end program p
Output with ifort:
1 32 2 32 3 1 49 4 2 50 5 3 51 6 4 52 7 . 46 8 5 53 9 6 54 10 7 55 11 . 0 12 32 13 32 14 32 15 32 16 32 17 32 18 32 19 32 20 32
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My above solution lacked elegance in that it required the user to painstakingly adjust the string to be read into the hollerith descriptor whenever he changed the format. This can be fixed:
program p implicit none character(20) gbuf character(80) fmt real flt integer i 1 format(f10.3,1H~) flt = 1.0 write(fmt,1) flt forall(i=1:len(fmt),fmt(i:i)=='~') fmt(i:i) = achar(0) read(fmt,1) flt flt = 1234.567 write(gbuf,1) flt do i = 1, len(gbuf) write(*,'(i2,1x,a1,1x,i2)') i, merge(gbuf(i:i),'.', & iachar(gbuf(i:i))>=32),iachar(gbuf(i:i)) end do end program p
Same output as before, but the Fortran processor is now automatically taking care of replacing any infrequently used character, such as '~', with ASCII NUL in the format.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, the solution of reading into a hollerith edit descriptor doesn't work in gfortran, which seems to me to be a lack of understanding of hollerith edit descriptors by the gfortran developers. It turns out that in a format statement like 1 FORMAT(1H#) gfortran allows the programmer to use any character where instead of the # except for 0,10,13, and 26. I guess 0 and 10 throw parsers written in C for a loop, and 13 being carriage return also could interfere with parsing, and 26 is DOS end of file. Similar for ifort, except the list is 0, 3, 10, and 26. I don't know why 3 should be such a problem.
Both gfortran and ifort have no problem with format strings such as character(*), parameter :: fmt0 = '(1H'//achar(0)//')' the hollerith edit descriptor works in both compilers for all 256 characters, unlike "('"//achar(0)//"')" so it looks like inserting the objectionable character by concatenation into the hollerith edit descriptor of a format string is the easiest way to do it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can insert the NUL character that way but the results may be unpredictable. If you need to write a NUL, put it in the I/O list and transfer using an A format.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The point of the thread was to somehow avoid having to append the ASCII NUL by hand every time and have the FORMAT do it. Of course, the ifort docs (in the old days ifort put the documentation somewhere under the Start menu, but now I have to search for it in my installation. Did I miss something in the install phase?) state that the string following the H edit descriptor consists of printable ASCII characters, so I am relying on undocumented behavior. Reading the page on H editing, one might almost think that this program:
program p implicit none character(5) fmt character(5) data fmt = '(1H1)' write(data,fmt) data(1:1) = '2' read(data,fmt) write(*,fmt) 1 format(1H1) write(data,1) data(1:1) = '2' read(data,1) write(*,1) end program p
would print '2' on both lines, but it prints '1' on the first line and '2' on the second. Possibly the '2' character is written into some address on line 8 of the program, but the address must then be a temporary address and not a pointer into the fmt variable.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The documentation is still under the Start menu (Intel Parallel Studio XE 2015 > Documentation), or you can get it through Help in Visual Studio.
RO, you shouldn't be encouraging bad habits... Reading into an H format is FORTRAN 66 and is nonstandard from F77 onward. In your example, the first READ modifies the internal compiled version of the format derived from fmt, but not into the variable fmt itself. As you note, it is thrown away afterward. We do still support reading into an H format in a FORMAT, as was allowed in F66, as the second case illustrates.
There is no standard-conforming way to embed a NUL (or any other nonprinting character) in a format.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Under Start > Intel Parallel Studio XE 2015 all I've got is 'Intel Premier Support', 'Intel Software Manager', 'Compiler and Performance Libraries', and 'Visual Studio Integrations'. No 'Documentation'. How can I fix this situation? If the documentation noted that on input, the characters are read into the H edit descriptor if it appeared in a FORMAT statement, and are simply skipped over otherwise, it may more effectively inform the user on what should be expected with my example from quote #33.
I hope you anticipate a certain amount of giggling from the back of the classroom when you admonish a user who calls himself 'Repeat Offender' not to encourage bad habits :)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Interesting. Documentation should be there. And under that would be links to the various component documentation files, including "C:\Program Files (x86)\Intel\Composer XE 2015\Documentation\en_US\compiler_f\index.htm" You could create a shortcut on your desktop with this if nothing else. I will ask the writers to add "when it appears in a FORMAT statement" to that text.
And yes, I definitely had my tongue in cheek when I wrote that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
RO thanks for the interest in looking for a solution. I long back concluded that there was no working/legal solution and just adopted the working (but more tedious) solution I was trying to shortcut in the original post.
I have to say I did not consider Holleriths, however H editing disappeared from my repertoire many years back, it surely must have been deprecated 20+ years ago??
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Reading into an H edit descriptor disappeared in F77. The H edit descriptor itself was deprecated in F90.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
C strings in a FORMAT will be disallowed in a future major release of the compiler.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
From purely academic interest what will happen where the non-printing char is embedded in a string used as a format? Will that not always been detected or will it be a run-time issue?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If the format is a variable that has to be interpreted at run-time, you should get a run-time error when the invalid character is encountered. The problem here had to do with syntax, not an invalid character. I just did a test where I embedded a NUL in a character constant in a run-time format, and that was fine.
character (80) f f = "('ABC','"//CHAR(0)//"','DEF')" print f end
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve, the following modification of your snippet brings out a discrepancy:
character (80) f f = "('ABC','"//CHAR(0)//"','DEF')" print f print "('ABC','"//CHAR(0)//"','DEF')" end
The second line of output shows ABCDEF (the NUL is missing). I have not checked what the standard requires in this case.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page