I want to get any types of variables in my code, so I did a void * type to accept others. But I can get in char * but not in int values. And I don't understand how I can did it.
Here my code :
void insertion(t_liste *liste, void *newValue) {
t_element *new = malloc(sizeof(void *));
int i;
int *j = &i;
if (liste == NULL || new == NULL) {
exit(EXIT_FAILURE);
}
if (newValue == j || (char *)newValue) {
new->value = newValue;
new->suivant = liste->premier;
liste->premier = new;
liste->taille++;
new->index = liste->taille;
}
}
In my main I did
insertion(maListe, 5);
it didn't work, but if I did this:
insertion(maListe, "test");
It works.
But I want both works !
Here my .h
typedef struct s_element t_element;
typedef struct s_liste t_liste;
struct s_element{
int index;
void *value;
t_element *suivant;
t_element *precedent;
};
struct s_liste{
t_element *premier;
t_element *dernier;
int taille;
};
Any idea ?
OK! In your function
void insertion(t_liste *liste, void *newValue)
you are taking a argument of type void* . In the first case when you send a string(char *) the base address of the string is passed , so address is taken to newValue,but in case when you pass a number,say 5 ,integer is passed to newValue where it expects an address.
Related
I am using nested structures to create a BST but I have a problem while inserting because I use a comparison function to do so!
here is my comparison function
int compare_doubles(const void* a, const void* b)
{
const double* a_ = (const double*)a;
const double* b_ = (const double*)b;
return (*a_ > *b_) - (*a_ < *b_);
}
int compare_int(const void* a, const void* b)
{
const int* a_ = (const int*)a;
const int* b_ = (const int*)b;
return (*a_ > *b_) - (*a_ < *b_);
}
and here is the structures
typedef struct tree_t BinarySearchTree; //opaque structure declared on BinarySearchTree.h
struct tree_t{
int (*comparison)(const void *, const void *);
struct tree_t* lchild;
struct tree_t* rchild;
struct t_node* noeud;
};
struct t_node{
const void *key;
const void *data;
City *city;
};
and this is my function to create a new BST
BinarySearchTree* newBST(int comparison_fn_t(const void *, const void *))
{
BinarySearchTree *t = (struct tree_t *)malloc(sizeof(struct tree_t));
t->comparison = comparison_fn_t;
t->lchild = t->rchild = NULL;
t->noeud = NULL;
return t;
}
This is my insertion function
BinarySearchTree* insertInBST(BinarySearchTree* bst, const void* key, const void* value) {
BinarySearchTree *t = bst;
if (bst->noeud == NULL)
{
struct t_node* n = (struct t_node *)malloc(sizeof(struct t_node));
t->noeud = n;
t->noeud->data = value;
t->noeud->key = key;
return t;
}
if ((bst->comparison(&key,&(bst->noeud->key))) < 0){
bst->lchild = insertInBST(bst->lchild, key, value);
}
else if ((bst->comparison(&key,&(bst->noeud->key))) >= 0){ // handle duplicate keys
bst->rchild = insertInBST(bst->rchild, key, value);
}
return bst;
}
when I try to run my code using these tests I get segfault (core dumped)
this is my main function
int main()
{
int *t =15;
int *g = 13;
int *j =15;
int *k = 13;
BinarySearchTree *root = newBST(&compare_doubles);
insertInBST(root, k,j);
insertInBST(root, t, g);
}```
Your comparison function is overly complicated (*a_ > *b_) - (*a_ < *b_) as you mix comparison (<, >) and arithmetic (-) operations. #WhozCraig suggested (a < b) ? -1 : (b < a).
You need to define struct City.
You need to #include <stdlib.h> for malloc.
In main you are casting integers to pointers. The compiler warning for the first case is:
warning: initialization of ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
As in int t = 15; int g = 13 and later insertInBST(root, &t, &g)
In main you use the wrong compare function (doubles instead of int).
I ran your code through gdb and it crashes in if (bst->noeud == 0) because insertInBST(root, t, g) invokes bst->rchild = insertInBST(bst->rchild, key, value) but bst->rchild is NULL.
In insertInBST, you only need to do the comparison once to figure out if you need the left or right branch.
I'm trying to create cluster with dynamic array objects.
Struct definitions are following:
struct obj_t {
int id;
float x;
float y;
};
struct cluster_t {
int size;
int capacity;
struct obj_t *obj;
};
Function for adding object to cluster is:
void append_cluster(struct cluster_t *c, struct obj_t obj)
{
if(c->capacity < (c->size + 1))
{
c = resize_cluster(c, c->size + 1);
}
if(c == NULL)
return;
c->obj[c->size] = obj; //at this point program crashes.
c->size++;
}
EDIT: Here is resize_cluster() function:
struct cluster_t *resize_cluster(struct cluster_t *c, int new_cap)
{
if (c->capacity >= new_cap)
return c;
size_t size = sizeof(struct obj_t) * new_cap;
void *arr = realloc(c->obj, size);
if (arr == NULL)
return NULL;
c->obj = (struct obj_t*)arr;
c->capacity = new_cap;
return c;
}
EDIT 2: Here is cluster initialization:
void init_cluster(struct cluster_t *c, int cap)
{
c = malloc(sizeof(struct cluster_t));
c->size = 0;
c->capacity = cap;
c->obj = (struct obj_t*)malloc(cap * sizeof(struct obj_t));
}
I can't figure out why program crashes when I try to add the object to the array in cluster. Is accessing array this way wrong? If so, how should I access it?
The issue is the call to init_cluster(). The c parameter is passed-by-value, so whatever you are sending remains unmodified:
struct cluster_t * c;
init_cluster(c, 1);
// c is uninitialized!
One fix would be to pass a pointer to an object:
struct cluster_t c;
init_cluster(&c, 1);
Then remove c = malloc(sizeof(struct cluster_t)); from init_cluster();
Or, you could create an alloc_cluster function:
struct cluster_t * alloc_cluster(int cap)
{
c = malloc(sizeof(struct cluster_t));
c->size = 0;
c->capacity = cap;
c->obj = malloc(cap * sizeof(struct obj_t));
return c;
}
And call it like:
struct cluster_t *c = init_cluster(1);
typedef char Last_t[MAXL];
typedef char Rest_t[MAXR];
typedef struct NodeTag {
Last_t Last;
Rest_t Rest;
struct NodeTag *Link;
} Node;
typedef struct {
Node *Index[26];
Node *L;
} ContactList;
// parameter to take in a char argument to set it to contact.Last
void INS( Node *cn )
Node contactName;
contactName.Last= cn;
// temp->data=num;
//contactName.Rest=restName;
}
//cant figure out how to pass a char argument
int main(void)
{
INS("David");
}
void INS should be passing an argument of type char *, not Node, if you want the code in your main to work.
To assign it to the member Last, you would have to use strcpy or something similar. This is because you can't assign a pointer to an array. More specifically, you can't assign a char * to char[MAXL].
You could try this:
void INS( char * cn ) {
Node contactName;
strncpy (contactName.Last, cn, MAXL);
}
int main(void){
INS("David");
return 0;
}
But, this doesn't handle errors very well. Here's a way of doing it that's more error-safe:
void INS (char * cn){
Node contactName = {
.Last[0] = 0,
.Rest[0] = 0,
.Link = 0
};
if (cn){
strncpy (contactName.Last, cn, MAXL - 1);
contactName.Last[MAXL - 1] = 0;
}
}
int main (void){
INS ("David");
return 0;
}
I'm new to C. I'm trying to pass a struct list to a function and within that function fill the list. Code is as follows:
#include <stdio.h>
#include <stdlib.h>
struct Abc {
int test;
struct Abc *next;
};
void demo_fill(struct Abc *data);
int main(int argc, char **argv) {
struct Abc *db = NULL;
demo_fill(db);
printf("%d\n",db->test);
return 0;
}
void demo_fill(struct Abc *data) {
int i;
for( i = 0; i < 5; i++ ) {
struct Abc *new;
new = malloc(sizeof(struct Abc));
new->test = i;
new->next = data;
data = new;
}
}
When running this a 'Segmentation fault (core dumped)' error occurs because the struct is still NULL when I try to print the first element. What am I doing wrong?
You're passing the pointer by value. You need to pass a pointer to a pointer if you want the change the value of the caller's pointer:
int main(int argc, char **argv) {
struct Abc *db = NULL;
demo_fill(&db);
printf("%d\n",db->test);
return 0;
}
void demo_fill(struct Abc **data) {
int i;
for( i = 0; i < 5; i++ ) {
struct Abc *new;
new = malloc(sizeof(struct Abc));
new->test = i;
new->next = *data;
*data = new;
}
}
Assigning data to new will have no effect. data is a local copy of the pointer. Pass a double pointer to fix that. Something like this:
void demo_fill(struct Abc** data) {
int i;
for( i = 0; i < 5; i++ ) {
struct Abc *new;
new = malloc(sizeof(struct Abc));
new->test = i;
new->next = *data;
*data = new;
}
}
And of course you will have to pas the pointer to db in main:
demo_fill(&db)
You can pass a pointer to the pointer as the other two answers say, so i just point out an alternative you might also consider: Instead of using a single struct you could use one struct for the list and another for entry-links:
struct link {
int test;
struct link* next;
};
struct list {
struct link* first;
};
void demo_fill(struct list* data);
You can then modify the first entry of the list without thinking about ** syntax.
Hello i am trying to return a struct from a function but i cant find a way to do so without declaring the struct as global. How can this be done? Here is the code (THIS WORKS AS IT IS)
...
void log_in();
struct node
{
char name_log[20];
int passlog;
int user_point;
}tmp;
int main()
{
...
else if(sel=='2')
{
log_in();
if (tmp.passlog==TRUE)
logged_in(tmp.name_log,tmp.user_point); //and here i want to use the retun values
}
void log_in()
{
... //make the changes in the struct
}
...
What i want to achieve is to place the struct node declaration within main but sadly it wont work. So here is what i am trying to do: (THIS DOESN'T WORK)
...
struct node log_in();
int main() {
...
else if(sel=='2') {
struct node //here is where i want to declare
{
char name_log[20];
int passlog;
int user_point;
}tmp;
log_in();
if (tmp.passlog==TRUE)
logged_in(tmp.name_log,tmp.user_point); //and here i want to use the retun values
}
struct node log_in()
{
...
return tmp;
}
...
else if(sel=='2') //or within this block but I don't know how.
{ struct node tmp;
tmp=log_in();
if (tmp.passlog==TRUE)
logged_in(tmp.name_log,tmp.user_point); //and here I want to use the return values
}
and inside the function log_in()
struct node log_in()
{
struct tmp
...
return tmp;
}
use a local variable inside the function and return this variable. Assign it to another variable inside main().
Declare the structure first, then create the variable temp. Like this:
struct node
{
char name_log[20];
int passlog;
int user_point;
};
Then you can create the local variable like
struct node tmp;
Pass a pointer to the struct node to your log_in function and have it return a boolean value so the caller can check whether logging in succeeded or didn't. (Note I'm trying to guess what you want to achieve, and I might be guessing wrong.)
#include <stdio.h>
#include <string.h>
struct node {
char name_log[20];
int passlog;
int user_point;
};
int log_in(char, struct node *);
int log_in(char sel, struct node * tmp) {
int ret = 0;
if (sel == '2') {
ret = 1;
strcpy( tmp->name_log, "Gonzo" );
tmp->passlog = 33;
tmp->user_point = 99;
}
return ret;
}
int main(int argc, char ** argv) {
struct node tmp;
char sel = argv[1][0];
if ( log_in(sel, &tmp) ) {
// tmp initialized
printf( "%s, %d, %d\n", tmp.name_log, tmp.passlog, tmp.user_point );
}
else {
// tmp not initialized
}
}
Call passing 2 on the command line. (If you don't, undefined behaviour.)
If you want to use some struct in 2 different routines - you must declare it outside of both of them since they both have to see how this struct is structured.
BTW - you invoke log_in but do not use its return value.
You can't operate on a type that is unknown. If log_in() doesn't know the definition of struct node, it can't use it directly. The only thing it can do is somehow receive a pointer to a variable of this type and then either treat it as raw data (sequence of bytes) or cast said pointer to a pointer to a known to log_in() type and work with that.
You can also redefine struct node inside of log_in(), which is a way of making log_in() operate on a known type:
void log_in(void*);
void logged_in(char*, int);
int main(void)
{
int sel = '2';
if (sel == '2')
{
struct node
{
char name_log[20];
int passlog;
int user_point;
} tmp;
log_in(&tmp);
if (tmp.passlog)
logged_in(tmp.name_log, tmp.user_point);
}
return 0;
}
void log_in(void* n)
{
struct node
{
char name_log[20];
int passlog;
int user_point;
} *p = n;
p->passlog = 1;
}
void logged_in(char* name, int point)
{
}
If you don't want to pass tmp by a formal reference into log_in(), you must make it available globally. For example like this:
void log_in(void);
void logged_in(char*, int);
void* pTmp;
int main(void)
{
int sel = '2';
if (sel == '2')
{
struct node
{
char name_log[20];
int passlog;
int user_point;
} tmp;
pTmp = &tmp;
log_in();
if (tmp.passlog)
logged_in(tmp.name_log, tmp.user_point);
}
return 0;
}
void log_in(void)
{
struct node
{
char name_log[20];
int passlog;
int user_point;
} *p = pTmp;
p->passlog = 1;
}
void logged_in(char* name, int point)
{
}