dynamic 2d matrix implementation - c

insdead of my static matrix i try to get 2d dynamic matrics
all i want to do is to change the init function so instead of using the defined heigh and width
it would init dynamicaly - please show me the how
void init(int board[][WIDTH], int rows) {
int x, y;
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
board[y][x] = 0;
/* Scatter some live cells: */
board[10][25] = 1;
board[10][26] = 1;
board[10][27] = 1;
board[11][25] = 1;
board[12][26] = 1;
}
int main(void) {
int board[HEIGHT][WIDTH];
init(board, HEIGHT);
..
..
}
this is the code i wanted to use - please show me the right implamintation
without using #define WIDTH 50 #define HEIGHT 20
int **matrix_dyn(int n, int m)
{
int i = 0;
int j = 0;
printf ("please enter the horizontal size of the board \n");
scanf ("%d", &n);
printf ("please enter the vertical size of the board \n");
scanf ("%d", &m);
int **board = (int**)malloc(n * sizeof(int*));
printf("please enter the 0's or 1's to fill the matrix \n");
for (i = 0; i <= n; i++)
board[i] = (int*)malloc(m*sizeof(int));
for(i = 0; i <= n; i++)
{
for(j = 0; j <= m; j++)
scanf ("%d", &board[i][j]);
}
return board;
}
this is all my code:
#include <stdio.h>
#define WIDTH 50
#define HEIGHT 20
void init(int board[][WIDTH], int rows) {
int x, y;
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
board[y][x] = 0;
/* Scatter some live cells: */
board[10][25] = 1;
board[10][26] = 1;
board[10][27] = 1;
board[11][25] = 1;
board[12][26] = 1;
}
void print(int board[][WIDTH], int rows, int cols)
{
int x, y;
char c;
for (y = 0; y < rows; y++) {
for (x = 0; x < cols; x++) {
if (board[y][x] == 1)
printf("X");
else
printf(" ");
}
printf("\n");
}
printf("Press any key to continue:\n");
getchar();
}
int count_neighbors(int board[][WIDTH], int rows,
int y, int x)
{
int i, j;
int result = 0;
for (i = -1; i <= 1; i++)
if ((y+i >= 0) && (y+i < rows))
for (j = -1; j <= 1; j++)
if ((x+j >= 0) && (x+j < WIDTH))
if ((i != 0) || (j != 0))
result += board[y+i][x+j];
return result;
}
int step(int board[][WIDTH], int rows) { // now returns a bool
int x, y;
int neighbors[HEIGHT][WIDTH];
int changed = 0; // save changes
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
neighbors[y][x] = count_neighbors(board, rows, y, x);
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
if (board[y][x] == 1) { /* Currently alive */
if (neighbors[y][x] < 2)
{
board[y][x] = 0; /* Death by boredom */
changed = 1; // change happened
}
else if (neighbors[y][x] > 3)
{
board[y][x] = 0; /* Death by overcrowding */
changed = 1; // change happened
}
}
else { /* Currently empty */
if (neighbors[y][x] == 3)
{
board[y][x] = 1;
changed = 1; // change happened
}
}
return changed; // return the status (changed yes/no?)
}
int main(void) {
int board[HEIGHT][WIDTH];
init(board, HEIGHT);
while (1) {
print(board, HEIGHT, WIDTH);
if(step(board, HEIGHT) == 0) // no change
break; // leave the loop
}
return 0;
}

Declare & allocate board like so:
int *board = malloc( n * m * sizeof(int) );
Then, anytime you wish to access board[x][y], use the following expression:
board[y*n+x]

