When trying to print a linked list nodes the program is turning off

104 views Asked by At

I am writing a phonebook code using singly linked list. When I try to print the contacts they are printed but then the program turns off.

This is the node struct:

struct contact{
  char *number;
  char *name;
  struct contact* next;
};
typedef struct contact contact;

and this is the printing contacts function:

void list(){
    contact *temp = first;
    if(first==NULL){
      printf("list is empty\n");
    }
    while(temp!=NULL){
      printf("name: %s  number: %s\n", temp->name, temp->number);
      temp = temp->next;
      
    }
    getch();
    system("cls");
  menu();
}

menu() function:

void menu(){
       system("cls");
  printf("+++++++++++++++++++Phone book+++++++++++++++++++++++++\n     1.add.\n     2.delete.\n     3.search.\n     4.modify.\n     5.list contacts.\n     6.recent\n     7.exit\n ");
  switch(getch())
  {
    case '1':
        add();
        break;
    case '2':
        delete();
        break;
    case '3':
        search();
        break;
    case '4':
        modify();
        break;
    case '5':
        list();
        break;
    case '6':
        recent();
        break;
    case '7':
        exit(0);
        break;
    default: system("cls");
                printf("\nPress any key");
                getch();
menu();
}
}

edit: the add function:

void add(){
  system("cls");
  contact* new = (contact*)malloc(sizeof(contact));
  char newname[MAX];
  char newnumber[MAX];
  printf("enter a name \n");
  gets(newname);
  printf("enter a number \n");
  gets(newnumber);
  new-> number = newnumber;
  new->name = newname;
  if(first== NULL){
    first= new;
  }
    else{
    if(first->name[0]>newname[0]){
      new->next = first;
      first = new;
    }
    else{
    contact* temp = first;
    while(temp->next!= NULL && temp->next->name[0]<newname[0]){  
      temp = temp-> next;
    }
    new->next = temp->next;
    temp->next = new;
    getch();

  }


}
file = fopen("file.txt", "w");
fprintf(file, "%s %s", newname, newnumber);
fclose(file);

system("cls");
menu();
}
1

There are 1 answers

0
Serge Ballesta On BEST ANSWER

The add function invokes Undefined Behaviour (the hell of C programmers) because you use local arrays after the functions where they are declared returns, and get only dangling pointers:

void add(){
  system("cls");
  contact* new = (contact*)malloc(sizeof(contact)); // ok you allocated a contact
  char newname[MAX];            // Oops a local array...
  char newnumber[MAX];          // and another one
  ...
  new-> number = newnumber;     // new->number points to the local array
  new->name = newname;          // id. for new->name
  ...
}                               // newname and newnumber both reach end of life...

When the add function returns, new->name and new->number point to object that have reached their end of life and are dangling pointers. Dereferencing them is explicitely Undefined Behaviour.

You should either use strdup to copy the content of newname and newnumber in dynamic memory:

  ...
  new-> number = strdup(newnumber);   // new->number points to allocated memory: fine
  new->name = strdup(newname);        // id. for new->name
  ...

, or directly use plain arrays in the contact struct:

struct contact{
  char number[MAX];
  char name[MAX];
  struct contact* next;
};
...
void add(){
  system("cls");
  contact* new = (contact*)malloc(sizeof(contact));
  printf("enter a name \n");
  gets(new->name);
  printf("enter a number \n");
  gets(new->number);
  ...

Unrelated, but you should stop using the deprecated gets and only use fgets. gets was deprecated because it was known for decades as the cause of numerous (and impossible to prevent) buffer overflows.