using array to insert all objects that are already declared - c

I have school assignment which consists in creating a program that does math operation with Matrix. In this program, I have to create Matrix using typedef.
This typedef should hold 4 x 4 Matrix with double type.
So for this here is my implementation:
typedef struct {
char * name;
double * data;
int elements;
} mat;
In main, I need to define several mat objects this way:
mat MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;
And this user should type its input for example: add_mat mat_a,mat_b,mat_c,
this operation will add 2 Matrix mat_a and mat_b into mat_c.
So after that this user input and split it with Comma\Tab, I want to write simple function that gets a char which is the required mat and returns the relevant mat:
For example:
mat getmatrix(char name, mat *mats)
{
int i;
for (i = 0; i < 6; i++)
{
if (strcmp(mats[i].name, "MAT_A") == 0)
{
return mats[i];
}
}
.....
}
For this, I insert all my mat objects into array:
mat mats[] = { MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F };
But I get this error for all my mat objects:
uninitialized local variable 'MAT_A' used
Any suggestions on how to fix it or maybe find another way to read the input?

The way you write it, mats would contain copies of MAT_A etc. This is not what you want.
Your getmatrix function also returns a copy of a matrix. You don't really need it (and copying structs that contain pointers is dangerous; but see below). You probably want to return the matrix by pointer, and also accept matrix parameters in all functions by pointer.
I suggest getting rid of MAT_A and friends as you don't really need them. Use only mats[i]. You need to specify the number of elements in mats:
mat mats[10];
Don't forget to initialise mats properly.
If for some ungodly reason you are required to define 10 or so different variables of type mat, you need to change mats to be an array of pointers (yes the common theme here is pointers, you have to use them everywhere).
mat* mats[] = { &MAT_A, &MAT_B, /* etc */ };
Change getmatrix accordingly.
Another thing to consider: if your matrix dimension is fixed, you are using pointers with no reason. Declaring double data[4][4] will simplify things considerably. Same thing about name, consider making it a fixed-size character array.

Related

How to use 2D calloced arrays in functions in C?

I need to create a matrix calculator, for that I think the best is to create functions for +,-,*,/.
But a lot of troubles come with this idea.
I create a calloced array like:
int **matrix = NULL;
matrix=calloc(cols,sizeof(int*));
for(int i=0;i<cols;i++) {
matrix[i]=calloc(rows,sizeof(int*));
}
For now I want to create a function where I want to work with this array.
void addition(int **array,int rows, int cols){
// ** some algoritm here**
return (the result of addition stored in 2D array);
}
I also tried to google the problem, but I didn't underestand the solutions. What I need to explain the way how to pass the array to function, just for reading.
After that I need to return some pointer to new array created as the result of addition. I will probably create the new array in the function.
But If I wanted to write something in array created in main, how to pass and use it in the function?

Allocate memory to variable of type int *a[13][13]

I came across an old code where I need to allocate memory for an array of matrices. Currently it is done by creating a structure matrix and allocating memory by making an arrray of structures.
Like so.
struct matrix
{
int x[13][13];
};
int main()
{
matrix *push = (matrix*)malloc(sizeof(matrix) * 1000);
//do stuff
free(push);
return 0;
}
But now the question.. Do I really need to do this? I know I am allowed to declare a variable of type int *matrix[13][13];
But I cant seem to figure out a way to allocate memory to this variable.
I tried matrix = (int***)malloc(sizeof(int[13][13])*1000); which results in
E0137 expression must be a modifiable lvalue and honestly in doesnt seem correct either
I know there are many better and creative ways of allocating an array like this, but I am curious
Questions
int *matrix[13][13] what will this kind of variable even mean or represent? Is it a pointer to a 2D matrix or s it an pointer to an array of 2D matrices?
How will I use the above mentioned variable?
How will I allocate memory for the above variable without using any more variables?
Clarifications
From comments it seems int *matrix[13][13] represents a matrix of 13x13 int*
What I am asking is actually, is there a way to have a variable with a dynamically allocated first dimension and static 2nd and 3rd dimensions without using structures typedefs etc
EDIT
As pointed out by felix
what I am looking for is int (*matrix)[13][13] = (int(*)[13][13])malloc(1000*sizeof(matrix));
I have noticed that sometimes beginner programmers are finding typedef-ing the multidimensional matrices which have to be dynamically allocated easier as it reduces the problem to the single star pointer and the sizeof of the defined type and pointer to it is much easier to understand.
#include <stdio.h>
typedef int my13x13matrix[13][13];
int main(void) {
my13x13matrix *mylargematrix = malloc(1000 * sizeof(*mylargematrix));
mylargematrix[999][12][12] = 5;
printf("%d \n", mylargematrix[999][12][12]);
return 0;
}
you can also use the single star pointer arithmetic.
my13x13matrix *anotherpointer = &mylargematrix[10];
(*anotherpointer)[5][5] = 1;
anotherpointer++;
(*anotherpointer)[5][5] = 2;
printf("%d %d\n", mylargematrix[10][5][5], mylargematrix[11][5][5]);
No, you don't want to use
int *matrix[13][13];
That will declare a [13][13] array of int*s.
You need
// pointer to "an array of 13 x 13 ints"
int (*matrix)[13][13];
or simplify it by using a type alias.
typedef int matrix_type[13][13];
matrix_type* matrix_ptr;
You can allocate memory for such a variable using
matrix_type* matrix_ptr = malloc(1000*sizeof(*matrix_ptr));
and assign values to it using
matrix_ptr[0][0][0] = 0;
...
matrix_ptr[999][12][12] = 0;

