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 :

Suppression élément d'un tableau


Sujet :

C

  1. #1
    Nouveau candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2012
    Messages : 1
    Par défaut Suppression élément d'un tableau
    Exercice: Ecrire un programme qui lit un entier X et un tableau A du type int au clavier et élimine toutes les occurrences de X dans A en tassant les éléments restants. Le programme utilisera les pointeurs P1 et P2 pour parcourir le tableau

    voilà ce que j'ai fait mais je ne sais pas pourquoi ça marche pas
    merci pour votre aide

    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
    #include <stdio.h>
    #include <conio.h>
    int main()
    {
        int t[50];
        int n;
        int *p1;
        int *p2;
        int q;
        int nb;
        printf("entrer la dimension du tableau");
        scanf("%d",&n);
        for(p1=t;p1<t+n;p1++){
                           printf("entrer l'element [%d]:    ",p1-t);
                           scanf("%d",p1);
                           }
                           printf("entrer l'élement à afficher");
                           scanf("%d",&q);
                           for(p1=t;p1<t+n;p1++){
                                                 while(*p1=!q)
                                                 *p2=*p1;
                                                 nb++;
                                                 }
                                                 n=nb;
        for(p2=t;p2<t+n;p2++){
                              printf("%4d",*p2);
                              }
                              printf("\n");
                              getch();
    }

  2. #2
    CGi
    CGi est déconnecté
    Expert confirmé
    Avatar de CGi
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 061
    Détails du profil
    Informations personnelles :
    Localisation : France, Allier (Auvergne)

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 061
    Par défaut
    Tu utilises le pointeur p2 sans qu'il soit initialisé !

    Edit : Mets la balise code, pour afficher ton code correctement !
    Site : http://chgi.developpez.com

    Pourquoi faire simple quand on peut faire compliqué ? (Jacques Rouxel)

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 491
    Billets dans le blog
    1
    Par défaut
    Un "bonjour" pour démarrer, un sujet, ça n'a jamais fait de mal....

    Bonsoir,

    L'identation du code est horrible, j'espère que c'est la faute du copier coller !

    L'exercice demande un entier X et un tableau A, pourquoi ne pas les avoir nommé ainsi ?

    L'algo est..... tordu ! Pour avoir besoin d'un pointeur p1 et p2 pour parcourir le tableau t de son début à sa fin de manière linéraire ? Pourquoi ne pas faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for(n=0 ; n<sizeof(t)/sizeof([0]); n++)
    {
        t[n]; // quelque chose avec le n-ieme élément....
    Les pointeurs p1 et p2 sont utiles pour faire les suppressions et surtout le tassement.

    Le tableau a une taille de 50. Et si l'utilisateur entre 75 ? Que va t-il se passer ?

    Voici un code sans la suppression :
    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
    50
    #include <stdio.h>
     
    int main(void)
    {
        int A[50] = {0};
        int X = 0;
        int dim = 50;
        int i = 0;
        int *p1 = A;
        int *p2 = A;
     
        printf("Entrer le nombre d'elements souhaites : ");
        scanf("%d", &dim);
     
        if(dim > 50)
        {
            dim = 50;
            printf("Troncature a 50\n");
        }
     
        printf("Valeur a eliminer ? = ");
        scanf("%d", &X);
     
        for(i=0; i<dim; i++)
        {
            printf("Entrer l'element [%d] : ", i);
            scanf("%d", &A[i]);
        }
     
     
        printf("Tableau avec suppression de '%d'\n", X);
        for(i=0; i<dim; i++)
        {
            printf("%d ", A[i]);
        }
     
        // for( ?? ) pour supprimer et tasser
     
        // noublions pas de sauvegarder la nouvelle taille :
        dim = 4;
     
     
        printf("Tableau apres suppression de '%d'\n", X);
        for(i=0; i<dim; i++)
        {
            printf("%d ", A[i]);
        }
     
        return dim;
    }
    C'est tentant quand l'énoncé dit "utiliser 2 pointeurs pour parcourir le tableau" de les utiliser tout le temps, mais il faut savoir rester calme, réfléchir un peu et écrire son algo en français, sur du papier, avant de vouloir le faire en C sur son éditeur préféré.

    Prenez le temps de réfléchir un peu et tout ira mieux

  4. #4
    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
    Sur le principe du tassement du tableau et de l'utilisation des deux pointeurs :
    - Un pointeur, disons p1, pointe sur la position où on va lire dans le tableau
    - l'autre pointeur, p2, pointe sur la position où on va écrire dans le tableau

    (0) Au départ, p1 et p2 sont placés au début du tableau.
    (1) Si *p1 est à éliminer, alors on incrémente p1
    (2) Si *p1 est à garder, alors on le copie à la position p2, on incrémente p1 et p2Et on fait cela jusqu'à ce que p1 ait parcouru tout le tableau.
    Note : on peut retrouver le nombre d'éléments restant dans le tableau en faisant la différence entre p2 et l'adresse du début du tableau.

    Pour illustrer, en notant '>' p1 et '<' p2 et la règle utilisée entre (), on veut éliminer x du tableau
          x   1   x   2   x   3   4   x
    (0) <>x   1   x   2   x   3   4   x  
    (1)  <x  >1   x   2   x   3   4   x   
    (2)   1  <1  >x   2   x   3   4   x    
    (1)   1  <1   x  >2   x   3   4   x   
    (2)   1   2  <x   2  >x   3   4   x    
    (1)   1   2  <x   2   x  >3   4   x    
    (2)   1   2   3  <2   x   3  >4   x    
    (2)   1   2   3   4  <x   3   4  >x    
    (1)   1   2   3   4  <x   3   4   x >  
    Résultat
          1   2   3   4   x   3   4   x    n=4

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 491
    Billets dans le blog
    1
    Par défaut
    Pas bête le coup d'écraser les éléments tant qu'on n'a pas trouvé d'élément à éliminer, on réduit la complexité

  6. #6
    Membre averti
    Homme Profil pro
    chirurgien retraité
    Inscrit en
    Mai 2018
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chirurgien retraité
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2018
    Messages : 21
    Par défaut Suppression éléments impairs d'un tableau d' int
    Bonjour

    Je recherchais une manière élégante de supprimer des éléments d'un tableau et je suis tombé sur cet ancien post que je me suis permis de réouvrir.

    Comme j'avais du mal à écrire l'astuce de Diogène en passant par deux pointeurs, j'ai mis au clair mes idées avec ce petit programme qui résume ce qu'il a écrit, mais en n'utilisant que le pointeur initial ( mais je le remercie pour son idée ).

    Le but, ici, est d'éliminer d'un tableau d'int, ceux qui sont impairs , de remettre à zéro les autres et de réallouer la mémoire utile.

    J'ai mis en PJ le programme sous Sublime Text.
    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 main(int argc, char const *argv[])
    {
    	int i=0,j=0,k=0,n=20,*tab=malloc(n*sizeof(*tab));
    	if(tab==NULL)exit(-1);[/B]
     
    	//  remplissage du tableau  //
     
    	for(i=0;i<n;i++)tab[i]=i+1;
     
    	//  impression tableau initial //
     
    	for(i=0;i<n;i++)printf("%d\n",tab[i]);
     
    	//
     
    	puts("\n");
     
    	//  élimination des éléments impairs du tableau  // 
     
    	i=0;
    	while(i<n)
    	{
    		while((*(tab+i))%2!=0)i++;
    		tab[j]=*(tab+i);
    		i++;
                    j++;
    	}
     
    	// mise a 0 des éléments impairs restants
     
    	for(k=j;k<n;k++)tab[k]=0;
     
    	/// réallocation à j éléments ///
     
    	tab=realloc(tab,j*sizeof(*tab));
    	if(tab==NULL)exit(-1);
     
    	/// résultat : reste les nbs pairs  ///
     
    	for(k=0;k<n;k++)printf("%d\n",tab[k]);
     
    	//  libération du pointeur //
     
    	free(tab);
    		return 0;
    }
    Merci pour cette belle astuce : et pour Diogène, j'utilise beaucoup realloc quand je ne connais pas la taille du tableau à créer, car j'ai découvert cela en lisant ses posts...et j'adore Glenn Gould !
    Fichiers attachés Fichiers attachés

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 800
    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 800
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par orthomimi Voir le message
    Comme j'avais du mal à écrire l'astuce de Diogène en passant par deux pointeurs, j'ai mis au clair mes idées avec ce petit programme qui résume ce qu'il a écrit, mais en n'utilisant que le pointeur initial
    Pour le second pointeur, te suffit de remplacer "j" et tab[j] par justement ce second pointeur.
    Attention, écrire *(tab+i) n'est pas plus rapide qu'écrire tab[i]. Et c'est moins lisible.
    On a en effet souvent coutume de dire qu'en C l'accès aux éléments d'un tableau est plus rapide en passant par un pointeur, mais c'est à condition d'avoir le pointeur déjà positionné sur la bonne case du tableau. Si le pointeur reste au début et qu'on calcule le décalage à chaque fois, alors ce n'est pas plus rapide que l'accès via l'indice qui lui aussi calcule ce même décalage.

    Et attention, quand tu lis ce qui reste (les pairs), ce n'est plus "n" éléments qu'il faut lire mais "j".

    Code c : 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
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(int argc, char const *argv[])
    {
    	int i=0,j=0,k=0,n=20,*tab=malloc(n*sizeof(*tab));
    	if (tab==NULL)exit(-1);
    	int *lire;
    	int *ecrire;
     
    	//  remplissage du tableau  //
     	for (i=0, ecrire=tab; i<n; i++, ecrire++) *ecrire=i+1;
     
    	//  impression tableau initial //
     	for (i=0, lire=tab; i<n; i++, lire++) printf("%d\n", *lire);
     
    	// 
    	puts("\n");
     
    	//  élimination des éléments impairs du tableau  // 
    	lire=tab;
    	ecrire=tab;
    	i=0;
    	j=0;
    	while (i<n) {
    		while ((*lire %2) !=0) {
    			i++;
    			lire++;
    		}
    		*ecrire=(*lire);
    		lire++;
    		i++;
                    ecrire++;
     	 	j++;
    	}
     
    	// mise a 0 des éléments impairs restants (pourquoi faire ????) 
     
    	/// réallocation à j éléments (pourquoi faire ???)
     
    	/// résultat : reste les nbs pairs  ///
     	for (k=0, lire=tab; k<j; k++, lire++) printf("%d\n", *lire);
     
    	//  libération du pointeur //
     	free(tab);
    	return 0;
    }
    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]

  8. #8
    Membre averti
    Homme Profil pro
    chirurgien retraité
    Inscrit en
    Mai 2018
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chirurgien retraité
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2018
    Messages : 21
    Par défaut
    Bonsoir et merci beaucoup pour le programme complet que vous avez écrit. Il répond bien à l'utilisation des deux pointeurs comme cela aurait être dans ce cas.

    Voici ma version corrigée selon vos conseils mais d'écriture plus banale qu'avec les deux pointeurs.

    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
    #include <stdio.h>
    #include <stdlib.h>
     
     
    int main(int argc, char const *argv[])
    {
    	int i=0,j=0,k=0,n=100,mod=13,*tab=malloc(n*sizeof(*tab));
    	if(tab==NULL)exit(-1);
     
    	//  remplissage du tableau  //
     
    	for(i=0;i<n;i++)tab[i]=i+1;
     
    	//  imprression tableau initial //
     
    	for(i=0;i<n;i++)printf("%d\n",tab[i]);
     
    	//
     
    	puts("\n");
     
    	//  elimination des éléments non divisibles par mod du tableau  // 
     
    	i=0;
    	while(i<n)
    	{
    		while(tab[i]%mod!=0) i++;
    		tab[j]=tab[i];
    		i++;
                    j++;
    	}
     
           // resultat //
     
    	for(k=0;k<j-1;k++)printf("%d\n",tab[k]); // cela fonctionne pour j-1 ...
     
    	//  liberation du pointeur //
     
    	free(tab);
     
    		return 0;
    }
    PS : j'aurai du écrire plutot : "calcul des multiples de mod !" au lieu de " elimination des éléments non divisibles par mod du tableau"

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 800
    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 800
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par orthomimi Voir le message
    Voici ma version corrigée selon vos conseils mais d'écriture plus banale qu'avec les deux pointeurs.
    Attention, il faut mettre les codes entre balises "code" => http://club.developpez.com/regles/#LIII-E. Et puis ce n'est pas interdit d'aérer un peu for(i=0;i<n;i++)tab[i]=i+1 vs for (i=0; i<n; i++) tab[i]=i+1...

    Citation Envoyé par orthomimi Voir le message
    for(k=0;k<j-1;k++)printf("%d\n",tab[k]); // cela fonctionne pour j-1 ...
    En fait c'est un plus compliqué que cela (et surtout c'est un parfait exemple de UB).
    Reprenons la boucle de recherche
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    i=0;
    j=0;
    while (i<n) {
    	while (tab[i]%mod !=0 ) i++;
    	tab[j]=tab[i];
    	i++;
    	j++;
    }
    Prenons le cas de départ: on cherche les pairs sur le tableau 1, 2, 3, 4 (4 éléments)
    i commence à 0. Le i<4 est vérifié, on entre dans la boucle
    Là tab[0] vaut 1, donc le while interne est vérifié, et i passe à 1. tab[1] vaut 2, le while interne n'est plus vérifié et i vaut toujours 1.
    Et on copie tab[1] dans tab[0]. Le tableau vaut maintenant 2, 2, 3, 4. i passe à 2 et j passe à 1.

    i vaut 2. Le i<4 est toujours vérifié, on entre dans la boucle
    Là tab[2] vaut 3, donc le while interne est vérifié, et i passe à 3. tab[3] vaut 4, le while interne n'est plus vérifié et i vaut toujours 3.
    Et on copie tab[3] dans tab[1]. Le tableau vaut maintenant 2, 4, 3, 4. i passe à 4 et j passe à 2.

    i vaut 4. Le i<4 n'est plus vérifié, on quitte la boucle avec j=2 et le tableau valant 2, 4, 3, 4. Là donc pour avoir les deux pairs "2" et "4" (avec j=2) il faut boucler jusqu'à j et non pas j-1=> for (k=0; k < j; k++) printf("%d\n", tab[k]).

    Prenons maintenant un tableau un poil plus long, exemple 1, 2, 3, 4, 5 (5 éléments).
    Au début, rien ne change. i commence à 0. Le i<5 est vérifié, on entre dans la boucle
    Là tab[0] vaut 1, donc le while interne est vérifié, et i passe à 1. tab[1] vaut 2, le while interne n'est plus vérifié et i vaut toujours 1.
    Et on copie tab[1] dans tab[0]. Le tableau vaut maintenant 2, 2, 3, 4, 5. i passe à 2 et j passe à 1.

    i vaut 2. Le i<5 est toujours vérifié, on entre dans la boucle
    Là tab[2] vaut 3, donc le while interne est vérifié, et i passe à 3. tab[3] vaut 4, le while interne n'est plus vérifié et i vaut toujours 3.
    Et on copie tab[3] dans tab[1]. Le tableau vaut maintenant 2, 4, 3, 4, 5. i passe à 4 et j passe à 2.

    Mais là ça diffère. i vaut 4, le 4<5 est encore vérifié, on entre dans la boucle.
    Là tab[4] vaut 5, donc le while interne est vérifié et i passe à 5. Et là on regarde la valeur de tab[5], sur un tableau de 5 éléments (donc qui s'arrête à tab[4]). C'est là qu'on a le UB (comportement indéterminé).
    A partir de là, il peut se passer n'importe quoi. L'hypothèse que je peux donner c'est que tab[5] (valeur aléatoire de la mémoire) est pair, donc le while interne n'est plus vérifié et i vaut toujours 5.
    Et on copie tab[5] dans tab[2]. Le tableau vaut maintenant 2, 4, ???, 4, 5. i passe à 6 et j passe à 3.

    Maintenant i vaut 6. Le i<5 n'est plus vérifié, on quitte la boucle mais cette fois avec j=3 alors que toi tu t'attends à avoir seulement deux valeurs (car dans le tableau de départ 1, 2, 3, 4, 5 tu sais qu'il n'y a que deux pairs). Donc pour solutionner ce souci tu décides qu'il faut retirer une itération et tu boucles alors jusqu'à j-1.
    Cela ne solutionne en réalité rien car
    • pour le cas où le dernier élément du tableau valide le chek, ce dernier élément (licite) n'est alors pas affiché (c'est en testant ton code sur les pairs d'un tableau allant de 1 à 10 et où je n'ai pas eu le dernier chiffre que j'ai commencé à me poser la question alors que j'avais bien tous les chiffres pour mod=13 !!!)
    • c'est déjà trop tard, de toute façon le tab[5] a déjà été demandé ce qui est interdit (c'est là que le UB se produit)


    Une solution possible, c'est de vérifier qu'on ne dépasse pas non plus dans la boucle interne
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    i=0;
    j=0;
    while (i<n) {
    	while (i < n && tab[i]%mod != 0) i++;
    	if (i >= n) break;
    	tab[j]=tab[i];
    	i++;
    	j++;
    }
    Et là on peut au final afficher le tableau en bouclant cette fois jusqu'à "j" qui contient bien la bonne valeur => for (k=0; k < j; k++) printf("%d\n", tab[k]).

    Bon, le souci c'est qu'on fait 3 fois le même test. On peut toutefois supprimer le premier (qui est devenu inutile) en mettant à la place while (1) mais pour les deux autres...

    PS: accessoirement je sais que mon code aussi faisait cette même erreur (je l'ai écrit hier soir à l'arrache sans m'y attarder).
    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]

  10. #10
    Membre averti
    Homme Profil pro
    chirurgien retraité
    Inscrit en
    Mai 2018
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chirurgien retraité
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2018
    Messages : 21
    Par défaut code corrigé
    Bonjour, et merci encore pour ta longue analyse : cela marche maintenant très bien, pour k<j et pour les divers essais que j'ai effectués avec des n et des mod différents : revoici le code selon tes suggestions.
    Entre temps, car je ne suis pas un habitué de ce forum , j'ai été lire les règles et j'ai découvert, entre autres, la balise "code" !
    J'ai aussi "aéré" l'écriture car, si cela "passe" bien dans Sublime Text, c'était trop touffu par copier-coller.

    En fait je travaille sur des tableaux de structures et je dois éliminer les éléments devenus inutiles : c'est aussi pour cela que j'avais mis les tab[] à zéro pour ne pas oublier de le faire. Ces structures contiennent des mpz_t et un tableau d'int à "nettoyer" avant suppression.

    J'ajoute que j'ai lu très en détail ton analyse et que je pense l'avoir compris : il faut limiter le i dans les deux boucles ( < n dans l'élimination et >=n dans la seconde ).
    Finalement c'était assez complexe quand on y réfléchit à froid ( dans mon programme réel cela ne collait d'ailleurs pas toujours, je comprends mieux pourquoi maintenant ).


    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
    #include <stdio.h>
    #include <stdlib.h>
     
     
    int main(int argc, char const *argv[])
    {
    	int i=0 , j = 0, k = 0 , n = 100 , mod = 10 , *tab=malloc(n*sizeof(*tab)) ;
    	if(tab == NULL) exit(-1);
    	//  remplissage et impression du tableau  //
    	for(i=0 ; i < n; i++)
    	{
    		tab[i] = i+1;
    		printf("%d\n", tab[i]);
    	}
     
    	puts("\n");
     
    	//  recherche des multiples de mod <= n  // 
     
    	i=0;
    	while(1)
    	{
    		while( tab[i]%mod!=0 && i<n) i++ ;
    		if( i >= n ) break ;
    		tab[j] = tab[i];
    		i++;
    		j++;
     
    	}
     
     
    	for( k = 0 ; k < j ; k++ ) printf("%d\n", tab[k]);
     
    	//  liberation du pointeur //
     
    	free(tab);
     
    	return 0;
    }

  11. #11
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 800
    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 800
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par orthomimi Voir le message
    J'ai aussi "aéré" l'écriture car, si cela "passe" bien dans Sublime Text, c'était trop touffu par copier-coller.
    Ok, encore quelques maladresses
    Pour être plus simple, je vais te dire comment moi j'aère:
    • pour les structures de code, un espace entre le mot clef et la parenthèse (ce n'est pas une fonction) => while (...)
    • notation Kernighan: l'accolade ouvrante juste après le mot-clef if (...) {. Au début je n'aimais pas puis au fil du temps j'ai trouvé finalement cette écriture plus sympa et surtout plus lisible
    • un espace après la virgule et le point-virgule, comme en français => for (i=0, ecrire=tab; i<n; i++, ecrire++)
    • pas d'espace pour les affectations, je trouve que ça s'accorde mieux avec son rôle (et surtout il existe d'autres langages dans lequel c'est interdit alors par mimétisme...) => tab[j]=tab[i]
    • parfois (là c'est plus de l'estimation selon le cas) j'espace pour souligner la priorité => 2 + 3*4 ou if (tab[i]%2 != 0)


    Citation Envoyé par orthomimi Voir le message
    En fait je travaille sur des tableaux de structures et je dois éliminer les éléments devenus inutiles : c'est aussi pour cela que j'avais mis les tab[] à zéro pour ne pas oublier de le faire. Ces structures contiennent des mpz_t et un tableau d'int à "nettoyer" avant suppression.
    Je ne suis pas dans ta peau ni soumis à tes contraintes... mais quelque part, je ne vois pas trop l'utilité de mettre un truc à 0 pour le libérer ensuite. C'est d'ailleurs une remarque que je voulais faire plus tôt à propos du realloc que j'ai vu. Déjà, quand on fait du realloc, il ne faut pas perdre le pointeur d'origine (au cas où le realloc se passe mal, faut pouvoir quand-même libérer le malloc initial). Donc éviter tab=realloc(tab, ...). Mais surtout quand j'étais plus novice, un de mes "seniors" en C m'avait dit qu'un realloc plus petit que la taille d'origine ne fait absolument rien. Avait-il dit vrai ou se trompait-il j'en sais rien. Mais ce que je sais c'est que je n'ai jamais eu besoin de "supprimer" (je mets ce verbe entre guillemets car en C on ne peut pas supprimer une variable, on ne peut que lui mettre une valeur X ou Y) et que même si c'était le cas, ben je ne m'embêterais pas à réallouer plus petit. Si j'ai un tableau de 500 au départ et qu'à la fin je n'ai plus que 10, ben je garde le tableau de 500 (ça ne coûte pas plus cher) tout en mémorisant que je n'en ai que 10 de valides (de toute façon cette mémorisation est obligatoire, avec ou sans realloc, donc autant éviter des instructions qui n'apportent rien à la réussite du code).

    Citation Envoyé par orthomimi Voir le message
    J'ajoute que j'ai lu très en détail ton analyse et que je pense l'avoir compris : il faut limiter le i dans les deux boucles ( < n dans l'élimination et >=n dans la seconde ).
    C'est ça. Faut pas que i dépasse n à chaque fois qu'on interroge tab[i].
    Et en y réfléchissant encore un peu, je réalise qu'on peut encore simplifier la recherche en ne faisant qu'une simple et unique boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    //  recherche des multiples de mod <= n  // 
    j=0;
    for (i=0; i < n; i++) {
    	if (tab[i]%mod != 0) continue;
    	tab[j]=tab[i];
    	j++;
    }
    Là c'est pareil, j'aurais pu écrire "si ça valide alors je copie" mais je préfère travailler dans l'autre sens en disant "si ça ne valide pas alors je passe directement au nombre suivant" car ça me permet éventuellement de mettre plusieurs raisons de refus et surtout de les shunter ou les réactiver en fonction des différents réglages pendant la mise au point.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for (...) {
    	if (echec1) continue;
    	if (echec 2) continue;
    	// if (echec 3) continue;
    	if (echec 4) continue;
    	... (action si tout est passé)...
    }
    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]

  12. #12
    Membre averti
    Homme Profil pro
    chirurgien retraité
    Inscrit en
    Mai 2018
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chirurgien retraité
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2018
    Messages : 21
    Par défaut
    Bonsoir

    Je suis un peu honteux de te faire perdre ton temps mais il est vrai que tes remarques sont très judicieuses : je suis hélas qu'un amateur en informatique, ce n'était pas mon métier d'origine ( ou alors il y a plus de 50 ans, et un court essai, quand j'ai du faire du Fortran pour un mémoire d'ingénieur ! ).

    Je prends donc note :

    -des écritures "aérées" : "mot, espace autre mot; espace etc" donc comme en français.
    -le if espace () ou tout autre instruction mais pas pour les fonctions.
    -pas d'espace en affectation mais peut-être un espace dans le booléen (?) : j'ai vu que c'est ce que tu fais. Ainsi que les priorités de calculs pour qu'on les voit clairement ( on pense d'ailleurs aux règles de bash pour l'affectation ).
    -pas d'intérêt à "realloquer" pour diminuer la taille (+++) : d'ailleurs dans ma structure la taille est prévue dans sa définition. Il faudra que je revoie aussi cela dans un autre programme ( division de polynomes ) : j'utilisais le "realloc" pour diminuer son degré au fur et à mesure mais en fait je mettais simultanément à zéro le coefficient , donc cela ne devait servir à rien.
    Par contre dans mon tableau de structure, sans faire de "realloc", je dois au minimum réinitialiser le mpz_t , je pense ? c'est parfois assez volumineux et il y en a beaucoup a remettre a zéro. Comme tu le dis : pas de suppression de variables en C mais réinitialisation possible.

    -et surtout, j'ai retenu l'utilisation de "continue" que, à la différence de "break", je n'utilisais jamais car c'est bien plus subtil à mettre en oeuvre.

    Et là, il a fallu que je réfléchisse un peu :
    -si ce n'est pas divisible mon i monte sans le j et surtout je n'affecte rien, car ce n'est pas le résultat que je cherche.
    -sinon j'affecte et je monte le i et le j .
    Et on s'arrête bien quand i<n (en partant de 0 ). Vachement élégant !

    Merci de m'instruire comme cela, c'est très sympa de ta part.

  13. #13
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 800
    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 800
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par orthomimi Voir le message
    Merci de m'instruire comme cela, c'est très sympa de ta part.
    Avec plaisir. Moi quand je vois un chirurgien (je me suis amusé une fois à regarder une annale de concours numerus clausus je n'ai même pas compris les questions !!!) s'intéresser à la programmation je suis super motivé pour l'aider (j'ai été prof de C). Peut-être éventuellement te proposer d'aller voir du côté de Python, langage pas aussi rapide que le C mais n'ayant pas à rougir de ses performances et surtout, permettant d'écrire 10 fois plus vite. Et mon tutoriel Python est en passe d'être bientôt mis en ligne sur le site.
    Exemple de ce même code en Python:
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    tab=list(range(1, 101))
    tab=[x for x in tab if x%10 == 0]		# Autre possibilité: tab=list(filter(lambda x: x%10 == 0, tab))
    print("\n".join(map(str, tab)))
    (ok la 3° ligne c'est pour le fun du Python, d'habitude j'écris plus simplement for x in tab: print(x)).

    Je remarque aussi avec plaisir que tu connais le BASH (donc Linux). Effectivement c'est à lui que je pensais quand j'ai parlé de langages qui n'acceptent pas les espaces dans les affectations. Et Python est installé en natif dans Linux.

    Et surtout Python a été associé à une librairie IHM nommée Qt (donc pour Python c'est PyQt) permettant non seulement de coder des choses mais aussi de les montrer dans un environnement fenêtré. Un exemple ici. Et pour s'initier un petit tutoriel PyQt https://pyqt.developpez.com/telechar.../47/Hello-Word.
    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]

  14. #14
    Membre averti
    Homme Profil pro
    chirurgien retraité
    Inscrit en
    Mai 2018
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chirurgien retraité
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2018
    Messages : 21
    Par défaut
    Bonjour

    Encore merci pour ton attention , le reste, et le "continue" !
    Je vais aussi me remettre à Python que j'ai pratiqué pendant une année.

    Amicalement

Discussions similaires

  1. Suppression élément d'un tableau dynamique
    Par gigacool1994 dans le forum C++
    Réponses: 7
    Dernier message: 08/01/2013, 23h52
  2. Suppression d'un élément dans un tableau
    Par hammag dans le forum Langage
    Réponses: 1
    Dernier message: 25/06/2009, 15h30
  3. Réponses: 6
    Dernier message: 10/01/2009, 14h12
  4. [Tableaux] suppression d'élément d'un tableau
    Par maysa dans le forum Langage
    Réponses: 8
    Dernier message: 04/04/2007, 08h37
  5. Suppression d'éléments dans un tableau (Array)
    Par jeremie74 dans le forum Flash
    Réponses: 4
    Dernier message: 06/03/2007, 13h54

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