Trying to change element in 2D array in C - c

I'm suppose to implement in the function make2Darray to make the elements in the 2D array correspond with the row number.
The other parts of the code that prints and frees was already given, so no need to worry about that. I'm only suppose to touch the make2Darray function. However, in that function, the allocating part was also given. So the only code I am to alter is the part where I change the elements in the 2D array.
int** make2Darray(int width, int height) {
int **a;
int i = 0;
int j = 0;
/*allocate memory to store pointers for each row*/
a = (int **)calloc(height, sizeof(int *));
if(a != NULL) {
/* allocate memory to store data for each row*/
for(i = 0; i < height; i++) {
a[i] = (int *)calloc(width, sizeof(int));
if(a[i] == NULL) {
/* clean up */
free2Darray(a, height);
return NULL; /*aborting here*/
}
}
}
/* from this point down is the part I implemented, all code above was
given*/
if (height < 0 && width < 0) {
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
a[i][j] = j;
}
}
}
return a;
}
The elements in the 2D array is suppose to correspond to the row number
If height = 4 and width = 3
0 0 0
1 1 1
2 2 2
3 3 3
However, I always get 0s which was the default setting when I got the code
0 0 0
0 0 0
0 0 0
0 0 0

You have two major problems in the code.
1) The code where you initialize the 2D array shall be inside the if-block
2) if (height < 0 && width < 0) { is wrong - you want > instead of <
Try:
int** make2Darray(int width, int height) {
int **a;
int i = 0;
int j = 0;
/*allocate memory to store pointers for each row*/
a = (int **)calloc(height, sizeof(int *));
if(a != NULL) {
/* allocate memory to store data for each row*/
for(i = 0; i < height; i++) {
a[i] = (int *)calloc(width, sizeof(int));
if(a[i] == NULL) {
/* clean up */
free2Darray(a, height);
return NULL; /*aborting here*/
}
}
// Moved inside the if(a != NULL) {
/* from this point down is the part I implemented, all code above was
given*/
if (height > 0 && width > 0) { // Corrected this part
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
a[i][j] = j;
}
}
}
}
return a;
}
A few hint:
1) Do the check for height and width in the beginning of your function - like:
if (height <= 0 || width <= 0) return NULL;
2) The prototype make2Darray(int width, int height) seems backward to me as we normally mention row-count before column-count. I would prefer: make2Darray(int height, int width). I even prefer the term "row" instead of "height" and "column" instead "width".
3) Your current code do "all the real stuff" inside the if(a != NULL) { That's okay but the code would (to me) be more clear if you instead did if(a == NULL) return NULL;
4) No need to cast calloc
With these updates the code could be:
int** make2Darray(int rows, int columns) {
int **a;
int i = 0;
int j = 0;
if (rows <= 0 || columns <= 0) return NULL;
a = calloc(rows, sizeof(int*));
if(a == NULL) return NULL;
/* allocate memory to store data for each row*/
for(i = 0; i < rows; i++) {
a[i] = calloc(columns, sizeof(int));
if(a[i] == NULL) {
/* clean up */
free2Darray(a, rows);
return NULL; /*aborting here*/
}
}
/* from this point down is the part I implemented, all code above was
given*/
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
a[i][j] = j;
}
}
return a;
}

In your code, the if check seems out of place.
if(a != NULL) {
/* allocate memory to store data for each row?
for(i = 0; i < height; i++) {
a[i] = (int *)calloc(width, sizeof(int));
if(a[i] == NULL) {
/* clean up */
free2Darray(a, height);
return NULL; /*aborting here*/
}
Well, that makes no sense. In case of success, a is supposed to be not equal to NULL.
You should rather have a check for a == NULL and subsequently return NULL;, not the other way around.
That said:
if (height < 0 && width < 0) does not look very good. It's most likely wrong (in this usage context) and counter productive.
All the access for a[i][j] is invalid. You just have the space allocated for the int *s, the int *s themselves do not point to any valid memory. You need to allocate memory to them also (for example, using the width as size).

Related

optimizing C code with imbedded for loops

