Removing an item from the beginning of a singly linked C++list

I wrote a program for working with a singly linked list. Each element has a name (name) and content (content), which is filled in by the user, and it is also assigned a system creation time and a request counter. The program is managed via the console.

The problem is that the delete function (file *perish) is not working properly. The function must find the element corresponding to the entered name in the list using the find_name function. Removal from the middle and end of the list works correctly, but when you delete an item at the beginning, its name field is filled in with machine code and remains in the list.

Please help me solve this problem. Here is my code:

#include <iostream>
#include <iomanip>
#include <conio.h>
#include <windows.h>

using namespace std;

class file
{
    public:
        char name[64];
        char content[256];
        int count;
        int day, month, year, min, hour;

        file *next;
};

file *add(file *head) //добавление узла в список
{
    file *pv = new file;
    pv->next = 0;

    cout << "Name of the file: ";
    cin.getline(pv->name, sizeof pv->name);

    pv->count = 0; 

    cout << "Input the content of the file: " << endl;;
    cin.getline(pv->content, sizeof pv->content);

    SYSTEMTIME st;
    GetSystemTime(&st);
    pv->day = st.wDay;
    pv->month = st.wMonth;
    pv->year = st.wYear;
    pv->hour = st.wHour;
    pv->min = st.wMinute;

    if(head)
    {
        file *temp = head;
        while(temp->next) 
            temp = temp->next;
        temp->next = pv;
    }
    else
        head = pv;
    return head;

}

void print(file *head) //вывод списка на экран
{
    if(head == 0)
    {
        system("cls");
        cout << "The catalog is empty!";
    } 
    else
    {
        while(head != 0){
            cout << head->name << "\t" << "\t" << head->day << "." << head->month << "." << head->year << " " << head->hour << ":" << head->min << "\t" << "\t" << head->count << endl;
            head = head->next;
        }
    }
}

file *find_name(file *pv, char *name, file** prev){ //нахождение файла в списке по имени
    *prev = 0;

    while(pv)
    {
        if(strstr(pv->name, name)) return pv;
        *prev = pv;
        pv = pv->next;
    }
    return 0;
}

file *perish(file *head) //удаление найденного по имени файла
{
    char name[64];
    system("cls");
    cout << "Input the name: ";
    cin.getline(name, sizeof name);

    file *prev;
    file *pv = find_name(head, name, &prev);
    if(pv)
    {
        if(pv == head) 
            head = head->next; 
        else 
            prev->next = pv->next;
        delete pv;
    }
    return head;
}

int main()
{
    file *head = 0;

    char ckey;
    do
    {
        system("cls");
        cout << "1 - Add file to the catalog\n";
        cout << "2 - Open the catalog\n";
        cout << "3 - Delete the file\n";
        cout << "4 - Exit\n";

        ckey = _getch();
        system("cls");

        if(ckey == '1') head = add(head);

        else if(ckey == '2')
        {
            cout << "Name" << "\t" << "\t" << "Date" << "\t" << "\t" << "\t" << "Count" << endl;
            print(head);
        }
        else if(ckey == '3') perish(head);
        else if(ckey == '4') 
        {
            cout << "Closing..." << endl;   
        }
        else continue;
        _getch();

    } while(ckey != '4');

    system("pause");
    return 0;
}
Author: Qwertiy, 2018-04-28

2 answers

The problem is in this line:

else if(ckey == '3') perish(head);

As I understood here you delete objects. And now look at the delete function:

file *perish(file *head)

Here you return a value. What is this value? And this is our head - if the first element was deleted, then head changes. But the change does not occur in the function - it returns a new value, which should be assigned to head. That is, it should be like this:

else if(ckey == '3') head = perish(head);

Well, the code is really bad, so with classes it is not they're coming in.

 0
Author: Andrej Levkovitch, 2018-04-28 09:50:31

I'll start with the implementation: it's better for ListNode to implement either its own mini class, or a structure in the form:

template <class V>
class ListNode {
private:
    V value;
    ListNode <V> *next;
public:
    template <class _V> friend class List;
protected:
};

And already everything else is already implemented as a class with a pointer *first

Then the class method for deleting an element should look something like this:

template <class V>
void List::remove (ListNode * rm) {
    if (rm == first) {
        first = first->next;
    } else {
        ListNode <V> * c = first;
        while (c->next != rm) { c = c->next; }
        c->next = c->next->next;
    }
    delete rm; // Если память под элемент была выделена через new
    return;
}
 0
Author: Алексей Исмагилов, 2018-05-01 15:23:55