Realloaction of memory in C - Arrays - c

I'm starting with an array array[0] let's say.
As I loop through a text file and find keywords I'd like to store those words in that array.
So the first run though I'd assing the first keyword very simply
array[0] = "Word"
However I'm not sure how to increment that array to 1, and 2, etc.
I've read a few posts on memory allocaiton but that seemed to be specific to strings; perhaps I'm misunderstanding the concept.
I'd like to preserve the current array's contents, and increment it.
I've rigged it by setting my array[10], but I'd prefer to learn the correct way to do this.
I've included the code below so far (without any memory allocation)
#include <stdio.h>
#include <memory.h>
#include "tables.h"
int main() {
insertVarbleTble("Name","CSTRING",1,0,"");
return 0;
}
int insertVarbleTble(char *ident, char *type, int local, int constVar, char *constVal){
int successful;
int sizeArry;
sizeArry = sizeof(varible)/ sizeof(varible[0]);
if(sizeArry <= 0){
varible[sizeArry]== ident;
}else{
successful = (searchVarbleTble(ident,sizeArry)==1;
}
if(successful ==0){
varible[sizeArry+1]==ident;
}else{
printf("Already exists");
}
}
void realocMem(int size){
varible[size];
}
int searchVarbleTble(char * ident, int arrySize){
int i;
int results = 0;
for(i=0;i<arrySize;i++){
if(!strcmp(varible[i],ident)){
results= 1;
}
}
return results;
}
Header file contains the array I'm using they are:
char varible[0];
int insertVarbleTble(char *, char *, int, int , char *);
int searchVarbleTble(char *, int);
Would a potential solution be to first count the number of keywords that exist, and then dimension the array?

Okay generally what you want to do is not possible with arrays. Your code is really hard to understand but I will try to give you an example on how it is done.
This is not directly what you want, but should help you find your own solution. If you want to work with strings it gets a bit more complicated because strings are arrays in itself so you have to make sure that you always have enough memory for your current string available.
#include <stdio.h>
#include <stdlib.h>
typedef struct data_container_{
int *mem;
int size;
} data_container;
void add_to_memory(data_container *data, int pos, int value)
{
if (pos+1 > data->size) //check if memory for this position is allocated
{
int *dummy = realloc(data->mem, pos+1); // call realloc to get more memory
if(dummy == NULL) //check if reallocation was succesful
{
puts("Memory reallocation failed");
exit(1); //terminate program
}
else
{
data->size = pos+1; //set size to the newly allocated size
data->mem = dummy; //if succesful point to the new memory location
}
}
data->mem[pos] = value;
}
int main(void)
{
data_container data; // create stuct
data.size = 2;
data.mem = malloc(sizeof (int) * data.size); //allocate memory, similar to an array but dynamic
if(data.mem == NULL) //check if allocation was succesful
{
puts("Memory allocation failed");
exit(1); //terminate program
}
add_to_memory(&data, 0, 3); //pass the address of the struct
add_to_memory(&data, 1, 6);
add_to_memory(&data, 2, 8); //now it uses realloc, pos would be out of the allocated range
for(int i =0; i<data.size; i++)
{
printf("%d\n",data.mem[i]); //a pointer can be accessed similar to an array
}
free(data.mem); //free the allocated memory
}
as Pablo said you should read about malloc and realloc especially you should keep in mind that the memory allocated is not initialized. calloc initializes with 0.
And always remember to free allocated space when it is not used anymore.

Related

array function in c /Append/Delete basic

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* create_int_array(){
int* arr;
arr = (int *)calloc(1,sizeof(int));
return arr;
}
char** create_string_array(){
char** arr = calloc(1,sizeof(char));
return arr;
}
void append_int(int* array, int element, int index){
array = (array+index);
*array = element;
}
void append_string(char** array , char* element,int index){
*(array + index) = calloc(1,sizeof(char*));
strcpy(*(array + index),element);
}
void delete_string(char** array, int index){
free(array[index]);
}
void delete_int(int* array,int index){
array[index] = NULL;
}
/////// M A I N F I L E ///////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "basic_data_file.h"
int main(int argc, char const *argv[])
{
/* code */
char **array;
array = create_string_array();
char *full_name = calloc(strlen("hamza arslan"),sizeof(char*));
strcpy(full_name,"hamza arslan");
char* mail = calloc(strlen("test#gmail.com"),sizeof(char*));
strcpy(mail,"test#gmail.com");
char* address = calloc(strlen("Hacettepe Universty"),sizeof(char*));
strcpy(address,"Hacettepe Universty");
char* statu = calloc(strlen("student"),sizeof(char*));
strcpy(statu,"student");
append_string(array,full_name,0);
append_string(array,mail,1);
append_string(array,address,2);
append_string(array,statu,4);
for(int i=0; i< 3; i++){
printf("%s\n",array[i]);
free(array[i]); // get free double pointer
}
printf("%s\n",array[4]); // because index 3 blow up
free(full_name);
free(mail);
free(address);
free(statu);
return 0;
}
I was try to own my basic array library . As you know else in some languages have high level array types. They are making easy our stocking operation. But in c, it's more complicated especially about string. I have 2 problem in here . First of all , when i give index=3 in append_string function , code blow up with Aborted(core dumped) error.(./run': double free or corruption (out)). Secondly , when i was checking leak memory ,it's get memory leak even i use free. What can i do?
Your create_xy_array functions allocate an array of 1 element, and they stay that way until the very end. When you have a one-element array and index, read/write its second and further elements, C itself happily approves, but the result will not work, it silently destroys everything in its path.
First of all, for having a dynamic array, you have to track its length yourself, C allocations/arrays do not know their own size. So you need a struct, containing the length and a pointer, something like
typedef struct IntArray {
int length;
int *elements;
} IntArray;
Then allocate it, for 0 elements, as there is nothing inside at the beginning:
IntArray* create_int_array() {
IntArray* ret = (IntArray*) malloc(sizeof(IntArray));
ret->length = 0;
ret->elements = NULL;
return ret;
}
void free_int_array(IntArray* arr) {
free(arr->elements);
free(arr);
}
Then you can try putting something inside:
void append_int(IntArray* arr, int element) {
arr->length++;
arr->elements = (int*) realloc(arr->elements, arr->length*sizeof(int));
arr->elements[length-1] = element;
}
(appending means adding something to the end of an array, there is no need for indices here)
And this could go on forever, deletion of an arbitrary element should shift the "upper" part of the array (memcpy) and resize the result to one element smaller or you could track the capacity of the array, which can be larger than its current length (but then it has to be incorporated into the append function and probably others).
(Disclaimer: I hope the snippet is correct, but I do not use C too often - and I can not suggest a good tutorial for the same reason, but that is what you probably need)
Note: I haven't code in C for years and I haven't check the code so double check and let me know.
Based on your description, you are trying to do a Vector.
Therefore, there are different ways that you can handle this.
Approach 1:
Create a structure which will hold the array, the capacity of the array, and the size of the array.
typedef struct StrArray{
int capacity;
int size;
int *integers;
}
The trick here is to take attention when you increase/decrease the capacity.
If you increase the capacity above the size of the array, then:
You need to create a new array with double the capacity
Copy all elements to the new array
Change pointer to new array
Free the memory of the old array
Approach 2
You can extend the previous approach by creating a function which returns a struct which holds the storage plus function pointers to the methods you wish to implement.
typedef struct StrStorage{
int capacity;
int size;
int *integers;
} StrStorage;
typedef struct StrArray {
StrStorage storage;
int (*capacity)(StrArray*);
int (*size)(StrArray*);
StrArray *(*append)(StrArray*, int);
void (*increaseStorage)(StrArray*);
// Add other methods here
} StrArray;
int capacity(StrArray *self) {
return self->storage->capacity;
}
int size(StrArray *self) {
return self->storage->size;
}
StrArray *append(StrArray *self, int integer){
if ((self->capacity() + 1) > self->size()){
self->increaseStorage();
}
// The rest of the magic goes here
return self;
}
StrArray *initializeStrArray(int n) {
StrArray* strArray = malloc(sizeof(StrArray));
strArray->chars = malloc(sizeof(char) * n);
strArray->capacity= capacity;
strArray->append = append;
return strArray;
}
Approach 3:
This approach is a continuation of the previous one.
In order to reduce the memory allocation, you can create an equivalent to a singleton which holds all the manipulation functions and then assi
There will be several crashes, but here is one:
char** arr = calloc(1,sizeof(char));
You are allocating 1 byte which is not sufficient to store a (char *), which needs between 2 and 8 bytes depending on the OS and target machine.
Try this instead:
char** arr = calloc(1,sizeof(char*));
You should double-check each line of code. C is not a forgiving language - mistakes are severely punished.

