void Pointer to a structure causes error 'dereferencing 'void *' pointer' - c

I try to initialize a queueADT pointer called initAmigo. Apparently I never create one if the structure is not making the pointers for the (void *data)
Reasons why I can't put any data in void *data in node structure:
Asuumption 1: Take away void *data and say User_struct (from .h file)
Assumption 2: RegisteredData is not supposed to be a pointer because the parameter in que_Insert asks for a pointer)
Assumption 3: In AddUser function, que_insert( initAmigo , registeredData); The registeredData to be inserted in the void *data node was actually a pointer to a pointer to a structure
Having a queue reference a void * creates the following error:
amigonet.c: In function 'findUser':
amigonet.c:247:21: warning: dereferencing 'void *' pointer [enabled by default]
if (currNode->data->name == name) { //If front is the name being searched
^
amigonet.c:247:21: error: request for member 'name' in something not a structure or union
amigonet.c:253:22: warning: dereferencing 'void *' pointer [enabled by default]
if (currNode->data->name == name ) {
.c file just has to create a structure of a queue of Users (QueueADT initAmigo)
typedef struct node {
//name of data userStruct (just for referencing)
void* data;
struct node *next;
}node;
struct queueStruct {
struct node *front; /* pointer to front of queue */
struct node *rear; /* pointer to rear of queue */
int (*cmprFunc)(const void*a,const void*b); /* The compare function used for insert */
};
typedef struct queueStruct *QueueADT; //typedef inserted for pointers,
//name is QueueADT
#define _QUEUE_IMPL_
#include "queueADT.h"
/// create a queue that is either sorted by cmp or FIFO
//function with two void
QueueADT que_create( int (*cmp)(const void*a,const void*b) ) {
QueueADT new;
new = (QueueADT)malloc(sizeof(struct queueStruct)); //NOTE: NO POINTERS HERE
//use pointers in Single lines
if (cmp == NULL) {
new->front = NULL;
new->rear = NULL;
new->cmprFunc = NULL;
} else {
new->cmprFunc = cmp;
new->front = NULL;
new->rear = NULL;
}
return ( new );
}
//free the queue once the nodes have been cleared from the queue
void que_destroy( QueueADT queue ) {
if ( queue->front == NULL ) {
free(queue);
} else {
que_clear(queue);
free(queue);
}
}
//passes a real pointer for dynamic allocation
//set a temp to the front to be deleted, then front becomes the next and delete the temp
void que_clear( QueueADT queue ) {
while (queue->front->next != NULL) {
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
temp = queue->front;
queue->front= queue->front->next;
free(temp);
}
}
//if the cmpr function returns a positive then put in in before the b node in cmp(curr, temp)
void que_insert( QueueADT queue, void *data ) {
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->data= data;
temp->next = NULL;
node *currNode; //simply a pointer
currNode = queue->front;
if ( queue->front != NULL ) { //+1 or more in Q
if ( queue->cmprFunc == NULL ) { //if the cmp_func is FIFO
queue->rear->next = temp;
queue->rear= temp;
queue->rear->next=NULL;
if ( queue->front == queue->rear ) {
currNode->next = temp;
queue->rear = temp;
temp->next= NULL;
}
} else {
while ( currNode->next != NULL ){ //2 or more
if (( (*(queue->cmprFunc))(currNode->data, temp->data) >= 0
&& ( currNode == queue->front)) ) {
temp->next = currNode;
queue->front=temp;
break;
}
if (( (*(queue->cmprFunc))(currNode->next->data, temp->data) >= 0 ) ) {
temp->next = currNode->next;
currNode->next = temp;
break;
} else {
currNode = currNode->next; //move past front and possibly rear
if (currNode->next == NULL ) { //currNode is rear of queue
currNode->next = temp;
queue->rear = temp;
temp->next = NULL;
break;
}
//exit_failure
}
}
if ( queue->front == queue->rear ) { //exactly 1 node in queue
if (( (*(queue->cmprFunc))(currNode->data, temp->data) >= 0 ) ) {
temp->next = queue->front;
queue->front = temp;
} else {
queue->front->next = temp;
queue->rear = temp;
}
}
}
} else {
queue->front = temp;
queue->rear= queue->front;
queue->front->next= queue->rear->next = NULL;
}
}
//removes the front
void *que_remove( QueueADT queue ) {
if ( queue->front != NULL ) { //if the size of queue is greater than 1
node *currNode; // dont make new node, pointer
currNode = queue->front;
void *data = currNode->data;
if ( queue->front == queue->rear ) { //if size of queue is 1
free(currNode);
queue->front = queue->rear = NULL; //set both to NULL
} else {
queue->front= currNode->next;
free(currNode);
}
return data;
}
return NULL;
}
bool que_empty( QueueADT queue ) {
if ( queue->front == NULL ) {
return true;
} else {
return false;
}
}
QueueADT initAmigo;
//struct queueStruct *initAmigo
//QueueADT initAmigo;
//make a Queue with front and rear
//compare function with A-Z
struct Friends_struct {
struct queueStruct *amigos_Queue;
};
void create_amigonet() {
//makes the same thing as que_Create
//(Friends)malloc(sizeof(struct Friend_struct));
initAmigo = que_create(NULL);
printf("%lu Founded size of an.c\n\n\n\n\n\n\n\n\n\n\n", sizeof(initAmigo));
}
//The add user will find a new user and make the name of the user to a amigonet
//add Usernode to queue initAmigo
//make sure set to first and display queue
void addUser( const char *name ) {
//create Usernode and void *data (user w/ friends)
//check to see if User already exists
if ( findUser(name) != NULL) {
return;
}
//create data for node, by initializing memorry for a userStruct
struct User_struct *registeredData;
registeredData = ( struct User_struct* )malloc(sizeof(struct User_struct)); //first user Data
registeredData->name = name;
//create a Friends
//put this in file create F
struct Friends_struct *initAmigos;
initAmigos = (struct Friends_struct*)malloc(sizeof(struct Friends_struct)); //NOTE: NO POINTERS HERE
//set Friends list to Null
initAmigos->amigos_Queue = que_create( NULL );
//put User with empty Friends struct
registeredData->amigos = initAmigos;
//void que_insert( QueueADT queue, void *data )
que_insert( initAmigo , registeredData);
printf("%s User was inerted \n", name);
}
//Find a user in the init Amgio
//start at front as temp, go to next until name found
User *findUser( const char *name ) {
struct node *currNode;
currNode = initAmigo->front;
printf("%lu Founded size of an.c\n\n\n\n\n\n\n\n\n\n\n", sizeof(initAmigo));
if ( initAmigo->front == NULL ) {
return NULL;
} else {
if (currNode->data->name == name) { //If front is the name being searched
return currNode->data;
}
//Loop after front
while ( currNode->next != NULL ) {
currNode = currNode->next;
if (currNode->data->name == name ) {
return currNode->data;
}
}
node *rear = currNode;
if (rear->data->name == name ) {
return rear->data;
}
}
//User Not Founded
return;
}
#if 0
void addAmigo( User *user, User *amigo ) {
//check to see if node exits within friends
//go to use friends list
//traverse the node, check data for amigo->name == data->name
if ( user->amigos->amigos_Queue->front != NULL ) {
node *currNode = user->amigos->amigos_Queue->front;
if ( currNode->data->name == amigo->name ) {
return ;
} else {
//loop to determine if User friend queue front to rear has amigo already
while ( currNode->next != NULL ) {
currNode = currNode->next;
if (currNode ->data->name == amigo->name) {
return;
}
}
}
}
que_insert( user->amigos->amigos_Queue, amigo);
}
void removeAmigo( User *user, User *ex_amigo) {
//Pre Condition: Amgio exists in user
//go to user
//set user as currNode
//either create a function in queueADT remove
// use a prev and curr and next and traverse, remove, connect
//preconditions: front is not examigo
// rear is not examigo
// amigo is friend of user
}
size_t separation( const User *user1, const User *user2 ) {
return;
//queue a DFS
// queue a BFS
//
}
//search using a queue BFS
//search using a DFS
//number of users and their names
void dump_data() {
if (initAmigo->front != NULL) {
node *currNode = initAmigo->front;
printf("%s: Amigos!\n", currNode->data->name); //prints the name of the first node
while ( currNode->next != NULL ) {
currNode = currNode->next;
printf("%s: Amigos!\n", currNode->data->name);
}
//while loop of each user set to currNodw
//set a variable for currNodeAmigo and print the names of them inside ^^^
}
}
void destroy_amigonet(){
//clear Friend Queue and destroy for each User Friend
//destroy initAmigo queue
}

The problem looks like this:
typedef struct node {
void* data;
struct node *next;
}node;
...
struct node *currNode;
if (currNode->data->name == name) { //If front is the name being searched
return currNode->data;
}
The type of currNode->data is void *. This is an incomplete type, which means that it cannot be dereferenced. The compiler has no idea what to make of whatever it points at. You need to convert the void pointer, into a pointer to a meaningful type.
You have not defined the User type in the code you posted, but I'm guessing that you want something like this:
User *user = currNode->data;
if (user->name == name) {
return user;
}
You will also have to make similar changes elsewhere in the same function.

Related

Queue implementing by linked list in c

I am implementing queue with a linked list but I am facing problem in the insertion() function. I am able to insert only one data, whenever I insert another data then again previous data insert whatever did I insert at first time.
#include <stdio.h>
#include <stdlib.h>
struct Queue
{
int data;
struct Queue *next;
};
struct Queue *rear = NULL;
struct Queue *front = NULL;
void insertion(int data)
{
struct Queue *n;
n = (struct Queue *)malloc(sizeof(struct Queue));
n->data = data;
n->next = NULL;
if (rear == NULL)
{
front = n;
rear = n;
}
else
{
rear->next = n;
rear = n;
}
}
void deletion()
{
if (front == NULL)
printf("\n Underflow");
else if (front == rear)
{
front = NULL;
rear = NULL;
}
else
front = front->next;
}
void viewList()
{
struct Queue *t = front;
if (t == NULL)
printf("\n there is no item for view...............");
else
{
while (t != NULL)
{
printf(" %d", front->data);
t = t->next;
}
}
}
int main()
{
struct Queue *q = NULL;
insertion(5);
insertion(10);
// deletion();
viewList();
printf("\n");
viewList();
return 0;
}
The function deletion produces a memory leak because it does not free the memory of the deleted node. The function can look at least like
void deletion() {
if(front == NULL)
printf("\n Underflow");
else
{
stuct Queue *n = front;
front = front->next;
if ( front == NULL ) rear = NULL;
free( n );
}
}
Within the function viewList you are always outputting the value stored in the node pointed to by the pointer front
printf(" %d", front->data);
You have to write
printf(" %d", t->data);
This declaration in main
struct Queue *q = NULL;
is redundant and does not make a sense.
Pay attention to that it is a bad idea when functions depend on global variables. You could define the queue the following way
struct Node
{
int data;
struct Node *next;
};
struct Queue
{
struct Node *front;
struct Node *rear;
};
And in main you could define an object of the queue the following way
struct Queue queue = { .front = NULL, .rear = NULL };
And the functions should be rewritten such a way that they would accept a pointer to the queue. For example
int insertion( struct Queue *queue, int data );
The function can be defined like
int insertion( struct Queue *queue, int data )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( queue->front == NULL )
{
queue->front = new_node;
}
else
{
queue->rear->next = new_node;
}
queue->rear = new_node;
}
return success;
}
And the function will be called like
int main( void )
{
struct Queue queue = { .front = NULL, .rear = NULL };
insertion( &queue, 5 );
insertion( &queue, 10 );
//...
you can check the returned value of the function to determine whether the insertion was successful as for example.
if ( !insertion( &queue, 5 ) ) puts( "Error. Not enough memory." );
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Queue
{
struct Node *front;
struct Node *rear;
};
int insertion( struct Queue *queue, int data )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( queue->front == NULL )
{
queue->front = new_node;
}
else
{
queue->rear->next = new_node;
}
queue->rear = new_node;
}
return success;
}
int empty( const struct Queue *queue )
{
return queue->front == NULL;
}
void viewList( const struct Queue *queue )
{
if ( empty( queue ) )
{
printf("\n there is no item for view...............");
}
else
{
for ( struct Node *current = queue->front; current != NULL; current = current->next )
{
printf( " %d", current->data );
}
}
}
int main(void)
{
struct Queue queue = { .front = NULL, .rear = NULL };
insertion( &queue, 5 );
insertion( &queue, 10 );
viewList( &queue );
return 0;
}
The program output is
5 10

