Linked List program error? In C - c

Trying to study linked list and tried my program on gcc 4.1.2 on terminal and Xcode.
xcode Error: Thread 1: Exe_BAD_ACCESS(Code=1)
Terminal Error; Segmentation fault
and i have no clue what the xcode error is. for some reason it gives me that same error for some programs that work on other gcc?
Code :
#include <stdio.h>
#include <stdlib.h>
typedef struct node *link;
struct node {int item; link next;};
int main(int argc, const char * argv[]) {
int i;
link t = malloc(sizeof *t);
while ( t != NULL)
{
for ( i = 0; i < 10;i++)
{
t->item = i;
t = t->next;
}
}
int count = 0;
while ( t != NULL)
{
for ( i = 0; i < 10; i++)
{
if (count == 3)
{
printf("%d\n", t->item);
continue;
}
t = t->next;
count++;
}
}
}

You dereferenced t->next, which is allocated via malloc() and not assigned some value, and invoked undefined behavior. You have to allocate buffer for second node and later.
Also you should get the pointer t back before dealing with the list.
#include <stdio.h>
#include <stdlib.h>
typedef struct node *link;
struct node {int item; link next;};
int main(int argc, const char * argv[]) {
int i;
link t = malloc(sizeof *t);
link head = t; /* add this line to get the pointer back */
while ( t != NULL)
{
for ( i = 0; i < 10;i++)
{
t->item = i;
t->next = malloc(sizeof *t); /* add this line */
t = t->next;
}
}
int count = 0;
t = head; /* add this line to get the pointer back */
while ( t != NULL) /* convinated with inner loop, this will lead to infinite loop */
{
for ( i = 0; i < 10; i++) /* you may want to check if t != NULL here for safety */
{
/* not invalid but odd program that print the 4th element again and again */
if (count == 3)
{
printf("%d\n", t->item);
continue;
}
t = t->next;
count++;
}
}
}

Related

searching for an element inside a linked list c

