Разработка программы для создания и работы с двусвязным списком, состоящим из структур. (Структура содержит фамилию и год рождения), страница 5

    int      strln = 0;

    int      it = 0;

    char    *buffer = (char*)malloc(sizeof(char) * szBuf);

    boolean  ret = TRUE;

    if (NULL == info)

    {

        puts("ERROR: wrong entry data");

        WaitAnyKey();

        return FALSE;

    }

    //ввод фамилии

    fseek(stdin, 0, SEEK_END);     //передвижение каретки в конец потока stdin

    printf("\nLast name: ");

    fgets(buffer, szBuf, stdin);   //безопасное чтение в буфер (на случай переполнения)

    fseek(stdin, 0, SEEK_END);     //передвижение каретки в конец потока stdin

    //выделение памяти для фамилии в структуре PersonalData

    strln = strlen(buffer);

    info->LastName = (char*)malloc(sizeof(char) * strln);

    memset(info->LastName, 0, sizeof(char) * strln);

    //копировать строку

    buffer[strln - 1] = 0;              //удалить символ переноса строки

    strcpy(info->LastName, buffer);

    //введение даты рождения (2 попытки, если первая – неудачна)

    while (FALSE == (ret = InputDate(&info->birthDate)))

    {

        if (it == 1)

        {

            break;

        }

        puts("Invalid date. Please try to enter again (Year: 1970 - 2037; Month: 1 - 12, Day: 1 - 30");

        it++;   //счетчик попыток ввода

    }

    if (ret)

    {

        printf("\n%s; %s\n\n", info->LastName, asctime(&info->birthDate));

    }

    free(buffer);   //очистка памяти

    return ret;

}

/*=======================================================================================

* Ввод даты

*======================================================================================*/

boolean InputDate(struct tm *date)

{

    if (NULL == date)

    {

        puts("ERROR: wrong entry data");

        WaitAnyKey();

        return FALSE;

    }

    fseek(stdin, 0, SEEK_END);                //передвижение каретки в конец потока stdin

    memset((void*)date, 0, sizeof(struct tm));//обнуление области памяти

    //ввод года

    printf("Enter year: ");

    scanf("%d", &date->tm_year);

    date->tm_year -= 1900;         //приведение года к стандарту хранения в структуре tm

    //ввод месяца

    printf("Enter month: ");

    scanf("%d", &date->tm_mon);

    date->tm_mon -= 1;           //приведение месяца к стандарту хранения в структуре tm

    //ввод дня

    printf("Enter day: ");

    scanf("%d", &date->tm_mday);

    //проверка введенной даты на корректность и возращение результата

    return mktime(date) == -1 ? FALSE : TRUE;

}

/*=======================================================================================

* Сравнение двух строк. «Колбэк» на нотификацию о сортировке.

* См. LL_SubscribeOnSortNotification()

*======================================================================================*/

int CompareLastNames_cb(const void* data1, const void* data2)

{

    PersonalData *info1 = (PersonalData*)data1;

    PersonalData *info2 = (PersonalData*)data2;

    char *str1 = NULL, *str2 = NULL;

    int ret = 0;

    int i = 0;

    if (NULL == data1 || NULL == data2)

    {

        return 0;

    }

    str1 = (char*)malloc(sizeof(char) * (strlen(info1->LastName) + 1));

    str2 = (char*)malloc(sizeof(char) * (strlen(info2->LastName) + 1));

    strcpy(str1, info1->LastName);

    strcpy(str2, info2->LastName);

    //приведение строки к нижнему регистру

    for (i = 0; i <= (int)strlen(str1); i++)

    {

        str1[i] = (char)tolower(str1[i]);

    }

    //приведение строки к нижнему регистру

    for (i = 0; i <= (int)strlen(str2); i++)

    {

        str2[i] = (char)tolower(str2[i]);

    }

    ret = strcmp(str1, str2);    //сравнение строк

    free(str1);

    free(str2);

    return ret;

}

/*=======================================================================================

* Очистка памяти: удаление указателя на строку (фамилия). «Колбэк» на нотификацию

* об удалении элемента. См. LL_SubscribeOnItemRemovingNotification

*======================================================================================*/

void FreePersonalData_cb(const void* userData)

{

    PersonalData *stuff = (PersonalData*)userData;

    if (stuff->LastName) free(stuff->LastName);

}

4.2.  Листинг модуля ‘llist.c’ – имплементация двусвязного списка

#include <stdlib.h>

#include <memory.h>

#include "LListcmn.h"

typedef struct LL_Item

{

    struct LL_Item *prev;    //предыдущий элемент. NULL, если первый

    struct LL_Item *next;    //следующий элемент. NULL, если последний

    void           *data;    //данные пользователя

} LL_Item;

typedef struct LL_LinkedList

{

    struct LL_Item *first;         //первый элемент в списке

    struct LL_Item *last;          //последний элемент в списке

    struct LL_Item *current;       //элемент на котором остановилось итерация списка

    LL_ItemRemovingNotification ItemRemovingNotification; //«колбэк» для нотификации об удалении элемента. См. LL_ItemRemovingNotification (llist.h)

    LL_CompareItems_cb          ItemSortNotification;     //«колбэк» для нотификации о сортировке. См. LL_CompareItems_cb (llist.h)

} LL_LinkedList;

/*=========================================================================================

* Функция создает новый список LL_LinkedList и возвращает на него указатель

* в newList

*========================================================================================*/

LL_Error LL_Create(LL_LinkedList **newList)

{

    LL_Error err = LL_ERR_OK;

    // проверка входных параметров

    if (NULL == newList || NULL != *newList)

    {

        return LL_ERR_BADPARAM;

    }

    // выделение памяти для нового списка

    *newList = (LL_LinkedList*)malloc(sizeof(LL_LinkedList));

    if (NULL != *newList)

    {

        memset(*newList, 0, sizeof(LL_LinkedList));

    }

    else

    {