Infinite loop when trying to add to the beginning of a linked list in C

I'm trying to practice Linked Lists in C and I created a simple LL with an add function that takes a position index and inserts the data at that position.
I keep getting an infinite loop when trying to add to the beginning of my list using the add_beg, which just calls the add_at function with position 0 (add(0, data)) function. I can't seem to find the reason why this is happening. I need another set of eyes. Here is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int _data;
struct node_t *_next;
} node_t;
node_t *_head = NULL;
void add_at(int pos, int data) {
node_t *node = malloc(1 * sizeof(node_t));
node->_data = data;
node->_next = NULL;
// insert if empty
if (_head == NULL) {
_head = node;
}
else {
int index = 0;
node_t *prev = NULL;
node_t *curr = _head;
while (curr != NULL && index != pos) {
prev = curr;
curr = curr->_next;
index++;
}
// insert beginning
if (index == 0) {
_head = node;
node->_next = _head;
}
// insert end
else if (index != 0 && curr == NULL) {
prev->_next = node;
}
// insert middle
else {
prev->_next = node;
node->_next = curr;
}
}
}
void add_beg(int data) {
add_at(0, data);
}
void add_end(int data) {
add_at(-1, data);
}
void dump() {
if (_head != NULL) {
node_t *curr = _head;
while (curr != NULL) {
if (curr->_next != NULL) {
printf("%d -> ", curr->_data);
}
else {
printf("%d", curr->_data);
}
curr = curr->_next;
}
printf("\n");
}
else {
printf("The list is empty\n");
}
}
int main() {
add_beg(6);
add_at(1, 1);
add_at(2, 3);
add_at(3, 9);
add_at(4, 8);
add_at(5, 5);
add_at(7, 2);
add_at(8, 4);
add_beg(9); // commenting this out prevents the infinite loop
dump();
return 0;
}
The error is in this section:
if (index == 0) {
_head = node;
node->_next = _head;
}
That second command sets node->_next to head. However, the line before set _head to node. Therefore, you just set node->_next to node, creating the infinite loop.
You need to reverse the order of those two statements.
if (index == 0) {
_head = node;
node->_next = _head;
}
here you set _head as node but after next node at _head then when your doing while loop you had already broke your linked list.
Fix :
first set the _head as node->_next then set _head as node

