[C] Supression d'un élément

Résolu/Fermé
pweteur Messages postés 24 Date d'inscription vendredi 9 juin 2006 Statut Membre Dernière intervention 26 mars 2007 - 23 janv. 2007 à 16:13
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 - 25 janv. 2007 à 19:42
Bonsoir, je suis sous windows XP et j'utilise le compilo Dev-C++ et enfaite voila j'aimerai savoir si il est possible d'éffacer
un élément bien spécifique sans effacer la ligne compléte de la liste ? exemple je la struc suivante :

typedef struct Utilisateur Utilisateur;
struct Utilisateur {
char email[64];
char nom[20];
char prenom[40];
struct Utilisateur *next;
};

Et j'ai réussit à y ajouter deux entrées. C'est entrée sont quand je fait la liste:

monmail@mon_fournisseur.fr Alain bubois
monmail@mon_fournisseur.fr Mickael galson

mais si par exemple je veux simplement supprimer Alain qui est contenu dans nom[20] de la premiére ligne comment pourrai-je faire ?

Merci par avance à vous.

14 réponses

kij_82 Messages postés 4089 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
23 janv. 2007 à 16:50
Pour cela il faut que tu parcours ta liste chainée en gardant à chaque fois en mémoire l'élément précédent l'entrée qui correspond à ta recherche, de facon a faire pointer l'élément next du précédent sur celui de l'élément trouvé.

Tu vois ce que je veux dire ?

De cette facon, tu aura reconstitué ta liste chainée, sans l'élément trouvé.
Puis ensuite, il te suffit de libérer l'espace mémoire de la structure trouvée lors de la recherche.
0
kij_82 Messages postés 4089 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
23 janv. 2007 à 17:00
Voilà un exemple grossomodo bourré de faute car je n'ai pas fais de C depuis tres longtemp, mais c'est pour que tu vois ce que je veux dire :
typedef struct Utilisateur Utilisateur; 
struct Utilisateur { 
char email[64]; 
char nom[20]; 
char prenom[40]; 
struct Utilisateur *next; 
}; 


int main ( ... ){
	
	struct Utilisateur *liste = null;
	
	// --- Ici tu rempli ta liste chainée comme tu semble avoir déjà fais.
	
	// --- Suppression de l'utilisateur Alain :
	struct Utilisateur * prec = null;
	struct Utilisateur * parcours 	= null;
	boolean trouve = false;
	
	parcours = liste;
	while ( parcours != null && !trouve ){
		if ( parcours->nom == "Alain" ){
			// --- Trouvé, on lie les éléments précédents et suivant de la liste ensemble :
			tmp = parcours;
			if ( prec == null )
				// --- Cas ou "Alain" est en premier dans la liste :
				liste = parcours->next; 
			else 
				// --- On lie le précédent au suivant :
				prec.next = parcours->next;
				
			// --- On libère ensuite l'espace mémoire pour l'utilisateur a supprimer :
			free(tmp);
			// --- On modifie le booléen pour arrêter la recherche :
			trouve = true;
		}
		parcours = parcours->next;
	}
	
}


Il te suffit reprendre l'idée et de bien le coder.
0
pweteur Messages postés 24 Date d'inscription vendredi 9 juin 2006 Statut Membre Dernière intervention 26 mars 2007
23 janv. 2007 à 20:53
Merci, mais j'ai essayé avec ton code, ensuite j'ai essayé de le modifier etc... mais aucun résultats , sa ne fonctionne pas...
0
kij_82 Messages postés 4089 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
24 janv. 2007 à 09:30
C'est que tu t'y prends mal, désolé je ne peux dire que ca.
Je suis sur qu'il s'agit là d'une méthode qui fonctionne car c'est ce que j'utilisais lorsque je faisait du C.
Je dis bien que l'idée fonctionne, pas le code.

Et qu'est ce qui ne va pas exactement ?
Déjà, es tu bien sur que tu construit correctement ta liste chainée au départ, peut tu en faire une lecture de ses éléments ?


