I'm using this code to write the file:
FILE *f = fopen("out/solution.raw", "wb");
int i, j;
//SIZE = 512
for(i = 0; i < SIZE; i++)
{
fwrite(matrix[i], 1, SIZE, f);
}
fclose(f);
The problem is that when I open the file, it 3 '0' between the numbers, here are 2 screenshots to help you understand what I mean:
This is what I should be getting:
And this is what I'm getting:
As you can see my code is correctly writing each number, but there are three 0 between each number and I have no idea why.
I've also tried this:
fwrite(matrix[i], sizeof(matrix[i][0]), SIZE, f);
But none seems to work, any help would be greatly appreciated.
my matrix is declared as a 2D array of ints, as I need to do some operations with those numbers:
matrix = (int**)malloc(SIZE * sizeof(int*));
for (i = 0; i < SIZE; i++)
{
matrix [i] = (int*)malloc(SIZE * sizeof(int*));
}
I've tried your solution but I can't assign an unsiged char to an int, so I've tried casting it and I get this warning:
cast from pointer to integer of different size.
unsigned char to_write;
for(i = 0; i < SIZE; i++)
{
to_write = (unsigned char)matrix[i];
fwrite(&to_write, 1, 1, f);
}
(code used)
After that this is what I'm getting:
And btw, my data is unsigned.
matrix[i] is a pointer on 32-bit integers. Even if you assign values that hold in 8 bits, that doesn't "compress" the data when you're writing to a binary stream (plus you probably don't write the 512 values but only 512/4 = 128 values)
Your machine is little endian, so you get the LSB first, then 3 zeros, for each value.
So change the type of matrix[i] from int32_t * to char * or unsigned char * depending on what you need, make sure your values are in 8-bit range, and you can use fwrite like you're planning to.
If you cannot change the data type of matrix, use a loop to convert the values
for(i = 0; i < SIZE; i++)
{
uint8_t to_write = matrix[i]; // assign/truncate for 0/255 range
fwrite(&to_write, 1, 1, f);
}
if your data is signed, you have to use int8_t. But in that case, you're not going to be able to write a0 as 160.
EDIT: your edit shows the real type of matrix. matrix[i] is a pointer on data, so you need to use a double loop to dump it, else you're copying the address of the array, not the value
for(i = 0; i < SIZE; i++)
{
const int *row = matrix[i];
for(j = 0; j < SIZE; j++)
{
uint8_t to_write = row[j]; // assign/truncate for 0/255 range
fwrite(&to_write, 1, 1, f);
}
}
Related
I'm using a C program on Linux to read data from a serial port.
The data to read comes from Code Composer Studio from the line: UART_writePolling(uartHandle, (uint8_t*) &value, sizeof(float));
value is the float I want to read in C, where value = 1.5.
When I read in the data from the serial port, in C, into a buffer and print with printf("%u\n", (int)buffer[i]);
I get value to be:
0
0
4294967232
63
and when I insert buffer[i] into a.array and print with
printf("%d\n", a.array[i]);
I get value to be:
0
0
-64
63
I've also tried using unions:
unsigned int value = 0;
for (int j = 3; j >= 0; j--){
//value <<= 8;
value = value + (int)a.array[i+8+j];
}
printf("value: %u\n", value);
data.u = value;
printf("(float): %f\n", data.f);
which doesn't give the correct answer.
How can I use union to get the correct data as a float?
Do I need to use <<?
EDIT: better idea of the code
//headers
typedef struct {
int *array;
size_t used;
size_t size;
} Array;
void initArray(Array *a, size_t initialSize) {
a->array = (int *)malloc(initialSize * sizeof(int));
a->used = 0;
a->size = initialSize;
}
... //more functions/code to resize array and free the memory later
union Data {
float f;
unsigned int u;
};
int main(){
union Data data;
//open serial port code
char buffer[1]; /* Buffer to store the data received,
reading one at a time */
Array a;
initArray(&a, 5); /* initialise an array to store the read data
that is read into buffer*/
//while loop to read in data for some amount of time/data
int b_read = 0;
b_read = read(fd, &buffer, sizeof(buffer));
for (int i=0; i<b_read; i++){
printf("%u\n", (int)buffer[i]);
// how the first set of values above were printed
insertArray(&a, buffer[i]);
// also adding the values read to buffer into array a
}
//end while
// close the port
for(int i=0; i<no. of elements in array a; i++){
printf("%d\n", a.array[i]);
// how the second set of results were printed
}
//below is an attempt at using union and <<:
unsigned int value = 0;
for (int j = 3; j >= 0; j--){
//value <<= 8;
value = value + (int)a.array[i+8+j]; //index used is particular to my code, where value is in a specific place in the array
}
printf("value: %u\n", value);
data.u = value;
printf("(float): %f\n", data.f);
//these printfs don't give a reasonable answer
// free memory
return 0;
}
Once the bytes are in buffer starting at offset i, you can reinterpret the bytes as a float with:
float f;
memcpy(&f, buffer+i, sizeof f);
To use a union, you could use:
union { uint32_t u; float f; } x;
x.u = value;
float f = x.f;
However, this requires that value contain all 32 bits that represent the float. When you attempted to construct the value with:
//value <<= 8;
value = value + (int)a.array[i+8+j];
There are two issues. First, value <<= 8 is needed. I presume you tried it first and did not get a correct answer, so you commented it out. However, it is required. Second, this code to insert the bytes one-by-one into value is order-dependent. Once the shift is restored, it will insert greater-addressed bytes into less-significant bits of value. Systems generally arrange bytes in objects in one of two orders: More significant bytes in lower addresses or more significant bytes in greater addresses. We do not know which order your system uses, so we do not know whether your code to insert the greater-addressed bytes in less significant bytes is correct.
Note: The above assumes that the bytes are read and written in the same order, or that issues of endianness have already been handled in other code.
You use printf with %u but cast into a int. So maybe it's not surprising to have this behavior since 2^32 = 4294967296, and 4294967296 - 64 (your second printf result) = 4294967232 (your first printf result).
Just cast into "unsigned" if you use "%u" or cast into "int" if you use "%d".
I have a char * who points to the structure. Here is my structure:
struct prot
{
int size;
unsigned short codeAction;
void *data;
};
I recovered size and codeAction, but now I want to recover data.
And when I cast my last 8 bytes I have nothing in it.
The following code is just a test, it's a bad code:
char lol[4];
for (int i = 0; i < 4; i++)
lol[i] = test[i];
int size = *(int*)lol;
char loli[2];
int index = 0;
for (int i = 4; i < 6; i++)
{
loli[index] = test[i];
index++;
}
int code = *(short*)loli;
char lolo[8];
index = 0;
for (int i = 6; i < size; ++i)
{
lolo[index] = test[i];
index++;
}
void *newData = (char *)lolo; // how can I cast it?
How I can display the content of newData?
Your problem is that when casting lolo you actually cast a pointer to the char array you defined. So the result of the cast would be a char pointer to the first cell of the array.
Why don't you just use this as a struct and access the fields regularly?
Anyway, you want to use lolo as a 64 bit type pointer and the access what's in it.
void* newData = *((uint64_t*)lolo)
Besides, don't loop until size in the last for loop, loop only 8 times, until lolo is full. The number of bytes in newData itself (not what it points to) is constant, and is 4 bytes on 32bit machines, 8 bytes on 64bit ones.
Last thing - index++, not o++. o isn't defined, as much as I can see.
Just a quick comment to start: While there are similar threads to this one, I haven't quite been able to find the solution I'm looking for. My problem is the following:
I have 2D arrays of doulbes saved to binary files and I would like to read the binary files (using C code) into a 2D array. Additionally, I need to allocate the memory dynamically as the shape of the arrays will be changing in my application. To get started, I tried the following code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
int N = 10; //number of rows of 2D array
int M = 20; //number of columns
/* first allocate the array */
double **data;
data = (double **)malloc(N*sizeof(double *));
for(unsigned int i=0; i < N; i++) {
data[i] = (double *)malloc(sizeof(double)*M);
}
FILE *ptr;
ptr = fopen("random_real_matrix.dat", "rb");
fread(data, sizeof(data), 1, ptr);
for(unsigned int i=0; i<10;i++){
for(unsigned int j=0; j<20;j++){
fprintf(stderr, "m[%d][%d] = %f\n ", i, j, data[i][j]);
}
}
}
Unfortunately, this code segfaults. I checked to see if I can set the array entries like
d[0][0] = 235;
and that works fine.
Assuming this approach can be fixed, I'm also interested to know if it could be extended to read to an array of double complex's.
Any advice would be greatly appreciated!
Your fread statement is incorrect. It's a common beginner mistake to think that sizeof gets the size of a dynamically allocated array. It doesn't. In this case it just returns the size of a double **. You will need to read in each double in the file and put that into the correct spot in the array.
for (int ii = 0; ii < N; ++ii)
{
for (int jj = 0; jj < M; ++jj)
{
fread(data[ii][jj], sizeof(double), 1, ptr);
// Be sure to check status of fread
}
}
You can do this with a single for loop (or a single fread) but this is probably clearer to read.
Because you allocated each row separately, you can't read into the entire array at once. You need to do it row by row.
for (int i = 0; i < N; i++) {
fread(data[i], sizeof(double), M, ptr);
}
I am trying to copy values from one array to another in C. The original array is of type long int, and it is inputted to the function as *pixel_frequency. The array I want to copy to is temp, and it is a 2D array. However, when I try to copy the values, pixel_frequency is fine but temp gives strange results. Below is the relevant code and some sample output.
Code:
struct node *generate_nodes(long int *pixel_frequency) {
int i;
int temp[max_value + 1][2];
for (i = 0; i < (max_value + 1); i++) {
temp[i][0] = i;
temp[i][1] = pixel_frequency[i];
printf("Frequency for %d is %d\n", temp[i][0], temp[i][1]);
}
...
Output (each frequency is supposed to be 256):
Frequency for 0 is 150160
Frequency for 1 is 256
Frequency for 2 is 256
Frequency for 3 is 256
Frequency for 4 is 255
...
Frequency for 254 is 892677956
Frequency for 255 is 1868789101
Below is an example version of code using your code snippet, take care of the return type and other things.
Instead of using a global variable for array size, you can pass it as a function argument so , it will be easy to identify the size of array you passed.
void generate_nodes(long int *pixel_frequency, size_t size) {
size_t i;
long int temp[size][2];
for (i = 0; i < size; i++) {
temp[i][0] = i;
temp[i][1] = pixel_frequency[i];
printf("Frequency for %ld is %ld\n", temp[i][0], temp[i][1]);
}
}
If you have declared pixel_frequency as a local variable in a function and used the address of array after the variable went out of scope, will lead to undefined behaviour.
int main(void) {
size_t max_len = 5000;
size_t i;
long int* pixel_frequency = malloc(max_len*sizeof(long int));
for( i = 0; i < max_len; ++i) {
pixel_frequency[i] = (i%256);
}
generate_nodes(pixel_frequency, max_len);
return 0;
}
This function is throwing an access violation when reading raw pixel values and I can't figure out why.
Can consider this as the only part of my code running, I've run this solo with the same result.
string filenames[]={"firstclick.raw", "secondclick.raw","thirdclick.raw","fourthclick.raw","fifthclick.raw","sixthclick.raw","seventhclick.raw","eighthclick.raw"};
FILE *file;
int height= 750, width = 453, bbp=3;
unsigned char ****images;
images = (unsigned char ****)malloc(sizeof(unsigned char ***)*8);
for(int j = 0; j<8; j++){
images[j] = (unsigned char ***)malloc(sizeof(unsigned char**)*height);
for(int i = 0; i<height; i++){
images[j][i]= (unsigned char **)malloc(sizeof(unsigned char*)*width);
for(int k = 0; k<bbp; k++)
images[j][i][k]= (unsigned char *)malloc(sizeof(unsigned char)*bbp);
}
}
for (int i = 0; i<8; i++){
if (!(file=fopen(filenames[i].c_str(),"rb"))){
cout << "Cannot open file: "<<filenames[i].c_str() <<endl;
exit(1);
}
fread(images[i], sizeof(unsigned char), height*width*bbp, file);
fclose(file);
}
The problem here is you've allocated each element of your array as a separate array (somewhere else in memory, whose location is kept as a pointer). But when you read in, you assume that it's a single contiguous block. You will overwrite all those pointers, and overflow the buffer to boot.
If you want images to be a set of discrete blocks of memory, allocate like this:
unsigned char ** images;
int i;
images = malloc( sizeof(unsigned char *) * 8 );
for( i = 0; i < 8; i++ ) {
images[i] = malloc( width * height * bpp );
}
Note that sizeof(unsigned char) is defined by the standard to always be 1. You don't need to multiply by sizeof(unsigned char) all the time.
Now, to get a pixel address in an image, you need to multiply out (usually row-major):
unsigned char * pixel = images[i] + (y * width + x) * bpp;
unsigned char r = pixel[0];
unsigned char g = pixel[1];
unsigned char b = pixel[2];
when you allocate the memory blocks in different locations in memory an fread on that structure will not work.
instead allocate one big block then set the pointers to point inside the block, that way you can use fread on it.