Try using a struct, heres a simple implementation I wrote up (compiled using GCC, to support the constructor attribute.
// IntGrid.h
typedef struct intGrid_t {
int **data;
int rows;
int cols;
} *IntGridRef;
struct {
IntGridRef(* create)(int, int);
void (* print)(IntGridRef);
void (* free)(IntGridRef);
int **(* data)(IntGridRef);
int (* rows)(IntGridRef);
int (* cols)(IntGridRef);
} IntGrid;
// IntGrid.c
IntGridRef _intGrid_create(int rows, int cols);
void _intGrid_print(IntGridRef this);
void _intGrid_free(IntGridRef this);
int **_intGrid_data(IntGridRef this);
int _intGrid_rows(IntGridRef this);
int _intGrid_cols(IntGridRef this);
__attribute__((constructor))
static void intGrid_setup()
{
IntGrid.create = _intGrid_create;
IntGrid.print = _intGrid_print;
IntGrid.free = _intGrid_free;
IntGrid.data = _intGrid_data;
IntGrid.rows = _intGrid_rows;
IntGrid.cols = _intGrid_cols;
}
IntGridRef _intGrid_create(int rows, int cols)
{
IntGridRef this = calloc(1, sizeof(struct intGrid_t));
this->rows = rows;
this->cols = cols;
this->data = calloc(rows, sizeof(int *));
for (int i = 0; i < rows; i++) {
this->data[i] = calloc(cols, sizeof(int *));
}
return this;
}
void _intGrid_print(IntGridRef this)
{
printf("{\n");
for (int i = 0; i < this->rows; i++) {
printf(" { ");
for (int j = 0; j < this->cols; j++) {
printf("%i", this->data[i][j]);
if (j != this->cols - 1)
{
printf(", ");
}
}
printf(" }\n");
}
printf("}\n");
}
void _intGrid_free(IntGridRef this)
{
for (int i = 0; i < this->rows; i++) {
free(this->data[i]);
}
free(this->data);
free(this);
}
int **_intGrid_data(IntGridRef this)
{
return this->data;
}
int _intGrid_rows(IntGridRef this)
{
return this->rows;
}
int _intGrid_cols(IntGridRef this)
{
return this->cols;
}
Example Usage:
int main(int argc, char *argv[])
{
IntGridRef grid = IntGrid.create(10, 10);
for (int i = 0; i < IntGrid.rows(grid); i++) {
for (int j = 0; j < IntGrid.cols(grid); j++) {
IntGrid.data(grid)[i][j] = arc4random_uniform(10);
}
}
IntGrid.print(grid);
IntGrid.free(grid);
return 0;
}

You're basically there, but instead of having the compiler generate code to map [x][y] to a specific element in the memory allocated for board, you have to do the mapping yourself: board[x*h+y] or board[y*w+x] (where w is width & h is height); it doesn't matter which you choose, just be consistent (a function or macro would help here).

Related

I want to show elements of a matrix that appear only once

I got this but it I can't seem to make it work, tried everything I could think of.
#include <stdio.h>
#include <stdlib.h>
void alocare_vector(int *v, int nr, int elem)
{
int *v1;
if ((v1 = realloc(v, nr * sizeof(int))) == NULL)
{
printf("Memorie insuficienta");
free(v);
exit(EXIT_FAILURE);
}
v = v1;
v[nr - 1] = elem;
}
int main()
{
int a[100][100];
int n, *v = NULL, i, j, k, l, ok = 0, nr = 0;
printf("Number de elements n:");
scanf("%d", &n);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &a[i][j]);
for (k = 0; k < n; k++)
{
for (l = 0; l < n; l++)
{
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (a[k][l] == a[i][j] && (k != i && l != j))
ok = 1;
if (ok == 0)
{
nr++;
alocare_vector(v, nr, a[k][l]);
}
ok = 0;
}
}
if (nr > 0)
{
printf("Elements:");
for (i = 0; i < nr; i++)
{
printf("%d ", v[i]);
}
}
free(v);
}
Basically, I need to create a matrix, ans print the elements that appear only once using an array with dynamic memory allocation.
one simple fix is to declare the "int * v" as a global variable and modify the function as alocare_vector(int nr, int elem)
now using a hash table you can store the numbers in the array, below is the your implementation just a bit modified.
#include <stdio.h>
#include <stdlib.h>
int hash[1000]={0};
int * v=NULL;
void alocare_vector(int nr, int elem)
{
int *v1;
if ((v1 = (int*)realloc(v, nr * sizeof(int))) == NULL)
{
printf("Memorie insuficienta");
free(v);
exit(EXIT_FAILURE);
}
v = v1;
v[nr - 1] = elem;
}
int main()
{
int a[100][100];
int n, i, j, nr = 0;
printf("Number de elements n:");
scanf("%d", &n);
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d", &a[i][j]);
++hash[a[i][j]];
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if(hash[a[i][j]]==1)
{
nr++;
alocare_vector(nr, a[i][j]);
}
}
}
if (nr > 0)
{
printf("Elements:");
for (i = 0; i < nr; i++)
{
printf("%d ", v[i]);
}
}
free(v);
}
When calling a your funtion you pass a copy of the pointer. Therfore any modifications to this local copy of the pointer will not affect the copy in main. Therfore you need a refrence or pointer to the pointer in main.
void alocare_vector(int **v, int nr, int elem)
{
...
*v = v1;
}
Here you have brut force example how to generate array of distinct elements of the 2D array:
typedef struct
{
size_t length;
int data[];
}data_t;
data_t *add_element(data_t *arr, int element)
{
size_t newsize = arr ? arr -> length : 0;
arr = realloc(arr, newsize * sizeof(arr -> data[0]) + sizeof(*arr));
if(arr)
{
arr -> length = newsize;
arr -> data[newsize - 1] = element;
}
return arr;
}
int isPresent(size_t rows, size_t cols, size_t vrow, size_t vcol, int (*array)[cols])
{
int val = array[vrow][vcol];
for(size_t row = 0; row < rows; row++)
for(size_t col = 0; col < cols; col++)
{
if(vcol == col && vrow == row) continue;
if(array[row][col] == val)
{
return 1;
}
}
return 0;
}
data_t *distinctElements(size_t rows, size_t cols, int (*array)[cols])
{
data_t *dist = NULL;
for(size_t row = 0; row < rows; row++)
{
for(size_t col = 0; col < cols; col++)
{
if(!isPresent(rows, cols, row, col, array))
{
data_t *tmp = add_element(dist, array[row][col]);
if(tmp) dist = tmp;
else { /* error handling */}
}
}
}
return dist;
}