Post moi tout ton code que je regarde, des fois que mes souvenirs suffisent ^^
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
pweteur Messages postés 24 Date d'inscription vendredi 9 juin 2006 Statut Membre Dernière intervention 26 mars 2007
24 janv. 2007 à 13:25
Alors enfaite mon programme consiste à enregistrer les connexions d'un utilisateur à un server. Donc pour cela j'ajoute de la facon suivante.

//Structure qui stock les connexions

typedef struct u_Nick u_Nick;
struct u_Nick {
char nick[MAXNICK];
char host[MAXHOST];
char identd[MAXIDENTD];
char *server;
char *ip;
struct u_Nick *next;
};

Code d'ajout :

u_Nick *co(u_Nick *ulist, char** rvs)
{
// rvs[1] = pseudo
// rvs[4] = identd
// rvs[5] = ip
// rvs[6] = server
// rvs[9] = host

u_Nick *val = (u_Nick *) malloc(sizeof(u_Nick));
if (val != NULL) {
if (ulist == NULL) {
strcpy(val->nick,rvs[1]);
strcpy(val->identd,rvs[4]);

strcpy(val->host,rvs[9]);

val->server = (char *) malloc(strlen(rvs[6]) +1);
strcpy(val->server,rvs[6]);

val->ip = (char *) malloc(strlen(rvs[5]) +1);
strcpy(val->ip,rvs[5]);

printf("Connexion de %s (%s@%s) sur %s avec l'ip %s\n",
val->nick,
val->identd,
val->host,
val->server,
val->ip);

val->next = ulist;
ulist = val;
zalist(ulist); //Ceci est la liste des connexion ajouté
return ulist;
}
val = ulist;
while (val->next != NULL)
{
val = val->next;

}
u_Nick *temps = (u_Nick *)malloc(sizeof(struct u_Nick));
if (temps == NULL) {
error("Erreur de \'malloc()\' L'allocation de mémoire \
est impossible pour le stockage! Fonction -> \'u_Nick *co\'");
return ulist;
}
strcpy(temps->nick,rvs[1]);
strcpy(temps->identd,rvs[4]);

strcpy(temps->host,rvs[9]);

temps->server = (char *) malloc(strlen(rvs[6]) +1);
strcpy(temps->server,rvs[6]);

temps->ip = (char *) malloc(strlen(rvs[5]) +1);
strcpy(temps->ip,rvs[5]);


val->next = temps;

temps->next = NULL;

printf("-> Connexion de %s (%s@%s) sur %s avec l'ip %s\n",
temps->nick,
temps->identd,
temps->host,
temps->server,
temps->ip);

zalist(ulist);
}else {
error("Erreur de \'malloc()\' L'allocation de mémoire \
est impossible pour le stockage! Fonction -> \'u_Nick *co\'");
}
}

//La liste

void zalist(u_Nick *ulist)
{
u_Nick *na = ulist;
while(na != NULL)
{
printf("%s %s@%s %s %s\n",na->nick,na->identd,na->host,
na->server,na->ip);
na = na->next;
}

Donc pour la liste ou l'ajout en structure j'ai compris,
mais enfaite il faut aussi que je modifie, ou supprime certain élément d'une des listes chainée lors d'un changement de pseudo sur le server ou si la personne le quitte... et la je plante car en théorie j'ai compris mais en pratique j'ai pas l'idée...
0
kij_82 Messages postés 4089 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
24 janv. 2007 à 15:06
Donc pour la liste ou l'ajout en structure j'ai compris


Je ne pense pas non.

Plusieurs chose à signaler dans le code que tu m'as donné :
Ne jamais nommée un élément d'une structure par le même nom comme tu le fais ici :
typedef struct u_Nick u_Nick; 


Sinon dans la fonction co j'ai noté qq truc :
u_Nick *val = (u_Nick *) malloc(sizeof(u_Nick)); 

Ne le met pas au début du code, mais dans la condition ou uList == NULL, car sinon tu alloue une zone mémoire pour rien puisque dans le cas ou uList n'est pas null (c'est a dire tout les cas sauf au premier ajout), tu fais :
val = ulist; 


De plus, dans le cas ou uList n'est pas nul, tu ne retourne rien alors que ta fonction est définie comme retournant un pointeur sur ta structure... donc soit tu n'as pas mis ton code entier, soit tu as mal copié, soit tu as fait un faute.

