Question

I am trying to write a C program to display the content of a binary file which contains a few numbers stored as follows: The first 4 bytes contain an integer n stored in little endian format. The next 8n bytes contain an array of n floating point numbers stored in 8 byte double precision format

"Data" was made with matlab, and this file includes: n = 7 array = [.7147, -.2050, -.1241, 1.4897, 1.4090, 1.4172, .6715]

So far this is the code that I have. Essentially I am trying to read in the file, send those variables through my little endian function, and display it. I'm not sure why I'm getting the outcome that I'm getting.

#include <stdio.h>
#include <stdint.h>

/* function to show bytes in memory, from location str to str+n*/
void extract_little(char *str,int offs, int n); 
void extract_big(char *str,int offs, int n);
/*Main function to call above function */
int ofset;

int main(){


int x;
int i[numE*4];
FILE* fp = fopen("data","rb");

fread(i,sizeof(i[x]),numE,fp);
fclose(fp);
for (x=1; x < numE;x++)
printf("%d%\n",i[x]);

//extract_little((char *)&i, ofset, sizeof(i));

  return 0;

}


  void extract_little(char *str,int offs, int n) 
    {
    int i;
    for (i = 0; i < n; i++){
       printf(" %04f\n\n", (unsigned int) str[i]);
      }

    }

New Outcome

-2103482977
1072095020
-359136765
-1077265325
-1953332745
-1077950484

Not 100% sure if this is correct, but it's a start. Unfortunately not utilizing the function, which it needs to.

Was it helpful?

Solution

An array of doubles needs to be created. Since the size is recorded in the file and is not known in advance, I dynamically allocated the memory for the array.

If the machine is also little-endian no conversion is necessary, but if it is big-endian the bytes must be reversed. To check if the machine is big-endian, the first byte of a known number can be inspected. It is possible (although very unlikely) for ints and doubles do have different endianness on the same system, so both should be checked.

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

// For detecting endianess.
// dummy_int: highest order byte is zero, lowest order byte is non-zero.
// dummy_double: highest order byte (part of exponent) is non-zero,
// lowest order byte (part of mantissa) is zero.
int32_t dummy_int = 1;
double dummy_double = 1.0;
#define INT_IS_BIG_ENDIAN (((char*) &dummy_int)[0] == 0)
#define DOUBLE_IS_BIG_ENDIAN (((char*) &dummy_double)[0] != 0)

void extract(FILE* fp, void *data, size_t size, int reverse);
void reverse_bytes(void *data, size_t size);
void display(void *data, size_t size);

int main()
{
    int32_t n, i;
    double *data;
    FILE* fp = fopen("data","rb");

    extract(fp, &n, sizeof(n), INT_IS_BIG_ENDIAN);
    data = (double*) malloc(n * sizeof(double));
    for (i = 0; i < n; i++) {
        extract(fp, &data[i], sizeof(double), DOUBLE_IS_BIG_ENDIAN);
    }

    fclose(fp);

    // print the data
    printf("n: %d\n", n);
    for (i = 0; i < n; i++) {
        printf("item #%d: %f\n", i+1, data[i]);
        printf("in hex: ");
        display(&data[i], sizeof(double));
    }

    free(data);

    return 0;
}

void extract(FILE* fp, void *data, size_t size, int reverse)
{
    fread(data, size, 1, fp);
    if (reverse) {
        reverse_bytes(data, size);
    }
}

void reverse_bytes(void *data, size_t size)
{
    char *i, *j;
    char tmp;
    for (i = (char*) data, j = i + size - 1; i < j; i++, j--) {
        tmp = *i;
        *i = *j;
        *j = tmp;
    }
}

void display(void *data, size_t size)
{
    size_t i;
    char *char_data = (char*) data;
    for (i = 0; i < size; i++) {
        printf("%02x ", (unsigned char) char_data[i]);
    }
    printf("\n");
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top