Deleting a specific node from singly linked list in C

I have made a singly linked list in C and I am trying to code a function which deletes a specific element from the list based on the integer value provided which corresponds to a particular node.
void deleteNodeVar(int val)
{
struct node *t, *temp, *temp2;
t = START;
while(t -> info != val)
{
if(t -> ptr == NULL) { break; }
t = t -> ptr;
}
printf("\nfound the val to be %d\n",t -> info);
temp = t -> ptr;
t -> ptr = temp -> ptr;
printf("now will free the node with value %d \n",t -> info);
free(t);
}
After some debugging I found: The function is working properly as it detects and deletes the node successfully
but printing the entire list gives weird results.
full code:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int info;
struct node *ptr;
};
struct node *START = NULL;
struct node* createNode()
{
struct node *p;
p = (struct node*) malloc(sizeof(struct node));
return p;
}
//inserting node
void insertNode(int val)
{
struct node *temp, *t;
temp = createNode();
temp -> info = val;
temp -> ptr = NULL;
if(START == NULL){ START = temp; }
else
{
t = START;
while(t -> ptr != NULL)
{
t = t -> ptr;
}
t -> ptr = temp;
}
}
void pop()
{
struct node *t;
t = START;
if(START == NULL) { printf("THE LIST IS EMPTY\n"); }
else
{
START = START -> ptr;
free(t);
}
}
//here are the 2 functions below in which I have problem
void deleteNodeVar(int val)
{
struct node *t, *temp, *temp2;
t = START;
while(t -> info != val)
{
if(t -> ptr == NULL) { break; }
t = t -> ptr;
}
printf("\nfound the val to be %d\n",t -> info);
temp = t -> ptr;
t -> ptr = temp -> ptr;
printf("now will free the val with value %d \n",t -> info);
free(t);
}
void viewList()
{
struct node *t, *temp;
t = START;
while(t != NULL)
{
printf("%d -> ",t->info);
t = t -> ptr;
}
}
int main()
{
insertNode(10);
insertNode(20);
insertNode(40);
insertNode(100);
viewList();
int v;
printf("\nEnter to delete: ");
scanf("%d",&v);
deleteNodeVar(v);
viewList();
}
Here is the screenshot of the output I am getting after trying to print the list after deleting node with value 40:
It is running into an infinite loop with these repeating values !
For starters it is a bad idea to use a global variable as a pointer to the heda node of the list and when functions depend on a global variable. In this case you are unable to create more than one list.
Nevertheless the function deleteNodeVar can be defined the following way
int deleteNodeVar(int val)
{
node *prev = NULL, *current = START;
while ( current != NULL && current->info != val )
{
prev = current;
current = current->ptr;
}
int success = current != NULL;
if ( success )
{
if ( prev == NULL )
{
START = START->ptr;
}
else
{
prev->ptr = current->ptr;
}
free( current );
}
return success;
}
According to your delete function if the node is not present in the list which you want to delete but even after your delete function will give a message that
found the val to be
which is totally wrong ....
so you can write your delete function like this
void deleteNodeVar(int val)
{
node *p ='\0', *n = START;
int flag=0;
while ( n != '\0' && n->info != val )
{
p =n;
n =n->ptr;
}
if(n!='\0')
flag=1;
if ( flag )
{
if ( p == '\0' )
{
START = START->ptr;
}
else
{
p->ptr = n->ptr;
}
printf("\nfound the val to be %d\n",n-> info);
free( n );
}
else
printf("The node is not present list\n");
}