So i have a header file with a linked list implementation with a structure, the problem is when i want to find if an element is already inside the linked list if i do all the steps in the main function it works, but if i do that in a seperate function it doesnt work and i dont know why.
Program:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Listas_ligadas2.h"
/*
ident: val[0]
linha: val[1]
*/
void remove_esp(char str[]); // removes the first char of the scanned string beacuse its of being a ' '
int equipa_in(link_v head, char nome[]);// the function with the problem
void A(char equipa[],int val[],link_v headv);
//basically while c != x it applies the switch
int main()
{
char c;char nome[1023];
link_v head2 = NULL;
int valores[2] = {0,1};
while ((c = getchar())!= 'x') {
switch (c)
{
case 'A':
{
scanf("%1023[^:\n]",nome);
remove_esp(nome);
if (equipa_in(head2,nome) == 1)
{
printf("%d Equipa existente.\n",valores[1]);
valores[1]++;
}
else
{
head2 = insertEnd_v(head2,nome,valores);
valores[1]++;
}
break;
}
}
}
return 0;
}
int equipa_in(link_v head, char nome[])
{
link_v t;
for(t = head; t != NULL; t = t->next)
if(strcmp(t->v.nome,nome) == 0)
return 1;
return 0;
}
void remove_esp (char str[])
{
int i;
if (str[0] == ' ')
{
for (i = 0; str[i] != '\0'; ++i)
str[i] = str[i + 1];
}
}
So if i do it like that it works fine, but if i do it like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Listas_ligadas2.h"
/*
ident: val[0]
linha: val[1]
*/
void remove_esp(char str[]); // removes the first char of the scanned string beacuse its of being a ' '
int equipa_in(link_v head, char nome[]);// the function with the problem
void A(char nome[],int valores[],link_v head2);
//basically while c != x it applies the switch
int main()
{
char c;char nome[1023];
link_v head2 = NULL;
int valores[2] = {0,1};
while ((c = getchar())!= 'x') {
switch (c)
{
case 'A':
{
scanf("%1023[^:\n]",nome);
remove_esp(nome);
A(nome,valores,head2);
break;
}
}
}
return 0;
}
int equipa_in(link_v head, char nome[])
{
link_v t;
for(t = head; t != NULL; t = t->next)
if(strcmp(t->v.nome,nome) == 0)
return 1;
return 0;
}
void remove_esp (char str[])
{
int i;
if (str[0] == ' ')
{
for (i = 0; str[i] != '\0'; ++i)
str[i] = str[i + 1];
}
}
void A(char nome[],int valores[],link_v head2)
{
if (equipa_in(head2,nome) == 1)
{
printf("%d Equipa existente.\n",valores[1]);
valores[1]++;
}
else
{
head2 = insertEnd_v(head2,nome,valores);
valores[1]++;
}
}
it doesnt work and i dont understand why.
header file:
#ifndef _Listas_ligadas2_
#define _Listas_ligadas2_
#include<stdlib.h>
#include<stdio.h>
#include <string.h>
typedef struct vit
{
int id;
char *nome;
int vit;
} vit;
typedef struct node_v
{
vit v;
struct node_v *next;
} *link_v;
//this function removes a certin char at a given index
void removechar_v(char *orig, int index, char *newStr)
{
if(!orig){};
if(!newStr){};
int i=0, j=0;
while (*(orig+i) != '\0')
{
if (i != index)
{
*(newStr+j) = *(orig+i);
j++;
i++;
}
else i++;
}
*(newStr+j) = '\0';
}
link_v NEW_vit(char *nome,int val[])
{
int i;
link_v x = (link_v) malloc(sizeof(struct node_v));
x->v.nome = (char*) malloc(sizeof(char)*(strlen(nome)+1));
strcpy(x->v.nome,nome);
x->v.vit = 0;
x->v.id = val[0];
x->next = NULL;
val[0]++;
return x;
}
link_v insertEnd_v(link_v head,char *nome,int val[])
{
link_v x;
if(head == NULL)
return NEW_vit(nome,val);
for(x = head; x->next != NULL; x = x->next)
;
x->next = NEW_vit(nome,val);
return head;
}
int length_v(link_v head)
{
int count=0;
link_v x;
for(x=head ; x!=NULL; x=x->next)
count++;
return count;
}
//prints the elements in the list and copies its name to another string because
//for some reason if i want to print t->v.nome and the nome is abc it prints abcc
void print_lista_v(link_v head,int val[])
{
link_v t;char *nnome;
for(t = head; t != NULL; t = t->next){
nnome = (char*) malloc(strlen(t->v.nome)*sizeof(char));
strcpy(nnome,t->v.nome);
removechar_v(nnome,strlen(t->v.nome)-1,nnome);
printf("%d %d %s %d\n",val[1],t->v.id,nnome,t->v.vit);
}
}
//after removing an element it puts the corresponding indexes of the list
void baixa_id_v(link_v head)
{
link_v t;int i;
i = 0;
for(t = head; t != NULL; t = t->next){
t->v.id = i++;
}
}
void FREEnode_v(link_v t)
{
free(t->v.nome);
free(t);
}
link_v delete_el_v(link_v head,char *nome)
{
link_v t, prev;
for(t = head, prev = NULL; t != NULL;
prev = t, t = t->next) {
if(strcmp(t->v.nome,nome) == 0) {
if(t == head)
head = t->next;
else
prev->next = t->next;
FREEnode_v(t);
break;
}
}
return head;
}
link_v lookup_v(link_v head, char *nome)
{
link_v t;
for(t = head; t != NULL; t = t->next)
if(strcmp(t->v.nome,nome) == 0)
return t;
return NULL;
}
#endif
I have had a go at copying and then compiling/running your code. Apart from a few typos (the code has a few references to link_char which I changed to link_v, I also declared char nome_jg[1023] and link_v head) it works for me.
I did have to write the following function:
void remove_esp (char str[])
{
int i;
if (str[0] == ' ')
{
for (i = 0; str[i] != '\0'; ++i)
str[i] = str[i + 1];
}
}
...this seems to be what the comment required of the function.
The issue might be with your implementation of remove_esp.
As has already been pointed out in the comments section, the problem is that the function main is passing a pointer to the head of the linked list by value to the function A. This means that the function A will have its own copy of the pointer to the head of the linked list. So any modification to this pointer in the function A will not change the pointer in the function main.
If you want the function main to receive an updated value of the pointer to the head of the linked list, then you must provide some way for the function main to receive this value. You have 3 options to accomplish this:
Change the prototype of the function 'A' to return the value of the new pointer to the head of the linked list.
Change the prototype of the function 'A' so that the pointer to the head of the linked list is passed by pointer instead of by value.
Store the pointer to the head of the linked list in a global veriable that will be used by both functions main and A.
Generally, I don't recommend option #3, as it is often bad programming style to use global variables. Option #1 is better, however using return values is not very flexible, because a function can only return one value. Therefore, the most flexible option would be option #2.
In order to implement option #2, you would have to change the function prototype from:
void A(char nome[],int valores[],link_v head2);
to:
void A(char nome[],int valores[],link_v *head2);
However, this is confusing, because link_v is already a pointer; it is a typedef for a struct node_v *. Threfore, a link_v * is actually a struct node_v **, so it is a double pointer. To make it clear that it is a double pointer, I will not use the link_v typedef, but will use struct node_v ** instead. Also, to make clear that it is a double pointer, I will also change the name of the variable by prefixing a "pp_", like this:
void A(char nome[],int valores[], struct node_v **pp_head2);
Now, you can rewrite the line
A(nome,valores,head2);
in the function main to the following:
A(nome,valores,&head2);
You are now passing the variable head2 by pointer and no longer by value, so that no copy of the variable is made. That way, any changes to this variable by the function A will also change the value of this variable in the function main.
However, since the head2 parameter of the function A is now a double pointer, it must be used differently inside that function. The line
head2 = insertEnd_v(head2,nome,valores);
must be changed to:
*pp_head2 = insertEnd_v(*pp_head2,nome,valores);
Please note that I had to add the * to dereference the double pointer once. I also had to change the variable name in that line, because I had changed the name of the function parameter.

