How do I create a space in a print statement? - format

I have some code that was previously working when I ran IDL on my Linux box. I'm not sure why the format has changed when I run IDL on my Windows box.
Specifically, it seems as if the problem is that a print statement is not creating a space between values.
OPENW, prof2d, outfilename+'.prf', /GET_LUN
printf, prof2d, numalts, altstart, delalt, numlats, latstart,dellat
printf, prof2d, format='(1(f3.1),500(i))', 0.0, findgen(num)+1.0
for i=0, numlats-1 do begin
printf, prof2d, FORMAT='(1(i),500(e15.8))',i+1, p2d(i,*)
endfor
CLOSE, prof2d & FREE_LUN, prof2d
popd
This seems to be the line that has an issue:
printf, prof2d, FORMAT='(1(i),500(e15.8))',i+1, p2d(i,*)
The linux box produces:
1 0.00000000e+00 0.00000000e+00 0.00000000e+00....9.17620019e+09
while the windows box produces:
1 0.00000000e+000.00000000e+000.00000000e+00....9.17620019e+09
Any help would be greatly appreciated.
Best regards,
Alex

In your example:
printf, prof2d, FORMAT='(1(i),500(e15.8))',i+1, p2d(i,*)
the "e15.8" means exponential notation ("e") with 15 total spaces for the number and 8 digits after the decimal place. Which is what the Linux box seems to be doing since "0.00000000e+00" is only 14 characters long, giving one space between values. I don't know why the Windows box is doing something different. But to give space between the values increase the 15 to 16 or more, like:
printf, prof2d, FORMAT='(1(i),500(e16.8))',i+1, p2d(i,*)
That's going to give two spaces between values on Linux, but should help you on Windows.

Related

Incoherent local/global line numbering in Scinotes

When I switch on the "local line numbering" option in SciNotes, I get a strange effect. The line numbers show as local (starting with the "function" line) for some of my functions, but global (counting from the beginning of the code file) for others.
My first thought was that a function wasn't ended properly (too few "end" instructions wrt the number of opened loops, ifs and other such), but then my code would crash, which it doesn't. Also, indentation looks fine when I auto-adjust it.
It doesn't very much get in my way, but I wonder if it isn't a symptom of something more serious cooking under the surface. Has anybody had a similar experience?
FWIW I'm using Scilab 6.0.2 under Windows 10.
I think I have found the source of the "problem". Line numbering only gets local in a function whose first line (the one with the "function" keyword) is not terminated with a semicolon.
Like this:
1 // This is my fantastic power program
2 clear;
3 clc;
4 cd "c:\myDir\Scilab\Sandbox\FunAndGames"
5
6 function S=square(x); // <-- now you see it
7 S=x*x; // (the semicolon, I mean)
8 endfunction;
9
1 function C=cube(x) // <-- now you don't
2 C=x*x*x;
3 endfunction;
13
14
15 // Now the body of my program:
16
17 X=zeros(5,5);
18 ....

How do I fix the split screen?

So I'm just wondering why my screen looks like this and how do I fix it. The screen splits down the middle where the color changes from orange to green so it looks for only the first part of that file when I run the code. I don't know why it's doing that or how to fix it.
Some compilers allow for a free format but most that I've used (IBM) require fixed. They have Area A and Area B which ends at column 72. If you need to use long literals you'll have to use continuation. The hyphen must appear in col 7 or you'll get a compiler error. This is straight out of the GNUCobol manual but it's the same for IBM.
IDENTIFICATION DIVISION.
PROGRAM-ID. LONGLIT.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 LONG-LITERAL-VALUE-DEMO PIC X(60) VALUE "This is a long l
- "ong literal that
- " must be continu
- "ed.".
PROCEDURE DIVISION.
DISPLAY LONG-LITERAL-VALUE-DEMO
STOP RUN
.

Fortran77 User Input Validation

