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 une valeur dans un tableau


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 47
    Par défaut Supprimer une valeur dans un tableau
    Salut à tous, l'exercice dit :
    Ecrire un programme en "C" qui lit un entier (X) et un tableau (A) de type entier et élimine tous les occurrences de (X) dans (A) en tassant les éléments. {Faire un décalage}.
    Le professeur veut une méthode dans laquelle on utilise la notion du pointeur pour résoudre ce problème.

    J'ai essayé bien sûr avec cet exercice et j'ai coincé : voici le code de mon programme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(int argc, char *argv[])
    {
      int val,n,pas,t[30];
      int *p=t;
      printf("Entrer N : ");scanf("%d",&n);
      for(p=t;p<p+n;p++)
      {Printf("\nT : ");scanf("%d",p);}
      printf("\nVal : ");scanf("%d",&val);
     
      pas=0;
     
      for(p=t;p<t+n;p++)
      {
          if(*p!=val)
          *(p-pas)= *p;
          if(*p==val)
          pas++;
      }
      system("PAUSE");	
      return 0;
    }
    Je crois que algorithmiquement c'est vrai mais d'un coté technique je ne sais pas comment faire.

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Ce code est pratiquement illisble. Commence par le découper en fonctions (typiquement, garde le main pour l'entrée des paramètres, et fais-toi une fonction pour supprimer X du tableau).
    Et aussi, utilise des noms de variable plus explicites (ou au moins, qui correspondent à l'énoncé).

    Ensuite, au niveau algorithme, tu as accès à deux méthodes: La méthode "naïve" en O(n²), qui supprime l'élément et fait un décalage à chaque fois, et la méthode plus optimisée en O(n) qui fait le tout en une passe.
    Si tu choisis la méthode naïve, pense à mettre la suppression d'un élément dans une autre fonction.

    Dans tous les cas, ta fonction doit au minimum avoir ceci:
    • En entrée: Un tableau avec sa taille, l'élément à supprimer
    • En sortie: Le tableau modifié (sur place), et la nouvelle taille du tableau


    Ainsi, comme fonction, je propose ceci:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #include <stddef.h>
     
    //Retourne la nouvelle taille du tableau
    size_t supprime_tous_les_x(int * a, size_t taille_a, int x);
    Maintenant, code le contenu de la fonction supprime_tous_les_x(), ainsi que le main() pour l'appeler.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ....
      for(p=t;p<t+n;p++)        // p+n est une erreur
      {
        printf("\nT : ");      // Printf  : Attention, le C est sensible à la casse
        scanf("%d",p);
      }
    ....
    Note : Eviter plusieurs instructions par ligne , le programme est moins lisible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {printf("\nT : ");scanf("%d",p);}
    On n'est pas à quelques lignes près.

  4. #4
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 47
    Par défaut
    Resalut, merci encore pour vous : et voilà une amélioration au niveau de code pour qu'il soit être lisible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #include <stdio.h>
    #include <stdlib.h>
    int effacer (int *x,int *a,int valsupp);
    int affiche(int x,int *a);
    int main(int argc, char *argv[])
    {
      int n,t[30],val;
      int *p=t;
     
      printf("Entrer N : ");scanf("%d",&n);
      for(p;p<t+n;p++)
      {printf("\nT : ");scanf("%d",p);}
      printf("\nVal : ");scanf("%d",&val);
      system("cls");
      printf("Taille initial : \t%d\n",n);
      affiche(n,t);
      effacer(&n,t,val);
      printf("\n");
      affiche(n,t);
      printf("\n\ntTaille devient : \t%d\n",n);
      system("PAUSE");	
      return 0;
    }
    int effacer (int *x,int *a,int valsupp)
    {
    int pas = 0;     
    int *p=a;
     
      for(p;p<a+*x;p++)
      {
          //Si le contenu de (*p) est différent à (valsupp)
          //Je déplace la case 
     
          *(p-pas)= *p;
          //Si le contenu de (*p) est égal à (valsupp) 
          //j'augmente le (pas) 
          if(*p==valsupp)
          pas++;
      }
      *x = (*x-pas);
      return 0;
    }
    int affiche(int x,int *a)
    {
        int *p=a;
        for(p;p<a+x;p++)
        printf("%d : ",*p);
        return 0;
        }
    Vos remarque SVP!

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Ce code n'est pas aussi lisible que tu le penses.
    Rien que cette fonction, qui appelle "x" une taille, alors que dans ce programme "x" désigne quelque chose de précis.
    De plus, la notation "tableau" est ici plus pertinente que la notation "pointeur", pour la boucle
    Code C peu lisible : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int affiche(int x,int *a)
    {
        int *p=a;
        for(p;p<a+x;p++)
        printf("%d : ",*p);
        return 0;
        }
    Voici le code corrigé:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int affiche(size_t taille, int const *a)
    {
    	size_t i;
    	for(i=0 ; i<taille ; i++)
    		printf("%d : ", a[i]);
    	return 0;
    }
    Si ton prof est maniaque, tu peux aussi virer le const et/ou remplacer les size_t par des unsigned int ou même des int, mais je te conseillerais plutôt de respecter les bonnes pratiques dès le début.

    PS: Au passage, peut-être devrais-tu aussi déplacer la saisie dans une nouvelle fonction.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Cette fonction là est pire, car tu as changé la signification de x.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    int effacer (int *x,int *a,int valsupp)
    {
    int pas = 0;     
    int *p=a;
     
      for(p;p<a+*x;p++)
      {
          //Si le contenu de (*p) est différent à (valsupp)
          //Je déplace la case 
     
          *(p-pas)= *p;
          //Si le contenu de (*p) est égal à (valsupp) 
          //j'augmente le (pas) 
          if(*p==valsupp)
          pas++;
      }
      *x = (*x-pas);
      return 0;
    }
    Voici mes corrections:
    Code C corrigé : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    int effacer(size_t *pTaille, int *a, int x)
    {
    	int offset = 0; //Med: Ce n'est pas un pas, mais un offset
    	int *p = a;
     
    	for(p ; p<a+*pTaille ; p++)
    	{
    		//Si le contenu de (*p) est différent à (valsupp)
    		//Je déplace la case 
     
    		*(p-offset)= *p;
    		//Si le contenu de (*p) est égal à (valsupp) 
    		//j'augmente le (pas) 
    		if(*p==x)
    			offset++;
    	}
    	(*pTaille) -= offset;
    	return 0;
    }
    Et encore, je serais plutôt du genre à faire ceci:
    Code C perso : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    size_t recopier_sauf(int *dest, int const *source, size_t taille, int x)
    {
    	size_t i;
    	size_t j=0;
    	for(i=0 ; i<taille ; i++)
    	{
    		int val = source[i];
    		if(val != x)
    		{
    			dest[j] = val;
    			j++;
    		}
    	}
    	return j;
    }
     
    int effacer(size_t *pTaille, int *a, int x)
    {
    	*pTaille = recopier_sauf(a, a, *pTaille, x);
    	return 0;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre confirmé
    Profil pro
    Lycéen
    Inscrit en
    Août 2008
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Août 2008
    Messages : 38
    Par défaut
    Médinoc:
    A propos de la méthode en O(n), c'est bien celle qui consiste à recopier de façon sélective le tableau dans un autre, non ?
    Or, tu as dis qu'il fallait le faire en place. Il n'y a pas un problème là ?
    Ensuite, au niveau algorithme, tu as accès à deux méthodes: La méthode "naïve" en O(n²), qui supprime l'élément et fait un décalage à chaque fois, et la méthode plus optimisée en O(n) qui fait le tout en une passe.
    Le tableau modifié (sur place)

Discussions similaires

  1. Chercher une valeur dans un tableau
    Par christel1982 dans le forum ASP
    Réponses: 5
    Dernier message: 14/09/2006, 09h01
  2. Rechercher une valeur dans un tableau
    Par pafi76 dans le forum Access
    Réponses: 2
    Dernier message: 29/06/2006, 14h23
  3. supprimer une ligne dans un tableau
    Par sandball22 dans le forum C++Builder
    Réponses: 9
    Dernier message: 16/05/2006, 21h53
  4. Supprimer une valeur dans un vecteur
    Par jalilv6 dans le forum Langage
    Réponses: 2
    Dernier message: 06/04/2006, 09h33
  5. Réponses: 21
    Dernier message: 28/02/2006, 15h23

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