The pointer variables overflows when they store integers larger than 1024 and some adresses seem to be locked.in C

How do I get to write to 2D pointers where I have pnumber[2%4][2%4] and how can I get pnumber with more than 3 ciphers to be displayed?
I'm making a program to write pascals triangle in C.
When the pointer pnumbers[i][j] have both i and j = 2 mod 4, except for when i and j = 2, then my program won't write to the address and give the error message:
pascals triangle: malloc.c:2406: sysmalloc: Assertion '{old_top == initial_top (av) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
Aborted.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =7;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
/*
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
*/
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
When I avoid writing to these addresses and just print them out I get some seemingly random integer at these memory addresses.
Also when avoid these addresses and just print out so many rows that I get some spots with a higher integer with more than 3 siphers, it seems to overflow - and I don't see the logic behind it.
The result of running the second code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =20;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
/*
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
*/
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
But row number 13 is still quite messed up.
Code is experiencing int overflow and thus undefined behavior (UB).
With 32-bit int and int factorial(int p), p > 12 oveflows the int range.
Code could use a wider integer type (long long works up to p==20), but improvements can be made at NchooseM() to avoid overflow for higher values.
Something like the below. Works up to int n = 30;
int NchooseM(int n, int m) {
// return factorial(n)/(factorial(n-m)*factorial(m));
int nm = 1;
int den = 1;
for (int i = m+1; i <= n; i++) {
assert(INT_MAX/i >= nm);
nm *= i;
assert(nm % den == 0);
nm /= den++;
}
return nm;
}
Tried unsigned long long and works up to int n = 62;
Edit: Another bug:
I "fixed" by initializing all to 1, yet I suspect something remains amiss in /* Calculating the value of pnumbers[k][l] */ for (i = 0; i < n; i++) { code.
pnumbers[i] = malloc((i + 1) * sizeof pnumbers[i][0]);
for (int j = 0; j < i + 1; j++) {
pnumbers[i][j] = 1;
}
Aside: rather than pnumbers[i] = (int *) malloc((i+1) * sizeof(int));, consider below with no unneeded cast nor trying to match the right type.
pnumbers[i] = malloc(sizeof pnumbers[i][0] * (i+1));

Filling a two-dimensional array correctly

I'm stuck in place. I cannot come up with the algorithm and will fill up the square matrix as below:
"Gets a natural number n from the user n not more than 20. Fills in a square table as below. The numbers below the main diagonal (a21; a31; a32, etc.) are given by the user."
#include <stdio.h>
int main() {
int tab[20][20] = { {0},{0} };
int size = 0;
printf("Enter the natural number n not more than 20: ");
while (scanf_s("%d", &size) != 1 || size < 0 || size >20 || getchar() != '\n')
{
while (getchar() != '\n');
printf("Error. Correct!");
}
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
if (y==x)
{
tab[x][y]=1; // what's next?
}
}
}
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
printf("%d ",tab[x][y]);
}
printf("\n");
}
return 0;
}
This is what you want.
You do not need to use if statement.
#include <stdio.h>
int main()
{
int tab[20][20]={ {0},{0} };
int size = 6,n=0;
for (int x = 0; x < size; x++)
{
n=0;
for (int y = x; y < size; y++)
{
n++;
tab[x][y]=n; //fill the upper part of the matrix including diagonal
}
}
for (int x = 1; x < size; x++)
{
for (int y = 0; y < x; y++)
{
tab[x][y]=8; //fill the lower part of the matrix
//or ask for user input
}
}
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
printf("%d ",tab[x][y]);
}
printf("\n");
}
return 0;
}
i think this would work for just above the main diagonal..
#include <stdio.h>
int main() {
int tab[20][20] = { {0},{0} };
int size = 0;
printf("Enter the natural number n not more than 20: ");
while (scanf("%d", &size) != 1 || size < 0 || size >20 || getchar() != '\n')
{
while (getchar() != '\n');
printf("Error. Correct!");
}
for (int x = 0; x < size; x++)
{
printf("%d. diagonal value:", x+1);
scanf("%d", & tab[0][x]);
}
for (int x = 0; x < size; x++)
{
for (int y = x; y < size; y++)
{
if (y==x)
{
tab[x][y]=1; // what's next?
}
else if(x>0){
tab[x][y]=tab[x-1][y-1];
}
}
}
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
printf("%d ",tab[x][y]);
}
printf("\n");
}
return 0;
}
output:

