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.
Data structure
You could abstract the idea of link and list:
The
Liststructure is any of the three lists you need (first name, last name, birthdate) andLinkis 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 writelink->student->first_nameinstead oflink->first_name.Link insertion/deletion
Adding a link to a list is something like
and removing a link from a list is something like
These two function can be used to manage lists/links of all three types (first_name, last_name and age) without any code duplication.
Insertion of a Student object
With this approach the student object can have all the data and many links objects
For example to insert the student in order for the
first_namelist the code becomesPlease 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
beforenode 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_listandage_list). Factoring out also the insertion point search would be possible by using function pointers.Deletion of a Student object
To delete a
Studentof 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 theremoveLinkfunction: