Потеря элементов вложенного списка при повторном их отображении - PullRequest
0 голосов
/ 02 июня 2019

Я пытаюсь создать «библиотеку», используя вложенные списки. Все работало нормально, я мог добавлять элементы, используя свои отсортированные функции добавления, пока не заметил, что, если я отобразлю список два раза подряд, в первый раз все будет хорошо, но во втором "элементы книги" добавлены в каталоги. не отображаются, как будто их там нет.

struct book
{
    char *title;
    int number;
    char *country;
    struct book* new;
};

struct catalog
{
    char *name;
    struct catalog* next;
    struct book* firstbook;
};

void printList(struct catalog *head)
{
    struct catalog *temp = head;
    while(temp != NULL)
    {
        if(temp->firstbook == NULL)
        {
            printf("%s\n", temp->name);

        }
        while(temp->firstbook != NULL)
        {   printf("%s  ", temp->name);
            printf("%s  ", temp->firstbook->title);
            printf("%d  ", temp->firstbook->number);
            printf("%s\n", temp->firstbook->country);
            temp->firstbook = temp->firstbook->new;
        }
        temp = temp->next;
    }
}

struct book *newbook(char *booktitle, int number, char *country)
{
    struct book* newbook = (struct book*) malloc(sizeof(struct book));
    newbook->title = malloc(sizeof(strlen(booktitle)+1));
    newbook->country = malloc(sizeof(strlen(country)+1));
    newbook->title = booktitle;
    newbook->country = country;
    newbook->number = number;
    newbook->new = NULL;
}

struct catalog *findcatalog(struct catalog** head, char *catalogname)
{
    struct catalog* current;
    current = *head;
    while(current != NULL)
    {
        if(current->name == catalogname)
        {
            return current;
        }
        current = current->next;
    }
}

void sortedBookInsert(struct catalog** head, char *catalogname, char *booktitle, int number, char *country)
{
    struct catalog* searched;
    struct book* pom;
    struct book* ksiazka = newbook(booktitle, number, country);
    searched = findcatalog(head, catalogname);
    if(searched->firstbook == NULL || strcmp(searched->firstbook->title, ksiazka->title)>0)
    {
        ksiazka->new =searched->firstbook;
        searched->firstbook = ksiazka;
    }
    else
    { pom = searched->firstbook;
        while(pom->new!= NULL && strcmp(searched->firstbook->title, ksiazka->title)< 0)
        {
            pom = pom->new;
        }
        ksiazka->new = pom->new;
        pom->new = ksiazka;
    }
}

void sortedInsert(struct catalog** head,char *name)
{
    struct catalog* current;
    struct catalog* new_node = newcatalog(name);

    if (*head == NULL || strcmp((*head)->name, new_node->name) > 0)
    {
        new_node->next = *head;
        *head = new_node;
    }
    else
    {
        current = *head;
        while (current->next!=NULL && strcmp(current->next->name, new_node->name) < 0)
        {
            current = current->next;
        }
        new_node->next = current->next;
        current->next = new_node;
    }
}

int main () {

struct catalog* head = NULL;
sortedInsert(&head, "Kappa");
sortedInsert(&head, "Aaaaaa");
sortedInsert(&head, "Sdafscx");
sortedInsert(&head, "Saxzxc");
sortedInsert(&head, "Asdas");
sortedInsert(&head, "Zzzzzzzz");
sortedInsert(&head, "Country");
sortedBookInsert(&head, "Country", "PKP", 11111, "Germany");
sortedBookInsert(&head, "Country", "Polacy", 11112, "Italy");
sortedBookInsert(&head, "Country", "Autobusy", 11234, "France");
sortedBookInsert(&head, "Country", "Polityka", 14111, "Russia");
printList(head);
printList(head);
return 0;

}

When I print my list for a second time, elements from SortedBookInsert just... are not there. I am very confused.

1 Ответ

1 голос
/ 02 июня 2019

возврат отсутствует в newbook , должен быть

struct book *newbook(char *booktitle, int number, char *country)
{
    struct book* newbook = (struct book*) malloc(sizeof(struct book));
    newbook->title = malloc(sizeof(strlen(booktitle)+1));
    newbook->country = malloc(sizeof(strlen(country)+1));
    newbook->title = booktitle;
    newbook->country = country;
    newbook->number = number;
    newbook->new = NULL;

    return newbook;
}

без возврата поведение не определено.

Обратите внимание, что вы создаете 2 утечки памяти, выполняя:

newbook->title = malloc(sizeof(strlen(booktitle)+1));
newbook->country = malloc(sizeof(strlen(country)+1));
newbook->title = booktitle;
newbook->country = country;

но вы также не выделяете правильную длину из-за sizeof , должно быть

newbook->title = malloc(strlen(booktitle)+1);
newbook->country = malloc(strlen(country)+1);
strcpy(newbook->title, booktitle);
strcpy(newbook->country, country);

