linked-list queue, endless loop - c

I use nested structure to define the linked-list queue:
queue.h:
#define QUEUE_MAX_SIZE 4096
struct QUEUE_NODE {
char *string;
struct QUEUE_NODE *next;
}queue_node;
struct COMMON_QUEUE {
struct QUEUE_NODE *q_node;
}common_queue;
=================================
queue.c:
/* here I define the operations */
struct COMMON_QUEUE *C_init_queue() {
struct QUEUE_NODE *head;
head = malloc(sizeof(struct QUEUE_NODE));
if (head==NULL) {
fprintf(stderr, "Insufficient memory!!!");
return NULL;
}
struct COMMON_QUEUE *new_queue;
new_queue = malloc(sizeof(struct COMMON_QUEUE));
if (new_queue==NULL) {
fprintf(stderr, "Insufficient memory!!!");
return NULL;
}
head->next = NULL;
head->string = NULL;
new_queue->q_node = head;
return new_queue;
}
int C_get_queue_length(struct COMMON_QUEUE *q) {
int count;
count = 0;
while (q->q_node->next!=NULL) {
count += 1;
q->q_node = q->q_node->next;
}
return count;
}
int C_enqueue(struct COMMON_QUEUE *q, char *in) {
if (C_get_queue_length(q)>=QUEUE_MAX_SIZE) {
fprintf(stderr, "Linked queue is full!!!");
return ERROR;
}
struct QUEUE_NODE *new_node;
new_node = malloc(sizeof(struct QUEUE_NODE));
if (new_node==NULL) {
return ERROR;
}
new_node->next = NULL;
new_node->string = NULL;
while (q->q_node->next!=NULL) {
q->q_node = q->q_node->next;
}
new_node->next = q->q_node->next;
q->q_node->next = q->q_node;
new_node->string = in;
return OK;
}
but when I use it in the main program, then it jumps into a endless loop, after backtracing, and I knew the problem is at:
while (q->q_node->next!=NULL) {
count += 1;
q->q_node = q->q_node->next;
}
but it seems correct, but I may make some mistake on my initialization of the two nested struct!
P.S. the I did not list the "free()".

This loop modifies the list while it traverses it. Specifically, it replaces q->q_node with q->q_node->next, which if nothing else will discard your entire loop.
while (q->q_node->next!=NULL) {
count += 1;
q->q_node = q->q_node->next;
}
If you want to correctly traverse the list, you need to declare a separate pointer that you use for traversal. Something like this:
int C_get_queue_length(struct COMMON_QUEUE *q) {
int count;
struct COMMON_QUEUE *p = q->q_node;
count = 0;
while (p->next != NULL) {
count += 1;
p = p->next;
}
return count;
}
The pointer p will step along the list without modifying the q_node pointers along the way.
You have a similar error in C_enqueue. You really want to use a separate pointer to walk the list, and not assign q->q_node during traversal. You can fix your C_enqueue similarly:
p = q->q_node;
while (p->next != NULL) {
p = p->next;
}
p->next = new_node; /* append the new node after where the list traversal stopped */
new_node->next = NULL; /* always NULL, because you always insert at the end */

One problem with your code is that your iterations through the queue are destructive: rather than using a temporary variable to iterate your linked list, you perform the iteration using the q_node itself. This leads to C_get_queue_length calls effectively destroying the queue, without freeing its nodes (a memory leak).
Here is an example of how to iterate a list non-destructively, using your "get length" method:
int C_get_queue_length(struct COMMON_QUEUE *q) {
int count;
count = 0;
struct QUEUE_NODE node = q->q_node;
while (node->next != NULL) {
count++;
node = node->next;
}
return count;
}
Your decision to pre-allocate one node when creating a queue is also questionable: it appears that the head node is unused, and also excluded from the count. This makes it easier to write the code to insert and delete nodes, but the same could be done with an extra level of indirection (i.e. a pointer to a pointer).

Related

I am implementing a doubly linked list in C, and having segmentation fault in a destroy function