C Program: Create Linked List Using argv, argc, Segmentation Fault

I have a program that takes in strings using the command line prompts argv and argc. I keep getting a segmentation fault when I go to run the code and after much researching, I cannot determine what might be causing this. Maybe how I execute the code is the issue? I am using gcc -o code code.c then ./code one two three with one two three being the strings added to the linked list. Any assistance in determining where my error might be would be great.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct list_node_s{
char the_char;
struct list_node_s *next_node;
}list_node;
void insert_node(list_node *the_head, char the_char);
void print_list(list_node *the_head);
int main(int argc, char *argv[]){
char next_char;
list_node *the_head = NULL;
insert_node(the_head, next_char);
the_head->next_node = malloc(sizeof(list_node));
if(the_head == NULL){
return 1;
}
the_head->the_char = 1;
the_head->next_node == NULL;
int the_count, the_count2;
for(the_count = 0; the_count < sizeof(argv); the_count++){
for(the_count2 = 0; argv[the_count][the_count2] != '\0'; the_count2++){
next_char = argv[the_count][the_count2];
insert_node(the_head, next_char);
}
}
print_list(the_head);
return (0);
}
void insert_node(list_node *the_head, char the_char){
list_node * current_node = the_head;
while (current_node->next_node != NULL) {
current_node = current_node->next_node;
}
current_node->next_node = malloc(sizeof(list_node));
current_node->next_node->the_char = the_char;
current_node->next_node->next_node = NULL;
}
void print_list(list_node *the_head){
if(the_head == NULL){
printf("\n");
}else{
printf("%c", the_head->the_char);
print_list(the_head->next_node);
}
}
Change this:
list_node *the_head = NULL;
insert_node(the_head, next_char);
the_head->next_node = malloc(sizeof(list_node));
to:
list_node the_head = { '\0', NULL };
to initialize the_head to an empty node.
One problem is in this function:
void insert_node(list_node *the_head, char the_char){
list_node * current_node = the_head;
while (current_node->next_node != NULL) {
current_node = current_node->next_node;
}
current_node->next_node = malloc(sizeof(list_node));
current_node->next_node->the_char = the_char;
current_node->next_node->next_node = NULL;
}
When you call it in main you're basically passing in NULL because you're setting the_head to NULL. You're trying to access current_node->next_node in the while loop conditions, but because of what you're passing in, you're basically doing NULL->next_node.
You need to initialize your head to an empty list_node. Basically since you're using a char as your node element you could set the value of the char to 0x00, which would make it a zero byte. Then that way you know that when you're at that value, you're at the head.
I don't mean to self-promote, but if you want to look at some code for this have a look at this github repo for the Barry_CS-331 Data Structures class. There's C and C++ in there for the Data Structures. I think it might have a list but if not you can use the stack and the queue as an overall example.
I have modified you code, there has some bugs:
1)、the key bug is in this code.
for(the_count = 0; the_count < sizeof(argv); the_count++)
{
for(the_count2 = 0; argv[the_count][the_count2] != '\0'; the_count2++)
{
next_char = argv[the_count][the_count2];
insert_node(the_head, next_char);
}
}
there some bugs:
you cann't use the_count < sizeof(argv), because of the type of argv is char* []; so sizeof(argv) maybe 4 or 8, based on your os.
the right is:
for(the_count = 1; the_count < argc; the_count++){
for(the_count2 = 0; argv[the_count][the_count2] != '\0'; the_count2++){
next_char = argv[the_count][the_count2];
insert_node(the_head, next_char);
}
}
2、this code aose has some bugs:
list_node *the_head = NULL;
insert_node(the_head, next_char);
the_head->next_node = malloc(sizeof(list_node));
if(the_head == NULL){
return 1;
}
the_head->the_char = 1;
the_head->next_node == NULL;
insert_node(the_head, next_char); is no need, you'd better do the_head->the_char = '\0', because of char 1 is no printable character.
One way:
#include <stdio.h>
#include <stdlib.h>
typedef struct list_node_s{
char the_char;
struct list_node_s *next_node;
}list_node;
void insert_node(list_node *the_head, char the_char);
void print_list(list_node *the_head);
int main(int argc, char *argv[]){
list_node *the_head = NULL;
int the_count, the_count2;
for(the_count = 0; the_count < argc; the_count++)
{
for(the_count2 = 0; the_count2 < strlen(argv[the_count]); the_count2++)
insert_node(&the_head, argv[the_count][the_count2]);
}
print_list(the_head);
return (0);
}
void insert_node(list_node **the_head, char the_char){
list_node *new_node;
list_node *tail_node;
/* Allocate and populate a new node. */
new_node = malloc(sizeof(list_node));
new_node->the_char = the_char;
new_node->next_node = NULL;
/* Is the_head already initialized? */
if(*the_head)
{
/* Yes... find the tail_node. */
tail_node = *the_head;
while(tail_node->next)
tail_node = tail_node->next;
/* Append the new_node to the end of the list. */
tail_node->next = new_node;
return;
}
/* the_head was not initialized. The new_node will be the head node. */
*the_head = new_node;
return;
}
void print_list(list_node *the_head){
if(the_head == NULL){
printf("\n");
}else{
printf("%c", the_head->the_char);
print_list(the_head->next_node);
}
}

