2016-08-31 3 views
0

Я пытаюсь создать список, отсортированный по алфавиту. Для кода, если любые два имени одинаковы, их возраст сравнивается. Предполагается, что их возраст будет не таким.Упорядочить по алфавиту с помощью связанного списка

Я сделал функцию, которая сравнивает двух учеников с их именем и возрастом, как показано выше. Это прекрасно работает.

Проблема, с которой я столкнулась, заключается в связывании четырех имен вместе, я получаю ошибку сегментации. Если кто-нибудь может дать мне несколько указателей на то, где я ошибаюсь, или отлаживать с помощью c, было бы здорово.

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <string.h> 
#include <ctype.h> 

typedef struct name_s Name; 

//Struct name_s contains a character pointer to a name, an age, and a 
// pointer to the next name in a linked list 

struct name_s{ 
    char* name; 
    int age; 
    Name* next; 
}; 

//comesBefore takes a pointer to student1 and student2. 
//The two students are compared to see which one comes first in 
//alphabetical order. 
//If both names are the same then their ages are compared. 
//The function returns true if student1 should come first else false 

bool comesBefore(const Name* student1, const Name* student2) 
{ 
    int i = 0; 
    if (student2 == NULL){ 
     return true; 
    } 
    while (student1->name[i]!= '\0' && student2->name[i] != '\0'){ 
     if (student1->name[i] < student2->name[i]){ 
      return true; 
     } 
     i++; 
    } 

    if (student1->name == student2->name){ 
     if (student1->age < student2->age){ 
      return true; 
     } 
    } 

    return false; 
} 

//creates a linked list in alphabetical order of the names 
//if any two names are the same the one with the lowest age comes first 

Name* linkedList(Name names[], int n) 
{ 
    Name* head = NULL; 
    Name* previous = NULL; 
    Name* last = NULL; 
    Name* current = &names[0]; 
    int i = 0; 
    while (i < n) { 
     if (head == NULL){ 
      head = current; 
     } else { 
      if (comesBefore(current, head)){ 
       current->next = head; 
       head = current; 
      } else { 
       previous = head; 
       while(comesBefore(current, previous->next) == false 
        && previous->next != NULL){ 
        previous = previous->next; 
       } 

       current->next = previous->next; 
       previous->next = current; 
      } 

     } 
     last = head; 
     int k = 0; 
     while (k <= i){ 
      last = last->next; 
      k++; 
     } 

     last->next = NULL; 
     i++; 
     current = &names[i]; 
    } 


    return head; 
} 


int main(void) 
{ 

    Name a; 
    Name b; 
    Name c; 
    Name d; 
    Name* s1 = &a; 
    Name* s2 = &b; 
    Name* s3 = &c; 
    Name* s4 = &d; 

    s1->name = "Zaphod Beeblebrox"; 
    s1->age = 250; 
    s2->name = "Albert Einstein"; 
    s2->age = 133; 
    s3->name = "Albert Einstein"; 
    s3->age = 7; 
    s4->name = "Brook Fleming"; 
    s4->age = 20; 

    Name names[4]; 
    names[0] = a; 
    names[1] = b; 
    names[2] = c; 
    names[3] = d; 

    Name* list = linkedList(names, 4); 
    while (list!=NULL){ 
     printf("Name: %s\nAge: %d\n--------\n", 
     list->name, 
     list->age 
     ); 
     list = list->next; 
    } 



    return 0; 
} 
+1

Вашего сравнения функция имеет проблемы. Предположим, что код сравнивает Зафод с Альбертом; первое сравнение показывает, что Z не меньше A, поэтому он продолжает сравнивать 'a' с' l' - что дает неправильный результат. Вам нужно проверить 'if (student1-> name [i]> student2-> name [i]) return false;' и продолжать цикл только тогда, когда имена равны. Следующее 'if (student1-> name == student2-> name)' test также является фиктивным; сравнение указателей на равенство - это не то, что вы хотите - и снова вам нужно проверить как меньше, так и больше, а затем решить, что вернуть, если возрасты равны. –

ответ

0

Проблема в том, что «следующие» указатели не инициализируются. Вам нужно свести их на нет.

Name a = {0}; 
Name b = {0}; 
Name c = {0}; 
Name d = {0}; 

Другое дело, что ваша сортировка не очень хорошо справляется с сопоставлением строк. Вы должны изменить его на:

bool comesBefore(const Name* student1, const Name* student2) 
{ 
    int i = 0; 
    if (student2 == NULL) 
    { 
     return true; 
    } 
    while (student1->name[i]!= '\0' && student2->name[i] != '\0') 
    { 
     if (student1->name[i] < student2->name[i]){ 
      return true; 
     } 
     else if (student1->name[i] > student2->name[i]){ 
      return false; 
     } 

    i++; 
} 
... 

или даже лучше, используйте strcmp()

также отмечает, что в целом «к» и «последний» части вашего кода не требуются при всех

+1

Пустые фигурные скобки недействительны в C; вам нужно хотя бы одно '0':' ... = {0}; '. –

+0

Спасибо за помощь! –

+0

@Brook Renzi: вы можете использовать отладчик, чтобы быстро находить такие проблемы. – eyalm

0

Изменить

while (list->next!=NULL){ 

в

while (list != NULL){ 

Там могут быть и другие проблемы, но это первое, что я заметил.

+0

У меня действительно было, что на самом деле спасибо за помощь на этом фронте. –