Insert at start of list - c

I am writing a simple function in c++.
I get some errors with my code. THERE is no output.
Also I need to call free after remembered where the next index.
I dont know how to do that.
Do I need to free current inside the while loop after printf?
here my code
#include <stdio.h>
#include<stdlib.h>
/* these arrays are just used to give the parameters to 'insert',
to create the 'people' array
*/
#define HOW_MANY 7
char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim",
"Harriet"};
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};
/* declare your struct for a person here */
typedef struct{
char* name;
int age;
struct person *next;
}
person;
static void insert( person *headptr, char *name, int age)
{
person *ptr=malloc(sizeof(person));
if(ptr==NULL) abort();
//assign to structure field
ptr->name = name;
ptr->age = age;
//link new object into the list
ptr->next=headptr;
headptr=ptr;
}
int main(int argc, char **argv)
{
/* declare the people array here */
person *headptr=NULL;
// Make a copy of the pointer to the head item in the list
for (int index=0;index < HOW_MANY;index=index+1)
{
insert(headptr, *(names+index), ages[index]);
}
person *current=NULL;
// current will be set to NULL when it reaches the end
while(current != NULL)
{
// print out the item information
printf("name: %s, age: %i\n",current -> name, current-> age);
// Now move to the next item in the linked list
current= current -> next;
}
}