В findcatalog возврата также нет, если каталог не найден, должно быть

struct catalog *findcatalog(struct catalog** head, char *catalogname)
{
    struct catalog* current;
    current = *head;
    while(current != NULL)
    {
        if(current->name == catalogname)
        {
            return current;
        }
        current = current->next;
    }
    return NULL;
}

без возврата поведение не определено.

В sortedBookInsert может потребоваться проверить, не равен ли искомый значение NULL, прежде чем searched->firstbook, например:

void sortedBookInsert(struct catalog** head, char *catalogname, char *booktitle, int number, char *country)
{
    struct catalog* searched;
    struct book* pom;
    struct book* ksiazka = newbook(booktitle, number, country);
    searched = findcatalog(head, catalogname);
    if (searched == NULL)
      return;
    if(searched->firstbook == NULL || strcmp(searched->firstbook->title, ksiazka->title)>0)
    {
        ksiazka->new =searched->firstbook;
        searched->firstbook = ksiazka;
    }
    else
    { pom = searched->firstbook;
        while(pom->new!= NULL && strcmp(searched->firstbook->title, ksiazka->title)< 0)
        {
            pom = pom->new;
        }
        ksiazka->new = pom->new;
        pom->new = ksiazka;
    }
}

но, честно говоря, я не уверен в этом

In findcatalog

if(current->name == catalogname)

должно быть

if(!strcmp(current->name, catalogname))

Функция printList изменить каталог, выполнив temp->firstbook = temp->firstbook->new;, вам нужно заменить

   while(temp->firstbook != NULL)
   {   printf("%s  ", temp->name);
       printf("%s  ", temp->firstbook->title);
       printf("%d  ", temp->firstbook->number);
       printf("%s\n", temp->firstbook->country);
       temp->firstbook = temp->firstbook->new;
   }

например:

struct book* firstbook = temp->firstbook;

    while(firstbook != NULL)
    {   printf("%s  ", temp->name);
        printf("%s  ", firstbook->title);
        printf("%d  ", firstbook->number);
        printf("%s\n", firstbook->country);
        firstbook = firstbook->new;
    }

Если я сделаю все эти модификации и использую это определение:

struct catalog* newcatalog(char *name)
{
  struct catalog* r = malloc(sizeof(struct catalog));

  r->name = malloc(strlen(name)+1);
  strcpy(r->name, name);
  r->next = NULL;
  r->firstbook = NULL;

  return r;
}

Компиляция и исполнение:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wall -Wextra l.c
pi@raspberrypi:/tmp $ ./a.out
one
Aaaaaa
Asdas
Country  Autobusy  11234  France
Country  PKP  11111  Germany
Country  Polacy  11112  Italy
Country  Polityka  14111  Russia
Kappa
Saxzxc
Sdafscx
Zzzzzzzz
two
Aaaaaa
Asdas
Country  Autobusy  11234  France
Country  PKP  11111  Germany
Country  Polacy  11112  Italy
Country  Polityka  14111  Russia
Kappa
Saxzxc
Sdafscx
Zzzzzzzz
pi@raspberrypi:/tmp $ 

Исполнение под valgrind

pi@raspberrypi:/tmp $ valgrind ./a.out
==7575== Memcheck, a memory error detector
==7575== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7575== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==7575== Command: ./a.out
==7575== 
one
Aaaaaa
Asdas
Country  Autobusy  11234  France
Country  PKP  11111  Germany
Country  Polacy  11112  Italy
Country  Polityka  14111  Russia
Kappa
Saxzxc
Sdafscx
Zzzzzzzz
two
Aaaaaa
Asdas
Country  Autobusy  11234  France
Country  PKP  11111  Germany
Country  Polacy  11112  Italy
Country  Polityka  14111  Russia
Kappa
Saxzxc
Sdafscx
Zzzzzzzz
==7575== 
==7575== HEAP SUMMARY:
==7575==     in use at exit: 148 bytes in 11 blocks
==7575==   total heap usage: 12 allocs, 1 frees, 1,172 bytes allocated
==7575== 
==7575== LEAK SUMMARY:
==7575==    definitely lost: 12 bytes in 1 blocks
==7575==    indirectly lost: 136 bytes in 10 blocks
==7575==      possibly lost: 0 bytes in 0 blocks
==7575==    still reachable: 0 bytes in 0 blocks
==7575==         suppressed: 0 bytes in 0 blocks
==7575== Rerun with --leak-check=full to see details of leaked memory
==7575== 
==7575== For counts of detected and suppressed errors, rerun with: -v
==7575== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from

Обратите внимание, что в вашем коде вы даете буквальные строки для имен / названий / стран, чтобы они никогда не исчезали / не изменялись, поэтому дублировать их бесполезно, но это не будет иметь место в «реальном» случае, когда вы повторно используете тот же массив или персонаж получает их из файла или читает их на stdin и т. д., поэтому я рекомендую вам продублировать их, как я и предлагал

...