How to create multi-dimensional array with dynamic rows and columns - c

I am trying to code a array with dynamic rows and columns (multi-dimensional).
This is what I've tried:
#include <stdio.h>
#include <stdlib.h>
#define LEN(arr) ((int) (sizeof (arr) / sizeof (arr)[0]))
int main() {
int size, q = 0;
// get arr size from stdin
scanf("%d", &size);
int *arr[size];
for (int i=0; i<size; i++) {
int len, element = 0;
// get length of column from stdin
scanf("%d", &len);
arr[i] = malloc(len * sizeof(int));
for(int j=0; j<len; j++) {
// get each column's element from stdin and append to arr
scanf("%d", &element);
arr[i][j] = element;
}
}
for (int i=0; i< LEN(arr); i++)
printf("%d\n", LEN(arr[i]));
}
stdin:
2
3 4 5 6
4 1 2 3 4
The first line of input is the size/amount of arrays to be stored in arr (2),
the following lines begin with the size of the columns (3, 4) followed by the elements to store (4 5 6, 1 2 3 4) in each column.
stdout:
2
2
When I run this program with the output is 2 meaning each column's length is 2, this is unintended. I am seeking for a solution to output the correct column lengths. What am I doing wrong?
The intended stdout is:
3
4

arr is an array, so sizeof(arr) gives you the size in bytes of the array as expected.
arr[i] is not an array however. It is a pointer, specifically a int *. So sizeof(arr[i]) gives you the size in bytes of an int *.
When you allocate memory dynamically, you need to keep track of how much space was allocated. You can do this by maintaining a separate array with size size of each subarray.
int *arr[size], arr_len[size];
...
for (int i=0; i<size; i++) {
...
arr[i] = malloc(len * sizeof(int));
arr_len[i] = len;
...
}
for (int i=0; i< LEN(arr); i++)
printf("%d\n", arr_len[i]));

Related

Get pointer to column of 2D array in C

I am new to C programming and especially to pointers. In the program I wrote, I tried to write a function that returns a pointer to specified column of array. See the code below for better understanding (or confusion :) ):
#include <stdio.h>
#include <stdlib.h>
// function for getting pointer to specidifed column index
// 'ind' is index of requested column, 'ncol' is number of items in column
int* get_col(const int* arr, unsigned int ind, unsigned int ncol);
int main() {
unsigned int n;
printf("Input matrix size : ");
scanf("%i", &n);
int arr[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
arr[i][j] = i * n + j;
}
for (int i = 0; i < n; i++) {
printf("values in column %d: \n", i);
int *col = get_col((int*)arr, i, n);
for (int j = 0; j < n; j++) {
printf("%d ", *col);
col = col + 1;
}
printf("\n");
}
return 0;
}
int* get_col(const int* arr, unsigned int ind, unsigned int ncol) {
int *result = malloc(sizeof(int) * ncol);
for (int i = 0; i < ncol; i++)
*result = *(arr + i*ncol + ind);
return result;
}
As you see get_col function accepts pointer to array, column index and column size (n of elements in column, i.e number of rows) as arguments and trying to return a pointer to 1D array that contains values of column at requested index. The problem is that result is not correct. In case n=3 results are like below:
Input matrix size : 3
values in column 0:
6 0 0 // supposed to be 0 3 6
values in column 1:
7 0 0 // supposed to be 1 4 7
values in column 2:
8 0 0 // supposed to be 2 5 8
I think that the problem lies in my understanding of pointers not the algorithm implemented. Actually, at first I didn't use pointer in my get_col function like below:
int result[ncol];
// ... do my work here to populate array
return &result;
Then as compiler complains warning: function returns address of local variable [-Wreturn-local-addr], I converted result from array to pointer in get_col function like above. What is the problem in this code? Did I use pointers in get_col function as it should be?
In the following line:
*result = *(arr + i*ncol + ind);
You're always writing to the same memory address.
Change it to one of the two following options:
*(result + i) = *(arr + i*ncol + ind);
result[i] = *(arr + i*ncol + ind);
Regarding your second problem when you used:
int result[ncol];
// ... do my work here to populate array
return &result;
You should understand that result variable in this case (static-memory allocation) is stored in the stack. So, after your function returns, the variable values doesn't exist anymore in the memory. That's why you need dynamic-memory allocation. In dynamic-memory allocation, that values stay in the memory until you call free by yourself.

Trying to append elements to multi-dimensional array. Exception thrown when trying to run the application

