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 :

Création d'une table en C


Sujet :

C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 14
    Points : 7
    Points
    7
    Par défaut Création d'une table en C
    Bonjour à tous,

    J'ai à concevoir une fonction permettant de créer une table en C. Selon ce que j'en sais, une table par définition est représentée par un tableau de structures en C. Cela ne me pose pas de problème à part un point: Je dois implanter cette fonction de telle sorte que l'utilisateur puisse, avec son appel, spécifier le type ainsi que le nom de chaque champs de la structure. Un fois ces données déterminées, elles doivent rester en place lors de la création des enregistrements de la table. Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    creerTable(int capacite, type1, nomType1, type2, nomType2)
    Bien sûr, capacite est un entier invariant indiquant le nombre d'élément que la table peut contenir... Type1 et nomType1 représententle type et le nom du premier champs de ma structure, idem pour type2, nomType2. Ce n'est pas faute d'avoir cherché, mais je n'ai trouvé à nulle part le moyen de modifier les types et noms des champs d'une structure à l'aide des paramètres de la fonction qui la contient. Ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void creerTable(int long, type1, nomChamps1)
    {
    typedef struct {
      type1 nomChamps1;
    } Enregistrement;
    Enregistrement* uneTable[long]; //Création tableau
    }
    Je sais, c'est complètement incohérent comme code C'est juste pour vous montrer comment je voudrais utiliser la paramètre de la fonction pour modifier le type de la structure.

    Bien qu'ayant une certaine expérience en C++, je suis un complet débutant en C. Peut-être y-a-t-il un moyen plus facile de faire ce je veux faire... SVP amis gourous du C, votre avis et votre aide seraient grandement appréciés

    PS J'ai fait bien des recherches infructueuses avant de m'adresser à vous!

  2. #2
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Points : 163
    Points
    163
    Par défaut
    Tu peux déclarer tous les champs comme float ou un autre type très "large" et ensuite faire un cast selon les choix de l'utilisateur.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 14
    Points : 7
    Points
    7
    Par défaut Chaine
    C'est vrai Dré Kam. Cependant, les champs doivent pouvoir prendre n'importe quel type, y compris char et char*. Dans le même ordre d'idée que ta suggestion, j'ai même pensé utiliser des pointeur void comme champs dans ma structure. J'ai testé et ça marche Cependant, ce qu'on me demande, c'est d'indiquer explicitement le type des champs avec l'appel de le fonction creerTable, c'est types pouvant changer d'un appel à l'autre, dépendant de la forme que l'utilisateur de la fonction veut donner à la table.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonsoir,

    pourquoi ne pas imaginer quelque chose comme ça
    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
     
    #define INT 1
    #define FLOAT 2
    // etc...
    struct Table {
      void* datas;
      int type;
    };
    Table createTable(void* datas, int type, int size)
    {
      Table t;
      t.datas = malloc(size);
      memcpy(t.datas, datas, size);
      t.type = type;
      return t;
    }
    En théorie ça me semble bon, en pratique je demande à voir, je n'ai pas testé le code.
    L'idée est de garder une information sur le type réel pour le cast.
    Bon là il n'y a qu'un seul champ, mais en créer plusieurs ne serait pas plus compliqué.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Salut moi ce que je ferais :
    1 utiliser des listes chainées pour la gestion des données ;une table c'est une sorte de matrice qui va gonfler...
    2 définir un type variant comme le définit Microsoft avec son type
    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
     
    struct  tagVARIANT
        {
        union 
            {
            struct  __tagVARIANT
                {
                VARTYPE vt;
                WORD wReserved1;
                WORD wReserved2;
                WORD wReserved3;
                union 
                    {
                    LONG lVal;
                    BYTE bVal;
                    SHORT iVal;
                    FLOAT fltVal;
                    DOUBLE dblVal;
                    VARIANT_BOOL boolVal;
                    _VARIANT_BOOL bool;
                    SCODE scode;
                    CY cyVal;
                    DATE date;
                    BSTR bstrVal;
     
                    }	__VARIANT_NAME_3;
                }	__VARIANT_NAME_2;
            DECIMAL decVal;
            }	__VARIANT_NAME_1;
        };
    en voici un morceau tu peux t'inspirer de cela....
    avec un struct { union{}}
    A la place de BSTR il faut définir son type char*
    Donc ainsi pour passer des paramètres il suffit de passer un type Variant au lieu de faire un cast

    3 il faut être masochiste pour faire cela il ya des SGBDR tout fait qui fonctionnenttrès bien

  6. #6
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Citation Envoyé par dré kam Voir le message
    Tu peux déclarer tous les champs comme float ou un autre type très "large" et ensuite faire un cast selon les choix de l'utilisateur.
    d'accord mais avec un float comment vais-je faire pour passer des char* ?

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Si je comprends bien, le but serait de mettre, pour chaque champs de la table, un pointeur void et un entier indiquant le type de la donnée, dans la struct... Et quand serait venu le temps de traiter les données ??? Faire un case sur le variable type et traiter datas en conséquence ??? Mmmmmmmm... j'crois bien que ça pourrait marcher... j'vais devoir tester... Merci

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Mat.M, je suis d'accord avec vous que ce serait plus facile avec un SGBD. Mais bon, le défi qu'on m'a lancé est de le faire de cette manière. Je dis défi car je fais partie de cette génération de programmeurs à qui on a enseigné la programmation orientée objet en C++ sans, malheureusement à mon avis, passer par C. Du coup, je suis un peu perdu sans tous mes beaux objets Hahaha!!

  9. #9
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Ce n'est pas faute d'avoir cherché, mais je n'ai trouvé à nulle part le moyen de modifier les types et noms des champs d'une structure à l'aide des paramètres de la fonction qui la contient.
    Ce n'est pas possible

    @dré kam :
    Tu peux déclarer tous les champs comme float ou un autre type très "large" et ensuite faire un cast selon les choix de l'utilisateur.
    Totalement à exclure. A noter qu'un cast n'est pas neutre et peut modifier la représentation binaire de la grandeur.

    Dans le même ordre d'idée que ta suggestion, j'ai même pensé utiliser des pointeur void comme champs dans ma structure. J'ai testé et ça marche
    un void* est effectivement la solution pour "banaliser" le type. Encore faudra t-il restituer le type exact lorsque le déréférencement du pointeur devra être fait

    Cependant, ce qu'on me demande, c'est d'indiquer explicitement le type des champs avec l'appel de le fonction creerTable, c'est types pouvant changer d'un appel à l'autre, dépendant de la forme que l'utilisateur de la fonction veut donner à la table.
    Ce n'est pas possible : Le type des objets C est déterminé à leur création et on ne peut plus le changer (et ce type détermine la taille des objets créés et les opérations qui leur sont applicables.

    On peut envisager par exemple les déclarations suivantes :

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdarg.h>
    // Codage du type d'un champ (à compléter)
    typedef enum {tyUnkwn, tyChar, tyInt, tyFloat, tyString} TType;
    // Taille en byte du champ (dans le même ordre)
    static size_t Taille[]= {0, sizeof(char), sizeof(int), sizeof(float), sizeof(char*)};
    /*---------------------------*/
    typedef struct
    {
       TType code;      // Code le type du champ
       void* champs;    // Pointe la valeur du champ
    } TChamps;
     
    typedef struct
    {
      int nbElements;    // Nombre de champs
      TChamps champs[];  // tableau des champs
    } Enregistrement;
    /*---------------------------*/
    Les fonctions de création sous forme variadique pour permettre un nombre variable d'arguments :
    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
    static void creerChamp(TChamps* champs,TType type1 , void* nomType1)
    {
         int dim = Taille[type1];
         champs->code = type1;
         if(type1 == tyString )dim = strlen(nomType1)+1;
         champs->champs = malloc(dim);
         if(champs->champs != NULL) memcpy(champs->champs, nomType1,dim );
    }
    /*---------------------------*/
    Enregistrement * creerTable(int capacite, ...)
    {
      int i;
      Enregistrement * p;
      va_list ap;
      va_start(ap,capacite);
      p = malloc(sizeof (*p)+ capacite* sizeof(TChamps));
      if(p!=NULL)
      {
         p->nbElements = capacite;
         for(i=0; i< capacite; i++)
         {
              TType type = va_arg(ap, TType);
              void * arg = va_arg(ap, void *);
              creerChamp(p->champs+i, type,arg);
         }
      }
      va_end(ap);
      return p;
    }
    L'utilisation n'est pas élégante à cause des cast : par exemple
    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
    void afficherTable(Enregistrement * table)
    {
      int i;
      if(table != NULL)
         for(i=0;i<table->nbElements;i++)
           switch(table->champs[i].code)
           {
     
              case tyInt : printf("%d\n", *(int*)table->champs[i].champs) ;
                           break;
              case tyFloat : printf("%f\n", *(float*)table->champs[i].champs) ;
                           break;
              case tyString : printf("%s\n",(char*)table->champs[i].champs) ;
                           break;
              //.......
           }
    }
    Une séquence d'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int main(void)
    {
      int i = 123456;
      float f = 3.1416;
      Enregistrement * table1;
      Enregistrement * table2;
      table1  = creerTable(3, tyString, "ABCDEF", tyInt, &i, tyFloat, &f);
      afficherTable(table1);
      table2  = creerTable(2, tyInt, &i, tyFloat, &f);
      afficherTable(table2);
    // reste à faire la destruction des tables
      return 0;
    }
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  10. #10
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 14
    Points : 7
    Points
    7
    Par défaut Merci à tous !!!
    Merci à tous pour vos suggestions !!!
    Étant nouveau sur le forum, je suis très agréablement surpris par le haut niveau d'entraide qui y règne

    Concernant le problème soulevé: diogène, la démarche que vous m'avez soumise pourrait bien être celle dont je m'inspirerai pour traiter la demande qui m'a été faite. Étant tout nouveau en C, je dois cependant vous avouer que je vais devoir prendre quelques temps pour l'étudier, tout en explorant les subtilités du C. On aura beau dire que le C et le C++ (que je connais très bien) se ressemblent, plusieurs différences font que le passage de l'un à l'autre demande un certain apprentissage... Je vais devoir apprendre à troquer mes New et Delete contre les malloc, free et autre sizeof

    L'utilisation n'est pas élégante à cause des cast : par exemple
    Franchement, considérant qu'on parle ici d'implanter des fonctions génériques dans un langage qui ne l'est pas, je considère que votre solution ne manque pas du tout d'élégance

Discussions similaires

  1. création d'une table dans une base de donnée accèss
    Par zidenne dans le forum Bases de données
    Réponses: 1
    Dernier message: 25/10/2005, 10h54
  2. Question sur la création d'une table
    Par air dans le forum Oracle
    Réponses: 4
    Dernier message: 23/10/2005, 12h46
  3. Réponses: 4
    Dernier message: 19/10/2005, 11h26
  4. Création d'une table avec foreign key
    Par lepierre dans le forum Langage SQL
    Réponses: 5
    Dernier message: 17/09/2004, 14h20
  5. INTERBASE Création d'une table
    Par Corben dans le forum InterBase
    Réponses: 2
    Dernier message: 19/06/2004, 20h55

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