Aller au menu - Aller au contenu

Utiliser l'API MySQL dans vos programmes


Informations sur le tutoriel

Avatar
Auteur : The BasheR
Visualisations : 33 170


Plus d'informations Plus d'informations
Tout d'abord bonjour tout le monde et bienvenue dans mon premier tuto pour le site du zéro! (pour cela je vous demanderai d'être indulgent :D )

Dans ce tuto je vous apprendrai à utiliser l'API MySQL dans vos programmes pour les rendre encore plus complet et intéressant, à condition pour cela que vous compreniez bien ce que je vais vous apprendre ;) .
A la fin de ce cours vous devriez être capable de vous connecter à une base de données (BDD) et de faire des requêtes SQL.

Si vous êtes toujours partant attachez vos ceintures et préparez-vous à partir à l'aventure ! :pirate:

Préface

Pré-requis



Pour pouvoir comprendre au mieux ce tuto quelques connaissances sont requises:

MySQL


Vous devez savoir ce qu'est une BDD (base de données), ainsi que tout le vocabulaire comme: table, champ, ligne, requête SQL, ...
Il vous est aussi conseillé de connaître les bases du langage SQL pour pouvoir comprendre les requêtes de base.

S'il vous manque certaines connaissances à ce sujet je vous conseille de lire le tuto de M@teo sur le PHP, de cette manière vous serez plus en mesure de comprendre ce tuto ;) .

C/C++


Il vous faudra avoir des bases en C (pointeurs, fonctions, conditions, boucles, installation d'une librairie, ...) pour comprendre ce tuto.
Si vous savez faire tout ça c'est tout bon, sinon je vous conseille encore une fois les cours de M@teo (mais sur le C/C++ cette fois ^^ ). (je vous conseille de le lire jusqu'à la partie 3 sur la SDL au minimum)

API MySQL mais pour faire quoi?



Ben oui à quoi ça nous sert d'apprendre à utiliser MySQL dans nos programmes?

Voici une bonne question et je vais y répondre par un exemple simple.

Imaginons que vous vouliez faire un jeu dans lequel le joueur à un score final, alors vous allez faire un fichier score et y stocker le score, comme ça le joueur et ses amis pourront se concurrencer pour voir lequel est le meilleur, mais alors pourquoi ne pas faire ça à une plus grande échelle? Eh oui vous pourriez enregistrer le score du joueur dans une BDD en utilisant l'API MySQL et de cette manière ce n'est plus qu'avec ses amis que le joueur va concurrencer, mais avec TOUT le monde puisque les scores de tout le monde seront enregistrés dans cette BDD, il vous suffira après de faire une requête pour récupérer ces scores pour que le joueur puisse voir s'il est le meilleur ou non.

Bien sûr ce n'est qu'un exemple parmi tant d'autres ;) .

Portabilité



Utilisant les sockets de windows, les exemples qui seront proposés dans ce tuto ne pourront être compatible que pour windows, je sais que ça pose problème pour les linuxiens qui veulent apprendre à utiliser l'API MySQL mais je ne connais pas d'autres moyens et j'en suis désolé :( .

Installation

Nous allons maintenant passer à l'installation de la librairie MySQL.

dev-C++


Je n'ai pas Dev-C++ donc je m'appuie sur ce qu'on m'a dit:
  • Allez tout d'abord dans Aide puis cliquez sur A propos de Dev-C++
  • Une fenêtre apparaît et vous cliquerez sur Nouvelle version
  • De là vous sélectionnez le serveur devpack.org comunity devpacks puis vous cliquez sur Check for update
  • Dans groups vous choisirez databases puis vous sélectionnerez libmysql
  • Téléchargez le
  • Allez dans les options du projet, onglet paramètres, case éditeur de liens et marquez -lmysql


VC


Pour VC il vous faut télécharger les includes et les librairies: Télécharger.
Une fois que vous avez ce qu'il faut vous devez:
  • Placer les fichiers .h dans ../vc/include/mysql
  • Placer le fichier .lib dans ../vc/lib
  • Ajouter libmysql.lib dans les options du projet /editeur de lien/entrée/dependence suplementaire
  • Ajouter libmysql.dll dans le dossier du projet