Hashing, linked list, delete node

My task is to delete a node from a array of pointers which point to structure.
My code doesn't work and I just don't know why:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Jmena4.h"
#define LENGTH 101
#define P 127
#define Q 31
typedef struct node {
char *name;
struct uzel *next;
} NODE;
int hash(const char Name[]) {
int i;
int n = strlen(Name);
int result;
result = Name[0] * P + Name[1] * Q + Name[n - 1] + n;
return result % LENGTH;
}
void Insert(NODE *array[], const char *name) {
NODE *u;
int h;
u = (NODE*)malloc(sizeof(NODE));
u->name = name;
h = hash(name);
u->next = array[h];
array[h] = u;
}
int Search(NODE *array[], const char *name) {
NODE *u;
u = array[hash(name)];
while (u != NULL) {
if (strcmp(u->name, name) == 0) {
printf("%s\n", u->name);
return 1;
}
u = u->next;
}
printf("Name: %s wasn't found\n", name);
return 0;
}
int Delete(NODE *array[], const char *name) {
NODE *current;
NODE *previous;
int position = hash(name);
current = array[position];
previous = NULL;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
if (previous == NULL) {
array[position] = current->next;
return 1;
} else {
previous->next = current->next;
current = NULL;
return 1;
}
}
previous = current;
current = current->next;
}
return 0;
}
int main() {
int i;
NODE *array[LENGTH];
for (i = 0; i < LENGTH; i++) {
array[i] = NULL;
}
for (i = 0; i < Pocet; i++) {
Insert(array, Jmena[i]);
}
for (i = 0; i < PocetZ; i++) {
Delete(array, JmenaZ[i]);
}
Search(array, "Julie");
system("PAUSE");
return 0;
}
EDIT 1: I changed names of variables and instead of position = array[position] should be current = array[position], but it still doesn't work.
EDIT 2 : In array Jmena is string "Julie" and I can search it after Insert function, but after I delete strings from JmenaZ which not included "Julie" program output is: Name: Julie wasn't found.
For one thing, current isn't initialized before it gets tested in the while loop.