Aussi : dans le cas ou uList est null, inutile de faire pointer uList sur val et de retourner uList, retourne directement val.

Dernière remarque, lorsque je demande si tu arrive à afficher ta liste, ce n'est pas dans la fonction d'ajout qu'il faut le faire, mais dans ton main ou fonction principale, pour voir si tu n'as pas fais de faute lors de l'ajout justement. Ca doit etre vérifier apres l'ajout et pas pendant.

Donc voici la correction de ton code (non testé non compilé) :
typedef struct u_Nick u_Nick; 	

struct u_Nick { 
	char nick[MAXNICK]; 
	char host[MAXHOST]; 
	char identd[MAXIDENTD]; 
	char *server; 
	char *ip; 
	struct u_Nick *next; 
}; 


Code d'ajout :

u_Nick *co(u_Nick *ulist, char** rvs) 
{ 
	// rvs[1] = pseudo 
	// rvs[4] = identd 
	// rvs[5] = ip 
	// rvs[6] = server 
	// rvs[9] = host 

	u_Nick *val = NULL;

	if (ulist == NULL) { 
			
			val = (u_Nick *) malloc(sizeof(u_Nick));
			if ( val == NULL ){
				error("Erreur de \'malloc()\' L'allocation de mémoire \ est impossible pour le stockage! Fonction -> \'u_Nick *co\'"); 
				return NULL;
			}
			
			strcpy(val->nick,rvs[1]); 
			strcpy(val->identd,rvs[4]); 

			strcpy(val->host,rvs[9]); 

			val->server = (char *) malloc(strlen(rvs[6]) +1); 
			strcpy(val->server,rvs[6]); 

			val->ip = (char *) malloc(strlen(rvs[5]) +1); 
			strcpy(val->ip,rvs[5]); 

			printf("Connexion de %s (%s@%s) sur %s avec l'ip %s\n", 
			val->nick, 	
			val->identd, 
			val->host, 
			val->server, 
			val->ip); 

			val->next = NULL; 
			
			return val; 
		}
	
		val = ulist; 
		while (val->next != NULL) { 
			val = val->next; 
		}
	
		u_Nick *temps = (u_Nick *)malloc(sizeof(struct u_Nick)); 
		if (temps == NULL) { 
			error("Erreur de \'malloc()\' L'allocation de mémoire \ 
			est impossible pour le stockage! Fonction -> \'u_Nick *co\'"); 
			return ulist; 
		} 
		strcpy(temps->nick,rvs[1]); 
		strcpy(temps->identd,rvs[4]); 

		strcpy(temps->host,rvs[9]); 

		temps->server = (char *) malloc(strlen(rvs[6]) +1); 
		strcpy(temps->server,rvs[6]); 

		temps->ip = (char *) malloc(strlen(rvs[5]) +1); 
		strcpy(temps->ip,rvs[5]); 

		val->next = temps; 
		temps->next = NULL; 

		printf("-> Connexion de %s (%s@%s) sur %s avec l'ip %s\n", 
		temps->nick, 
		temps->identd, 
		temps->host, 
		temps->server, 
		temps->ip); 

		return ulist;

} 


//La liste
void zalist(u_Nick *ulist) 
{ 
	u_Nick *na = ulist; 
	while(na != NULL) { 
		printf("%s %s@%s %s %s\n",na->nick,na->identd,na->host, 
		na->server,na->ip); 
		na = na->next; 
	}
} 


Maintenant il faut travailler sur le prog principal, si tu as déjà quelque chose met le moi que je regarde.

Essai de faire fonctionner un truc dans ce style pour voir si l'ajout et l'affichage fonctionne réellement :
void principal (){
	u_Nick *liste = NULL;
	
	// Ajout d'utilisateurs :
	liste = co(...);
	liste = co(...);
	...
	
	// Affichage des utilisateurs :
	zalist(liste);
	
}

0
kij_82 Messages postés 4089 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
24 janv. 2007 à 15:31
Et voilà une fonction de suppression d'un utilisateur :
u_Nick *eraseUtil ( u_Nick *ulist, char *name ){
	
	// --- Pointeur de parcours
	u_Nick *parcours = ulist;
	// --- Sert à lier le précédent élément de la
	// --- chaine au suivant lors de la suppression
	u_Nick *prec		 = NULL;
	// --- Indicateur de sortie de boucle si utilisateur trouvé
	int trouve = 0;

	while ( trouve == 0 && parcours != NULL ){
		if ( strcmp(parcours->nick,name) == 0 ){
			// --- User is in the list, so delete him.
			// --- 1°) Link the prec to the next in the list
			if ( prec != NULL )
				prec->next = parcours->next;
			else
				// --- Cas ou l'utilisateur est en premier dans la liste
				ulist = parcours->next;
			// --- 2°) Delete the current (free)
			free(parcours);
			// --- Sortie de boucle
			trouve = 1;
		}
		else {
			// --- Passage au suivant
			prec = parcours;
			parcours = parcours->next;
		}
	}
	
	if ( trouve == 1 )
		printf("Utilisateur %s supprimé",name);
	else
		printf("Aucun utilisateur de ce nom dans la liste");
	
	// --- Retourne la nouvelle liste :
	return ulist;
	
}


0
pweteur Messages postés 24 Date d'inscription vendredi 9 juin 2006 Statut Membre Dernière intervention 26 mars 2007
24 janv. 2007 à 20:23
Merci de m'aider comme cela car yavais pas male d'erreur:) Le code est trés bien et il fonctionne , mais il me supprime toute la ligne , est-ce normal ?

