I am trying to play around with structures in C and I am stuck at this point. Here's my code:
#include <stdio.h>
void Test(void);
void updateIt(struct Item* ptr);
struct Item
{
double value;
int unitno;
int isTa;
int quant;
int minQuant;
char name[21];
};
int main(void)
{
Test(); // here I am gonna call updateit() function and print
}
void Test(void) {
struct Item I = { 100.10,100,10,110,10,"NAME!" };
updateIt(&I);
}
void updateIt(struct Item* ptr){
struct Item I[0] = 200 // This doesn't work — but why?
}
How do I update values of Item I = { 100.10,100,10,110,10,"NAME!" } to { 200.20,200,20,220,20,"NAME2!"} by accessing values inside the updateIt function?
In the code snippet:
void updateIt(struct Item* ptr){
struct Item I[0] = 200 // This doesn't work — but why?
}
There is no variable I in this scope.
Since you passed the address of the structure through updateIt(&I); in the above function you will have to use the pointer to it.
The pointer variable ptr in the arguments of the function has the address of the structure, which can be used to update the values as :
ptr->structureMember
where structureMember is any member of the structure.
updateIt(struct Item* ptr) accepts pointer ptr of type item; to access fields of structure Item using a pointer, one should use -> operator like below:
void updateIt(struct Item* ptr){
ptr->value = 200.20;
ptr->unitno = 200;
ptr->isTa = 20;
ptr->quant = 220;
ptr->minQuant = 20;
strcpy(ptr->name, "NAME2");
}
You must use the ptr value like
ptr->unitno = 200 and so for every member of the struct
Related
I'm working on a project that strictly requires to realize two set of functions in C with same signature that can be used from a sigle .c test file. one set is for a data structure, the other one for a different and incompatible data structure.
Since in C there is no polymorphism is not possible to call a function that has two implementation with same signature in two different headers (.h) files and taking for granted that the call will be referred to the right implementation of the function that is actually capable of managing the right data structure.
Ok I know it seems impossible and contradictory but..that is it...
I have to merge two generic items that can be list or dynamic array
Update:
on List.h (dynamicArray is in another .h)
typedef struct Node{
void *data;
struct Node *next, *prevNode;
} Node;
//typedef struct declaration List
typedef struct List {
struct Node *top, *bot, *prev;
int size;
} List;
//in the dynamicarray.h file:
typedef struct dynamicArray{
void **array;
size_t size;
size_t capacity;
}dynArray;
//in the dynamicarray.h file:
void* merge(void *element1,void *element2, int parameters){
void * returner;
if (parameters==ARRAY) {
returner= Array_Merge(element1,element2); // expected to receive two arrays
}
else {
returner= List_Merge(element1,element2); // expected to reveice two lists
}
return returner;
}
Do you have any suggestion to accomplish this request?
Thanks.
You need to pass both, a pointer to your function and some handler function to the test, along with argument(s). In 'c' void * can be use in place of any pointer. Something like the following might work for you:
int mytest(void*(*function)(void *), int(*handler)(void *), void *arg) {
if (handler(function(arg)))
return OK;
return FAIL;
}
So, you just need to have separate handler functions for arrays and lists and pass them to the test function along with other params.
Answering your last comment
I can imagine some scheme as the following.
List list1;
dyArray array1;
MergedList outList;
MergedArray outArray;
...
void *getNextArrayElement(dynArray *array){...}
void *getNextListElement(List *list){...}
int mergeAsList(void* el, void *list){
if (el == NULL)
return 0;
ListMember *mmb = malloc(sizeof(ListMember));
mmb->el = el;
mmb->next = ((MergeList*)list)->head;
(MergeList*)mergeList->head = mmb;
return 1;
}
int mergeAsArray(void *el, void *array) {
if (el == NULL)
return 0;
if (((MergeArray *)array)->index) >= MAX)
return 0;
((MergeArray *)array)[((MergeArray *)array)->index++] = el;
return 1;
}
int mergeAsSortedArray(void *el, void *array){...}
...
test(getNextArrayEelement, mergeAsList, &arraty1, &outList);
test(getNextListEelement, mergeAsList, &list1, &outArray);
...
int test (void *(get*)(void*),
int (merge*)(void *m1, void *result),
void *in,
void *out) {
void *el = get(in);
int res = merge(el, out);
return res;
}
Function pointers are the means in which you accomplish this.
Function pointers are what you would use if, for example, you wanted to pass a function to a sort function that told the sort function how to compare two adjacent members. Such a comparison function allows you to provide a generalized sort function that will work on a collection of any struct, since you can change out the comparison function to accommodate any struct.
Consider the following sort code:
typedef struct node{
void* item;
struct node* next;
} Node;
// Just an ordinary bubble sort
void sort(Node *start, bool greaterThan(void* a, void* b))
{
int swapped, i;
Node *ptr1;
Node *lptr = NULL;
/* Checking for empty list */
if (start == NULL)
return;
do
{
swapped = 0;
ptr1 = start;
while (ptr1->next != lptr)
{
if (greaterThan(ptr1->item, ptr1->next->item))
{
swap(ptr1, ptr1->next);
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
}
while (swapped);
}
// Swap function used above
void swap(Node *a, Node *b)
{
void* temp = a->item;
a->item = b->item;
b->item = temp;
}
To use it, we just need to define a payload to put into Node* item and a sort function to tell it how to order the items:
typedef struct {
int book_id;
char title[50];
char author[50];
char subject[100];
char ISBN[13];
} Book;
// Comparison function.
bool bookGreaterThan(void* left, void* right)
{
Book* a = (Book*)left;
Book* b = (Book*)right;
return strcmp(a->title, b->title) > 0;
}
Finally, you would sort your list like so:
// Pass a pointer to the first node in your list, and a function pointer to your comparer.
sort(pointerToMyList, bookGreaterThan);
A complete example can be found here.
See also Is it possible to achieve runtime polymorphism in C?
I am creating a simple array of structures in C, but the first structure is always jibberish. How do i fix this?
I have tried to set the first element of the double pointer to struct in many ways but it always fails.
This is my graph.h file:
#ifndef GRAPH_H
#define GRAPH_H
#include "set.h"
typedef struct urlNode * URLList;
typedef struct GraphRep * Graph;
struct urlNode {
int id;
char* URL_NAME;
URLList next; // link to next node
};
struct GraphRep {
int nV;
URLList * collections;
};
Graph newGraph(Set s);
int nameToId(Graph g, char *name);
void showGraph(Graph g);
#endif
And my newGraph(Set s) function looks like this:
Graph newGraph(Set s){
int size = nElems(s);
Graph new_graph = malloc(sizeof(struct GraphRep));
if (new_graph == NULL) {
printf("ERROR: COULDNT ALLOCATE GRAPH\n");
}
new_graph->nV = size;
char *name = getNextVal(s);
// THIS IS THE NODE TO BE ADDED TO THE GRAPH
URLList list_to_add = malloc(sizeof(struct urlNode));
list_to_add->URL_NAME = strdup(name);
list_to_add->id = 0;
list_to_add->next = NULL;
// HERE I ADD THE NODE TO THE GRAPH.
new_graph->collections[0] = list_to_add;
// PRINT OUT THE VALUES OF THE NEWLY ADDED NODE TO MAKE SURE IT WORKS
// THE URL_NAME IS PRINTED OUT FINE
// BUT THE ID IS JIBBERISH.
printf("%s\n", new_graph->collections[0]->URL_NAME);
printf("%d\n", new_graph->collections[0]->id);
if(new_graph->collections[0]->next != NULL) {
printf("%s\n", new_graph->collections[0]->next->URL_NAME);
printf("%d\n", new_graph->collections[0]->next->id);
}
printf("\n");
return new_graph;
}
I expect new_graph->collections[0]->id to be 0 but it keeps on giving me random ints.
Also even if the next for the newly declared pointer to struct is NULL, it still gives me a jibberish next value too.
Any help would be appreciated, thanks!
The data member collections of the object *new_graph is not initialized.
There is initialized only this data member
new_graph->nV = size;
So this statement
new_graph->collections[0] = list_to_add;
results in undefined behavior.
If you need an array of pointers of the type URLList you have to allocate the memory and its address assign to the pointer collections.
For example
new_graph->collections = malloc( new_graph->nV * sizeof( URLList ) );
And after that this statement
new_graph->collections[0] = list_to_add;
could be valid.
(I suppose that the data member nV corresponds to the number of elements in the dynamically allocated array though it may not be truth)
Pay attention to that as the string pointed to by the pointer name is not changed in the function then it is better to declare it like
const char *name = getNextVal(s);
It has been a LONG time (25y) since I have done C and so I forget some things so please forgive the question.
Given that I have the following declarations:
typedef struct item {
int field;
} Item;
typedef struct data {
Item b;
} Data;
I have been trying to update the struct when its passed to a function and this doesn't work at all.
static void foo(Data *data) {
data->b.field = 3; // doesn't work, the struct remains unchanged.
}
static void test() {
Data v = {.b = {.field = 2}};
foo(&v);
}
However, if I alter the declaration slightly, use malloc to allocate it it works.
typedef struct data {
Item *b;
};
static void foo(struct data *data) {
data->b->field = 3; // works.
}
static void test() {
Data v = (struct data*) malloc(sizeof(Data));
Item i = (struct item*) malloc(sizeof(Item));
foo(v);
free(i);
free(v);
}
Can someone inform me why this is? Is it not possible to have struct members that are updatable as members? How could I make the first example work?
Thanks in advance.
Your first approach actually works (and I would have been surprised if it did not):
struct item {
int field;
};
struct data {
struct item b;
};
static void foo(struct data *data) {
data->b.field = 3;
}
static void test() {
struct data v = {.b = {.field = 2}};
printf("v.b.field before calling foo: %d\n", v.b.field);
foo(&v);
printf("v.b.field afterwards: %d\n", v.b.field);
}
int main() {
test();
}
Output:
v.b.field before calling foo: 2
v.b.field afterwards: 3
Probably your setting is a different one that than you've shown in the code. Mysterious things (i.e. undefined behaviour) often happens if you access an object after it's lifetime has ended. malloc often prevents such issues as it keeps an object alive until it is explicitly freed.
But in your case, there should not be any difference.
BTW: the typedef does not make sense, as you do not define an alias for the struct-type just declared. So
struct item {
int field;
};
is sufficient.
I want to pass struct members in function . I don't mean something like that:
struct smth
{
int n;
};
void funct(struct smth s);
I want these structs
struct student {
char name[50];
int semester;
};
struct prof {
char name[50];
char course[50];
};
struct student_or_prof {
int flag;
int size;
int head;
union {
struct student student;
struct prof prof;
}
}exp1;
struct student_or_prof *stack;
struct student_or_prof exp2;
To pass their members in a fucntion with variables not struct variables
int pop(int head,int n)
{
if(head==n)
return 1;
else head++;
}
Because i don't want to use the function for structs only. Is it possible?
EDIT I want the numbers also to change , not return , something like pointer.
EDIT_2 Also i know that this pop(exp1.head,n) it works, but i want also the exp1.head to change after the end of the function pop.
Use pointers. pass poniter to exp1.head and manipulate it by dereferencing it in function as,
int pop(int * head,int n)
{
if(*head==n)
return 1;
else (*head)++;
}
call function as,
pop(&exp1.head,n);
First things first, you are missing a semicolon, after the union definition inside the struct student_or_prof.
As per your edit #2, you should be passing the address of the variable, taking it as a pointer to a variable by the function, and then editing/incrementing the content of the address (the variable that pointer points to). Like the following:
#include <stdio.h>
struct student_or_prof {
int head;
} exp1;
int pop( int * head, int n ) {
if ( *head == n )
return 1;
else (*head)++;
}
int main( ){
int returnval;
exp1.head = 5;
returnval = pop( &exp1.head, 10 );
printf( "%d", exp1.head );
getchar( );
return 0;
}
This will print a 6. Here, I am passing the address of the exp1.head, so that the function pop can refer to the actual exp1.head you have in your hands. Otherwise, the pop will be only informed about the value that exp1.head had, copy that value into its own head variable, play around with that.
And also, it would be sensible to return some int from the pop in any case. Right now it returns a value only when *head == n is satisfied, and returns something that wouldn't make sense. I don't think you'd want that, so:
...
else {
(*head)++;
return 0;
}
...
Would be better.
If you don't like the parenthesis around the *head, then you may want to use ... += 1; instead of a postfix increment, which has less precedence over the dereferencing operator *.
I have written the following code for my project. The code is scattered across various files and quite long so i am posting the minimal code.
#include<stdio.h>
#include<stdbool.h>
struct TwoPoint
{
int width;
int value;
};
struct Module
{
int categ;
void *ptr;
};
struct Rect
{
struct TwoPoint val;
struct TwoPoint val_new;
bool is_changed;
};
struct S
{
int numInstances;
struct Module instances[20];
struct Rect RectList[40];
int numRect;
}s1;
struct Test
{
int categ;
struct Rect state;
};
struct TwoPoint initPVal(int v,int w)
{
struct TwoPoint temp;
temp.value=v;
temp.width=w;
return temp;
}
int getValue(struct TwoPoint *b)
{
return (b->value);
}
struct TwoPoint get(struct Rect *r)
{
return (r->val);
}
void initialize()
{
s1.numInstances=0;
s1.numRect=0;
}
void addRect(struct Rect *r)
{
if(s1.numRect<40)
{
s1.RectList[s1.numRect].val=r->val;
s1.RectList[s1.numRect].val_new=r->val_new;
s1.RectList[s1.numRect].is_changed=r->is_changed;
s1.numRect++;
}
}
struct Rect initRect(struct TwoPoint initval)
{
struct Rect temp;
struct TwoPoint tempP;
tempP=initPVal(0,0);
temp.val=initval;
temp.val_new=tempP;
temp.is_changed=false;
addRect(&temp);
return temp;
}
void copy(struct Rect *r)
{
if(r->is_changed)
{
r->val= r->val_new;
r->is_changed=false;
}
}
void copyRect()
{
int i=0;
for(i=0;i<s1.numRect;i++)
{
copy(&s1.RectList[i]);
}
}
void setInstance(struct Module *m)
{
s1.instances[s1.numInstances].categ=m->categ;
s1.instances[s1.numInstances].ptr=m->ptr;
s1.numInstances++;
if (s1.numInstances >= 20)
{
printf("Too many instances");
}
}
void setModule(struct Test *t)
{
struct Module m;
m.categ=t->categ;
m.ptr=&t;
setInstance(&m);
}
void init(struct Test *t)
{
t->categ=2;
struct Rect tr;
struct TwoPoint tb1=initPVal(0,5);
tr=initRect(tb1);
t->state=tr;
}
void actions(struct Test *t)
{
struct TwoPoint tb=get(&t->state);
int y=getValue(&tb);
printf("%d\n",y);
unsigned int x=getValue(&tb);
printf("%u\n",x);
switch(y)
{
....
}
}
void initS()
{
init(s1.instances[0].ptr);
}
void act()
{
actions(s1.instances[0].ptr);
}
void setup()
{
struct Test t;
initialize();
init(&t);
setModule(&t);
}
void run()
{
initS();
act();
copyRect();
}
int main()
{
printf("foo\n");
setup();
printf("bar\n");
run();
return 0;
}
There are two errors:
The init() function when called through initS() function leads to Stack Overdumped error whereas it worked fine while i called it in setup(). I think Call is correct as action() function is being executed.
The second problem is in actions() function. When i am calculating the value of y to be used as switch condition instead of the value being 0,1,2 or 3 it is some memory address which i found by printing it while trying to debug.
The problem is:
void setup()
{
struct Test t;
initialize();
init(&t);
setModule(&t);
}
A Test structure is allocated as a local stack variable and then the address of it assigned to some variable which is accessed later. The next time this variable is accessed is in (init):
void init(struct Test *t)
{
t->categ=2;
struct Rect tr;
struct TwoPoint tb1=initPVal(0,5);
tr=initRect(tb1);
t->state = tr;
}
At this point the pointer points to a variable that has fallen out of scope, resulting in undefined behaviour. What actually happens is that the stack gets smashed because of the structure assignment which is attempted. This is why it's also difficult to get a backtrace.
One solution is to allocate the memory with malloc like so:
void setup()
{
struct Test * t = malloc(sizeof (struct Test));
initialize();
init(t);
setModule(t);
}
Another problem existed, namely a semantic bug in setModule:
void setModule(struct Test *t)
{
struct Module m;
m.categ=t->categ;
m.ptr=&t;
setInstance(&m);
}
m.ptr=&t should actually be m.ptr = t. The assignment of a pointer to a Test structure was intended. Instead, what happened was that the address of a stack variable holding a pointer to a Test structure (double pointer to a Test structure) was assigned.
I'm assuming that where you show run() calling actions(), it is actually calling act(), since the former function requires a parameter.
In setModule(), you have
m.ptr=&t;
where t is already a pointer to struct Test. So what you have stored in m.ptr is a pointer to a pointer to a struct. In act(), you pass this stored pointer to actions(), which is expecting a pointer to a struct, not a pointer to a pointer to a struct. So when the function dereferences the pointer and treats the result as a struct Test, it's getting who-knows-what.
Most likely, you want to simply change the line in setModule() to
m.ptr=t;
since t is already a pointer. But perhaps there is some reason you really want to have a pointer to a pointer, in which case you need to change the code that uses the pointer to use it properly. A problem here is that the compiler can't help you ensure type safety since you're storing the pointer as void * and implicitly converting it to other types.
As a side note, you seem to be using the & operator a lot more than I think is usual. It seems to me that your functions that are read-only, e.g. getValue(), should simply take a struct parameter, not a pointer to a struct, and then you would not need to obtain the addresses of variables so much. But perhaps this is a matter of taste.