Array in structure

I'm new to C. Below are codes written in C.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char name[256];
int age;
int sex;
} People;
void InputPeople(People *data);
void ShowPeople(People data);
int main(void)
{
int i,count,datasize;
People *data;
datasize = 10;
data = (People*)malloc(sizeof(People) * datasize);
count = 0;
while (1) {
InputPeople(&data[count]);
if (data[count].age == -1) break;
count++;
if (count >= datasize) {
datasize += 10;
data = (People*)realloc(data,sizeof(People) * datasize);
}
}
for (i = 0;i < count;i++) {
ShowPeople(data[i]);
}
free(data);
return 0;
}
I have no idea why it is possible to write like "data[count]". I've learned Structure and Array. I would appreciate if somebody could explain to me.
People is your struct.
You declare a People pointer, which then points to the memory that you dynamically allocated with malloc(). How big is that memory chunk you allocated? datasize * size of the struct, i.e. 10 structs, since datasize = 10.
That means that data now points to a 1D array, thus you can index it like data[0] to get the first element (struct). count is a counter, which can be 0 as well.
You can think it like you had done People data[10];, which statically declares an array of 10 structs People, although it's not the same, since in your code the memory is dynamically allocated.
BTW, Do I cast the result of malloc? No.
Also, I would suggest you to read a C book.

