Supression d'une valeur : language C

Fermé
Julie - 29 avril 2008 à 14:12
 labiko445 - 20 nov. 2012 à 02:02
Bonjour,


je dois écrire une fonction permettant d'éliminer un entier caractérisé par sa position dans
le tableau.


Si l'entier n'est pas présent, le tableau reste inchangé. Le tableau résultant ne doit
comporter aucun "trou", c'est-à-dire que si le nombre d'éléments effectifs size diminue de 1,
seules les cases d'index compris entre 0 et (size-1) ont une valeur effective après suppression de la valeur


( dans le même style j'avias fait la fonction recherche d'une valeur si ca peut vosu aider :

#define capacity 20 ( j'ai mis 20 au pif )


int tab[capacity];
int index,i,v;

index = -1;
for(i=0;((i<=capacity ) &&(index == -1));i++)
{
if(tab[i]==v)
index=i; //si la valeur dans le tableau est égale à la valeur recherchée (v) index prend le

numéro de la case (position de l'élément)

}

)



merci d'avance :)

7 réponses

Moeb Messages postés 102 Date d'inscription lundi 21 avril 2008 Statut Membre Dernière intervention 5 août 2008 12
29 avril 2008 à 14:20
Bonjour,

#define capacity 20


int tab[capacity];
int trouve=0;
int i=0;
int j;

int v = 'la valeur que tu veux';

while(!trouve)
{
   if(tab[i]==v)
      trouve=1;
   else
      i++;
}

if(trouve)
{
   for(j=i; j<capacity; j++)
   {
       tab[j]=tab[j+1];
   }

   capacity -= 1;
}


Ca te va?
0
ca ma l'air pas mal :)

vous en pensez quoi les autres ?

il a bon moeb ? ( que je remercie beaucoup )
0
pas mal cest un peut malin avec le j qui marque apres avoir trouver la valeure cible
0
Moeb Messages postés 102 Date d'inscription lundi 21 avril 2008 Statut Membre Dernière intervention 5 août 2008 12
29 avril 2008 à 15:02
Pas de problème ;)
Modulo des erreurs idiotes ça doit être ça, je l'ai pas testé
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
29 avril 2008 à 15:33
oui, modulo les erreur idiotes c'est pas mal. Enfin, à ce traitement là, TOUT est pas mal ;)
la plus grosse, je pense que c'est la modification de la macro capacity.
Je pense que pour être propre dans ce genre de problème, il vaut mieux utilisé l'allocation dynamique de mémoire, éventuellement associé à une structure.
0
Moeb Messages postés 102 Date d'inscription lundi 21 avril 2008 Statut Membre Dernière intervention 5 août 2008 12
29 avril 2008 à 16:00
Ah ouais, la grosse boulette effectivement, j'ai pas réfléchi, je t'avouerais ^^
Pour ce qui est de la gestion d'une structure, vu que son exemple était visiblement simple, j'ai pas jugé utile de compliquer, à moins que ce soit dans un cadre pro.
0

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

Posez votre question
et uassi j'ai aps compris dans la fonction a moeb le TROUVE quand il marque while(!trouve) ou if ( trovue )

c'est quoi trouve ?
0
Sinon j'avais pesné à ca :

void supprimer (tableau t, int *nb)
{
int i,j;
if(*nb<=0)printf("déja vide !\n");
else
{
printf("Quelle valeur voulez vous supprimer ?");
scanf("%d",&j);
if (j<*nb && j>=0)
{
(*nb)--;
for(i=j;i<*nb;i++)
t[i]=t[i+1];
}
}
}


come c'est une boucle ca va parcourir tout le tableau non ?
0
que voulez vous dire avec *nb ???
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125
29 avril 2008 à 22:13
Oups

Effectivement je pense que pour un sudoku il n'y aura jamais plusieurs fois une valeur dans un même tableau.

