Pass an array of pointers to function argument - c

I am trying to construct a bus network using adjacent linked list graph data structure.
A simplified code is shown below:
typedef struct BusNetwork
{
struct AdjStopList *stopsArray; //defing the array of pointers
} BusNetwork;
typedef struct Node
{
int stopID;
struct Node *next;
} Node;
typedef struct AdjStopList
{
char stopName[20];
int numOfAdjStp;
struct Node *first;
} AdjStopList;
void insertStopAtLast(AdjStopList *L, int stopID)
{
//add stopID to the last node of the list
return;
}
void addBusRoute(AdjStopList *L[], int from, int to)
{
if (from == to)
return;
insertStopAtLast(L[from], to);
return;
}
void main(BusNetwork *BN, int from, int to)
{
addBusRoute(BN->stopsArray, from, to);
}
The problem is with addBusRoute(BN->stopsArray, from, to); It seems I didn't pass the same type of value as function argument. But my understanding of BN->stopsArray is an array of pointers, which should be the same as AdjStopList L[]. What went wrong?

The argument AdjStopList *L[] has the same meaning as AdjStopList **L.
On the other hand, what is passed BN->stopsArray is struct AdjStopList *.
The argument is a pointer to a pointer to AdjStopList, but what is passed is a pointer to AdjStopList.
Therefore, the type differs.

Related

Why I need to add '&' when calling the function

typedef struct sTree {
int key;
struct sTree* p;
struct sTree* left;
struct sTree* right;
} sTree;
typedef sTree* tree;
void treeInsert(tree* root);
int main(){
srand((unsigned)time(NULL));
tree *root = NULL;
treeInsert(&root);
return 0;
}
void treeInsert(tree* root){
......
}
I don't understand why I have to pass '&' when calling tree insert (&root instead of root).
I've created a struct representing a node of binary tree and I declared a pointer to the root of the tree as 'tree*'.
So 'root' is double pointer. The function 'treeInsert' expects a double pointer. If I pass simply 'root' it takes the value (NULL) else with the operator '&' it points correctly to the root. The problem is:
passing '&root' I'm not passing a triple pointer? Can someone explain why?
regarding:
treeInsert(&root);
the need for the & is because the function: treeInsert() will need to modify the contents of the pointer. Without the & any assignment to that passed parameter will only change the parameter on the call stack and not the the contents of the parameter in main()
regarding:
tree *root = NULL;
Since tree is already a pointer, this results in (effectively)
tree ** root = NULL;
which will not accomplish what is needed.
A prime example of why a pointer should NOT be hidden in a typedef statement
the following proposed code is clear about what is wanted:
struct sTree
{
int key;
struct sTree* p;
struct sTree* left;
struct sTree* right;
};
typedef struct sTree tree;
void treeInsert(tree** root);
int main( void )
{
srand((unsigned)time(NULL));
tree *root = NULL;
treeInsert(&root);
return 0;
}
void treeInsert(tree** root)
{
tree *localroot = *root; // now 'localroot' is a pointer to the variable `root` in function: `main()`
......
}

Random Queue in C