Merci à dorone pour ces informations sur VC.



Code::blocks


Avec Code::Blocks ce n'est pas vraiment compliqué mais les tutos montrant l'installation de cette librairie étant tellement rares que j'ai mis 3 jours avant de réussir à le faire :D .
Tout d'abord je vous ai préparé un petit fichier ZIP avec tout ce que vous allez avoir besoin pour l'installation.



Ouvrez ensuite le ZIP, vous trouverez dedans:

  • Le fichier libmysql.dll que vous mettrez dans le dossier de tous vos programmes utilisant l'API MySQL (comme vous le faite habituellement pour tous vos fichiers .dll)
  • Le fichier libmysqlclient.a que vous mettrez dans le dossier lib du dossier mingw32 de Code::Blocks
  • Et enfin un dossier MYSQL où se trouvent tous les headers dont vous pourrez avoir besoin. Copiez ce dossier et collez le dans le dossier include du dossier mingw32 de Code::Blocks


Maintenant vous n'avez plus qu'à créer un nouveau projet, mettre le fichier .dll dans le répertoire de celui-ci et linker le fichier libmysqlclient.a comme vous le faites habituellement.

Voilà la librairie est installée vous allez enfin pouvoir commencer à coder (c'est pas trop tôt :p ).

Linux


Pour linux voici la commande pour installer l'API MySQL. (c'est tout de suite plus simple ^^ )
Code : Console
$ sudo su
# apt-get install libmysqlclient15-dev

Bien sûr adaptez à votre distribution

Information de Xhtml_boys

Un peu de théorie

Nous arrivons maintenant à la partie "théorique" du tuto, dans cette partie nous allons étudier les principales fonctions de l'API MySQL pour pouvoir ensuite créer un petit jeu utilisant tout ce qu'on aura appris.

Connexion/déconnexion



Tout d'abord créez un nouveau projet en console en prenant bien soin de linker ce qu'il faut et de mettre les .dll là où il faut.
Une fois ceci prêt vous devez avoir ce code sous Code::Blocks:

Code : C
1
2
3
4
5
6
7
#include <stdio.h>
#include <stdlib.h>

int main()
{
        return 0;
}


Mais ça ne suffit pas encore pour pouvoir utiliser l'API MySQL, pour cela il faut inclure 2 librairies:

#include <winsock.h>
#include <MYSQL/mysql.h>


Vérifiez que vous avez bien mis #include <winsock.h> avant #include <MYSQL/mysql.h>, car dans le cas contraire vous aurez droit à une belle petite erreur. ;)


Voilà maintenant, vous pouvez compiler et que se passe-t-il? Comment ça, pas grand chose, vous ne vous attendiez quand même pas à ce que votre programme se mette à danser la samba après 2 includes. :lol:
lors une fois que tout se passe bien lorsque vous compiler vous pouvez continuer ce tuto. Maintenant nous allons faire quelque chose d'indispensable pour pouvoir faire des requêtes dans votre programme: l'initialisation, la connexion et la déconnexion. Eh oui sans ces choses là vous n'iriez pas bien loin , sauf pour la déconnexion mais il est quand même bien préférable de la faire croyez moi. :soleil:

Tout d'abord il va falloir que nous déclarions un pointeur de type MYSQL, ce pointeur nous servira tout au long du tuto pour pouvoir utiliser la plupart des fonctions.

Donc déclarons notre pointeur comme ceci:

Code : C
1
MYSQL *mysql = NULL;


Puis initialisons MySQL, la fonction pour faire ça est tout simplement: mysql_init(MYSQL *mysql); .
Une fois l'initialisation faite il faut se connecter, pour cela nous allons utiliser 2 fonctions que voici:

Code : C
1
2
mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg);
mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag);


Prenons-les dans l'ordre:

-mysql_options:

  • Le premier argument est le pointeur de structure que nous avons vu juste avant.
  • Le 2e argument est l'option que nous voulons configurer, nous utiliserons toujours MYSQL_READ_DEFAULT_GROUP qui lie les options spécifiées dans le fichier my.cnf.
  • Enfin le troisième argument est la valeur de cette option, donc vous pouvez mettre le nom que vous voulez.