There are several problems in your code.
Your struct's next field is declared using an unknown type.
Your insert() function is not updating the headptr variable in main().
You get no output because the current variable in main() is initialized to NULL instead of headptr, so there is nothing for the loop to do.
You are leaking the allocated memory.
Try something more like this instead:
#include <stdio.h>
#include <stdlib.h>
/* these arrays are just used to give the parameters to 'insert', to create the 'people' array */
#define HOW_MANY 7
char* names[HOW_MANY] = {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim", "Harriet"};
int ages[HOW_MANY] = {22, 24, 106, 6, 18, 32, 24};
/* declare your struct for a person here */
typedef struct person {
char* name;
int age;
struct person *next;
} person;
static void insert(person **headptr, char *name, int age) {
person *ptr = malloc(sizeof(person));
if (!ptr) abort();
//assign to structure fields
ptr->name = name;
ptr->age = age;
//link new object into the list
ptr->next = *headptr;
*headptr = ptr;
}
int main(int argc, char **argv) {
/* declare the people array here */
person *headptr = NULL;
// insert items at the head of the list
for (int index = 0; index < HOW_MANY; ++index) {
insert(&headptr, names[index], ages[index]);
}
person *current = headptr;
// current will be set to NULL when it reaches the end
while (current) {
// print out the item information
printf("name: %s, age: %i\n", current->name, current->age);
// Now move to the next item in the linked list
current = current->next;
}
// free the items
current = headptr;
while (current) {
person *next = current->next;
free(current);
current = next;
}
return 0;
}

To insert at the front of a linked list, I would suggest that you pass a pointer to the head of the list, not the head, resulting in something like this example (written from memory, but should work):
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct list {
struct list *next;
int value;
} list;
void list_push(list **phead, int value) {
list *front = malloc(sizeof(struct list));
front->next = *phead;
front->value = value;
*phead = front;
}
bool list_insert(list **phead, int value, int index) {
list **ptr = phead;
while (index-- > 0) {
if (!*ptr) return false;
ptr = &(*ptr)->next;
}
list_push(ptr, value);
return true;
}
void list_dump(list *head) {
while (head) {
printf("%d\n", head->value);
head = head->next;
}
}
void main(void) {
list *head = NULL; // empty list
list_push(&head, 23);
list_insert(&head, 42, 1);
list_insert(&head, 13, 0);
list_dump(head);
}

You need to modify your insert method like below:-
static person* insert(person *headptr, char *name, int age)
{
if (headptr == NULL) {
headptr = (person*)malloc(sizeof(person));
headptr->name = name;
headptr->age = age;
headptr->next = NULL;
}
else{
person *ptr = (person*)malloc(sizeof(person));
if (ptr == NULL) abort();
//assign to structure field
ptr->name = name;
ptr->age = age;
//link new object into the list
ptr->next = headptr;
headptr = ptr;
}
return headptr;
}
And now you need to call the above method like below:-
// Make a copy of the pointer to the head item in the list
for (int index=0;index < HOW_MANY;index=index+1)
{
headptr = insert(headptr, *(names+index), ages[index]);
}
Now you need to print your list like below:-
person *current=headptr;//you need to point to the first node of the list
// current will be set to NULL when it reaches the end
while(current != NULL)
{
// print out the item information
printf("name: %s, age: %i\n",current -> name, current-> age);
// Now move to the next item in the linked list
current= current -> next;
}

Related

Swapping elements in a linked list

So I'm running into a little problem with my sorting function.
While it's doing what it's supposed to in the second edge case,
the elements get swapped and then swapped back continuously.
The example here happens when Sven(25) and Bob(22) meet.
void sortPerson(person *pers, person* newPerson)
{
if(pers == NULL || pers->next == NULL)
{
printf("List is emtpy");
return;
}
person* tempValue;
person* prev = pers;
person* curr = pers->next;
//person* newValue = pers;
while(prev != NULL && curr != NULL)
{
//first edge case
//adds a new person
if(prev->age < newPerson->age)
{
newPerson->next = prev->next;
prev->next = newPerson;
}
//second edge case
//swapping process when prev age greater than curr age
//forming a decending order of ages
if(prev->age > curr->age)
{
tempValue = prev;
prev = prev->next;
prev->next = tempValue;
printf("\nPerson age: %d\n", tempValue->age);
printf("loop test\n");
printf("%d and %d\n",prev->age, prev->next->age);
}
//third edge case
//if age is the same do nothing
if(prev->age == curr->age)
{
return;
}
prev = prev->next;
curr = curr->next;
}
}
This function returns a new person
person* addPerson( person *newPers ){
return newPers;
}
And here is my main if you want to test it yourself
int main(){
person* person1 = construct_person("Max", 20);
person* person2 = construct_person("Sven", 25);
person* person3 = construct_person("Bob", 22);
person* person4 = construct_person("John", 23);
person* newPerson = construct_person("Markus", 21);
person1->next = person2;
person2->next = person3;
person3->next = person4;
//person4->next = addPerson(person1, newPerson);
//swapPerson(person1);
sortPerson(person1, addPerson(newPerson));
printperson(person1);
free(person1);
free(person2);
free(person3);
free(person4);
free(newPerson);
}
My struct person and constructor
typedef struct person person;
struct person{
char *name;
int age;
person *next;
};
person* construct_person(char *name, int age)
{
person* pers = (person*) malloc (sizeof(person));
pers->name = name;
pers->age = age;
pers->next = NULL;
return pers;
}
I suspect the problem is that my 'prev' struct pointer gets altered throughout the process, but I'd like a second opinion and potential fix.
*Note I'm only freeing it like this because this is testing only and I'm not gonna add more people else I'd done so iteratively.
Some remarks:
The name sortPerson is not well chosen. It should better be named insertPerson
You cannot hope to sort a list with just one iteration and a swap here and there during that iteration. If that were possible, you would have invented the most efficient sorting algorithm. So, this cannot work -- at least not always.
Instead of implementing some sort algorithm (like bubble sort, selection sort, ...), make sure you add all persons using that insertPerson function. That way you can be sure that the list into which a new person is inserted, is already sorted. This way you don't have to swap elements at all. You only have to find the correct insertion point and insert the new person there. So in the main program you should not be fiddling with next pointers. Leave that to this insertPerson function.
When a list is empty or just has one person, you should still insert the new person. It makes no sense to not do it when the list is empty (or just has one element).
The only base case is when you need to insert the person before all other persons. In that case the reference to the first person needs to change, as the new person becomes that first person. One way to make that work, is to make the first parameter a call-by-reference. In other words: pass the address of where the first person pointer is stored, so that this pointer can be changed, and the caller will have access to that change.
I don't see the logic in omitting an insertion when the age of the new person matches the age of a person already in the list. Surely your list should allow Bob and Alice, even when they are both 28.
There are several other points to make...
Here is a working version. I had to make some assumptions about the code that you didn't share, but the principle should be clear even if your code is different:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct person_s {
int age;
char name[100];
struct person_s * next;
} person;
person* construct_person(char* name, int age) {
person* p = malloc(sizeof(person));
strcpy(p->name, name);
p->age = age;
p->next = NULL;
return p;
};
void insertPerson(person** youngest, char* name, int age)
{
person* newPerson = construct_person(name, age);
// Even when list is empty, still add it
if (*youngest == NULL || (*youngest)->age > age) {
newPerson->next = *youngest;
*youngest = newPerson;
return;
}
person* prev = *youngest;
person* curr = prev->next;
// Search insertion point
while (curr != NULL && curr->age < age) {
prev = curr;
curr = curr->next;
}
// Found it:
prev->next = newPerson;
newPerson->next = curr;
}
void printList(person* pers) {
while (pers != NULL) {
printf("%s is %d years old.\n", pers->name, pers->age);
pers = pers->next;
}
}
void freeList(person** pers) {
while (*pers != NULL) {
person* temp = *pers;
*pers = (*pers)->next;
free(temp);
}
}
int main(){
person* personList = NULL;
insertPerson(&personList, "Max", 20);
insertPerson(&personList, "Sven", 25);
insertPerson(&personList, "Bob", 22);
insertPerson(&personList, "John", 23);
insertPerson(&personList, "Markus", 21);
printList(personList);
freeList(&personList);
}