I've written this code with all correct understandings i have. please check my problems.
#include<stdio.h>
#include<stdlib.h>
// Define a structure for the dequeue elements
This structure is all good, with data, next, previous pointers.
typedef struct RanElmt_ {
void *data;
struct DeqElmt_ *prev;
struct DeqElmt_ *next;
void (*destroy)(void *data);
//Your Code here
} RanElmt;
THis is ok too, acording to what i think is correct.
typedef struct RandQ_{
int size;
struct RanElmt *head;
struct RanElmt *tail;
}RandQ;
RandQ * RandomizedQueue(void (*destroy)(void *data)){
RandQ *relmt = (RandQ*)malloc(sizeof(RandQ));
} // construct an empty randomized queue
int isREmpty(RandQ *rQ){
if ( rQ->size == 0)
return 1;
return 0;
} // is the queue empty?
int rsize(RandQ *rQ){
return rQ->size;
}
// return the number of items on the queue
ACtually this is only one function,(enqueue) I'm going to get the idea and code other functions(dequeue, sample etc..)
int enqueue(RandQ *rQ, const void *data){
RanElmt *relmt = (RanElmt*)malloc(sizeof(RanElmt));
relmt->data = (void*)data;
if (rQ->head == NULL){
relmt = rQ->head;
relmt = rQ->tail;
relmt->prev = NULL;
relmt->next = NULL;
}
else{
rQ->head = relmt;
}
(rQ->head)->prev = relmt;
relmt->prev = rQ->head;
rQ->head = relmt;
} // add the item
main(){
Deque(free);
printf(" okk \n");
}
THis program is giving these errors:
Errors i'm getting
In C struct tags and type names live in different name spaces. That is struct RanElmt and RanElmt are two different types, in addition struct RanElmt is not completely defined.
Your RandQ should be defined something like
typedef struct RandQ_{
int size;
struct RanElmt_ *head; // or RanElmt* head;
struct RanElmt_ *tail; // or RanElmt* tail;
}RandQ;
in addition your RanElmt is probably not what you want, maybe you meant:
typedef struct RanElmt_ {
void *data;
struct RanElmt_ *prev; // pointer to a struct of the same type
struct RanElmt_ *next; // pointer to a struct of the same type
void (*destroy)(void *data);
// You cannot put code here in C (or even a function definition AFAIK).
} RanElmt;
You have confused the struct tag and the typedeffed alias for the queue elements in the definition of the queue:
typedef struct RandQ_{
int size;
struct RanElmt *head;
struct RanElmt *tail;
} RandQ;
Here, the head and tail are of the type struct RanElmt. This struct doesn't exist in your program. You have a struct RanElmt_ (with trailing underscore) that you can also call ´RanElmtwithout thestructkeyword, because you have combined the struct definition with atypedef`.
The compiler still generates the code, because pointers to unknown structs are okay, unless you try to get at their data. Obviously the compiler can't access the struct fields if it doesn't know them.
There's no need for the underscore. The names of structs are in a separate namespace, so you can have both a struct called RandQ and a type (in global namespace) called RanQ. I recommend to use the same name for struct tag and aliassed type.
You can also get rid of the need to use the struct keyword inside the struct defnition if you separate the typedef from the struct definition:
typedef struct RanElmt RanElmt; // use just RanElmt from now on
struct RanElmt {
void *data;
RanElmt *prev;
RanElmt *next;
} RanElmt;
Your code has several other problems, but I think he program is in an early state, so I don't address them here.

Value of struct member changes after printing C

I got this code and a strange behaviour while printing the id member variable of node.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
int id;
int visited;
// struct node *neighbors_[];
};
struct graph
{
struct node nodes[26];
int adjMat[26][26];
};
struct stack_item
{
struct node node;
struct stack_item *next_;
};
struct myStack
{
struct stack_item *anfang_;
};
void initGraph(struct graph *graph_);
void push(struct myStack *stack_, struct node node);
int main()
{
struct graph graph;
struct myStack stack;
char ausgabe[26]="";
initGraph(&graph);
//READ DATA
char line[200];
int firstTime=1,first;
first=0;
push(&stack,graph.nodes[first]);
printf("ID %i\n",stack.anfang_->node.id);
printf("ID %i\n",stack.anfang_->node.id);
//FINISHED DATA READING
//CALL DFS
//dfs(graph,stack,ausgabe);
}
void push(struct myStack *stack_, struct node node)
{
struct stack_item item;
item.node=node;
item.next_=stack_->anfang_;
stack_->anfang_=&item;
}
void initGraph(struct graph *graph_)
{
int i,j;
for(i=0; i<26; i++)
{
struct node node= {i,0};
graph_->nodes[i]=node;
for(j=0; j<26; j++)
{
graph_->adjMat[i][j]=0;
}
}
}
If i execute this, the first print command leads to 'ID 0',the second to 'ID 1980796117'. How can this value change by printing it? Could please anyone help me, i've got really no idea!
void push(struct myStack *stack_, struct node node)
{
struct stack_item item;
item.node=node;
item.next_=stack_->anfang_;
/* BAD! */
stack_->anfang_=&item;
}
item is a local variable which, when the push function returns, goes out of scope. Any existing pointers which refer to this object are now invalid, and dereferencing it results in undefined behavior.
You will need to dynamically allocate item (i.e., malloc) if you need it to persist once the function has returned.

access element of struct passed into a void* pointer

