For some reason the data I have added to my linked list is not printing.
It prints if I add the function PrintList right after adding or if I print it within a for loop with a set number but I want it to print after adding all the products and after breaking the while loop.
This is my code:
typedef struct SProducts
{
char *name;
struct SProducts *next;
}Products;
Products *Add(Products *list, char *file)
{
Products *el = (Products *) malloc(sizeof(Products));
if(el != NULL)
{
el->name = file;
el->next = list;
}
return el;
}
void PrintList(Products *list)
{
while(list != NULL)
{
printf("%s", list->name);
list = list->next;
}
}
int main(void){
Products *list = NULL;
char file[255];
while (fgets(file,sizeof(file),stdin) != NULL)
{
list = Add(list, file);
if (file[0] == '\n')
{
break;
}
}
PrintList(list);
}
You are always passing the same address of the first character of the local character array file.
list = Add(list, file);
So the last string that is stored in this array will be outputted for all nodes of the list.
You need to allocate dynamically a character array in each node that will store the passed string.
For example
#include <stdlib.h>
#include <string.h>
//...
Products * Add( Products *list, const char *file )
{
Products *el = malloc( sizeof( Products ) );
if ( el != NULL )
{
e1->name = malloc( strlen( file ) + 1 );
if ( e1->name != NULL ) strcpy( el->name, file );
el->next = list;
}
return el;
}
//...
while ( fgets( file, sizeof( file ), stdin ) != NULL && file[0] != '\n' )
{
file[ strcspn( file, "\n" ) ] = '\0';
Products *tmp = Add( list, file );
if ( tmp != NULL ) list = tmp;
}
Pay attention to that you need also at least write a function that will delete all the allocated memory of the list when it will not be required any more.
Related
I had to write a recursive function that receives two sorted lists:
typedef struct listNode {
int* dataPtr;
struct listNode* next;
} ListNode;
typedef struct list
{
ListNode* head;
ListNode* tail;
} List;
and merge them into one sorted list.
I wrote these functions:
void mergeRec(ListNode* head1, ListNode* head2, ListNode* mergedList)
{
if (head1 == NULL && head2 == NULL)
return;
else if (head1 == NULL) {
mergedList->next = head2;
head2 = head2->next;
}
else if (head2 == NULL) {
mergedList->next = head1;
head1 = head1->next;
}
else if (*(head1->dataPtr) > *(head2->dataPtr)) {
mergedList->next = head1;
head1 = head1->next;
}
else
{
mergedList->next = head2;
head2 = head2->next;
}
mergeRec(head1, head2, mergedList->next);
}
List merge(List lst1, List lst2)
{
List mergedList;
makeEmptyList(&mergedList);
mergeRec(lst1.head, lst2.head, mergedList.head);
return mergedList;
}
Now, the problem I have with the recursive function is that at the first call when merged list is pointing to null, so obviously when I write something like mergeList->next I will get a running bug.
I tried to solve it by adding the following condition in the recursion:
if (mergedList == NULL)
{
if (*(head1->dataPtr) > *(head2->dataPtr))
{
mergedList = head1;
head1 = head1->next;
}
else
{
mergedList = head2;
head2 = head2->next;
}
}
but I got this error:
"Exception thrown at 0x00661EB9 in q2d.exe: 0xC0000005: Access violation writing location 0x01000F48."
I can't tell the problem, or how do I solve it.
I would very much appreciate your help.
Thanks!
For starters it is entirely unclear why in this structure there is a data member of type int *
typedef struct listNode {
int* dataPtr;
struct listNode* next;
}List;
instead of just of type int
typedef struct listNode {
int data;
struct listNode* next;
}List;
Nevertheless, the functions merge and mergeRec are invalid because they deal with copies of values of lists and of pointers list1.head, list2.head, and mergedList.head.
List merge(List lst1, List lst2)
mergeRec(lst1.head, lst2.head, mergedList.head);
Moreover the pointers list1.tail, list2.tail, and mergedList.tail are ignored.
I can suggest the following solution shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
typedef struct listNode
{
int *dataPtr;
struct listNode *next;
} ListNode;
typedef struct list
{
ListNode *head;
ListNode *tail;
} List;
void makeEmpty( List *list )
{
list->head = list->tail = NULL;
}
int push( List *list, int data )
{
ListNode *current = malloc( sizeof( ListNode ) );
int success = current != NULL;
if ( success )
{
current->dataPtr = malloc( sizeof( int ) );
success = current->dataPtr != NULL;
if ( success )
{
*current->dataPtr = data;
current->next = NULL;
if ( list->head == NULL )
{
list->head = list->tail = current;
}
else
{
list->tail = list->tail->next = current;
}
}
else
{
free( current );
current = NULL;
}
}
return success;
}
List merge( List *first, List *second )
{
List result;
makeEmpty( &result );
if ( ( second->head != NULL ) &&
( first->head == NULL || *second->head->dataPtr < *first->head->dataPtr ) )
{
result.head = result.tail = second->head;
second->head = second->head->next;
if ( second->head == NULL ) second->tail = NULL;
}
else if ( first->head != NULL )
{
result.head = result.tail = first->head;
first->head = first->head->next;
if ( first->head == NULL ) first->tail = NULL;
}
if ( !( first->head == NULL && second->head == NULL ) )
{
List tmp = merge( first, second );
result.head->next = tmp.head;
result.tail = tmp.tail;
}
return result;
}
void output( const List *list )
{
for ( const ListNode *current = list->head; current != NULL; current = current->next )
{
printf( "%d ", *current->dataPtr );
}
puts( "NULL" );
}
int main(void)
{
List even_numbers;
List odd_numbers;
makeEmpty( &even_numbers );
makeEmpty( &odd_numbers );
const int N = 10;
for ( int i = 0; i < N; i++ )
{
i % 2 == 0 ? push( &even_numbers, i )
: push( &odd_numbers, i );
}
printf( "even_numbers: " ); output( &even_numbers );
printf( "odd_numbers: " ); output( &odd_numbers );
List all_numbers = merge( &even_numbers, &odd_numbers );
printf( "all_numbers: " ); output( &all_numbers );
printf( "even_numbers: " ); output( &even_numbers );
printf( "odd_numbers: " ); output( &odd_numbers );
return 0;
}
The program output is
even_numbers: 0 2 4 6 8 NULL
odd_numbers: 1 3 5 7 9 NULL
all_numbers: 0 1 2 3 4 5 6 7 8 9 NULL
even_numbers: NULL
odd_numbers: NULL
I'm trying to write two functions: One that pushes out the last cell of a list, and another one to make that cell the first one in another list. Somehow, my functions don't work (and I've checked the other parts of my code many times).
void last_cell_out(CellPtr list, CellPtr c)
{
if (list==NULL)/*if list is empty*/
return;/*doing nothing*/
if (list->next==NULL)/*if theres only one cell in the list*/
{
c=list;
list=NULL;
return;/*deleting from list and moving to c*/
}
if (list->next->next==NULL)
{
c=list->next;
list->next=NULL;
}
else
last_cell_out(list->next, c);
return;
}
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next=list;
return c;/*returnes the start of the list*/
}
This function seems perfectly fine to me, given how you described your requirements
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next=list;
return c;/*returnes the start of the list*/
}
However the last_cell_out has some problems.
first of all you don't need this block of code
if (list->next->next==NULL)
{
c=list->next;
list->next=NULL;
}
it would be dealt with in the next cycle anyway.
That being said your function does remove the last element from the list.
It just does not return it or change it in your code in a way that you can see that.
One option would be to return the last cell, instead of passing it as a parameter.
CellPtr last_cell_out(CellPtr *listPtr)
{
CellPtr list = *listPtr;
if (list==NULL)/*if list is empty*/
return NULL;/*doing nothing*/
if (list->next==NULL)/*if theres only one cell in the list*/
{
*listPtr = NULL;
return list;/*deleting from list and return*/
}
return last_cell_out(&(list->next));
}
The second variant would pass the c as a pointer so you can change it's contents inside the code.
void last_cell_out(CellPtr *listPtr, CellPtr *c)
{
CellPtr list = *listPtr;
if (list==NULL)/*if list is empty*/
{
*c = NULL;
return;/*doing nothing*/
}
if (list->next==NULL)/*if theres only one cell in the list*/
{
*c=list;
*listPtr = NULL;
return;/*deleting from list and moving to c*/
}
last_cell_out(&((*listPtr)->next), c);
return;
}
You can also completely avoid recursion to avoid a possible stack overflow if your list becomes too large.
CellPtr last_cell_out(CellPtr *listPtr)
{
CellPtr list = *listPtr;
if(list == NULL)
return NULL;
if(list->next == NULL) {
*listPtr = NULL;
return list;
}
while(list->next->next != NULL)
list = list->next;
CellPtr tmp = list->next;
list->next = NULL;
return tmp;
}
Complete test program:
#include <stdlib.h>
#include <stdio.h>
typedef struct cell *CellPtr;
typedef struct cell
{
int contents; /* contents of the cell */
CellPtr next; /* next cell in the list */
} Cell;
CellPtr last_cell_out(CellPtr *listPtr)
{
CellPtr list = *listPtr;
if(list == NULL)
return NULL;
if(list->next == NULL) {
*listPtr = NULL;
return list;
}
while(list->next->next != NULL)
list = list->next;
CellPtr tmp = list->next;
list->next = NULL;
return tmp;
}
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next=list;
return c;/*returnes the start of the list*/
}
void show_list(CellPtr list)
{
if(list == NULL) {
printf("\n");
return;
}
printf("%d ", list->contents);
show_list(list->next);
}
int main()
{
CellPtr list = NULL;
CellPtr out;
int i;
show_list(list);
CellPtr elem = malloc(sizeof(struct cell));
elem->contents = 0;
list = new_first_cell(list, elem);
show_list(list);
out = last_cell_out(&list);
show_list(list);
list = new_first_cell(list, out);
show_list(list);
for(i = 1; i < 5; ++i) {
CellPtr elem = malloc(sizeof(struct cell));
elem->contents = i;
list = new_first_cell(list, elem);
}
show_list(list);
out = last_cell_out(&list);
show_list(list);
list = new_first_cell(list, out);
show_list(list);
}
The function last_cell_out has to accept its arguments by reference because it changes their original values. Otherwise the function will have undeifined behaviour because for example this statement
list=NULL;
does not changes the original value of the list. It only changes its local variable list defined as a parameter that has a copy of the vlaue of the original list.
So the function should be defined at least the following way
void last_cell_out(CellPtr *list, CellPtr *c)
{
if ( *list == NULL )/*if list is empty*/
{
*c = NULL;
return;/*doing nothing*/
}
else if ( ( *list )->next == NULL )/*if theres only one cell in the list*/
{
*c = *list;
*list = NULL;
return;/*deleting from list and moving to c*/
}
else if ( ( *list )->next->next == NULL )
{
*c = ( *list )->next;
( *list )->next = NULL;
return;/*deleting from list and moving to c*/
}
else
{
last_cell_out( &( *list )->next, c );
return;/*doing nothing*/
}
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct Cell
{
int data;
struct Cell *next;
};
typedef struct Cell *CellPtr;
void last_cell_out(CellPtr *list, CellPtr *c)
{
if ( *list == NULL )/*if list is empty*/
{
*c = NULL;
return;/*doing nothing*/
}
else if ( ( *list )->next == NULL )/*if theres only one cell in the list*/
{
*c = *list;
*list = NULL;
return;/*deleting from list and moving to c*/
}
else if ( ( *list )->next->next == NULL )
{
*c = ( *list )->next;
( *list )->next = NULL;
return;/*deleting from list and moving to c*/
}
else
{
last_cell_out( &( *list )->next, c );
return;/*doing nothing*/
}
}
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next = list;
return c;/*returnes the start of the list*/
}
void print_cells( CellPtr list )
{
for ( CellPtr current = list; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "NULL" );
}
int main(void)
{
CellPtr list = NULL;
CellPtr cell = malloc( sizeof( struct Cell ) );
cell->data = 1;
list = new_first_cell( list, cell );
print_cells( list );
last_cell_out( &list, &cell );
CellPtr list1 = NULL;
list1 = new_first_cell( list1, cell );
print_cells( list );
print_cells( list1 );
last_cell_out( &list1, &cell );
free( cell );
return 0;
}
Its output is
1 -> NULL
NULL
1 -> NULL
Take into account that it is a bad idea to use a typedef for a pointer because it sometimes confuses users.
And the function last_cell_out can be written simpler without recursion. For example
void last_cell_out(CellPtr *list, CellPtr *c)
{
if ( *list )
{
while ( ( *list )->next ) list = &( *list )->next;
}
*c = *list;
*list = NULL;
}
Or with recursion
void last_cell_out(CellPtr *list, CellPtr *c)
{
if ( *list && ( *list )->next )
{
last_cell_out( &( *list )->next, c );
}
else
{
*c = *list;
*list = NULL;
}
}
I am trying to delete a node from a linked list but I am still new to the concept of double pointers so I tried using a global variable to hold the head pointer instead. However, I get the wrong results when I try to print my list after deleting the middle node.
I saw this question
deleting a node in the middle of a linked list and I don't know how is my delete node function different from the answer.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char u8;
typedef struct Node node;
void addfirstnode( u8 );
void addnode( u8 );
void print( void );
void deletenode( u8 key );
void deleteonlynode();
void deletefirstnode();
struct Node
{
u8 x;
node *next;
};
node *head;
u8 length = 0;
void main( void )
{
u8 x;
printf( "\nTo add node enter 0\nTo print linked list enter 1\nTo exit press 2\nTo delete node press 3\nYour Choice:" );
scanf( "%d", &x );
if ( x == 2 )
{
printf( "\nThank You\nGood Bye" );
}
while ( x != 2 )
{
switch ( x )
{
u8 n;
u8 key;
case 0: //Add node
printf( "\nPlease enter first value:" );
scanf( "%d", &n );
if ( length == 0 )
{
addfirstnode( n );
//printf("%d",head->x);
}
else
{
addnode( n );
}
printf( "\nNode added , Thank you\n" );
break;
case 1: //Print
print();
break;
case 3: //DeleteNode
printf( "\nPlease enter value to be deleted:" );
scanf( "%d", &key );
deletenode( key );
//deletefirstnode();
break;
default:
printf( "\nInvalid Choice please try again\n" );
}
printf( "\nTo add node enter 0\nTo print linked list enter 1\nTo exit press 2\nTo delete node press 3\nYour Choice:" );
scanf( "%d", &x );
if ( x == 2 )
{
printf( "\nThank You\nGood Bye" );
}
}
//where do I use free();
}
void addfirstnode( u8 n )
{
head = ( node * ) malloc( sizeof( node ) );
head->next = NULL;
head->x = n;
length++;
}
void addnode( u8 n )
{
node *last = head;
while ( ( last->next ) != NULL )
{
last = last->next;
}
last->next = ( node * ) malloc( sizeof( node ) );
( last->next )->next = NULL;
( last->next )->x = n;
length++;
}
void print( void )
{
node *last = head;
u8 count = 1;
printf( "\n---------------------" );
if ( last == NULL )
{
printf( "\nList is empty" );
}
while ( last != NULL )
{
printf( "\nNode Number %d = %d", count, last->x );
last = last->next;
count++;
}
printf( "\n---------------------" );
printf( "\n" );
}
void deletenode( u8 key )
{
node *last = head;
//node*postlast = NULL;
if ( ( last->x == key ) && ( last->next == NULL ) )
{
deleteonlynode();
}
else
{
while ( last != NULL )
{
if ( ( last->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = last->next;
last->next = last->next->next;
free( temp );
length--;
}
last = last->next;
}
}
}
void deleteonlynode()
{
printf( "\n Deleting the only node" );
free( head );
head = NULL;
length--;
}
void deletefirstnode()
{
printf( "\n Deleting the first node" );
node *temp = head;
head = head->next;
free( temp );
length--;
}
The code is removing the wrong item from the linked list:
See:
if ( ( last->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = last->next; // last->next? No, just last.
last->next = last->next->next;
free( temp );
length--;
}
last is pointing at the element to be removed. But then the code assigns temp to point at last->next (NOT last), and then cuts that from the list.
So by looking at node->next rather than the current node, it's possible to trim it out since you're starting from the pointer before the one to remove. Basically your code was almost there already.
void deletenode( u8 key )
{
node *ptr = head;
if ( ( ptr->x == key ) )
{
// Delete the first/head element
node *temp = ptr;
head = head->next;
free( temp );
length--;
}
else
{
while ( ptr->next != NULL )
{
if ( ( ptr->next->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = ptr->next;
ptr->next = ptr->next->next;
free( temp );
length--;
}
ptr = ptr->next;
}
}
}
Also I took the liberty of renaming last to ptr because it was confusing me.
EDIT: Updated to remove the head cleanly too.
Your code seems to be deleting last->next while last should be the node that matches the key.
I guess the following code may be shorter and do the deletion
node* head;
/* returns the node* the previous_node->next should be after the deletion */
node* delete_node(node* current, u8 key) {
if (current == NULL) return NULL; // deletion comes to end
if (head->x == key) {
node* temp = current->next;
free(current);
return delete_node(temp, key);
}
current->next = delete_node(current->next, key);
return current;
}
int main() {
// build the linked list
// ...
head = delete_node(head, key);
return 0;
}
However, this implement (which uses recursion instead of loop) may cause StackOverFlow if the list is too long. I had not tested if gcc would optimize the recursion out.
I'm writing a program which creates lists, print it and remove from the list (3 functions).
Print and pushBack are fine, they work nice but I can't figure out how to pick up a number to remove from the list in removeFromList() function.
Don't pay attention on names (like client, socket), it's for my client-server application to save active sockets (that's why I need to remove them from a list when client has disconnected).
Here I have 2 structures: listElement and clientList (which contains a pointer to head element of listElement)
struct listElement
{
SOCKET socket;
struct listElement* next;
};
struct clientList
{
listElement * head;
};
My pushBack function:
int pushBackŠ”lient(struct clientList* list, int socket)
{
struct listElement* newClient = (struct listElement*)malloc(sizeof(struct listElement));
struct listElement* currentElement = list->head;
newClient->socket = socket;
newClient->next = 0;
do
{
// IT'S PUSHBACK
if (list->head == 0)
{
list->head = newClient;
break;
}
while (currentElement->next != 0)
{
currentElement = currentElement->next;
}
currentElement->next = newClient;
} while (false);
return 0;
}
My print:
void print(struct clientList* list)
{
struct listElement* currentElement = list->head;
while (currentElement != 0)
{
printf("%d\n", currentElement->socket);
currentElement = currentElement->next;
}
}
And the function I have a problem with (I made debug messages to see if a "socket" was added correctly). I suppose I don't need the first 3 lines but not sure.
Updated13/05/2017
void removeFromList(struct clientList* list, int socket)
{
struct listElement* currentElement = list->head;
do
{
if (list->head == 0)
{
return;
}
while (currentElement != 0 && currentElement->next != 0)
{
if (currentElement->socket == socket)
{
printf("currentElement == %d\n", currentElement);
currentElement = currentElement->next;
printf("currentElement == %d\n", currentElement);
free(currentElement);
//break; // if I only want to remove the first socket?
}
currentElement = currentElement->next;
}
} while (false);
}
Thank you.
The function removeFromList is wrong at least because this condition of the while statement can be equal to false when the list contains only one element. In this case even this one element contains the target vakue it will not be removed.
while (currentElement != 0 && currentElement->next != 0)
The functions can look as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef int SOCKET;
struct listElement
{
SOCKET socket;
struct listElement *next;
};
struct clientList
{
struct listElement *head;
};
int pushBackClient( struct clientList *list, SOCKET socket )
{
struct listElement *newClient = malloc( sizeof( struct listElement ) );
int success = newClient!= NULL;
if ( success )
{
newClient->socket = socket;
newClient->next = NULL;
struct listElement **current = &list->head;
while ( *current != NULL ) current = &( *current )->next;
*current = newClient;
}
return success;
}
int removeFromList( struct clientList *list, SOCKET socket )
{
int success;
struct listElement **current = &list->head;
while ( *current != NULL && ( *current )->socket != socket )
{
current = &( *current )->next;
}
if ( ( success = *current != NULL ) )
{
struct listElement *tmp = *current;
*current = ( *current )->next;
free( tmp );
}
return success;
}
void print(struct clientList *list)
{
for ( struct listElement *current = list->head;
current != NULL;
current = current->next )
{
printf( "%d ", current->socket );
}
}
int main(void)
{
const int N = 10;
struct clientList list = { NULL };
for ( int i = 0; i < N; i++ ) pushBackClient( &list, i );
print( &list );
putchar( '\n' );
for ( int i = 0; i < N; i++ )
{
if ( i % 2 == 0 ) removeFromList( &list, i );
}
print( &list );
putchar( '\n' );
for ( int i = 0; i < N; i++ )
{
if ( i % 2 == 1 ) removeFromList( &list, i );
}
print( &list );
putchar( '\n' );
return 0;
}
The program output is
0 1 2 3 4 5 6 7 8 9
1 3 5 7 9
You need at least to add a function that will free all elements of the list.
For your remove function I suggest something like this:
void removeFromList(struct clientList* list, int socket)
{
struct listElement* aux, prev;
if(list->head == 0)
return;
aux = list->head;
prev = aux;
while(aux != 0){
if(aux->socket == socket) {
prev->next = aux->next;
free(aux);
break; // if you only want to remove the first socket
}
prev = aux;
aux = aux->next;
}
}
As for your list structure, I suggest using a structure of structs, like follows:
struct list
{
int numberOfElements;
NODE * first;
} LIST;
struct node
{
ELEMENT * info;
NODE * prev; // If you want to have a double connection between the nodes
NODE * next;
} NODE;
struct element
{
int id;
/* Other Properties */
} ELEMENT;
It should give you a better control of your list.
I have developed the below hash table implementation code, but it fails to execute while trying to insert key,value pair.
I am very new to this concept and trying hard to fix this one.Any help would be greatly appreciated.
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include<conio.h>
struct entry_s {
char *key;
char *value;
struct entry_s *next;
};
typedef struct entry_s entry_t;
struct hashtable_s {
int size;
struct entry_s **table;
};
typedef struct hashtable_s hashtable_t;
/* Create a new hashtable. */
hashtable_t *ht_create( int size ) {
hashtable_t *hashtable = NULL;
int i;
if( size < 1 ) return NULL;
/* Allocate the table itself. */
if( ( hashtable = malloc( sizeof( hashtable_t ) ) ) == NULL ) {
return NULL;
}
/* Allocate pointers to the head nodes. */
if( ( hashtable->table = malloc( sizeof( entry_t * ) * size ) ) == NULL ) {
return NULL;
}
for( i = 0; i < size; i++ ) {
hashtable->table[i] = NULL;
}
hashtable->size = size;
return hashtable;
}
/* Hash a string for a particular hash table. */
int ht_hash( hashtable_t *hashtable, char *key ) {
unsigned long int hashval=0;
int i = 0;
/* Convert our string to an integer */
while( hashval < ULONG_MAX && i < strlen( key ) ) {
hashval = hashval << 8;
hashval += key[ i ];
i++;
}
return hashval % hashtable->size;
}
/* Create a key-value pair. */
entry_t *ht_newpair( char *key, char *value ) {
entry_t *newpair=NULL;
if( ( newpair == malloc( sizeof( entry_t ) ) ) == NULL ) {
return NULL;
}
if( ( newpair->key = _strdup( key ) ) == NULL ) {
return NULL;
}
if( ( newpair->value = _strdup( value ) ) == NULL ) {
return NULL;
}
newpair->next = NULL;
return newpair;
}
/* Insert a key-value pair into a hash table. */
void ht_set( hashtable_t *hashtable, char *key, char *value ) {
int bin = 0;
entry_t *newpair = NULL;
entry_t *next = NULL;
entry_t *last = NULL;
bin = ht_hash( hashtable, key );
next = hashtable->table[ bin ];
while( next != NULL && next->key != NULL && strcmp( key, next->key ) > 0 ) {
last = next;
next = next->next;
}
/* There's already a pair. Let's replace that string. */
if( next != NULL && next->key != NULL && strcmp( key, next->key ) == 0 ) {
free( next->value );
next->value = _strdup( value );
/* Nope, could't find it. Time to grow a pair. */
} else {
newpair = ht_newpair( key, value );
/* We're at the start of the linked list in this bin. */
if( next == hashtable->table[ bin ] ) {
newpair->next = next;
hashtable->table[ bin ] = newpair;
/* We're at the end of the linked list in this bin. */
} else if ( next == NULL ) {
last->next = newpair;
/* We're in the middle of the list. */
} else {
newpair->next = next;
last->next = newpair;
}
}
}
/* Retrieve a key-value pair from a hash table. */
char *ht_get( hashtable_t *hashtable, char *key ) {
int bin = 0;
entry_t *pair;
bin = ht_hash( hashtable, key );
/* Step through the bin, looking for our value. */
pair = hashtable->table[ bin ];
while( pair != NULL && pair->key != NULL && strcmp( key, pair->key ) > 0 ) {
pair = pair->next;
}
/* Did we actually find anything? */
if( pair == NULL || pair->key == NULL || strcmp( key, pair->key ) != 0 ) {
return NULL;
} else {
return pair->value;
}
}
int main( int argc, char **argv ) {
hashtable_t *hashtable = ht_create( 65536 );
ht_set( hashtable, "key1", "john" );
ht_set( hashtable, "key2", "kris" );
ht_set( hashtable, "key3", "ricky" );
ht_set( hashtable, "key4", "mike" );
printf( "%s\n", ht_get( hashtable, "key1" ) );
printf( "%s\n", ht_get( hashtable, "key2" ) );
printf( "%s\n", ht_get( hashtable, "key3" ) );
printf( "%s\n", ht_get( hashtable, "key4" ) );
return 0;
}
Change
newpair == malloc( sizeof( entry_t ) ) to
newpair = malloc( sizeof( entry_t ) )
in ht_newpair