Using malloc on variables created from typedef in a function

I want to create a new intarr_t with initial size len, but I've never handled this type of problem with a typedef'ed variable.
My problem is that intarr_create() should allocate the array space and then return a pointer to it if malloc was successful or a pointer to NULL if I failed. How can I fix this?
Also, why there is a * symbol in the function?
Here's my code:
#include <stdio.h>
typedef struct {
int* data;
unsigned int len;
} intarr_t;
intarr_t* intarr_create(unsigned int len) {
//intarr_t with initial size len
intarr_t = (int *) malloc(len); // not working here, can someone explain why?
if(intarr_t != NULL) {
return intarr_t;
} else {
return NULL;
}
}
int main() {
int len = 15;
int h = intarr_create(len);
printf("%d\n", h);
return 0;
}
It's not working because you did not give your variable a name. Also, int* and intarr_t are not the same type, so you will get a type mismatch unless you change the cast.
Rewrite your function into this:
intarr_t* intarr_create(unsigned int len)
{
intarr_t *result;
result = (intarr_t *)malloc(sizeof(intarr_t)); // allocate memory for struct
if(result != NULL)
{
result->data = (int *)malloc(len * sizeof(int)); // allocate memory for data
result->len = len;
if (result->data == NULL)
{
/* handle error */
}
}
else
{
/* handle error */
}
return (result);
}
You have to do a "double" malloc to get it right. First you have to allocate the memory for the intarr_t and if that was successful you have to allocate the memory for the data array.
Additionally malloc returns a void * which must be cast to the correct pointer type (should be a warning or maybe even an error with some compilers).
You have a few problems with your intarr_create function. First of all, you need to name your intarr_t variable. Now you have the slightly trickier problem of allocating memory for the actual array of integers in addition to your intarr structure. Remember, that you will have to call delete twice to destroy this object. Once on the data, and once on the actual structure itself.
intarr_t* intarr_create(unsigned int len)
{
intarr_t* array = (intarr_t*)malloc(sizeof(intarr_t));
array->data = (int*)malloc(len * sizeof(int));
return array;
}

Using pointers for string manipulation in c

