Is it possible to create an array of arrays in c
Thank you.
It's the same as for example in PHP:
int arrayInArray[10][50];
You read data out of it with:
printf("%d", arrayInArray[3][37]);
I bet you mean Multi Dimensional Array instead of "array of arrays".
Some links for this topic:
http://www.dfstermole.net/OAC/harray2.html
http://webster.cs.ucr.edu/AoA/Windows/HTML/Arraysa2.html
For using an array of arrays with all the power of C you should have some knowledge of dynamic memory handling in c, with the functions malloc, realloc, and free, and some knowledge about pointers. For this example that you ask a possible solution would be this:
#include <stdio.h>
void main(int argc, char* argv[]){
int** myArray; /* This would be a double pointer, because you want a two dimension array.*/
int firstDimension = 10;
int secondDimension = 20;
int i;
myArray = (int**)malloc(firstDimension*sizeof(int*)); This way you initialize the first dimension of the array.
for(i = 0; i < firstDimension; i++){
myArray[i] = (int*)malloc(secondDimension*sizeof(int));
}
/*Once you have the array initialized, you can access in the way myArray[i][j];*/
/*For releasing resources */
for(i = 0; i < firstDimension; i++){
free(myArray[i]);
}
free(myArray);
}
This is the dynamic way, the one that is teached on CS courses.
If you need an array of arrays then you should use structs.
typedef ArrayStruct* ArrayStructPtr;
struct ArrayStruct
{
void* array;//Node array
ArrayStructPtr arrays;//Pointer to sub arrays
};
int main()
{
ArrayStruct* a;//Declare Some Arrays
a=(ArrayStruct*)malloc(sizeof(ArrayStruct)*N);
for(int i=0;i<N;i++)
{
a[i].array=(void*)malloc(sizeof(int)*N);//Malloc the actual array
a[i].arrays=NULL;//Malloc subarrays if needed
}
//add subarray on array 0
ArrayStruck * temp=(ArrayStruct*)malloc(sizeof(ArrayStruct));
temp->array=(void*)malloc(sizeof(char)*MAXNAME*N);
temp->arrays=NULL;
a[0]=arrays=temp;
return 0;
}
What you need is a List Of arrays Where each node of the struct can hold an array and a pointer to another node.
The array type is void* to support int,float,char*.
So each array can have as many subarrays as you want.You can create 3 dimension Arrays if you want!
Related
I want to use a struct to contain some data and passing them between different functions in my program,this struct has to contain a dynamic 2D array (i need a matrix) the dimensions change depending on program arguments.
So this is my struct :
struct mystruct {
int **my2darray;
}
I have a function that read numbers from a file and has to assign each of them to a cell of the struct array.
I tried doing this :
FILE *fp = fopen(filename, "r");
int rows;
int columns;
struct mystruct *result = malloc(sizeof(struct mystruct));
result->my2darray = malloc(sizeof(int)*rows);
int tmp[rows][columns];
for(int i = 0;i<rows;i++) {
for(int j = 0;j<columns;j++) {
fscanf(fp, "%d", &tmp[i][j]);
}
result->my2darray[i]=malloc(sizeof(int)*columns);
memcpy(result->my2darray[i],tmp[i],sizeof(tmp[i]));
}
But this is giving me a strange result : all the rows are correctly stored except for the first.
(I'm sure that the problem is not in the scanning of file).
While if i change the fourth line of code in this :
result->my2darray = malloc(sizeof(int)*(rows+1));
it works fine.
Now my question is why this happens?
Here's an answer using some "new" features of the language: flexible array members and pointers to VLA.
First of all, please check Correctly allocating multi-dimensional arrays. You'll want a 2D array, not some look-up table.
To allocate such a true 2D array, you can utilize flexible array members:
typedef struct
{
size_t x;
size_t y;
int flex[];
} array2d_t;
It will be allocated as a true array, although "mangled" into a single dimension:
size_t x = 2;
size_t y = 3;
array2d_t* arr2d = malloc( sizeof *arr2d + sizeof(int[x][y]) );
Because the problem with flexible array members is that they can neither be VLA nor 2-dimensional. And although casting it to another integer array type is safe (in regards of aliasing and alignment), the syntax is quite evil:
int(*ptr)[y] = (int(*)[y]) arr2d->flex; // bleh!
It would be possible hide all this evil syntax behind a macro:
#define get_array(arr2d) \
_Generic( (arr2d), \
array2d_t*: (int(*)[(arr2d)->y])(arr2d)->flex )
Read as: if arr2d is a of type array2d_t* then access that pointer to get the flex member, then cast it to an array pointer of appropriate type.
Full example:
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
size_t x;
size_t y;
int flex[];
} array2d_t;
#define get_array(arr2d) \
_Generic( (arr2d), \
array2d_t*: (int(*)[(arr2d)->y])(arr2d)->flex )
int main (void)
{
size_t x = 2;
size_t y = 3;
array2d_t* arr = malloc( sizeof *arr + sizeof(int[x][y]) );
arr->x = x;
arr->y = y;
for(size_t i=0; i<arr->x; i++)
{
for(size_t j=0; j<arr->y; j++)
{
get_array(arr)[i][j] = i+j;
printf("%d ", get_array(arr)[i][j]);
}
printf("\n");
}
free(arr);
return 0;
}
Advantages over pointer-to-pointer:
An actual 2D array that can be allocated/freed with a single function call, and can be passed to functions like memcpy.
For example if you have two array2d_t* pointing at allocated memory, you can copy all the contents with a single memcpy call, without needing to access individual members.
No extra clutter in the struct, just the array.
No cache misses upon array access due to the memory being segmented all over the heap.
The code above never sets rows and columns, so the code has undefined behavior from reading those values.
Assuming you set those values properly, this isn't allocating the proper amount of memory:
result->my2darray = malloc(sizeof(int)*rows);
You're actually allocating space for an array of int instead of an array of int *. If the latter is larger (and it most likely is) then you haven't allocated enough space for the array and you again invoke undefined behavior by writing past the end of allocated memory.
You can allocate the proper amount of space like this:
result->my2darray = malloc(sizeof(int *)*rows);
Or even better, as this doesn't depend on the actual type:
result->my2darray = malloc(sizeof(*result->my2darray)*rows);
Also, there's no need to create a temporary array to read values into. Just read them directly into my2darray:
for(int i = 0;i<rows;i++) {
result->my2darray[i]=malloc(sizeof(int)*columns);
for(int j = 0;j<columns;j++) {
fscanf(fp, "%d", &result->my2darray[i][j]);
}
}
In your provided code example, the variables rows and columns have not been initialized before use, so they can contain anything, but are likely to be equal to 0. Either way, as written, the results will always be unpredictable.
When a 2D array is needed in C, it is useful to encapsulate the memory allocation, and freeing of memory into functions to simplify the task, and improve readability. For example, in your code the following line will create an array of 5 pointers, each pointing to 20 int storage locations: (creating 100 index addressable int locations.)
int main(void)
{
struct mystruct result = {0};
result.my2darray = Create2D(5, 20);
if(result.my2darray)
{
// use result.my2darray
result.my2darray[0][3] = 20;// for simple example, but more likely in a read loop
// then free result.my2darray
free2D(result.my2darray, 5);
}
return 0;
}
Using the following two functions:
int ** Create2D(int c, int r)
{
int **arr;
int y;
arr = calloc(c, sizeof(int *)); //create c pointers (columns)
for(y=0;y<c;y++)
{
arr[y] = calloc(r, sizeof(int)); //create r int locations for each pointer (rows)
}
return arr;
}
void free2D(int **arr, int c)
{
int i;
if(!arr) return;
for(i=0;i<c;i++)
{
if(arr[i])
{
free(arr[i]);
arr[i] = NULL;
}
}
free(arr);
arr = NULL;
}
Keep in mind that what you have created using this technique is actually 5 different pointer locations each pointing to a set of 20 int locations. This is what facilitates the use of array like indexing, i.e. we can say result.my2darray[1][3] represents the second column, forth row element of a 5X20 array, when it is not really an array at all.
int some_array[5][20] = {0};//init all elements to zero
Is what is commonly referred to in C an int array, also allowing access to each element via indexing. In actuality (Even though commonly referred to as an array.) it is not an array. The location of elements in this variable are stored in one contiguous location in memory.
|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0... (~ 82 more)
But C maintains the locations such that they are all indexable as an 2D array.
I am trying to dynamically allocate a 2D array, put some values, and print output. However it seems that I am making mistake in getting input to program in atoi() function.
Basically when we assign a static 2D array, we declare it as say int a [3][3]. So 3*3 units if int, that much memory gets allocated. Is same thing holds for allocating dynamic array as well?
Here is my code:
#include<stdio.h>
#include<stdlib.h>
int main(int arg,char* argv)
{
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
int rows =3;
int col=3;
int i,j;
int (*arr)[col] = malloc(sizeof (*arr)*rows);
int *ptr = &(arr[0][0]);
int ct=1;
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
arr[i][j]=ct;
ct++;
}
}
printf("printing array \n");
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
printf("%d \t",arr[i][j]);
}
printf("\n");
}
free(arr);
return (0);
}
Program crashes in runtime. Can someone comment?
The first issue I see is this line:
int (*arr)[rows][col] = malloc(sizeof (*arr) * rows);
This is not problematic at all because you are in fact allocating more memory than you need. This would suffice:
int (*arr)[rows][col] = malloc(sizeof (*arr));
sizeof *arr is enough because *arr is of type int [rows][cols]; the memory you want is exactly the size of that array. The sizeof operator, when applied to arrays, gives you the count for the whole array.
The main problem with your code, however, is how you use arr. You are indexing it with arr[i][j], but instead, you should be using (*arr)[i][j], because arr is not an array, it's a pointer to an array. You need to dereference it before any further indexing - as simple as that. arr[i][j] is equivalent to *(*(arr+i)+j). Note that i should be an offset into *arr, not an offset on arr. That's why you need to dereference arr before indexing.
Since you're already using variable-length arrays, you may take advantage of that:
int (*arr)[col] = malloc(sizeof *arr * rows);
This way you can simply access elements with the usual syntax arr[i][j] without worrying about pointers and dereferences, pointer arithmetic will do all the work for you.
Also since indexes start from 0 your tests should look like i < rows and j < col.
And you have some minor errors for the wrong main declaration and the second printf.
I have an array of structs. Actually, it is a 2d-array but an unusual 2d array.
I am allocating memory on stack:
#define MAX_VERTICES 5068
struct ARRAY_FIX {
int ele[MAX_VERTICES];
int size;
int first;
};
ARRAY_FIX C[MAX_VERTICES];
int main() {
//...
}
So, I need to replace one row with another one (actually, i need this operation to be performed for sorting rows by some criteria).
How is it possible to perform? As I understand, if I use this code:
С[i] = C[j];
In this code, the operator "=" will copy all array, won't it? I needn't it, I want to change the rows by changing the pointer
How can I do it?
You can use an array of pointers to struct ARRAY_FIX and just switch the pointers into the array.
I am allocating memory on stack.
An object declared at file scope is usually NOT on the stack.
In your case, each row is represented by struct ARRAY_FIX object. If you want to be able to work with these rows by using references (changing the order of rows by swapping pointers etc.), your 2D array must be stored in a way that allows you to do that.
Possible solution is to change your 2D array to an array of pointers to struct ARRAY_FIX so that when you call С[i] = C[j]; only the reference (address of your object) is copied, not an object itself.
Also note, that you should worry about the performance and try to make your program faster only when it's really needed. It's much easier to make a correct program fast than it's to make a fast program correct.
as said before
Possible solution is to change your 2D array to an array of pointers
to struct ARRAY_FIX
here after how to do it:
#define MAX_VERTICES 5068
struct ARRAY_FIX {
int ele[MAX_VERTICES];
int size;
int first;
};
ARRAY_FIX *C[MAX_VERTICES];
int main() {
int i;
ARRAY_FIX *p;
//...
for (i=0;i<MAX_VERTICES;++i)
{
C[i] = malloc (sizeof(ARRAY_FIX ));
//...
}
//...
p = C[1];
C[1] = C[2];
C[2] = p;
//...
}
I'm trying to create an array of structs and also a pointer to that array. I don't know how large the array is going to be, so it should be dynamic. My struct would look something like this:
typedef struct _stats_t
{
int hours[24]; int numPostsInHour;
int days[7]; int numPostsInDay;
int weeks[20]; int numPostsInWeek;
int totNumLinesInPosts;
int numPostsAnalyzed;
} stats_t;
... and I need to have multiple of these structs for each file (unknown amount) that I will analyze. I'm not sure how to do this. I don't like the following approach because of the limit of the size of the array:
# define MAX 10
typedef struct _stats_t
{
int hours[24]; int numPostsInHour;
int days[7]; int numPostsInDay;
int weeks[20]; int numPostsInWeek;
int totNumLinesInPosts;
int numPostsAnalyzed;
} stats_t[MAX];
So how would I create this array? Also, would a pointer to this array would look something this?
stats_t stats[];
stats_t *statsPtr = &stats[0];
This is how it is usually done:
size_t n = <number of elements needed>
stats_t *ptr = malloc (n * sizeof (stats_t));
Then, to fill it in,
for (size_t j = 0; j < n; ++j)
{
ptr [j] .hours = whatever
ptr [j] .days = whatever
...
}
The second option of a pointer is good.
If you want to allocate things dynamically, then try:
stats_t* theStatsPointer = (stats_t*) malloc( MAX * sizeof(stats_t) );
as Roland suggests.
Just don't forget to
free(theStatsPointer);
when you're done.
Use malloc():
http://en.wikipedia.org/wiki/Malloc
malloc is your friend here.
stats_t stats[] = (stats_t*)malloc(N * sizeof(stats_t));
stats sort of is a pointer to the array. Or you can use stats[3] syntax as if it were declared explicitly as an array.
Based on your replies to other answers it looks like you need a dynamic data structure like a linked list. Take a look at the queue(3) set of facilities.
New to C, thanks a lot for help.
Is it possible to define an array in C without either specifying its size or initializing it.
For example, can I prompt a user to enter numbers and store them in an int array ? I won't know how many numbers they will enter beforehand.
The only way I can think of now is to define a max size, which is not an ideal solution...
Well, you can dynamically allocate the size:
#include <stdio.h>
int main(int argc, char *argv[])
{
int *array;
int cnt;
int i;
/* In the real world, you should do a lot more error checking than this */
printf("enter the amount\n");
scanf("%d", &cnt);
array = malloc(cnt * sizeof(int));
/* do stuff with it */
for(i=0; i < cnt; i++)
array[i] = 10*i;
for(i=0; i < cnt; i++)
printf("array[%d] = %d\n", i, array[i]);
free(array);
return 0;
}
Perhaps something like this:
#include <stdio.h>
#include <stdlib.h>
/* An arbitrary starting size.
Should be close to what you expect to use, but not really that important */
#define INIT_ARRAY_SIZE 8
int array_size = INIT_ARRAY_SIZE;
int array_index = 0;
array = malloc(array_size * sizeof(int));
void array_push(int value) {
array[array_index] = value;
array_index++;
if(array_index >= array_size) {
array_size *= 2;
array = realloc(array, array_size * sizeof(int));
}
}
int main(int argc, char *argv[]) {
int shouldBreak = 0;
int val;
while (!shouldBreak) {
scanf("%d", &val);
shouldBreak = (val == 0);
array_push(val);
}
}
This will prompt for numbers and store them in a array, as you asked. It will terminated when passed given a 0.
You create an accessor function array_push for adding to your array, you call realloc from with this function when you run out space. You double the amount of allocated space each time. At most you'll allocate double the memory you need, at worst you will call realloc log n times, where is n is final intended array size.
You may also want to check for failure after calling malloc and realloc. I have not done this above.
Yes, absolutely. C99 introduced the VLA or Variable Length Array.
Some simple code would be like such:
#include <stdio.h>
int main (void) {
int arraysize;
printf("How bid do you want your array to be?\n");
scanf("%d",&arraysize);
int ar[arraysize];
return 0;
}
Arrays, by definition, are fixed-size memory structures. You want a vector. Since Standard C doesn't define vectors, you could try looking for a library, or hand-rolling your own.
You need to do dynamic allocation: You want a pointer to a memory address of yet-unkown size. Read up on malloc and realloc.
If all you need is a data structure where in you can change its size dynamically then the best option you can go for is a linked list. You can add data to the list dynamically allocating memory for it and this would be much easier!!
If you're a beginner, maybe you don't want to deal with malloc and free yet. So if you're using GCC, you can allocate variable size arrays on the stack, just specifying the size as an expression.
For example:
#include <stdio.h>
void dyn_array(const unsigned int n) {
int array[n];
int i;
for(i=0; i<n;i++) {
array[i]=i*i;
}
for(i=0; i<n;i++) {
printf("%d\n",array[i]);
}
}
int main(int argc, char **argv) {
dyn_array(argc);
return 0;
}
But keep in mind that this is a non standard extension, so you shouldn't count on it if portability matters.
You can use malloc to allocate memory dynamically (i.e. the size is not known until runtime).
C is a low level language: you have to manually free up the memory after it's used; if you don't, your program will suffer from memory leaks.
UPDATE
Just read your comment on another answer.
You're asking for an array with a dynamically-changing-size.
Well, C has no language/syntactic facilities to do that; you either have to implement this yourself or use a library that has already implemented it.
See this question: Is there an auto-resizing array/dynamic array implementation for C that comes with glibc?
For something like this, you might want to look into data structures such as:
Linked Lists (Ideal for this situation)
Various Trees (Binary Trees, Heaps, etc)
Stacks & Queues
But as for instantiating a variable sized array, this isn't really possible.
The closest to a dynamic array is by using malloc and it's associated commands (delete, realloc, etc).
But in this situation, using commands like malloc may result in the need to expand the array, an expensive operation where you initialize another array and then copy the old array into that. Lists, and other datatypes, are generally much better at resizing.
If you're looking for array facilities and don't want to roll your own, try the following:
Glib
Apache APR
NSPR
Above given answers are correct but there is one correction, the function malloc() reserve a block of memory of specified size and return a pointer of type void* which can be casted into pointer of any form.
Syntax: ptr = (cast-type*) malloc(byte-size)
#include<stdio.h>
#include<cstdlib>
int main(int argc,char* argv[]){
int *arraySize,length;
scanf("%d",&length);
arraySize = (int*)malloc(length*sizeof(int));
for(int i=0;i<length;i++)
arraySize[i] = i*2;
for(int i=0;i<length;i++)
printf("arrayAt[%d]=%d\n",i,arraySize[i]);
free(arraySize);
}