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
3 Réponses :
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!)
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.
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 поÑле каждого. Ðлла ÐаÑÑÑ ÐеÑа ÐденÑиÑикаÑоÑÑ: Ðлла ÐеÑа ÐаÑÑÑ
pech_sp(p); delete p;
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é"?
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 utilisernew
pour la mémoire dynamique; lemalloc
n'appelle pas les constructeurs. 3) Préférez utiliserstd :: 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 champid
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 a>.
@ user4581301 bien, j'ai essayé j = NULL, rien n'a changé.