Pointer in function to linked list not updating element in 1 case

I am using a struct like this
struct infoM {
char* direction;
int key;
};
typedef struct nodeM{
struct infoM nodeInfo;
struct nodeM *next;
struct nodeM *prev;
} node;
typedef node list;
I have one function that returns the wanted node by a specific field
node * search(list *l, char* direction) {}
And this is my function to remove elements from the list
int delete(list *l, char* direction) {
node *tmp = search(l, direction);
if (tmp != NULL) {
node *ant = tmp->prev;
node *seg = tmp->next;
if (seg != NULL) {
if (ant != NULL) {
ant->next = seg;
seg->prev = ant;
free(tmp);
return 1;
} else { //prev null
seg->prev = NULL;
*l = *seg;
tmp = NULL;
free(tmp);
return 1;
}
} else { //next null
if (ant == NULL) {
l->nodeInfo.key = somevalue;
l->next = NULL;
l->prev = NULL;
return 1;
} else {
printf("Here is the problem\n");
ant->next = NULL;
free(tmp);
return 1;
}
}
} else { //tmp nulo
perror("Error delete : node null\n");
return 0;
}
}
If I have 4 elements in the list, 1234 and I delete first first element everything is okay and returns 234. If I delete the last element it returns 23 seems to work great. But if I try to delete the last element now the function does nothing despite being the same case that when it is 234 and I don't understand why. The list is not being updated.
In the main I am using the list like this :
list a;
delete(&a, "whatever");
What am I doing wrong ?
This is the code for search
node * createnode(){
node *tmp = (node *) malloc (sizeof(node));
return tmp;
}
node * search(list *l, char* direction) {
node *tmp = createnode();
if (l->nodeInfo.key == 777) {
perror("Error search: empty list\n");
return NULL;
}
tmp=l;
while((strcmp(direction, tmp->nodeInfo.direction) !=0) && (tmp->next != NULL)) {
tmp = tmp->next;
}
if (strcmp(direction, tmp->nodeInfo.direction) == 0) {
return tmp;
} else {
perror("Error search: element not found\n");
return NULL;
}
}