I divided the code in two files, .h and .c
The definition of function names is in .h, the implementation of the function is in .c
in my main file:
struct no
{
tipo info;
struct no *ant;
struct no *nxt;
};
struct list
{
no_t *head;
no_t *tail;
int size;
};
this is in my .h file:
typedef struct no no_t;
typedef struct list list_t;
typedef int tipo;
...again in main
void list_destroy(list_t **l)
{
if ((*l) == NULL || l == NULL)
return;
if (!(*l)->head)
return;
no_t *next = (*l)->head; //create two variables for iterating through the list
no_t *aux; //set aux to free
while (next->nxt) //the pointer for next node, in the last node, is NULL
{ //by that I believe I'm able to iterate through all nodes
aux = next;
free(aux);
next = next->nxt;
}
free(*l);
(*l) = NULL;
}
is quite a simple code, but I can't see where I'm missing here
next = next->nxt;
For the compiler it makes no difference, for sure. But for someone, even you, it is hard to read this next = next->nxt stuff. Or is it is not?
A possible alternative (using your code) and a short test program
so_list.h
#include <stdio.h>
#include <stdlib.h>
typedef int Tipo;
typedef struct st_no
{
Tipo info;
struct st_no* prev;
struct st_no* next;
} Node;
typedef struct
{
Node* head;
Node* tail;
unsigned size;
} List;
List* list_create();
List* list_destroy(List*);
int list_insert(const Tipo, List*);
In the header, only typedefs and the function prototypes.
names with only the first letter in uppercase are reserved here for defined names. An useful convention.
instead of using List** is often clearer to just return the pointer to the list. In this way it is easier for example to invalidate the pointer and to create the linked lists as in
List* my_list = list_create();
my_list = list_destroy(my_list);
and there is no need to test the two levels of indirection as you need when ** is used
main.c: a minimalist test set
#include "so-list.h"
int main(void)
{
List* my_list = list_create();
my_list = list_destroy(my_list);
my_list = list_create();
for (int i = 1; i <= 5; i += 1)
printf("insert(%d,list) returned %d\n",
i, list_insert(i,my_list)
);
my_list = list_destroy(my_list);
my_list = list_create();
for (int i = 11; i <= 15; i += 1)
printf("insert(%d,list) returned %d\n",
i, list_insert(i, my_list)
);
my_list = list_destroy(my_list);
return 0;
}
A list is created, then destroyed
using the same pointer, a list is created, values 1 to 5 are inserted ant then the list is deleted.
using the same pointer, a list is created, values 11 to 15 are inserted ant then the list is again deleted.
the output
List created!
List deleted!
List created!
insert(1,list) returned 1
insert(2,list) returned 2
insert(3,list) returned 3
insert(4,list) returned 4
insert(5,list) returned 5
1 deleted
2 deleted
3 deleted
4 deleted
5 deleted
List deleted!
List created!
insert(11,list) returned 1
insert(12,list) returned 2
insert(13,list) returned 3
insert(14,list) returned 4
insert(15,list) returned 5
11 deleted
12 deleted
13 deleted
14 deleted
15 deleted
List deleted!
code for destroy_list()
List* list_destroy(List* l)
{
if (l == NULL) return NULL;
// delete the ´size´ nodes, 1 by 1
Node* p = NULL;
for (unsigned i = 0; i < l->size; i += 1)
{
p = l->head->next; // save pointer
printf("%d deleted\n", l->head->info); // just for the demo
free(l->head); // free head
l->head = p; // advance head
}
free(l); // free list
printf("List deleted!\n\n"); // just for the demo
return NULL;
}
This function always return NULL as just a way to invalidade the pointer in the caller in the same expression as in pList = destroy_list(pList);
This is somewhat different than the code you wrote. We just delete the elements one by one as we know the list has size elements. A local pointer is used in the loop to save the address of the next element. It seems to be easier to read.
The complete code for so-list.c
#include "so-list.h"
List* list_create()
{
List* one = (List*)malloc(sizeof(List));
one->head = NULL;
one->tail = NULL;
one->size = 0;
printf("List created!\n");
return one;
}
List* list_destroy(List* l)
{
if (l == NULL) return NULL;
// delete the ´size´ nodes, 1 by 1
Node* p = NULL;
for (unsigned i = 0; i < l->size; i += 1)
{
p = l->head->next; // save pointer
printf("%d deleted\n", l->head->info);
free(l->head); // free head
l->head = p; // advance head
}
free(l); // free list
printf("List deleted!\n\n");
return NULL;
}
// just for test, insert ´info´ at the end, returns size
int list_insert(const Tipo info, List* l)
{
// insert node at the end, just for test
Node* one = (Node*)malloc(sizeof(Node));
one->info = info;
one->next = NULL;
one->prev = l->tail;
if (l->size == 0)
l->head = one; // 1st node
else
l->tail->next = one;
l->tail = one;
l->size += 1;
return l->size;
};
about your version of list_destroy()
The logic there is a bit wrong but the error is well described in another answer. I recommend not to use ** in this situations. But it can be done for sure.
so-list.c
This is just a minimum to have a running test
#include "so-list.h"
List* list_create()
{
List* one = (List*)malloc(sizeof(List));
one->head = NULL;
one->tail = NULL;
one->size = 0;
printf("List created!\n");
return one;
}
List* list_destroy(List* l)
{
if (l == NULL) return NULL;
// delete the ´size´ nodes, 1 by 1
Node* p = NULL;
for (unsigned i = 0; i < l->size; i += 1)
{
p = l->head->next; // save pointer
printf("%d deleted\n", l->head->info);
free(l->head); // free head
l->head = p; // advance head
}
free(l); // free list
printf("List deleted!\n\n");
return NULL;
}
// just for test, insert ´info´ at the end, returns size
int list_insert(const Tipo info, List* l)
{
// insert node at the end, just for test
Node* one = (Node*)malloc(sizeof(Node));
one->info = info;
one->next = NULL;
one->prev = l->tail;
if (l->size == 0)
l->head = one; // 1st node
else
l->tail->next = one;
l->tail = one;
l->size += 1;
return l->size;
};
This has an issue
no_t *next = (*l)->head;
no_t *aux;
while (next->nxt)
{
aux = next; // aux point to the same object as next
free(aux); // free aux, which is the same as next
next = next->nxt; // deference next, which just got free'd. OOPS!
}
You invoke free on aux, which is also aliasing next. Then you try to deference next->nxt. Well, next just got released in the previous statement. Also, as I called out in the comment, you are leaking the last element in the list.
Fixed:
no_t* aux = (*l)->head;
while (aux)
{
no_t* next = aux->nxt;
free(aux);
aux = next;
}
You should look to your "free" and your "next->nxt" statements. May it can help you solve it.

