I'm trying to recurvisely implement an insert function in C, but I'm having all sorts of issues. I'm in an intro CS class and they started throwing C labs at us before we had ever worked with it before. Part of the issue is that the list pointer is not being recognized as NULL and I'm also pretty sure that I'm using malloc improperly.
#include <stdio.h>
#include <stdlib.h>
#define True 1
#define False 0
typedef int BOOLEAN;
struct Node{
int value;
struct Node *next;
};
void insert(int x, struct Node **pL){
printf("insert\n");
if(*pL == NULL){
printf("inside if\n");
struct Node *pN;
pN = (struct Node*) malloc(sizeof(struct Node));
(*pN).value = x;
(*pN).next = NULL;
return;
}
if (*pL != NULL){
printf("inside else\n");
insert(x, &(((*pL)->next)));
}
printf("end insert\n");
};
void printList(struct Node *L){
while (L != NULL){
printf("%d", (*L).value);
printList((*L).next);
}
return;
};
main(){
printf("main\n");
struct Node* L;
//L).next = NULL;
int i;
printf("for loop\n");
for (i = 3; i < 20; i+=2){
printf("%d\n", i);
insert(i, &L);
}
printList(L);
};
First of all, in main you need to initialise L:
struct Node* L = NULL;
Second, in insert when you allocate the new node pN, you are not assigning it to the pL, i.e., it doesn't get inserted. Put this right before the return; in insert:
*pL = pN;
(Also you could remove the return and change if (*pL != NULL) into else.)
Then, in printList you are both iterating with a while loop, and with recursion. Choose one, not both, e.g.,:
while (L) {
printf("%d\n", L->value);
L = L->next;
}
Also, throughout your code you can replace (*pointer_to_struct).field with pointer_to_struct->field for better style.
Related
This is my program I have written in C, I created a structure and a head and I am trying to make a linked list, but I keep getting read access violations and it seems I am not passing in my head pointer properly and it keeps having problems when it is trying to add to my list.
#define _CRT_SECURE_NO_WARNINGS // Since I want to strictly use ANSI C and not Microsoft C without getting the warning message, I'm adding this line of code before I include header files.
#include <stdio.h> // "#include" includes the contents of another file, commonly called header file, into the source code file.
#include <string.h> // This library contains a variety of functions to manipulate strings.
#include <stdlib.h> // Header file which has the necessary information to include the input/output related functions in our program.
#define MAX 100
typedef struct node {
char model[MAX];
float price;
int miles;
struct node *next;
} *NODEPTR;
NODEPTR getNode();
void freeNode(NODEPTR p);
void printTotalMiles(NODEPTR);
void addLast(NODEPTR *list, char c[], float pri, int num);
int main(void) { //It is the first function of every C program that is responsible for starting the execution and termination of the program.
int i = 0;
NODEPTR head = NULL;
if (head == NULL) {
printf("NULL");
}
//head = (NODEPTR) malloc(sizeof(struct node));
//head->next = NULL;
//addFront(head, 2600.00, 48000);
//addFront(head, 1400.00, 22000);
//printf("first, %d", head->price);
addLast(head, "64 Impala", 1800.00, 12000);
addLast(head, "56 Ford", 500.00, 23000);
//printTotalMiles(head);
//printArray(p);
return 0; // This statement indicates "main()" is returning the value 0 upon completion.
} // Curly brace marks the end of the function.
NODEPTR getNode(void) {
NODEPTR p;
p = (NODEPTR)malloc(sizeof(struct node));
if (p == NULL) {
printf("List Overflow.");
}
return (p);
}
void freeNode(NODEPTR p) {
free(p);
}
void addFront(NODEPTR *list, float pri, int num) {
NODEPTR p, q;
p = getNode();
//strcpy(p->model, c);
// memset(p->model, '\0', sizeof(c))
//printf("%s\n", p->model);
p->price = pri;
p->miles = num;
p->next = *list;
*list = p;
q = *list;
printf("hey %.2f hey\n", q->price);
}
void printTotalMiles(NODEPTR *list) {
int total = 0;
NODEPTR p;
while (*list) {
p = *list;
printf(" Car: \tPrice: %.2f\tI drove it: %d\n", p->price, p->miles);
total += p->miles;
list = p->next;
}
printf("The Total Miles: %d", total);
}
void addLast(NODEPTR *list, char c[], float pri, int num) {
NODEPTR p, q;
p = getNode();
memset(p->model, '\0', sizeof(c));
strcpy(p->model, c);
p->price = pri;
p->miles = num;
p->next = NULL;
if (*list == NULL) {
*list = p;
} else {
q = *list;
while (q->next) {
q = q->next;
}
q->next = p;
}
}
//void printArray(struct node cars[]) { //function definition
// break;
//}
How can I get it so I can properly add nodes to this list?
I just want it to add nodes to the list with the character, float and int. I tried messing with the pointers, I tried setting head first and setting head->next to null as well but nothing seems to work. It keeps having errors every time it tries to deal with the null.
void addLast(NODEPTR* list, char c[], float pri, int num);
addLast wants a pointer to pointer (read Is it a good idea to typedef pointers?), but you pass a single pointer here:
addLast(head, "64 Impala", 1800.00, 12000);
addLast(head, "56 Ford", 500.00, 23000);
switch to
addLast(&head, "64 Impala", 1800.00, 12000);
addLast(&head, "56 Ford", 500.00, 23000);
And here:
void addLast(NODEPTR* list, char c[], float pri, int num) {
NODEPTR p, q;
p = getNode();
memset(p->model, '\0', sizeof(c));
strcpy(p->model, c);
sizeof(c) is the size of a pointer (read What is ‘array decaying’ in C?).
Use the size of the member, in this case MAX:
memset(p->model, '\0', MAX);
or better yet: delete the whole line, you don't need it if you call strcpy on the next line.
One more:
void printTotalMiles(NODEPTR* list) {
differs from the propotype:
void printTotalMiles(NODEPTR);
Compile with warnings.
My code has two separate (although likely connected) problems, one of which being that when I print out the linked list (regardless of if I push nodes to the front or to the back), it prints an additional 0 at the start of the linked list. I saw a similar post about this, but the implementation of the push method was different, as it didn't take head as an argument, so I've defined head in the main() method with:
struct node *head = NULL;
and my linked list instantiation looks like
struct node *temp, *ptr;
temp=(struct node*)malloc(sizeof(struct node));
if(temp==NULL) {
exit(0);
}
temp->next=NULL;
if(head==NULL) {
head=temp;
} else {
ptr=head;
while(ptr->next!=NULL) {
ptr=ptr->next;
}
ptr->next=temp;
ptr->data=NULL;
}
The issue I'm having is that I'm not sure whether or not the issue is in the print method, my push front method or my linked list instantiation.
The relevant code is:
case PUSH_FRONT: ; // push onto front of list
struct node *temp1;
temp1=(struct node*)malloc(sizeof(struct node));
if(temp1==NULL) {
break;
}
temp1->next=NULL;
temp1->data=val;
if(head==NULL) {
head=temp1;
} else {
temp1->next=head;
head=temp1;
}
break;
case PRINT_LIST: ; // print list
printf("Elements: ");
struct node *ptr4;
ptr4=(struct node*)malloc(sizeof(struct node));
if(head==NULL) {
break;
} else {
ptr4=head;
while(ptr4) {
printf("%d",ptr4->data);
printf(" ");
ptr4=ptr4->next;
}
printf("\n");
free(ptr4);
}
break;
My other issue (although I'm still convinced that this issue lies elsewhere) is that my pop front method does absolutely nothing, which I'm guessing has to do with the initial instantiation of the linked list. The relevant code is:
case POP_FRONT: ; // remove from front of list
// If list is empty, do nothing.
struct node *ptr2;
ptr2=(struct node *)malloc(sizeof(struct node));
if(ptr2==NULL) {
break;
}
if(head==NULL) {
break;
} else if(head->next==NULL) {
ptr2=head;
head=head->next;
free(ptr2);
}
break;
You should post code someone could download and compile. And when
needed a data file or a description of the problem. Code fragments are
not good.
I believe that the data component of your list is just an int by looking at the code at the label PRINT_LIST
here goes what I think
a list is a collection of nodes. In java a list is even called a collection. In C++ lists are called containers. When you write code for a linked list as if it is a node you will have more work and less results.
as a direct consequence of using a node as a list you have 3 pointers here just to manage the list, in the instantiation code: head, temp and ptr, It is too much. Imagine if there where 3 lists...
a list with pointers only to one direction is harder to program and much less useful than one with pointers to next and previous nodes. If it is your decision may be you should reconsider. If the space of the additional pointer is not a concern, it is hard to justify not to use 2 pointers. Imagine a list for a library, a path,, a playlist, all the classic examples: it is very handful to be able to navigate in both directions.
the use of a switch() is uncommon. Why not just use functions?
back to your code
struct node *temp, *ptr;
temp=(struct node*)malloc(sizeof(struct node));
if(temp==NULL) {
exit(0);
}
temp->next=NULL;
if(head==NULL) {
head=temp;
} else {
ptr=head;
while(ptr->next!=NULL) {
ptr=ptr->next;
}
ptr->next=temp;
ptr->data=NULL;
}
here you write ptr->data = NULL; and we may think that data is a pointer, but in the list label you wrote
ptr4=head;
while(ptr4) {
printf("%d",ptr4->data);
printf(" ");
ptr4=ptr4->next;
}
printf("\n");
free(ptr4);
and data is just an int as you are using %d in the printf(). Well, the NULL in instantiation is, well, a zero.
And that NULL is the 0 you are complaining about.
This code seems to be much more complex and hard to read than it may need to be.
Let me show an alternative
about the declaration
You may write the node struct like
typedef struct _nd
{
int data;
struct _nd* next;
} node;
So you can use node in the declaration and not have to repeat struct at all times. Also it is useful to have a convention for typedef, like using first letter uppercase to help in readability
As I said before a list is a collection of nodes, it is NOT just a node --- with a pointer inside --- and each node has a payload, some data, usually a pointer. As an example consider
an alternate example of list structs
typedef struct _nda
{
int data;
struct _nda* next;
} Node;
struct _the_list
{
char* name;
unsigned size;
unsigned limit;
Node* head;
Node* tail;
};
typedef struct _the_list List;
Here the list is, well, List. And each list has head, tail, size, limit and even a name. I kept data as an int but is is not good: you really want it as a pointer, maybe (void*).
Why? Because in this way you can reuse the code everywhere with no change.
How to use a List like this?
Using functions like these possible prototypes
List* _create(const char*);
int _define_max(List* l, const unsigned);
List* _delete(List*);
int _empty(List*);
int _get_max(List*);
List* _insert_begin(int, List*);
List* _insert_end(int, List*);
int _insert_your_way(List*, int(*)(int,int));
int _print(List*);
int _print_your_way(List*, int(*)(int,int));
List* _remove(int, List*);
int _size(List*);
I will post a running example below just to have something you can test or ask about case you need. But it is the usual. Only these two functions are less usual, but more useful:
int _insert_your_way(List*, int(*F)(int,int));
int _print_your_way(List*, int(*F)(int,int));
Here you can pass a function like in the qsort() function, and the node is inserted at the position, using the function F() to compare the nodes. The effect is that you can have the nodes inserted (or listed) in any order, with no change in the list code, just by providing different functions to the print or insert function. C does that, C++ does that, everybody does that, so we can too :)
code for instantiating such a list
List* _create(const char* name)
{
List* one = (List*)malloc(sizeof(List));
one->name = (char*)malloc(1 + strlen(name));
strcpy(one->name, name);
one->size = 0;
one->limit = 0;
one->head = NULL;
one->tail = NULL;
return one;
}; // criar()
You may find that writing this way makes easier to maintain or read the code. And the List as a container is much more expressive: metadata about the list in included in the list. No need for ptr, head, temp, size or other controls hanging loose in main()
To create a list you can just write, like in the example
List* first = _create("The First List");
inserting nodes at the beggining
List* _insert_begin(int value, List* l)
{
if (l == NULL) return l; //no list
if ((l->limit > 0) && (l->size == l->limit)) return l; // full
// ok: create a node and stuff data in
Node* nd = (Node*)malloc(sizeof(Node));
nd->data = value; // data comes in
nd->next = l->head; // depois vem o que estava na frente
l->head = nd; // nd fim
l->size = l->size + 1;
// if it is the first node
if (l->size == 1)l->tail = nd;
return l;
};
As I told you this is just a toy, an example. In practice you will use a void* in order to have a generic code. I am using an int as data here, as you did. To insert a few nodes in the list created above you just write
// insert 6,7,8,9,10 at the end
for(int i = 6; i<11; i+=1 ) _insert_end(i, first);
And you can have even an array of lists and all goes well. No external variables to look after. And each list has size updated, head, tail...
printing nodes
print is also easy and can be more expressive, since we have metadata with limits, size, head, tail and even the name for each list.
sample program
int main(void)
{
List* first = _create("The First List");
_print(first);
_define_max(first,300);
_print(first);
// insert 5,4,3,2,1 at the beggining
for(int i = 5; i>0; i-=1 ) _insert_begin(i, first);
// list again
_print(first);
// insert 6,7,8,9,10 at the end
for(int i = 6; i<11; i+=1 ) _insert_end(i, first);
// list again
_print(first);
printf("empty(): %d size()= %d\n",
_empty(first),
_size(first) );
first = _delete(first);
_print(first);
return 0;
}
This code just
create a list and prints the nodes
set the optional limit to 300 nodes
list the nodes
insert 5,4,3,2,1 at the beginning
list the nodes
insert 6,7,8,9,10 at the tail
list the nodes
call a few functions on the list
deletes all data
output
List 'The First List' with 0 elements [MAX not defined yet]
List 'The First List' with 0 of 300 MAX elements
List 'The First List' with 5 of 300 MAX elements
First: 1
Last: 5
Elements
1
2
3
4
5
End of list
List 'The First List' with 10 of 300 MAX elements
First: 1
Last: 10
Elements
1
2
3
4
5
6
7
8
9
10
End of list
empty(): 0 size()= 10
Deleting 'The First List'
List not created!
the code (with almost no testing)
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct _nda
{
int data;
struct _nda* next;
} Node;
struct _the_list
{
char* name;
unsigned size;
unsigned limit;
Node* head;
Node* tail;
};
typedef struct _the_list List;
List* _create(const char*);
int _define_max(List* l, const unsigned);
List* _delete(List*);
int _empty(List*);
int _get_max(List*);
List* _insert_begin(int, List*);
List* _insert_end(int, List*);
int _insert_your_way(List*, int(*)(void*));
int _print(List*);
int _print_your_way(List*, int(*)(void*));
List* _remove(int, List*);
int _size(List*);
int main(void)
{
List* first = _create("The First List");
_print(first);
_define_max(first,300);
_print(first);
// insert 5,4,3,2,1 at the beggining
for(int i = 5; i>0; i-=1 ) _insert_begin(i, first);
// list again
_print(first);
// insert 6,7,8,9,10 at the end
for(int i = 6; i<11; i+=1 ) _insert_end(i, first);
// list again
_print(first);
printf("empty(): %d size()= %d\n",
_empty(first),
_size(first) );
first = _delete(first);
_print(first);
return 0;
}
List* _create(const char* name)
{
List* one = (List*)malloc(sizeof(List));
one->name = (char*)malloc(1 + strlen(name));
strcpy(one->name, name);
one->size = 0;
one->limit = 0;
one->head = NULL;
one->tail = NULL;
return one;
}; // criar()
int _define_max(List* l, const unsigned m)
{
if (l == NULL) return -1;
// new value can not be less than present size
if (l->size > m) return -2;
l->limit = m;
return m;
};
List* _delete(List* l)
{
if (l == NULL) return NULL;
printf("Deleting '%s'\n", l->name);
free(l->name);
if (l->size == 0)
{
free(l);
return NULL; // empty
}; // if()
Node* node = l->head;
do
{
Node* p = node->next;
free(node);
node = p;
} while (node != NULL);
return NULL;
};
int _empty(List* L)
{
if (L == NULL) return -1;
return (L->size == 0);
};
int _get_max(List* L)
{
if (L == NULL) return -1;
return (int)L->limit;
};
List* _insert_begin(int value, List* l)
{
if (l == NULL) return l; //no list
if ((l->limit > 0) && (l->size == l->limit)) return l; // full
// ok: create a node and stuff data in
Node* nd = (Node*)malloc(sizeof(Node));
nd->data = value; // data comes in
nd->next = l->head; // depois vem o que estava na frente
l->head = nd; // nd fim
l->size = l->size + 1;
// if it is the first node
if (l->size == 1)l->tail = nd;
return l;
};
List* _insert_end(int value, List* l)
{
if (l == NULL) return l;
if ((l->limit > 0) && (l->size == l->limit)) return l; // full
// ok: create a node and insert at the end
Node* nd = (Node*)malloc(sizeof(Node));
nd->data = value;
// first one?
if (l->size == 0)
{
l->head = nd;
nd->next = NULL;
}
else
{
nd->next = NULL; // no one after this
(l->tail)->next = nd;
}; // if()
l->tail = nd; // nd is tail now
l->size = l->size + 1;
// of this is the first node
if (l->size == 1)l->head = nd;
return l;
};
int _insert_your_way(List* L, int(*F)(void*))
{
return 0;
};
int _print(List* l)
{
if (l == NULL)
{
printf("List not created!\n");
return -1;
};
if (l->limit > 0)
{
printf("\nList '%s' with %d of %d MAX elements\n",
l->name,
l->size,
l->limit
);
}
else
{
printf("\nList '%s' with %d elements [MAX not defined yet]\n",
l->name,
l->size
);
}
if (l->size < 1) return 0;
// assume data as just an int
Node* p = l->head;
printf("\n First:%10d\n", l->head->data);
printf(" Last:%10d\n", l->tail->data);
printf("\nElements\n\n");
do
{
printf("%10d \n", p->data);
p = p->next;
} while (p != NULL);
printf("\nEnd of list\n\n");
return 0;
}; // _print()
int _print_your_way(List* L, int(*F)(void*))
{
return 0;
};
List* _remove(int value, List* L)
{
return NULL;
};
int _size(List* L)
{
if (L == NULL) return -1;
return (int)L->size;
};
It was extracted for a larger example, for WIndows. Compiled just under gcc 9.3 on Ubuntu on Windows WSL
I am trying basic creation of linked list using C. I have written the following code which is working up until first node but fails eventually on second one. I think the issue is where I am trying to display the node values in list separated by arrow(->). I think my logic is right but please correct me. Thanks in advance
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node
{
int number;
struct node *next;
};
typedef struct node NODE;
NODE *node1, *node2, *start, *save;
int main()
{
node1 = (NODE *)malloc(sizeof(NODE));
int i = 0;
start = NULL;
for(i = 0; i < 3; i++)
{
int inf;
printf("Enter node value:");
scanf("%d", &inf);
node1->number = inf;
node1->next = NULL;
if(start == NULL)
{
start = node1;
save = node1;
}
else
{
// save=start;
// start=node1;
// node1->next=save;
node1->next = start;
start = node1;
}
while(node1 != NULL)
{
printf("%d ->",node1->number);
node1 = node1->next;
}
}
return 0;
}
The issues are
How you're allocating your nodes for insertion (i.e. save for one, you're not).
How they're placed in the list once you fix the above.
Don't cast malloc in C programs (read here for why).
Fail to check the success of your scanf invoke.
Fail to check the success of your malloc invoke
Before you get discouraged, things you did correctly:
Did not mask a node pointer in a typedef
Properly included a MCVE for review
Prospected the things you may be doing wrong.
A very simple example of iterating three values into a linked list would look something like this:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int number;
struct node *next;
};
typedef struct node NODE;
int main()
{
NODE *head = NULL, *p;
int i = 0;
for(i = 0; i < 3; i++)
{
int inf;
printf("Enter node value:");
if (scanf("%d", &inf) == 1)
{
p = malloc(sizeof *p);
if (p != NULL)
{
p->number = inf;
p->next = head;
head = p;
}
else
{
perror("Failed to allocate new node");
return EXIT_FAILURE;
}
}
else
{
// failed to read data. break
break;
}
// report current linked list
printf("%d", p->number);
for (p=p->next; p; p = p->next)
printf(" -> %d", p->number);
fputc('\n', stdout);
}
// cleanup the linked list
while (head)
{
p = head;
head = head->next;
free(p);
}
head = NULL;
return 0;
}
Input
The values 1 2 3 are input upon being prompted:
Output
Enter node value:1
1
Enter node value:2
2 -> 1
Enter node value:3
3 -> 2 -> 1
Best of luck.
You should use malloc() inside for loop.
Since it is outside, same memory is being used.
As said by Vamsi, you should use malloc to put the nodes on the heap. You also generally shouldn't cast the output of malloc, it isn't needed. And then you could play around with making a doubly-linked list, where you also have a prev pointer inside your struct.
I need to sort the numbers that are entered in a list, but I am doing something wrong and it's sorting all of them except the first one.Any ideas how to fix this?
Here's my code:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node* List;
void Add (struct node* p, int d)
{
struct node* q;
q=malloc(sizeof(struct node));
if (q==NULL)
printf("Not enaugh memory!");
else
{
q->data=d;
if(List==NULL)
{
q->next=NULL;
List=q;
}
else
{
struct node *ptr=List;
while((ptr->next!=NULL)&&(ptr->next->data>d))
{
ptr=ptr->next;
}
q->next=ptr->next;
ptr->next=q;
}
}
}
int main()
{
int n,i,a;
printf("How much numbers are you going to enter? ");
scanf("%d",&n);
for (i=1; i<=n; i++)
{
printf("\nEnter a number: ");
scanf("%d",&a);
Add(List,a);
}
printf("\nThe sorted numbers are: ");
struct node *ptr=List;
while(ptr!=NULL)
{
printf("%d\t",ptr->data);
ptr=ptr->next;
}
printf("\n\n");
system("PAUSE");
return 0;
}
Thanks for the help in advance :-)
in add() function,
if(List==p)
this statement is true for all elements you insert to list since the call to add is,
Add(List,a);
so p=List. therefore the sorting code written in else part is not executed.
Also add statements to check for empty initial list.
You can use code similar to this,
void Add (int d)
{
struct node* q;
q=malloc(sizeof(struct node));
if (q==NULL)
printf("Not enaugh memory!");
else
{
q->data=d;
if(List==NULL)
{
q->next=NULL;
List=q;
}
else
{
struct node *ptr=List;
while((ptr->next!=NULL)&&(ptr->next->data>d))
{
ptr=ptr->next;
}
q->next=ptr->next;
ptr->next=q;
}
}
}
Since list is a global variable you dont need to pass it to Add() function. change the function call to
Add(a);
void Add (struct node* p, int d){
struct node* q;
q=malloc(sizeof(struct node));
if (q==NULL)
printf("Not enaugh memory!");
else{
q->data=d;
if(List==NULL || List->data < d){//modify this line
q->next= List;//and change NULL to List
List=q;
} else {
struct node *ptr=List;
while((ptr->next!=NULL)&&(ptr->next->data>d)){
ptr=ptr->next;
}
q->next=ptr->next;
ptr->next=q;
}
}
}
You always call Add with List as the first parameter, so it's alway true inside Add that (List==p). Consequently each new item is just inserted at the front of the list and there is no sorting at all.
EDIT 1
A good practice would be sending a list to the Add routine as a parameter. Or, if you want to keep it external, just don't give it to Add at all and test if(List == NULL)
void Add( int d)
{
// ... alloc 'q' and fill q->d here, then:
if(List == NULL)
{
q->next = NULL;
List = q;
}
else
{
struct node *b; // put q after b
for( b = List; b->next != NULL; b = b->next)
if( b->next->data >= d)
break;
q->next = b->next;
b->next = q;
}
}
EDIT 2
Example of transferring the list to a function by parameter
void Add( struct node **n, int d)
{
// ... alloc 'q' and fill q->d here, then:
while( *n != NULL && (*n)->data < d)
n = & (*n)->next;
q->next = *n;
*n = q;
}
int main()
{
// ...
Add( &List, a);
// ...
}
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;