1
votes

Supprimer le premier élément d'une structure

J'ai un code dans lequel j'essaye de supprimer le premier identifiant d'une structure. Cela fonctionnait, mais maintenant il renvoie simplement "ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ" (lettre russe répétée). J'ai essayé de réinstaller VS, je n'ai pas aidé. Je sais que cela fonctionne parce que je l'ai essayé sur un compilateur en ligne. Ces deux avertissements pointent également vers la fonction de suppression, dont je suppose que c'est le problème. Avertissement C4156 suppression d'une expression de tableau sans utiliser la forme de tableau de 'delete'; forme de tableau substituée
Avertissement C4154 suppression d'une expression de tableau; conversion en pointeur fournie

Voici le code 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;
}

P.S. Delete fait la même chose quoi que j'essaye, dans n'importe quel code P.S.S. Désolé pour le mauvais formatage, c'est la façon dont notre prof en a besoin


7 commentaires

Initialisez également vos variables, ne désactivez pas la vérification des erreurs. Votre application fonctionnera mal si vous ne


Puisque vous programmez en C ++: 1) Le mot-clé struct n'est pas nécessaire lors de la déclaration de variables ou de pointeurs. 2) Préférez utiliser new pour la mémoire dynamique; le malloc n'appelle pas les constructeurs. 3) Préférez utiliser std :: string , car il gère la mémoire dynamique pour vous (et il est facile de passer et de copier).


Ne pas supprimer p-> id . Le champ id de la structure n'est pas alloué dynamiquement.


Pensez à passer les pointeurs par référence. L'ajout d'un niveau d'indirection ouvre des possibilités pour plus de problèmes (défauts).


Êtes-vous vraiment sûr de vouloir désactiver les avertissements de variables non initialisées? C'est l'un des avertissements les plus utiles à mon avis.


"c'est la façon dont notre prof en a besoin" - veuillez noter que nous ne sommes pas votre professeur. Vous êtes autorisé à reformater votre code pour nous. En fait, cela pourrait être apprécié. Dans le même ordre d'idées, puisque nous ne sommes pas votre professeur, vous êtes autorisé / encouragé à simplifier votre code en un exemple reproductible minimal .


@ user4581301 bien, j'ai essayé j = NULL, rien n'a changé.


3 Réponses :


3
votes

N'appelez pas delete p-> id . Cela ne sert à rien sauf à planter votre programme: ni lui ni la structure dans laquelle il se trouve n'ont été alloués par new .

De plus, n'utilisez jamais delete pour essayer de libérer malloc ed mémoire, ou free pour libérer de la nouvelle mémoire ed.

Vouliez-vous supprimer tout le premier nœud? Ensuite, faites quelque chose comme

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

La suppression d'un nœud au milieu est en fait un peu plus facile. Utilisez des "pointeurs de poursuite" qui pointent vers l'élément précédent ( prev ) et l'élément courant ( cur ). Si cur est le nœud que vous souhaitez supprimer, faites simplement

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

(en supposant que vous allouiez des nœuds avec new , qui vous devriez!)


2 commentaires

Merci, cela fonctionne, mais j'essaie toujours de comprendre pourquoi cela n'a pas fonctionné sur mon PC mais fonctionne dans un compilateur en ligne. Et comment pourrais-je supprimer un certain nœud au milieu sans supprimer les premiers?


Si cela semble «fonctionner», c'est entièrement par accident. Essayer de supprimer ou libérer de la mémoire qui n'a pas été allouée avec le bon allocateur est la définition même du comportement indéfini. Quant à la suppression au milieu, voyez ma réponse.



1
votes

Je comprends que parfois les professeurs veulent les choses à leur manière, mais il est tout aussi important de savoir quelle serait la façon la plus simple d'atteindre vos objectifs.

C'est ce que j'ai proposé. Notez qu'il n'y a pas de gestion manuelle de la mémoire, le tri est automatisé et vous pouvez facilement remplacer le type de conteneur. Dans la plupart des cas, le vecteur sera parfaitement adéquat - la liste ne doit être utilisée que si les benchmarks montrent que vous obtenez de meilleures performances. Dans la plupart des cas - vous ne le ferez pas (contrairement à ce que les professeurs peuvent vous dire: faites confiance à la réalité plutôt qu'aux enseignements).

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;
}

Exemple de session:

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


0 commentaires

1
votes
pech_sp(p);
delete p;

2 commentaires

Mais j'ai besoin de sortir la liste avec le nœud supprimé, comment puis-je faire cela sans l'appeler après la suppression?


@DaniAli Que voulez-vous dire "afficher la liste avec le nœud supprimé"?