Bibliothèque de code

Vous trouverez ici quelques exemples de code source (ce ne sont pas des tutoriels donc peu d'explications)

C

Exemples de code C pouvant être réutilisé librement tant que l'auteur est cité :)

Allouer dynamiquement un tableau à deux dimensions avec uniquement deux malloc

Ce qu'il ne faut pas faire

Beaucoup de gens font un truc du genre :

int **createTable(int nbLin, int nbCol){
int **tab;
 
/* Allocation de la 1er dimension */
    tab = (int **)malloc ( sizeof(int *)  *  nbLin);
/* Allocation 2e dimension */
    for (int i = 0 ; i < nbLin ; i++){
        tab[i] = (int *)malloc (sizeof(int) * nbCol);
    }

Ce qui demande nbLin+1 malloc (c'est moche). Il faut savoir que l'allocation mémoire est considérée comme une action lente.

Ce qu'il faudrait faire

Une autre méthode consiste à allouer la première dimension comme dans l'exemple précédent, et a allouer d'un seul bloc, tout le reste.

#include <stdlib.h>
#include <stdio.h>
 
int **createTable(int nbLin, int nbCol){
	int **tableau = (int **)malloc(sizeof(int*)*nbLin);
	int *tableau2 = (int *)malloc(sizeof(int)*nbCol*nbLin);
	for(int i = 0 ; i < nbLin ; i++){
		tableau[i] = &tableau2[i*nbCol];
	}
	return tableau;
}
 
void freeTable(int **tableau){
	free(tableau[0]);
	free(tableau);
}

Pourquoi ?

Voici un tableau du type int tab[5][6]

Un tableau a deux dimensions ça marche comment ? (à pied)
Cela équivaut à créer une premiere dimension (en rouge à gauche), et chaque case de cette première dimension va pointer vers un tableau (vers la première case du tableau) de dimension inférieure. Il est donc possible de faire des tableaux de dimension n > 3.

Merci à ar0x qui m'a fait découvrir cette possibilité :)

Fichier attachéTaille
Image icon tab2dim.png7.95 Ko

Allouer dynamiquement un tableau à deux dimensions avec uniquement un malloc

En faite je reprend le même principe que pour deux malloc, mais en allouant le tout en une seule fois !!!
Puis ensuite, il s'agit de jouer avec les pointeurs !!!

En terme de complexité c'est toujours la même o(lignes), sans compter le temps d'allocation de la mémoire !!!
Et puis pour la libération des ressources, il y a juste un seul free à faire ^^

#include "stdlib.h"
 
int** allocation(int lignes, int colones)
{
    int** tableau;
    int* data;
    int i;
 
    if(lignes <= 0 || colones <= 0)
    {
        return NULL;
    }
 
    tableau = (int**) malloc(lignes*colones*sizeof(int) + lignes*sizeof(int*));
    if(tableau == NULL)
    {
        return NULL;
    }
 
    for(i=0,data=(int*)(tableau+lignes); i<lignes; i++,data+=colones)
    {
        tableau[i] = data;
    }
 
    return tableau;
}
 
void desallocation(int** memoire)
{
    free(memoire);
}
Fichier attachéTaille
Plain text icon malloc.c.txt965 octets

Allouer dynamiquement un tableau à n dimensions avec uniquement un malloc

Voici le code de la fonction array_alloc qui perment d'allouer un tableau de dimention n.
Le premier argument qu'elle prend c'est le nombre de dimention du tableau.
Le deuxième c'est un tableau contenant la taille de chaque dimention.
Le dernier argument désigne la taille du type avec lequel on rempliera la tableau.

#define PTR_SIZE sizeof (void*)
 
void* array_alloc(int n, int tab[], size_t elemSize) {
	int i, j;
	int pro;
	int sum;
	size_t dataSize;
	size_t blocSize = 0;
	void* ptrAlloc;
 
	void *ptrBase, *ptrP;
 
	if (tab == NULL || n == 0 || elemSize == 0) {
		return NULL;
	}
	if (n == 1) {
		return malloc(tab[0] * elemSize);
	}
	sum = 0;
	pro = 1;
	for (i = 0; i < n - 1; i++) {
		pro *= tab[i];
		sum += pro;
	}
 
	blocSize = sum * PTR_SIZE + pro * elemSize * tab[i];
 
	if ((ptrAlloc = malloc(blocSize)) == NULL) {
		return NULL;
	}
	ptrBase = ptrP = ptrAlloc;
	for (i = 0, pro = 1; i < n - 1; i++) {
		pro *= tab[i];
		ptrBase += pro * PTR_SIZE;
		dataSize = (i == n - 2) ? elemSize : PTR_SIZE;
		for (j = 0; ptrP < ptrBase; ptrP += PTR_SIZE, j++){
			*((void**) ptrP) = ptrBase + tab[i + 1] * j * dataSize;
		}
	}
	return ptrAlloc;
}

Allouer statiquement un tableau de taille variable

En fait il est tout a fait possible d'allouer statiquement un tableau dont la taille n'est connue qu'a l'exécution. Pour cela, il faut faire du c99 !!! -std=c99

Et on peut tout simplement écrire :

int taille = 5;
int tableau[taille];

Et pour les tableau à plusieurs dimensions, on peut faire:

void utilisatonTableau(int x, int y) {
    int tableau[x][y];
}

Ceci évite les problèmes d'allocation, mais ne permet pas de l'utiliser en dehors du domaine de validité de la variable le déclarant.

Calcul rapide de puissance de 2

Ce qu'il ne faut pas faire

Encore une fois, il y a la méthode > (private joke inside) qui consiste à faire une boucle du genre :

int puissance2(int puissance){
	unsigned int resultat = 1;
	for (int i = 0 ; i<puissance ; i++){
		resultat *= 2;
	}
	return resultat;
}

Temps d'execution: o(puissance)

C'est moche... Pourquoi c'est moche ? Parce que le programme effectue pour calculer 2^n, n multiplication. Temps moyen par multiplication : 5 à 6 cycles d'horloges, soit n*6 ça peut faire beaucoup).

Ce qu'il faudrait faire

Petit rappel sur la numération binaire :
binaire => décimal
0 =>0
1 =>1
10 => 2
11 => 3
100 => 4
1000 => 8
10000 => 16

Il suffit donc pour calculer une puissance de 2 de faire des décalage a gauche comme suit :

unsigned int puissance2(int puissance){
	return 1 << puissance;
}

Temps d'exécution : o(1)

Domaine: 

Chargement d'interface gtk avec la libglade (obsolète)

(obsolète) : il faut maintenant utiliser gtkBuilder qui est directement inclue dans gtk

Le code

Petit bout de code illustrant comment charger une interface gtk depuis un fichier .glade

#include <gtk/gtk.h>
#include <glade/glade.h>
 
int main (int argc, char *argv[]){
  GladeXML  *main_window;
  GtkWidget *bouton;
 
  gtk_init (&argc, &argv);
 
  /* charge l'interface depuis le fichier test.glade */
  main_window = glade_xml_new ("test.glade", NULL, NULL);
 
 /* charge le widget nommé bouton depuis l'interface principale */
    bouton = glade_xml_get_widget (main_window, "bouton");
 
    g_signal_connect (G_OBJECT (boutton), "clicked", G_CALLBACK (click01), NULL);
    g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL);
 
  /* lance l'interface */
  gtk_main ();
 
  return 0;
}

Compile ?

Comme souvent pour les librairies utilisées, il faut des options de partout. Et quand il existe plusieurs versions de la librairie c'est encore plus long. Un petit utilitaire permet de faire tout ça tout bien j'ai nommé "pkg-config".

Il se contente d'aller chercher les informations dans le fichier .pc qui va bien (encore faut il qu'il y en ait un, ce qui est le cas pour gtk et libglade).

Pour compiller :

gcc -Wall `pkg-config  --cflags gtk+-2.0 libglade-2.0` -c fichier.c 

Pour linker

gcc -Wall `pkg-config  --cflags --libs gtk+-2.0 libglade-2.0`  fichier.o -o prog 

Clés RSA, chiffrement et déchiffrement avec openssl

Petit code pour chiffrer et déchiffrer des fichiers en RSA avec openssl

Le code génère une paire de clef 4096 bits (qui sont écrites en pem dans le répertoire courant), chiffre un fichier, et le déchiffre (histoire de montrer que ça fonctionne pour de vrai)

gcc -lcrypto -std=gnu99

#include <openssl/rsa.h>
#include <glib.h>
#include <openssl/pem.h>
 
 
gboolean encRSA (RSA *rsa, FILE *fpClr, FILE *fpEnc) {
 
  unsigned char *buffRead, *buffWrite;
  int size;
  gboolean ret = FALSE;
 
  buffRead    = g_malloc(sizeof(unsigned char)*RSA_size(rsa));
  buffWrite   = g_malloc(sizeof(unsigned char)*RSA_size(rsa));
 
 
  while ((size = fread(buffRead, 1, RSA_size(rsa)-11, fpClr)) > 0) {
    size = RSA_private_encrypt (size, buffRead, buffWrite, rsa, RSA_PKCS1_PADDING);
    fwrite (buffWrite, 1, size, fpEnc);
  }
 
 
  ret = TRUE;
 
  return ret;
}
 
gboolean decRSA (RSA *rsa, FILE *fpEnc, FILE *fpClr) {
 
  unsigned char *buffRead, *buffWrite;
  int size;
  gboolean ret = FALSE;
 
  buffRead    = g_malloc(sizeof(unsigned char)*RSA_size(rsa));
  buffWrite   = g_malloc(sizeof(unsigned char)*RSA_size(rsa));
 
 
  while ((size = fread(buffRead, 1, RSA_size(rsa), fpEnc)) > 0) {
    size = RSA_public_decrypt (size, buffRead, buffWrite, rsa, RSA_PKCS1_PADDING);
    fwrite (buffWrite, 1, size, fpClr);
  }
 
 
  ret = TRUE;
 
  return ret;
}
 
int main(int argc, char *argv[]){
  FILE *fpPriv, *fpPub;
  FILE *fpLicenceClr, *fpLicenceEnc, *fpLicenceDbg;
 
  RSA *rsaPub = NULL;
  RSA *rsaPriv = NULL;
 
  if (argc != 6){
    fprintf(stderr, "USAGE : %s filePubKey filePrivKey clearLicence cypheredLience testClrLience\n", argv[0]);
 
    return -1;
  }
 
  if((fpPub = fopen(argv[1], "r")) == NULL){
    fprintf(stderr, "Could not open %s\n", argv[1]);
    return -1;
  }
 
  if((fpPriv = fopen(argv[2], "r")) == NULL){
    fprintf(stderr, "Could not open %s\n", argv[2]);
    return -1;
  }
 
  if((fpLicenceClr = fopen(argv[3], "r")) == NULL){
    fprintf(stderr, "Could not open %s\n", argv[3]);
    return -1;
  }
 
  if((fpLicenceEnc = fopen(argv[4], "w")) == NULL){
    fprintf(stderr, "Could not open %s\n", argv[4]);
    return -1;
  }
 
 
  if((fpLicenceDbg = fopen(argv[5], "w")) == NULL){
    fprintf(stderr, "Could not open %s\n", argv[5]);
    return -1;
  }
 
  PEM_read_RSAPrivateKey (fpPriv, &rsaPriv, 0, NULL);
  PEM_read_RSAPublicKey  (fpPub, &rsaPub, 0, NULL);
 
  printf(">>%p %p\n", rsaPub, rsaPriv);
 
  encRSA (rsaPriv, fpLicenceClr, fpLicenceEnc);  
 
  fclose(fpLicenceEnc);
  if((fpLicenceEnc = fopen(argv[4], "r")) == NULL){
    fprintf(stderr, "Could not open %s\n", argv[4]);
    return -1;
  }
 
  decRSA (rsaPub, fpLicenceEnc, fpLicenceDbg);  
 
 
  fclose(fpPub);
  fclose(fpPriv);
  fclose(fpLicenceClr);
  fclose(fpLicenceEnc);
  fclose(fpLicenceDbg);
 
 
 
  return 0;
}
Domaine: 

Comment protéger ses ".h" de l'inclusion multiple

Faire du travail propre

Quand les projets grossissent un peu, une inclusion multiple est très vite arrivée.
schema inclusion multiple
Le fichier "plop.h" est inclut plusieurs fois dans "test.c" ce qui pose des problème de redéfinition de symboles.

Comme c'est le préprocesseur qui plante, c'est aussi avec lui que nous allons résoudre le problème. Nous allons faire un test sur une constante, si celle ci n'est pas définie nous pouvons inclure le code et définir la constante en question. Il suffit de mettre le corps du fichier ".h" dans

#ifndef __FICHIER_H__ /* si la constante __FICHIER_H__ n'est pas defini entrer dans l'espace */
#define __FICHIER_H__ /* definit la constante __FICHIER_H__ */
 
/* corps du fichier .h */
 
#endif /* __FICHIER_H__ */

Se la couler douce sous Visual Studio (c)

Attention ce qui suit est uniquement valable pour Visual Studio (c). Car ces instructions préprocesseur sont spécifiques aux compilateurs Microsofts (c)

Il suffit de mettre a la première ligne du fichier ".h" le code suivant

#pragma once
 
/* corps du fichier .h */

C'est plus court, mais c'est pas portable!!!

Convertir string en nombre

Convertir une chaîne de caractères en int (nombre)

Fichiers entête à inclure :

#include <stdlib.h>
#include <errno.h>
 int string2int (char *eugeni){
   errno  = 0;
   int t = strtol (eugeni, NULL, 10);
   if (errno == ERANGE || errno != 0) {
     perror ("strtol");
     exit (EXIT_FAILURE);
   }
   return t;
 }
 

Convertir chaine de caractères en double

 double string2double(char *eugeni){
   errno  = 0;
   double t = strtod(eugeni, NULL);
   if (errno == ERANGE || errno != 0) {
     perror("strtod");
     Err(__FILE__, __LINE__, Le nombre nen nest pas un);
     exit(EXIT_FAILURE);
   }
   return t;
 }
 

Convertir chaine de caractères en longlongint

 long long int string2longlongint(char *eugeni){
   errno  = 0;
   long long int t = strtoll(eugeni, NULL,10);
   if (errno == ERANGE || errno != 0) {
     perror("strtoll");
     Err(__FILE__, __LINE__, Le nombre nen nest pas un);
     exit(EXIT_FAILURE);
   }
   return t;
 }

Crypter un fichier avec une clée symétrique

Voilà le but est simple on utilise un XOR pour crypter un fichier bit par bit. La méthode décrite est très simple à casser, en effet la clée du XOR étant sur 1 octect pour être sur de pouvoir le fichier quelque soit sa taille il existe seulement 255 combinaisons pour retrouver le texte (bien que le l'octet égal à 11111111b = 255d soit initule car on réalise simplement une inversion de bits).
Petit rappel sur la table de vérité du XOR :

0 0 0
0 1 1
1 0 1
1 1 0

le programme n'utilise que stdio et stdlib, un man permet d'obtenir des informations sur le fonctionnement des fonctions. A savoir l'opérateur XOR s'écrit ^ en C.

A compiler avec :
gcc -W -Wall -o crypt cryptXor.c pas de -ansi parceque sa sert à rien (en plus ca fera bloquer le compilateur).

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void chiffrer(unsigned char, FILE *,FILE *);
  5.  
  6. int main(int argc, char **argv){
  7. FILE *In, *Out;
  8. unsigned char clee;
  9. int toto;
  10.  
  11. // Validation des arguments de la ligne de commande
  12.  
  13. if(argc !=3){
  14. printf("Usage : %s <source> <destination>\n", *argv);
  15. return 0;
  16. }
  17.  
  18. // Ouverture du fichier en lecture binaire
  19.  
  20. if( (In = fopen(argv[1], "rb+")) == NULL ){ // affectation de In
  21. printf("%s introuvable\n",argv[1]);
  22. return -1;
  23. }
  24.  
  25. // Ouverture en écriture binaire du fichier de destination
  26.  
  27. if( (Out = fopen(argv[2], "rb+")) == NULL ){ // affectation de Out
  28. printf("%s impossible à créer\n",argv[2]);
  29. fclose(In);
  30. return -1;
  31. }
  32.  
  33. // Saisie de la clée (sur 1 octet)
  34. printf("\nEntrez une clée de chiffrement sur 1 octet\n");
  35. scanf("%d",&toto);
  36. if(0 > toto || toto > 255){
  37. printf("Clée incorecte. Attention la clée ne doit pas dépasser 255!\n");
  38. fclose(In);
  39. fclose(Out);
  40. return -1;
  41. }
  42. clee = (unsigned char)toto;
  43. // Chiffrement du fichier
  44.  
  45. chiffrer(clee, In, Out);
  46. fclose(In);
  47. fclose(Out);
  48. printf("Terminé\n");
  49.  
  50. return 0;
  51. }//void main(int, char **)
  52.  
  53. void chiffrer(unsigned char k, FILE *entre, FILE *sort){
  54. unsigned char octet;
  55.  
  56. while( fread(&octet,1,1,entre) ){
  57. octet ^= k;
  58. fwrite(&octet,1,1,sort);
  59. }
  60.  
  61. }// fin chiffrer(unsigned char, FILE *, FILE *)

Effectuer des requêtes sur un serveur mysql

#include "mysql.h"
 
MYSQL *mysqlOpenDB(char *server, char *db, char *user, char *pwd){
	MYSQL *myH;
 
	if(NULL == (myH = mysql_init(NULL))){
		fprintf(stderr, "erreur lors de l'ouverture : %s\n", mysql_error(myH));
	}
 
	if(mysql_real_connect(myH, server, user, pwd, db, 0, NULL, 0) == NULL){
		fprintf(stderr, "erreur lors de la connexion : %s\n", mysql_error(myH));
	}
 
	return myH;
 
}
 
void mysqlExecReq (MYSQL *myH, char *req){
	if(mysql_query(myH, req) != 0){
		fprintf(stderr, "Echec de la requete : %s\n", mysql_error(myH));
		mysql_close(myH);
	}
 
}
 
void mysqlCloseDB(MYSQL *db){
	mysql_close(db);
}

Ligne de compilation

gcc -Wall -lmysqlclient plop.c -o prog

Gestion des signaux

Ce code permet de gérer les signaux de manière simple. Entre autre il permet d'intercepter les Ctrl+C, Segfault, ou autre. Il intercepte tous les signaux sauf le -SIGKILL (-9) qui ne peux etre intercepté.

Le programme

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
 
void signalement(int sig){
    printf("Signal : %d\n" , sig);
}
 
int main(){
    int Nb_Sig;
    printf("Nb max signaux : %d\n", SIGRTMAX); 
    for (Nb_Sig = 1; Nb_Sig < SIGRTMAX ; Nb_Sig ++){
        signal(Nb_Sig,signalement);
    }
    while(1) {
        sleep(1);
    }
}

Pour tester le programme

trax@clubnix $ gcc -Wall signal.c -o prog
trax@clubnix $ ./prog

Puis faire un Ctrl+C ou taper la commande

kill -X pid_de_prog
  • X : le numéro du signal à tester (tout sauf 1 et 9)
  • pid_de_prog : obtenu en tapant la commande
    pgrep -lu votre_login |grep prog 

IMPORTANT :
pour fermer le programme, faire un kill -9 PID_Programme.
Pour trouver le PID "pgrep -lu votre_login", ceci affichera la liste de vos programme.

Macro de debugage et constante preprocesseur

Bien sur il y a gdb mais utiliser la sortie standard peut être utile

Mettre un commentaire différent c'est sympa mais ça peut être lourd à mettre en place

Il existe des constantes préprocesseurs qui peuvent être bien utile :

#define BUG printf("Dans le fichier %s dans la fonction %s à la ligne %d\n",__FILE__, __FUNCTION__, __LINE__)
#define DATE printf("Compile le %s %s\n", __DATE__, __TIME__)
 
#include <stdio.h>
 
 
void plop(){
        BUG;
        printf("%s %s %d\n", __FILE__ ,__FUNCTION__, __LINE__);
}
 
int main(){
        DATE;
 
        plop();
        return 0;
}

Manipuler des tableaux

Voici un tout petit code source qui permet de manipuler des tableaux en C.
Le code est simplissime, cela permet d'avoir une mini bibliothèque/aide mémoire pas loin.
Un bon exercice consisterait à reprendre ce code et y ajouter des nouveaux tris...

tableaux.h :

  1. #ifndef TABLEAUX_H
  2. #define TABLEAUX_H
  3. #define TAILLE 10
  4. void afficheTab(long[], int);
  5. long sommeTab(long[] , int);
  6. double moyenneTab(long[], int);
  7. void copieTab(long[], long[], int);
  8. void clearMaxTab(long[], int taille, long valMax);
  9. void ordonnerTab(long[], int);
  10. void swap(long *, long *);
  11. #endif

tableaux.c

  1. #include <stdio.h>
  2. #include "tableaux.h"
  3.  
  4. int main(){
  5. long tab[TAILLE];
  6. long x = 0.0;
  7. int i;
  8. for(i=0; i<10 ; i++) tab[i]=x++;
  9.  
  10. printf("somme = %ld\r\n",sommeTab(tab, TAILLE));
  11. printf("moyenne = %lf\r\n",moyenneTab(tab,TAILLE));
  12.  
  13. long newtab[TAILLE];
  14. copieTab(tab, newtab, TAILLE);
  15. /*afficheTab(newtab, TAILLE);*/
  16.  
  17. clearMaxTab(tab, TAILLE, 2);
  18. /*afficheTab(tab, TAILLE);*/
  19.  
  20. long newtab2[TAILLE];
  21. for(i=0; i<TAILLE; i++){
  22. printf("\nveuillez entrer un nombre entier :");
  23. scanf("%ld",newtab2+i);
  24. }
  25. ordonnerTab(newtab2, TAILLE);
  26. afficheTab(newtab2, TAILLE);
  27.  
  28.  
  29. return 0;
  30. }
  31.  
  32. /*
  33. * Affiche le contenu d'un tableau sous forme décimale
  34. */
  35. void afficheTab(long tab[], int taille){
  36. int i;
  37. for(i=0; i<taille; i++) printf("tab[geshifilter-questionmarkphp]d] = %ld\r\n&quot;,i,tab[i]);&#10;}&#10;&#10;/*&#10;* Fait la somme de tous les éléments d&#039;un tableau&#10;*/&#10;long sommeTab(long tab[], int taille){&#10; long somme=0;&#10; int i=0;&#10; for(i=0 ; i&lt;taille ; i++) somme+= tab[i];&#10; return somme;&#10;}&#10;&#10;/*&#10;* Fait la moyenne algébrique de tous les éléments d&#039;un tableau&#10;*/&#10;double moyenneTab(long tab[], int taille){&#10; double somme = (double)sommeTab(tab, taille);&#10; return somme/(double)taille;&#10;}&#10;&#10;/*&#10;* Copie le contenu de tab1 dans tab2&#10;* tab2 et tab1 doivent être de taille inférieure à taille1 donnée en paramètre &#10;*/&#10;void copieTab(long tab1[], long tab2[], int taille1){&#10; int i;&#10; for(i=0; i&lt;taille1; i++) tab2[i]=tab1[i];&#10;}&#10;&#10;/*&#10;* Efface tous les éléments du tableau dont la valeur est &lt;= valMax passée en paramètre&#10;*/&#10;void clearMaxTab(long tab[], int taille, long valMax){&#10; int i;&#10; for(i=0; i&lt;taille; i++)&#10; if(tab[i]&gt;valMax) tab[i]=0;&#10;}&#10;&#10;/*&#10;* Range les éléments d&#039;un tableau par ordre croissant&#10;*/&#10;void ordonnerTab(long tab[], int taille){&#10; int j=0;&#10; int i;&#10; while(j&lt;taille){&#10; for(i=0; i&lt;taille; i++)&#10; if ( tab[i] &lt; tab[i+1] ) swap( (tab+i) , (tab+(i+1)) );&#10; j++;&#10; }&#10; &#10;}&#10;&#10;/*&#10;* Echange deux éleménts&#10;*/&#10;void swap(long *ptr1, long *ptr2){&#10; long temp;&#10; temp = *ptr1;&#10; *ptr1 = *ptr2;&#10; *ptr2 = temp;&#10;&#10;}&#10;&#10;

[/geshifilter-questionmarkphp]

Quick sort ou tris rapide

Une des nombreuses implémentations du quick sort (tris rapide).

#include <stdio.h>
void quick(int *, int p, int r);
void quick(int *tab,int debut, int fin){
	int pivot = debut;
	int g = debut;
	int d = fin;
	int tmp;
	do {
		if (tab[g] >= tab[d]){
			tmp = tab[g];
			tab[g] = tab[d];
			tab[d] = tmp;
			pivot = g + d - pivot;
		}
		if (pivot == g){
			d--;
		}else{
			g++;
		}
	}while(g<d);
	if (debut < (g-1)){
		quick(tab, debut, (g-1));
	}
	if (fin > (d + 1)){
		quick(tab, (d+1), fin);
	}
}

Récupérer les arguments de la ligne de commande avec getopt_long

Voici un extrait du code (actuel) de BIDON qui j'espère pourra illustrer un peu l'utilisation de la fonction getopt_long.
Pour les informations sur les informations sur cette fonction :
* man 3 getopt
* http://www.gnu.org/software/libtool/manual/libc/Getopt.html
* http://www.opengroup.org/onlinepubs/000095399/functions/getopt.html
* Le C en action (aux éditions O'Reilly)

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
 
/* The name of this program */
const char* program_name;
 
/* Print infos about program version and authors */
void print_versionInfo()
{
	printf("you are running version %.3lf\n", VERSION);
	printf("this program was developped by %s\n",AUTHORS);
	printf("you can find some information on bidon's project page at %s\n",WEBSITE);
	exit(EXIT_SUCCESS);
}
 
/* Print help an exit with exit code exit_msg */
void print_help(FILE *stream, int exit_msg)
{
	fprintf(stream,"usage : %s [ options ]\n",program_name);
	printf("valid options are :\n");
	fprintf(stream,
	"  -h  --help\t print this message\n"
	"  -s  --server server_name\t	the name of the server you want to connect to\n"
	"  -P  --port port_number\t this not a needed option, you may used it if you want to connecter on port\
#port_number instead of default 5222\n"
	"  -l  --login gid\t login into server_name with gid as your login. You need your full gid.\
i.e. if you are toto and your account is on jabber.clubnix.esiee.fr you need to do :\n \
%s -s jabber.clubnix.esiee.fr -l toto@jabber.clubnix.esiee.fr\n"
	"  -p --passwd password\t it is your password\n"
	"  -r --recipient recipient\t your messages will be sent to recipient"
	"  -v --version\t print version and exit"
	"  -S --SINGLE\t use this if you want to start a user to user chat.\
	by default the chat_mode is set to MUC to allow to connect to a Multi Users Channel\n"
	,program_name);
	exit(exit_msg);
}
 
int main( int argc, char **argv)
{
	int next_option;
	/* A string listing the valid short options letters */
	const char *short_options = "s:P::l:p:r:hvS";
 
	/* An array listing valid long options */
	static const struct option long_options[]=
	{
		{"server",required_argument,NULL,'s'},
		{"port",optional_argument,NULL,'P'},
		{"login",required_argument,NULL,'l'},
		{"passwd",required_argument,NULL,'p'},
		{"recipient",required_argument,NULL,'r'},
		{"help",no_argument,NULL,'h'},
		{"version",no_argument,NULL,'v'},
		{"Single", no_argument,NULL,'S'},
		{NULL, 0, NULL, 0} /* End of array need by getopt_long do not delete it*/
	};
 
	/* You can connect to a serveur in 2 modes :
	 * SINGLE start a conversation with an other user already connected to the server
	 * MUC Multi Users Channel to connect to a chat room
	 */
	typedef enum chat_mode chat_mode;
	enum chat_mode
	{
		SINGLE,	MUC
	};
 
	char *server_name;
	int port;
	char *login_name;
	char *passwd;
	char *recipient;
 
	/* By default chat_mode is set to MUC since we want
	  to managed a chat room */
	chat_mode mode = MUC;
 
	/* Remember the program name to incorporate it in messages. */
	program_name = argv[0];
 
	do
	{
		next_option = getopt_long(argc, argv, short_options, long_options, NULL );
 
		switch(next_option)
		{
			case 's':
			server_name = optarg;
			printf("you will be connected to %s\n",server_name);
			break;
			case 'P':
			if (NULL != optarg)
			{
				port = atoi(optarg);
				printf("you be connected on %s on port %d\n",server_name,port);
			}
			break;
			case 'l':
			login_name = optarg;
			printf("your will be logged as %s\n",login_name);
			break;
			case 'p':
			passwd = optarg;
			printf("use %s as password\n",passwd);
			break;
			case 'r':
			recipient = optarg;
			printf("your messages will be sent to %s\n",recipient);
			break;
			case 'S':
			mode = SINGLE;
			printf("entering in SINGLE chat mode\n");
			break;
			case 'h':
			print_help(stdout, EXIT_SUCCESS);
			break;
			case 'v':
			print_versionInfo();
			break;
			case '?': /* An invalide option has been used,
			print help an exit with code EXIT_FAILURE */
			print_help(stderr, EXIT_FAILURE);
			break;
		}
	}
	while(next_option !=-1);
 
 
	if (optind < argc)
	{
		printf ("this arguments are not reconized: ");
		while (optind < argc)
		printf ("%s ", argv[optind++]);
		printf ("\n");
	}
 
	exit(EXIT_SUCCESS);
}

Normalement avec ces informations vous devriez être en mesure de coder votre fonction getopt_long. Il ne reste plus qu'à parser les variables utilisées pour stocker les résultats de l'appel de main aux autres fonctions.

A noter : On peut aussi utiliser des librairies autres que celles fournies par le projet GNU, comme la Glib qui a l'avantage d'être disponible sur GNU/Linux *-BSD et MS Windows. Voici un article intéressant :
http://www.unixgarden.com/index.php/programmation/dissection-de-glib-l%E...

Régression Linéaire

Suite à un cours de math je me suis qu'il pourrait être intéressant d'implémenter un algorithme de regression linéaire histoire de mieux s'en rappeler (je suis sur qu'il existe pleins d'autres implémentations bien meilleurs). Celle-ci est volontairement non optimisée pour rester le plus lisible possible

Le code suivant charge un fichier sous la forme : "valX valY" (voir bas de page pour une code exemple). Le résultat peut être vérifié grâce gnuplot qui propose aussi une implémentation de cette algorithme.

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
 
int main(int argc, char *argv[]){
 
  FILE *fData;
  float x1, x2;
 
  double moyenneX = 0, moyenneY = 0;
  double moyenneX2 = 0;
  double moyenneXY = 0;
  double a, b;
  int count = 0;
 
  assert (argc == 2);
 
  if ((fData = fopen (argv[1],"r")) == NULL){
	goto err;
  }
 
 
  while (fscanf (fData, "%e %e", &x1, &x2) == 2){
	moyenneX += x1;
	moyenneY += x2;
	moyenneX2 += x1*x1;
	moyenneXY += x1*x2;
	count++;
  }
  moyenneX /= count;
  moyenneY /= count;
  moyenneX2 /= count;
  moyenneXY /= count;
 
  a = (moyenneXY - moyenneX*moyenneY)/(moyenneX2 - moyenneX*moyenneX);
  b = moyenneY - a*moyenneX;
  printf ("a = %e\n", a);
  printf ("b = %e\n",b);
 
  fclose (fData);
 
 
  goto fin;
 err :
  fprintf (stderr, "Erreur\n");
 fin :
  return 0;
}

Code pour générer un fichier de données exemple :

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
 
int main(int argc, char *argv[]){
  int m;
  FILE *fp;
  assert (argc == 2);
  if ((fp = fopen (argv[1], "w")) != NULL){ 
	for (int i = 0 ; i < 10000 ; i++){
	  m = (rand()%2 == 0)?1:-1;
	  fprintf (fp, "%d %d\n", i, i*2+m*rand()%150);
	} 
  }else{
	fprintf (stderr , "Cannot open file %s\n", argv[1]);
  }
	  return 0;
}
Domaine: 

Saisie de mot de passe masquée

Ce petit bout de code (en grande partie provenant du livre "C en action" d'O'Reilly), permet de saisir un mot de passe en console sans afficher les caractères tapés.
Ce code existe également en syntaxe C++

#define _GNU_SOURCE
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <termios.h>
 
char* get_pwd(){
	char *cr = NULL;
	unsigned int len; 
	struct termios t;
 
	tcgetattr (0, &t);
	t.c_lflag &= !ECHO;
	tcsetattr(0, TCSANOW, &t);
	getline(&cr, &len, stdin);
	cr[strlen(cr)-1] = 0;
	tcgetattr(0, &t);
	t.c_lflag |= ECHO;
	tcsetattr (0, TCSANOW, &t);
	return cr;
}
 
int main(){
	char *mdp;
	mdp = get_pwd();
	printf("ton mot de passe est : %s\n", mdp);
	free(mdp);
	return 0;
}

Test Unitaire (simple)

Vous voulez faire des tests unitaire mais Cunit/JUnit/ les modules intégré a votre IDE vous semble lourd pour de simple test?
Pas de panique! premièrement qu'est-ce que c'est que ces tests unitaire dont j'entend tout le temps parler?

il peut être utile de savoir si votre fonction marche vraiment et souvent vous faites des tests unitaire sans le savoir, prenons notre bonne vielle fonction swap:

badSwap(int a, int b){
        int c = a;
        a = b;
        b = c;
}

pour voir si vous avez pas fait de bêtise, souvent vous faites un rapide test avec des valeurs bidon:

void test_badSwap(){
        int a = 42;
        int b = 1337;
        badSwap(a,b);
        printf("a: %d,  b: %d\n", a, b);
}

la vous voyez que la fonction marche pas et la corriger en conséquence, mais une fois la fonction débugué ces tests passe a l'oubliette!

Pourquoi ne pas tous les garder dans un coin (branch test par exemple) et les exécuter lorsque votre boss passe derrière vous pour montrer que vous faites de bon travail ; )

rendont ça un peu plus convivial (avec des couleurs °.°) grâce a une petite macro:

#define makeTest(test)	if(test()){ \
				puts("\e[1;32m"#test" pass\e[m"); \
			}else{ \
				puts("\e[1;31m"#test" fail\e[m"); \
			}

reste plus qu'a réécrire le test et a le lancer

int test_badSwap(){
        int a = 42;
        int b = 1337;
        badSwap(a,b);
        return (a == 1337) && (b == 42); // la fonction de test doit renvoyer 1 si le test réussi, 0 sinon
}
 
int main(){
        makeTest(test_badSwap);
        return 0;
}

voila! plus de raison de ne pas faire de test unitaire maintenant ; )

bonus: une fonction swap qui marche

#include <stdio.h>
#define makeTest(test)	if(test()){puts("\e[1;32m"#test" pass\e[m");} \
			else{puts("\e[1;31m"#test" fail\e[m");}
void badSwap(int a, int b){
	int c = a;
	a = b;
	b = c;
}
 
void goodSwap(int *a, int *b){
	int c = *a;
	*a = *b;
	*b = c;
}
 
int test_badSwap(){
	int a = 42;
	int b = 1337;
	badSwap(a,b);
 return (a == 1337) && (b == 42);
}
 
int test_goodSwap(){
	int a = 9;
	int b = 666;
	goodSwap(&a,&b);
 return (a == 666) && (b == 9);
}
 
int main(){
	makeTest(test_badSwap);
	makeTest(test_goodSwap);
        return 0;
}

Test de Rabbin Miller (nombre premier)

Petit code effectuant le test de Rabbin-Miller utilisant la librairie de calcul gmp

static int rabbin(int a_, mpz_t p){
 
	mpz_t temp;
	mpz_t r;
	mpz_t a;
	mpz_t q;
	mpz_t pm;
	mpz_t i;
 
	int moinsUn = 0;
 
	mpz_init(temp);
 
	mpz_init_set(r,p);
	mpz_init_set(pm,p);
	mpz_sub_ui(pm,pm,1);
	mpz_init_set_ui(a,a_);
	mpz_init_set_ui(q,0);
 
 
	mpz_sub_ui(r,r,1);
	do{
		mpz_cdiv_q_2exp(r,r,1);
		mpz_mod_ui(temp, r, 2);
		mpz_add_ui(q,q,1);
	}while (mpz_cmp_ui(temp,0) == 0);
	/**
	 * Nous avons q = r2^{pp}
	*/
 
	mpz_powm (a, a, r, p);
 
	if(mpz_cmp_ui(a, 1) == 0){
		return 0; /* le nombre est considere comme premier */
	}
 
	mpz_init_set_ui(i,0);
	while(mpz_cmp(i, q) < 0){
		mpz_powm_ui(a,a,2,p);
 
		if(mpz_cmp(a, pm) == 0){
			moinsUn = 1;
		}else if(mpz_cmp_ui(a, 1) == 0){
			if(moinsUn == 1 || i == i){
				return 0; /* le nombre est considere comme premier */
			}else{
				return -1; /* compose */
			}
		}
		mpz_add_ui(i,i,1);
	}
 
	return -1;
 
}
Domaine: 

Tester si un nombre est premier

Calcul de nombres premiers

Petit test de primalité d'un unsigned long long int (sur x86 archi 32bits cela donne un nombre entre 0 et 18446744073709551616). Un exemple de code sera posté, utilisant la librairie gmp pour des nombres plus grands.

Nous utilisons ici la méthode dite "naïve" qui conciste à calculer les modulos successifs de tous les nombres impairs de 3 à la racine du nombre en question, après avoir testé si le nombre est divisible par 2.

#include <stdio.h>
#include <math.h>
 
unsigned long long int primeTest(unsigned long long int nb){
    unsigned long long int racine = (unsigned long long int)(sqrt(nb))+1;
    unsigned long long int i;
    if(nb == 1){
            return 1;
    }
    if((nb % 2) == 0) {
        return 2;
    }
    for (i = 3 ; i < racine ; i+=2){
        if((nb %i) == 0){
            return i;
        }
    }
    return 0;
}
 
int main(void){
    unsigned long long int nb = 3151468321657; 
    unsigned long long int diviseur;
    if((diviseur = primeTest(nb)) == 0){
        printf("Le nombre %lld est premier\n",nb);
    }else{
            printf("Le nombre %lld est divisible par %lld\n", nb, diviseur);
    }
    return 0;
}

A compiler avec la librairie math (-lm) par exemple :

gcc -Wall -lm test.c -o prog -std=gnu99
Domaine: 

Tri par tas ou Heapsort

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
#define TRUE 1
#define FALSE 0
 
void initTableau(int *tab, int taille){
	int i;
	for(i = 0; i < taille; i++)
		tab[i] = random();
}
 
void swap(int *a, int *b){
	int x = *a;
	*a = *b;
	*b = x;
}
 
char domine( int *tab, int taille, int j ){
 
	if( 2*(j+1)-1 >= taille) /* tab[j] est seul */
		return TRUE;
 
	else if(2*(j+1)-1 == taille-1 && tab[j] >= tab[2*(j+1)-1]) /* tab[j] a 1 descendant et domine */
			return TRUE;
 
	else if(tab[j] >= tab[2*(j+1)-1] && tab[j] >= tab[2*(j+1)]) /* tab[j] a 2 descendants et domine */
			return TRUE;
 
	return FALSE; /* Dans le cas ou tab[j] n'est pas seul et ne domine pas */
}
 
void retablirTas( int *tab, int j, int taille ){
 
	while(!domine(tab, taille, j)){/* I(j) et j domine => tab[0...taille-1] est un tas.*/
 
		if( 2*(j+1) == taille){ /* degre 1 && I(2(j+1)-1) */
			swap(&tab[j], &tab[ 2*(j+1)-1 ]);
			j = 2*(j+1)-1;
		}
 
		else{ /* degre 2 */
			if( tab[ 2*(j+1)-1 ] >= tab[ 2*(j+1) ] ){ /* I(2(j+1)-1) */
				swap( &tab[ 2*(j+1)-1 ], &tab[j] );
				j = 2*(j+1)-1; /* I(j) */
			}
 
			else{ /*I(2*(j+1)) */
				swap(&tab[ 2*(j+1) ], &tab[j]);
				j = 2*(j+1); /* I(j) */
			}
		}
	}
}
 
void faireTas(int *tab, int taille){
	int k;
	for(k = taille-1; k >= 0; k--)
		retablirTas(tab, k, taille);
}
 
int main(){
	int *tab;
	int taille;
	int f;
 
	/* Mesure du temps d'execution*/
	clock_t start, end;
	double elapsed;
 
	printf("Entrer la taille du tableau :\t");
	scanf("%d", &taille);
	f = taille;
 
	if ( ( tab = (int *)malloc( (sizeof(int)*taille)) ) == NULL)
		exit(EXIT_FAILURE);
 
	initTableau(tab,taille);
 
	start = clock(); /* lancement de la mesure */
 
	faireTas(tab, taille);
 
	/* I(f) = tab[0 ... f-1] est un tas
	&& ensemble des elements de tab[0 ... f-1] inferieur ou egal 
	a ensemble des elements tab[f ... taille-1]
	&& tab[f ... taille-1] est trie croissant
	*/
 
	while ( f > 1){ /* I(k) && (k>1)*/
                swap(&tab[0], &tab[f-1]);
                retablirTas(tab, 0, f-1); /* I(k-1) */
                f--;
        }
 
	end = clock(); /* arret de la mesure */
	elapsed =(double)(end-start)/CLOCKS_PER_SEC;
	printf("Temps de calcul : %lf\n",elapsed);
 
	exit(EXIT_SUCCESS);
}

calcul d'une racine carrée

/**
* \file square_root.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
/**
* \def EPSI est la précision recherchée
*/
 
#define EPSI 1.e-6
 
/**
* \brief Algorithme de Newton pour calculer une racine carrée.
* Utilise une boucle do while pour calculer la racine. Deux conditions de sortie de boucle :
* 1 L'erreur comise est <= à EPSI
* 2 Le nombre max d'itérations est atteind.
* NB : Aucun renseignement n'est donné quant à la condition de sortie réalisée ;
* la fonction n'indique pas si e <= EPSI en fin de boucle.
* A est supposé > 0 sinon les calculs n'auraient aucun sens.
*
* \param A Nombre dont on cherche la racine
* \param U sert a stocker le résultat U=0.5*A pour des calculs relativements rapides
* \param V sert a stocker le resultat, contient l'itération suivante
* \param e erreur relative tant que e <= EPSI on continue les calculs
* \param n nombre maximum d'itératons
* \param i compteur de boucle
*/
int main(){
 
	double A,U,V,e;
	int n,i=0;
	printf("A :\t");
	scanf("%lf",&A);
	printf("\nn :\t");
	scanf("%d",&n);
	U=A*0.5;
 
	do{
		V = 0.5*(U+A/U);
		e = fabs((V-U)/V);
		U = V;
		i++;
	}while(e>=EPSI && i<n);
 
	printf("%lf",U);
	return 0;
}
Domaine: 

calcul somme MD5

#include <stdio.h>
#include <string.h>
#include <openssl/md5.h>
 
void mdpCheckSum(const unsigned char *mdp, unsigned char *hash){
    char check[16];
    MD5((const unsigned char *)mdp, strlen((char *)mdp),(unsigned char *)check);
    for (int i = 0; i < 16; ++i){
        sprintf((char *)hash + (i * 2), "%02x", (unsigned char)check[i]);
    }
}
 
int main(){
    unsigned char hash[33];
    const unsigned char *mdp = "plop";
    mdpCheckSum(mdp, hash);
    printf("MD5 de %s : %s\n",mdp, hash);
}
Domaine: 

dumper une stack trace en cas de segfault

Petit bout de code qui bien pratique, imprimer une trace d'exécution en cas de segfault (pour avoir les numéro de lignes utiliser addr2line)

void sigSevHandler(int sig) {
  void *array[10];
  size_t size;
 
  size = backtrace(array, 10);
 
  fprintf(stderr, "Error: signal %d:\n", sig);
  backtrace_symbols_fd(array, size, 2);
  exit(1);
}
 
 
 
void setStacktraceDumpOnSegfault(){
    signal(SIGSEGV, sigSevHandler);
}
Domaine: 

scanf (légèrement) plus sécurisé

int main() {
  char string[42];
  scanf("%42s%*[^\n]",string);
  /* %42s --> on ne récupère que 42 caractère */
  /* %*   --> on récupère une nouvelle string qu'on ne stockera pas dans une variable */
  /*[^\n] --> tous les caractères sauf le retour à la ligne final */
  return 0;
}

C++

Sommaire :

Executer du code C++ dans du code C

Problème:

Vous voulez vous simplifier la vie en codant en C++ mais le reste de votre équipe est composé de vieux gnous qui ne veulent pas se mettre a l'orienté objet?
(ok il existe des bibliothèque pour faire de l'orienté objet en C mais soyons réaliste,
on atteins rapidement les limites du langage)

Le C++ se traduit en C, il n'apporte donc rien de nouveau

Et bien oui et non, en effet on pourrait s'amuser (d’ailleurs les plus vieux des gnous ne font que ça)
à réécrire tout son code C++ en C et avaler 3 boîtes d'aspirine pour convertir son code mais il y a plus simple.

g++ (ainsi que n'importe quel autre compilateur c++) peuvent compiler du code C,
c'est cette fonctionnalité que nous utiliserons pour exécuter notre code C++.

Du code C dans du C++?

Je vous vois venir, c'est un tuto pour faire exactement l'inverse de ce que je dis, mais pas de panique, on y viens
Pour exécuter son code cpp dans son code c, un seul mot d'ordre "encapsulation".

Votre compilateur C ne peut compiler que du code C, nous allons donc lui fournir.

Pensez aux nombreuses bibliothèques que vous avez inclues dans vos projet, au final vous n'aviez qu'un fichier compilé
(.so) et un header (.h) et au final (a part pour les plus barbus d'entre nous) vous ne saviez pas ce qu'il y avait dans votre bibliothèque, peut être même que du code C++ s'y cachait sans le savoir

Du code!

notre fichier cpp:

void Miaou::miauler(){
   std::cout << "miaou!" << std::endl;
}

le fichier c que l'on souhaiterais obtenir:

#include "parser.h"
int main(){
  miauler(); /* il manque quelque chose
mais c'est pour donner une idée de ce que l'on cherche à obtenir */
 return 0;
}

Manque plus que le fichier qui fait la liaison des deux code que j'ai nommé ici parser.

Parser

Le parser doit permettre l’exécution du code cpp a partir de celui écrit en C,
en c++, plus haut je parlais d'encapsulation, c'est ce que nous allons faire ici,
pour chaque méthode publique de notre fichier cpp, nous lui créerons une fonction C
qui ne fera qu'appeler cette méthode.

Parser.cpp

#include "Miaou.hpp"
 
Miaou* createNewMiaou(){
   return new Miaou();
}
 
void destructMiaou(Miaou* chat){
   delete chat;
}
 
void miauler(Miaou* chat){ //c'est ce qu'il manquait, on applique une méthode sur un objet
   chat->miauler();
}

voila, rien de bien compliquer une fois compilé, nous obtenons un code C qui ne pose aucun problème de link pour gcc
(enfin, pratiquement...)

il manque en effet la touche finale, le "name mangling" (le compilateur renomme toute les fonctions parce qu'il aime pas les chats)
est différent pour le compilateur C++ et C, il suffit juste de lui préciser d'utiliser le même nom pour ne pas qu'il se perde une fois rendu au linkage.

Parser.hpp:

#include "Miaou.hpp"
extern "C"{ //utiliser les convention du C,
   Miaou* createNewMiaou();
   void destructMiaou(Miaou* chat);
   void miauler(Miaou* chat);
}

eh mais, on utilise des pointeur de Miaou, mais gcc ne connait pas les objets!
effectivement mais ce ne sont pas des objet mais des pointeurs d'objet, on utilisera donc un type générique, le void*
qui sera de toute façon transtypé correctement dans notre code cpp.

Parser.h

typedef void* Miaou;
 
Miaou* createNewMiaou();
void destructMiaou(Miaou* chat);
void miauler(Miaou* chat);

il ne manque plus qu'a compiler notre library:
[quote]
g++ -fPIC -shared *.cpp -o libMiaou.so
[/quote]

Memo

- Créer un parser qui encapsule les méthodes publique d'une classe

#include "ClassCpp.hpp"
 
ClasseCpp* createObjet(){
   return new ClasseCpp();
}
 
void executeMethodeMiaou(ClasseCpp *objet){
   objet->methodeMiaou();
}
 
int executeMethodeChat(ClasseCpp *objet, int milk){
   objet->methodeChat(milk);
}

- Créer un fichier hpp pour spécifier un name Mangling de type C

extern "C"{
   ClasseCpp* createObjet()
   void executeMethodeMiaou(ClasseCpp *objet);
   int executeMethodeChat(ClasseCpp *objet, int milk);
}

- header de notre library utilisant des void*

typedef void * MD25Command;
ClasseCpp* createObjet()
void executeMethodeMiaou(ClasseCpp *objet);
int executeMethodeChat(ClasseCpp *objet, int milk);

Notes

En vrac,
Si vous créez une library, penser à la passer en LGPL ; )

Les compilateurs n'utilisent pas forcement un name mangling identique par langage (vous devrez sans doute utiliser un compilateur C de la même "marque" que votre compilateur C++)

C'est tordu? on me le dit souvent...

si vous avez d'autres remarques, n’hésitez pas a laisser un commentaire ; )
PS: (si quelqu'un passe par là et trouve que j'ai fait trop de faute de grammaire/orthographe/syntaxe (malheureusement pas de mention inutile...) je le remercie d'avance de ne pas pouvoir lire ce document sans pouvoir s’empêcher de le corriger :- ° )

Saisie de mot de passe masquée

Version C++ du code présent dans la partie C :

Fichier mdp.cpp:

#include <fstream>
#include <termios.h>
 
using namespace std;
 
void get_pwd(char *pwd, int len){
	struct termios t;
 
	/* Désactive l'affichage des caractères */	
	tcgetattr (0, &t);
	t.c_lflag &= !ECHO;
	tcsetattr(0, TCSANOW, &t);
 
	/* Lecture du mot de passe */
	cin.getline(pwd, len, '\n');
 
	/* Réactive l'affichage des caractères */
	tcgetattr(0, &t);
	t.c_lflag |= ECHO;
	tcsetattr (0, TCSANOW, &t);
}

Fichier main.cpp:

#include <iostream>
#include "mdp.cpp"
 
#define MAX_PASS 20
 
using namespace std;
 
int main(){
	char mdp[MAX_PASS];
	cout << "Entrez votre mot de passe : " ;
	get_pwd( mdp, MAX_PASS);
	cout << endl;
	cout << "Votre mot de passe est : " << mdp << endl ;
	return 0;
}

Lisp

Quelques exemples en Lisp Emacs pour débuter plus facilement

Pose une question binaire et utilise la réponse

Pose une question binaire et utilise la réponse

(defun cacahuete (toto)
  (if (y-or-n-p (format "%s mange des cacahuetes ? " toto))
      "Il a bien raison"
    "Il devrait"))
 
(cacahuete "Toto")

Matlab

Il parait qu'on peut aussi progammer sous matlab !
Cette section contient quelques scripts qui pourront peut être vous aider si vous devez utiliser matlab en TP mais que vous ne savez pas comment on déclare une fonction ou encore comment faire une boucle while...

Les rapports de tps sont accessibles en ligne à l'adresse suivante :
http://clubnix.esiee.fr/~furet/TP/ma213
Ils peuvent être utiles pour comprendre le code. Et n'oubliez pas : COPIER/COLLER SAY MAL ! (surtout si on comprend pas)

Calcul d'un zero d'une droite par la méthode de Descartes

La fonction dont on veut calculer le zéro :
fun.m

% Put your fun stuff here :)
function y=fun(x)
y= x^2 -10;

Le script qui calcule numériquement ce zéro (s'il existe) :
descartes.m

% auteurs : Erwan Le Guennec & Paul Hillereau
% version 1.0
% fevrier 2008
% script qui permet de résoudre numériquement une équation du type
% f(x)=0 sur un intervalle [a,b]
% Attention on suppose que f ne s'annule qu'une seule fois
% sur [a,b]
% on se fixe une précision epsi pour calculer le zero
% Attention pour éviter de lancer une boucle infinie
% on fixe arbitrairement le nombre max d'itérations
 
% nombre max d'iterations
imax=100;
% epsi precision recherchee
epsi=1/100;
% compteur de boucle
I=0;
 
% intervalle [a,b]
a=-5;
b=7;
 
% utilise pour stocker les resultats numeriques
z=0;
e=0;
d=0;
 
% fun() est une fonction du type f(x)
% c'est celle dont on cherche le zéro
% on utilise la méthode de Descartes
% qui consiste à remplacer le zéro de la courbe
% par le zéro de la corde (a,b)
 
while (I<imax)
    d=( (fun(b)-fun(a)) / (b-a) );
    e = fun(a) - (d*a);    % equation de droite y = dz +e
    z = -(e/d);     % 0 = dz + e
    if (fun(a)*fun(z) <= 0)
        a=z;
    else
        b=z;
    end
    if( abs(fun(z)) <= epsi )
        'ok'
        break;
    elseif (I==imax-1)
        'pas ok'
        break;
    end
    I = I + 1;
end
 
'nb d iterations'
I+1
'resultat'
z
Fichier attachéTaille
Plain text icon fun.txt59 octets
Plain text icon descartes.txt1.17 Ko

Calcul d'un zero d'une droite par la méthode de Newton

La fonction dont on veut calculer le zéro :
fun.m

% Put your fun stuff here :)
function y=fun(x)
y= x^2 -10;

La fonction qui permet de calculer les dérivées :
deriv.m

% calcul la dérivée de fun() en un point donné
% (à 10^-5 près)
function y=deriv(x)
y= (fun(x+10^(-5))-fun(x))/(10^(-5));

Le script qui permet de calculer le zéro :
newton.m

% auteurs : Erwan Le Guennec & Paul Hillereau
% version 1.0
% fevrier 2008
% script qui permet de résoudre numériquement une équation du type
% f(x)=0
% On utilise pour ça la dérivée première en a
% on se fixe une précision epsi pour calculer le zero
% Attention pour éviter de lancer une boucle infinie
% on fixe arbitrairement le nombre max d'itérations
 
% nombre max d'iterations
imax=100;
% epsi precision recherchee
epsi=1/100;
% compteur de boucle
I=0;
 
% pour le calcul de la tangente en a
a=-5;
 
% utilise pour stocker les resultats numeriques
z=0;
e=0;
d=0;
 
% fun() est une fonction du type f(x)
% c'est celle dont on cherche le zéro
% on utilise la méthode de Newton
% qui consiste à remplacer le zéro de la courbe
% par le zéro de la tangente à la courbe en (a,f(a))
 
while (I<imax)
    d=deriv(a);
    e= fun(a) - d*a;	% equation de droite y = dX + e
    z= - (e/d);	% z est l'absice en y = 0
 
    if (abs (fun(z)) <= epsi)
        'ok'
        break;
    else
        a=z;
    end 
 
    I=I+1;
 
end
 
'nombre d iterations'
I+1
'resultat'
z
Fichier attachéTaille
Plain text icon deriv.txt58 octets
Plain text icon fun.txt59 octets
Plain text icon newton.txt1.06 Ko

Calcul d'un zero d'une droite par une méthode dichotomique

La fonction dont on veut calculer le zéro :
fun.m

% Put your fun stuff here :)
function y=fun(x)
y= x^2 -10;

Le script qui calcule numériquement ce zéro (s'il existe) :
dichotomie.m

% auteurs : Erwan Le Guennec & Paul Hillereau
% version 1.0
% fevrier 2008
% script qui permet de résoudre numériquement une équation du type
% f(x)=0 sur un intervalle [a,b]
% Attention on suppose que f ne s'annule qu'une seule fois
% sur [a,b]
% on se fixe une précision epsi pour calculer le zero
% Attention pour éviter de lancer une boucle infinie
% on fixe arbitrairement le nombre max d'itérations
 
% nb d it max
imax = 100;
% epsi precision recherchee
epsi = 1/100; 
% compteur de boucle
I=0;
%Intervalle [a,b]
a=-5;
b=7;
% sert a stocker les resultats numeriques
c=0;
 
% fun() est une fonction du type f(x)
% c'est celle dont on cherche le zéro
% Principe : on divise [a,b] en deux
% on regarde de quel côté est le zéro
% (on teste si le signe change ou pas)
% On se place sur le nouvel intervalle
% et on recommence.
 
while (I < imax)
    c=(a+b)/2	% c milieu de [a,b]
    if (fun(a)*fun(c) <= 0)	% si il y a un changement de signe
        b=c;	% le zéro est compris entre a et c
    else
        a=c;	% le zéro est compris entre c et b
    end
    if (abs(fun(c))<= epsi)
        sprintf 'ok'
        break;
    elseif (I == imax-1)
        sprintf 'pas ok'
        break;
    end
    I = I +1;
end
'nombre d iterations'
I+1
'resultat'
c
Fichier attachéTaille
Plain text icon fun.txt59 octets
Plain text icon dichotomie.txt1.23 Ko

Outils

Makefile en force

Oulala j'ai 4 fichiers a compiler, faire les .o puis linker. Ca devient compliqué tout ça :s

Makefile est la pour toi, pour toi !

Nous sommes dans la rubrique Code ce n'est donc pas un tutoriel à part entière mais deux trois explications s'impose quand même.

Ce que fait le Makefile ?

Compare les dates de modifications des fichiers avec l'heure actuel pour déterminer lesquels sont a recompiler.

Pour compiler un binaire, Makefile établie un arbre :
Pour le binaire il faut :

    *  plop.o
          o plop.c
          o plop.h
          o temps.o
                + temps.c
                + temps.o
    * plip.o
          o plip.c
          o plip.h

C'est pour cela qu'il ne faut pas oublier de spécifier les .h dans le Makefile pour qu'il recompile votre projet si ils sont modifiés.

LE Makefile

Loin d'être parfait, bien évidement, il vous permettra quand même de vous dépanner de temps à autre (du moins je l'espère).

Rien d'extraordinaire, mais il a quand même la particularité d'avoir une règle pour une compilation "normale" et une compilation activant les flags de debug si besoin est.

CC = gcc 
 
CFLAGS = -Wall -W  -std=gnu99  
LDFLAGS =
 
SRC = plop.c plop.h
OBJS = $(SRC:.c=.o)
EXEC = prog
 
COMPILE := $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(EXEC)
debug : CFLAGS += -DDEBUG -g
 
all:$(EXEC)
	./$(EXEC)	
 
$(EXEC):$(OBJS) 
	$(COMPILE)
 
debug :$(OBJS)
	$(COMPILE)
 
%.o: %.c
	$(CC) $(CFLAGS) -c $(<) -o $(@) 
 
clean: 
	-rm *.o
	-rm $(EXEC)

Autre exemple à télécharger : Makefile

Script

colorize

Script bash permettant de coloriser la sortie d'une application à l'aide de regexp

exemple d'utilisation:

$ echo "hello word" |./colorize --blue hello --purple word

nous donne:
hello word

java

Sommaire

Accent et Windows

Par ce que chez windows on fait jamais comme les autres:

pour écrire dans la console windows le bon vieux
 System.out.println(); ne veux pas vous afficher d'accent?
pas de fatalisme anti-micro$oft primaire, leurs console en est capable!

pour cela il faut utiliser  System.console().printf();
rien de plus évident, n'est-ce pas?
maintenant si y'a que moi qui savait pas on pourrait m'expliquer? (même si y'a pas que moi d'ailleurs)

Application TCP Client Serveur en java

La source proposé permet de connecter plusieurs clients à un même serveur. Reste un gros problème, si après l'établissement d'une connexion le serveur meurt, le client ne reçoit pas d'erreur lors de l'envoie de message. Si quelqu'un trouve une solution (pas bourrine), faites moi signe.

Ce code est composé de trois classes

  • Le serveur : Server.java
  • Une classe de connection : Connect.java
  • Une classe client : Client.java

Server.java

import java.net.ServerSocket ;
import java.net.SocketException ;
 
import java.io.IOException ;
 
public class Server {
 
	private boolean ok=true ;
	private ServerSocket server;
 
	private final int PORT= 5163;
 
	public static void main (String [] args ){
		new Server();
	}
 
	public Server (){
		try{
			server = new ServerSocket (PORT);
		}//try
		catch (SocketException e) {
			System.out.println(e.getMessage() + " 01");
		} // catch
		catch (IOException e) {
			System.out.println(e.getMessage()+" 02");
		}//catch
		System.out.println("En écoute sur le port : " + PORT );
		while (ok) {
			try {
				new Connect(server.accept());
			} //try
			catch (IOException e) {
				System.out.println(e.getMessage()+ " 03");
			}//catch
 
		}//while
	}//Serve
 
}//class

Connect.java

import java.net.Socket ;
 
import java.lang.Thread ;
import java.lang.IllegalThreadStateException ;
import java.lang.NullPointerException ;
 
import java.io.PrintWriter ;
import java.io.BufferedWriter ;
import java.io.OutputStreamWriter ;
import java.io.IOException ;
 
import java.util.ArrayList ;
public class Connect implements Runnable {
	private Thread thd ;
	private Socket socket ;
	private PrintWriter out ;
	//private InputStream in  ;
 
	private static ArrayList<Connect> listC = new ArrayList<Connect>(1);
	public Connect (Socket socket_) {
		listC.add(this);
		socket = socket_ ;
		thd = new Thread (this) ;
		thd.start();
	}//connect
 
	public void run () {
		try {
			out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true );
//in  = new BufferedReader(new  InputStreamReader(socket.getInputStream ()));
		}//try
 
		catch (IOException a ) {
			System.out.println("erreur2") ;
			a.printStackTrace() ;  }//catch IO
 
			while (true){
				try {
					/*if (in.ready()==true) {*/
 
//-------------------------Reception des caracteres----------------------------------
					int t;
					String tmp="" ;
					do {t = socket.getInputStream().read() ; tmp = tmp + (char)t; }
					while (t!=10) ;
 
//-----------------------------------------------------------------------------------
 
					System.out.println("|" + tmp + "|" ) ;
// 					dispatch(tmp, );
					switch(tmp.charAt(0)) {
						case 0 :
							System.out.println("MSG> " + tmp) ;
							dispatch(tmp , socket) ;
							break ;
						case 1 :
							System.out.println("ATK> " + tmp) ;
							break ;
						case 2 :
							System.out.println("MOV> " + tmp) ;
							break ;
						default :
							System.out.println("INC>" + tmp) ;
					}//switch
				}//try
				catch (IOException a ) {
					System.out.println("erreur2") ;
					a.printStackTrace() ;  }//catch IO
 
			}//while
	}//run
 
	public static void dispatch (String scor, Socket socket) {
		for (int i = 0 ; i < listC.size() ; i++) {
			if (listC.get(i).socket!=socket){try{listC.get(i).send(scor) ;}
				catch (NullPointerException e) {
					System.out.println("morte la connection :(" ) ;listC.remove(i) ;
				}//catch
			}//if
		}//for
	}//dispatch
 
 
	public void send (String scor){
		out.println(scor) ;
	}//send
}//class

Client.java

import java.net.Socket ;
 
import java.io.PrintWriter ;
import java.io.OutputStreamWriter;
import java.io.IOException ;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.DataOutputStream;
 
 
public class Client implements Runnable {
 
 
	private String addr;
	private String port;
	private PrintWriter out;
	private DataOutputStream out2;
	private	Socket socket;
	private Thread thd;
 
public static void main (String [] args) {
	if(args.length == 0){
		System.out.println("Tentative de connection à localhost:5163");
		new Client("localhost","5163");
	}else{
		new Client(args[0], args[1]);
	}
}
 
 
public Client(String addr, String port){
	try{
		socket = new Socket (addr , Integer.parseInt(port));
		socket.setSoLinger(true , 10);
	}//try
	catch (IOException a ){
		System.out.println("erreur2 " + a.getMessage()) ; a.printStackTrace() ;
	}
 
	try{
		out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true );
		out2 = new DataOutputStream(socket.getOutputStream());
	}//try
 
	catch (IOException a ) {
		System.out.println("erreur3") ;
		a.printStackTrace();
	}//catch IO
	thd = new Thread (this) ;
	thd.start();
 
		while (true){
			try {
//-----------------------------------------------------------------------------------
				int t;
				String tmp="" ;
				do {
					t = socket.getInputStream().read();
					tmp = tmp + t;
				}while (t!=0) ;
 
//-----------------------------------------------------------------------------------
					System.out.println(tmp);
			}//try
			catch (IOException a ) {
				System.out.println("erreur4") ;
				a.printStackTrace() ;  }//catch IO
		}//while
}//Client
 
public void run (){
	BufferedReader entree = new BufferedReader(new InputStreamReader(System.in));
	try {
		out.println(entree.readLine());
		out.flush();
// 		out2.writeBytes(entree.readLine() + "\n");
	} catch( IOException e ) {
		System.out.println("Erreure lors de l'envoie");
		e.printStackTrace();
	}
}
 
}//class

Créer une fenêtre en java Swing

Code java créant une fenêtre. Ce code est implémenté pour la jvm 1.5. La gestion du thread graphique ayant légèrement changé sous la 1.6 (utilisant la pile de l'edt). Néanmoins, l'implémentation

import javax.swing.JFrame ;
 
public class Fen {
	private JFrame frame1 ;
 
	public static void main (String[] args) {
		System.out.println ("çà démarre") ;
		new Fen () ;
	}//main
 
 
	Fen () {
		frame1 = new JFrame ("titre de la fenetre") ;
		frame1.setSize(1000 , 768) ;
		frame1.setDefaultCloseOperation(frame1.EXIT_ON_CLOSE) ;
		frame1.setVisible(true) ;
	}//Fen
 
 
	SwingUtilities.invokeLater(new Runnable() {
		public void run() {
			/* Démarrage de l'interface graphique et du SwingWorker. */
			SwingWorkerDemo demo = new SwingWorkerDemo();
			MonSwingWorker swingWorker = demo.new MonSwingWorker();
			swingWorker.execute();
		}
	});
 
}//class

Lire et écrire dans un fichier (en java)

Ce code permet de lire et écrire dans une fichier texte

import java.io.FileReader ;
import java.io.FileWriter ;
import java.io.BufferedReader ;
import java.io.IOException ;
import java.io.PrintWriter;
 
public class Fichier
{
	public static void ecrire(String path, String text) 
	{
		PrintWriter ecri ;
		try
		{
			ecri = new PrintWriter(new FileWriter(path));
			ecri.print(text);
			ecri.flush();
			ecri.close();
		}//try
		catch (NullPointerException a)
		{
			System.out.println("Erreur : pointeur null");
		}
		catch (IOException a)
		{
			System.out.println("Problème d'IO");
		}
	}//ecrire
 
	public String lire (String path) 
	{
		BufferedReader lect ;
		String tmp = "";
		try
		{
			lect = new BufferedReader(new FileReader(path)) ;
			while (lect.ready()==true) 
			{
				tmp += lect.readLine() ; 
			}//while
		}//try
		catch (NullPointerException a)
		{
			System.out.println("Erreur : pointeur null");
		}
		catch (IOException a) 
		{
			System.out.println("Problème d'IO");
		}
		return tmp;
	}//lecture 
}//class

php