History in own C Shell

I'm writing my own C Shell and I'm having trouble implementing something to maintain a history of commands.
I'd like to store it in a struct with an integer and string (so I can keep the command and its place in memory together), and I only want to store 20 elements.
I've tried using code from questions other people have asked on this website but when I compile it, it just returns a segmentation fault, so I'm guessing there's something wrong with the pointers.
Here's all the code I found relating to the history:
char** cmdHistory; /* command history - no longer than 20 elements & null terminated */
int historySize = 0;
void addToHistory(char* newEntry) {
char** h;
int historySize = 0;
while (*cmdHistory != NULL)
if (sizeof(cmdHistory) == 20) {
char** newPtr = ++cmdHistory;
free(cmdHistory[0]);
cmdHistory = newPtr;
h = (char**)realloc(cmdHistory,20*sizeof(int));
cmdHistory = h;
cmdHistory[20] = newEntry;
} else {
h = (char**)realloc(cmdHistory,sizeof(int)+sizeof(cmdHistory));
cmdHistory = h;
cmdHistory[historySize] = newEntry;
++historySize;
}
}
void printHistory() {
char** currCmd = cmdHistory;
printf("\n\n");
while (*currCmd != NULL) {
printf("%s\n", *currCmd);
currCmd++;
}
printf("\n\n");
}
int main() {
cmdHistory[20] = NULL; /* null terminate the history */
}
I'm pretty useless with C, so any help is much appreciated.
You can use link list to implement history, always adding present command at the head. Like this:
#include <stdio.h>
typedef struct history
{
char *ent;
struct history * next;
}hist;
hist *top = NULL;
void add(char *s)
{
hist *h = (hist *) malloc(sizeof(hist));
h->ent = s;
h->next = top;
top = h;
}
void print()
{
hist *i;
for (i = top; i != NULL; i = i->next)
printf("%s\n", i->ent);
}
int main()
{
add("command");
print();
}

Heap error in DLL

