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 :

Allocation d'un tableau au fur et à mesure de la saisie


Sujet :

C

  1. #1
    Nouveau membre du Club
    Inscrit en
    Janvier 2011
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 79
    Points : 35
    Points
    35
    Par défaut Allocation d'un tableau au fur et à mesure de la saisie
    Bonjour,
    mon problème est le suivant:Soit w un tableau dynamique de type entier.
    Ecrire un programme qui fait l’allocation de la mémoire au fur et à mesure de la saisie de w, en exigeant que les éléments soient distincts (rejeter toute valeur en double, au cours de la saisie).
    Mon modeste essai est le suivant:
    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
     
    main()
    {
        int ch=2;
        int *w;
        int k=0,j;
        int cpt=0;
        void *p;
     
        printf("la saisie:\n");
     
        int sidouble_existe(int *tab,int val)
        {
            int existe_double=0,i=0;
            while (existe_double==0 && i<strlen(tab))
            {
                if (*(tab+i)==val)
                {existe_double=1;}
                else { i++; existe_double=0;}
                //printf("existe double est :%d", existe_double);
            }
            return existe_double;
     
        }
     
        w=(int*)malloc(sizeof(int));// si on l'enleve programme va cesser de fonctionner
        do
        {
            //fflush(stdin);
            printf("Entrez un chiffre:\n");
            scanf("%d",&ch);
            if (sidouble_existe(w,ch)==0)
            {   
                cpt++;
                if (p=(int*)realloc(w,sizeof(int)))
                {
                    w=p;//la réallocation s est bien passe
                    *(w+k)=ch;
                    k++;
                }
            }
            else {
                printf("Vous avez saisi une valeur qui existe dèja");
            }
        }while(cpt<5);//par ex
        //printf("les elements du tableau sont:\n%d",*w);
        getch();
    }
    le problème que je rencontre dans ce programme c'est qu'il ne compare le chiffre entré qu'avec le premier,par exemple si je tape 1 2 1 2,il va m'indiquer que le 1 est double mais le 2 non.puis dans l'affichage,est ce que je peut afficher le tableau sans une boucle.Si vous avez des propositions je serais reconnaissante.Merci

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    On mettra la définition de la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int sidouble_existe(int *tab,int val)
    en dehors de la fonction main() qui elle a un retour de type int.

    Plusieurs remarques dans cette fonction sidouble_existe() :
    • strlen(tab) n'est absolument pas adapté ici. Cette fonction détermine la taille d'une chaine de caractères. Pour cela elle se base sur une adresse de départ, et se termine sur le premier caractère '\0' qu'elle rencontre à partir de cette adresse. En aucun cas elle ne calcule la taille allouée d'un tableau quelconque.
      Tu dois ici passer en argument supplémentaire cette même taille que tu essayes de calculer.
    • Cette affectation existe_double=0; ne sert à rien : existe_double est déjà à zéro, et si ce n'est pas le cas, on est sorti de la boucle.
    • *(tab+i) question de goût je préfère l'écriture tab[i]

    Passons au reste :
    • Tu vérifies bien le retour de p=(int*)realloc(w,sizeof(int)) (bien que tu continues normalement ton programme...) mais tu ne vérifies pas w=(int*)malloc(sizeof(int));.
      À noter que le cast de malloc/realloc est inutile en C (cf. FAQ).
    • La réallocation précédente ne fait que ré-allouer de l'espace mémoire pour un seul entier, et cet espace n'est PAS complémentaire aux précédents, mais il les remplace. Il te faut multiplier sizeof(int) par le nouveau nombre d'éléments voulu.
    • getch(); on lui préfèrera getchar(); qui lui est portable.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Comme l'a dit Winjerome, strlen() s'appuie sur la présence d'un caractère particulier pour détecter une fin de chaine. Elle s'appuie aussi sur l'assertion que ledit caractère ne peut en aucun cas faire partie des caractères habituels d'une chaine.
    Malheureusement tu ne peux pas appliquer ce mécanisme dans ton cas car dans ton cas, tout entier quel qu'il soit est susceptible d'appartenir au tableau d'entiers. Tu n'as donc aucune valeur disponible pour marquer la fin de ton tableau.

    Partant de là, tu es obligé d'utiliser autre chose pour savoir où t'arrêter. Et le seul autre élément que tu as à ta disposition est de gérer toi-même le nombre d'entiers insérés.

    De plus, le realloc étant assez lourd, il est d'usage de ne pas l'appliquer à chaque élément mais d'essayer d'allouer des buffers d'éléments. Par exemple tu alloues 10 et tu remplis le tableau. Quand le nombre d'éléments atteint 10 alors tu réalloues 10 de plus et tu continues à remplir. Et etc etc. Cela te fait une seconde valeur à gérer, à savoir la taille allouée pour pouvoir détecter quand cette taille est atteinte. Et il reste aussi à créer un pointeur intermédiaire permettant de tester le realloc sans perdre le pointeur principal (au cas où realloc plante, il ne faut pas perdre le pointeur principal pour pouvoir te rattrapper)

    Ainsi, pour gérer ton tableau tu dois gérer 4 choses:
    1. le pointeur principal
    2. le pointeur temporaire
    3. le nb d'éléments utiles
    4. la taille dispo

    Partant de là, autant créer une structure dédiée qui embarquera tous ces éléments

    Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct {
        int *data;
        int *tmp;
        size_t sz_alloc;
        size_t nb;
    } t_tab;

    Ensuite, l'algo est assez simple: a chaque nombre saisi que tu dois insérer tu vérifies d'abord qu'il y a assez de place et si c'est pas le cas tu agrandis. Ce qui donne le pseudo code suivant
    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
    t_tab tab;
    tab.data=NULL;
    tab.nb=0;
    tab.sz_alloc=0;
    while ((n=saisie()) != valeur_spéciale_indiquant_la_fin_de_saisie)
    {
        // Si le tableau est plein, le nombre saisi ne pourra pas y entrer
        if (tab.nb == tab.sz_alloc)
        {
            // Dans ce cas il faut d'abord réallouer
            tab.sz_aloc+=SIZE_BUFFER;
            if ((tab.tmp=realloc(tab.data, tab.sz_alloc * sizeof(int))) == NULL)
           {
                // Ici problème de realloc à gérer - Généralement on quitte la fonction puisqu'elle ne peut plus rien faire - Mais on n'oublie pas de libérer ce qui a déjà été alloué
                free(tab.data);
                return;
           }
           // Realloc ok - On affecte le pointeur principal avec la zone réallouée
           tab.data=tab.tmp;
        }
     
        // Ici, soit qu'on soit passé par realloc, soit pas, on sait qu'on a assez de place pour stocker le nb saisi
        tab.data[tab.nb]=n;
     
        // On a un élément de plus dans le tableau
        tab.nb++;
    }

    Ce type d'algo te garanti:
    • une reallocation optimisée (tu peux à loisir faire varier SIZE_BUFFER selon les capacités de ta machine, même le mettre à 1 si tu as envie de ne réallouer que le strict nécessaire)
    • une taille toujours suffisante pour stocker tous les nombres voulus

    A noter que quand le pointeur d'origine est à NULL, realloc se comporte comme malloc (c'est pour ça que je l'initialise à NULL au début)

    Il y a juste dans ton cas le fait que le nombre ne doit pas déjà y être: pas de souci pour ça, tu fais juste un test avant la phase de reallocation (perso je passerais par une fonction dédiée à ce travail à laquelle je lui passe tab). Si le nombre est déjà dans le tableau tu tapes un continue et tu passes à la saisie suivante sans le traiter. Et ton pb est fini.
    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]

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/07/2013, 22h58
  2. [XL-2003] Recherche au fur et à mesure de la saisie
    Par stefan69 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 14/01/2010, 16h50
  3. Filtrer la source d'un combo au fur et à mesure de la saisie
    Par modafine dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 24/11/2008, 17h42
  4. calcul au fur et à mesure de la saisie
    Par papimcha dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 29/04/2008, 14h27
  5. Réponses: 6
    Dernier message: 12/01/2008, 22h53

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