int main()
{
int r;
scanf("%d", &r);
int **arr = (int *)malloc(r * r * sizeof(int));
*(*(arr + r) + r);
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= r; j++)
{
printf("Enter element %d.%d: \n", i,j);
scanf("%d", &arr[i-1][j-1]);
}
}
getch();
}
so this recently happened, basically what I want is to append matrix elements to 2d array, but it says
'Exception thrown at 0x0F1B97AE (ucrtbased.dll) in Matrix.exe: 0xC0000005: Access violation writing location 0xCDCDCDCD'
don`t know what to do :( help please
You're using a malloc'ed block of memory as a C multi-dimensional array. Instead, you need to use a single set of square brackets.
Instead of arr[i-1][j-1], you need something like arr[i * r + j].
I'm surprised that most compilers would accept this by default because you use an int * to initialize and int **.
The problem is that you don't allocate or create a "two-dimensional" array. Your memory allocation allocates one array of r * r elements.
This single array can't be used as an array of arrays.
The usual solution to create a dynamic array of arrays is to create a jagged array:
int **arr = malloc(r * sizeof(int *));
for (unsigned i = 0; i < r; ++i)
{
arr[i] = malloc(r * sizeof(int));
}
You can use a large single array in a "two-dimensional" way, but you need to use some other arithmetic to access the elements of it:
arr[i * r + j]
[Note that the above requires zero-based indexes i and j]
int **arr = (int *)malloc(r * r * sizeof(int));
You can't create a 2D array with a single allocation like that, at least not one you can access with a int **. What you have instead is space for r * r, objects of type int which can be accessed via a int * and some additional arithmetic.
When you later do this:
*(*(arr + r) + r);
The first dereference is fine, since arr points to an allocated buffer. The second one is not, however, because you read an uninitialized value from that allocated buffer and attempt to use to as a valid address. This invokes undefined behavior which in this cause results in a crash.
You need to allocate space for an array of int *, they for each of those allocate an array of int:
int **arr = malloc(r * sizeof(int *));
for (int i=0; i<r; i++) {
arr[i] = malloc(r * sizeof(int));
}
Just forget all about this int** nonsense and allocate a 2D array instead:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int r;
scanf("%d", &r);
int (*arr)[r] = malloc( sizeof(int[r][r]) );
for (int i = 0; i<r; i++)
{
for (int j = 0; j<r; j++)
{
arr[i][j] = 1; // some sort of input here
printf("%d ", arr[i][j]);
}
printf("\n");
}
free(arr);
}
Output example with input 5:
5
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
For this to work, you need a standard-compliant C compiler from this millennium.
More information: Correctly allocating multi-dimensional arrays.

2D array program shows garbage value in output

I am writing this simple code for dynamically allocated 2D array and displaying it. When I execute this program, it gives garbage value in the first row. How is that? Any errors in my program?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int **ptr, limit, i, j;
printf("Enter the limit: ");
scanf("%d", &limit);
ptr = (int **) malloc(limit * (sizeof(int)));
for(i=0; i<limit; i++)
{
*(ptr+i) = (int *) malloc((i+1) * sizeof(int));
for(j=0; j<=i; j++)
{
ptr[i][j] = i;
}
}
for(i=0; i<limit; i++)
{
for(j=0; j<=i; j++)
{
printf("%d ", ptr[i][j]);
}
printf("\n");
}
return 0;
}
Output:
Enter the limit: 4
0
1 1
2 2 2
3 3 3 3
Enter the limit: 5
9478320
1 1
2 2 2
3 3 3 3
4 4 4 4 4
If I try to print the 2D array with the limit is less than or equal to 4, it works fine. What am I missing here..
Thanks
Maybe there are other issues as well; but one thing is for sure - you are allocating the wrong size for the pointer elements:
ptr = (int **) malloc(limit * (sizeof(int)));
though there should be limit objects of pointers to int, you are allocating ints. So it needs to be...
ptr = malloc(limit * (sizeof(int*)));
BTW: In C, avoid casting the result of malloc.

C: populate multiple dimension array [duplicate]

This question already has answers here:
Correctly allocating multi-dimensional arrays
(2 answers)
Closed 5 years ago.
I have several numbers that i want to insert into Matrix.
This is how i am get all my numbers one by one:
int i, n;
int ch;
int *arr;
int dimension;
int numbers = 0;
char str[512];
// User input.
fgets(str, sizeof str, stdin);
for (i = 0; i <= (strlen(str)); i++)
{
if (str[i] != '\0' && !isspace(str[i]))
{
int num = atoi(&str[i]);
numbers++;
if (i == 0)
{
dimension = num;
arr = allocatearraysize(dimension);
}
// Here i want to add the current number to my `Maxtix`.
}
}
free(arr);
int* allocatearraysize(int size)
{
return (int *)malloc(size * size * sizeof(int));
}
So i try:
arr[0][0] = num;
only for see if thats works but got an error:
expression must have pointer-to-object type
Edit
So if my input is 2 1 2 3 4:
the first number (2) means that my matrix should be 2x2 and i expected 4 numbers after this number (2).
In case the numbers of number not match the first number for example:
3 1 2 3 4
The first number here is 3 so after this number i excepted to 9 numbers so in this case i only want to print error message.
But any way i want to insert this numbers into my Matrix.
You can't access arrays with var[i][j] if it's not a 2-dimensional array.
A possible answer would be :
int i, j, n;
int ch;
int **arr;
int size;
int numbers = 0;
char str[512];
fgets(str, sizeof str, stdin);
size = atoi(&str[0]);
if(size > 1) {
arr = (int**) malloc(size * sizeof(int*))
for (i = 0; i < size; i++)
arr[i] = (int*) malloc(size * sizeof(int));
// Fill with arr[i][j]
free(arr);
}
else {
fprintf(stderr, "Size must be a valid number");
}

How to malloc 2D arrays? [duplicate]

This question already has answers here:
Allocating 2-D array in C
(2 answers)
Closed 8 years ago.
I need to create a two dimensional array. Presently I created it as
int a[100][100]
but I need to allocate the memory dynamically using malloc in C language. I used the code
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n=6, m=5, i, j;
int **a = malloc(n * sizeof(int *));
for(i = 0; i < m; i++)
a[i] = malloc(m * sizeof(int));
for( i = 1; i <= n; i++ )
{
for( j = 1; j <= m; j++ )
{
scanf("%d %d",&a[i][j]);
}
}
return 0;
}
but now while inputting the elements into the array it shows SEGMENTATION ERROR.
You say in the comments that n is the number of rows. So you need to allocate n rows each of length m. Therefore, the second for loop condition should be i < n. Also, you should check the return value of malloc for NULL in case it fails to allocate memory. I suggest the following change -
long long **a = malloc(n * sizeof(*a));
for(i = 0; i < n; i++)
a[i] = malloc(m * sizeof(*a[i]));
Please note that a multi-dimensional array is not a fundamentally new type. It's simply an array of elements where each element itself is an array (for a 2D array), an array of arrays (for a 3D) array and so on. If you are using C99, you can allocate your array cleanly and succinctly as
int nrow = 4; // number of rows
int ncol = 8; // number of columns
// define arr to be a pointer to an array of ncol ints, i.e.,
// arr is a pointer to an object of type (int[ncol])
int (*arr)[ncol] = malloc(sizeof(int[nrow][ncol]));
// check the result of malloc for NULL
if(arr == NULL) {
printf("malloc failed to allocate memory\n");
// handle it
}
// do stuff with arr
for(int i = 0; i < nrow; i++)
for(int j = 0; j < ncol; j++)
arr[i][j] = i + j;
// after you are done with arr
free(arr);
You should also go through this - How do I work with dynamic multi-dimensional arrays in C?
You have three errors: The first is that you allocate only 5 secondary arrays, but in the input you loop over 6 of them.
The second problem is that array indices are zero-based, i.e. the index start at zero and goes to the size minus one.
The third problem is that you scan for two numbers (why?), but you provide only one destination pointer to scanf.
you just need
long *a = malloc(100*100*sizeof(long));
if you want one single big block of memory.
if you want an array of long* pointers and then each array to be in a separate block of memory go like this:
long **a = malloc(100*sizeof(long*));
for (i=0; i<100; i++) {
a[i] = malloc(100*sizeof(long));
}
This creates 1 array of long* pointers, and then 1 array of 100 longs of each pointer, but I'm not sure now if you say a[10][15] for example if it would calculate position of the element as if its a continuous block. Check that out. :)
If you have C99 use Variable Length Array
#include <stdio.h>
#include <stdlib.h>
int main(void) {
unsigned rows, cols;
printf("Enter rows and columns: ");
fflush(stdout);
scanf("%u%u", &rows, &cols);
int (*a)[cols]; // pointer to VLA
a = malloc(rows * cols * sizeof a[0][0]);
if (a) {
for (unsigned r = 0; r < rows; r++) {
for (unsigned c = 0; c < cols; c++) {
a[r][c] = r*c;
}
}
printf("the element at [4, 2] is %d\n", a[4][2]);
free(a);
}
return 0;
}
Otherwise, you need to calculate the indexing manually.
There are many problems in your code
First, you need long long a[100][100] but you only allocate enough space for ints
a[i] = malloc(m * sizeof(int));
You're also accessing arrays out-of-bound. Indexes start from 0 to array_length-1.
Another problem is that you scanf 2 int values but only provide the address for 1.
scanf("%d %d",&a[i][j]);
You can allocate a 100-element array of pointers, each points to an array of another 100-element array but that's not good because it takes time to do 100 mallocs, and the resulting memory most probably isn't contiguous, which makes it cache unfriendly. There are also a small memory overhead too because the memory allocator must round it up to the nearest block size and this is most probably powers of 2, which may be large as you allocate more and more elements in the first dimension.
You should declare a 1D array of size 100*100 instead. This will be much faster and improve cache coherency. To get the element at a[i][j] just do a[i*WIDTH + j]
long long* a = malloc(WIDTH*HEIGHT*sizeof(long long));
for (i = 0; i < WIDTH*HEIGHT; i++)
{
scanf("%lld ",&a[i]);
}
for (i = 0; i < HEIGHT; i++)
{
for (j = 0; j < WIDTH; j++)
{
printf("%lld ", a[i*WIDTH + j]);
}
printf("\n");
}

Resources