Karandash8
Karandash8

Reputation: 346

Fortran to C translation of reading unformatted files

I am struggling with translating a small piece of Fortran code to C. I have a file written in a binary format and a Fortran program that reads that format. My goal is to have a C program that is able to read the same format. I am completely new to Fortran and I do not have the original specification of the format. So, it is kind of a reverse-engineering process.

filename = 'file'
integer :: status
integer, parameter :: di=selected_int_kind(9)
integer(di) :: nn

OPEN(11,file = filename, status = 'old', action = 'read', form = 'unformatted', iostat = status)
if(status /= 0) then
   write(*,*) 'FILE ERROR: '//filename
   stop
endif
read(11) nn
CLOSE(11)

One thing that really confuses me is the selected_int_kind() statement. What exactly it does? What would be the equivalent in C?

Actually, my first attempt to translate was pretty much the same as the answer by @JohnBode and it did not work. It reads a totally incorrect value.

After a few more attempts I found a working solution, however, I do not understand why it is so. For some reason the correct value is written in the 5th-8th bytes. So, I can either read two int values (where the second one will be the correct one), or I can read a long value and then make a right shift for 32 bits. Any idea why Fortran can so easily retrieve the right value?

Upvotes: 0

Views: 233

Answers (2)

John Bode
John Bode

Reputation: 123558

This is close to a 1:1 translation.

const char *filename = "file"; // or const char filename[] = "file";
long nn;

FILE *input = fopen( filename, "rb" ); // open as binary
if ( !input ) // or if ( input == NULL )
{
  fprintf( stderr, "FILE ERROR: %s\n", filename );
  exit(0);
}

if ( fread( &nn, sizeof nn, 1, input ) < 1 )
{
  fprintf( stderr, "Error while reading input\n" );
}

fclose( input );  

C doesn't have an equivalent to the "selected_int_kind" as above; instead, you would pick the appropriate type to represent the expected range of values (i.e., short, int, long, long long, etc.). If you need to be able to represent 9 decimal digits, a plain int might not be wide enough (although in practice it should be), so you should probably use long instead.

Upvotes: 0

Thomas Baruchel
Thomas Baruchel

Reputation: 7517

Types in Fortran have a KIND because the same type (INTEGER in your case) may have different "flavors" (a little like short, long, signed, unsigned, etc. in C). These kinds are integer numbers: see a list here for instance. Your expression selected_int_kind(9) means: what is the kind-number of the smallest integer kind that can contain values between -1e9 and 1e9 (see explanations here).

In C, I guess signed int should be OK because even 4 bytes (32 bits) goes from -2^31 up to 2^31-1 which is a little wider than required.

Upvotes: 1

Related Questions