I'm looking for some help with some C dll programming. I am getting an error in Visual Studio that occurs when I call free from within the dll. The program runs fine in debug mode within the IDE, but when I try to execute it as "Start without debugging", the program crashes. I read that with debugging, the heap is shared, which probably explains why the code runs fine with F5 and not Ctrl-F5. Is this correct??
I've searched around, and I learned that it is dangerous to pass dynamically allocated memory through the dll-exe boundary, however as I am calling malloc and free from within the same dll, this should not be a problem. I have posted the code below. Any help would be greatly appreciated. Please note that this code works on my Linux box, I am simply trying to port it to Windows to garner experience programming in Windows.
Thank you
#ifndef HASHTABLE_H
#define HASHTABLE_H
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the HASHTABLE_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// HASHTABLE_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef HASHTABLE_EXPORTS
#define HASHTABLE_API __declspec(dllexport)
#else
#define HASHTABLE_API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* This is a naive implementation
* of a hashtable
*/
typedef struct node {
struct node *next;
char *value;
char *key;
} Node;
typedef struct hashtable {
struct node **nodes;
int num_elements;
int size;
int (*hash_function)(const char * const);
} Hashtable_str;
// Construction and destruction
HASHTABLE_API void tbl_construct(Hashtable_str **table);
HASHTABLE_API void tbl_destruct(Hashtable_str *table);
// Operations
HASHTABLE_API int tbl_insert (Hashtable_str *table, const char * const key, const char * const element); // return the key
HASHTABLE_API int tbl_remove(Hashtable_str *table, const char * const key);
HASHTABLE_API char * tbl_find(Hashtable_str *table, const char * const key); // return the element
HASHTABLE_API int size(Hashtable_str *table); // Return the size
// default hash function
int def_hash(const char * const key);
#ifdef __cplusplus
}
#endif
#endif
Here is the implementation code
// hashtable.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "hashtable.h"
#include <stdlib.h> // for memcpy
#include <stdio.h>
#include <string.h>
#define SIZE 100
int def_hash(const char * const key)
{
// simply sum the ascii
// values and take modulo
// 100
//int i;
//int sum;
//sum = 0;
//for (i=0; key[i] != '\0'; i++)
// sum += key[i];
//return sum % SIZE;
return 0;
}
// construct a hashtable and return a pointer
HASHTABLE_API void tbl_construct(Hashtable_str **tbl)
{
int i;
Hashtable_str *tbl_ptr;
*tbl = (Hashtable_str*) malloc (sizeof(Hashtable_str*));
tbl_ptr = *tbl;
tbl_ptr->nodes = (Node**) malloc (SIZE * sizeof(Node*));
for (i=0; i < SIZE; i++) tbl_ptr->nodes[i] = NULL;
tbl_ptr->hash_function = &def_hash;
tbl_ptr->num_elements = 0;
tbl_ptr->size = SIZE;
}
HASHTABLE_API void tbl_destruct(Hashtable_str *tbl)
{
void free_tbl_node(Node*); // declare the release function
int i;
for (i=0; i < tbl->size; i++)
{
if (tbl->nodes[i] != NULL)
free_tbl_node(tbl->nodes[i]);
}
}
void free_tbl_node(Node *curr_node)
{
if (curr_node->next != NULL)
free_tbl_node(curr_node->next);
free(curr_node->value);
curr_node->value = NULL;
free(curr_node->key);
curr_node->key = NULL;
//free(curr_node);
//Node *temp = NULL;
//Node *temp2 = NULL;
//temp = temp2 = curr_node;
//while (temp->next != NULL)
//{
// temp2=temp->next;
// free(temp->key);
// free(temp->value);
// free(temp);
// temp=temp2;
//}
}
// table operations
HASHTABLE_API int count(Hashtable_str *tbl) { return tbl->num_elements; }
HASHTABLE_API int size(Hashtable_str *tbl) { return tbl->size; }
HASHTABLE_API int tbl_insert(Hashtable_str *table, const char * const key, const char * const element)
{
int hash;
Node *temp_ptr = NULL;
hash = table->hash_function(key);
// printf("Placing into column %d\n", hash);
if (table->nodes[hash] == NULL)
{
table->nodes[hash] = (Node*) malloc(sizeof(Node*));
temp_ptr = table->nodes[hash];
temp_ptr->next = NULL;
temp_ptr->key = (char*) malloc (strlen(key) + 1 * sizeof(char));
temp_ptr->value = (char*) malloc (strlen(element) + 1 * sizeof(char));
strcpy_s(temp_ptr->key, strlen(key)+1, key);
strcpy_s(temp_ptr->value, strlen(element)+1, element);
table->num_elements += 1;
}
else
{
// Collision!!
temp_ptr = table->nodes[hash];
while (temp_ptr->next != NULL)
temp_ptr = temp_ptr->next;
temp_ptr->next = (Node*) malloc(sizeof(Node));
temp_ptr->next->key = (char*) malloc (strlen(key)+1 * sizeof(char));
temp_ptr->next->value = (char*) malloc (strlen(element)+1 * sizeof(char));
temp_ptr->next->next = NULL;
strcpy_s(temp_ptr->next->key, strlen(key)+1, key);
strcpy_s(temp_ptr->next->value, strlen(element)+1, element);
table->num_elements += 1;
}
// Return the hash value itself for hacking
return hash;
}
HASHTABLE_API int tbl_remove(Hashtable_str *tbl, const char * const key)
{
int hash;
Node *temp_ptr = NULL;
Node *chain = NULL;
hash = tbl->hash_function(key);
if (tbl->nodes[hash] == NULL)
return 1;
else
{
temp_ptr = tbl->nodes[hash];
if (strcmp(key, temp_ptr->key) == 0)
{
// The next node is the node in question
chain = temp_ptr->next;
free(temp_ptr->value);
printf("Deleted the value\n");
free(temp_ptr->key);
printf("Deleted the key\n");
//printf("About to delete the node itself\n");
//free(temp_ptr);
tbl->nodes[hash] = chain;
tbl->num_elements -= 1;
return 0;
}
else
{
while (temp_ptr->next != NULL)
{
if (strcmp(key, temp_ptr->next->key) == 0)
{
// The next node is the node in question
// So grab a pointer to the node after it
// and remove the next node
chain = temp_ptr->next->next;
free(temp_ptr->next->key);
free(temp_ptr->next->value);
//free(temp_ptr->next);
temp_ptr->next = chain;
tbl->num_elements -= 1;
return 0;
}
else
temp_ptr = temp_ptr->next;
}
}
// Couldn't find the node, so declare not existent
return 1;
}
}
HASHTABLE_API char * tbl_find(Hashtable_str *tbl, const char * const key)
{
// Compute the hash for the index
int hash;
Node *temp_ptr = NULL;
hash = tbl->hash_function(key);
if (tbl->nodes[hash] == NULL)
return NULL;
else
{
temp_ptr = tbl->nodes[hash];
if (strcmp(key, temp_ptr->key) != 0)
{
while (temp_ptr->next != NULL)
{
temp_ptr = temp_ptr->next;
if (strcmp(key, temp_ptr->key) == 0)
return temp_ptr->value;
}
}
// Couldn't find the node, so declare not existent
return NULL;
}
}
Here's my main
#include <hashtable.h>
#include <utils.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int i=0;
Hashtable_str *my_table = NULL;
tbl_construct(&my_table);
tbl_insert(my_table, "Daniel", "Student");
tbl_insert(my_table, "Derek", "Lecturer");
//tbl_insert(my_table, "Melvyn", "Lecturer");
tbl_print(my_table);
printf("\nRemoving Daniel...\n");
tbl_remove(my_table, "Daniel");
//tbl_print(my_table);
tbl_destruct(my_table);
my_table = NULL;
scanf_s("%d", &i);
return 0;
}
This is incorrect as allocates the size of a pointer, not a Hashtable_str:
*tbl = (Hashtable_str*) malloc (sizeof(Hashtable_str*));
it should be:
*tbl = malloc(sizeof(Hashtable_str));
Same issue with:
table->nodes[hash] = (Node*) malloc(sizeof(Node*));
See Do I cast the result of malloc?

Resources