-mysql_real_connect:

  • Le premier argument est toujours le pointeur de structure.
  • Le 2e argument est le nom de domaine ou l'adresse de votre hébergeur, dans mon cas c'estwww.goldzoneweb.info.S'il est marqué 'localhost' pour vous je vous conseille de faire comme moi et mettre l'adresse de votre hébergeur car 'localhost' engendre des erreurs.
  • Le 3e argument est votre identifiant de connexion.
  • Le 4e argument est votre mot de passe.
  • Le 5e argument est le nom de votre base de données.
  • Le 6e argument est le port, je vous conseille de mettre 0 pour éviter les erreurs.
  • Le 7e argument est le socket à utiliser, je vous conseille de mettre NULL ici.
  • Et le 8e argument est le flag, je vous conseille de mettre 0.


Pour travailler en local (avec EasyPHP par exemple), il faut mettre localhost comme 2e argument, puis root en identifiant, et il faut laisser vide pour le mot de passe. (information de Arabesque356)


Certains hébergeurs bloquent le port pour la connexion, il vous est donc impossible d'utiliser l'api avec ces hébergeurs. (information de Arabesque356)


Voilà pour les arguments de ces 2 fonctions, comme vous l'aurez sûrement compris, mysql_options sert à spécifier des options de connexion et mysql_real_connect sert à se connecter à votre base de données.

Enfin il vous reste à fermer la connexion MySQL, pour cela appelez la fonction mysql_close(MYSQL *mysql); .

Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <MYSQL/mysql.h>



int main()
{
    MYSQL mysql;
    mysql_init(&mysql);
    mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"option");

    if(mysql_real_connect(&mysql,"www.goldzoneweb.info","mon_pseudo","******","ma_base",0,NULL,0))
    {
        mysql_close(&mysql);
    }
    else
    {
        printf("Une erreur s'est produite lors de la connexion à la BDD!");
    }

    return 0;
}


Voilà je ne crois pas avoir besoin d'expliquer ce code si ce n'est que lorsque la connexion plante mysql_real_connect renvoit NULL , ce qui nous permet de gérer les erreurs.

Les requêtes n'attendant aucun jeu de résultats



Hein, c'est quoi que ça, un nouveau type de requêtes !?


Non non rassurez-vous. En fait les requêtes n'attendant aucun jeu de résultats sont en fait les requêtes comme INSERT, DELETE, CREATE, UPDATE , ...Ces requêtes n'attendent aucune réponse.
Quant aux requêtes qui attendent un jeu de résultats ce sont les requêtes comme: SELECT, SHOW , ... car elles attendent une réponse. Dans le cas de SELECT elle attend la liste des lignes qui font partie du résultat.

Donc voyons maintenant la fonction permettant de faire des requêtes MySQL:

Code : C
1
mysql_query(MYSQL *mysql, const char *query);


Il vous faudra spécifier pour cette fonction le pointeur de structures ainsi que la requête.
Voici un exemple de son utilisation:

Code : C
1
mysql_query(&mysql, "INSERT INTO ma_table VALUES('valeur 1', 'valeur 2', 'etc')");


Cette requête comme vous pouvez le voir va enregistrer dans la table ma_table les valeurs que j'ai mises dans l'exemple.

Maintenant si vous voulez savoir combien de lignes ont été affectées par votre requête il suffit d'appeler après la fonction: mysql_affected_rows(MYSQL *mysql); .

Voilà ce sont les choses principales qu'il faut savoir pour ce type de requête, maintenant nous pouvons passer aux requêtes de type SELECT , ...

Les requêtes attendant un jeu de résultats



Ce type de requête n'est pas plus compliqué que l'autre si ce n'est que comme on attend un résultat il faut faire des opérations en plus. ;)

Pour la requête en elle même ça ne change pas, il faut utiliser la fonction: mysql_query(MYSQL *mysql, const char *query); . Mais pour récupérer le résultat il y a 2 façons que nous allons voir ensemble.

mysql_use_result(MYSQL *mysql);