Send dynamic array to function C++

I have an array, which is now static. This are the operations I do with it.
Firstly I create a two-dimensional array. Then I fill it in, using cycles. And then I send it to function, where there are also cycles which are used.
Here I 'd like to post some sample code, which is similar to mine.
bool picture[20][20]; //here's my array right now. Pretty ugly. Just for testing.
for (int y=0;y<Height;y++)
{
for (int x=0;x<Width;x++)
{
if (treshold<middle)
{
picture[x][y]=1;
}
else
{
picture[x][y]=0;
}
}
}
//Here's an example of filling an array
leftk = left(picture,widthk, heightk); //That's how I use a function
int left(int picture[200][200],int row,int col)
{
for (int x = 0; x <=row-1; x++)
{
for (int y = 0; y <=col-1 ;y++)
{
if (picture1[x][y]==1)
{
return x;
}
}
}
}
//And that's the function itself
So here I need to switch my array to a dynamic one. That's how I declare my dynamic array
bool** picture=new bool*[size];
for(int i = 0; i < size; ++i)
picture[i] = new bool[size];
//size is just a variable.
As for statically declared cycles, everything is very simple. Sending this array as a parameter to function.
I've already managed to create a dynamic array, it's simple. Then I fill it in with numbers. No problems here too. But I can't understand, how to send an array to function and moreover how to use it there.
Could you give me an exaple of modifying two-dimensional arrays in functions.
Sorry for such a newbie question. Hope someone will help.
By the way, class wrapping would be a bit confusing here, I think.
A function such as:
Process2DArray(int **pArray, int rowCount, int colCount)
Should suffice the needs assuming its a 2D array that is being operated on. Also, consider using std::vector<std::vector<int>> instead of a multidimensional array allocated manually. This approach will help prevent leaks. The second approach also lets you have jagged arrays.
The usual solution is to wrap the array in a class; C doesn't handle
arrays very well, and C++ doesn't have any real support for 2D arrays in
its library either. So you define either:
class Array2D
{
std::vector<double> myData;
int myColumnCount;
int myRowCound;
// ...
};
with accessors which convert the two indexes using i * myColumnCount +
j, or:
class Array2D
{
std::vector<std::vector<double> > myData;
// ...
};
with initialization logic ensure that all of the rows have the same
length. The first is generally simpler and easier to understand; if you
want to increase the number of columns, however, the second is
significantly easier.
You have several options:
an array of arrays. For example, for int would be int **a which should be able to hold n arrays new int *[n], then go with a for through them and initialized them a[i] = new int[elems_per_line]
a "packed" 1D array int *a = new int[n * elems_per_line], where element (i, j) - 0-based is actually a[i * elems_per_line + j].
you can refine point 1, and have the 2D matrix be "curly" - with lines of different lengths, but you'll need an array to hold each length.
Hope this helps.

initialize a global 2-dimensional C array of integers at run time

