Удаление первого элемента в конструкции - PullRequest
1 голос
/ 17 июня 2020

У меня есть код, в котором я пытаюсь удалить первый идентификатор в структуре. Раньше работало, но теперь просто возвращает «ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ» (повторяющееся русское письмо). Пробовал переустановить VS, не помогло. Я знаю, что это работает, потому что я пробовал это на онлайн-компиляторе. Эти два предупреждения также указывают на функцию удаления, которая, как я предполагаю, является проблемой. Предупреждение C4156 удаление выражения массива без использования формы массива 'delete'; замещенная форма массива
Предупреждение C4154 удаление выражения массива; преобразование в предоставленный указатель

Вот код itslef:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <locale.h>
#include <iostream>
#pragma warning (disable: 4703) //disables warning of uninitialized variable j
using namespace std;
#define  MAXDL    9      
struct el_sp
{
    char  id[MAXDL];
    struct el_sp* sled;
};
void  vkl(struct el_sp** p, char t_id[]) //enters the entered ID's from keyboard into the struct
{
    struct el_sp* pt,
        * k, * j;
    pt = (struct el_sp*)malloc(sizeof(struct el_sp));
    strcpy_s(pt->id, t_id);
    if (*p == NULL || strcmp(pt->id, (*p)->id) < 0)
    {
        pt->sled = *p; *p = pt;
    }
    else
    {
        k = *p;
        while (k != NULL && strcmp(pt->id, k->id) >= 0)
        {
            j = k; k = k->sled;
        }
        j->sled = pt; pt->sled = k;
    }
}

void pech_sp(struct el_sp* p) //prints the struct
{
    struct el_sp* i;
    char* o;
    printf("\Result:\n");
    for (i = p; i != NULL; i = i->sled)
        puts(i->id);
}

int main() {
    setlocale(LC_ALL, "RUS");
    struct el_sp* p;
    unsigned  n;
    unsigned  i;
    char t_id[MAXDL];

    printf("\nEnter the amount of identificators\n n=");
    scanf_s("%u", &n);
    getchar();
    p = NULL;
    printf("Enter the identificators (press enter after each one)\n");
    for (i = 1; i <= n; i++)
    {
        gets_s(t_id);
        vkl(&p, t_id);
    }
    delete p->id;
    pech_sp(p);
    return 0;
}

PS Delete делает то же самое, что бы я ни пробовал, в любом коде PSS Извините за плохое форматирование, это то, что нужно нашему профи это

Ответы [ 3 ]

3 голосов
/ 17 июня 2020

Не звоните delete p->id. Это не служит никакой цели, кроме sh вашей программы: ни она, ни структура, в которой она находится, не были выделены new.

Кроме того, никогда не используйте delete, чтобы попытаться освободить malloc ed память , или free, чтобы освободить new ed память.

Вы хотели удалить весь первый узел? Затем сделайте что-нибудь вроде

el_sp *oldp = p;
p = p->next;
free(oldp);

Удаление узла посередине на самом деле немного проще. Используйте «указатели поиска», которые указывают на предыдущий элемент (prev) и текущий элемент (cur). Если cur - это узел, который вы хотите удалить, просто выполните

prev->next->next = cur->next;
delete cur;

(при условии, что вы выделяете узлы с new, что вам следует!)

1 голос
/ 17 июня 2020
struct el_sp
{
   char  id[MAXDL];
   struct el_sp* sled;
};

id - статически распределенный массив. Его нельзя удалить.

  delete p->id;

Выше неверно. Удаление указателя, память которого не выделена new, приводит к неопределенному поведению.

У вас должно быть

  delete p;

И после удаления вы не должны использовать p. Поэтому pech_sp следует вызывать до, а не после.

pech_sp(p);
delete p;
1 голос
/ 17 июня 2020

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

Это то, что я придумал. Обратите внимание, что нет ручного управления памятью, сортировка автоматизирована, и вы можете легко заменить тип контейнера. В большинстве случаев вектор будет вполне адекватным - список следует использовать только в том случае, если тесты показывают, что вы получаете лучшую производительность. В большинстве случаев - вы не будете (вопреки тому, что профессора могут сказать вам: доверяйте реальности, а не учениям).

#include <algorithm>
#include <clocale>
#include <iostream>
#include <list>
#include <vector>

struct El_Sp
{
    std::string id;
};

#if 1
using El_Spy = std::vector<El_Sp>;
#else
using El_Spy = std::list<El_Sp>;
#endif

template <> struct std::less<El_Sp>
{
    bool operator()(const El_Sp &l, const El_Sp &r) const
    { return l.id < r.id; }
};

std::istream &operator>>(std::istream &in, El_Sp &el_sp)
{
    return in >> el_sp.id;
}

std::ostream &operator<<(std::ostream &out, const El_Sp &el_sp)
{
    return out << el_sp.id;
}

std::ostream &operator<<(std::ostream &out, const El_Spy &el_spy)
{
    for (auto &el : el_spy)
        out << el << '\n';
    return out;
}

template <typename Container, typename T, typename Pred = std::less<typename Container::value_type>>
auto insert_sorted(Container &cont, T &&item, Pred pred = {})
{
    return cont.insert(
        std::upper_bound(std::begin(cont), std::end(cont), std::as_const(item), pred),
           std::forward<T>(item));
}

void enter_id(El_Spy &el_spy)
{
    El_Sp el;
    std::cin >> el;
    insert_sorted(el_spy, el);
}

int main()
{
    El_Spy el_spy;

    std::setlocale(0, "");
    size_t n = 0;
    std::cout << "Введите количество идентификаторов n=";
    std::cin >> n;
    std::cout << "Введите идентификаторы. Нажмите Enter после каждого.\n";
    while (n--)
        enter_id(el_spy);

    std::cout << "Идентификаторы:\n" << el_spy;
}

Пример сеанса:

Введите количество идентификаторов n=3                                                                                                          
Введите идентификаторы. Нажмите Enter после каждого.                                                                                            
Алла                                                                                                                                            
Дарья                                                                                                                                           
Вера                                                                                                                                            
Идентификаторы:                                                                                                                                 
Алла                                                                                                                                            
Вера                                                                                                                                            
Дарья                                                                                                                                           

При использовании std::vector, сортировка вставкой на самом деле не нужна - вы можете использовать std::sort после того, как были введены все идентификаторы:

int main()
{
    std::setlocale(0, "");
    size_t n = 0;
    std::cout << "Введите количество идентификаторов n=";
    std::cin >> n;

    El_Spy el_spy(n);
    std::cout << "Введите идентификаторы. Нажмите Enter после каждого.\n";
    for (auto &el_sp : el_spy)
        std::cin >> el_sp;

    std::sort(std::begin(el_spy), std::end(el_spy), std::less<El_Sp>());

    std::cout << "Идентификаторы:\n" << el_spy;
}

...