Cette fonction récupère le jeu de résultat mais ne l'enregistre pas dans le client. L'avantage de cette fonction est qu'elle est rapide et qu'elle utilise peu de mémoire, cependant vous ne pourrez pas faire d'opérations comme revenir au résultat n°2, ... avec cette fonction.
Vous devrez stocker la valeur de retour de cette fonction dans un pointeur de structure de type MYSQL_RES qui est fait spécialement pour stocker le jeu de résultats.

Mais stocker un jeu de résultat ne suffit pas pour le lire, pour ça vous devrez appeler une autre fonction: mysql_fetch_row(MYSQL_RES *result); . La valeur de retour de cette fonction devra quant à elle être stockée dans un pointeur de structure de type MYSQL_ROW . Cette fonction stock les valeurs de la ligne suivante dans le jeu de résultats.
Il est nécessaire après avoir utilisé cette fonction de libérer la mémoire allouée, pour cela on utilise la fonction suivante:

Code : C
1
void mysql_free_result(MYSQL_RES *result);


Comme vous le voyez elle prend en paramètre la structure MYSQL_RES .

Pensez à vérifier que mysql_use_result revoie quelque chose, sinon vous aurez le droit à une petite erreur s'il ne renvoie rien.


Voici un exemple de l'utilisation de ces 2 fonctions:

Code : C
 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
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <MYSQL/mysql.h>



int main()
{
    //Déclaration du pointeur de structure de type MYSQL
    MYSQL mysql;
        //Initialisation de MySQL
        mysql_init(&mysql);
        //Options de connexion
        mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"option");

        //Si la connexion réussie...
        if(mysql_real_connect(&mysql,"www.goldzoneweb.info","mon_pseudo","*****","ma_base",0,NULL,0))
        {
            //Requête qui sélectionne tout dans ma table scores
            mysql_query(&mysql, "SELECT * FROM scores");

            //Déclaration des pointeurs de structure
            MYSQL_RES *result = NULL;
            MYSQL_ROW *row = NULL;

            int i = 1;

            //On met le jeu de résultat dans le pointeur result
            result = mysql_use_result(&mysql);

            //Tant qu'il y a encore un résultat ...
            while ((row = mysql_fetch_row(result)))
            {
               printf("Resultat %ld\n", i);
               i++;
            }

            //Libération du jeu de résultat
            mysql_free_result(result);

            //Fermeture de MySQL
            mysql_close(&mysql);

        }
        else  //Sinon ...
        {
            printf("Une erreur s'est produite lors de la connexion à la BDD!");
        }


    return 0;
}


Et voici ce que ce code me donne:

Code : Console
Resultat 1 
Resultat 2 
Resultat 3 
Resultat 4 
Resultat 5 
Resultat 6 

Press any key to continue.


Voilà je ne crois pas avoir besoin d'expliquer ce code car tout à été expliqué juste avant: le jeu de résultat est mis dans result, puis on fait une boucle pour lister toutes les lignes.
Mais ça ne me dit pas la valeur de la ligne vous allez me dire, eh bien pour faire ça il nous faut encore 2 fonctions! Eh oui il y en a beaucoup pour une si petite chose. ;)

La première fonction est: mysql_num_fields(MYSQL_RES *result); . Cette fonction retourne un entier non signé qui correspond au nombre de champs de la table sélectionnée. Donc pour pouvoir avoir les valeurs de notre requête il va falloir stocker dans une variable le nombre de champs puis faire une boucle pour avoir chaque valeur une par une.

La 2e fonction est: mysql_fetch_lengths(MYSQL_RES *result); . Celle-ci retourne un pointeur de long non signé qui correspond à la taille de la valeur courante.

Voici un exemple de requête complet:
Code : C
 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
62
63
64
65
66
67
68
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <MYSQL/mysql.h>



