Programmation Impérative
Imperative Programming

Winter and Spring 2024




Overview

Ch I) Let's try!

Ch II) Easy C

   

Ch III) C Addresses

Ch IV) C more than that

Ch V) Just for you (Projects 2024)

    V.A) Example: a report in LaTeX

   

    IV.A) Compiler
Règles de Compilation

  • The four steps for compiling
    Les quatre étapes de la compilation
    • The preprocessor. La précompilation (on obtient le résultat en utilisant l'option -E)
    • Assembly code. le code assembleur (option -S)
    • Building of the object code. le code objet (option -c)
    • The linker. l'édition de liens (option -o et le nom de l'exécutable).

  • The preprocessor

    It obeys to orders starting with #. Examples:
    Les directives qui commencent par # et elles seules sont évalluées par le précompilateur. Il les exécute. Parmi ces directives nous verrons essentiellement les :

    • #define
    • #include
    • #if then else
    Pseudo-constants and pseudo-functions
    pseudo-constantes et pseudo-fonctions
    Il s'agit de remplacer dans le texte, dans le corps du programme, toute occurence du mot défini par sa définition. Exemple :
    #define MAXI 100
    every occurence of MAXI will be replaced by 100.
    #include <stdio.h>
    #define GT(a, b) a < b ? b : a
    #define CARRE(a) a * a
    
    main () {
      int i, s;
      i = 10;
      s = 12;
      printf("Le MAX de %3d et %3D est %d\n",i,s,GT(i,s));
      printf("Le MAX de %3d et %3D est %d\n",i,s, GT(i++,s++));
      printf("Le MAX de %3d et %3D est %d\n",i,s, GT(i+1,s+1));
      printf("Le carre de %3d est %d\n",i + 1,CARRE(i + 1));
      printf("Le carre de %3d est %d\n",i,CARRE(i++));
      printf("Le carre de %3d est %d\n",i,CARRE(--i));
    }
    

    After preprocessoring, this part of the program becomes:
    après compilation partielle, devient
    main () {
      int i, s;
      i = 10;
      s = 12;
      printf("Le MAX de %3d et %3D est %d\n",i,s,i < s ? s : i);
      printf("Le MAX de %3d et %3D est %d\n",i,s, i++ < s++ ? s++ : i++);
      printf("Le MAX de %3d et %3D est %d\n",i,s, i+1 < s+1 ? s+1 : i+1);
      printf("Le carre de %3d est %d\n",i + 1,i + 1 * i + 1);
      printf("Le carre de %3d est %d\n",i,i++ * i++);
      printf("Le carre de %3d est %d\n",i,--i * --i);
    }
    

    The program does:
    dhcp2.ai.univ-paris8.fr: a.out
    Le MAX de  10 et  12 est 12
    Le MAX de  10 et  12 est 13
    Le MAX de  11 et  14 est 15
    Le carre de  12 est 23
    Le carre de  11 est 132
    Le carre de  13 est 132
    
    Et que diriez-vous de ce résultat paradoxal ?
    #define MAX(s,t) s < t ? t : s
    
    main () {
      int i, j, k, m, n;
      i = 2;
      j = 5;
      k = 6;
      n = MAX(i,j);
      m = MAX(n, k);
      printf("MAX(%3d,%3d,%3d) == %3d\n",i,j, k, m);
      printf("MAX(%3d,%3d,%3d) == %3d\n",i,j, k, MAX(MAX(i,j),k));
    }
    

    Ça a l'air tout simple et, presque, normal, non ? Essayons.
    jj@mu $ a.out
    MAX(  2,  5,  6) ==   6
    MAX(  2,  5,  6) ==   5
    jj@mu $ 
    

    ... qui n'est pas tout à fait normal.
    Let's look at the preprocessed code:
    jj@mu $ gcc -E ex.c
    # 1 "ex.c"
    # 1 ""
    # 1 ""
    # 1 "ex.c"
    
    
    main () {
      int i, j, k, m, n;
      i = 2;
      j = 5;
      k = 6;
      n = i < j ? j : i;
      m = n < k ? k : n;
      printf("MAX(%3d,%3d,%3d) == %3d\n",i,j, k, m);
      printf("MAX(%3d,%3d,%3d) == %3d\n",i,j, k, i < j ? j : i < k ? k : i < j ? j : i);
    }
    

    Just look at it and the error seems ovious.
    Cette fois je vois bien où est l'erreur, dans ce cas on regarde, si i est plus petit que j on revoie j, sinon on fait l'évaluation de i plus petit que k. C'est idiot, on voudrait justement le contraire !
  • Libraries
    Bibliothèques

    There are some very well documented standard libraries, you should check them on:
    On trouvera de la documentation précise sur les bibliothèques standard sur
    le lien suivant. Vous devriez en prendre connaissance.


        IV.A) Arithmétique


    1. Décalages
    2. Remarquons :
        Décimal       Binaire
            3              11
            6             110
           12            1100
           24           11000
           48          110000
           96         1100000
          192        11000000
            4             100
            8            1000
           16           10000
           13            1101
           26           11010
      
      Remarquons que, en décimal, 1230 et dix fois plus grand que 123. Donc, en binaire, 101010 et deux fois plus grand que 10101. L'opérateur de décalage à gauche
       << 
      permet donc de décaler un nombre binaire de n cases donc de le multiplier par 2 puissance n.
      void puiss2 (int pmax) {
        int i, p;
        p = 1;
        for (i=0; i < pmax; i++) {
          printf("%d\t",p);
          p = p << 1;
        }
        printf("\n");
      }
      

      Bien sûr le décalage à droite fait exactement le contraire.
      Attention, pour les nombres négatifs, comme vous le savez, pour que le nombre reste négatif, si le premier chiffre est un 1, au cours du déclage à droite, ce sont des 1 qui sont mis à gauche !
    3. Et binaire
    4.     01011010
      &   00011100
      ------------
          00011000
      
          01011010
      &   00000001
      ------------
          00000000
      
      S'écrit avec &.

      int imper (int i) {
        return i & 0x01;
      }
      

    5. Ou binaire
    6. int nonul (int i) {
        while (i) {
          if (i | 0x01)
             return 1;
          i = i << 1;
        }
        return 0;
      }
      /* completement inutile, non */
      

    7. Ou bien binaire
    8. int differ (int i, int j) {
         if (i ^ j)
            return 1;
         return 0;
      }
      

    9. Non binaire
    10. Essayez donc ceci :

      int inver (int i) {
        return 1 + ~i;
      }
      int main () {
        int n;
      
        for (n = -10; n < 11; n++)
      	printf("%d == -  %d\n", n, inver(n));
      }
      

        IV.B) Input/output
    Entrées/Sorties


    1. First example see in class on March the 20th 2024
      To write on a file one needs to open it and... to write on it.
      We start by the vector definition.
      #include <stdio.h>
      #include <stdlib.h>
      #include <assert.h>
      struct vect {
        int nbele;
        int * v;
      } ;
      typedef struct vect vect_t;
      
      Print such a vector is easy :
      void afficv(vect_t v) {
        int i;
        for (i = 0; i < v.nbele; i++)
          printf("%d ",v.v[i]);
        printf("\n");
      }
      
      Read from a file, first the number of elements then the elements is easy too, as soon as we have a file descriptor :
      vect_t lire (FILE * fd, int nbele) {
        vect_t v;
        int i, nbelefic, tmp;
        v.nbele = nbele;
        fscanf(fd, "%d ", &nbelefic);
        if (nbelefic < nbele) {
          nbele = nbelefic;
        }
        v.v = (int *) malloc (nbele* sizeof(int));
        assert(v.v);
        for(i=0; i < nbele; i++) {
          fscanf(fd, "%d", &tmp);
          v.v[i] = tmp;
        }
        return v;
      }
      
      Write such a file should not worry you :
      void ecrire (FILE * fd, vect_t w) {
        int i;
        fprintf(fd,"%9d ",w.nbele);
        printf(" on met %d\n",w.nbele);
        for (i = 0; i < w.nbele; i++)
          fprintf(fd,"%9d ",w.v[i]);
        fprintf(fd,"\n");
      }
      
      All that remain are two simple functions.
      vect_t creervect(nb) {
        int i, a, b, c;
        vect_t w;
        w.nbele = nb;
        w.v = (int *) malloc (nb * sizeof(int));
        assert(w.v);
        a = 1;
        b = 1;
        w.v[0]=1;
        w.v[1]=1;
        for (i = 2; i < nb; i++) {
          c = a + b;
          w.v[i] = c;
          b = a;
          a = c;
        }
        return w;
      }
      
      int main (int argc, char * * argv) {
        int nb, lireou;
        FILE * fd;
        vect_t w;
      
        if (argc != 3) {
          printf(" Mode : a.out nb nmfic\rn nb est un entier et nmfic un nom de fichier\n");
          exit (0);
        }
        nb = atoi (argv[1]);
        printf("argv[1] valait %d\n", nb);
        printf("Pour lire (1) ou ecrire (2) ?\n");
        scanf("%d",&lireou);
        if (lireou == 1) {
          fd = fopen(argv[2],"r+");/* open the file to read it*/
          assert(fd);
          w = lire(fd,nb);
          afficv(w);
          printf("Ou suis-je ? %ld\n",ftell(fd));
          fseek(fd, 0L, 0);
          printf("Ou suis-je ? %ld\n",ftell(fd));
          fseek(fd, -10L, SEEK_END);
          printf("Ou suis-je ? %ld\n",ftell(fd));
          fclose(fd);
          exit (0);
        }
        printf("On va ecrire \n");
        fd = fopen(argv[2],"w");/* open the file to write it*/
        assert(fd);
        w = creervect(nb);
        afficv(w);
        ecrire(fd,w);
        fclose(fd);
        exit (0);
      
      }
      /*    r      r+     w      w+     a       a+
      Où    debut debut début  début  fin     fin
      non   err   err           creation
      
      ftell(fd) -> le numéro de la case du fichier (0 c'est le début, 1 le second octet...)
      fseed(fd,ecart,point) permet d'avancer de "ecart" octets à partir du "point"
      SEEK_SET  0
      SEEK_CUR  1
      SEEK_END  2
      */
      
    2. Second example
      #include <stdio.h>
      #include <stdlib.h>
      
      struct vectd {
        int nb;
        double * v;
      } ;
      typedef struct vectd vectd_t;
      
      Then we are able to write such a vector on the terminal:
      void afficher (vectd_t v){
        int i;
      
        printf("%d ",v.nb);
        for (i = 0; i < v.nb; i++)
      	printf("%lf ",v.v[i]);
        printf("\n");
      }
      
      ... or on the file:
      void ecrire (vectd_t v, char * nomfichier) {
        int i;
        FILE * fd;
      
        fd = fopen (nomfichier, "w");
        if (! fd) { /* good old ways */
      	printf("Impossible d ouvrir le fichier %s !\n\n", nomfichier);
      	exit (1);
        }
        fprintf(fd,"%d ",v.nb);
        for (i = 0; i < v.nb; i++)
      	fprintf(fd,"%lf ",v.v[i]);
        fclose(fd);
      }
      
      we need to create it:
      vectd_t creer (int nb) {
        vectd_t v;
        int i;
        double x, eps;
        
        v.nb = nb;
        v.v = (double *) malloc (nb * sizeof(double));
        assert(v.v);
        eps = - 0.07;
        for (i = 0, x=1.3; i < v.nb; i++) {
      	v.v[i] = x;
      	x += eps;
      	if (x < 1.0) 
      	  eps = 0.145 + eps;
      	if (x > 1.7) 
      	  eps = - 0.145 + eps;
        }
        return v;
      }
      
      or to read it from the file:
      vectd_t lire (char * nomfichier) {
        vectd_t v;
        int i, nb;
        FILE * fd;
        double x;
        
        fd = fopen (nomfichier, "r");
        if (! fd) {
      	printf("Impossible d ouvrir le fichier %s !\n\n", nomfichier);
      	exit (1);
        }
        fscanf(fd,"%d ",&nb);
        v.nb = nb;
        v.v = (double *) malloc (nb * sizeof(double));
        if (! v.v) {
      	printf("Impossible d allouer la memoire de taille %d !\n\n", nb);
      	exit (1);
        }
        for (i = 0; i < v.nb; i++) {
      	fscanf(fd,"%lf ",&x);
      	v.v[i] = x;
        }
        fclose(fd);
        return v;
      }
      
      Here is a main function to use all the functions above.
      
      int main (int argc, char * * argv) {
        int nb, choix;
        vectd_t w;
        char * nf = "donnees.txt";
        
        choix = 0;
        if (argc == 3) {
      	choix = atoi (argv[1]);
      	nb = atoi (argv[2]);
      	printf("creation du fichier avec %d valeurs\n", nb);
      	w = creer(nb);
      	afficher(w);
      	ecrire(w,nf);
      	return 0;
        }
        if (argc == 2) {
      	choix = atoi (argv[1]);
        }
        if (choix < 0 || choix > 1)
      	choix = 0;
        switch(choix) {
        case 0:
      	printf("creation du fichier\n");
      	nb = 21;
      	w = creer(nb);
      	afficher(w);
      	ecrire(w,nf);
      	break;
        case 1:
      	printf("lecture du fichier\n");
      	w = lire(nf);
      	afficher(w);
      	break;
        }
      }
      
      Faites maintenant les fonctions suivantes :
      1. Une fonction qui lit et renvoie l‘élément nb du fichier.
      2. Une fonction qui tente de lire l‘émént nb du fichier, mais s‘il n‘existe pas, finit de remplir le fichier jusqu‘au rang nb.
      3. Une fonction qui renvoie la somme de tous les éléments du fichier.
    3. Second example

      We need to read and write files. Let's start with some definitions.

      Nous allons voir maintenant comment on écrit et comment on peut lire les contenus de fichiers. D'abord, il nous faut quelques définitions, c'est le fichier mydef.h :
      int fib (int);
      void remplir (FILE * f);
      int remplirn (FILE *, int);
      void lire (FILE *);
      int liren (FILE *, int);
      
      #ifdef DBG
       #define trace(s) printf s
      #else
       #define trace(s)
      #endif
      

      We can then write the main function.
      Dès que ceci est connu, nous pouvons voir le fichier main.c :
      #include <stdio.h>
      #include "mydef.h"
      #define NOM "nom.dat"
      
      main (int argc, char * * argv) {
        FILE * fichier;
        int i, j, v, w;
      
        if (argc == 2) {
      	i = atoi (argv [1]);
      	if ((fichier = fopen(NOM,"r"))!= NULL) {
      	  v = liren (fichier, i);
      	  printf("fib(%d) = %d\n",i,v);
      	}
      	else {
      	  if ((fichier = fopen(NOM,"w+"))== NULL) {
      		printf(" Rien a faire nous revenons a une fonction classique\n");
      		v = fib (i);
      		printf("fib(%d) = %d\n",i,v);
      	  }
      	  else {
      		v = remplirn (fichier, i);
      		fseek (fichier, -10L, 2);
      		fscanf(fichier,"%d",&w);
      		printf("fib(%d) = %d ou %d\n",i,v, w);
      	  }
      	}
      	fclose(fichier);
        }
        else if (argc == 3) {
      	i = atoi (argv [1]);
      	j = atoi (argv [2]);
      	if ((fichier = fopen(NOM,"r"))!= NULL) {
      	  for ( ; i <= j; i++) {
      		v = liren (fichier, i);
      		printf("fib(%3d) = %10d\n",i,v);
      	  }
      	}
      	else {
      	  if ((fichier = fopen(NOM,"w+"))== NULL) {
      		printf(" Rien a faire nous revenons a une fonction classique\n");
      		for ( ; i <= j; i++) {
      		  v = fib (i);
      		  printf("fib(%d) = %d\n",i,v);
      		}
      	  }
      	  else {
      		v = remplirn (fichier, i);
      		fseek (fichier, -10L, 2);
      		fscanf(fichier,"%d",&w);
      		printf("fib(%d) = %d ou %d\n",i,v, w);
      	  }
      	}
      	fclose(fichier);
        }
        else { /* Taille indefinie  */
      	if ((fichier = fopen(NOM,"r"))== NULL) {
      	  printf("il faut creer ce fichier \n\n");
      	  fichier = fopen(NOM,"w+");
      	  remplir (fichier);
      	  lire (fichier);
      	  fclose (fichier);
      	}
      	else {
      	  lire (fichier);
      	  close(fichier);
      	}
        }
      }
      

      Nous ne savons toujours pas vraiment lire et écrire, qu'à cela ne tienne, voici le fichier qui s'en charge, truc.c :
      #include <stdio.h>
      #include "mydef.h"
      #define NOM "num.dat"
      
      #define SIZE 45
      /* fill to the maximum */
      void remplir (FILE * f) {
        int i,n,m,p;
        n=1, m=1;
        fprintf(f,"%9d %9d %9d ",SIZE,1,1);
        for (i=2;i < SIZE; i++ ) {
      	p = n+m;
      	fprintf(f,"%9d ",p);
      	n=m;
      	m=p;
      	printf("%d ",p);
        }
        fprintf(f,"\n");
        printf("\n");
      }
      int remplirn (FILE * f, int nb) {
        int i,n,m,p;
        n=1;
        m=1;
        p=1;
      
        fprintf(f,"%9d %9d %9d ",nb,1,1);
        for (i=2;i < nb; i++ ) {
      	p = n+m;
      	fprintf(f,"%9d ",p);
      	n=m, m=p;
      	printf("%d ",p);
        }
        fprintf(f,"\n");
        printf("\n");
        return p;
      }
      void lire (FILE * f) {
        int i, j, taille, buf[SIZE];
        fscanf(f,"%d ",&j);
        taille = j > SIZE ? SIZE : j;
        for (i=0;i < taille;i++) {
      	fscanf(f,"%d ",&j);
      	buf[i]=j;
        }
        for (i=0;i < taille;i++) {
      	printf("%9d ",buf[i]);
      	printf("%l |",buf[i]);
        }
        printf("\n");
      }
      int liren (FILE * f, int nb) {
        int i, j, v0, v1, v;
        long posi;
        
        fseek(f, 0, SEEK_SET);
        fscanf(f,"%d ",&j);
        if (j > nb) {
      	posi = (nb * 10);
      	fseek(f, posi, SEEK_SET);
      	fscanf(f,"%d ",&v);
      	return v;
        }
        /* Il n'y avait pas assez de valeurs  
           on reouvrira donc le fichier pour pouvoir aussi
           le reecrire */
        fclose(f);
      /* wouldn't freopen do the job? */
        if ((f = fopen(NOM,"r+"))== NULL) {
      	printf("Ca ne va plus du tout\n\n");
      	return fib(nb);
        }
        fseek(f, -19L, 2);
        fscanf(f,"%d ",&v0);
        printf("%d => %d\n",j-2, v0);
        fseek(f, -10L, 2);
        fscanf(f,"%d ",&v1);
        printf("%d => %d\n",j-1, v1);
        for ( ; j <= nb; j++ ) {
      	v  = v0 + v1;
      	fprintf(f,"%9d ",v);
      	printf("%d ",v);
      	v0 = v1;
      	v1 = v;
        }
        fseek(f,0L,SEEK_SET);
        fprintf(f,"%9d ",nb);
        printf("remis %d au debut\n", nb);
        return v;
      }
      
      int fib (int n) {
        int v0, v1, v;
      
        v0 = 1;
        v1 = 1;
        while (--n) {
      	v  = v0 + v1;
      	v0 = v1;
      	v1 = v;
        }
        return v1;
      }
      /*
      gcc truc.o main.o -o fil
      neige: fil
      il faut creer ce fichier 
      
      2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155 165580141 267914296 433494437 701408733 1134903170 
      
      neige: fil 49
      43 => 408733
      44 => 34903170
      35311903 70215073 105526976 175742049 281269025 on est maintenant en 512
      On y trouve 45
      remis 49 au debut
      on est encore en 522
      On y trouve 45
      fib(49) = 281269025
      neige: cat num.dat 
             45         1         1         2         3         5         
      8        13        21        34        55        89       144       
      233       377       610       987      1597      2584      4181      
      6765     10946     17711     28657     46368     75025    121393    
      196418    317811    514229    832040   1346269   2178309   3524578   
      5702887   9227465  14930352  24157817  39088169  63245986 102334155 
      165580141 267914296 433494437 701408733 1134903170 
       3
      */
      

      Bien sûr la compilation n'est pas possible sans le fichier Makefile, le voici donc :
      # Compilation par Bourdin
      CC=gcc
      fil:    truc.o main.o mydef.h
      	$(CC) truc.o main.o -o fil
      	rm num.dat
      
      main.o: main.c mydef.h
      truc.o: truc.c mydef.h
      
      clean:
      	rm *.o *~ core
      
      hop:	
      	for i in 0 1 2 3 4 5 6 7 8 9
      	do
      		./fil $i ;
      	done
      
      

      Quand je m‘en sers, voici ce qui se passe. Ça ne veut pas dire que tout ira aussi bien chez vous...

      jj@mu$ make clean
      rm *.o *~ core
      rm: *~: No such file or directory
      rm: core: No such file or directory
      make: *** [clean] Error 1
      jj@mu$ make fil
      gcc    -c -o truc.o truc.c
      truc.c: In function 'liren':
      truc.c:68: warning: incompatible implicit declaration of built-in function 'malloc'
      gcc    -c -o main.o main.c
      gcc truc.o main.o -o fil
      rm nom.dat
      

      On fait les corrections nécessaires et voilà :
      jj@mu$ fil
      il faut creer ce fichier 
      
      2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946
      17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269
      2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986
      102334155 165580141 267914296 433494437 701408733 1134903170 
      
      jj@mu$ fil 49
      43 => 408733
      44 => 34903170
      35311903 70215073 105526976 175742049 281269025 on est maintenant en 512
      On y trouve 45
      remis 49 au debut
      on est encore en 522
      On y trouve 45
      fib(49) = 281269025
      jj@mu$ cat num.dat 
             45         1         1         2         3         5         
      8        13        21        34        55        89       144       
      233       377       610       987      1597      2584      4181      
      6765     10946     17711     28657     46368     75025    121393    
      196418    317811    514229    832040   1346269   2178309   3524578   
      5702887   9227465  14930352  24157817  39088169  63245986 102334155 
      165580141 267914296 433494437 701408733 1134903170 
       3
      

    4. A quicker version

      Version plus rapide

      The prototypes and definitions are given at first:
      Nous donnons ici simplement les fichiers direct.h, qui contient les décalrations et prototypes,
      /* direct.h*/
      #include <stdio.h>
      #include <stdlib.h>
      
      int fibiter (int);
      int lire (FILE *, int);
      int remplir (FILE *, int);
      

      the file with the main function

      puis le fichier contenant la fonction main
      /* miam.c */
      #include "direct.h"
      #define NOM "fib.dat"
      #define NORMAL 43
      
      main (int argc, char * * argv) {
        FILE * fichier;
        int i, j, v, w;
      
        if (argc == 2) {
      	i = atoi (argv [1]);
      	if ((fichier = fopen(NOM,"r+"))!= NULL) {
      //	  printf("On cherche fib(%d)\n",i);
      	  v = lire (fichier, i);
      	  printf("fib(%d) = %d\n",i,v);
      	}
      	else {
      	  if ((fichier = fopen(NOM,"w+"))== NULL) {
      		printf(" Rien a faire nous revenons a une fonction classique\n");
      		v = fibiter (i);
      		printf("fib(%d) = %d\n",i,v);
      	  }
      	  else {
      		v = remplir (fichier, i);
      		printf("fib(%d) = %d \n",i,v);
      	  }
      	}
      	fclose(fichier);
        }
        else { /* Taille indefinie  */
      	if ((fichier = fopen(NOM,"r+"))== NULL) {
      	  printf("il faut creer ce fichier \n\n");
      	  fichier = fopen(NOM,"w+");
      	  v = remplir (fichier, NORMAL);
      	  w = lire (fichier, NORMAL);
      	  printf("fib(%d) = %d == %d\n",NORMAL,v, w);
      	  fclose (fichier);
      	}
      	else {
      	  v = lire (fichier, NORMAL);
      	  printf("fib(%d) = %d \n",NORMAL,v);
      	  close(fichier);
      	}
        }
      }
      

      then the two functions of file direct.c

      puis les deux fonctions qui composent le fichier direct.c, lire
      /*direct.c*/
      /* Il s agit de lire et d ecrire dans un fichier massif */
      #include "direct.h"
      
      int lire (FILE * f, int nb) {
        int nf, i, v, w, * tf;
      
      /* on commence par savoir s'il y a assez d'elements dans f*/
      
        fread(&nf, (size_t) 4, (size_t) 1, f);
        printf("Dans ce fichier il y a %d elements\n",nf);
        if (nf > nb) {
      	tf = (int *) malloc ((nb+1) * sizeof (int));
      	fread(tf, (size_t) 4, (size_t) (1 + nb), f);
      	for (i=0; i <= nb; i++) {
      	  printf("fib(%d) == %d\n",i, tf[i]);
      	}
      	return tf[nb];
        }
        else {
      	return remplir (f, nb);
        }
      }
      
      then remplir(fill it)
      puis remplir
      int remplir (FILE * f, int nb) {
        int nf, i, v, w, * tf;
      
        tf = (int *) malloc ((nb+1) * sizeof (int));
        tf[0] = 1;
        tf[1] = 1;
        for (i=2, v=1, w=1; i <= nb; i++) {
      	v += w;
      	tf[i] = v;
      	w = v - w;
        }
        for (i=0; i < nb; i++) {
      	printf("fib(%d) = %d\n",i,tf[i]);
        }
        fseek (f,0,SEEK_SET);
        fwrite(&nb, (size_t) 4, (size_t) (1), f);
        fwrite(tf, (size_t) 4, (size_t) (1 + nb), f);
        return tf[nb];
      }
      

      All that is to do now is compile and run the program.
      Il ne reste plus qu‘à compiler.
      Mu.local: make fool
      gcc -o direct.o -c direct.c 
      gcc -o fool miam.o fibiter.o direct.o direct.h
      rm fib.dat
      Mu.local: fool 12
      fib(0) = 1
      fib(1) = 1
      fib(2) = 1
      fib(3) = 2
      fib(4) = 3
      fib(5) = 5
      fib(6) = 8
      fib(7) = 13
      fib(8) = 21
      fib(9) = 34
      fib(10) = 55
      fib(11) = 89
      fib(12) = 144 
      Mu.local: fool 10
      Dans ce fichier il y a 12 elements
      fib(0) == 1
      fib(1) == 1
      fib(2) == 1
      fib(3) == 2
      fib(4) == 3
      fib(5) == 5
      fib(6) == 8
      fib(7) == 13
      fib(8) == 21
      fib(9) == 34
      fib(10) == 55
      fib(10) = 55
      

      There are some problems in the above program:

      1. The type used (int) drastically limits the number of elements to present. Rewrite the functions with for example long long int.
      2. When the file contains nf elements, if one wants the element nf+i, the program starts again to build everything. It should be much better to just add the missing values. Make the appropriate changes.

          V.A) Projets : un exemple de rapport

      Vous pouvez utiliser LaTeX pour rédiger votre projet. Pour cela vous trouverez ici plusieurs fichiers :
      Dernière mise à jour le 27/4/2024 10h00

      Ajout d‘une image dans le rapport<\P>