Here I'm taking a sentence a checking if it is a palindrome or not.I'm doing this in the process of learning stacks.
Is there a way i can use pointers instead of char array 'sent' so that the number of input characters need not be constrained to 20 in the following code?
The code is working fine, but should there be any improvements in terms of performance or anything else?
is there anything important about pointers i should remember while using stacks, like initializing it to NULL?
Thanks
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node
{
char data;
struct node *link;
}StackNode;
void insertData(StackNode **);
void push(StackNode **, char);
void checkData(StackNode **);
bool pop(StackNode **,char *);
char sent[20] = "";
void main()
{
StackNode *stackTop;
stackTop = NULL;
insertData(&stackTop);
checkData(&stackTop);
printf("\n");
return;
}
void insertData(StackNode **stackTop)
{
char c;
int len;
printf("Enter the Sentence\n");
while( ( ( c = getchar() ) != '\n'))
{
if( ( ( c>='a' &&c<='z') || (c>='A' && c<='Z')))
{
if((c>='A' && c<='Z'))
{
int rem;
rem = c-'A';
c='a' + rem;
}
push(stackTop,c);
len = strlen(sent);
sent[len++]=c;
sent[len]='\0';
}
}
printf("Letters are %s\n\n",sent);
}
void push(StackNode **stackTop,char c)
{
StackNode *pNew;
pNew = (StackNode*) malloc(sizeof(StackNode));
if(!pNew)
{
printf("Error 100:Out of memory\n");
exit(100);
}
pNew->data = c;
pNew->link = *stackTop;
*stackTop = pNew;
}
void checkData(StackNode **stackTop)
{
char c;
int i=0;
while(pop(stackTop,&c))
{
if( c !=sent[i++])
{
printf("Not palindrome");
return;
}
}
printf("Palindrome");
}
bool pop(StackNode **stackTop,char *c)
{
StackNode *pNew;
pNew = *stackTop;
if(pNew == NULL)
return false;
*c = pNew->data;
*stackTop = pNew->link;
printf("char poped %c\n",*c);
free(pNew);
return true;
}
As far as I know, there is no way to have an "infinite array" or an array with no limitations. However, if you use malloc you can produce a section of memory large enough that you won't need to worry about the limitations as much. I see that later on in the code you have used malloc, so I assume you know how it works. However, I would use something like this;
char * sent = malloc(sizeof(char) * 100);
if(sent == NULL){
printf("OUT OF MEMORY!");
return 1;
}
Where 100 is the buffer size you wish to have. I have used a size up to 10000 and had no problems at runtime, so that may be what you need.
In C, arrays are really pointers to statically allocated memory. It is pretty straightforward to create a pointer to an array, or any element in an array. For example, suppose we have you array char sent[20]. If we wanted to create a pointer that pointed to the exact same memory as sent, we can declare char *sentP = sent. We can now replace any use of sent with sentP. We can even create a pointer to the middle of sent: char *sentMidP = sent + 9. Now, sentMidP[0] is the same as sent[9] and sentMidP[-9] is the same as sent[0].
However, unlike sent, we can change where sentP and sentMidP point (think of sent as a constant pointer char * const, which you can't change). Thus, if you had another array char sent2[100]'. You can set the value ofsentPtosent2. What's cool about this is that you can do it *at runtime*, which effectively means that you can change the size ofsentP` depending on the size of your input.
However, there is no need to limit yourself to statically allocated input. C provides the malloc function (see here) to allocate memory at runtime. Thus, if you don't know the size of your sentence at compile time, but you will know it at runtime (say in a variable called sentenceLength), you can allocate `sentP' like the following.
char *sentP = malloc(sizeof(char) * (sentenceLength + 1)); // Plus one for the NUL termination byte in C strings
if (sentP == NULL) {
fprintf(stderr, "No more memory :(");
exit(EXIT_FAILURE);
}
Note how we now have to handle out-of-memory errors. In general, dynamic allocation introduces more overhead, because there is a possibility that we run out of memory, a requirement that we ensure we only access what was allocated, and a need to release the memory with free once we're done.
When you're done with the sentP pointer, be sure to free it with:
free(sentP);
That's it! You can use the sentP pointer we made in your code, and everything should work great. Good luck!

C Dynamically creating array of structs which include variable sized 2d array [duplicate]

I know how to create an array of structs but with a predefined size. However is there a way to create a dynamic array of structs such that the array could get bigger?
For example:
typedef struct
{
char *str;
} words;
main()
{
words x[100]; // I do not want to use this, I want to dynamic increase the size of the array as data comes in.
}
Is this possible?
I've researched this: words* array = (words*)malloc(sizeof(words) * 100);
I want to get rid of the 100 and store the data as it comes in. Thus if 76 fields of data comes in, I want to store 76 and not 100. I'm assuming that I don't know how much data is coming into my program. In the struct I defined above I could create the first "index" as:
words* array = (words*)malloc(sizeof(words));
However I want to dynamically add elements to the array after. I hope I described the problem area clearly enough. The major challenge is to dynamically add a second field, at least that is the challenge for the moment.
I've made a little progress however:
typedef struct {
char *str;
} words;
// Allocate first string.
words x = (words) malloc(sizeof(words));
x[0].str = "john";
// Allocate second string.
x=(words*) realloc(x, sizeof(words));
x[1].FirstName = "bob";
// printf second string.
printf("%s", x[1].str); --> This is working, it's printing out bob.
free(x); // Free up memory.
printf("%s", x[1].str); --> Not working since its still printing out BOB even though I freed up memory. What is wrong?
I did some error checking and this is what I found. If after I free up memory for x I add the following:
x=NULL;
then if I try to print x I get an error which is what I want. So is it that the free function is not working, at least on my compiler? I'm using DevC??
Thanks, I understand now due to:
FirstName is a pointer to an array of char which is not being allocated by the malloc, only the pointer is being allocated and after you call free, it doesn't erase the memory, it just marks it as available on the heap to be over written later. – MattSmith
Update
I'm trying to modularize and put the creation of my array of structs in a function but nothing seems to work. I'm trying something very simple and I don't know what else to do. It's along the same lines as before, just another function, loaddata that is loading the data and outside the method I need to do some printing. How can I make it work? My code is as follows:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
typedef struct
{
char *str1;
char *str2;
} words;
void LoadData(words *, int *);
main()
{
words *x;
int num;
LoadData(&x, &num);
printf("%s %s", x[0].str1, x[0].str2);
printf("%s %s", x[1].str1, x[1].str2);
getch();
}//
void LoadData(words *x, int * num)
{
x = (words*) malloc(sizeof(words));
x[0].str1 = "johnnie\0";
x[0].str2 = "krapson\0";
x = (words*) realloc(x, sizeof(words)*2);
x[1].str1 = "bob\0";
x[1].str2 = "marley\0";
*num=*num+1;
}//
This simple test code is crashing and I have no idea why. Where is the bug?
You've tagged this as C++ as well as C.
If you're using C++ things are a lot easier. The standard template library has a template called vector which allows you to dynamically build up a list of objects.
#include <stdio.h>
#include <vector>
typedef std::vector<char*> words;
int main(int argc, char** argv) {
words myWords;
myWords.push_back("Hello");
myWords.push_back("World");
words::iterator iter;
for (iter = myWords.begin(); iter != myWords.end(); ++iter) {
printf("%s ", *iter);
}
return 0;
}
If you're using C things are a lot harder, yes malloc, realloc and free are the tools to help you. You might want to consider using a linked list data structure instead. These are generally easier to grow but don't facilitate random access as easily.
#include <stdio.h>
#include <stdlib.h>
typedef struct s_words {
char* str;
struct s_words* next;
} words;
words* create_words(char* word) {
words* newWords = malloc(sizeof(words));
if (NULL != newWords){
newWords->str = word;
newWords->next = NULL;
}
return newWords;
}
void delete_words(words* oldWords) {
if (NULL != oldWords->next) {
delete_words(oldWords->next);
}
free(oldWords);
}
words* add_word(words* wordList, char* word) {
words* newWords = create_words(word);
if (NULL != newWords) {
newWords->next = wordList;
}
return newWords;
}
int main(int argc, char** argv) {
words* myWords = create_words("Hello");
myWords = add_word(myWords, "World");
words* iter;
for (iter = myWords; NULL != iter; iter = iter->next) {
printf("%s ", iter->str);
}
delete_words(myWords);
return 0;
}
Yikes, sorry for the worlds longest answer. So WRT to the "don't want to use a linked list comment":
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char** words;
size_t nWords;
size_t size;
size_t block_size;
} word_list;
word_list* create_word_list(size_t block_size) {
word_list* pWordList = malloc(sizeof(word_list));
if (NULL != pWordList) {
pWordList->nWords = 0;
pWordList->size = block_size;
pWordList->block_size = block_size;
pWordList->words = malloc(sizeof(char*)*block_size);
if (NULL == pWordList->words) {
free(pWordList);
return NULL;
}
}
return pWordList;
}
void delete_word_list(word_list* pWordList) {
free(pWordList->words);
free(pWordList);
}
int add_word_to_word_list(word_list* pWordList, char* word) {
size_t nWords = pWordList->nWords;
if (nWords >= pWordList->size) {
size_t newSize = pWordList->size + pWordList->block_size;
void* newWords = realloc(pWordList->words, sizeof(char*)*newSize);
if (NULL == newWords) {
return 0;
} else {
pWordList->size = newSize;
pWordList->words = (char**)newWords;
}
}
pWordList->words[nWords] = word;
++pWordList->nWords;
return 1;
}
char** word_list_start(word_list* pWordList) {
return pWordList->words;
}
char** word_list_end(word_list* pWordList) {
return &pWordList->words[pWordList->nWords];
}
int main(int argc, char** argv) {
word_list* myWords = create_word_list(2);
add_word_to_word_list(myWords, "Hello");
add_word_to_word_list(myWords, "World");
add_word_to_word_list(myWords, "Goodbye");
char** iter;
for (iter = word_list_start(myWords); iter != word_list_end(myWords); ++iter) {
printf("%s ", *iter);
}
delete_word_list(myWords);
return 0;
}
If you want to dynamically allocate arrays, you can use malloc from stdlib.h.
If you want to allocate an array of 100 elements using your words struct, try the following:
words* array = (words*)malloc(sizeof(words) * 100);
The size of the memory that you want to allocate is passed into malloc and then it will return a pointer of type void (void*). In most cases you'll probably want to cast it to the pointer type you desire, which in this case is words*.
The sizeof keyword is used here to find out the size of the words struct, then that size is multiplied by the number of elements you want to allocate.
Once you are done, be sure to use free() to free up the heap memory you used in order to prevent memory leaks:
free(array);
If you want to change the size of the allocated array, you can try to use realloc as others have mentioned, but keep in mind that if you do many reallocs you may end up fragmenting the memory. If you want to dynamically resize the array in order to keep a low memory footprint for your program, it may be better to not do too many reallocs.
This looks like an academic exercise which unfortunately makes it harder since you can't use C++. Basically you have to manage some of the overhead for the allocation and keep track how much memory has been allocated if you need to resize it later. This is where the C++ standard library shines.
For your example, the following code allocates the memory and later resizes it:
// initial size
int count = 100;
words *testWords = (words*) malloc(count * sizeof(words));
// resize the array
count = 76;
testWords = (words*) realloc(testWords, count* sizeof(words));
Keep in mind, in your example you are just allocating a pointer to a char and you still need to allocate the string itself and more importantly to free it at the end. So this code allocates 100 pointers to char and then resizes it to 76, but does not allocate the strings themselves.
I have a suspicion that you actually want to allocate the number of characters in a string which is very similar to the above, but change word to char.
EDIT: Also keep in mind it makes a lot of sense to create functions to perform common tasks and enforce consistency so you don't copy code everywhere. For example, you might have a) allocate the struct, b) assign values to the struct, and c) free the struct. So you might have:
// Allocate a words struct
words* CreateWords(int size);
// Assign a value
void AssignWord(word* dest, char* str);
// Clear a words structs (and possibly internal storage)
void FreeWords(words* w);
EDIT: As far as resizing the structs, it is identical to resizing the char array. However the difference is if you make the struct array bigger, you should probably initialize the new array items to NULL. Likewise, if you make the struct array smaller, you need to cleanup before removing the items -- that is free items that have been allocated (and only the allocated items) before you resize the struct array. This is the primary reason I suggested creating helper functions to help manage this.
// Resize words (must know original and new size if shrinking
// if you need to free internal storage first)
void ResizeWords(words* w, size_t oldsize, size_t newsize);
In C++, use a vector. It's like an array but you can easily add and remove elements and it will take care of allocating and deallocating memory for you.
I know the title of the question says C, but you tagged your question with C and C++...
Another option for you is a linked list. You'll need to analyze how your program will use the data structure, if you don't need random access it could be faster than reallocating.
Your code in the last update should not compile, much less run. You're passing &x to LoadData. &x has the type of **words, but LoadData expects words* . Of course it crashes when you call realloc on a pointer that's pointing into stack.
The way to fix it is to change LoadData to accept words** . Thi sway, you can actually modify the pointer in main(). For example, realloc call would look like
*x = (words*) realloc(*x, sizeof(words)*2);
It's the same principlae as in "num" being int* rather than int.
Besides this, you need to really figure out how the strings in words ere stored. Assigning a const string to char * (as in str2 = "marley\0") is permitted, but it's rarely the right solution, even in C.
Another point: non need to have "marley\0" unless you really need two 0s at the end of string. Compiler adds 0 tho the end of every string literal.
For the test code: if you want to modify a pointer in a function, you should pass a "pointer to pointer" to the function. Corrected code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct
{
char *str1;
char *str2;
} words;
void LoadData(words**, int*);
main()
{
words **x;
int num;
LoadData(x, &num);
printf("%s %s\n", (*x[0]).str1, (*x[0]).str2);
printf("%s %s\n", (*x[1]).str1, (*x[1]).str2);
}
void LoadData(words **x, int *num)
{
*x = (words*) malloc(sizeof(words));
(*x[0]).str1 = "johnnie\0";
(*x[0]).str2 = "krapson\0";
*x = (words*) realloc(*x, sizeof(words) * 2);
(*x[1]).str1 = "bob\0";
(*x[1]).str2 = "marley\0";
*num = *num + 1;
}
Every coder need to simplify their code to make it easily understood....even for beginners.
So array of structures using dynamically is easy, if you understand the concepts.
// Dynamically sized array of structures
#include <stdio.h>
#include <stdlib.h>
struct book
{
char name[20];
int p;
}; //Declaring book structure
int main ()
{
int n, i;
struct book *b; // Initializing pointer to a structure
scanf ("%d\n", &n);
b = (struct book *) calloc (n, sizeof (struct book)); //Creating memory for array of structures dynamically
for (i = 0; i < n; i++)
{
scanf ("%s %d\n", (b + i)->name, &(b + i)->p); //Getting values for array of structures (no error check)
}
for (i = 0; i < n; i++)
{
printf ("%s %d\t", (b + i)->name, (b + i)->p); //Printing values in array of structures
}
scanf ("%d\n", &n); //Get array size to re-allocate
b = (struct book *) realloc (b, n * sizeof (struct book)); //change the size of an array using realloc function
printf ("\n");
for (i = 0; i < n; i++)
{
printf ("%s %d\t", (b + i)->name, (b + i)->p); //Printing values in array of structures
}
return 0;
}
If you want to grow the array dynamically, you should use malloc() to dynamically allocate some fixed amount of memory, and then use realloc() whenever you run out. A common technique is to use an exponential growth function such that you allocate some small fixed amount and then make the array grow by duplicating the allocated amount.
Some example code would be:
size = 64; i = 0;
x = malloc(sizeof(words)*size); /* enough space for 64 words */
while (read_words()) {
if (++i > size) {
size *= 2;
x = realloc(sizeof(words) * size);
}
}
/* done with x */
free(x);
Here is how I would do it in C++
size_t size = 500;
char* dynamicAllocatedString = new char[ size ];
Use same principal for any struct or c++ class.

Resources