Je me permets une remarque et je ne pense pas que ce soit un simple goût personnel. Il y a des morceaux de code qui vont te servir plutôt à réaliser le sudoku et d'autres plutôt à demander au joueur ce qu'il veut faire. Idéalement on essaie de mélanger le moins possible ces deux là. (A vrai dire je bien qu'ici on s'en tape un peu, mais un jour tu te rappelleras, Mais oui ! Un jour un vieux fou sur un forum m'avait baragouiné que patati-patata...) Pour faire très rapidement car ton objectif est plutôt d'avancer ton programme, cette séparation sert à avoir un code plus clair et surtout plus simple, ici par exemple : ne pas avoir à vérifier si la saisie est correcte au beau milieu d'une fonction de suppression. L'autre but est de pouvoir utiliser tout ton code réalisant un sudoku avec un autre interface utilisateur. Une fenêtre avec des boutons etc.

Revenons en à tes moutons.

Ici... oui, ça me paraît bien. Si le tableau est non vide on demande un indice et on supprime l'élément qui se trouve à cet indice. Allez, on titille un peu : Il est demandé "quelle valeur" et il faut saisir l'indice correspondant à la valeur.

Je retitille mais c'est du superflu, prends en compte si tu as envie... Que ce soit un indice ou une valeur, c'est un entier positif. On peut donc utiliser un unsigned int et supprimer le test ">= 0". (%u pour le scanf)

Il y a deux autres solutions envisageables, une qui garde ton idée avec le tableau de valeurs possibles et son nombre d'éléments, l'autre en codant différemment l'information des valeurs possibles.

La première "solution" est de faire une petite structure qui contiendrait le tout.

typedef struct
{
    unsigned int valeurs[9];
    unsigned int nbValeurs;
} ValeursPossibles_t;

void supprimerValeur( ValeursPossible_t *pLesValeurs, unsigned int valeurASuppr )
{
    ...

    for( i = ... ; i != (*pLesValeurs).nbValeurs ; 
    (*pLesValeurs).valeurs[i] ...
    ...
}


Ca c'est juste histoire de faire plus compact avec les informations que tu utilises.

A noter que :
(*unPointeurSurUneStructure).nomDuChamp peut aussi s'écrire :
"unPointeurSurUneStructure->nomDuChamp" C'est rien qu'une histoire de notation. Aucun reproche faisable là dessus.

La deuxième solution changerait plus de choses. Cela consiste à ne pas garder les valeurs possibles dans un tableau mais plutôt être capable pour chaque valeur de dire si elle est possible ou non. Bizarrement il n'est plus question de garder (jusqu'à) 9 valeurs et un taille mais plus que un seul entier pour les neufs valeurs. (Accessoirement c'est aussi beaucoup plus pratique pour la suite...)
Je dois partir pour aujourd'hui, je finis la prochaine fois si tu montres un intérêt pour que je présente plus la deuxième solution.

A bientôt,
M.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
30 avril 2008 à 08:50
a on y reviens aux structure, c'est bien !
juste, il me semble que de faire :
struc->val;
est plus rapide que :
(*struc).val;
non ?
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125 > Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023
30 avril 2008 à 10:08
Bonjour,

Tout à fait, c'est ce qui était à entendre par "C'est rien qu'une histoire de notation.". Apprenant le C je préférais voir distinctement la déréférrence puis l'accès au membre. Je ne voulais donc pas imposer la flèche ne sachant pas si les structures sont une notion connue ou non pour Julie.

M.
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125
29 avril 2008 à 17:57
Bonjour,

Moi je vois un problème.

La recherche de l'index ne s'arrête jamais si la valeur ne se trouve pas dans le tableau.
Le code ci-dessus ne supprime que la première valeur trouvée dans le tableau et non pas toutes. (Est-ce demandé ?)

Je proposerais ceci pour toutes les supprimer :

#include <stdio.h>

// Fonction eliminer:
// Valeur est la valeur à éliminer
// tableau est ...
// taille est la taille du tableau
// index est l'index de début de la recherche.
// decallage DOIT valoir zéro.
// Valeur de retour : nombre d'éléments supprimés.

unsigned int eliminer( int valeur, int *tableau, unsigned int taille, unsigned int index, unsigned int decallage )
{
    // Si il reste des éléments à traiter.
    if ( index != taille )
    {
        if ( tableau[index] != valeur )
        {// On conserve la valeur.

            // recopie avec decallage éventuel.
            tableau[index-decallage] = tableau[index];

            // On traite les éléments suivants.
            return eliminer( valeur, tableau, taille, index+1, decallage );
        }
        else
            // On ne recopie pas la valeur.
            // On augmente le decallage.
            return eliminer( valeur, tableau, taille, index+1, decallage+1 );
    }
    else
        return decallage;
}

int main( int argc, char *argv[])
{
    int tab[] = { 1, 5, 9, 7, 3, 6, 4, 5, 2, 1, 8, 5, 4, 6, 9, 7, 3 };
    unsigned int taille = sizeof(tab) / sizeof(*tab);

    // Affichage du tableau
    for ( unsigned int i = 0 ; i != taille ; i++ )
        printf( "%d ", tab[i] );
    puts( "" );


    taille -= eliminer( 5, tab, taille, 0, 0 );


    // Affichage du tableau
    for ( unsigned int i = 0 ; i != taille ; i++ )
        printf( "%d ", tab[i] );
    puts( "" );

    printf( "%u elements trouves\n", ( sizeof(tab) / sizeof(*tab) ) - taille );

    getchar();

    return 0;
}


Ce qui se produit au final pour un tableau de taille N :
N comparaisons de l'index courant avec la taille (comme une boucle for)
N - "nombre d'occurrences de la valeur" écritures.
Ce qui me semble pas mal sauf si le tableau ne comportait pas la valeur. On pourrait faire le test de voir si l'écriture est nécessaire ou non (decallage != 0) mais j'ai préféré un écriture à un test supplémentaire.

Pour faire plus beau si on veut, on peut cacher dans une fonction le dernier paramètre qui doit être nul:
unsigned int eliminer( int valeur, int *tableau, unsigned int taille, unsigned int index )
{
    return eliminerQuOnAppellePas( valeur, tableau, taille, index, 0 );
}

On pourrait aussi masquer index car l'utilisateur peut demander de commencer l'élimination à partir d'un certain index en faisant :
eliminer( valeur, tableau + indexDebut, taille - indexDebut );


Voili voilou,
M.
-1
Mahmah le génie du C oO

j'ai rien compris à ce que t'a fais :p

par contre ta oublié de mettre int i et int j :) ( omg je corrige mahmah )

sinon pour la question de savoir si c'est pour une valeurr ou pour toutes les valeurs

en fait je veux cré cette fonction car il faut que j'écrive une fonction qui élimine le candidat de valeur val dans la case de coordonnées ( ligne , colonne ). Cette fonction retourne le nombre de candidats éliminés ( c'est a dire 0 ou 1 )



j'avais pensé à void reduirecandidatcase(int i,int j,int val, sudoku grille)
{
int k;
int i ;
int size;
for (k=0;k<9;k++)
{
if(grille[i][k].size!=0)
{

/* c'est une fonciton qui élimine un valeur du tableau s'il existe et décrémente la taille du tableau afin de réduire la possibilité des solutions possible*/

supprimer_val(grille[i][j].taille_tableau,grille[i][j].tab,grille[i][k].size­);
}
}
}



enfin j'ai un peu de mal a faire ces fonctions ( je galére trop en fait ^^ )
0