void evolve(board prv, board nxt){
int i, j;
int n;
printf("\rGeneration %d\n", generation++);
if (printLazy == 1){
lazyPrint(prv);
for (j=0; j < WIDTH; ++j) {
for (i = 0; i < HEIGHT; ++i) {
n = neighbors(prv, i, j);
if (prv[i][j] && (n == 3 || n == 2))
nxt[i][j] = true;
else if (!prv[i][j] && (n == 3))
nxt[i][j] = true;
else
nxt[i][j] = false;
}
}
}
** Some asked me to add the neighbors method so
static int neighbors (board b, int i, int j) {
int n = 0;
int i_left = max(0,i-1);
int i_right = min(HEIGHT, i+2);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int ii, jj;
for (ii = i_left; ii < i_right; ++ii) {
for (jj = j_left; jj < j_right; ++jj) {
n += b[ii][jj];
}
}
return n - b[i][j];
}
So I am working on optimizing this so that it will go faster and I'm stuck on how to optimize this more. Here's what I have so far
void evolve(board prv, board nxt) {
register int i, j;
int n;
bool next;
printf("\rGeneration %d\n", generation++);
if (printLazy == 1){
lazyPrint(prv);
}
for (j=0; j < WIDTH; ++j) {
for (i = 0; i < HEIGHT; ++i) {
n = neighbors(prv, i, j);
if (prv[i][j])
if (n == 2)
next = true;
else if (n == 3)
next = true;
else
next = false;
else
if(n == 3)
next = true;
else
next = false;
nxt[i][j] = next;
}
}
}
Is there a better way to do this or are there any resources or videos y'all recommend?
Thanks, any help is appreciated.
Some ideas Inline your function neighbors(). Or turn it into a macro. Tidy up the conditional. To unroll the inner loop replace every use of i with the literal values so your code looks like :
for (j =0;.......
n = fun(prev, 0 ,j);
If.....
n = fun(prev, 1, j);
if......
and so on.
If the value of HEIGHT was let's say 100, then you get a code explosion of 100 function calls and 100 compound conditionals. Even worse if you unroll the outer loop.
If n was limited to say 8 neighbors, use a lookup table
bool foo[2][8] = { [1][2] = true, [1][3] = true, [0][3] = true };
for (j=0; j < WIDTH; ++j) {
for (i = 0; i < HEIGHT; ++i) {
n = neighbors(prv, i, j);
nxt[i][j] = foo[prv[i][j]][n];
}
}
A common weakness is the neighbors(prv, i, j) function itself. One trick to to oversize the 2D array by 1 on all four sides and populate the edge with false so neighbors() can always check 8 neighbors as it is never used on the edge/corners.
Making sure the 2nd dimension is a power of 2 helps also - simplifies index calculation. So if the original array way 12*11, make the new array (1+12+1)*(1+11+1+4) or 14*16.

Dynamic 2 array in C

I am learning C and I am trying to have a virtual grid in it, where the user can put new grid elements to "activate" into the console. So for example if I am starting with nothing and the user adds (40,50), then the size is at least 40x50 with element (40,50) initialised. If (20,30) follows, it just activates the element at 20,30. But if the user then enters (500,300), it will allocate some more memory and increases the size of the array. I would like to access them easily. I would like to work (I might have to anyway), because they are new for me.
My code (at the moment) is the following:
int width = 4, height = 5;
bool **arr = (bool **) malloc(height * sizeof(bool *));
for (int x = 0; x < height; x++) {
arr[x] = (bool *) malloc(width * sizeof(bool));
}
for (int x = 0; x < height; x++) {
for (int y = 0; y < width; y++) {
*(*(arr + x) + y) = false;
}
}
*(*(arr + 3) + 2) = true;
// user puts a value bigger than (4,5) inside
int newX=10, newY = 10;
//allocate more memory
So I am using a 2D pointer with booleans and I do "malloc" the height first and afterwards make an array of them for the width.
In the last line is just an example of entering the first element at (2,3). The scan method for the user doesn't matter here.
So is there a way of increasing the size of my array afterwards or do I need a totally different concept for it?
=====
The current code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main() {
int width = 4, height = 5;
bool **arr = (bool **) malloc(height * sizeof(bool *));
for (int x = 0; x < height; x++) {
arr[x] = (bool *) malloc(width * sizeof(bool));
}
for (int x = 0; x < height; x++) {
for (int y = 0; y < width; y++) {
*(*(arr + x) + y) = false;
}
}
*(*(arr + 3) + 2) = true;
int newWidth = 10, newHeight = 10;
bool **narr = realloc(arr, newHeight * sizeof(bool*));
if(narr) {
arr = narr;
for(size_t i = 0; i < newHeight; i++){
bool* p = realloc(arr[i] , newWidth * sizeof(bool));
if( !p ){
perror("realloc");
}
arr[i] = p;
}
// here resize the number of elements if needed
}
else {
perror("realloc failed");
exit(EXIT_FAILURE);
}
return 0;
}
Yes there is a mathod called realloc. And you can use that. You can resize the jagged array completely.
bool **narr = realloc(arr , newsize * sizeof(bool*));
if( narr ) {
arr = narr;
for(size_t i = 0; i < newsize; i++){
bool* p = realloc(arr[i] , newsize1 * sizeof(bool));
if( !p ){
perror("realloc");
}
arr[i] = p;
}
// here resize the number of elements if needed
}
else {
perror("realloc failed");
exit(EXIT_FAILURE);
}
Also simplify things write a[1][2] instead of *(*(a+1)+2). The check is needed as realloc may fail - in that case instead of letting your code go awry, take appropriate step as needed.
Also note that you need to set all the newly allocated bool* to NULL. So do this:-
for(size_t i = 0; i < newHeight; i++){
if( i >= height)
arr[i] = NULL;
bool* p = realloc(arr[i] , newWidth * sizeof(bool));
if( !p ){
perror("realloc");
}
arr[i] = p;
}
This is needed because realloc expects address of memory previously allocated with *alloc functions or NULL.
You can use realloc to increase the size of the array
in your situation you'd do
arr = (bool **)realloc(arr, sizeof(bool*) * new_height)
for(int i = 0; i < new_height; i++){
arr[i] = (bool *)realloc(arr, sizeof(bool) * new_width);
}
Note that you have to check whether the array needs to even get bigger, realloc can also "shrink" your array so tread carefully.
Initializing the newly created memory to false:
for(int i = old_height; i < new_height; i++){
for(int j = old_width; j < new_width; j++){
arr[i][j] = false;
}
}
arr[new_height - 1][new_width - 1] = true;

C: Memory usage and problems with Array

I have two arrays (representing rooms) with items that are traveling through the space. I found an interesting way to allocate the ram here in the forum. Here is what I am doing:
First I create an empty room with some default values.
After that I put some elements into it. There are two different items. An obstacle and an item that travels through the room. I have an iteration that runs for example 100 times and puts all items one coordinate further. The obstacles keep their position.
Every iteration has to do the following:
First it creates a new temporary room (new_room). It copies all obstacles because they stay at the same place(id = 3). Next, every item from the old room(room) gets his new coordinate in the new_room. After that I change the rooms, so room gets new_room. I have some big problems with the memory usage. I want to free the old new_room every time I create a new one with createRoomNew().In this implementation I get a segmentation fault. I think because of the function changeroom().
I am really confused right now because I am new to C.... I hope I pointed out what I mean. Thank you very much!
item_node ***room;
item_node ***room_new;
void createRoom(int x, int y, int z)
{
if (room == NULL) {
item_node *allElements = malloc(x * y * z * sizeof(item_node));
room = malloc(x * sizeof(item_node **));
for(int i = 0; i < x; i++)
{
room[i] = malloc(y * sizeof(item_node *));
for(int j = 0; j < y; j++)
{
room[i][j] = allElements + (i * y * z) + (j * z);
}
}
for (j = 0; j < x_format; j++) {
for (k = 0; k < y_format; k++) {
for (l = 0; l < z_format; l++) {
room[j][k][l].id = 3;
room[j][k][l].next = NULL;
}
}
}
}
}
void createRoomNew(int x, int y, int z)
{
if (room_new != NULL) {
for(int i = 0; i < x; i++)
{
free(room_new[i]);
}
free (room_new);
room_new = NULL;
}
if (room_new == NULL) {
item_node *allElements = malloc(x * y * z * sizeof(item_node));
room_new = malloc(x * sizeof(item_node **));
for(int i = 0; i < x; i++)
{
room_new[i] = malloc(y * sizeof(item_node *));
for(int j = 0; j < y; j++)
{
room_new[i][j] = allElements + (i * y * z) + (j * z);
}
}
}
for (j = 0; j < x_format; j++) {
for (k = 0; k < y_format; k++) {
for (l = 0; l < z_format; l++) {
if ((room[j][k][l].next) != NULL) {
if ((room[j][k][l].next->id) == 1) {
room_new[j][k][l] = room[j][k][l];
} else {
room_new[j][k][l].id = 3;
room_new[j][k][l].next = NULL;
}
}
else {
room_new[j][k][l].id = 3;
room_new[j][k][l].next = NULL;
}
}
}
}
}
void changeRoom(item_node *** newRoom)
{
room = newRoom;
}
Example call:
createRoom(200, 200, 200);
createRoomNew(200, 200, 200);
changeRoom(room_new);
createRoomNew(200, 200, 200);
changeRoom(room_new);
From the code it seems you think that when you do free, e.g. free(room_new) that room_new ends up being set to NULL. That is not the case
free() doesn't set a pointer to NULL (it can't), it is still pointing to wherever it was pointing just that the memory is no longer usable. You need to manually set the pointer to NULL after freeing.

C - Read matrix of unknown size from file

I have file that has 30 matrices and each matrix has unknown size of rows and columns(with a max size of 1000). For instance:
0 5 2
5 0 2
1 6 0
0 9 7 4
3 0 9 1
9 1 0 4
9 4 1 0
I need to read each matrix into a 2d array. What would be the most efficient way of doing this?
This is what I have so far:
int** mat=malloc(1000000*sizeof(int*));
for(i=0;i<1000000;++i)
mat[i]=malloc(4*sizeof(int));
while(!feof(file))
{
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++){
fscanf(file,"%d%*[^\n]%*c",&mat[i][j]);
printf("%d\n", mat[i][j]);
}
}
}
Well the most efficient way is definitely not that. First figure out how big an array you need, then allocate it.
Apparently some matrices are small, so there is no need to allocate the maximum size 1000x1000. One way is to put the matrix in a structure to make it easier to keep track of size:
struct s_matrix
{
int **matrix;
int N; //one side of the square matrix N x N
};
typedef struct s_matrix Matrix;
Then allocate and free the matrix
void allocate_matrix(Matrix *m, int N)
{
m->N = N;
m->matrix = (int**)malloc(N * sizeof(int*));
*m->matrix = (int*)malloc(N * N * sizeof(int));
for (int i = 0; i < N; i++)
m->matrix[i] = *m->matrix + i * N;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
m->matrix[i][j] = 0;
}
void free_matrix(Matrix *m)
{
if (!m) return;
if (!m->matrix) return;
free(*m->matrix);
free(m->matrix);
}
Now we can declare how many matrices we need. It looks like this number is fixed at 30, so I don't think we need dynamic allocation.
int main()
{
const int max_count = 30;
Matrix list[max_count];
for (int i = 0; i < max_count; i++)
list[i].matrix = NULL;
allocate_matrix(&list[0], 3);//allocate 3x3 matrix
allocate_matrix(&list[1], 1000);//1000x1000
allocate_matrix(&list[2], 4000);//4000x4000
int **m;
m = list[0].matrix;
m[0][0] = 0;
m[0][1] = 1;
m[0][2] = 2;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
printf("%02d %s", m[i][j], (j == 2) ? "\n" : "");
//...
for (int i = 0; i < max_count; i++)
free_matrix(&list[i]);
printf("hey it worked, or maybe it didn't, or it did but there is memory leak\n");
return 0;
}