Pointers exit code 6

Well i m struggling with the pointers, why doesn t work the function biggest in the end (yes of that s dummy function)? (exit code 6)
Ty for help
code:
int search(int const a[], int n, int key) {
for (int *i = a; i < a + n; i++) {
if ( key == *i ) return 1;
}
return 0;
}
void print_row(int const a[], int n, int row) {
for (int *i = a + n * row; i < a + n * (row + 1); i++) {
printf("%d ", *i);
}
printf("\n");
}
void biggest(double x, long *int_part, double *frac_part) {
*int_part = (long) x;
*frac_part = x - *int_part;
}
main () {
int tempretures[7][24];
for (int *i = &tempretures[0][0]; i < &tempretures[7][24]; i++) {
static int j = 1;
*i = j;
j+=2;
}
tempretures[6][5] = 32;
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 24; j++) {
printf("%d ", tempretures[i][j]);
}
printf("\n");
}
printf("Is it: %d\n", search(tempretures, 7*24, 32));
for (int i = 0; i < 7; i++) {
print_row(tempretures, 24, i);
}
long a = 0; double b = 0;
biggest(5.67, &a, &b);
printf("%li", a);
}
for (int *i = &tempretures[0][0]; i < &tempretures[7][24]; i++) {
static int j = 1;
*i = j;
j+=2;
}
This runs way past the end of the array, stopping only when it hits every element of row number 7, but there is no row number 7.

C int array issue

my output values
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define W 160
#define H 105
struct dungeons {
int x;
int y;
int width;
int height;
};
void randomNumberGenerator(int seed);
void makeGameBoard(int gameBoard[W][H]);
void makeDungeonRooms(struct dungeons d[10]);
void printGame(int gameBoard[W][H]);
int main(int argc, char *argv[]) {
int gameBoard[W][H];
//int gameBoard[160][105] = {2};
struct dungeons d[10];
makeGameBoard(gameBoard);
makeDungeonRooms(d);
printGame(gameBoard);
return 0;
}
void randomNumberGenerator(int seed) {
srand(seed);
}
void makeGameBoard(int gameBoard[160][105]) {
int i;
int j;
for (j = 0; j < 105; j++) {
for (i = 0; i < 160; i++) {
gameBoard[i][j] = 2;
//gameBoard[i][j] = 2;
/*
if (j == 0) {
gameBoard[i][j] = 2;
} else
if (j == 104) {
gameBoard[i][j] = 2;
} else
if (i == 0) {
gameBoard[i][j] = 2;
} else
if (i == 159) {
gameBoard[i][j] = 2;
} else {
gameBoard[i][j] = 4;
}
*/
}
}
gameBoard[0][1] = 2;
gameBoard[0][0] = 2;
gameBoard[159][0] = 3;
}
void makeDungeonRooms(struct dungeons d[10]) {
int i;
for (i = 0; i < W; i++) {
d[i].x = 0;
d[i].y = 0;
d[i].width = 0;
d[i].height = 0;
}
}
void printGame(int g[W][H]) {
int i;
int j;
for (i = 0; i < W; i++) {
for (j = 0; j < H; j++) {
printf("%d", g[i][j]);
/*
if (g[i][j] == 2) {
printf("|");
} else
if (g[i][j] == 1) {
printf("X");
} else {
printf(" ");
}
*/
}
printf("\n");
}
}
I'm making a grid. But the first 5 rows and half of the 6th row, when printed output the value 0. I'm setting everything to 2 in the for loop, and even after when I try to manually change the value, it still doesn't. The last one [159][0] works but nothing in the first 5 rows and half of the 6th seem to work. They stay 0. Why?
The problem is here:
void makeDungeonRooms(struct dungeons d [10]){
int i;
for(i = 0; i< W; i++){
d[i].x = 0;
d[i].y = 0;
d[i].width = 0;
d[i].height = 0;
}
}
where #define W 160. Accessing array out of bound can trigger undefined behavior. It can trigger a segmentation fault, it can remain unnoticed for a long time or alter the output of the program in very strange ways. Here, zeroing the dungeons also partly zeroed the gameBoard. Keep it that way: your game is going to be hilarious!

Resources