I am working on a project which is similar to an address book. Firstly we have a number of students in a text file. I am going to implement a multi linked list which this list have 2 head+tail pointer (head+tail pointer for name,surname). These pointers show the same list but different locations because I am adding the nodes in ascending order and use double pointers to print the list backwards. The problem is I implemented the list by adding nodes by name and surname and the operation goes successfully when I insert another one. But I realized that when I deleted a node by her/his "name" and print the list again the student doesn't exist, but when I print the list by "surname" the student does exist. Then I recognize that I was implemented two separate linked lists. I was told to implement only ONE add and remove function. But how can I add a node by its first name pointers and surname pointers together? I hope I explained my issue understandably. Here are my blocks of code.
My structures:
typedef struct node {
int birth_date;
int zipcode;
int phone_num;
char first_name[50];
char last_name[50];
char city[50];
char address[50];
char email_addr[50];
struct node* fn_next;
struct node* fn_pre;
struct node* ln_next;
struct node* ln_pre;
struct node* birdat_next;
struct node* birdat_pre;
} NODE;
typedef struct {
int fn_count;
int ln_count;
NODE* fn_head;
NODE* ln_head;
NODE* fn_tail;
NODE* ln_tail;
}LIST;
The code block where I read the file line by line and call the add functions:
while ( !feof(myfile) ) {
NODE* pnew_stu;
if( !(pnew_stu = (NODE*) malloc(sizeof(NODE))) ) {
printf("ERROR NOT ENOUGH MEMORY!!!\n");
exit(100);
}
fscanf(myfile,"%s", &(pnew_stu->first_name) );
fscanf(myfile,"%s", &(pnew_stu->last_name) );
fscanf(myfile,"%s", &(pnew_stu->email_addr) );
fscanf(myfile,"%d", &(pnew_stu->phone_num) );
fscanf(myfile,"%s", &(pnew_stu->address) );
fscanf(myfile,"%s", &(pnew_stu->city) );
fscanf(myfile,"%d", &(pnew_stu->zipcode) );
add_Node(list,pnew_stu);
}
And finally my add functions:
void add_fn_Node(LIST* list, NODE* pnew_stu) {
NODE* temp = list->fn_head;
if( list->fn_head == NULL ) {
pnew_stu->fn_next = list->fn_head;
pnew_stu->fn_pre = list->fn_head;
list->fn_head = pnew_stu;
list->fn_count = 1;
return;
}
else {
if ( (strcmp( pnew_stu->first_name, temp->first_name )) <= 0 ) { // Basa Ekleme Kosulu
pnew_stu->fn_next = temp;
pnew_stu->fn_pre = temp->fn_pre;
temp->fn_pre = pnew_stu;
list->fn_head = pnew_stu;
list->fn_count++;
return;
}
else {
while ( temp->fn_next != NULL ) { // Ortaya Ekleme Kosulu
if ( (strcmp( pnew_stu->first_name, temp->first_name ) >= 0 ) && (strcmp( pnew_stu->first_name, temp->fn_next->first_name) < 0)) {
pnew_stu->fn_next = temp->fn_next;
pnew_stu->fn_pre = temp;
temp->fn_next->fn_pre = pnew_stu;
temp->fn_next = pnew_stu;
list->fn_count++;
return;
}
temp = temp->fn_next;
}
if ( temp->fn_next == NULL ) { // Sona Ekleme Kosulu
temp->fn_next = pnew_stu;
pnew_stu->fn_pre = temp;
pnew_stu->fn_next = NULL;
list->fn_tail = pnew_stu;
list->fn_count++;
return;
}
}
}
}
void add_ln_Node(LIST* list, NODE* pnew_stu) {
NODE* temp = list->ln_head;
if( list->ln_head == NULL ) {
pnew_stu->ln_next = list->ln_head;
pnew_stu->ln_pre = list->ln_head;
list->ln_head = pnew_stu;
list->ln_count = 1;
return;
}
else {
if ( (strcmp( pnew_stu->last_name, temp->last_name )) <= 0 ) { // Basa Ekleme Kosulu
pnew_stu->ln_next = temp;
pnew_stu->ln_pre = temp->ln_pre;
temp->ln_pre = pnew_stu;
list->ln_head = pnew_stu;
list->ln_count++;
return;
}
else {
while ( temp->ln_next != NULL ) { // Ortaya Ekleme Kosulu
if ( (strcmp( pnew_stu->last_name, temp->last_name ) >= 0 ) && (strcmp( pnew_stu->last_name, temp->ln_next->last_name) < 0)) {
pnew_stu->ln_next = temp->ln_next;
pnew_stu->ln_pre = temp;
temp->ln_next->ln_pre = pnew_stu;
temp->ln_next = pnew_stu;
list->ln_count++;
return;
}
temp = temp->ln_next;
}
if ( temp->ln_next == NULL ) { // Sona Ekleme Kosulu
temp->ln_next = pnew_stu;
pnew_stu->ln_pre = temp;
pnew_stu->ln_next = NULL;
list->ln_tail = pnew_stu;
list->ln_count++;
return;
}
}
}
}
My delete functions:
void del_fn_name(LIST* list, char* str_key) {
NODE* temp;
int num,counter=1,flag;
temp = list->fn_head;
if( list->fn_head == NULL ) {
printf("The list is EMPTY!!!\n");
return;
}
flag = search_fn(list,str_key);
if ( flag ) {
printf("Enter the number of student you want to delete : ");
scanf("%d", &num);
if( strcmp( list->fn_head->first_name, str_key ) == 0 ) { // Bastan Silme Kosulu
if( num == counter ) {
list->fn_head->fn_next->fn_pre = list->fn_head;
list->fn_head = list->fn_head->fn_next;
free(list->fn_head);
printf("%s is deleted and the new header is %s\n", str_key, list->fn_head->first_name );
return;
}
counter++;
}
temp = temp->fn_next;
while ( temp->fn_next != NULL ) {
if( strcmp( temp->first_name, str_key ) == 0 ) {
if( num == counter ) {
temp->fn_pre->fn_next = temp->fn_next;
temp->fn_next->fn_pre = temp->fn_pre;
free(temp);
printf("%s deleted at between %s and %s\n", str_key, temp->fn_pre->first_name, temp->fn_next->first_name);
return;
}
counter++;
}
temp = temp->fn_next;
}
if( temp->fn_next == NULL ) { // Sondan Silme Kosulu
if( strcmp(temp->first_name, str_key) == 0 ) {
if( num == counter ) {
list->fn_tail = temp->fn_pre;
temp->fn_pre->fn_next = NULL;
free(temp);
printf("%s deleted at the end and new tail is %s \n", str_key, list->fn_tail->first_name );
return;
}
}
}
}
void del_ln_name(LIST* list, char* str_key) {
NODE* temp;
int num,counter=1,flag;
temp = list->ln_head;
if( list->ln_head == NULL ) {
printf("The list is EMPTY!!!\n");
return;
}
flag = search_ln(list,str_key);
if ( flag ) {
printf("Enter the number of student you want to delete : ");
scanf("%d", &num);
if( strcmp( list->ln_head->last_name, str_key ) == 0 ) { // Bastan Silme Kosulu
if( num == counter ) {
temp->ln_next->ln_pre = list->ln_head;
list->ln_head = temp->ln_next;
free(temp);
printf("%s is deleted and the new header is %s\n", str_key, list->ln_head->last_name );
return;
}
counter++;
}
temp = temp->ln_next;
while ( temp->ln_next != NULL ) {
if( strcmp( temp->last_name, str_key ) == 0 ) {
if( num == counter ) {
temp->ln_pre->ln_next = temp->ln_next;
temp->ln_next->ln_pre = temp->ln_pre;
free(temp);
printf("%s deleted at between %s and %s\n", str_key, temp->ln_pre->last_name, temp->ln_next->last_name);
return;
}
counter++;
}
temp = temp->ln_next;
}
if( temp->ln_next == NULL ) { // Sondan Silme Kosulu
printf("The last item %s second last item %s\n", temp->first_name, list->fn_tail->fn_pre->first_name);*/
if( strcmp(temp->last_name, str_key) == 0 ) {
if( num == counter ) {
list->ln_tail = temp->ln_pre;
temp->ln_pre->ln_next = NULL;
free(temp);
printf("%s deleted at the end and new tail is %s \n", str_key, list->ln_tail->last_name );
return;
}
}
}
}
The integers flag and counter are for deleting the duplicate students. For example, if there are three duplicates it asks me to which number of student I want to delete. So if I enter number 2 it deletes the second duplicate.
print(search(type="cliente", codice=random.randrange(1000))) print(find(type="cliente", codice=random.randrange(1000))) import sys sys.exit(1)
Your code seems a bit complex for what is needed but the idea is correct. I don't see any error in the insert method but it's quite hard to follow all this sort of copy'n paste program. You can have each students in several different lists at the same time, but I'd suggest using a different approach to avoiding all this duplication that makes very easy to introduce bugs.
You could abstract the idea of link and list:
typedef struct TList
{
struct TLink *first, *last;
} List;
typedef struct TLink
{
struct TStudent *student;
struct TLink *prev, *next;
} Link;
The List structure is any of the three lists you need (first name, last name, birthdate) and Link is any of the links. See the following picture...

With this approach the code for inserting/removing a link in a list is shared with all link types (first_name, last_name, age). The price to pay is an extra pointer for each link and the need to write link->student->first_name instead of link->first_name.
Adding a link to a list is something like
// Adds a new link before the link `before` or as last link
// if `before` is NULL
void addLink(List *list, Link *newlink, Link *before)
{
newlink->next = before;
newlink->prev = before ? before->prev : list->last;
if (newlink->next) newlink->next->prev = newlink;
else list->last = newlink;
if (newlink->prev) newlink->prev->next = newlink;
else list->first = newlink;
}
and removing a link from a list is something like
void removeLink(List *lists, Link *link)
{
if (link->next) link->next->prev = link->prev;
else list->last = link->prev;
if (link->prev) link->prev->next = link->next;
else list->first = link->next;
}
These two function can be used to manage lists/links of all three types (first_name, last_name and age) without any code duplication.
With this approach the student object can have all the data and many links objects
typedef struct TStudent
{
char first_name[NAMESIZE];
char last_name[NAMESIZE};
int age;
Link first_name_link, last_name_link, age_link;
} Student;
For example to insert the student in order for the first_name list the code becomes
Student *newstudent = ...
...
Link *before = first_name_list.first;
while (before != NULL &&
strcmp(newstudent->first_name,
before->student->first_name) > 0)
{
before = before->next;
}
addLink(&first_name_list,
&newstudent->first_name_link,
before);
Please note that this simple loop handles correctly all cases that in your code are instead handled separately with copy'n paste of similar statements (this is the first student inserted, the last, one in the middle).
The idea here is just to set the before node to the first in the list and keeping moving it to next student if the new one must be inserted after instead.
Of course the same kind of loop is needed to find the correct insertion point in the other two lists (last_name_list and age_list). Factoring out also the insertion point search would be possible by using function pointers.
To delete a Student of course the student data must be removed from all the lists, in other words all three links must be removed. This however simply means calling three times the removeLink function:
removeLink(&first_name_list, &student->first_name_link);
removeLink(&last_name_list, &student->last_name_link);
removeLink(&age_list, &student->age_link);
free(student);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With