Add a list on a trie node in C

I'm adding words (character per node) on a trie data structure - that happens correctly based on a implementantion I found on the web -
http://www.techiedelight.com/trie-implementation-insert-search-delete/
Although I want to extend this and add a list containing some data based on the words, such term frequency etc.
Right now I'm facing an issue with the pointer of the list when adding the first element on a trie node - in the method append_posting_list - and getting a segmetation fault.
Here is the code so far.
main.h
#ifndef TRIE_H
#define TRIE_H
#define CHAR_SIZE 26
typedef struct posting_list {
int doc_id;
int tf;
int df;
struct posting_list *next;
} posting_list_node ;
struct Trie
{
posting_list_node *p_node; // this will be the head of the posting list for every word;
int isLeaf; // 1 when node is a leaf node
struct Trie* character[CHAR_SIZE];
};
struct Trie* getNewTrieNode();
void insert(struct Trie* *head, char* str, int doc_id);
int search(struct Trie* head, char* str);
#endif //TRIE_H
main.c
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
int main(){
struct Trie* head = getNewTrieNode();
insert(&head, "hello", 1);
return 0;
}
// Function that returns a new Trie node
struct Trie* getNewTrieNode()
{
struct Trie* node = (struct Trie*)malloc(sizeof(struct Trie));
node->isLeaf = 0;
for (int i = 0; i < CHAR_SIZE; i++)
node->character[i] = NULL;
return node;
}
posting_list_node* get_mem(){
posting_list_node* p;
p = (posting_list_node *)malloc(sizeof(posting_list_node));
if (p == NULL){
printf("Memory allocation failed\n");
exit(EXIT_FAILURE);
}
return p;
}
void append_posting_list(int doc_id, posting_list_node **n){
posting_list_node *new, *q;
new = get_mem();
new->doc_id = doc_id;
new->tf = 1;
new->next = NULL;
// if new is the first element of the list
if(n == NULL) {
*n = new;
} else {
q = *n;
while( q->next!=NULL) {
q = q->next;
}
q->next = new;
}
}
// Iterative function to insert a string in Trie.
void insert(struct Trie* *head, char* str, int doc_id)
{
// start from root node
struct Trie* curr = *head;
while (*str)
{
// create a new node if path doesn't exists
if (curr->character[*str - 'a'] == NULL)
curr->character[*str - 'a'] = getNewTrieNode();
// go to next node
curr = curr->character[*str - 'a'];
// move to next character
str++;
}
// already found this word, increase frequency
if(curr->isLeaf) {
curr->p_node->tf += 1;
} else {
append_posting_list(doc_id, curr->p_node);
// mark current node as leaf
curr->isLeaf = 1;
}
}
// Iterative function to search a string in Trie. It returns 1
// if the string is found in the Trie, else it returns 0
int search(struct Trie* head, char* str)
{
// return 0 if Trie is empty
if (head == NULL)
return 0;
struct Trie* curr = head;
while (*str)
{
// go to next node
curr = curr->character[*str - 'a'];
// if string is invalid (reached end of path in Trie)
if (curr == NULL)
return 0;
// move to next character
str++;
}
// if current node is a leaf and we have reached the
// end of the string, return 1
return curr->isLeaf;
}
I'm really stuck here.
Any suggestions would be really appreciated.
I found a couple things that when fixed, got rid of your segmentation fault.
In getNewTrieNode() I think you need to set p_node to NULL
struct Trie* getNewTrieNode() {
struct Trie* node = (struct Trie*)malloc(sizeof(struct Trie));
node->isLeaf = 0;
for (int i = 0; i < CHAR_SIZE; i++)
node->character[i] = NULL;
node->p_node = NULL;
return node;
}
append_posting_list() takes post_list_node **, but in insert(), you are passing just post_list_node *
void append_posting_list(int doc_id, posting_list_node **n)
append_posting_list(doc_id, curr->p_node);
looks like it should be
append_posting_list(doc_id, &(curr->p_node));
In append_posting_list()
if (n == NULL) {
should be
if (*n == NULL) {
in order to see if a pointer to an empty list is being passed in.
You should really have some functions to print out your data structure while you are working on it, so you can test each piece as you develop it. Simply compiling and running code and not getting any errors is no gurantee the code is working correctly with complex data structures like this. Making sure that each piece works perfectly before going on to the next piece will save you hours in trying to track down segmentation faults and other errors like this.

Split linked list into half

I am trying to create a function splitlist(), which will split a singly linked list into two sublists – one for the front half, and one for the back half. I have come up with a code below which will work for the first time that I call the function, but when I call the function repeatedly, the program crashes. Any advice on how I can change my code to prevent such an error? The function splitlist() is void as it prints two lists which contains frontList and backList.
typedef struct _listnode {
int item;
struct _listnode *next;
} ListNode;
typedef struct _linkedlist {
int size;
ListNode *head;
} LinkedList;
void splitlist(LinkedList* list1, LinkedList * firsthalf, LinkedList *secondhalf)
{
ListNode *cur = list1->head;
ListNode *front = firsthalf->head;
ListNode *back = secondhalf->head;
int totalnodes = list1->size;
int i;
if (totalnodes % 2 != 0) //if odd number of elements, add 1 to make it easier for traversal of list
{
totalnodes = totalnodes + 1;
}
int halfnodes = totalnodes / 2;
{
for (i = 0; i < halfnodes; i++)
{
if (firsthalf->head == NULL) //initialise the head
{
firsthalf->head = malloc(sizeof(ListNode)); //create first node
front = firsthalf->head;
}
else
{
front->next = malloc(sizeof(ListNode));
front = front->next;
}
front->item = cur->item; // insert value from list1 into firsthalf
cur = cur->next; //point to next node in list1
}
front->next = NULL; //last node
for (i = halfnodes; i < totalnodes; i++)
{
if (secondhalf->head == NULL)
{
secondhalf->head = malloc(sizeof(ListNode));
back = secondhalf->head;
}
else
{
back->next = malloc(sizeof(ListNode));
back = back->next;
}
back->item = cur->item;
cur = cur->next;
}
back->next = NULL;
}
}
There are many things wrong with this code. First of all malloc return values are not checked, malloc can fail. And i strongly suspect that because of malloc fail your programm stops. You repeatedly allocate the memory inside the function, but do you free it when you do not need it anymore? Why do yo use malloc at all?
As posted earlier you do not need to.
Please post how the function is called, because it is really unclear how LinkedList* list1, LinkedList * firsthalf, LinkedList *secondhalf are used. Also it is unclear what is the structure of LinkedList is.
why use malloc?It will create a new list.But we want to split the list.
I guess firsthalf and second half are NULL
void splitlist(LinkedList* list1, LinkedList * firsthalf, LinkedList *secondhalf)
{
ListNode *cur = list1->head;
ListNode *front;
int totalnodes = list1->size;
int i;
if (totalnodes % 2 != 0) //if odd number of elements, add 1 to make it easier for traversal of list
{
totalnodes = totalnodes + 1;
}
int halfnodes = totalnodes / 2;
firsthalf->head=list1->head;
front=firsthalf->head;
for(i=0;i<halfnode;i++)
front=front->next;
secondhalf->head=front->next;
front->next=NULL;
}
At first glance I can't see much wrong with your code (assuming the assignment is to create copies of the list nodes in the new half lists), so the error could be in how you call the function, as an exmple, that could be:
LinkedList mainlist= {0};
LinkedList firsthalf= {0}, secondhalf= {0};
//mainlist got filled somehow; we now want to split
firsthalf->List= malloc(sizeof(ListNode));
secondthalf->List= malloc(sizeof(ListNode));
memset(firsthalf->List, 0, sizeof(ListNode));
memset(secondhalf->List, 0, sizeof(ListNode));
splitlist(&mainlist, &firsthalf, &secondhalf);

Correct Freeing double-linked nodes in C language

I'm pretty new to C world and I don't know how is the correct way to delete this data structure avoiding memory leaks and segmentation faults.
The data structure is this:
typedef struct Node {
int id;
struct Node *parent; /* node's parent */
struct Node *suffix_node;
int first_char_index;
int last_char_index;
bool is_leaf;
struct Node **children; /* node's children */
int children_size; /* size of children structure */
int children_count; /* # of children */
int depth;
}Node;
typedef struct SuffixTree {
Node *root;
int nodes_count;
char *string;
}SuffixTree;
What I would do is, from a pointer to SuffixTree structure, freeing entirely tree.
I have tried to do this:
void deleteSubTree(Node *nd)
{
if (nd->is_leaf)
{
free(nd->children);
free(nd);
return;
}
int i = 0;
for(;i < nd->children_count; ++i)
{
deleteSubTree(nd->children[i]);
}
free(nd->children);
free(nd);
return;
}
void deleteSuffixTree(SuffixTree *st)
{
deleteSubTree(st->root);
free(st);
}
But it is not correct.
EDIT:
This is main:
int main()
{ char *str = "BOOK\0";
SuffixTree *st = createSuffixTree(str);
deleteSuffixTree(st);
return 0;
}
And this is how I allocate tree and nodes:
Node* createNode(){
Node *stn = (Node*)malloc(sizeof(Node));
stn->id = node_id++;
stn->parent = (Node*)malloc(sizeof(Node));
stn->suffix_node = (Node*)malloc(sizeof(Node));
stn->first_char_index = -1;
stn->last_char_index = -1;
stn->children_size = NODE_BASE_DEGREE;
stn->children_count = 0;
stn->children = (Node**)malloc(stn->children_size*sizeof(Node*));
stn->is_leaf = true;
stn->depth = 1;
return stn;
}
SuffixTree* createSuffixTree(char *str)
{
SuffixTree *st = (SuffixTree*)malloc(sizeof(SuffixTree));
st->root = createNode();
st->root->parent = (Node*)malloc(sizeof(Node));
st->root->parent->id = -1;
st->nodes_count = 1;
st->string = str;
makeTreeWithUkkonen(st);
return st;
}
makeTreeWithUkkonen is correct, I can display correct tree after createSuffixTree() call.
As GeoMad89 said, you malloc already existing nodes in the createNode() method.
If you change your createNode() code into this:
Node* createNode(Node* parent, Node* suffixNode){
Node *stn = (Node*)malloc(sizeof(Node));
stn->id = node_id++;
stn->parent = parent; //(Node*)malloc(sizeof(Node));
if(suffixNode != NULL)
stn->suffix_node = suffixNode; //(Node*)malloc(sizeof(Node));
stn->first_char_index = -1;
stn->last_char_index = -1;
stn->children_size = NODE_BASE_DEGREE;
stn->children_count = 0;
stn->children = (Node**)malloc(stn->children_size*sizeof(Node*));
if(parent != NULL){
parent->children[parent->children_count++] = stn;
parent->is_leaf = false;
}
stn->is_leaf = true;
stn->depth = 1;
return stn;
}
And if you try it with valgrind, using this toy main:
main(int argc, char** argv){
Node* root = createNode(NULL, NULL);
Node* node1 = createNode(root, NULL);
Node* node2 = createNode(root, NULL);
Node* node3 = createNode(node1, NULL);
deleteSubTree(root);
return 0;
}
You will see that all the malloc'd memory will be freed!
Needless to say, this code works only with NODE_BASE_DEGREE=2, otherwise, if you use a greater NODE_BASE_DEGREE value, you have to realloc the children array.
I have noticed that the leaf nodes have their children array not empty, because children_size is equal to NODE_BASE_DEGREE.
Try to delete the elements of the array in the leaves before eliminating them.
I have noticed two possible memory leaks:
In createNode, i suppose that the parent of the node that you going to create already exist, there is no need to malloc a space for it. But anyway you change the value of the pointer of parent in createSuffixTree, at least in the root of the tree, so this memory that you have allocated in createNode for parent is lost.
I don't know what suffix_node is, if is a node of the tree there is the same problem of the point one. But if is another node and so it is correct allocate memory, you don't freed when deleted the tree.

Sequence insert at arbitrary index implemented with Linked list

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;

Resources