I'm having trouble finding the answer to this problem; I've found similar examples of this online but none that address my problem.
I have a struct for the data for a company, Company, and a second struct for collections of companies, Consortium. The second struct will contain variable length arrays of the first struct, the company data struct. The number of elements of the variable length arrays will depend on the number of companies in a consortium.
I want to dynamically allocate whatever is required but I'm getting a bit lost. These are the structs:
typedef struct {
char code[];
double sharePrice;
int numShares;
double totalVal;
double totalDebts;
} Company;
typedef struct {
int numCore;
int numAssoc;
Company core[];
Company assoc[];
} Consortium;
There will be a number of core companies, and this number will be the size of the core array in the Consortium struct. Same goes for associate companies.
I came up with this expression but I'm not sure what I'm missing:
Consortium *consort=((Consortium*)malloc((numCore+numAssoc)*(sizeof(Consortium));
You'll need to use pointers and allocate the arrays separately:
typedef struct
{
char *code;
double sharePrice;
int numShares;
double totalVal;
double totalDebts;
} Company;
typedef struct
{
int numCore;
int numAssoc;
Company *core;
Company *assoc;
} Consortium;
Consortium *c = malloc(sizeof(*c)); // Error check
c->numCore = 4;
c->core = malloc(sizeof(*c->core) * c->numCore); // Error check
c->numAssoc = 3;
c->assoc = malloc(sizeof(*c->assoc) * c->numAssoc); // Error check
for (int i = 0; i < c->numCore; i++)
c->core[i].code = malloc(32); // Error check
for (int i = 0; i < c->numAssoc; i++)
c->assoc[i].code = malloc(32); // Error check
// Worry about other data member initializations!
It would be simpler and possibly better to modify the Company type to:
typedef struct
{
char code[32];
double sharePrice;
int numShares;
double totalVal;
double totalDebts;
} Company;
That saves the loops allocating the code elements.
You might consider that you make the Consortium struct a bit simpler. Since you have the counts for each type, core and assoc, you can have just a single array, the first part of which is for core and the second part of which is for assoc.
So your struct would look something like the following source (which has not been compiled and is just jotted down rather than tested so caveat emptor):
typedef struct {
int numCore; // number of core companies, first part of m_companies
int numAssoc; // number of assoc companies, second part of m_companies
Company m_companies[1];
} Consortium;
Then you would create your actual data structure by something like:
Consortium *makeConsortium (int numCore, int numAssoc) {
Consortium *pConsortium = malloc (sizeof(Consortium) + sizeof(Company) * (numCore, numAssoc));
if (pConsortium) {
pConsortium->numCore = numCore;
pConsortium->numAssoc = numAssoc;
}
return pConsortium;
}
After this you could fill it in by some functions which indicate success or not:
int addCompanyCore (Consortium *pConsortium, int index, Company *pCompany) {
int iRetStatus = 0;
if (pConsortium && index < pConsortium->numCore) {
pConsortium->m_companies[index] = *pCompany;
iRetStatus = 1;
}
return iRetStatus;
}
int addCompanyAssoc (Consortium *pConsortium, int index, Company *pCompany) {
int iRetStatus = 0;
if (pConsortium && index < pConsortium->numAssoc) {
index += pConsortium->numCore;
pConsortium->m_companies[index] = *pCompany;
iRetStatus = 1;
}
return iRetStatus;
}
And then you would access them with another set of helper functions.
Company *getCompanyCore (Consortium *pConsortium, int index) {
Company *pCompany = 0;
if (pConsortium && index < pConsortium->numCore) {
pCompany = pConsortium->m_companies + index;
}
return pCompany;
}
Company * getCompanyAssoc (Consortium *pConsortium, int index) {
Company *pCompany = 0;
if (pConsortium && index < pConsortium->numAssoc) {
index += pConsortium->numCore;
pCompany = pConsortium->m_companies + index;
}
return pCompany;
}
Related
I have a function that writes custom structs to some kind of "data block" (struct) that I created, which contains a void pointer that can store a custom struct. I created a function to write and to read to that specific void pointer but unfortunately, the first element of the returned struct always returns as "80" instead of it's original value. Here's the code:
#include <stdio.h>
#include <malloc.h>
typedef struct dataBlock {
void* dataObject;
} DataBlock;
typedef struct testingStruct {
int testingInt1;
int testingInt2;
}TestObject;
void dataWriter(DataBlock *dataBlock, void* inputObject, int objSize) {
if (objSize > 255) {
printf("Error. Maximum 255 Bytes of data can be stored.");
exit(0);
}
dataBlock->dataObject = malloc(objSize+1); // Allocates the size of dataObject plus one byte to store the size of the data Object.
((char*)dataBlock->dataObject)[0] = (char)objSize; //Stores the size of the data object to position 0 in the void*
for (int i = 1; i < objSize; ++i) {
((char*)dataBlock->dataObject)[i] = (char)((char*)inputObject)[i];
}
}
void* dataGetter(DataBlock *dataBlock) {
void* dataToReturn = malloc(((int)((char*)dataBlock->dataObject)[0])); // Creates Container to store read data using Void* Pos 0 in dataObject
for (int i = 1; i < (int)(((char*)dataBlock->dataObject)[0]); ++i) {
((char*)dataToReturn)[i] = (char)((char*)dataBlock->dataObject)[i]; //writes each byte of data to return to dataToReturn
}
return dataToReturn;
}
int main() {
TestObject *testObject = malloc(sizeof(TestObject));
testObject->testingInt1 = 74;
testObject->testingInt2 = 49;
DataBlock *dataBlockToStore = malloc(sizeof(DataBlock));
dataWriter(dataBlockToStore, testObject, sizeof(TestObject));
TestObject *testObjectCpy = dataGetter(dataBlockToStore); // Reads data from Block and generates another TestObject
printf("%d\n", testObjectCpy->testingInt1); // Should be 74
printf("%d\n", testObjectCpy->testingInt2); // Returned Correctly
return 0;
}
I am unsure, if I am either reading or writing the data in the wrong way but the first variable in the written testingStruct always returns a wrong value.
for (int i = 1; i < objSize; ++i) {
((char*)dataBlock->dataObject)[i] = (char)((char*)inputObject)[i];
Array indices are zero-based. You are skipping the first element.
You need to do e.g. (avoid i and 'l' in loops when adding 1.....)
for (int j = 0; j < objSize; ++j) {
((char*)dataBlock->dataObject)[j+1] = (char)((char*)inputObject)[j];
You could alternatively use memcpy.
You should also assert/fail if the size is above 255
Also, if you make dataBlock a char* you will need to perform less casting.
I have implemented naive Bayes but I did it in static memory allocation.
I wanted to convert into dynamic but my small brain is not able to do that.
#define COLS 4 //including class label
#define BINS 100
#define CLASS_COL 0
#define CLASS 2
The idea is to fetch above value from a configuration file and then set it.
struct each_col //Probability for each feature based on classes
{
double col_PB[BINS][CLASS];
};
struct NB_Class_Map
{
char label[250];
unsigned int label_value;
double class_PB;
};
struct NB //Proabability for entire feature
{
struct NB_Class_Map classes[CLASS];
struct each_col cols[COLS];
};
NB nb = {0}; //gloabal value
The function to train NB:
long strhash(const char *str)
{
long hash = 5381;
int c;
printf("IN: %s ",str);
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
printf("OUT: %ld ||",hash);
return hash;
}
int setup_train_NB(vector<vector<string> > &data)
{
//Finding the feature count
static int class_label = -1;
for(unsigned int i=0;i<data.size();i++)
{
unsigned int Class;
printf("\n===========New ROW==============\n");
int k;
for(k=0;k<CLASS;k++)
{
if(strcmp(data[i][CLASS_COL].c_str(), nb.classes[k].label) == 0)
{
printf("MATCHED\n");
Class = nb.classes[k].label_value;
break;
}
}
if(k==CLASS)
{
printf("NOT MATCHED\n");
class_label++;
nb.classes[class_label].label_value = class_label;
strcpy( nb.classes[class_label].label, data[i][CLASS_COL].c_str());
Class = nb.classes[class_label].label_value;
}
printf("Class: %d ||\n", Class);
for(unsigned j=0;j<data[0].size();j++)
{
printf("\n===========New COLUMN==============\n");
if(j == CLASS_COL)
{
nb.classes[Class].class_PB++;
continue;
}
unsigned int bin = strhash((data[i][j].c_str()))%BINS;
printf("Bin: %d ||", bin);
printf("Class: %d ||\n", Class);
nb.cols[j].col_PB[bin][Class]++; //[feature][BINS][CLASS]
}
}
//Finding the feature PB
for(unsigned int i=0;i<COLS;i++)
{
if(i==CLASS_COL)
continue;
for(unsigned j=0;j<BINS;j++)
{
for(unsigned k=0;k<CLASS;k++)
{
// nb.cols[i].col_PB[j][k] /= nb.classes[k].class_PB; //without laplacian smoothing
nb.cols[i].col_PB[j][k] = (nb.cols[i].col_PB[j][k] + 1) / (nb.classes[k].class_PB + COLS - 1); //with laplace smoothing
}
}
}
int k = 0;
int sum = 0;
while(k<CLASS)
{
sum += nb.classes[k].class_PB;
k++;
}
//Finding the class PB
k = 0;
while(k<CLASS)
{
nb.classes[k].class_PB /= sum;
k++;
}
return 0;
}
The program is supposed to be written in C but for the moment, I use vector to fetched the data from a CSV file. Please ignore that for the moment. The actual question is how I can remove those hardcoded define value and still declare my structs.
Although it does not matter but the CSV file look like this and it may change in terms of no of cols and labels. The first line is ignored and not put into data.
Person,height,weight,foot
male,654,180,12
female,5,100,6
female,55,150,8
female,542,130,7
female,575,150,9
What actually I am doing is, for each value is put into a bin, then for each of those value, I am finding proabability for the CLASS/label i.e male = 0, female = 1
Basically:
Define variables instead of preprocessor macro constants: size_t cols; size_t bins; etc.
Replace your 1-dimensional fixed-size arrays with pointers (initialized to NULL!) and length variables. Alternatively, you could use a struct mytype_span { size_t length; mytype* data; }
Replace your 2-dimensional fixes-size arrays with "1-dimensional" pointers (also initialized to NULL of course) and pairs off dimension variables. Again, you could use a struct.
Replace your 2-d array accesses a[x][y] with a "linearized" access, i.e. a[x * row_length_of_a + y] (or you could do this in an inline function which takes the relevant arguments, or a struct mytype_span)
When you've read your configuration values from, um, wherever - set the relevant length variables (see above).
use the malloc() library function to allocate the correct amount of space; remember to check the malloc() return value to make sure it's not null, before using the pointer values!
Your use of struct, is probably wrong, except for struct NB_Class_Map. You shouldn't use struct in the goal of puting big arrays in the same variable. Instead of this, you should define of variable for each array, not putting it inside a struct, and instead of using array, replace it by a pointer. Then you can allocate memory to your pointer. e.g. :
struct mydata {
type1 field1;
type2 field2;
etc...
} *myarray;
myarray = calloc(number_of_record_you_need, sizeof(struct mydata));
// here, error checking code, etc.
Now, having done that, if you really want, you may put your different pointers into a global structure, but each of your table should be allocated separately.
Edit (about your variables) :
NB has no real interest as a structure. It's just 2 variables you glued together:
struct NB_Class_Map classes[CLASS];
struct each_col cols[COLS];
NB.Cols is not really a structure. It's just a three dimensional array
double cols[COLS][BINS][CLASS];
The only real structure is
struct NB_Class_Map
{
char label[250];
unsigned int label_value;
double class_PB;
};
So you just have to replace
struct NB_Class_Map classes[CLASS];
with
struct NB_Class_Map *classes;
and
double cols[COLS][BINS][CLASS];
with
double *cols[BINS][CLASS];
Or if you want a type name :
typedef double each_col[BINS][CLASS];
each_cols *cols;
and allocate memory space for classes and colls with calloc.
Now, if you really want this struct NB :
typedef double each_col[BINS][CLASS];
struct NB
{
struct NB_Class_Map *classes;
each_col *cols;
};
I am new to C programming and I am trying to create a key value structure as in Perl Programming. I saw one solution like :-
struct key_value
{
int key;
char* value;
};
struct key_value kv;
kv.key = 1;
kv.value = "foo";
But I don't know how to access these values from this structure. Can someone enlight on this ?
Here is an example:
#include <stdio.h>
#include <stdlib.h>
struct key_value
{
int key;
char* value;
};
int main(void)
{
int number_of_keys = 2;
struct key_value *kv = malloc(sizeof(struct key_value) * number_of_keys);
if (kv == NULL) {
perror("Malloc");
exit(EXIT_FAILURE);
}
kv[0].key = 8;
kv[0].value = "Test 8 key!";
kv[1].key = 6;
kv[1].value = "Test 6 key!";
printf("Key = %d\nKey value = %s\n", kv[0].key, kv[0].value);
printf("Key = %d\nKey value = %s\n", kv[1].key, kv[1].value);
free(kv);
return 0;
}
What you are missing is a collection. Most languages have a data type called a dictionary or a map or an associative array or some variation thereof. C does not have a data structure of this type; in fact, the only collection type you have built in to C is the array. So, if you want something where you can supply a key and get the value, you have to roll your own or find one on the Internet. The latter is probably preferable because you are likely to make mistakes and produce a slow data structure if you roll your own (especially if you are a beginner).
To give you a flavour of what you'll end up with, here's a simple example:
You'll need something to represent the collection; call it a ListMap for now:
struct ListMap;
The above is called an incomplete type. For now, we are not concerned with what's in it. You can't do anything with it except pass pointers to instances around.
You need a function to insert items into your collection. Its prototype would look something like this:
bool listMapInsert(struct ListMap* collection, int key, const char* value);
// Returns true if insert is successful, false if the map is full in some way.
And you need a function to retrieve the value for any one key.
const char* listMapValueForKey(struct ListMap* collection, int key);
You also need a function to initialise the collection:
struct ListMap* newListMap();
and to throw it away:
void freeListMap(struct ListMap* listMap);
The hard bit is implementing how those functions do what they do. Anyway, here's how you would use them:
struct ListMap* myMap = newListMap();
listMapInsert(myMap, 1, "foo");
listMapInsert(myMap, 1729, "taxi");
listMapInsert(myMap, 28, "perfect");
char* value = listMapValueForKey(myMap, 28); // perfect
freeListMap(myMap);
Here's a simple implementation. This is just for illustration because I haven't tested it and searching for entries increases linearly with the number of entries (you can do much better than that with hash tables and other structures).
enum
{
listMapCapacity = 20
};
struct ListMap
{
struct key_value kvPairs[listMapCapacity];
size_t count;
};
struct ListMap* newListMap()
{
struct ListMap* ret = calloc(1, sizeof *ret);
ret->count = 0; // not strictly necessary because of calloc
return ret;
}
bool listMapInsert(struct ListMap* collection, int key, const char* value)
{
if (collection->count == listMapCapacity)
{
return false;
}
collection->kvPairs[count].key = key;
collection->kvPairs[count].value = strdup(value);
count++;
return true;
}
const char* listMapValueForKey(struct ListMap* collection, int key)
{
const char* ret = NULL;
for (size_t i = 0 ; i < collection->count && ret == NULL ; ++i)
{
if (collection->kvPairs[i].key == key)
{
ret = kvPairs[i].value;
}
}
return ret;
}
void freeListMap(struct ListMap* listMap)
{
if (listMap == NULL)
{
return;
}
for (size_t i = 0 ; i < listMap->count ; ++i)
{
free(listMap->kvPair[i].value);
}
free(listMap);
}
typedef struct key_value
{
int key;
char* value;
}List;
struct key_value k1;
struct key_value k2;
struct key_value k3;
k1.key = 1;
k1.value = "foo";
k2.key = 2;
k2.value = "sec";
k3.key = 3;
k3.value = "third";
You will need to create N times the struct and give them values the way you did the first one. Or create array with N structs and iterate assign it values with a loop.
Array:
List arr[29];
int i;
for(i = 0;i<=28;i++){
arr[i].key = i;
arr[i].value = "W/e it needs to be";
}
The functionality you are looking for needs your own implementation in C; e.g. an array of your struct-type.
Here is an example of how to read the value for a key, without knowing anything about at which array-index the key will be found.
I have the keys numbered backward in order to illustrate that.
Note that more sophisticated API definitions are needed for special cases such as non-existing key; I just blindly return the last entry to keep things easy here.
#include <stdio.h>
#define MAPSIZE 30
struct key_value
{
int key;
char* value;
};
struct key_value kvmap[MAPSIZE];
void initmap(void)
{
int i;
for(i=0; i<MAPSIZE; i++)
{
kvmap[i].key=MAPSIZE-i-1;
kvmap[i].value="unset";
}
kvmap[0].value="zero";
kvmap[1].value="one";
kvmap[2].value="two";
kvmap[3].value="three";
kvmap[4].value="four";
kvmap[5].value="five";
kvmap[6].value="six";
kvmap[7].value="seven";
kvmap[8].value="eight";
kvmap[24].value="find this"; // it has the key "5"
}
char* readmap(int key)
{
int i=0;
while ((i<MAPSIZE-1) && (kvmap[i].key!=key))
{ printf("Not in %d\n", i);
++i;}
// will return last entry if key is not present
return kvmap[i].value;
}
int main(void)
{
initmap();
printf("%s\n", readmap(5));
return 0;
}
"I have to store 30 key/value pair"
Create an array of struct e.g., key_value.
struct key_value
{
int key;
char* value;
};
struct key_value kv[30];
kv[0].key = 1;
kv[0].value = "foo";
printf("%s", kv[0].value);
You can loop through to assign values to keys and values.
Access to whatever is in kv is simple.
int i = kv[0].key`;// copy value of k[0].key to i
char *v = kv[0].value; // copy value of k[0].value to v;
Your code already have the method to acess the values.
kv.key = 1
kv.value = "foo"
To get the values assigned is simple
kv.key
kv.value
It is a simple struct, if you wanna something like python dict you will need to implement a hash struct which will be more complicated.
I'm trying to create the following array:
"Fruits", 25, {
{"Apple", 2},
{"Grapes", 13},
{"Melon", 10}
}
"Meats", 40, {
{"Beef", 9},
{"Chicken", 27},
{"Pork", 4}
}
...
Feels like there's a more elegant way of doing what I got so far. Any feedback/samples on how to create this structure more efficient given the input struct would be appreciated.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct Product {
char *name;
int qty;
} Prods;
typedef struct Category {
char *name;
int qty;
int prods_count;
Prods *prod;
} Cats;
typedef struct Inventory {
Cats *cat;
int cats_count;
} Inv;
struct tmp_input {
char name[12];
int qty;
char cat[12];
};
// return index if found
int in_array(Inv *inv, char *k) {
int i;
if (inv->cats_count == 0)
return -1;
for (i = 0; i < inv->cats_count; i++) {
if (strcmp (k, inv->cat[i].name) == 0) return i;
}
return -1;
}
int main () {
int i, j, exists = 0;
// temp struct.
struct tmp_input items[] = {
{"Apple", 2, "Fruit"}, {"Coke", 10, "Drink"}, {"Pork", 4, "Meat"},
{"Beef", 9, "Meat"}, {"Chicken", 27, "Meat"}, {"Melon", 10, "Fruit"},
{"Tea", 3, "Drink"}, {"Coffee", 20, "Drink"}, {"Grapes", 13, "Fruit"}
};
size_t len = sizeof (items) / sizeof (struct tmp_input);
Inv *inven = malloc(sizeof(Inv));
inven->cats_count = 0;
inven->cat = calloc(1, sizeof(Cats));
for (i = 0; i < len; i++) {
exists = in_array(inven, items[i].cat);
// category does not exist
if (exists == -1) {
inven->cat = realloc(inven->cat, sizeof(Cats) * (inven->cats_count + 1));
inven->cat[inven->cats_count].name = strdup(items[i].cat);
inven->cat[inven->cats_count].qty += items[i].qty;
inven->cat[inven->cats_count].prods_count = 1;
inven->cat[inven->cats_count].prod = calloc (1, sizeof (Prods));
inven->cat[inven->cats_count].prod->name = strdup (items[i].name);
inven->cat[inven->cats_count].prod->qty = items[i].qty;
inven->cats_count++;
}
// category found
else {
inven->cat[exists].qty += items[i].qty;
int size = inven->cat[exists].prods_count + 1;
inven->cat[exists].prod = realloc(inven->cat[exists].prod, sizeof(Prods) * (size));
inven->cat[exists].prod[size - 1].name = strdup (items[i].name);
inven->cat[exists].prod[size - 1].qty= items[i].qty;
inven->cat[exists].prods_count++;
}
}
for (i = 0; i < inven->cats_count; i++) {
printf("%3d %s\n", inven->cat[i].qty, inven->cat[i].name);
for (j = 0; j < inven->cat[i].prods_count; j++) {
printf("%3d %s\n", inven->cat[i].prod[j].qty, inven->cat[i].prod[j].name);
}
}
return 0;
}
You aren't allocating any memory for the Prod array.
Something like
...
if (exists == -1) {
inven->cat = realloc(inven->cat, sizeof(Cats) * (inven->cats_count + 1));
inven->cat[inven->cats_count].name = items[i].cat;
inven->cat[inven->cats_count].qty += items[i].qty;
// Allocate memory for 1 product
inven->cat[inven->cats_count].prods_count = 1;
inven->cat[inven->cats_count].prod = malloc (sizeof (Prods));
// Now allocate space and copy the name
inven->cat[inven->cats_count].prod->name = strdup (items[i].name + 1);
inven->cats_count++;
}
...
I will leave it to you to handle the case where there are more than 1 product in a category, where you'll need to reallocate the memory again.
Another error is that you need to allocate and copy the category name
inven->cat[inven->cats_count].name = items[i].cat;
should be replaced by
inven->cat[inven->cats_count].name = strdup (items[i].cat);
This is because the items array does not exist outside of this function, so if you just do
inven->cat[inven->cats_count].name = items[i].cat;
then after you leave this function, invent->cat[inven->cats_count].name will point to garbage memory.
A final suggestion would be to split each structure into a function that handles creation of it, just to clean up the code.
--- edit to add comments on Abstract Data Types
Arrays are useful if you have data that you know you will be accessing via indices. If you don't know the index of the item you want (as in this case), an array is less useful.
Unlike other comments, I don't think using a Linked List really gives you anything useful. Linked Lists are useful when you need to walk sequentially through all the items, without really caring where they are in the list. It seems to me that the most common use case for a system like you are creating is searching: Do we have any Fruit in stock? Add 10 cases of Coke to the inventory... those sorts of things.
Also, you only want a single entry for each category/product. You don't want 3 Fruit categories in the data. Both arrays and linked lists don't really have any restrictions on adding the same structure multiple times. This means that every time you'll need to check the whole list to see if you need to add the new structure.
For that reason, I'd certainly make both the Categories and products arrays into hashtables (or called a dictionary in some languages) that map name -> structure. This will speed up your search as you don't have to search the entire dataset every time and will prevent you from adding the same structure multiple times.
Wikipedia article on Hashtables: http://en.wikipedia.org/wiki/Hashtable
Here's an example of how to set up the structures dynamically (simpler than a linked list, but not as flexible).
typedef struct Product {
char *name;
int qty;
} Prods;
typedef struct Category {
char *name;
int qty;
int prods_count;
Prods *prod; // dynamic array of Products
} Cats;
The structures as they were.
struct Category categ[10];
An arbitrary number of categories, for now take categ[0] for 'Fruits'.
Next dynamically create an array of 10 product structures:
Prods *prod_array = malloc(sizeof(Prods) * 10); // i.e. prod_array[0] to [9]
Now just store the array in the category structure:
categ[0].prod = prod_array;
categ[0].prods_count = 10;
If you need to access the product name, it's just: categ[i].prod[j].name
Now, if you need another 10 products, you can just use realloc to increase the size of the array, and update its count.
Put all these things in functions, and the code isn't too complex.
I'm having some very strange bug in my ANSI C program.
I'm using debugger and I've observed that 'size' variable is corrupted in function 'doSthing.' Outside of 'doSthing' 'size' got a proper value, but inside 'doSthing' I've got a value nothing similar to what it should be, possibly some random data. This would be not be such a mystery but...
In 'doAnotherThing' which is called from 'doSthing' I get the proper value again. I suppose if it passes the correct value, it is not corrupted anyway, am I wrong? But then why does it have a different value?
The pointer in struct does not change inside the functions.
Memory is allocated for both oTV and oTV->oT.
I really don't see what's happening here...
typedef struct{
ownType *oT[] /* array of pointers */
int size;
} ownTypeVector;
void doSthing(ownTypeVector* oTV);
void doAnotherThing(ownTypeVector* oTV);
void doSthing(ownTypeVector* oTV)
{
...
doAnotherThing(oTV);
...
}
Thanks for your comments, I collected all the code that contains control logic and data structures so that it compiles. It runs on in an embedded systems, that can receive characters from multiple sources, builds strings from it by given rules and after the strings are ready, calls a function that needs that string. This can also be a list of functions. This is why I have function pointers - I can use the same logic for a bunch of things simply by choosing functions outside the 'activityFromCharacters' function.
Here I build a data structre with them by adding A-s, B-s and C-s to the AVector.
Of course every one of these separate sources has their own static strings so that they do not bother each other.
The problem again in the more detailed version of the code:
'aV->size' has got a proper value everywhere, except 'handleCaGivenWay.' Before it gets calles, 'aV->size' is ok, in 'addA' 'aV->size' is ok, too. After leaving 'handleCaGivenWay' it is ok again.
#define NUMBER_OF_AS 1
#define NUMBER_OF_BS 5
#define NUMBER_OF_CS 10
typedef struct{
char name[81];
} C;
typedef struct{
C *c[NUMBER_OF_CS]; /* array of pointers */
int size;
int index;
} B;
typedef struct{
B *b[NUMBER_OF_BS]; /* array of pointers */
char name[81];
int size;
} A;
typedef struct{
A *a[NUMBER_OF_AS]; /* array of pointers */
int size;
} AVector;
typedef struct {
char *string1;
char *string2;
} stringBundle;
typedef struct{
void (*getCharacter)(char *buffer);
void (*doSthingwithC)(stringBundle* strings,AVector* aV);
AVector* aV;
} functionBundle;
void getCharFromaGivenPort(char *buffer)
{
//...
}
void addA(AVector * aV, stringBundle* strings)
{
aV->a[aV->size]->size = 0;
++aV->size;
int i = 0;
if(strlen(strings->string2) < 81)
{
for(i;i<81;++i)
{
aV->a[aV->size-1]->name[i] = strings->string2[i];
}
}
else {report("Too long name for A:");
report(strings->string2);}
}
void handleCaGivenWay(stringBundle* strings,AVector* aV)
{
A* a;
a = NULL;
if(aV->size) { a = aV->a[aV->size-1]; }
switch(1)
{
case 1: addA(aV,strings); break;
case 2: //addB()...
default: if (a && aV->size)
{ //addC(a->thr[a->size-1],c);
}
else report("A or B or C invalid");
break;
}
//handleCaGivenWay
}
void activityFromCharacters(stringBundle* strings,functionBundle* funcbundle)
{
/* some logic making strings from characters by */
/* looking at certain tokens */
(* funcbundle->doSthingwithC)(strings,funcbundle->aV);
}
//activityFromCharacters
AVector* initializeAVector(void)
{
AVector* aV;
if (NULL == (aV = calloc(1,sizeof(AVector))))
{ report("Cannot allocate memory for aVector."); }
int i = 0;
int j = 0;
int k = 0;
for(i; i < NUMBER_OF_AS; ++i)
{
if (NULL == (aV->a[i] = calloc(1,sizeof(A))))
{ report("Cannot allocate memory for As."); }
aV->a[i]->size = 0;
aV->a[i]->name[0] = 0;
for(j; j < NUMBER_OF_BS; ++j)
{
if (NULL == (aV->a[i]->b[j] = calloc(1,sizeof(B))))
{ report("Cannot allocate memory for Bs."); }
aV->a[i]->b[j]->size = 0;
for(k; k < NUMBER_OF_CS; ++k)
{
if (NULL == (aV->a[i]->b[j]->c[k] = calloc(1,sizeof(C))))
{ report("Cannot allocate memory for Cs."); }
}
}
}
aV->size = 0;
return aV;
//initializeProgramVector
}
int main (void)
{
AVector* aV;
aV = initializeAVector();
while(1)
{
static stringBundle string;
static char str1[81];
static char str2[81];
string.string1 = str1;
string.string2 = str2;
functionBundle funcbundle;
funcbundle.getCharacter = &getCharFromaGivenPort;
funcbundle.doSthingwithC = &handleCaGivenWay;
funcbundle.aV = aV;
activityFromCharacters(&string,&funcbundle);
}
//main
}
your code shows that it hasn't any error...
But i think you are doing mistake in getting the value of size in doSthing function.
you are printing there its address. so concentrate on some pointer stuff..
Try printing the oTV->size just before the call and as the first statement in doSthing function. If you get the correct value in both print, then the problem is with the function doSthing. Problem could be better understood if you've shown the code that calls doSthing.
Searched a long time to find this. I found 2 problems, but dont know what exactly you are trying to accomplish so i cannot tell for certain that the fix'es i propose are what you intend.
typedef struct{
A *a[NUMBER_OF_AS]; /* array of pointers */
int size;
} AVector;
// and in addA():
aV->a[aV->size]->size = 0;
First: You are inlining the array of pointers in the struct. What i think what you want and need is a pointer to a pointer array so that it can grow which is what you want in addA() i think. The line from addA() aV->a[aV->size]->size = 0; does not communicate your intention very well but it looks like you are trying to change the value beyond the last entry in the array and since it is inlined in the struct it would result to the separate field size by pure coincidence on some alignments; this is a very fragile way of programming. So what i propose is this. Change the struct to contain A** a; // pointer to pointer-array, malloc it initially and re-malloc (and copy) it whenever you need it to grow (in addA()).