Problems with removing the last item in a linked list in c

I am just learning c and about linked lists I have some major problems.
I have following code :
#include <stdio.h>
#include <stdlib.h>
struct people {
int age;
char *name;
struct people * next;
};
typedef struct people people;
void count(people array) {
people *current=malloc(sizeof(people));
current = &array;
int count = 0;
while(current){
count++;
printf("name %s\n",current->name);
printf("age %d\n",current->age);
current=current->next;
}
printf("%d\n", count);
free(current);
}
void push(people *array){
people * new=malloc(sizeof(people));
people *last=malloc(sizeof(people));
new->age=300;
new->name="baz";
new->next=NULL;
last=array;
while(last->next){
last=last->next;
}
last->next=new;
// free(new);
}
void pop(people *array){
people * last=malloc(sizeof(people));
last=array;
while(last->next){
//get the last element in the list
last=last->next;
}
// free the last element
free(last);
}
int main(int argc, char** argv) {
people person = {
.name = "foo",
.age = 25
};
person.next = malloc(sizeof (people));
person.next->age = 26;
person.next->name = "bar";
person.next->next = NULL;
//push into the list
push(&person);
//count after pushing
count(person);
//remove last
pop(&person);
//at this count i get just the age 0 but the name was not removed and still counts 3
count(person);
return 0;
}
When I run pop it is supposed to work similar to Array.prototype.pop from Javascript. It behaves really weird the last next has the name "baz" and age 300. After I run this code instead of removing this last struct it just shows the age as 0.
Seems free is not really freeing the pointer allocated with malloc.
example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct people {
int age;
char *name;
struct people * next;
} people;
people *new_people(const char *name, int age){
people *node = malloc(sizeof(people));
char *copy_name = malloc(strlen(name)+1);
strcpy(copy_name, name);
node->age = age;
node->name = copy_name;
node->next = NULL;
return node;
}
void free_people(people *p){
free(p->name);
free(p);
}
void count(people *array) {
people *current = array;
int count = 0;
while(current){
count++;
printf("name %s\n", current->name);
printf("age %d\n", current->age);
current = current->next;
}
printf("%d\n", count);
}
void push(people **array, people *addNode){
if(*array == NULL){
*array = addNode;
return ;
}
people *last = *array;
while(last->next){
last = last->next;
}
last->next = addNode;
//return length;
}
people *pop(people **array){
if(*array == NULL)
return NULL;
people *last = *array;
people *prev = NULL;
while(last->next){
prev = last;
last=last->next;
}
if(prev != NULL)
prev->next = NULL;
else
*array = NULL;
return last;
}
int main(void) {
people *array = NULL;
push(&array, new_people("foo", 25));
push(&array, new_people("bar", 26));
push(&array, new_people("baz", 300));
count(array);
people *baz = pop(&array);
free_people(baz);
count(array);
people *bar = pop(&array);
free_people(bar);
people *foo = pop(&array);
free_people(foo);//free_people(pop(&array))
return 0;
}
The problem is that, in the void count(people array), current=current->next; would be assigned in the while loop. So you need to make sure last->next shall be assigned to NULL in the pop function.
I modified your pop function to:
void pop(people *array){
people * last=malloc(sizeof(people));
while(array->next){
last=array;
array=array->next;
if(array->next){
//get the last element in the list
last=last->next;
}else{
break;
}
}
last->next=NULL;
array=last;
}
In the pop function, you should assign the address of 'array' to 'last', and then points the 'array' to 'array->next'.
As the program breaks from the while loop, you can do last->next=NULL; and array=last; to make sure the last struct is fine.