int main()
{
    //Déclaration du pointeur de structure de type MYSQL
    MYSQL mysql;
        //Initialisation de MySQL
        mysql_init(&mysql);
        //Options de connexion
        mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"option");

        //Si la connexion réussie...
        if(mysql_real_connect(&mysql,"www.goldzoneweb.info","mon_pseudo","*****","ma_base",0,NULL,0))
        {
            //Requête qui sélectionne tout dans ma table scores
            mysql_query(&mysql, "SELECT * FROM scores");

            //Déclaration des pointeurs de structure
            MYSQL_RES *result = NULL;
            MYSQL_ROW *row = NULL;

            unsigned int i = 0;
            unsigned int num_champs = 0;

            //On met le jeu de résultat dans le pointeur result
            result = mysql_use_result(&mysql);

            //On récupère le nombre de champs
            num_champs = mysql_num_fields(result);

            //Tant qu'il y a encore un résultat ...
            while ((row = mysql_fetch_row(result)))
            {
                //On déclare un pointeur long non signé pour y stocker la taille des valeurs
                unsigned long *lengths;

                //On stocke cette taille dans le pointeur
                lengths = mysql_fetch_lengths(result);

                //On fait une boucle pour avoir la valeur de chaque champs
               for(i = 0; i < num_champs; i++)
               {
                   //On ecrit toutes les valeurs
                   printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
               }
               printf("\n");
            }

            //Libération du jeu de résultat
            mysql_free_result(result);

            //Fermeture de MySQL
            mysql_close(&mysql);

        }
        else  //Sinon ...
        {
            printf("Une erreur s'est produite lors de la connexion à la BDD!");
        }


    return 0;
}


Et voici ce que ce code me retourne:

Code : Console
[1] [The BasheR] [130000] 
[2] [Rom] [10005120] 
[3] [Tib] [51203] 
[4] [Joe] [78491] 
[5] [Fab] [12054] 
[6] [Nic] [1102350]


La seule chose qui devrait vous poser problème dans le code c'est cette ligne:

Code : C
1
printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");


D'abord, la chaîne de conversion de printf() . La chaîne de conversion %.*s est assez austère, il faut l'avouer. Cependant, en prenant les éléments un par un, on arrive à la comprendre sans problème.

Je passerai sur le '%', je crois que ce n'est pas la peine de s'éterniser dessus. :-°

Ensuite vient le point. Il sert à séparer un nombre éventuel indiquant la largeur du champ et la précision désirées. Par exemple, avec %10.20s, on aura une largeur de champ de 10 et on écrira au maximum 20 caractères (spécificateur %s).

