IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Supprimer élément d'un tableau générique en C


Sujet :

C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 8
    Points : 8
    Points
    8
    Par défaut Supprimer élément d'un tableau générique en C
    Bonjour,

    Je voudrais écrire une function en C qui prend en paramètre un tableau générique et l'indice d'un element à supprimer. Voilà ma fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void  delete_data(void * array[], size_t nb_elt, size_t size_elt, int index)
    {
    	size_t i;
    	for (i = index; i < nb_elt-1; i++)
    	{
    		void *ptr = array +i;//pointer on the (i+1)-th element
    		array[i]=array[i+1];
    	}
    	array[nb_elt-1]= 0;
    }
    Je la teste dans mon main sur un tableau d'entier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	int T[]={0,1,2,3,4,5,6,7,8,9};
     
    	delete_data(T, sizeof(T)/sizeof(T[0]),sizeof(T[0]), 1);
    	int i;
    	for (i=0; i< sizeof(T)/sizeof(T[0]); i++)
    	{
    		printf("%d\n", T[i]);
    	}
    Malheureusement voilà le résultat affiché :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    0
    1
    4
    5
    6
    7
    8
    9
    0
    0
    Pouvez-vous m'aider svp ? Merci d'avance !

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    C'est parce qu'il faut n'afficher le tableau que jusqu'à la nouvelle taille.
    Le reste semble bon.
    Tu as même pensé à mettre des 0 à la fin du tableau.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 8
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par ternel Voir le message
    C'est parce qu'il faut n'afficher le tableau que jusqu'à la nouvelle taille.
    Le reste semble bon.
    Tu as même pensé à mettre des 0 à la fin du tableau.
    Le probleme est surtout que ça me supprime 2 elements, et pas les bons en plus ! Ca a supprimé T[3] et T[4] au lieu de T[1] :-(

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 984
    Points
    30 984
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Contrairement à ce que dit Ternel (et je regrette de contredire cet excellent intervenant) , moi ça ne me semble pas bon (mais c'est compréhensible vu que tu n'as pas jugé bon d'encadrer ton code dans des balises )

    Ta fonction "delete_data()" prend en premier paramètre un void *array[] autrement dit un tableau de pointeurs. Or, tu lui passes dans ton main() la variable "T" qui est un tableau d'int

    Or, un tableau d'ints (donc un int []) n'est pas un tableau de pointeurs void !!!

    Accessoirement je ne vois pas à quoi sert la variable "ptr"...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    C'est presque bon. Sauf qu'il faut tenir compte de la taille de l'élément, le paramètre size_elt.
    Attention que l'arithmétique de pointeurs (comme ptr+i) est sensible à la taille du type pointé.

    Il convient donc de faire les conversions nécessaires.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 8
    Points : 8
    Points
    8
    Par défaut
    Merci pour vos réponses, et désolé pour les balises (je savais pas comment faire ^^)

    Effectivement j'avais un probleme avec le tableau d'entrée. De plus je me suis rendu compte que le calcul d'adresse ne pouvait pas être effectué sur un pointeur générique, il faut donc passer par un autre pointeur.

    Voilà mes modifications :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void  delete_data(void * array, size_t nb_elt, size_t size_elt, int index)
    {
    	size_t i;
    	char *ptr = array;
    	for (i = index; i < nb_elt-1; ++i)
    	{
    		void *tmp = *(ptr+((i+1)*size_elt));
    		*(ptr+(i*size_elt))= tmp;
    	}
    	*(ptr+((nb_elt-1)*size_elt))= 0;
    }
    Ce code a l'air de marcher pour un tableau d'int, mais pas pour des flottants :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    float T[]={0.1,1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.0};
    delete_data(T, sizeof(T)/sizeof(T[0]),sizeof(T[0]), 9);
    int i;
    for (i=0; i< sizeof(T)/sizeof(T[0]); ++i)
    {
    	printf("%f\n", T[i]);
    }
    Résultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    0.100000
    1.200000
    2.300000
    3.400000
    4.500000
    5.600000
    6.700000
    7.800000
    8.900000
    9.000000
    Savez vous pourquoi aucun element n'est supprimé ? Merci d'avance !

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Cela me semble logique ... sans avoir testé le truc (tout comme tu ne peux pas travailler avec un tableau de void)

    À chaque fois tu effaces un char soit 1 octet. Or un int, un float mais aussi tous les autres types (comme un short, un double) c'est plus d'1 octet.


    Et un conseil , mets ton pointeur dans ta boucle comme à peu près ceci (non compilé) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        size_t index, copy_index;
        char* case_ptr = (((char*) array) + (index * size_elt));
     
        for (index = delete_index; index < (nb_elt - 1); ++index) {
            for (copy_index = 0; copy_index < size_elt; ++copy_index, ++case_ptr) {
                *(case_ptr + size_elt) = *(case_ptr);
            }
        }
     
    //  XXX : here verify case_ptr is the last case
        for (copy_index = 0; copy_index < size_elt; ++copy_index, ++case_ptr) {
            *(case_ptr) = 0;
        }

    Édit : La solution de Sve@r ci-dessous avec memcpy/ memset est mieux
    Édit : Dans mon exemple, on peut fusionner les 2 boucles for imbriquées

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 984
    Points
    30 984
    Billets dans le blog
    1
    Par défaut
    Et au lieu d'utiliser le "=" pour copier (où comme le dit foetus tu ne copies qu'un seul octet alors que chaque élément flottant en fait 4), utilise memcpy().

    Un truc de ce genre devrait le faire...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void  delete_data(void * array, size_t nb_elt, size_t size_elt, int index)
    {
    	size_t i;
    	char *ptr;
    	for (i = index, ptr=(char*)array + i * size_elt; i < nb_elt-1; ++i, ptr+=size_elt)
    		memcpy(ptr, ptr+size_elt, size_elt);
    	memset(ptr, 0, size_elt);
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 8
    Points : 8
    Points
    8
    Par défaut
    Un grand merci à tous pour vos réponses, j'ai appris beaucoup de choses Finalement j'ai opté pour la solution de Sve@r et ça marche très bien

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Supprimer élément d'un tableau
    Par Amnael dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 09/07/2017, 21h24
  2. [Lazarus] Supprimer élément d'un tableau d'objets
    Par Manusm dans le forum Lazarus
    Réponses: 7
    Dernier message: 16/11/2016, 13h55
  3. Supprimer élément d'un tableau
    Par totot dans le forum Collection et Stream
    Réponses: 13
    Dernier message: 01/11/2014, 13h03
  4. Supprimer élément d'un tableau
    Par cougar5 dans le forum Langage
    Réponses: 16
    Dernier message: 07/04/2011, 22h36
  5. Supprimer éléments d'un tableau
    Par liline150 dans le forum ActionScript 1 & ActionScript 2
    Réponses: 1
    Dernier message: 02/09/2007, 14h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo