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.
Related
I need to make a program for bakery managment, I've done structures and three pointer arrays that must contain pointers for object of these structures. But i can't make function to add new bakery because it needs dynamic memory allocating. I've tried to do this but it throws Segmentation Fault on realloc. I would be grateful for any advice how to properly reallocate memory for these arrays to add element. Also feel free to make comments about other errors in the code, I'm just learning.
typedef struct BakeryType {
char *name;
} BakeType;
typedef struct Bakerys {
char *name;
BakeType *type;
char *photo;
float weight;
int portions;
float price;
char *description;
} Bakery;
Bakery *bakeryList[0];
BakeType *bakeTypeList[0];
void addBakery() {
Bakery new;
*bakeryList = realloc(*bakeryList, (sizeof(bakeryList)/ sizeof(Bakery))+ 1);//Segmentation Fault
bakeryList[sizeof(bakeryList)/sizeof(Bakery)]=&new;
}
bakeryList is a zero-element array of pointers to Bakery. It has room for zero pointers.
Yet later you set the first element of this array (*bakeryList which is the same as bakeryList[0]) to whatever comes back from realloc. So you're overwriting something, and it probably goes downhill from there.
I think you want bakeryList to just be a pointer to Bakery. That's how dynamically-allocated arrays work in C: you define a pointer to the first element and use pointer math (e.g., bakeryList[5] or *(bakeryList + 5)) to access other elements.
Another issue is your use of sizeof(bakeryList). sizeof is an operator that's evaluated by the compiler. It doesn't change at runtime. sizeof(bakeryList) / sizeof(Bakery) will evaluate to zero because you defined bakeryList as a zero-element array. You need another variable to keep track of how many elements are actually in the array at runtime.
Something like this would work:
int bakeryCount = 0;
Bakery *bakeryList = NULL;
void addBakery() {
// Add one to the array.
bakeryCount++;
bakeryList = realloc(bakeryList, bakeryCount * sizeof (Bakery));
// Create a pointer to the new element at the end of the array.
Bakery *newBakery = bakeryList + bakeryCount - 1;
// Set all the fields. Note that they will probably contain
// garbage so you should set them all.
newBakery->name = ...
}
I am currently attempting to insert a string argument into a 2D array inside of a struct. The problem I am having is that I am not sure how to use realloc to dynamically increase the size of this 2D array inside the struct. Currently it is set up to use Malloc so I can test it for a single argument, which still is giving me a segmentation fault.
Here is the struct I am working with:
typedef struct SimpleCommand {
// Available space for arguments currently preallocated
int _numberOfAvailableArguments;
// Number of arguments
int _numberOfArguments;
// Array of arguments
char **_arguments;
}SimpleCommand;
//The struct is declared in Main as follows:
struct SimpleCommand _currentSimpleCommand = {._numberOfAvailableArguments = 0, ._numberOfArguments = 0, ._arguments = NULL};
The struct is then passed into a function thats job is to strcpy an argument into the 2D array inside the simple command struct.
//insert argument into simple command
void insertArgument(struct SimpleCommand command, char * argument ){
//malloc some space for the argument
command._arguments = malloc(strlen((argument)));
//copy argument into array
strcpy(command._arguments[command._numberOfArguments], argument);
command._numberOfArguments++; //added an argument
}
Any help is much appreciated!
I'm not sure I understand your problem, but here goes my deduction:
malloc allocates memory.
realoc realocates memory preserving, when possible, the data previously stored.
pseudo (not compiled)
int count = 10;
Thing * things = malloc(count * sizeof(Thing));
things[0] = athing;
// things[0] ... [9] is ok
// need more memory
count += 10;
Thing * things = realloc(things, count * sizeof(Thing));
// things[0] ... [19] is ok
// things[0] still hold athing
As you pointed out, you are using a 2D array. The line below looks suspicious:
command._arguments = malloc(strlen((argument)));
You are allocating size for a char* and storing it in a char**!!
In your problem you need to allocate space for your array of arguments and space to copy your arguments (if I understand what you are trying to do). One will need malloc as its size does not change. The other will need realloc as more arguments are added.
I hope this helps you complete your homework without giving you the full solution.
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
}
}
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?