This question already has answers here:
Dynamic array in C — Is my understanding of malloc and realloc correct?
(3 answers)
Closed 5 years ago.
So for my school project, a large CSV file will be entered through stdin and we will have to sort it based on column and print it out as a sorted csv file.
The step I am on right now is figuring out how to keep reallocing a struct of arrays so that it will grow if there is not big enough to hold the data coming in from stdin. We don't know the exact amount of rows that will be inputted in the CSV file. Right now we just used a static amount to test and see if the values are assigned to the structs.
I am still a beginner at C so I do not clearly know how I would iterate through a pointer like I would iterate through an array. Since we are using a static amount of structs in the array, we can just iterate using array[i] like in Java but how would you iterate through something like *array?
I do not know where to start for creating this dynamic array. I tried
struct array* testArray = (array*)malloc(sizeof(testArray));
but I have no idea how to iterate through it like I did with the static array by using array[i].
Any help would be greatly appreciated, sorry for the wall of text...
You can navigate through a malloced space the same way as with an array (using indicies), but it seems that your main issue lies in your use of malloc. Malloc's argument is the size in number of bytes that you want to allocate. So if you want to have an array of structs, you would first need to find out how many bytes one struct contains using sizeof(struct array), and then determine how large of an array you want, let's say N. So that line of code should look more like struct array* testArray = malloc(N * sizeof(struct array));. The return value of malloc will be a void pointer containing the memory address of the first byte of allocated space. Upon assigning this value to testArray, it will be type-casted to the assigned variable type (struct array *). Now you can use pointer arithmetic to access a specific index i with *(testArray + i), or simply testArray[i]. If you find that N was not a sufficient size, you can use realloc to increase the array size to 2N, or whatever size deemed necessary.
struct array* testArray = (array*)malloc(sizeof(testArray));
is a little wrong as you only allocate 1 element of testArray.
It is more like:
struct A
{
int a;
int b;
....
};
struct A* arr = malloc( N * sizeof(struct A) );
^^^
N element of struct A
int j;
for (j=0; j<N; ++j) // Iterate it like any other array
{
arr[j].a = 5;
arr[j].b = 42;
....
}
Use realloc when you need the array to grow.
When reading from a file/stdin it could look like (based on comment from David C. Rankin):
int n=0; // Count of the number of structs read from the file
struct A* arr = malloc( N * sizeof(struct A) );
while (read line from file)
{
arr[n].a = val1;
arr[n].b = val2;
++n; // Increment count
if (n == N) // Check if current array is full, i.e. realloc needed
{
// realloc array to 2 * N; N = N * 2
}
}
Related
Using c, I'm trying to input stuff into an array of structs, and once that array is filled, double the size of the array and keep going, using realloc.
I know there's been several question like this asked already, but I was hoping someone could explain it clearly since I didn't create my array the way those questions did and am getting a bit confused.
I have a struct
struct Data {
// Some variables
}
and initialised the array using
struct Data entries[100];
int curEntries = 100;
int counter = 1; // index, I use (counter - 1) when accessing
To realloc, I'm currently using
if(counter == curEntries){ // counter = index of array, curEntries = total
entries = realloc(entries, curEntries * 2);
}
I know I need to cast realloc to something right? I'm just not sure how or what I'm meant to be casting it to, so I currently don't have anything, which of course gives me the error "assignment to expression with array type"
Thanks!
struct Data entries[100];// memory is already allocated to this
You need to declare entries as pointer like:
struct Data *entries=NULL;
entries = malloc(curEntries * sizeof(struct Data));
//When its time to reallocate
entries = realloc(entries, (curEntries * 2 * sizeof(struct Data)));
I've been stuck on this for a while now!
I have to use this given struct:
typedef struct ArList
{
char **array; // pointer to array of strings
int size; // number of elements
int capacity = 10; // length of array
} ArList;
to create a dynamically allocated Arlist by using a function(This is where I'm supposed to come in:
ArList *createArList(int length)
Instructions given: First goal is to create an ArList:
ArList* list = malloc(sizeof(ArList));
Then I have to initialize the internal array:
list->size = 0; //Given as initially 0
list->array[list->size];
Lastly, (this comes later but I wanted to tested now) I have to copy a string into an element of the array.
strcpy(ArList[0], "CAT");
At this point I ran the code to see how it was going and it outputs the word "CAT" but immidiately crashes afterwards.
I'm just starting to learn about structures and memory allocation, and it all seems confusing right about now.
This is for C programming.
You cannot allocate with list->array[list->size], use:
list->array = malloc(sizeof(char*)*list->size);
and then when you want to fill the array:
list->array[0] = strdup("CAT");
if i correctly understand what you are trying to do.
i am a beginner so please cut me some slack on this one. So I have two functions and a struct in a header file I am currently working with.
This is the struct:
typedef struct ArrayList
{
// We will store an array of strings (i.e., an array of char arrays)
char **array;
// Size of list (i.e., number of elements that have been added to the array)
int size;
// Length of the array (i.e., the array's current maximum capacity)
int capacity;
} ArrayList;
Here is the first function, which creates and dynamically allocates memory for an array of strings. Capacity is the length of the internal array and size is the current size (how many strings are in the array which is essentially 0.)
ArrayList *createArrayList(int length){
char **array = NULL;
ArrayList *n;
int size = 0;
if (length > DEFAULT_INIT_LEN)
{
array = malloc(sizeof(int) * length);
n->capacity = length;
}
else
{
array = malloc(sizeof(int) * DEFAULT_INIT_LEN);
n->capacity = DEFAULT_INIT_LEN;
}
if (array == NULL)
panic("ERROR: out of memory in Mylist!\n");
n->size = size;
printf("-> Created new ArrayList of size %d\n", n->capacity);
return *array;
When I try to implement a pointer to the capacity member of the ArrayList struct inside another function within the same file, it is uninitialized instead of set as the value from the previous function. I.e. in createArrayList, n->capacity is equal to 10, but when used in printArrayList it is uninitialized and a random number appears such as 122843753.:
void printArrayList(ArrayList *list)
{
printf("\n%d", list->capacity);
return NULL;
}
My question is, how can I make it so all these functions "share" the same value when referring to the struct members. I.E. the first function prints -> Created new ArrayList of size 10, and the second function prints 10 as well. Also, I have to do this without changing the struct function itself. Sorry if this is a poorly worded question, but I can further clarify if it is confusing. Thanks in advance!
I see a couple of major issues with this code, in createArrayList you are returning array which is a char ** but you should be returning an ArrayList * which is what n is. So it looks like you want to assign array to n->array. The next issue is that n is an ArrayList * but you do not allocate memory for n.
If I create a struct in C and want to add them to an array that is not set to a fixed size, how is the array created?
Can one create a tempStruct which is used on every iteration while getting user input and store this in an array, always using the same tempStruct struct in the loop?
How is an array created if the size is unknown as it depends on user input, and how are structs added to this array?
When the size is unknown at compile time, you'll need to allocate the memory on the heap, rather than in the data segment (where global variables are stored) or on the stack (where function parameters and local variables are stored). In C, you can do this by calling functions like malloc.
MyStructType *myArray = (MyStructType *)malloc(numElements * sizeof(MyStructType)
... do something ...
free(myArray)
If you're actully using C++, it's generally better to use new[] and delete[], e.g.
MyStructType *myArray = new MyStructType[numElements]
... do something ...
delete [] myArray
Note that new[] must be paired with delete[]. If you're allocating a single instance, use new and delete (without "[]"). delete[] and delete are not equivalent.
Also, if you're using C++, it's generally easier and safer to use an STL vector.
the C array must be with fixed size this is what we have learned years ago
but memory allocation functions may help you to find a solution
in c++ you can use the operator new
int num=0;
cout<<"please enter the number"<<endl;
cin>>num;
int *x=new int[num];
for(int i=0;i<num;i++)
{
cout<<"enter element "<<(i+1)<<endl;
cin>>x[i];
}
//do your work
and as
Mr Fooz
mentioned delete[] is used to free the memory allocated by new[]
and this is a general example
If you are using the older C89 standard compiler, you cannot use variable length arrays. If you use C99 then you can create variable length array. For clarification: variable-lenght doesnt mean that the array lenght can change during execution. It just means that you can set it during execution instead of fixing a value during compile time.
For eg:
CreateArray(const int numberOfElements)
{
struct MyStruct arrayOfStructs[numberOfElements];
}
This is valid in C99 but not in C89. Check your compiler documentaion.
Yes, you can use a tempStruct during input which you add later to the array.
If the size of the array is unknown, then you are in trouble. You must keep track of the array's size somewhere. Just have an integer variable that you change every time you change your array to keep track of your array's size.
If the size of the struct is not known at compile time it is even more complicated. You either just store Pointers in the array which point to your actual struct elements in memory, or you have to keep track of the sizes of every struct in the array. In the later case you would have to do addressing in the array completely manually calculating a lot. While this is very memory efficient, it is also error prone and extremely hard to debug.
OK. sample to create an array that hold your struct using pointers:
struct MyStruct
{
/* code */
}
main()
{
counter = 0;
struct MyStruct** array = malloc(counter);
// Create new Element
struct MyStruct myElement;
myElement.someData = someValue;
// Add element to array:
array = realloc(array, sizeof(struct MyStruct*) * (counter + 1);
array[counter] = &myElement;
counter++;
// Create yet another new Element
struct MyStruct myElement;
myElement.someData = someOtherValue;
array = realloc(array, sizeof(struct MyStruct*) * (counter + 1);
array[counter] = &myElement;
counter++;
// Now remove the last element
free(array[counter -1]); // may have something more complicated than that, depending on your struct
array = realloc(array, sizeof(struct MyStruct*) * (counter - 1);
counter--;
}
this code is not tested!
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?