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

  1. #1
    Membre régulier
    Initialiser un tableau => base de donnée mysql/mariaDb
    Bonjour à tous,

    Mon petit soucis du jour : j'aimerai récupérer des données données dans une tableau 2d " tableau[i][j] ". Je ne sais comment initialiser mon tableau car je ne connais pas le nombre de ligne que va me donner ma requête à la base de donnée .... Les informations récupérées "row[2]" sont de type binary(64) dans la base de donnée.

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/inotify.h>
    #include <time.h> 
    //mysql
    #include <mariadb/mysql.h>
     
    int main()
    {
     
    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;
     
    char *server = "localhost";
    char *user = "***";
    char *password = "***"; 
    char *database = "TEST";
     
    int row_precedent;
    int i,j = 0;
     
    conn = mysql_init(NULL);
       if (!mysql_real_connect(conn, server,
             user, password, database, 0, NULL, 0)) {
          fprintf(stderr, "%s\n", mysql_error(conn));
          exit(1);
       }  
    	 char insertion[300];
    	 sprintf(insertion, "SELECT * FROM BDtest WHERE temps > %d", (int)time(NULL));
    	 if (mysql_query(conn, insertion)) {
          fprintf(stderr, "%s\n", mysql_error(conn));
          exit(1);
       }
       res = mysql_use_result(conn);
     
       while ((row = mysql_fetch_row(res)) != NULL)
           {
          printf("%s %s %s \n", row[0],row[1],row[2]);
     
    		if(row[1]!=row_precedent)
    		{
    		j=0;
    		tableau[i][j]=row[2];
    		i++;
                    row[1]=row_precedent;
    		} 
     		else
    		{
    		tableau[i][j]=row[2];
    		j++;
    		}
    	}
     mysql_free_result(res);
     mysql_close(conn);	
    //fin connexion mysql	
     
    }


    Merci de votre aide et bon WE

  2. #2
    Membre habitué
    Bonjour,
    si tu ne connais pas la dimension à l'avance, soit tu utilises un tableau statique dont la taille vaut le maximum de la longueur possible des données (mais ce n'est pas forcément une bonne solution), soit tu utilises un tableau dynamique:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    #include <vector>
    vector<type_donnée> tableau(longueur_tableau); //longueur_tableau est int (et non un const int)

    Bon courage.

  3. #3
    Membre habitué
    Ici ce sera donc le type vector<vector<string>> qu'il faudra utiliser (si les données à rentrer dans le tableau sont des chaines de caractère).

  4. #4
    Expert éminent
    Citation Envoyé par racine carrée Voir le message
    soit tu utilises un tableau dynamique
    Citation Envoyé par racine carrée Voir le message
    Ici ce sera donc le type vector<vector<string>> qu'il faudra utiliser (si les données à rentrer dans le tableau sont des chaines de caractère).


    Cela n'existe pas en C - en C++ oui avec std::vector et std::string (<- liens cplusplus.com en anglais)

    il faut y aller à coup de malloc/ realloc (<- liens cplusplus.com en anglais)

    Pour un exemple, regarde la structure t_list_keys et la fonction list_keys_add_one_key dans mon code dans ce fil de discussion (<- lien)

  5. #5
    Membre habitué
    Ah désolé j'avais pas fait gaffe qu'on était en C &#128514;.
    Du coup y a moyen d'utiliser des listes chainées (pour manipuler le tableau on manipule le pointeur du premier élément du tableau, chaque élément du tableau contient l'élément qu'on veut y mettre + un pointeur vers l'élément suivant, le dernier élément contient un pointeur null en plus de l'élément qu'il doit contenir, pour indiquer qu'on est arrivé à la fin du tableau).

  6. #6
    Rédacteur/Modérateur

    Est-ce que tu comptes récupérer de très larges sets de données ?
    Si non, utilise mysql_store_result puis mysql_num_rows.
    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.

  7. #7
    Membre habitué
    Voici un petit exemple de liste chainée pouvant contenir des chaines de caractères (de 300 caractères max, comme il semble que cela soit nécessaire dans ton code source).
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct elem elem;
    typedef char valeur[300];
    typedef struct elem{
        valeur chaine;
        elem* suivant;
    } *tableau, *Pelem;
     
    tableau ajoute(tableau tab,valeur chaine){
        if(tab){
            tab->suivant=ajoute(tab->suivant,chaine);
        } else {
            tab = malloc(sizeof(elem));
            strcpy(tab->chaine,chaine);
            tab->suivant=NULL;
        }
        return tab;
    }
     
    void affiche(tableau tab){
        if(tab){
            printf("adresse: %i\n",tab);
            printf("%s\n",tab->chaine);
            printf("adresse suivant: %i\n",tab->suivant);
            affiche(tab->suivant);
        }
    }
     
    int main()
    {
        tableau tab=NULL;
        tab=ajoute(tab,"ligne 1");
        affiche(tab);
        printf("\n\n");
        tab=ajoute(tab,"ligne 2");
        affiche(tab);
        return 0;
    }


    Pour l'adapter à ton cas il faudrait avoir un tableau de tableaux de chaines de caractères, donc je pense qu'un moyen pourrait être de créer une liste chainées contenant des pointeurs vers des tableau (de type tableau dans ce code source), et ensuite de créer les fonctions qui vont bien pour récupérer une élément du tableau quand nécessaire.
    Bon courage...

  8. #8
    Expert éminent
    Citation Envoyé par racine carrée Voir le message
    je pense qu'un moyen pourrait être de créer une liste chainées contenant des pointeurs vers des tableau (de type tableau dans ce code source), et ensuite de créer les fonctions qui vont bien pour récupérer une élément du tableau quand nécessaire.


    Est-ce que tu sais lire ? " j'aimerai récupérer des données données dans une tableau 2d"
    C'est quoi cette idée de l'enfer de coder 1 liste chaînée pour 1 matrice/ tableau 2D

  9. #9
    Membre régulier
    Citation Envoyé par Bousk Voir le message
    Est-ce que tu comptes récupérer de très larges sets de données ?
    Si non, utilise mysql_store_result puis mysql_num_rows.
    J'ai du mal comprendre comment initialiser mon tableau alors que je ne connais la taille qu'après lecture de chacune des lignes de la requête.

    La solution serait de faire 2 fois la requête:
    - la 1er fois pour compter le nombre i et de j pour connaître la taille de tableau[i][j]
    - la 2ème fois pour remplir mon tableau
    Mais je pense que la mémoire qui va être allouée est trop grande: si "i" va jusque de 1 à 10 et que "j" varie entre 1 et 100 pour chaque "i" => alors la taille de mon tableau sera de 10 x 100 alors que dans les faits j'ai peut-être besoin d'une taille 9 x 1 (car le 9 "i" ne contiennent qu'une valeur) + 1x100 (car il y a un "i" qui contient 100 valeurs différentes).



    Je vois une autre solution en récupérant le nombre de ligne avec "mysql_num_rows" ce qui me donne la taille de mon tableau. Enfin la taille globale : si le résultat est par exemple 109 car 109 ligne, est ce que je peux initialiser mon tableau comme cela :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    int tableau[109];

    Puis utiliser mon tableau comme suit :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    tableau[0][0]=1;
    tableau[1][0]=5;
    tableau[2][0]=6;
    tableau[3][0]=1;
    tableau[3][1]=0;
    tableau[3][2]=8;
    ...
    tableau[3][99]=7;
    tableau[4][0]=5;
    tableau[5][0]=6;
    ...
    tableau[9][0]=6;

  10. #10
    Expert éminent
    Citation Envoyé par sebaaas Voir le message
    J'ai du mal comprendre comment initialiser mon tableau alors que je ne connais la taille qu'après lecture de chacune des lignes de la requête.
    Il faut utiliser l'allocation dynamique et savoir qu'1 tableau à X dimensions en C est juste un tableau contiguë ligne par ligne en mémoire - il faut aller voir les cours si tu n'y connais rien.
    En gros, array[i][j] == array[j + i * nb_columns]

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        int* array /* = NULL */;
        size_t nb_rows, nb_columns;
     
    //  lecture nb_rows, nb_columns
     
        array = malloc(nb_rows * nb_columns * sizeof(int));
     
       if (array != NULL) {
           memset(array, 0, (nb_rows * nb_columns);
       } else {
    //     error
       }


    memset : documentation officielle en anglais
    calloc : documentation officielle en anglais

    Ensuite, cela va dépendre pour faire la copie des données : soit avec une boucle for soit avec la fonction memcpy (<- lien cplusplus.com en anglais)

    Et n'oublie le free (<- lien cplusplus.com en anglais) pour désallouer ton tableau

  11. #11
    Membre habitué
    C'est quoi cette idée de l'enfer de coder 1 liste chaînée pour 1 matrice/ tableau 2D
    Moi j'aurais pensé faire une liste chainées de pointeurs vers des listes chainées contenant des char[const int], ce qui aurait permis de créer une matrice (à 2d) dont les des deux dimensions peuvent varier. Il est vrai que l'allocation dynamique dont tu parles parait intéressante, mais j'ai juste une interrogation à ce propos: à chaque élément qu'on rajoute à la fin du tableau on utilise realloc() pour agrandir le tableau, et cette fonction est obligée décaller toute la zone mémoire plus loin s'il n'y a pas assez de place pour l'agrandir; donc si on rajoute un nombre important d'éléments on a beaucoup de chances que l'ensembles des éléments soit déplacé un grand nombre de fois, ce qui risque de diminuer les performances. Alors que le fait d'utiliser une liste chainées de pointeurs vers des listes chainées de char[const int] ne va jamais tous les éléments lors de l'ajout d'un élément, mais réservera juste une place en mémoire et actualisera un pointeur (après il est vrai que cette méthode est plus longues à programmer et semble un peu tordue, et a probablement des inconvénients que je n'ai pas vus...)

    Je vois une autre solution en récupérant le nombre de ligne avec "mysql_num_rows" ce qui me donne la taille de mon tableau. Enfin la taille globale : si le résultat est par exemple 109 car 109 ligne, est ce que je peux initialiser mon tableau comme cela :
    Attention la taille d'un tableau statique est un const int, ce qui fait que sa taille ne peut pas dépendre d'une variable du programme (si tu fixes à 109 ok, mais ça sera toujours 109). C'est pour ça qu'il faut utiliser de l'allocation dynamique.

  12. #12
    Expert éminent
    Citation Envoyé par racine carrée Voir le message
    à chaque élément qu'on rajoute à la fin du tableau on utilise realloc() pour agrandir le tableau, et cette fonction est obligée décaller toute la zone mémoire plus loin s'il n'y a pas assez de place pour l'agrandir; donc si on rajoute un nombre important d'éléments on a beaucoup de chances que l'ensembles des éléments soit déplacé un grand nombre de fois, ce qui risque de diminuer les performances
    Déjà, c'est l'allocateur mémoire qui est "en dessous" qui gère cela - cet allocateur est spécifique à chaque système d'exploitation et on ne sait pas vraiment comment il fonctionne.
    Mais tu as raison plus on fait d'allocations et/ ou de grosses allocations, plus il faut s'attendre à des recopies.

    C'est pour cela qu'à chaque réallocation , on fait cela par chunk (X cases par X cases) - std::vector travaille comme cela et c'est ce que j'ai fait dans mon code que j'ai posté dans mon précédent message.
    Et donc, la difficulté c'est de calibrer ce X. Dans mon code, à la fin, on a un tableau de 326688 valeurs ... alloué 7 par 7 - Ce n'est pas terrible - mais dès fois, on ne connait pas la taille finale.


    Citation Envoyé par racine carrée Voir le message
    Moi j'aurais pensé faire une liste chainées de pointeurs vers des listes chainées contenant des char[const int], ce qui aurait permis de créer une matrice (à 2d) dont les des deux dimensions peuvent varier.
    la liste chaînée pour des POD (Plain Old Data, entiers et flottants sauf structures) il faut vraiment vraiment 1 besoin spécifique.
    Pourquoi ? parce comme 1 valeur a au plus la taille d'1 pointeur (<= 4 ou 8 octets), tu doubles la quantité mémoire. (chaque maillon contient 1 POD + 1 pointeur)

  13. #13
    Rédacteur/Modérateur

    Citation Envoyé par sebaaas Voir le message
    J'ai du mal comprendre comment initialiser mon tableau alors que je ne connais la taille qu'après lecture de chacune des lignes de la requête. ...
    Et si tu lisais la doc au lieu de faire au petit bonheur ?

    mysql_use_result permet d'itérer sans connaître le nombre de résultats et est utilisé quand ils sont très nombreux. Parce qu'avoir tout ça en mémoire peut être problématique.
    C'est pourtant on ne peut plus clair si tu lis le lien...
    You may not use mysql_data_seek(), mysql_row_seek(), mysql_row_tell(), mysql_num_rows(), or mysql_affected_rows() with a result returned from mysql_use_result(), nor may you issue other queries until mysql_use_result() has finished. (However, after you have fetched all the rows, mysql_num_rows() accurately returns the number of rows fetched.)
    mysql_store_result met tout en mémoire et permet d'utiliser mysql_num_rows.
    Idem, j'ai juste lu la doc disponible pour absolument tout le monde...
    After you have called mysql_store_result() and gotten back a result that is not a null pointer, you can call mysql_num_rows() to find out how many rows are in the result set.
    Maintenant faudrait voir si tu as vraiment besoin de stocker ces résultats, parce qu'itérer dessus est bien souvent suffisant.
    Mais si tu veux connaître le nombre de résultats, il ne faut pas utiliser mysql_use_result mais mysql_store_result.
    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.