I need the user to enter only real numbers when prompted. An error message should be displayed and program should stop in case the user enters a character or any other symbol. How can i do this in fortran 77.
I assumed, you probably want to have more tries, because what you have in your question does the compiler does automatically.
You can use the IOSTAT= or ERR= specifiers.
INTEGER IE
DO I = 1, MAX
READ(*,*,IOSTAT=IE) X
IF (IE.eq.0) GOTO 10
PRINT *,"Wrong input, try again."
END DO
10 CONTINUE
or
GOTO 10
20 PRINT *,"Wrong input, try again."
10 READ(*,*,ERR=20) X
improving the user interface a little, i like to read a string, then do the error check on an internal read:
character insting*80
ie=1
do while(ie.ne.0)
read(*,'(a)')instring
if(instring(1:1).eq.'q')stop
read(instring,*,iostat=ie)x
if(ie.ne.0)then
write(*,*)'invalid input ',trim(instring),' is not a real number'
endif
enddo
(note trim is not f77 btw, but its easy enough to replicate if needed)
Note, with some effort you can handle the pathalogic cases. A leading '/' or ',' throws no error but leaves the value of x unchanged (likely system/compiler dependent however!), so you can do something like this:
x=-999999.
read(instring,*,iostat=ie)x
if(ie.eq.0.and.x.eq.-999999.)then
.. code to handle error..
endif
You could alternately use index to look for the bad characters. On my system a decimal . by itself is taken as zero. That gets a bit cumbersome to handle, but it can be done by parsing instring

Fortran: FORMAT statement over two lines

I have an old Fortran 77 code, which I would like to run in a F90-Compiler, and my goal is to change the code as less as possible. It works quite well, but I have some problem with format statements in the code. And I don't understand what's the problem. I work with Eclipse, and gfortran. I use free form.
Question 1
This compiles fine:
program HelloWorld
400 FORMAT(7HK GAMMA,2X,G13.5,7H P0,2X,G13.5,6H A1,2X,G13.5)
end program
This doesn't compile
program HelloWorld
400 FORMAT(7HK 'GAMMA',2X,G13.5,7H 'P0',2X,G13.5,6H 'A1',2X,G13.5)
1
end program
The Error is
P descriptor needs leading scale factor in format string at (1)
(the error is translated from german, might not be exactly the same words in english) What is wrong?
Question 2
This also compiles fine:
program HelloWorld
400 FORMAT(7HK GAMMA,2X,G13.5,7H P0, &
2X,G13.5,6H A1,2X,G13.5)
end program
If I add more code to the last code:
program HelloWorld
400 FORMAT(7HK GAMMA,2X,G13.5,7H P0,2X,G13.5,6H A1,2X,G13.5, &
2X,7HK,ALPHA-1,2X,G13.5,7H BETA-4,2X,G13.5 )
end program
it doesn't compile anymore. The error is:
P Edit descriptor expected in the format string* at (1)
whereas the (1) is placed at the third line after the closing bracket.
*I'm not sure about the translation of "format string", as my console is in german.
What is the problem there?
Your format statements have an H (for Hollerith) edit descriptors - the things in the format statements that have a number followed immediate by a H. The descriptor results in the characters (including blanks) following the H and counted by the leading number being output to the file.
This language feature was made obsolescent in Fortran 90 and removed completely from the language in Fortran 95.
They are very error prone. Since Fortran 77 a far better way of achieving the same result has been to use character constant edit descriptors.
The problem is that you have (or are creating) a mismatch between the number of characters indicated by the leading number and the actual count of characters that apparently were in the descriptor. For example, your second FORMAT statement is copied below, showing the seven characters that would be in the descriptor. You can see how that appears to end in the middle of a "string". This then confuses what the compiler sees for the remainder of the format specification.
400 FORMAT(7HK 'GAMMA',2X,G13.5,7H 'P0',2X,G13.5,6H 'A1',2X,G13.5)
1234567
As I write in the comment it looks more like FORTRAN66 than 77 because the Hollerith H descriptor and data type was used before introducing the CHARACTER data type to the language. It was also used to assign character data to integer variables, but fortunately that is very rare to encounter. The use as an edit descriptor is however more common, although very obsolete.
It is not clear what you want to achieve, good example of the desired output would be helpful.
Do you meant:
400 FORMAT(7HK GAMMA,2X,G13.5,3H P0,2X,G13.5,3H A1,2X,G13.5)
so that
print 400, 1. ,2. ,3.
outputs
K GAMMA 1.0000 P0 2.0000 A1 3.0000
Or should the P0 and A1 serve as edit descriptors?
What was the original code in the legacy software?
The nH Hollerith descriptor just outputs n next characters so it can unintentionally "eat" some of your descriptors and just print them.
That is the problem that causes that your examples do not compile, because the n before H is too large and the rest of the format then has no sense.
The next one could be
400 FORMAT(8H 'GAMMA',2X,G13.5,5H 'P0',2X,G13.5,5H 'A1',2X,G13.5)
to print
'GAMMA' 1.0000 'P0' 2.0000 'A1' 3.0000
The effect of the above in Fortran 95 and above is better achieved by
print '(A0,2X,G13.5,A0,2X,G13.5,A0,2X,G13.5)', " 'GAMMA'",1.," 'P0'", 2.0, " 'A1'", 3.0
and maybe you would rather use just:
print '(A0,2X,G13.5,A0,2X,G13.5,A0,2X,G13.5)', "GAMMA",1.,"P0", 2.0, "A1", 3.0
for printing
GAMMA 1.0000 P0 2.0000 A1 3.0000
or even
print *, "GAMMA",1.,"P0", 2.0, "A1", 3.0