Pour répondre à ta question quand je fait la liste j'ai :

user1 identd rox-E64A9D74 monirc.net localhost
user2 identd rox-E64A9D74 monirc localhost

Donc ces correctement ajouté car dans la liste j'obtien ce que j'ai ajouté. mais je me suis peut être male exprimé.

enfaite la j'ai deux lignes et sur la premiére ou deuxiéme ligne jaimerai simplement supprimer 'identd ' ou 'localhost' mais ton code (qui est ce que tu a du comprendre parce que je me suis mal exprimer me supprime une des deux lignes complétement.)

mais la ligne qui me supprime correspond bien a l'utilisateur et sa parcontre c super :)
0
kij_82 Messages postés 4089 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
25 janv. 2007 à 09:50
Haa, oui soit tu t'es mal exprimé soit j'ai mal compris ^^

Donc tu ne souhaite supprimer qu'un "champ" ou "propriété" d'un utilisateur alors.

Par supprimé, tu veux dire quoi exactement ? Supprimé totalement (par un free) la propriété pour qu'elle n'existe plus, ou juste re-initialiser la propriété (mettre sa valeur à NULL).

Dans le premier cas c'est tout simplement infessable, car tu déclare un type structure qui possède un certain nombre de champ, et cela tu ne peux pas le changer en cours de programme.

Par contre, tu peux mettre des valeurs à NULL, ou "", ou 0 selon le type de donnée pour symboliser le fait que la propriété de telle personne n'est pas enregistrée ou n'as pas de valeur, et c'est ce que tu veux faire il me semble.
Pour cela rien de plus simple, il te suffit de copier la fonction de suppression que je t'ai donné, et de la modifier quelque peu comme suit :
void eraseHost ( u_Nick *ulist, char *name, char *newHost ){
	
	// --- Pointeur de parcours
	u_Nick *parcours = ulist;
	// --- Indicateur de sortie de boucle si utilisateur trouvé
	int trouve = 0;

	while ( trouve == 0 && parcours != NULL ){
		if ( strcmp(parcours->nick,name) == 0 ){
			// --- User is in the list, so replace the property 'host' with the new value.
			parcours->host = newHost;
			// --- Sortie de boucle
			trouve = 1;
		}
		else {
			// --- Passage au suivant
			parcours = parcours->next;
		}
	}
	
}