I'm working with a binary search tree data structure to sort a series of structs with the type definitions:
typedef struct {
char c;
int index;
} data_t;
typedef struct node node_t;
typedef node {
void *data;
node_t *left;
node_t *right;
}
The node_t typedef is from a library provided to me for this purpose, presumably with a void* pointer to ensure polymorphism. node will be passed into the function:
static void
*recursive_search_tree(node_t *root,
void *key, int cmp(void*,void*))
Within the recursive_search_tree function, I want to be able to modify the code to use the index element as a condition to find the match closest to the index of the linear pass over an array of characters, which would ultimately involve a data_t being passed into *key and key->index being accessed within the function.
The Question
Is it possible to access key->index where key is a void* pointing to a data_t struct, or would this only be possible if data_t was declared as the type for key? I have tried to do the latter, however even casting the pointer to an int doesn't seem to pass the compiler.
Sure it's possible, you'd cast key as type *data_t. (As long as that's really what key points to!)
key /* argument of type void* */
(data_t*)key /* cast as type data_t* */
((data_t*)key)->index /* dereferenced */
Here is a simple example:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
char c;
int index;
} data_t;
typedef struct node {
void *data;
struct node *left;
struct node *right;
} node_t;
static int cmp(void *lhs, void *rhs)
{
return ((data_t *)lhs)->index - ((data_t *)rhs)->index;
}
int main(void)
{
data_t d0;
data_t d1;
d0.c = 'A';
d0.index = 1;
d1.c = 'B';
d1.index = 2;
printf("d0 < d1? %s\n", (cmp((void *)&d0, (void *)&d1) < 0 ? "yes" : "no"));
printf("d1 < d0? %s\n", (cmp((void *)&d1, (void *)&d0) < 0 ? "yes" : "no"));
return EXIT_SUCCESS;
}
This is type unsafe, as is any use of void. The use of void is generally because the intermediate is holding onto something it doesn't use for someone else's convenience.
This is a C function to let you hold whatever you want in a tree.
All it does is return whatever pointer you give it.
In your search function
int cmp(void* dt1, void* dt2)
{
data_t* data1 = (data_t*)dt1;
data_t* data2 = (data_t*)dt2;
/* Do what you need with data1 and data2 here */
}
Should let you do whatever you need. The problem you have is you need to cast your values inside the function. The parameters to cmp should exactly match the API for the library you are using, which says void* for the parameters.

Store address dynamic array in c

I'm trying to save the address of a dynamic array index. The last line of this function is what gives the pointer error.
static struct sstor *dlist
struct node *ins_llist(char *data, struct llist *l) {
struct node *p, *q;
q = malloc((size_t)sizeof(struct node));
if(q == NULL)
return(NULL);
if(ins_list(data, &dlist))
return NULL;
q->item = &(dlist->item[(dlist->sz)-1]); // Problem?
...}
Allocation of dlist
struct llist *init_llist(void) {
struct llist *l;
dlist = init_list(INITSZ);
if(dlist == NULL)
return(NULL);
This is my node
struct node {
char **item;
struct node *next;
struct node *prev;
};
This is my array
struct sstor {
int sz;
int maxsz;
char item[][1024];
};
I'm still new to pointers. The line below gives the error: assignment from incompatible pointer type
q->item = &(dlist->item[(dlist->sz)-1]);
Presuming that you allocate an actual struct node for q to point to...
The "incompatible pointer types" error arises because q->item has type char ** (a pointer to a pointer to char), and &(dlist->item[...]) has type char (*)[1024] (a pointer to an array of 1024 char). These types simply aren't compatible (there is no actual "pointer to char" object for q->item to point to).
You can fix the problem in two ways. The first is by changing the declaration of struct node to this:
struct node {
char (*item)[1024];
struct node *next;
struct node *prev;
};
The second is by changing both the declaration of struct node to this:
struct node {
char *item;
struct node *next;
struct node *prev;
};
..and changing the assignment statement to this:
q->item = dlist->item[(dlist->sz)-1]; // No Problem!
(The first alternative makes q->item point to the entire array, and the second makes it point to the first char in the array. The perspecacious will note that these are pointers to the same location, but with different types. Usually, the second form is what you want).
char** is not the same as char[][1024]
Try to fix the sstor structure like this:
struct sstor {
int sz;
int maxsz;
char *item[1024];
};

Resources