C- Binary Search Tree

I am trying to build a a binary search tree. But I am not getting the correct output when performing the different traversals.
typedef struct binary_search_tree{
struct binary_search_tree *lchild;
int data;
struct binary_search_tree *rchild;
}bst_t;
#define ALLOCATE (bst_t*)malloc(sizeof(bst_t))
Here is the insert function:
void insert(bst_t *ptr,int data){
if( ptr->data < data){
if ( ptr->lchild == NULL ){
ptr->lchild = ALLOCATE;
ptr->lchild->data = data;
return;
}else
insert(ptr->lchild,data);
}else{
if ( ptr->rchild == NULL ){
ptr->rchild = ALLOCATE;
ptr->rchild->data = data;
return;
}else
insert(ptr->rchild,data);
}
}
Is this function correct?
I am sending the address of root while calling that function.
The problem is the ALLOCATE macro. It doesn't do nearly enough to properly allocate and initialize a new node. I suggest creating a newNode function that allocates memory for the node, and then initializes all of the members of the structure, like this
bst_t *newNode(int data)
{
// allocation and error checking
bst_t *node = malloc(sizeof(bst_t));
if ( node == NULL )
{
fprintf(stderr, "out of memory\n");
exit( 1 );
}
// initialize the members of the structure
node->lchild = NULL;
node->data = data;
node->rchild = NULL;
return node;
}
Then the insert function can be simplified to this
void insert(bst_t *ptr,int data)
{
if( ptr->data < data){
if ( ptr->lchild == NULL )
ptr->lchild = newNode(data);
else
insert(ptr->lchild,data);
}else{
if ( ptr->rchild == NULL )
ptr->rchild = newNode(data);
else
insert(ptr->rchild,data);
}
}

Resources