So I have a program that takes an int for input, and inserts the integer into a doubly linked list where the functions are createQueue, enqueue, dequeue, display, peek, and destroyQueue. I have a main.c and a queue.h file but the problem doesn't lay in there, it's in the queue.c file. The problem is when I pipeline a test12.txt file and print to an output.txt with the following commands, enqueue 0 0 display, I get a segmentation fault. If I run just enqueue 0 0 in the test12.txt file there's no problem, it works just fine. My question is, am I dereferencing temp in display when it points to nothing when I write temp = temp->prev; or is that a valid call and my problem lies in the initialization of my temp node?
queue.c file:
#include "queue.h"
Queue_ptr createQueue() {
Queue_ptr s = (Queue_ptr)malloc(sizeof(Queue));
s->front = NULL;
s->back = NULL;
return s;
}
void enqueue(Queue_ptr s, element e) {
DN_ptr n = (DN_ptr)malloc(sizeof(DLLNode));
n->e = e;
if (s->front == NULL) {
n->next = NULL;
s->front = n;
s->back = n;
}else{
s->back->next = n;
n->prev = s->back;
s->back = n;
}
}
element dequeue(Queue_ptr s) {
DN_ptr temp = s->front->next;
element e = s->front->e;
free(s->front);
s->front = temp;
s->front->next = NULL;
s->front->prev = NULL;
return e;
}
int isEmpty(Queue_ptr s) {
if (s->front == NULL)
return 1;
else
return 0;
}
element peek(Queue_ptr s) {
return s->front->e;
}
void display(Queue_ptr s) {
DN_ptr temp = s->back;
while (temp) {
printf("%d\n", temp->e);
temp = temp->prev;
}
}
void destroyQueue(Queue_ptr s) {
DN_ptr temp = s->front;
DN_ptr next;
while (temp) {
next = temp->next;
free(temp);
temp = next;
}
free(s);
}
queue.h file:
#ifndef queue_h
#define queue_h
#include "stdheader.h"
//Structures
//element is content of a node.
typedef int element;
//_DLLnode is 1 link in a doubly linked list.
struct _DLLNode {
element e;
struct _DLLNode *next;
struct _DLLNode *prev;
};
typedef struct _DLLNode DLLNode;
typedef struct _DLLNode *DN_ptr;
//DLL is a series of links tracked by the head and back of the list.
struct _DLL {
DN_ptr front;
DN_ptr back;
};
typedef struct _DLL Queue;
typedef struct _DLL *Queue_ptr;
Queue_ptr createQueue();
void enqueue(Queue_ptr, element);
element dequeue(Queue_ptr);
int isEmpty(Queue_ptr);
element peek(Queue_ptr);
void display(Queue_ptr);
void destroyQueue(Queue_ptr);
#endif /* queue_h */
You do not set n->prev in enqueue when the queue is empty, neither do you set n->next when the queue is not empty.
dequeue corrupts the queue if it has more than 2 elements, and it crashes if it has only one element.
Here is a corrected version:
void enqueue(Queue_ptr s, element e) {
DN_ptr n = (DN_ptr)malloc(sizeof(DLLNode));
n->e = e;
n->next = NULL;
if (s->front == NULL) {
n->prev = NULL;
s->front = n;
s->back = n;
} else {
s->back->next = n;
n->prev = s->back;
s->back = n;
}
}
element dequeue(Queue_ptr s) {
DN_ptr temp = s->front->next;
element e = s->front->e;
free(s->front);
s->front = temp;
if (temp) {
temp->prev = NULL;
} else {
s->back = NULL;
}
return e;
}
Related
I am trying to write an intrusion detection system in c where I have a linked list of detectors and in each element inside detectors list I have a list of memory_cells and best_detector.
But I am getting two types of erros: double free or corruption (!prev) and segmentation fault
I made a research and I know that the first one is caused by trying to free the same address of a pointer twice. And the second is caused when I try to access a memory position wich is not initialized.
I have been trying to figure out why this happens in my code but I don't understand why. Below is my code; I commented the lines of code where the errors occur like this -> // ERROR 1 // ERROR 2
Lists are made from the struct Node like in the Data.h file:
#ifndef DATA
#define DATA
#include <stdbool.h>
struct Node{
double pattern[19];
double bitstring[19];
double affinity;
double fitness;
double radius;
double cost;
bool instance_class; // normal-> false / anomaly-> true
int counter;
int correct; // Number of anomalies correctly identified
int confirm;
struct Node* next;
struct Node* memory_cells;
struct Node* best_detector;
};
typedef struct cells{
double pattern[19];
int confirm;
}cells;
#endif
delete_list method:
void delete_list(struct Node** head_ref)
{
/* deref head_ref to get the real head */
struct Node* current = *head_ref;
struct Node* next;
while (current != NULL)
{
next = current->next; // ERROR 2
free(current); //ERROR 1
current = next;
}
/* deref head_ref to affect the real head back
in the caller. */
*head_ref = NULL;
}
delete_note_list method:
void delete_node_list(struct Node** list){
struct Node* temp = *list;
while(*list != NULL){
delete_list(&((*list)->memory_cells)); // ERROR 1
delete_list(&((*list)->best_detector)); // ERROR 2
*list = (*list)->next;
}
*list = temp;
delete_list(list);
}
insert_list method:
void insert_list(struct Node** list, double detector[SIZE]){
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
for(int i = 0; i < SIZE; i++){
temp -> pattern[i] = detector[i];
temp -> bitstring[i] = doubleToBinary(detector[i]);
}
temp->memory_cells = NULL;
temp->best_detector = NULL;
temp->affinity = 0.0;
temp->fitness = 0.0;
temp->radius = 0.0;
temp->cost = 0.0;
temp->counter = 0;
temp->correct = 0;
temp->confirm = 0;
temp -> next = *list;
*list = temp;
}
insert_memory_cells method:
void insert_memorycell(struct Node** list, double pattern[SIZE]) {
struct Node* cell = (struct Node*)malloc(sizeof(struct Node));
for(int i = 0; i < SIZE; i++){
cell -> pattern[i] = pattern[i];
cell -> bitstring[i] = doubleToBinary(pattern[i]);
}
cell->memory_cells = NULL;
cell->best_detector = NULL;
cell->affinity = 0.0;
cell->fitness = 0.0;
cell->radius = 0.0;
cell->cost = 0.0;
cell->counter = 0;
cell->correct = 0;
cell->confirm = 0;
cell->next = (*list)->memory_cells;
(*list)->memory_cells = cell;
}
insert_best_detector method:
void insert_best_detector(struct Node** list, double pattern[SIZE]) {
struct Node* cell = (struct Node*)malloc(sizeof(struct Node));
for(int i = 0; i < SIZE; i++){
cell -> pattern[i] = pattern[i];
cell -> bitstring[i] = doubleToBinary(pattern[i]);
}
cell->memory_cells = NULL;
cell->best_detector = NULL;
cell->affinity = 0.0;
cell->fitness = 0.0;
cell->radius = 0.0;
cell->cost = 0.0;
cell->counter = 0;
cell->correct = 0;
cell->confirm = 0;
cell->next = (*list)->best_detector;
(*list)->best_detector = cell;
}
main program:
/****************** CLIENT CODE ****************/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<string.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "NSA_NSL_KDD.h"
#include "CLONALG_NSL_KDD.h"
#include "aiNet_NSL_KDD.h"
#include "SortingLists.h"
#include "TCPClient.h"
#include "TCPCommunication.h"
#define TRUE 1
#define FALSE 0
#define PORT 9005
#define MAX_DETECTORS 300
void initialization_phase(struct Node** detectors, struct Node** recv_memory_cells, struct Node* self_dataset, int iteration, int max_detectors){
int received_antigen = list_size(*recv_memory_cells);
if(iteration == 0){
negative_selection(detectors, self_dataset, max_detectors);
}else{
//insert received memory cells in detectors list
struct Node* temp = *recv_memory_cells;
while(temp != NULL){
insert_list(detectors, temp->pattern);
set_detector_radius(detectors, self_dataset);
temp = temp->next;
}
delete_node_list(recv_memory_cells);
negative_selection(detectors, self_dataset, max_detectors - received_antigen);
}
}
void detection_phase(struct Node** detectors, struct Node* dataset){ //Negative selection
struct Node * temp = *detectors;
struct Node * temp2 = dataset;
while(*detectors != NULL){
while(dataset != NULL){
if(euclidian_distance(dataset->pattern, (*detectors)->pattern) < (*detectors)->radius){
(*detectors)->counter += 1;
insert_memorycell(detectors, dataset->pattern);
if(dataset->instance_class)
(*detectors)->correct += 1;
}
dataset = dataset->next;
}
*detectors = (*detectors)->next;
dataset = temp2;
}
*detectors = temp;
}
void calculation_phase(struct Node** detectors, char* file_name){
int lines = 0;
int lineCount = 0;
int self_antigen_num = 0;
int non_self_antigen_num = 0;
char * lastAttribute;
FILE * f_Calculation_Phase_Pointer = fopen(file_name, "r");
lineCount = GetFileLines(file_name);
struct Node* temp = *detectors;
// get self_antigen_num and non_self_antigen_num values
while(lines < lineCount){
lastAttribute = GetInstanceClass(&f_Calculation_Phase_Pointer);
lines++;
if(strncmp(lastAttribute,"normal",6) == 0)
self_antigen_num++;
else
non_self_antigen_num++;
}
printf("\nself antigen num: %d\n", self_antigen_num);
printf("non self antigen num: %d\n", non_self_antigen_num);
// calculate each detector's fitness
while(*detectors != NULL){
if(non_self_antigen_num > 0)
(*detectors)->fitness = (double)(*detectors)->correct/(double)non_self_antigen_num;
else
(*detectors)->fitness = 0.0;
*detectors = (*detectors)->next;
}
*detectors = temp;
fclose(f_Calculation_Phase_Pointer);
}
void selection_phase(struct Node* detectors, struct Node** best_detectors, struct Node** judgment_agents){
struct Node* temp = detectors;
double max_fitness = 0.0;
int counter = 0;
int max_counter = 0; // to select judgment_agents
// find max fitness value
while(detectors != NULL){
if(detectors->fitness > max_fitness)
max_fitness = detectors->fitness;
if(max_counter < detectors->counter)
max_counter = detectors->counter;
detectors = detectors->next;
}
detectors = temp;
//find best detectors with the highest fitness
while(detectors != NULL){
if(detectors->fitness == max_fitness){
insert_list(best_detectors, detectors->pattern);
(*best_detectors)->counter = detectors->counter;
(*best_detectors)->fitness = detectors->fitness;
(*best_detectors)->radius = detectors->radius;
struct Node* temp2 = detectors->memory_cells;
while(detectors->memory_cells != NULL){
insert_memorycell(best_detectors, detectors->memory_cells->pattern);
detectors->memory_cells = detectors->memory_cells->next;
}
detectors->memory_cells = temp2;
}
detectors = detectors->next;
}
//find best detector
if(list_size(*best_detectors) > 1){
struct Node* temp2 = NULL;
while(*best_detectors != NULL){
if((*best_detectors)->counter >= counter){
counter = (*best_detectors)->counter;
temp2 = *best_detectors;
}
*best_detectors = (*best_detectors)->next;
}
//list best_detectors with only the best detector
delete_node_list(best_detectors);
*best_detectors = temp2;
delete_node_list(&((*best_detectors)->next));
}
//select judgment agents
detectors = temp;
int n = list_size(detectors)/2;
int i = 0;
while(i < n){
while(detectors != NULL){
int c = 0;
if(max_counter > 0)
c = rand()%max_counter;
if(detectors->counter >= c && !euclidian_distance_match_list(*judgment_agents, detectors->pattern, 0.0)
&& !cell_equal((*best_detectors)->pattern, detectors->pattern)){
insert_list(judgment_agents, detectors->pattern);
i++;
}
detectors = detectors->next;
}
detectors = temp;
}
}
void detection_phase_2(struct Node** judgment_agents, struct Node** detectors, struct Node* best_detector){ //clonal selection
struct Node* temp = *judgment_agents;
while(*judgment_agents != NULL){ //informed by best detector
insert_best_detector(judgment_agents, best_detector->pattern);
*judgment_agents = (*judgment_agents)->next;
}
*judgment_agents = temp;
while(*judgment_agents != NULL){ //Mutating -> Moving near best agent
//mutating one clone instance in clones each time function is called
hypermutate(judgment_agents);
*judgment_agents = (*judgment_agents)->next;
}
*judgment_agents = temp;
//Sorting by fitness and fixing agents control population
sort_fitness(detectors);
}
void judgment_phase(struct Node** judgment_clones, struct Node** memory_cells, struct Node* self_dataset){ //Immune Network
//set judgment_clones radius
struct Node* temp = *judgment_clones;
while(*judgment_clones != NULL){
set_detector_radius(judgment_clones, self_dataset);
*judgment_clones = (*judgment_clones)->next;
}
*judgment_clones = temp;
struct Node* temp2 = *memory_cells;
while(*judgment_clones != NULL){
while(*memory_cells != NULL){
if(euclidian_distance((*judgment_clones)->pattern, (*memory_cells)->pattern) < (*judgment_clones)->radius)
(*memory_cells)->confirm += 1;
*memory_cells = (*memory_cells)->next;
}
*memory_cells = temp2;
*judgment_clones = (*judgment_clones)->next;
}
*judgment_clones = temp;
*memory_cells = temp2;
sort_confirm(memory_cells);
}
int main(){
srand ( time(NULL) );
struct Node* detectors = NULL;
struct Node* self_dataset = NULL;
struct Node* train_dataset = NULL;
struct Node* best_detector = NULL;
struct Node* judgment_agents = NULL;
struct Node* recv_memory_cells = NULL;
struct Node* final_detectors = NULL;
double max_fitness = 0.0;
const int max_detectors = 150; //Number of cells to send or receive
//generate datasets...
generate_dataset(&self_dataset, "Self_Dataset.txt");
generate_dataset(&train_dataset, "Dataset.txt");
start_connection();
double accuracy = -1;
for(int iteration = 0; iteration < ITERATIONS; iteration++){
printf("\niteration: %d\n", iteration);
//delete lists
if(iteration != 0){
delete_node_list(&detectors); // ERROR 2
delete_node_list(&judgment_agents);
delete_node_list(&best_detector); // ERROR 1 when iteraton == 1
}
//--- deleted lists
initialization_phase(&detectors, &recv_memory_cells, self_dataset, iteration, max_detectors);
detection_phase(&detectors, train_dataset);
calculation_phase(&detectors, "Dataset.txt");
selection_phase(detectors, &best_detector, &judgment_agents);
if(get_detectors_accuracy(detectors, train_dataset) > get_detectors_accuracy(final_detectors, train_dataset)){
delete_node_list(&final_detectors);
struct Node* temp = detectors;
while(temp != NULL){
insert_list(&final_detectors, temp->pattern);
final_detectors->fitness = temp->fitness;
final_detectors->counter = temp->counter;
final_detectors->correct = temp->correct;
final_detectors->radius = temp->radius;
temp = temp->next;
}
}
detection_phase_2(&judgment_agents, &detectors, best_detector);
judgment_phase(&judgment_agents, &best_detector->memory_cells, self_dataset);
client(best_detector->memory_cells, &recv_memory_cells, max_detectors);
}
close_client();
sort_fitness(&final_detectors);
printf("\nFINAL DETECTORS\n\n");
print_list(final_detectors);
print_detectors_performance(final_detectors, train_dataset);
return 0;
}
Here is a doubly linked list, with the node/link carrying the information needed in order to be stored in the list (intrusive):
dlist.h:
#ifndef DLIST_H
#define DLIST_H
//--------------------------------------------------------------------------
typedef struct Link
{
struct Link* succ;
struct Link* prev;
} Link;
//--------------------------------------------------------------------------
typedef struct List
{
Link* first;
Link* last;
} List;
//--------------------------------------------------------------------------
void init(List* lst)
{
assert(lst);
lst->first = 0;
lst->last = 0;
}
//--------------------------------------------------------------------------
List* create()
{
List* lst = (List*) malloc(sizeof(List*));
init(lst);
return lst;
}
//--------------------------------------------------------------------------
void push_back(List* lst, Link* l)
{
assert(l);
assert(lst);
{
Link* last = lst->last;
if (last)
{
last->succ = l;
l->prev = last;
}
else
{
lst->first = l;
l->prev = 0;
}
lst->last = l;
l->succ = 0;
}
}
//--------------------------------------------------------------------------
void clear (List* lst)
{
assert(lst);
{
Link* curr = lst->first;
Link* next = 0;
while (curr)
{
next = curr->succ;
free(curr);
curr = next;
}
lst->first = 0;
lst->last = 0;
}
}
//--------------------------------------------------------------------------
void destroy (List* lst)
{
assert(lst);
clear(lst);
free(lst);
}
//--------------------------------------------------------------------------
typedef struct Name
{
Link l;
char* s;
} Name;
//--------------------------------------------------------------------------
Name* make_name(char* str)
{
Name* n = (Name*) malloc(sizeof(Name*));
n->s = str;
return n;
}
//--------------------------------------------------------------------------
#endif
main.c:
#include <stdlib.h> // malloc
#include <stdio.h> // printf
#include <assert.h> // assert
#ifdef __cplusplus
#else // compiling in C.
int main ()
{
List* lst = create();
char* names[ ] = { "Giorikas", "Kostikas", "Foo", "Bar", "Gosho", "Pesho" };
char* name;
int i = 0;
int size = 6;
for (i; i < size; ++i)
{
push_back(lst, (Link*)(make_name(names[i])));
name = ((Name*)(lst->last))->s;
printf("Name: %s \n", name);
}
destroy(lst);
getchar();
return 0;
}
#endif
Stepping with the debugger I get the names printed and in function clear(), at the first attempt of freeing a link, I get two warnings and finally:
_CrtIsValidHeapPointer(pUserData)
Note: after a bit of research I understand that: "you'll receive heap corruption not immediately on rewrite occurs, but on the next heap check, which will be performed on any next memory allocation/deallocation.". So, probably, what happens in clear()is the heap check that triggers the error.
Where is this heap corruption taking place?
You make bad allocations. You need to allocate objects not pointer to, so:
List* lst = (List*) malloc(sizeof(List*));
should be
List* lst = (List*) malloc(sizeof(List));
and the same for Nameat least. You can also remove the cast:
List* lst = malloc(sizeof(List));
-----EDIT----
and a much better idiom is:
List* lst = malloc(sizeof(*lst));
Write a function that rearranges a linked list to put the nodes in even positions after the nodes in odd positions in the list, preserving the relative order of both the evens and the odds.
I found this problem in the book Algorithm in c writtern by Sedgewick. I have tried but failed. I trid to put all nodes in even positions on another linked list. It's grateful for you to help me. A good idea is enough. Thanks :).
This is my Code in C.
/*
* File: rearranges.c <Exercise 3.36>
* Note: Write a function that rearranges a linked list to put the nodes in even
* positions after the nodes in odd positions in the list, preserving the
* relative order of both the evens and the odds.
* NOTICE: I think it's necessary to use linked list with a dummy head.
* Time: 2013-10-26 10:58
*/
#include <stdio.h>
#include <stdlib.h>
#define LEN 11
typedef struct node *link;
struct node {
int item;
link next;
};
/* Traverse a linked list with a dummy head. */
void traverse(link t) {
link x = t->next;
while (x != NULL) {
printf("%d ", x->item);
x = x->next;
}
putchar('\n');
}
/* Detach even positon nodes from a linked list. */
link detach(link t) {
link u = malloc(sizeof(*u));
link x = t, y = u;
/* x is odd position node. We should ensure that there's still one even
* position node after x. */
while (x != NULL && x->next != NULL) {
y->next = x->next;
x->next = x->next->next;
x = x->next;
y = y->next;
y->next = NULL;
}
return u;
}
/* Combine two linked list */
link combine(link u, link t) {
link x = u;
link y = t->next;
while (y != NULL) {
link n = y->next;
y->next = x->next;
x->next = y;
x = x->next->next;
y = n;
}
return u;
}
/* The function exchanges the position of the nodes in the list. */
link rearranges(link t) {
link u = detach(t);
link v = combine(u, t);
return v;
}
int main(int argc, char *argv[]) {
int i;
link t = malloc(sizeof(*t));
link x = t;
for (i = 0; i < LEN; i++) {
x->next = malloc(sizeof(*x));
x = x->next;
x->item = i;
x->next = NULL;
}
traverse(t);
traverse(rearranges(t));
return 0;
}
curr=head;
end=lastOfList;//last node if size of list is odd or last-1 node
for(int i=1;i<=listSize()/2;i++)
{
end->next=curr->next;
end=end->next;
end->next=null;
if(curr->next!=null)
if((curr->next)->next!=null)
curr->next=(curr->next)->next;
curr=curr->next;
}
You can implement a recursive solution where each call returns an updated node that will serve as the new next reference for the upper caller. We just have to go down the list until we find the last element, and then move every even node to the end of the list, and update the reference to the last element. Here's my solution (please try to do it yourself before looking at my and other solutions):
struct node {
int val;
struct node *next;
};
struct node *reorder_aux(struct node *l, int count, struct node **last);
struct node *reorder(struct node *l) {
struct node *x;
if (l == NULL)
return NULL;
return reorder_aux(l, 1, &x);
}
struct node *reorder_aux(struct node *l, int count, struct node **last) {
struct node *n;
if (l->next == NULL) {
*last = l;
return l;
}
n = reorder_aux(l->next, count+1, last);
if (count & 1) {
l->next = n;
return l;
}
else {
(*last)->next = l;
l->next = NULL;
*last = l;
return n;
}
}
At each step, if the current node l is an even node (as determined by count), then we append this node to the end, and tell the upper caller that its next pointer shall be updated to our next (because our next will be an odd node). In case we're an odd node, we just have to update our next pointer to whatever the recursive call returned (which will be a pointer to an odd node), and return the current node, since we will not move ourselves to the end of the list.
It's a nice exercise!
#include <stdio.h>
struct list {
struct list *next;
int ch;
};
void swap_odd_even (struct list **pp)
{
struct list *one, *two ;
for( ; (one = *pp) ; pp = &one->next) {
two = one->next;
if (!two) break;
*pp = two;
one->next = two->next;
two->next = one;
}
}
struct list arr[] =
{ {arr+1, 'A'} , {arr+2, 'B'} , {arr+3, 'C'} , {arr+4, 'D'}
, {arr+5, 'E'} , {arr+6, 'F'} , {arr+7, 'G'} , {arr+8, 'H'}
, {arr+9, 'I'} , {arr+10, 'J'} , {arr+11, 'K'} , {arr+12, 'L'}
, {arr+13, 'M'} , {arr+14, 'N'}, {arr+15, 'O'} , {arr+16, 'P'}
, {arr+17, 'Q'} , {arr+18, 'R'} , {arr+19, 'S'} , {arr+20, 'T'}
, {arr+21, 'U'} , {arr+22, 'V'}, {arr+23, 'W'} , {arr+24, 'X'}
, {arr+25, 'Y'} , {NULL, 'Z'} };
int main (void) {
struct list *root , *ptr;
root = arr;
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
printf( "Swap\n" );
swap_odd_even ( &root);
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
return 0;
}
In the following, every time swap_nodes is called another odd sinks to the last sunk odd. The evens are grouped together on each iteration and they bubble up to the end of the list. Here is an example:
/*
[0]-1-2-3-4-5
1-[0-2]-3-4-5
1-3-[0-2-4]-5
1-3-5-[0-2-4]
*/
#include <stdio.h>
#include <stdlib.h>
#define LIST_LENGTH 10
struct node{
int id;
struct node *next;
};
void print_list(struct node *current)
{
while(NULL != current){
printf("node id = %d\n",current->id);
current = current->next;
}
printf("Done\n");
}
struct node *swap_nodes(struct node *head_even, struct node *tail_even, struct node *next_odd)
{
tail_even->next = next_odd->next;
next_odd->next = head_even;
return next_odd;
}
struct node *reorder_list(struct node *head)
{
struct node *head_even;
struct node *tail_even;
struct node *next_odd;
struct node *last_odd;
if(NULL == head->next){
return head;
}
head_even = head;
tail_even = head;
next_odd = head->next;
last_odd = head->next;
head = swap_nodes(head_even, tail_even, next_odd);
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
while (NULL != tail_even->next) {
next_odd = tail_even->next;
last_odd->next = swap_nodes(head_even, tail_even, next_odd);
last_odd = last_odd->next;
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
}
return head;
}
int main(void)
{
int i;
struct node *head = (struct node *) malloc(LIST_LENGTH*sizeof(struct node));
struct node *mem = head;
if(NULL == head){
return -1;
}
struct node *current = head;
for(i=0;i<LIST_LENGTH-1;i++){
current->next = current + 1;
current->id = i;
current = current->next;
}
current->next = NULL;
current->id = i;
head = reorder_list(head);
print_list(head);
free(mem);
return 0;
}
I'm trying to implement sequence_insert_at using the add_to_front function here
Everything before
typedef struct sequence *Sequence;
is pasted from another c file.
void sequence_insert_at(Sequence s, int pos, int item)
{
struct node* temp = s->lst;
for(; pos > 0; --pos)
{
temp = temp->rest;
}
add_to_front(&temp, item);
++s->length;
if(!temp->rest)
{
s->end = temp;
}
//s->lst = temp;
}
I don't know why I keep getting a runtime error. if I clone s->lst and traverse the clone, I'm not modifying the pointer to the node in s, but if I change temp, s->lst should have the reflected changes since the nodes are all linked still. Any ideas as to how to fix this? I tried creating another node that is one before the temp after traversal, and then setting it->rest = temp, but that failed as well.
following mistakes a could spot but only so far to get the main function run
new_sequence does not initialize anything in Sequence it creates. lst is not initialized when you access it in sequence_insert_at
struct node* temp = s->lst;
here how it should look like
Sequence new_sequence()
{
Sequence s = malloc(sizeof(struct sequence));
if(!s)
{
printf("Out of memory. Can't allocate s\n");
exit(EXIT_FAILURE);
}
s->lst = malloc(sizeof(struct node));
if(! s->lst) {
printf("Out of memory. Can't allocate lst\n");
}
s->lst->rest = NULL;
s->length = 0;
return s;
}
also s->lst->rest has to be set to NULL, this is what tells that the list has no more elements an not end witch turns obsolete.
struct sequence
{
struct node* lst;
int length;
};
You should be passing the sequence itself to your functions not a pointer to some internal data in the sequence.
add_to_front(&temp, item);
Your sequence_insert_at function should be the one that can handle any position not add_to_front() so it is easier to call with the position 0 from add_to_front() and your having the the hole work done in one function, not a half here and a half there.
void sequence_insert_at(Sequence s, int pos, int item)
{
if(s && pos <= s->length) {
print_sequence(s);
struct node *newnode = malloc(sizeof(struct node));
if (newnode == NULL) {
printf("ERROR! add_to_front ran out of memory!\n");
exit(EXIT_FAILURE);
}
newnode->first = item;
struct node* temp = s->lst;
struct node* prv = NULL;
for(int i = 0; i < pos; i++) {
printf("skip %d\n", temp->first);
prv = temp;
temp = temp->rest;
}
newnode->rest = temp;
if(pos == 0) {
printf("insert as first\n");
s->lst = newnode;
} else {
printf("insert before %d\n", temp->first);
prv->rest = newnode;
}
++s->length;
}
}
and in add_to_front only one statement is needed
void add_to_front(Sequence s, int item) {
sequence_insert_at(s, 0, item);
}
as for inserting at the back of the list
void add_to_back(Sequence s, int item) {
sequence_insert_at(s, s->length, item);
}
A small test with the main function
void print_sequence(Sequence s)
{
struct node* temp = s->lst;
for(int i = 0; i < s->length; temp = temp->rest) {
printf("%d ", temp->first);
i++;
}
printf("\n");
}
int main()
{
Sequence derp = new_sequence();
sequence_insert_at(derp, 0, 14);
add_to_front(derp, 16);
sequence_insert_at(derp, 0, 17);
sequence_insert_at(derp, 2, 15);
add_to_back(derp, 13);
print_sequence(derp);
delete_sequence(derp);
return 0;
}
output is:
17 16 15 14 13
You'll have to go trough the other functions and fix them.
Finally i should note that variable names you have choosen are little bit confusing if not misleading, i would name them this way
typedef struct node {
int data; /* the data that a node holds */
struct node* next; /* the pointer to the next node */
} Node_t;
typedef struct sequence {
struct node* head; /* head or first element of the sequence/list */
int length; /* length is ok but size is better */
} Sequence_t;
I have a linked list with a hash table in each node. The hash table is implemented by an array of pointers to structs. The whole management of this is made by a global static pointer to the linked list.
I changed a little bit the question! Now the question is more focused.
in the lookup and insert function to make the code shorter I assign
temp = cur_table->symbols_table[entry];
but I see that temp gets NULL all the time.
I can't understand why is that happens?
The code is below in 3 modules.
Thank you in ahead.
symbols.h file:
#include <stdlib.h>
#include <stdio.h>
#define TABLE_SIZE 26
typedef struct symbol_node
{
char* name;
int type;
int role;
struct symbol_node* next;
} symbol_node;
typedef struct table_node
{
struct symbol_node* symbols_table[TABLE_SIZE];
struct table_node* prev;
struct table_node* next;
} table_node;
static struct table_node* cur_table;
//functions declarations:
void init_table();
int hash_function(char* id);
symbol_node* lookup(char* id_name);
symbol_node* insert(char* id_name);
// debug
void printtable();
symbols.c
void init_table() // creates the first node
{
int i = 0;
cur_table = NULL;
cur_table = (table_node*)malloc(sizeof(table_node));
cur_table->prev = NULL;
cur_table->next = NULL;
for(i=0; i < TABLE_SIZE; i++)
{
cur_table->symbols_table[i] = NULL;
}
}
symbol_node* lookup(char* id_name) // returns null if the id name not found
{
symbol_node* result = NULL;
symbol_node* temp = NULL;
int entry = atoi(id_name);
temp = cur_table->symbols_table[entry];
while(temp != NULL)
{
if( strcmp( id_name, temp->name ) == 0 )
{
result = temp;
break;
}
else
temp = temp->next;
}
return result;
}
symbol_node* insert(char* id_name)
{
symbol_node* result = NULL;
symbol_node* temp = NULL;
int index = -1;
if(lookup(id_name)==NULL)
{
index = atoi(id_name);
temp = cur_table->symbols_table[index];
while(temp!=NULL)
{
temp = temp->next;
}
temp = (symbol_node*)malloc(sizeof(symbol_node));
temp->next = NULL;
temp->name = id_name;
// TODO: other params
result = temp;
}
return result;
}
void printtable()
{
int i=0;
for(i=0; i<TABLE_SIZE; i++)
{
if(cur_table->symbols_table[i]==NULL)
printf("NULL at index %d\n",i);
else
printf("There are something\n");
}
}
main.c
void main()
{
int i=0;
symbol_node* t = NULL;
symbol_node* tt = NULL;
init_table();
t = insert("markhit");
t = insert("mark");
tt = lookup("mark");
printtable();
_getch();
free(t);
free(tt);
free(cur_table);
}
avoid memory allocation [`malloc'] statically. try it
cur_table = new table_node;
for statically allocated memory, you can not set your value for memory reason. when you are inserting it is not reallocating your cur_table