All Nodes in a linked list point to same object

The problem is somewhere in here....
char buffer[80];
char *name;
while (1) {
fgets(buffer, 80, inf); //reads in at most 80 char from a line
if (feof(inf)) //this checks to see if the special EOF was read
break; //if so, break out of while and continue with your main
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");//get first token up to space
stock = newStock(name,...)
....
}
I'm working in C with generic linked lists. I made a list implementation that I've tested and know works with chars. I'm trying to add stocks (I created a stock struct) to the linked list, with each node of the linked list holding a stock struct, but when I finish reading in the stocks all of the nodes point to the same struct and I can't figure out why. Here's some snippets of my code
list *list = malloc(sizeof(list));
newList(list, sizeof(stock_t));
while(1) {
...
(read from file)
...
stock_t *stock;
stock = newStock(name, closes, opens, numshares, getPriceF, getTotalDollarAmountF,getPercentChangeF,toStringF);
addToBack(list, stock);
}
Here's the newStock function:
stock_t *newStock(char *name, float closingSharePrice, float openingSharePrice, int numberOfShares, getPrice getP, getTotalDollarAmount getTotal, getPercentChange getPercent, toString toStr) {
stock_t *stock = malloc(sizeof(stock));
stock->stockSymbol = name;
stock->closingSharePrice = closingSharePrice;
stock->openingSharePrice = openingSharePrice;
stock->numberOfShares = numberOfShares;
stock->getP = getP;
stock->getTotal = getTotal;
stock->getPercent = getPercent;
stock->toStr = toStr;
return stock;
}
In a way I see what's wrong. newStock returns a new pointer every time, but it always gets stored in the variable 'stock' which is what every node points to, so it's going to be equal to whatever the last pointer newStock returned was...but I don't see the way around this. I tried having newStock return just a stock_t, and doing addToBack(list, &stock), but that didn't solve the problem either.
Any help would be appreciated!
Here is some code from the list:
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
Here's code from the stock struct:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef float (*getPrice)(void *S);
typedef float (*getTotalDollarAmount)(void *S);
typedef float (*getPercentChange)(void *S);
typedef char *(*toString)(void *S);
typedef struct stock{
char *stockSymbol;
float closingSharePrice;
float openingSharePrice;
int numberOfShares;
getPrice getP;
getTotalDollarAmount getTotal;
getPercentChange getPercent;
toString toStr;
}stock_t;
The generic functions probably seem like overkill but this is for homework (if you couldn't tell already) so we were asked to specifically use them. I don't think that has anything to do with the problem though.
Here are the definitions for those functions anyway
float getPriceF(void *S) {
stock_t *stock = (stock_t*)S;
return stock->closingSharePrice;
}
float getTotalDollarAmountF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice) * (stock->numberOfShares));
}
float getPercentChangeF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice - stock->openingSharePrice)/(stock->openingSharePrice));
}
char *toStringF(void *S) {
stock_t* stock = (stock_t*)S;
char *name = malloc(20*sizeof(char));
//sprintf(name, "Symbol is: %s. ", (stock->stockSymbol));
return stock->stockSymbol;
}
void printStock(void *S) {
char *str = toStringF(S);
printf("%s \n", str);
}
And this is how I'm traversing the list:
typedef void (*iterate)(void *); //this is in the list.h file, just putting it here to avoid confusion
void traverse(list *list, iterate iterator) {
assert(iterator != NULL);
node_t *current = list->head;
while (current != NULL) {
iterator(current->data);
current = current->next;
}
}
And then in my main I just called
traverse(list, printStock);
I can't find any problems with your code (that would cause your problem, anyway - there are places where you don't check the return from malloc() and stuff like that, but those are not relevant to this question). You don't supply the definition of stock_t, so I made a new data struct, and a new couple of functions, otherwise I just copied and pasted the code you provided:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* Your code starts here */
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
/* Your code ends here */
/* I made a new struct, rather than stock, since you didn't supply it */
struct mydata {
int num1;
int num2;
};
/* I use this instead of newStock(), but it works the same way */
struct mydata * newNode(const int a, const int b) {
struct mydata * newdata = malloc(sizeof *newdata);
if ( newdata == NULL ) {
fputs("Error allocating memory", stderr);
exit(EXIT_FAILURE);
}
newdata->num1 = a;
newdata->num2 = b;
return newdata;
}
/* I added this function to check the list is good */
void printList(list * list) {
struct node * node = list->head;
int n = 1;
while ( node ) {
struct mydata * data = node->data;
printf("%d: %d %d\n", n++, data->num1, data->num2);
node = node->next;
}
}
/* Main function */
int main(void) {
list *list = malloc(sizeof(list));
newList(list, sizeof(struct mydata));
struct mydata * data;
data = newNode(1, 2);
addToBack(list, data);
data = newNode(3, 4);
addToBack(list, data);
data = newNode(5, 6);
addToBack(list, data);
printList(list);
return 0;
}
which outputs this:
paul#MacBook:~/Documents/src$ ./list
1: 1 2
2: 3 4
3: 5 6
paul#MacBook:~/Documents/src$
demonstrating that you have a 3 node list, with all nodes different and where you'd expect them to be.
Either there is some other problem in code you're not showing, or for some reason you are thinking each node points to the same struct when it actually doesn't.
One possibility is that you have a char * data member in your stock struct. It's impossible to tell from the code you provided, but it's possible that you really are creating different nodes, but they all end up pointing to the same name, so they just look like they're the same. If you're assigning a pointer to name, you should make sure it's freshly allocated memory each time, and that you're not just, for instance, strcpy()ing into the same memory and assigning the same address to each stock struct.
EDIT: Looks like that was your problem. This:
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");
should be:
name = (char *) malloc(sizeof(char)*20);
....
strcpy(name, strtok(buffer, " "));
Right now, you malloc() new memory and store a reference to it in name, but then you lose that reference and your memory when you overwrite it with the address returned from strtok(). Instead, you need to copy that token into your newly allocated memory, as shown.