Format statement with unknown columns

I am attempting to use fortran to write out a comma-delimited file for import into another commercial package. The issue is that I have an unknown number of data columns. My output needs to look like this:
a_string,a_float,a_different_float,float_array_elem1,float_array_elem2,...,float_array_elemn
which would result in something that might look like this:
L1080,546876.23,4325678.21,300.2,150.125,...,0.125
L1090,563245.1,2356345.21,27.1245,...,0.00983
I have three issues. One, I would prefer the elements to be tightly grouped (variable column width), two, I do not know how to define a variable number of array elements in the format statement, and three, the array elements can span a large range--maybe 12 orders of magnitude. The following code conceptually does what I want, but the variable 'n' and the lack of column-width definition throws an error (of course):
WRITE(50,900) linenames(ii),loc(ii,1:2),recon(ii,1:n)
900 FORMAT(A,',',F,',',F,n(',',F))
(I should note that n is fixed at run-time.) The write statement does what I want it to when I do WRITE(50,*), except that it's width-delimited.
I think this thread almost answered my question, but I got quite confused: SO. Right now I have a shell script with awk fixing the issue, but that solution is...inelegant. I could do some manipulation to make the output a string, and then just write it, but I would rather like to avoid that option if at all possible.
I'm doing this in Fortran 90 but I like to try to keep my code as backwards-compatible as possible.
the format close to what you want is f0.3, this will give no spaces and a fixed number of decimal places. I think if you want to also lop off trailing zeros you'll need to do a good bit of work.
The 'n' in your write statement can be larger than the number of data values, so one (old school) approach is to put a big number there, eg 100000. Modern fortran does have some syntax to specify indefinite repeat, i'm sure someone will offer that up.
----edit
the unlimited repeat is as you might guess an asterisk..and is evideltly "brand new" in f2008
In order to make sure that no space occurs between the entries in your line, you can write them separately in character variables and then print them out using theadjustl() function in fortran:
program csv
implicit none
integer, parameter :: dp = kind(1.0d0)
integer, parameter :: nn = 3
real(dp), parameter :: floatarray(nn) = [ -1.0_dp, -2.0_dp, -3.0_dp ]
integer :: ii
character(30) :: buffer(nn+2), myformat
! Create format string with appropriate number of fields.
write(myformat, "(A,I0,A)") "(A,", nn + 2, "(',',A))"
! You should execute the following lines in a loop for every line you want to output
write(buffer(1), "(F20.2)") 1.0_dp ! a_float
write(buffer(2), "(F20.2)") 2.0_dp ! a_different_float
do ii = 1, nn
write(buffer(2+ii), "(F20.3)") floatarray(ii)
end do
write(*, myformat) "a_string", (trim(adjustl(buffer(ii))), ii = 1, nn + 2)
end program csv
The demonstration above is only for one output line, but you can easily write a loop around the appropriate block to execute it for all your output lines. Also, you can choose different numerical format for the different entries, if you wish.

Resources