Puis, le plus déroutant parce qu'il est rare, l'étoile. Elle désigne en fait la valeur du second argument passé à printf(), qui doit être un int (d'où le cast ). Ainsi, l'appel à printf() suivant (tiré du K&R) :

Code : C
1
printf("%.*s, max, s);


... signifiera : "imprimer sur stdout au plus max caractères de la chaîne s".

Je vous épargne l'adaptation à notre propre cas, si vous m'avez suivis jusque là il ne devrait pas y avoir de problème.

Ensuite, la condition ternaire. Elle est un peu ambigüe. Personnellement, je la trouve un peu douteuse. A prendre avec des pincettes.

Voici son équivalent sous forme classique :

Code : C
1
2
3
4
if (row[i])
    printf("%.*s", (int) lengths[i], row[i]);
else
    printf("NULL");


Or, selon la doc, mysql_fetch_row() est censée renvoyer NULL en cas d'erreur ou de fin de jeu. C'est ici que se pose le problème. En effet, NULL est généralement implémenté ainsi :

Code : C
1
#define NULL (void *) 0


Auquel cas la condition est parfaitement valable.

En revanche, rien ne garantit (du moins il me semble) que sur certains systèmes, NULL ne soit pas égal à une autre valeur que 0. Cela provoquerait un bug important.

Merci à mleg pour l'explication de ce point.


Voilà nous avons fini avec la fonction mysql_use_result , nous allons donc maintenant passer à l'autre fonction.


mysql_store_result(MYSQL *mysql)



Le principe est le même avec cette fonction, à la différence que celle-ci stocke le jeu de résultat dans une mémoire tampon ce qui rend possible les opérations sur le jeux de résultat mais ça rend la fonction plus lente que l'autre.

Donc pour faire une requête comme celle de l'exemple précédent il suffit juste de changer mysql_use_result par mysql_store_result , vous obtiendrez le même résultat mais se sera plus lent:

Code : C
 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
62
63
64
65
66
67
68
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <MYSQL/mysql.h>



int main()
{
    //Déclaration du pointeur de structure de type MYSQL
    MYSQL mysql;
        //Initialisation de MySQL
        mysql_init(&mysql);
        //Options de connexion
        mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"option");

        //Si la connexion réussie...
        if(mysql_real_connect(&mysql,"www.goldzoneweb.info","mon_pseudo","*****","ma_base",0,NULL,0))
        {
            //Requête qui sélectionne tout dans ma table scores
            mysql_query(&mysql, "SELECT * FROM scores");

            //Déclaration des pointeurs de structure
            MYSQL_RES *result = NULL;
            MYSQL_ROW *row = NULL;

            unsigned int i = 0;
            unsigned int num_champs = 0;

            //On met le jeu de résultat dans le pointeur result (maintenant on utilise mysql_store_result
            result = mysql_store_result(&mysql);

            //On récupère le nombre de champs
            num_champs = mysql_num_fields(result);

            //Tant qu'il y a encore un résultat ...
            while ((row = mysql_fetch_row(result)))
            {
                //On déclare un pointeur long non signé pour y stocker la taille des valeurs
                unsigned long *lengths;

                //On stocke cette taille dans le pointeur
                lengths = mysql_fetch_lengths(result);

                //On fait une boucle pour avoir la valeur de chaque champs
               for(i = 0; i < num_champs; i++)
               {
                   //On ecrit toutes les valeurs
                   printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
               }
               printf("\n");
            }

            //Libération du jeu de résultat
            mysql_free_result(result);

            //Fermeture de MySQL
            mysql_close(&mysql);

        }
        else  //Sinon ...
        {
            printf("Une erreur s'est produite lors de la connexion à la BDD!");
        }


    return 0;
}


Mais alors pourquoi utiliser cette fonction si elle fait la même chose en plus de temps ?! o_O


Eh bien c'est vrai qu'à première vue ça ne sert pas à grand chose, mais en fait l'intérêt de cette fonction est qu'on peut "voyager" dans le jeu de résultat, c'est à dire qu'on peut demander à avoir seulement le résultat n°2, ou n°3, ...
Pour ça il existe une fonction que voici: mysql_data_seek(MYSQL_RES *result, my_ulonglong offset); . Cette fonction prend en argument le jeu de résultat ainsi que le numéro de la ligne qu'on veut voir.
Voici un exemple de son utilisation:

Code : C
 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
//Requête qui sélectionne tout dans ma table scores
            mysql_query(&mysql, "SELECT * FROM livreor");

            //Déclaration des pointeurs de structure
            MYSQL_RES *result = NULL;
            MYSQL_ROW *row = NULL;

            unsigned int i = 0;
            unsigned int num_champs = 0;

            //On met le jeu de résultat dans le pointeur result
            result = mysql_store_result(&mysql);
            
            //On choisie une ligne
            mysql_data_seek(result, 4);

            //On récupère le nombre de champs
            num_champs = mysql_num_fields(result);

            //on stock les valeurs de la ligne choisie
            row = mysql_fetch_row(result);

                //On déclare un pointeur long non signé pour y stocker la taille des valeurs
                unsigned long *lengths;

                //On stocke cette taille dans le pointeur
                lengths = mysql_fetch_lengths(result);

                //On fait une boucle pour avoir la valeur de chaque champs
               for(i = 0; i < num_champs; i++)
               {
                   //On ecrit toutes les valeurs
                   printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
               }


Ce code me donne:
Code : Console
[4] [Joe] [78491]


Voilà ce code ne me semble pas compliqué, on définit juste la ligne voulue puis on fait comme avant mais sans la boucle while, ce qui est normal puisque on a plus qu'un résultat à afficher. :lol:

Voilà nous avons terminé avec la théorie, nous allons maintenant passer à la pratique dans un petit TP, que de réjouissances en perspective. :ange:


La pratique

Nous y voilà enfin ! Après toute cette attente nous allons enfin pouvoir pratiquer :D .
Ce petit TP ne sera pas bien compliqué et utilisera ce que vous venez d'apprendre.

Concept



Le concept de ce jeu est assez simple, nous allons reprendre le jeu du plus ou moins en console et y apporter quelques modifications.

Tout d'abord il va nous falloir une table pour stocker les scores, voici le code SQL de la table:
Code : SQL
1
2
3
4
5
6
CREATE TABLE `scores` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `pseudo` varchar(20) NOT NULL,
  `score` int(11) NOT NULL,
  KEY `id` (`id`)
);