I need to store an array of point (x,y). I read the points from a file, and the number of points are not constant, but i can get it at the first line of the file. So i write a procedure load() to loading the points from the file and store them in a global array. It doesn't work.
My code:
int *array[][]; // this is a pointer to a 2-dimensional array??
void load(){
..
int tempArray[2][n]; //n is the first line of the file
..
array = tempArray;
}
You're trying to return a pointer to memory that is local to the function that defines the variable. Once that function stops running ("goes out of scope"), that memory is re-used for something else, so it's illegal to try and reference it later.
You should look into dynamic allocation, and have the loading function allocate the needed memory and return it.
The function prototype could be:
int * read_points(const char *filename, size_t *num_points);
Where filename is of course the name of the file to open, num_points is set to the number of points found, and the returned value is a pointer to an array holding x and y values, interleaved. So this would print the coordinates of the first point loaded:
size_t num_points;
int *points;
if((points = load_points("my_points.txt", &num_points)) != NULL)
{
if(num_points > 0)
printf("the first point is (%d,%d)\n", points[0], points[1]);
free(points);
}
This declaration of yours does not work:
int *array[][]; // this is a pointer to a 2-dimensional array??
First, it is trying to declare a 2D array of int *. Second, when you declare or define an array, all dimensions except the first must be specified (sized).
int (*array)[][2]; // This is a pointer to a 2D array of unknown size
This could now be used in a major variant of your function. It's a variant because I misread your question at first.
void load(void)
{
...
int tempArray[n][2]; // Note the reversed order of dimensions!
...
array = &tempArray;
...there must be some code here calling functions that use array...
array = 0;
}
Note that the assignment requires the & on the array name. In the other functions, you'd need to write:
n = (*array)[i][j];
Note, too, that assigning the address of a local array to a global variable is dangerous. Once the function load() returns, the storage space for tempArray is no longer valid. Hence, the only safe way to make the assignment is to then call functions that reference the global variable, and then to reset the global before exiting the function. (Or, at least, recognize that the value is invalid. But setting it to zero - a null pointer - will more nearly ensure that the program crashes, rather than just accessing random memory.
Alternatively, you need to get into dynamic memory allocation for the array.
Your question actually is wanting to make a global pointer to a VLA, variable-length array, where the variable dimension is not the first:
int tempArray[2][n]; // Note the reversed order of dimensions!
You simply can't create a global pointer to such an array.
So, there are multiple problems:
Notation for pointers to arrays
Initializing pointers to arrays
Assigning global pointers to local variables
You can't have global pointers to multi-dimensional VLAs where the variable lengths are not in the first dimension.
You should minimize the use of globals.
A more elegant version might go like this:
typedef struct point_ { int x; int y; } point;
point * create_array(size_t n)
{
return calloc(n, sizeof(point));
}
void free_array(point * p)
{
free(p);
}
int main()
{
size_t len = read_number_from_file();
point * data = create_array(len);
if (!data) { panic_and_die(); }
for (size_t i = 0; i != len; ++i)
{
/* manipulate data[i].x and data[i].y */
}
free_array(data);
data = 0; /* some people like to do this */
}
You are trying to assign an array but in C arrays cannot be assigned.
Use memcpy to copy one array to another array. Arrays elements in C are guaranteed to be contiguous.
int bla[N][M] = {0};
int blop[N][M];
/* Copy bla array to blop */
memcpy(blop, bla, sizeof blop);

Coding problem using a 2-d array of structs inside another struct in C

I am working with a 2-dimensional array of structs which is a part of another struct. It's not something I've done a lot with so I'm having a problem. This function ends up failing after getting to the "test" for-loop near the end. It prints out one line correctly before it seg faults.
The parts of my code which read data into a dummy 2-d array of structs works just fine, so it must be my assigning array to be part of another struct (the imageStruct).
Any help would be greatly appreciated!
/*the structure of each pixel*/
typedef struct
{
int R,G,B;
}pixelStruct;
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
imageStruct ReadImage(char * filename)
{
FILE *image=fopen(filename,"r");
imageStruct thisImage;
/*get header data from image*/
/*make a 2-d array of of pixels*/
pixelStruct imageArr[thisImage.height][thisImage.width];
/*Read in the image. */
/*I know this works because I after storing the image data in the
imageArr array, I printed each element from the array to the
screen.*/
/*so now I want to take the array called imageArr and put it in the
imageStruct called thisImage*/
thisImage.arr = malloc(sizeof(imageArr));
//allocate enough space in struct for the image array.
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*/
//test to see if assignment worked: (this is where it fails)
for (i = 0; i < thisImage.height; i++)
{
for (j = 0; j < thisImage.width; j++)
{
printf("\n%d: R: %d G: %d B: %d\n", i ,thisImage.arr[i][j].R,
thisImage.arr[i][j].G, thisImage.arr[i][j].B);
}
}
return thisImage;
}
(In case you are wondering why I am using a dummy array in the first place, well it's because when I started writing this code, I couldn't figure out how to do what I am trying to do now.)
EDIT: One person suggested that I didn't initialize my 2-d array correctly in the typedef for the imageStruct. Can anyone help me correct this if it is indeed the problem?
You seem to be able to create variable-length-arrays, so you're on a C99 system, or on a system that supports it. But not all compilers support those. If you want to use those, you don't need the arr pointer declaration in your struct. Assuming no variable-length-arrays, let's look at the relevant parts of your code:
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
arr is a pointer to pixelStruct, and not to a 2-d array of pixels. Sure, you can use arr to access such an array, but the comment is misleading, and it hints at a misunderstanding. If you really wish to declare such a variable, you would do something like:
pixelStruct (*arr)[2][3];
and arr would be a pointer to an "array 2 of array 3 of pixelStruct", which means that arr points to a 2-d array. This isn't really what you want. To be fair, this isn't what you declare, so all is good. But your comment suggests a misunderstanding of pointers in C, and that is manifested later in your code.
At this point, you will do well to read a good introduction to arrays and pointers in C, and a really nice one is C For Smarties: Arrays and Pointers by Chris Torek. In particular, please make sure you understand the first diagram on the page and everything in the definition of the function f there.
Since you want to be able to index arr in a natural way using "column" and "row" indices, I suggest you declare arr as a pointer to pointer. So your structure becomes:
/* data for each image */
typedef struct
{
int height;
int width;
pixelStruct **arr; /* Image data of height*width dimensions */
} imageStruct;
Then in your ReadImage function, you allocate memory you need:
int i;
thisImage.arr = malloc(thisImage.height * sizeof *thisImage.arr);
for (i=0; i < thisImage.height; ++i)
thisImage.arr[i] = malloc(thisImage.width * sizeof *thisImage.arr[i]);
Note that for clarity, I haven't done any error-checking on malloc. In practice, you should check if malloc returned NULL and take appropriate measures.
Assuming all the memory allocation succeeded, you can now read your image in thisImage.arr (just like you were doing for imageArr in your original function).
Once you're done with thisImage.arr, make sure to free it:
for (i=0; i < thisImage.height; ++i)
free(thisImage.arr[i]);
free(thisImage.arr);
In practice, you will want to wrap the allocation and deallocation parts above in their respective functions that allocate and free the arr object, and take care of error-checking.
I don't think sizeof imageArr works as you expect it to when you're using runtime-sized arrays. Which, btw, are a sort of "niche" C99 feature. You should add some printouts of crucial values, such as that sizeof to see if it does what you think.
Clearer would be to use explicit allocation of the array:
thisImage.arr = malloc(thisImage.width * thisImage.height * sizeof *thisImage.arr);
I also think that it's hard (if even possible) to implement a "true" 2D array like this. I would recommend just doing the address computation yourself, i.e. accessing a pixel like this:
unsigned int x = 3, y = 1; // Assume image is larger.
print("pixel at (%d,%d) is r=%d g=%d b=%d\n", x, y, thisImage.arr[y * thisImage.width + x]);
I don't see how the required dimension information can be associated with an array at run-time; I don't think that's possible.
height and width are undefined; you might want to initialise them first, as in
thisImage.height = 10; thisImage.width = 20;
also,
what is colorRGB?
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*
This won't work. You have to declare arr as colorRGB **, allocate it accordingly, etc.
it looks like you are trying to copy array by assignment.
You cannot use simple assignment operator to do that, you have to use some function to copy things, for example memcpy.
*thisImage.arr = *imageArr;
thisimage.arr[0] = imagearr[0];
The above statements are doing the same thing.
However this is not most likely what causes the memory corruption
since you are working with two dimensional arrays, do make sure you initialize them correctly.
Looking at the code, should not even compile: the array is declared as one-dimensional in your image structure but you refer to as two-dimensional?

Resources