Linked List Implementation Memory Allocation

I've implemented a linked list using structs and pointers in C as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* these arrays are just used to give the parameters to 'insert',
* to create the 'people' array */
#define HOW_MANY 7
char * names[HOW_MANY] = {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim", "Harriet"};
int ages[HOW_MANY] = {22, 24, 106, 6 ,18, 32, 24};
/* declare your struct for a person here */
struct p {
char *peopleName;
int age;
struct p* next;
} person;
struct p* insert_end (struct p *people,char *name, int age) {
/* put name and age into nthe enxt free place in the array parameter here */
/* modify nextfreeplace here */
struct p *nextPerson;
nextPerson = (struct p*)malloc(sizeof(struct p));
if (nextPerson == NULL) {
printf("Error performing malloc.\n");
return(NULL);
} else {
nextPerson -> peopleName = name;
nextPerson -> age = age;
if (people == NULL) {
nextPerson -> next = people;
return nextPerson;
} else {
struct p* temp = people;
while ((temp -> next) != NULL) {
temp = temp -> next;
}
temp -> next = nextPerson;
nextPerson -> next = NULL;
return people;
}
}
}
int main (int argc, char **argv) {
/* declare the people array here */
struct p *people = NULL;
for (int i = 0; i < HOW_MANY; i++) {
people= insert_end(people, names[i], ages[i]);
}
while (people != NULL) {
printf("Freeing\n");
free(people);
people = people -> next;
}
return 0;
}
This works fine, but what I don't understand is why it doesn't work when insert_end is declared as follows:
struct p* insert_end (struct p *people,char *name, int age) {
/* put name and age into nthe enxt free place in the array parameter here */
/* modify nextfreeplace here */
struct p *nextPerson;
nextPerson = (struct p*)malloc(sizeof(struct p));
if (nextPerson == NULL) {
printf("Error performing malloc.\n");
return(NULL);
} else {
nextPerson -> peopleName = name;
nextPerson -> age = age;
if (people == NULL) {
nextPerson -> next = people;
return nextPerson;
} else {
while ((people -> next) != NULL) {
people= people-> next;
}
people-> next = nextPerson;
nextPerson -> next = NULL;
return people;
}
}
}
As you can see, the memory is not being freed correctly when this implementation is used. Could anyone help me in understanding why this does not work?
The function is apparently supposed to return a pointer to the first entry in the list. The second implementation does not, instead returning a pointer to the next-to-last entry in the case where there's already at least one thing on the list.
Not the answer to your question, but even when you use the first version of insert_end which works fine, you have undefined behaviour in this piece of code :
while (people != NULL) {
printf("Freeing\n");
free(people);
people = people -> next; // << you are using people after it has been freed
}
On your platform the code may seem to work correctly, but this is only by chance.
This works in all cases on all platforms :
while (people != NULL) {
printf("Freeing\n");
struct p *temp = people ;
people = people -> next;
free(temp);
}

compare list items, and sort in order in c

The code is compiled, however, there are logical errors in my code. I want to compare the string in the array and then list them in order in the list.I cant not figure out, how I can compare the list items without using index, and how can i compare the current name with the next name. Any one can help?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* these arrays are just used to give the parameters to 'insert',
to create the 'people' array */
char names[][10]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim",
"Harriet"};
int ages[7]= {22, 24, 106, 6, 18, 32, 24};
/* declare your struct for a person here */
typedef struct Record{
char *name;
int age;
struct Record *next;
} Record;
//set the head pointer at the start of the list
Record *headptr = NULL;
int compare_people( Record *a, Record *b)
{
return strcmp((*(Record *)a).name, (*(Record *)b).name);
}
static void insert (Record *p, char *s, int n) {
/* create a new space for the new person */
Record *ptr = ( Record *) malloc(sizeof(Record));
/* check if it is succeeded */
if( ptr == NULL){
abort();
printf("memory allocation fail");
exit(1);
}else{
printf("memory allocation to person - %s - \n", s);
}
//set the data for the new person
ptr->name=s;
ptr->age=n;
ptr->next= NULL;
//ptr= NULL;
//printf("%i", p->age);
/* do not compare when the list is empty*/
if(headptr==NULL)
{
ptr->next=headptr;
headptr=ptr;
printf("ok1\n");
}else{
Record *tail = headptr;
/* go through all the list */
while(tail->next!=NULL)
{
if(compare_people(ptr->name,tail->name)== 1){
tail = tail->next;
}else{
tail->next=headptr;
}
}//while
//tail->next=ptr;
}
}
int main( int argc, char **argv) {
/* declare the people array here */
Record *p=headptr;
headptr = NULL;
//insert the members and age into the unusage array.
for (int i=0; i < 7; i++) {
insert (p,names[i], ages[i]);
/* do not dereference the pointer */
}
/* print out a line before printing the names and ages */
printf("\n");
//set the pointer at the start of the list
p = headptr;
/* print the people array here*/
for ( int i=0; i < 7; i++, p = p->next ) {
printf("The name is: %s, the age is:%i\n", p->name, p->age);
}
/* This is the third loop for call free to release the memory allocated by malloc */
/* the free()function deallocate the space pointed by ptr. */
for( int i=0; i<7; i++){
free(p->next);
}
}
This code doesn't look right:
Record *tail =headptr;
/* go through all the list */
while(tail->next!=NULL)
{
if(compare_people(ptr->name,tail->name)== 1){
tail = tail->next;
} else {
tail->next=headptr;
}
} //while
If you want to insert something after tail, simply setting tail->next = headptr is going to (a) leak anything that currently comes after tail and (b) turn your linked list into a loop with no end.
If you want to insert ptr into your list, you should probably do something like
ptr->next = tail->next;
tail->next = ptr;
...and then break out of the loop.
First major problem is here:
Record *tail =headptr;
/* go through all the list */
while(tail->next!=NULL) {
...
You'll never make it into this while() loop. On the first iteration you did this:
ptr->next= NULL; // setting the pointer's next pointer to NULL
...
headptr=ptr; // have headptr point at what ptr is pointing to
That means that headptr->next will be NULL. Then in the above code snippet you set tail to headptr, thus tail->next will be NULL and you'll never execute that loop.
Second major problem is here:
if(compare_people(ptr->name,tail->name)== 1){
You're passing a string to this function (record->name is a string), but in the function itself you've set it up as:
int compare_people(Record *a, Record *b)
taking a record (not a char *) as the input. This is going to kill you once you fix the first problem and actually get to this function.
Your code contains many error . I can not go over all errors of your code and comments on. I tried to fix your code .
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char names[][10]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim",
"Harriet"};
int ages[7]= {22, 24, 106, 6, 18, 32, 24};
/* declare your struct for a person here */
typedef struct Record{
char *name;
int age;
struct Record *next;
} Record;
//set the head pointer at the start of the list
Record *headptr = NULL;
int compare_people(char *a, char *b)
{
return strcmp(a, b);
}
void insert (char *s, int n) {
Record *t, *pnew, *prv;
int i;
prv=NULL;
pnew=(Record *)malloc(sizeof(struct Record));
if(pnew == NULL){
abort();
printf("memory allocation fail");
exit(1);
}else{
printf("memory allocation to person - %s - \n", s);
}
pnew->name = s;
pnew->age = n;
pnew->next = NULL;
if (headptr==NULL)
{
headptr = pnew;
return;
}
for (t=headptr;t!=NULL;t=t->next) { // look for the right place to insert in order to get a tri list
if (compare_people(s,t->name)<0) {
pnew->next=t;
if (prv!=NULL)
prv->next = pnew;
else
headptr=pnew;
return;
}
prv=t;
}
prv->next=pnew;
return;
}
int main(int argc, char **argv) {
Record *p, *q;
int i;
for (i=0; i < 7; i++) {
insert (names[i], ages[i]);
}
printf("\n");
for (p = headptr; p!=NULL; p = p->next) {
printf("The name is: %s, the age is:%i\n", p->name, p->age);
}
/* To free your linked list: */
p = headptr;
while (p!=NULL){
q = p;
p = p->next;
free(q);
}
}
The output of the execution of the above code:
linux$ ./test
memory allocation to person - Simon -
memory allocation to person - Suzie -
memory allocation to person - Alfred -
memory allocation to person - Chip -
memory allocation to person - John -
memory allocation to person - Tim -
memory allocation to person - Harriet -
The name is: Alfred, the age is:106
The name is: Chip, the age is:6
The name is: Harriet, the age is:24
The name is: John, the age is:18
The name is: Simon, the age is:22
The name is: Suzie, the age is:24
The name is: Tim, the age is:32
You probably have to use doubled chained list (Add a pointer to the previous record of the list). Then it will be easier to sort element of the list. I hope it helps.

Resources