Voilà pour ce qui est de la propriété 'host', tu peux faire de même pour les autres propriétés.
0
pweteur Messages postés 24 Date d'inscription vendredi 9 juin 2006 Statut Membre Dernière intervention 26 mars 2007
25 janv. 2007 à 16:59
Merci beaucoup ça fonctionne et c bien cela que je voulai faire. donc c'est bien moi qui mettais male exprimé en tous cas merci :)
mais pour quelqun qui a pas fait de C depuis longtemps tes bon soit ta une bonne mémoire :) parcontre j'ai une question si tu me permet, j'aimerai savoir pk parfois ya différent pointeurs qui n'appartienne pas à la structrure meme (cette fois je m'explique :) )

exemple dans la structure

typedef struct u_Nick u_Nick;
struct u_Nick {

struct u_Nick *next;
};

dedans ya le pointeur struct u_Nick *next qui pointe sur l'élément suivant
mais parfois ya des pointeur différent genre a la place d'avoir
struct u_Nick *next; ya struct autrestruct *element;

toi qui ty connais mieu que moi peut tu me donner une explication ?
0
kij_82 Messages postés 4089 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
25 janv. 2007 à 17:10
Généralement dans une liste chainée, tu as toujours le même genre d'information, c'est à dire que tous les éléments de la liste chainée sont du même type ('u_Nick' dans ton cas).

Mais tu peux aussi très bien avoir dans ta structure d'autre pointeur sur structure pour stocker d'autres informations. Ainsi ta structure ressemblerai à cela :

struc ma_struct {
     char * pseudo;
     char * pwd;
     struct Profil * profil;
     struct ma_struct *next;
}

typedef struct Profil {
    char * libelle;
    int paie;
};


Tu vois ce que je veux dire ?

Sinon, dans le cas ou tu veuille dire que les éléments d'une liste chainée ne sont pas du même type... ce n'est pas possible, du moins pas que je me souvienne.
Pourquoi ce n'est pas possible ? Parce que dans ta déclartion de structure, tu déclare ce qu'elle contient et le type de ces éléments. Tu ne peux donc pas les changer comme ca dans le code, au même titre que supprimer ces éléments (propriété).
0
mamiemando Messages postés 33459 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 8 janvier 2025 7 813
25 janv. 2007 à 17:56
Euh j'ai une question qui est un peu hors sujet mais qui pourrait grandement te simplifier la vie. Le code doit impérativement être en C ou il peut être en C++ ?

Car en C++ avec les std::list, ou même mieux ici les std::set, tu auras un code plus simple, plus lisible, et plus rapide. En utilisant les std::string plus de problème liée à la longueur des chaines non plus d'ailleurs. Enfin après c'est toi qui voit...

Bonne chance
0
pweteur Messages postés 24 Date d'inscription vendredi 9 juin 2006 Statut Membre Dernière intervention 26 mars 2007
25 janv. 2007 à 19:26
D'accord, merci kij_82 pour toutes ces explications. Tous cela me parrait franchement beaucoup plus clair (dans tous cela je veux dire , les structures) un grand merci tes trés proffessionel autant dans tes commentaire, que dans ton savoir vivre face à une personne qui cherche à apprendre alors que pour toi c'est une évidence :)

Autrement mamiemando oui je suis d'accord que le C++ est plus complet que le C (pour cela que ya les '++' devant de C :) ) bref enfaite oui mon programme est intégralement en C donc comme tu le sais le C et le C++ ne font pas vraiment bon ménage donc merci pour ton commentaire car il pourra peut être interréser les personnes qui sont en C++ et qui on à peut prés ou totalement les méme difficulté que moi :) mais je la je m'interresse au C :)
0
pweteur Messages postés 24 Date d'inscription vendredi 9 juin 2006 Statut Membre Dernière intervention 26 mars 2007
25 janv. 2007 à 19:32
PS : j'ai coché la case "problème résolu" mais il est écrit qui faut récapituler la solution, mais si je fait cela il va y avoir un poste immense, alors j'invite les utilisateurs à reprendre la discution en totalité pour pouvoir profiter des questions posées et des explications donnée pour ainsi mieu comprendre :) merci et à bientôt :)
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 569
25 janv. 2007 à 19:42
Salut,

mais il est écrit qui faut récapituler la solution

C'est une bonne chose que tu as coché la case problème résolu :-)
Pour ce qui est de récapituler, sûrement ceux qui aurront besoin, ça sera dans leur intérêts de lire le thread :-)

Bonne continuation.
0