Ensuite au début il devra y avoir un menu demandant si on veut jouer ou voir les scores.

- jouer



Si le joueur choisi de jouer, alors on entre dans le jeu du plus ou moins, donc un nombre est généré aléatoirement et on doit essayer de le trouver, une fois ce nombre trouvé on indique au joueur le nombre de coups qu'il a fait, puis on demande son pseudo. Une fois ces opérations terminées on enregistre le tout dans la table scores.

- scores



Pour les scores c'est un peu plus compliqué. Eh oui je n'allais pas me contenter de vous demander simplement de tout m'afficher :p . Je vais vous demander d'afficher tous les scores de la manière suivante:
Code : Autre
1
2
3
4
5
6
7
1- pseudo1 score1 pts

2- pseudo2 scores2 pts

...

...

Et il faudra afficher ces scores par ordre de score croissant.


Voilà je crois en avoir dit assez, vous êtes largmement capable de faire ça en quelques minutes (moi ça m'a pris 10 min :D ).

Correction



Ca y est vous avez trouvé?
Ce n'était pas compliqué, alors voilà la solution, si vous n'aviez pas trouvé c'est que vous n'avez pas compris mon cours (dans ce cas c'est ma faute ^^ ), ou que vous n'avez pas bien compris le cours de M@teo (dans ce cas c'est sa faute :p ).

Vous êtes prêt?
Alors c'est partit voilà la solution:
Secret (cliquez pour afficher)
Code : C
  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
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <winsock.h>
#include <MYSQL/mysql.h>



int main()
{


    long nombreMystere = 0, nombreEntre = 0, choix = 0;
    const long MAX = 100, MIN = 1;
    char pseudo[20] = "";

    // Génération du nombre aléatoire

    srand(time(NULL));

    //Choix de voir les scores ou de jouer
    printf("Bienvenue dans mon jeu de plus ou moins!\n\n");

    printf("1- Jouer\n");
    printf("2- Scores\n\n");

    scanf("%ld", &choix);


    switch (choix)
    {
        //Si on veut jouer
        case 1:
            //On génére le nombre aléatoire
            nombreMystere = (rand() % (MAX - MIN + 1)) + MIN;

            int i = 1;

            do
            {
                // On demande le nombre
                printf("Quel est le nombre ? ");
                scanf("%ld", &nombreEntre);

                // On compare le nombre entré avec le nombre mystère

                if (nombreMystere > nombreEntre)
                    printf("C'est plus !\n\n");
                else if (nombreMystere < nombreEntre)
                    printf("C'est moins !\n\n");
                else
                    printf ("Bravo, vous avez trouve le nombre mystere !!!\n\n");

                i++;
            } while (nombreEntre != nombreMystere);

            printf("Votre score est de: %ld\n\n", i);
            printf("Veuillez entrer votre pseudo\n");
            scanf("%s", pseudo);

            //Déclaration du pointeur de structure de type MYSQL
            MYSQL mysql;
            //Initialisation de MySQL
            mysql_init(&mysql);
            //Options de connexion
            mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"option");

            //Si la connexion réussie...
            if(mysql_real_connect(&mysql,"www.votrehebergeur.com","mon_pseudo","*****","ma_base",0,NULL,0))
            {
                //On déclare un tableau de char pour y stocker la requete
                char requete[150] = "";

                //On stock la requete dans notre tableau de char
                sprintf(requete, "INSERT INTO scores VALUES('', '%s', '%ld')", pseudo, i);


                //On execute la requete
                mysql_query(&mysql, requete);


                //Fermeture de MySQL
                mysql_close(&mysql);
            }
            else
            {
                printf("Une erreur s'est produite lors de la connexion a la BDD!\n");
            }


            break;

        //On veut voir les scores
        case 2:
            printf("Liste des scores du jeu: \n\n");

            //Déclaration du pointeur de structure de type MYSQL
            MYSQL mysql2;
                //Initialisation de MySQL
                mysql_init(&mysql2);
                //Options de connexion
                mysql_options(&mysql2,MYSQL_READ_DEFAULT_GROUP,"option2");

                //Si la connexion réussie...
                if(mysql_real_connect(&mysql2,"www.votrehebergeur.com","mon_pseudo","*****","ma_base",0,NULL,0))
                {
                    //Requête qui sélectionne tout dans ma table scores
                    mysql_query(&mysql2, "SELECT * FROM scores ORDER BY score");

                    //Déclaration des pointeurs de structure
                    MYSQL_RES *result = NULL;
                    MYSQL_ROW *row = NULL;

                    unsigned int i = 0;
                    unsigned int num_champs = 0;
                    int j =1;

                    //On met le jeu de résultat dans le pointeur result
                    result = mysql_use_result(&mysql2);

                    //On récupère le nombre de champs
                    num_champs = mysql_num_fields(result);

                    //on stock les valeurs de la ligne choisie
                    while (row = mysql_fetch_row(result))
                    {

                        //On déclare un pointeur long non signé pour y stocker la taille des valeurs
                        unsigned long *lengths;

                        //On stocke cette taille dans le pointeur
                        lengths = mysql_fetch_lengths(result);

                        //On affiche la position du joueur
                        printf("%ld- ", j);

                        //On fait une boucle pour avoir la valeur de chaque champs
                       for(i = 1; i < num_champs; i++)
                       {

                           //On ecrit toutes les valeurs
                           printf("%.*s ", (int) lengths[i], row[i] ? row[i] : "NULL");
                       }
                       printf("pts\n");

                       //On incrémente la position du joueur
                       j++;

                    }

                    //Libération du jeu de résultat
                    mysql_free_result(result);


                    //Fermeture de MySQL
                    mysql_close(&mysql2);

                }
                else  //Sinon ...
                {
                    printf("Une erreur s'est produite lors de la connexion a la BDD!");
                }

            break;

        //Sinon
        default:
            printf("Le choix que vous avez entre n'est pas valide!");
            break;


    }




    return 0;
}


Voilà ce n'était pas très compliqué, je ne crois même pas avoir besoin d'expliquer ce code, les commentaires sont assez parlant.

Q.C.M.

Quel est le bon ordre?
Quelle structure permet de stocker le résultat d'une ligne?
Quelles sont les différences entre mysql_use_result et mysql_store_result?
A quoi sert mysql_data_seek?

Statistiques de réponses au QCM


Voilà ce cours sur l'API MySQL est maintenant fini, j'espère qu'il a été assez clair et que vous avez bien tout compris.

Voici quelques idées d'amélioration du mini-jeu que l'on vient de faire. Je ne vais pas dire les améliorations du jeu en lui-même car M@teo le fait dans son TP mais je vais vous dire les améliorations que l'on peut faire au niveau de MySQL:

  • Limiter le nombre de scores à afficher à 10 pour éviter que ça prenne trop de place
  • Prévenir le joueur que l'enregistrement de son score s'est bien déroulé

C'est à peu près toutes les améliorations que j'ai en tête, il n'y en a pas tellement ^^ , mais après vous pouvez laisser libre cours à votre imagination ;) .

Nous pouvons donc nous quitter maintenant (j'en vois qui se réjouissent dans le fond :p ).
Si vous voulez en apprendre encore plus sur cette librairie je conseille cette page, c'est la liste de toutes les fonctions de l'API MySQL avec leur description en français !! :soleil:

Sur ce, au revoir tout le monde et à bientôt pour de nouvelles aventures ^^ .

Informations sur le tutoriel

Retour en haut Retour en haut

Créé : Le 03/09/2006 à 15:03:24
Modifié : Le 15/05/2009 à 12:35:35
Avancement : 100%
Licence : Copie non autorisée

41 commentaires