Expression cannot be evaluated. Malloc fail

I' having a problem allocating a structure in a function. Here is the code(I'm currently using visual studio 2008):
Mat3x3* ProdMat(Mat3x3 *m, Mat3x3 *n)
{
if(m == NULL || n == NULL)
{
cout << "\t[W] Cannot compute product of the two matrixes one or both are NULL." << endl;
return NULL;
}
Mat3x3 *p; // product
int i, j;
float sum = 0;
p = (Mat3x3*)malloc(sizeof(Mat3x3)); // <= Exp cannot be evaluated
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
sum = 0;
for(int k = 0; k < 3; k++)
{
float a = m->a[i][k];
float b = n->a[k][j];
sum += a * b;
}
p->a[i][j] = sum;
}
}
return p;
}
P contains a matrix with 9 entries. Here is the context in which the error is given:
Mat3x3* compute_final_trans(Trans **transes) // compute product of all transformation matrixes from right to left
{
int k_trans = 0, i, j;
Mat3x3 *final_trans;
if(transes == NULL)
{
printf("\t[E] Cannot compute sequence of NULL transformations.\n");
return NULL;
}
final_trans = (Mat3x3*)malloc(sizeof(final_trans));
for(i = 0; i < 3; i++) // generate eye matrix
for(j = 0; j < 3; j++)
{
if(i == j)
{
final_trans->a[i][j] = 1;
}
else
{
final_trans->a[i][j] = 0;
}
}
while(transes[k_trans++]);
for(i = k_trans - 2; i >= 0; i--)
{
final_trans = ProdMat(transes[i]->matrix, final_trans); // <= ERROR
}
return final_trans;
}
Final trans is initialised as the eye matrix and transes have been succesfully computed before this step(before calling compute_final_trans). The while is used to retreieve the number of transformations that transes contains. At line:
final_trans = ProdMat(transes[i]->matrix, final_trans);
ProdMat fails to allocate memory for p which is a pointer to a Mat3x3 structure.
perror suggests that there isn't enough memory to allocate to the structure. However I'm only using 1GB of RAM(4GB in all).
Any help/suggestion/reference will be very much appreciated.
Sebi
malloc(sizeof(final_trans))
This is bad. You are only allocating enough space for a pointer, not space for an array.

Resources