Search in a doubly linked list

An array of instances of the contact structure is read from the file. These instances form a doubly linked list. The search() function outputs the entire list starting with the sequence number that the user enters. To save time with large lists, I made a search for an element from 2 sides( depending on the position of the element relative to the center of the list) when entering the list from the head-it works, but when entering from the end, an error pops up, because the last one in the list is the first one the element. How can I fix this error?

#include "stdafx.h"
#include<cstdlib>
#include<string.h>
#include<iostream>

struct contact
{
    char nomer[50];
    char adress[50];
    char sname[50];
};

struct Node
{
    char nomer[50];
    char adress[50];
    char sname[50];
    Node *next, *prev;
};typedef Node *PNode;

PNode CreateNode(contact buf)
{
    PNode NewNode = new Node;
    strcpy(NewNode->nomer, buf.nomer);
    strcpy(NewNode->adress, buf.adress);
    strcpy(NewNode->sname, buf.sname);
    NewNode->next = NULL;
    NewNode->prev = NULL;
    return NewNode;
}

void AddNode(PNode &Head, PNode &Tail, PNode NewNode)
{
    NewNode->next = NULL;
    NewNode->prev = Tail;
    if (Tail) Tail->next = NewNode;
    Tail = NewNode;
    if (!Head) Head = Tail;
}

void AddAfter(PNode &Head, PNode &Tail, PNode p, PNode NewNode)
{   
    if (p==Tail)
{
    NewNode->prev = Tail;
    Tail = NewNode;
}
    NewNode->next = p->next;
    NewNode->prev = p;
    if (p->next)
    p->next->prev = NewNode;
    p->next = NewNode;
    Tail= NewNode;// add
}
void AddBefore(PNode &Head, PNode &Tail, PNode p, PNode NewNode)
{
    if (Head == p)
    {
        NewNode->next = Head;
        Head = NewNode;
    }
    else
    {
        NewNode->prev = p->prev;
        NewNode->next = p;
        p->prev->next = NewNode;
        p->prev = NewNode;
    }
}    


void ShowTwoLinkedList(PNode Head)
{
    PNode p = Head;
    while (p != NULL)
    {
        printf("%s\n", p->sname);
        p = p->next;
    }
    fflush(stdin);
    getchar();
}    

void AddAndSort(contact buf, PNode Head, PNode Tail)
{
    PNode NewNode = CreateNode(buf);
    PNode p = Head;
    while (p->next && (strcmp(p->sname, NewNode->sname) < 0))
        p = p->next;
    if ((strcmp(p->sname, NewNode->sname) < 0))
        AddAfter(Head, Tail, p, NewNode);
    else
        AddBefore(Head, Tail, p, NewNode);
}
int Search(PNode Head,PNode Tail,int NumOfPosition, int kol_el)
{
    if ((NumOfPosition < 1) || (NumOfPosition > (kol_el)))
    {
        printf("Ошибка:некорректный ввод позиции в списке.\n");
        return -1;
    }
    else if (kol_el / 2 >= NumOfPosition)
        {//cлева
            int count = 1;
            PNode p = Head;
            while (count != NumOfPosition)
            {
                p = p->next;
                count++;
            }
            system("cls");
            printf("Информация по запросу:\n");
            while (p->next)
            {
                printf("%s\n", p->sname);
                printf("%s\n", p->adress);
                printf("%s\n", p->nomer);
                printf("\n\n");
                p = p->next;
            }
            system("pause");
        }
        else 
        {
            //справа
            int count = kol_el;
            PNode p = Tail;
            while (count != NumOfPosition)
            {
                p = p->prev;
                count--;
            }
            system("cls");
            printf("Информация по запросу:\n");
            while (p->next)
            {
                printf("Информация по запросу:\n");
                printf("%s\n", p->sname);
                printf("%s\n", p->adress);
                printf("%s\n", p->nomer);
                printf("\n\n");
                p = p->next;
            }
            system("pause");

        }
}    

int main()
{
    setlocale(LC_ALL, "RUS");
    int rezh;
    PNode Head = NULL;
    PNode Tail = NULL;
    FILE *f;
    f = fopen("telbook.dat", "r+b");
    fseek(f, 0, SEEK_END);
    int size = ftell(f);
    int kol_el = size / sizeof(contact);
    contact *buf = new contact[kol_el];
    fseek(f, 0, SEEK_SET);
    fread(buf, sizeof(contact), kol_el, f);
    fclose(f);
        do {
        system("cls");
        const int NotUsed = system("color 03");
        printf("Выберите действие:\n");
        printf("1.Показать список.\n");
        printf("2.Создание+сортировка.\n");
        printf("3.Поиск по списку.\n");
        printf("4.Выйти из программы.\n");
        scanf_s("%d", &rezh);
        switch (rezh)
        {
        case 1:
        {
            ShowTwoLinkedList(Head);
            break;
            }    

        case 2:
        {
            PNode NewNode = CreateNode(buf[0]);
            AddNode(Head, Tail, NewNode);
            for (int i = 1; i < kol_el; i++)
                AddAndSort(buf[i], Head, Tail);
            break;
        }

        case 3:
        {
            system("cls");
            printf("Введите номер:\n");
            int NumOfPosition;
            scanf("%d", &NumOfPosition);
            Search(Head,Tail,NumOfPosition,kol_el);
        }
        }
    } while (rezh != 4);
    system("pause");
    return 0;    
Author: Qwertiy, 2016-06-05

1 answers

We've got some pointers. Each item in your list should have a pointer to the next one and the previous one (except the head one, which doesn't have the previous one, and the last one, which doesn't have the next one). Well, I got the idea.

  1. In your AddAfter method, the end of the list is constantly overwritten with a new element, from where errors with pointers come from. The AddBefore method is also muddy.
  2. The actual search, the Search method. The string while (p->next) in the condition will always cut off the last element, i.e. the search will be up to the penultimate item in the list (maybe it is necessary, but I think it is not necessary).
  3. The main loop with the menu, at the very beginning is system("cls"); to clear the screen. When you display the contents of the list, the contents are displayed and the screen is cleared immediately, you can add the same delay as in the search.

The actual code:

void AddAfter(PNode &Head, PNode &Tail, PNode& p, PNode NewNode)
{
    // Для добавляемой ноды устанавливаем указатели на следующую и предыдущую ноды списка
    NewNode->next = p->next;
    NewNode->prev = p;

    // Для ноды, следующей ЗА замещаемой, изменяем указатель на предыдущую ноду
    if (p->next)
        p->next->prev = NewNode;

    // Для замещаемой ноды изменяем указатель на следующую ноду
    p->next = NewNode;

    // Если это конец списка, то перезаписываем указатель конца списка
    if (p == Tail)
        Tail = NewNode;
}

void AddBefore(PNode &Head, PNode &Tail, PNode& p, PNode NewNode)
{
    // Для добавляемой ноды устанавливаем указатели на следующую и предыдущую ноды списка
    NewNode->next = p;
    NewNode->prev = p->prev;

    // Для ноды, следующей ПЕРЕД замещаемой, изменяем указатель на следующую ноду
    if (p->prev)
        p->prev->next = NewNode;

    // Для замещаемой ноды изменяем указатель на предыдущую ноду
    p->prev = NewNode;

    // Если это начало списка, то перезаписываем указатель начала списка
    if (p == Head)
        Head = NewNode;
}

In the Search method, replace while (p->next) with while (p)

 1
Author: goldstar_labs, 2016-10-08 10:07:17