En gros ma console plante et se ferme donc aucune erreur de compilation. Et quand j'essaye de remplacer "->" par "." j'ai le message d'erreur suivant :
error : 'liste_1' is a pointer; did you mean to use '->' ?
C'est à dire qu'il doit être initialisé avec l'adresse d'une zone mémoire valide (allouée).
Dans ce cas on peut utiliser malloc pour allouer de la mémoire vers laquelle on le fera pointer.
Tant que tu n'as pas initialisé le pointeur avec l'adresse d'un espace mémoire valide tu ne peux pas l'utiliser !
Ton pointeur, il ne pointe nulle part et surtout n'importe où, donc plantage si tu l'utilises avant de l'avoir initialisé avec l'adresse d'un espace mémoire valide
PS : Avec un pointeur c'est bien l'opérateur -> qu'il faut utiliser.
> En gros ma console plante et se ferme donc aucune erreur de compilation
Si la console "plante", c'est à l'exécution, pas à la compilation (qui a pu produire des avertissements en trouvant le code chelou, il faudrait regarder).
Et ça veut dire quoi, que "la console plante" ? Elle se referme illico ? Pourquoi elle ne devrait pas se refermer ?
On n'a pas assez de code sous les yeux pour pouvoir en dire quelque chose qui soit basé sur des faits plutôt que des suppositions. On va pas jouer aux devinettes sur des millions de causes possibles.
- Edité par michelbillaud 28 septembre 2022 à 17:54:47
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct elem{
int valeur ;
struct elem *suivant ;
}element ;
typedef element *liste ;
bool is_empty(liste list1){
if (list1){
printf("La liste contient au moins un élément") ;
return false ;
}
else{
printf("La liste est vide.") ;
return true ;
}
}
liste insert_head (liste list1, int v){
liste temp ;
temp =( element*)malloc(sizeof(element)) ;
temp->valeur=v ;
temp->suivant=list1->suivant ;
list1 = temp ;
return list1 ;
}
liste insert_tail (liste list1, int v){
liste parcours, temp ;
parcours = ( element*)malloc(sizeof(element)) ;
temp = ( element*)malloc(sizeof(element)) ;
parcours = list1 ;
while (parcours->suivant){
parcours = parcours->suivant ;
}
temp =( element*)malloc(sizeof(element)) ;
temp->valeur=v ;
parcours->suivant = temp ;
return list1 ;
}
liste remove_head (liste list1){
liste temp, temp2 ;
temp = ( element*)malloc(sizeof(element)) ;
temp2 = ( element*)malloc(sizeof(element)) ;
temp = list1->suivant ;
temp2 = temp->suivant ;
list1 = temp2 ;
free(temp) ;
return list1 ;
}
liste remove_tail (liste list1){
liste parcours1, parcours2 ;
parcours1 = ( element*)malloc(sizeof(element)) ;
parcours2 = ( element*)malloc(sizeof(element)) ;
parcours1 = list1 ;
parcours2 = parcours1 ;
while (parcours2->suivant){
parcours1 = parcours2 ;
parcours2 = parcours2 -> suivant ;
}
free(parcours2) ;
free(parcours1->suivant) ;
return list1 ;
}
void print_list(liste list1){
liste parcours ;
parcours = ( element*)malloc(sizeof(element)) ;
parcours = list1->suivant ;
printf("\n[") ;
while (parcours->suivant){
printf("%d, ",parcours->valeur) ;
parcours = parcours->suivant ;
}
printf("%d]",parcours->valeur) ;
}
int gestion_liste(liste list1, int c){
int reponse ;
if (c==0){
printf("Entrez le chiffre a ajouter en queue\n") ;
scanf("%d",&reponse) ;
insert_tail(list1, reponse) ;
}
else if (c==1){
printf("Entrez le chiffre a ajouter en tete\n") ;
scanf("%d",&reponse) ;
insert_head(list1, reponse) ;
}
else if (c==2){
printf("Suppression de la queue de la liste\n") ;
remove_tail(list1) ;
}
else if (c==3){
printf("Suppression de la tete de la liste\n") ;
remove_head(list1) ;
}
else if (c==4){
print_list(list1) ;
}
else{
return false ;
}
return true ;
}
int main()
{
bool continuer = true ;
int rep ;
liste liste_1 ;
liste_1 = ( element*)malloc(sizeof(element)) ;
while (continuer){
printf("Que voulez-vous faire ?\n") ;
printf("0 = Ajouter queue ; 1 = Ajouter tete ; 2 = Supprimer queue ; 3 = Supprimer tete ; 4 = Afficher liste\n") ;
scanf("%d",&rep) ;
continuer = gestion_liste(liste_1,rep) ;
}
}
Voilà le code complet. Quand par exemple j'entre "0" (pour ajouter un élément) et qu'après je rentre "5" (élément à ajouter en queue de la liste), la console tourne dans le vide alors qu'elle devrait me redemander "Que voulez-vous faire ?".
Le moins qu'on puisse dire est que tu aimes faire des malloc ... parcours = ( element*)malloc(sizeof(element)) ; temp = ( element*)malloc(sizeof(element)) ; parcours = list1 ; Et temp->suivant tu ne l'initialises pas à la fin? Pourquoi retourner list1 si tu ne le modifie pas? (tu modifies ses composantes, mais c'est un pointeur)
OK on est obligé de le retourner si on n'a pas de descripteur de liste ... C'est plus compliqué sans descripteur de liste. Comment peut-on avoir une liste vide?
Est-ce que tu le gères?
Dans le main, tu n'initialises pas liste_1. Ça vaut n'importe quoi.
Ton insertion au début ne marchera pas. Le suivant de NULL c'est n'importe où (dans la nature ...)
- Edité par PierrotLeFou 28 septembre 2022 à 18:55:46
Le Tout est souvent plus grand que la somme de ses parties.
Effectivement, il bien trop de malloc et pas les free qui vont avec !
A mon avis, il faut tout reprendre du début. Et avant de faire l'interface, il faut faire les principales fonctions et les tester !
Tu peux commencer par la fonction insert_head par exemple et la fonction print_list pour voir si ta liste se rempli bien. Tu t'occuperas du reste quand cela fonctionnera !
Ne pas oublier que les paramètres de fonctions sont passé par copie.
Je vais suivre vos conseils mais du coup les malloc je les ai ajouté parce que on m'a dit de le faire un peu plus haut, et là personne ne donne de réponse à mon problème, à savoir pourquoi est ce que je ne peux pas accéder aux valeurs de mes noeuds en utilisant "list1->valeur", c'est ça dont j'ai besoin.
Voilà le code complet. Quand par exemple j'entre "0" (pour ajouter un élément) et qu'après je rentre "5" (élément à ajouter en queue de la liste), la console tourne dans le vide alors qu'elle devrait me redemander "Que voulez-vous faire ?".
Ce n'est pas le cas ici
$ gcc -Wall -Wextra a.c
$ ./a.out
Que voulez-vous faire ?
0 = Ajouter queue ; 1 = Ajouter tete ; 2 = Supprimer queue ; 3 = Supprimer tete ; 4 = Afficher liste
0
Entrez le chiffre a ajouter en queue
5
Que voulez-vous faire ?
0 = Ajouter queue ; 1 = Ajouter tete ; 2 = Supprimer queue ; 3 = Supprimer tete ; 4 = Afficher liste
Histoire de dire quelque chose :
A partir de ce bout de code
typedef element *liste ;
liste insert_head (liste list1, int v){
liste temp ;
temp =( element*)malloc(sizeof(element)) ;
temp->valeur=v ;
temp->suivant=list1->suivant ;
1. Définir un typedef pour des pointeurs est généralement une mauvaise idée.
En C, on est quasiment obligé tout le temps de savoir si un truc contient des données ou est l'adresse d'une donnée, on n'en fera pas la même chose. . La preuve dans ton malloc, tu parles d'element. Ou sinon tu parlerais de *temp, ce qui implique de savoir que c'est un pointeur. C n'est pas le langage idéal pour l'abstraction
ca fait un nom de plus à garder en tete, alors que element* fait l'affaire
2. Si tu veux faire de l'abstraction, définis plutot list comme une structure contenant un pointeur vers son premier élément. Tu nous remerciera quand tu passeras à des listes doublement chainées et/ou indication du nombre d'éléments.
3. Depuis des temps où vous étiez pas nés (comme les poissons), malloc retourne un pointeur génériques (void *) que le langage C convertit comme un grand. Il faut donc eliminer les typecasts explicites qui n'apportent aucune information, et donc causent du bruit.
4. il est de bon goût de combiner déclaration et initialisation des variables à une valeur qui a un sens, quand c'est possible.
Donc ça donnerait
liste insert_head (element *first, int v){
element *temp = malloc(sizeof(element)) ;
;...
ce qui est quant même plus simple, et plus lisible
5. Il faut éviter de se répéter, allouer un élément et initialiser ses champs est une opération fréquente, qu'on condense dans une fonction
element * nouvel_element(int valeur, element *suivant)
{
element *nouveau = malloc(element);
nouveau->valeur = valeur;
nouveau->suivant = suivant;
return nouveau;
}
et qu'on réutlilise à tour de bras
liste insert_head (element *first, int v)
{
element *temp = nouvel_element(v, ....);
PS: les listes avec élément fictif au début, c'est pas une idée géniale. Ca traine dans quelques bouquins célèbres, mais à la rubrique "y en a aussi qui font comme ça" (*). En fait l'élément fictif tient lieu, maladroitement, de la structure avec pointeur sur le premier vrai élément, voir plus haut.
(*) on faisait effectivement parfois comme ça en assembleur, il y a des décennies. Autres langages, autres considérations de génie logiciel (on ne définissait pas de _types_, en assembleur)
- Edité par michelbillaud 29 septembre 2022 à 13:45:39
Ok merci beaucoup pour ta réponse j'en prends bonne note, t'as l'air d'avoir raison et c'est vrai que ma structure est un peu bizarre mais je me base sur des cours et instructions de mon prof (pour le malloc, ou le typedef element *liste), du coup je sais pas vraiment quoi faire...
Je vais essayer de chopper la correction et de la comparer avec mon prog et les conseils que tu m'as donné, mais je te suis vraiment reconnaissant !!!
> mais je me base sur des cours et instructions de mon prof
Il faut toujours faire comme dit le prof, pour les trucs qu'il dit de faire (et de lui rendre pour qu'il les note).
Après, rien n'empêche de regarder plusieurs façons, et de comparer. Et de chercher à comprendre pourquoi les uns font comme ci et les autres comme ça. Ils ont certainement des raisons. Pour certains, c'est juste qu'ils l'ont vu quelque part dans un bouquin où ils piquent les exos (Sedgewick ?) sans se poser de questions.
- Edité par michelbillaud 29 septembre 2022 à 18:33:18
> Force est de constater que j'ai TOUJOURS raison. Il est comme moi. Il a toujours raison, sauf quand il a tort.
Le Tout est souvent plus grand que la somme de ses parties.
Modifier valeur dans une liste chainée
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.