Jean-Jacques BOURDIN
Attention Une note va donc être affichée sur votre ENT. Elle tient compte de
votre second partiel pour ceux qui l'ont passé ou simplement du
premier. Dans tous les cas, il sera possible de passer un "second partiel" à
la fin des cours de second semestre, à une date que nous fixerons
via un sondage en ligne.
Voici un programme simple que nous voudrions structurer :
#include <stdio.h> double puis (double x, int n) { double res = 1.0; while (n) { if (n & 0x01) res *= x; x *= x; n >>= 1; } return res; } main () { int n; double y; for (y=0.0; y < 3.1; y += 0.2) { for (n = 0; n < 10; n++) printf ("%3.5lf ^ %d == %6.8lf\n", y, n, puis(y,n)); } } |
D'abord, il faut spécifier pour la fonction puis. Elle renvoie un double et reçoit comme paramètre un double et un entier.
double puis (double, int) ; |
Ensuite, séparez ce programme en trois parties :
#include "puis.h" |
$gcc main.c puis.c -o puissances |
CC=gcc puissance: main.o puis.o puis.h $(CC) -o puissance main.o puis.o main.o: main.c puis.h $(CC) -c main.c puis.o: puis.c puis.h $(CC) -c puis.c clean: rm *.o *~ core |
$make |
# Compilation generique par Bourdin CC=gcc SRC=puis.c main.c OBJ=puis.o main.o CFLAGS=-Wall fil: $(OBJ) puis.h $(CC) -o $@ $(OBJ) main.o: main.c $(CC) -c main.c $(CFLAGS) puis.o: puis.c $(CC) -c puis.c $(CFLAGS) |
CC=gcc SRC=puis.c main.c OBJ=$(SRC:.c=.o) FLAGS=-Wall fil: $(OBJ) puis.h $(CC) -o $@ $(OBJ) %.o: %.c $(CC) -c $< $(CFLAGS) clean: rm *.o *~ core |
#define MAX 100000 typedef unsigned short Shu; int suite (int n) { int a; a = n >> 1; if (n & 0x01) return 3 * (a + 1); return a; } int main (int argc, char * * argv) { int n, i, v, seed; Shu tab [MAX], *crt; if (argc > 1) n = atoi (argv[1]); else n = 7; for (seed = 1; seed < 900; seed++) { for (i = 0, crt = tab; i < MAX; i++) *crt++ = (Shu) 0; v = seed; tab [v] = 1; for (i = 1; i < n; i++) { v = suite (v); if (v > MAX) { printf("Depassement pour %d : %d\n", seed, v); exit (0); } if (tab[v]) break; tab[v] = 1; } if (n == i) printf("seed %d \t n %d i %d\n", seed, n, i); } } |
Implémenter les deux exemples ci-dessus.
Prendre un programme déjà fait en C, le séparer en divers fichiers et créer le Makefile correspondant. Vérifier que la compilation se passe correctement.
Voir la page wikipedia la plus sérieuse sur le sujet.
#include <stdio.h> int fct (int n) { int i, v1, v2; v1 = 1; v2 = 1; i = 2; while (i <= n) { v2 += v1; v1 = v2 - v1; i++; } return v2; } int ftc (int n) { if (n < 2) return 1; return ftc(n-1) + ftc (n-2); } main () { int n = 0; while (n < 20) { printf("f(%3d)\t== %d\n",n, fct(n)); printf("\t== %d\n", ftc(n)); n++; } } |
#include <stdio.h> int fct (int n) { int i, v1, v2; v1 = 1; v2 = 1; for (i = 2; i <= n; i++) { v2 += v1; v1 = v2 - v1; } return v2; } int ftc (int n) { if (n < 2) return 1; return ftc(n-1) + ftc (n-2); } main () { int n; for (n = 0; n < 20; n++) { printf("f(%3d)\t== %d\n",n, fct(n)); printf("\t== %d\n", ftc(n)); } } |
.text .globl _fct _fct: LFB3: pushq %rbp LCFI0: movq %rsp, %rbp LCFI1: movl %edi, -20(%rbp) movl $1, -8(%rbp) movl $1, -12(%rbp) movl $2, -4(%rbp) jmp L2 L3: movl -8(%rbp), %eax addl %eax, -12(%rbp) movl -8(%rbp), %edx movl -12(%rbp), %eax subl %edx, %eax movl %eax, -8(%rbp) incl -4(%rbp) L2: movl -4(%rbp), %eax cmpl -20(%rbp), %eax jle L3 movl -12(%rbp), %eax leave ret LFE3: .globl _ftc _ftc: LFB4: pushq %rbp LCFI2: movq %rsp, %rbp LCFI3: pushq %rbx LCFI4: subq $24, %rsp LCFI5: movl %edi, -20(%rbp) cmpl $1, -20(%rbp) jg L7 movl $1, -24(%rbp) jmp L9 L7: movl -20(%rbp), %edi decl %edi call _ftc movl %eax, %ebx movl -20(%rbp), %edi subl $2, %edi call _ftc addl %eax, %ebx movl %ebx, -24(%rbp) L9: movl -24(%rbp), %eax addq $24, %rsp popq %rbx leave ret LFE4: .cstring LC0: .ascii "f(%3d)\11== %d\12\0" LC1: .ascii "\11== %d\12\0" .text .globl _main _main: LFB5: pushq %rbp LCFI6: movq %rsp, %rbp LCFI7: subq $16, %rsp LCFI8: movl $0, -4(%rbp) jmp L12 L13: movl -4(%rbp), %edi call _fct movl -4(%rbp), %esi movl %eax, %edx leaq LC0(%rip), %rdi movl $0, %eax call _printf movl -4(%rbp), %edi call _ftc movl %eax, %esi leaq LC1(%rip), %rdi movl $0, %eax call _printf incl -4(%rbp) L12: cmpl $19, -4(%rbp) jle L13 leave ret LFE5: .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support EH_frame1: .set L$set$0,LECIE1-LSCIE1 .long L$set$0 LSCIE1: .long 0x0 .byte 0x1 .ascii "zR\0" .byte 0x1 .byte 0x78 .byte 0x10 .byte 0x1 .byte 0x10 .byte 0xc .byte 0x7 .byte 0x8 .byte 0x90 .byte 0x1 .align 3 LECIE1: .globl _fct.eh _fct.eh: LSFDE1: .set L$set$1,LEFDE1-LASFDE1 .long L$set$1 LASFDE1: .long LASFDE1-EH_frame1 .quad LFB3-. .set L$set$2,LFE3-LFB3 .quad L$set$2 .byte 0x0 .byte 0x4 .set L$set$3,LCFI0-LFB3 .long L$set$3 .byte 0xe .byte 0x10 .byte 0x86 .byte 0x2 .byte 0x4 .set L$set$4,LCFI1-LCFI0 .long L$set$4 .byte 0xd .byte 0x6 .align 3 LEFDE1: .globl _ftc.eh _ftc.eh: LSFDE3: .set L$set$5,LEFDE3-LASFDE3 .long L$set$5 LASFDE3: .long LASFDE3-EH_frame1 .quad LFB4-. .set L$set$6,LFE4-LFB4 .quad L$set$6 .byte 0x0 .byte 0x4 .set L$set$7,LCFI2-LFB4 .long L$set$7 .byte 0xe .byte 0x10 .byte 0x86 .byte 0x2 .byte 0x4 .set L$set$8,LCFI3-LCFI2 .long L$set$8 .byte 0xd .byte 0x6 .byte 0x4 .set L$set$9,LCFI5-LCFI3 .long L$set$9 .byte 0x83 .byte 0x3 .align 3 LEFDE3: .globl _main.eh _main.eh: LSFDE5: .set L$set$10,LEFDE5-LASFDE5 .long L$set$10 LASFDE5: .long LASFDE5-EH_frame1 .quad LFB5-. .set L$set$11,LFE5-LFB5 .quad L$set$11 .byte 0x0 .byte 0x4 .set L$set$12,LCFI6-LFB5 .long L$set$12 .byte 0xe .byte 0x10 .byte 0x86 .byte 0x2 .byte 0x4 .set L$set$13,LCFI7-LCFI6 .long L$set$13 .byte 0xd .byte 0x6 .align 3 LEFDE5: .subsections_via_symbols |
#include <assert.h> #include <stdio.h> /*Premiere version : main () { int i, j, n; n = 10; for (i=0, j=0; i <= n; i++){ j += 1 + (i << 1); assert(j==(i*i)); printf("%d carre == %d\n",i,j); } } /* Macintosh.local: gcc asser.c Macintosh.local: a.out Assertion failed: (j==(i*i)), function main, file asser.c, line 9. Abort trap */ /* Seconde version */ main () { int i, j, n; n = 10; for (i=0, j=0; i <= n; i++){ assert(j==(i*i)); printf("%d carre == %d\n",i,j); j += 1 + (i << 1); } } /* Macintosh.local: gcc asser.c Macintosh.local: a.out 0 carre == 0 1 carre == 1 2 carre == 4 3 carre == 9 4 carre == 16 5 carre == 25 6 carre == 36 7 carre == 49 8 carre == 64 9 carre == 81 10 carre == 100 */ |
#include <setjmp.h> #include <stdio.h> jmp_buf ebuf; /* ceci est une variable globale, mais comment l eviter ?*/ void f2(void); int main(void) { int i; printf("1 "); i = setjmp(ebuf); printf("\t ligne : %d\n", __LINE__); if(i == 0) { printf("\t ligne : %d\n", __LINE__); f2(); printf("This will not be printed."); } printf("%d \n", i); return 0; } void f2(void) { printf("2 "); printf("\t ligne : %d\n", __LINE__); longjmp(ebuf, 3); } /* 1 ligne : 13 ligne : 15 2 ligne : 27 ligne : 13 3 */ |
#include <setjmp.h> #include <stdio.h> jmp_buf ebuf, env, env2; /* ce sont des variables globales, encore ! */ void f2(void); void f1(void); int main(void) { int i; printf("1 "); i = setjmp(ebuf); printf("\t ligne : %d\n", __LINE__); if(i == 0) { printf("\t ligne : %d\n", __LINE__); i = setjmp(env); if (i) { printf("i : %d\t ligne : %d\n", i, __LINE__); return 0; } f2(); printf("This will not be printed."); } printf("%d \n", i); f1(); return 0; } void f1(void) { printf("f1 "); printf("\t ligne : %d\n", __LINE__); longjmp(env, 35); } void f2(void) { printf("2 "); printf("\t ligne : %d\n", __LINE__); longjmp(ebuf, 3); } /* JJBook : a.out 1 ligne : 13 ligne : 15 2 ligne : 36 ligne : 13 3 f1 ligne : 31 i : 35 ligne : 18 */ |
#include<stdio.h> #include<signal.h> #include<unistd.h> void sig_handler(int signo) { if (signo == SIGINT) printf("received SIGINT\n"); } int main(void) { if (signal(SIGINT, sig_handler) == SIG_ERR) printf("\ncan't catch SIGINT\nIf you get this message something is definitely wrong\n"); // A long long wait so that we can easily issue a signal to this process while(1) sleep(1); return 0; } dhcp8.ai.univ-paris8.fr: gcc sighandle.c dhcp8.ai.univ-paris8.fr: a.out ^Creceived SIGINT ^Creceived SIGINT ^Z [1]+ Stopped a.out dhcp8.ai.univ-paris8.fr: bg [1]+ a.out & dhcp8.ai.univ-paris8.fr: dhcp8.ai.univ-paris8.fr: jobs [1]+ Running a.out & dhcp8.ai.univ-paris8.fr: kill %1 dhcp8.ai.univ-paris8.fr: [1]+ Terminated: 15 a.out dhcp8.ai.univ-paris8.fr: jobs dhcp8.ai.univ-paris8.fr: |
/* signal exemple : sortie douce de SegFault */ #include <stdio.h> #include <stdlib.h> #include <signal.h> void catch(int); int main(int argc, char **argv) { int a, *ptr; signal(SIGSEGV, catch); /* intercepte SIGSEGV - SegFault */ a = *ptr; /* Qu'y-a-til |
#include <stdarg.h> /* Pour va_list */ #include <stdio.h> /* Pour printf */ void afficher (const char *format, const char *espace, ...) { /* Liste des arguments */ va_list args; /* Initialisation, à partir du dernier paramètre connu */ va_start (args,espace); /* Parcours de la chaîne de format et affichage des données */ int i; for (i=0; format[i]; i++) switch (format[i]) { case 'C' : case 'c' : printf ("%c%s",va_arg(args,int),espace); break; case 'D' : case 'd' : case 'i': printf ("%d%s",va_arg(args,int),espace); break; case 'E' : printf ("%E%s",va_arg(args,double),espace); break; case 'e' : printf ("%e%s",va_arg(args,double),espace); break; case 'F' : case 'f' : printf ("%f%s",va_arg(args,double),espace); break; case 'G' : printf ("%G%s",va_arg(args,double),espace); break; case 'g' : printf ("%g%s",va_arg(args,double),espace); break; case 'H' : printf ("%X%s",va_arg(args,int),espace); break; case 'h' : printf ("%x%s",va_arg(args,int),espace); break; case 'O' : case 'o' : printf ("%o%s",va_arg(args,int),espace); break; case 'P' : case 'p' : printf ("%p%s",va_arg(args,void*),espace); break; case 'S' : case 's' : printf ("%s%s",va_arg(args,char*),espace); break; default : ; } /* Fermeture */ va_end (args); printf("\n"); } /* Exemple d'utilisation */ int main () { afficher ("ioHefGcsp"," ",9572,9572,9572,6569.28,6569.28,6569.28,'$',"Exemple",NULL); } |
Faites une procédure de
sauvegarde de données.
Arrangez-vous
pour la lancer lorsque le programme s interrompt.
Notez que, avec signal, les passages de paramètre vont être un
peu complexe, l utilisation d un setjmp bien pensé permet
d éviter cet écueil.
Écrivez un type permettant de lier deux entiers de taille "unsigned long
long int". Écrivez une fonction qui prend deux entiers en paramètre et
renvoie un objet de votre type contenant le reste et le résultat de
la division entière du premier paramètre par le second.
En quoi
ce travail est-il différent de la fonction standard div ?
#include <stdio.h> #include <stdarg.h> int fib (int arg1, ...) { va_list liste; int v, w; if (arg1 < 0) { va_start(liste,arg1); v = va_arg(liste, int); w = va_arg(liste, int); va_end(liste); if (arg1 < -2) { return fib(arg1 + 1, v + w, v); } return v; } if (arg1) return fib(-arg1, 1, 1); return 1; } int main () { int i, n; i = 10; for (i = 0; i < 11; i++) { n = fib(i + 1); printf("Resultat de %d\t %d\n", i, n); } } /* Resultat de 0 1 Resultat de 1 1 Resultat de 2 2 Resultat de 3 3 Resultat de 4 5 Resultat de 5 8 Resultat de 6 13 Resultat de 7 21 Resultat de 8 34 Resultat de 9 55 Resultat de 10 89 */ |
#include <stdio.h> #include <stdlib.h> void sortie () { printf("This is the end\n"); } void finir () { printf("My only friend the end\n"); } void definir () { printf("Of everything that stands the end\n"); } void refinir () { printf("Of our elaborate plans the end\n"); } int main () { printf("Jim Morrisson\n\nThe end\n\n"); atexit(definir); atexit(refinir); atexit(finir); atexit(sortie); } /*Jim Morrisson The end This is the end My only friend the end Of our elaborate plans the end Of everything that stands the end */ |
Voici un programme qui permet de travailler. D abord son Makefile :
# Compilation generique par Bourdin CC=gcc SRCDIRECT=miam.c fibiter.c direct.c OBJDIRECT=$(SRCDIRECT:.c=.o) FLAGS=-Wall fool: $(OBJDIRECT) direct.h $(CC) -o $@ $^ rm fib.dat %.o: %.c $(CC) -o $@ -c $< $(CFLAGS) clean: rm *.o *~ core hop: for i in 0 1 2 3 4 5 6 7 8 9 do ./fool $i ; done |
/*direct.h*/ #include <stdio.h> #include <stdlib.h> int fibiter (int); int lire (FILE *, int); int remplir (FILE *, int); |
/* miam.c */ #include "direct.h" #define NOM "fib.dat" #define NORMAL 43 int 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); } } } |
/*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); } } 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]; } |
S il vous manque une fonction, comme celle qui calcule la suite de Fibonacci, je vous fais confiance.
Second exemple
Nous utilisons maintenant des fprintf et des fscanf, pour faire la même chose. Bien sûr le "programme" n est pas complet sans au moins le fichier main.c qui suit mais il manque d autres choses...#include <stdio.h> #include "mydef.h" #define NOM "num.dat" #define SIZE 45 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("%d |",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 */ fclose(f); 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; } v1 = ftell(f); printf("on est maintenant en %d\n",v1); fseek(f,-v1,1); fscanf(f,"%d ",&v0); printf("On y trouve %d\n", v0); fseek(f,0L,SEEK_SET); fprintf(f,"%9d ",nb); printf("remis %d au debut\n", nb); v1 = ftell(f); printf("on est encore en %d\n",v1); fseek(f,-v1,1); fscanf(f,"%d ",&v0); printf("On y trouve %d\n", v0); 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 */ |
#include <stdio.h> #include "mydef.h" #define NOM "num.dat" int 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]); // printf("les valeurs de %d a %d\n",i,j); 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); fclose(fichier); } } } |
#include<stdio.h> #include<assert.h> #include<stdlib.h> #include<time.h> #include<string.h> int main (int argc, char * * argv) { clock_t cp; int tps_init, tps_crt, dtps, n, i, j; int *veca, *vecb, *vecc, *ptr; if (argc != 2) { n = 100; } else n = (int) atoi (argv[1]); veca = (int *) malloc (n * sizeof(int)); vecb = (int *) malloc (n * sizeof(int)); vecc = (int *) malloc (n * sizeof(int)); assert(veca && vecb && vecc); printf("Temps pour %u avec bzero\t", n); tps_init = (int) clock (); for (i = 0; i < n; i++) { bzero(vecb, n << 2); vecb[i] = i - 2; } tps_crt = (int) clock (); dtps = tps_crt - tps_init; printf(" \t%d\n", dtps); printf("Temps pour %u avec memset\t", n); tps_init = (int) clock (); for (i = 0; i < n; i++) { memset(veca, 0, n << 2); veca[i] = i - 2; } tps_crt = (int) clock (); dtps = tps_crt - tps_init; printf(" \t%d\n", dtps); printf("Temps pour %u avec boucle\t", n); tps_init = (int) clock (); for (i = 0; i < n; i++) { for (j = 0, ptr = vecc; j < n; j++) *ptr++ = 0; } tps_crt = (int) clock (); dtps = tps_crt - tps_init; printf(" \t%d\n", dtps); } |
Vous connaissez plusieurs méthodes permettant de calculer la n-ième valeur de la suite de Fibonacci. Programmez-les et vérifiez laquelle est la plus rapide.
Même chose avec la valeur n,m du triangle de Pascal.
void intervertir (float * pa, float *pb) { *pa += *pb; *pb = *pa - *pb; *pa = *pa - *pb; } |
float somtf (float t[100], int nb) { /* ou t est le vecteur (surdimensionne) et nb le nombre d elements presents */ float s, *ptr; ptr = t; for (s = 0.0; nb--;) s += *ptr++; return s; } |
typedef unsigned int Uint; struct tabf { Uint nb; float * t; } ; typedef struct tabf tabf; |
tabf remplir (Uint nb) { float v, w, * ptr; int i; tabf t; t.t = (float *) malloc (nb * sizeof (float)); assert(t.t); t.nb = nb; v = 1.0; w = 0.215; ptr = t.t; for (i=0; i < nb; i++) { *ptr++ = v; v += w; if (v > 2.0) w -= 0.3; if (v < 1.0) w += 0.3; } return t; } |
Une liste est, soit la liste vide (notée NULL ou (liste) 0), soit la construction d un objet et d une liste.
Voir l exemple de liste donné dans la partie sur la gestion du temps.
Deuxième exemple, une structure de liste et une fonction pour créer la dite liste.struct cell { int n; float val; struct cell * nxt; }; typedef struct cell cell_t; typedef struct cell * liste; liste cons (liste l, int v, float x) { liste new; new = (liste) malloc (sizeof(cell_t)); new->n = v; new->val = x; new->nxt = l; return new; } /* creer la liste avec des valeurs fibonacciennes */ liste creerliste (int nb) { int v, w, x; int * pt; float a, b; liste l, crt; l = (liste) 0; v = 1; a = 1.0; w = 1; b = (float) w / v;; l = cons (l, v, a); l = cons (l, w, b); nb -= 2; while (nb--) { x = (v + w); v = w; w = x; l = cons(l, x, (float) x / v); } return l; } |
Comment la corriger ?
double newton (double x) { double xi; if (x < 0.0) return DBL_MIN; if (x > 0.0) xi = x / 2.0; else xi = 0.005; while (x != xi * xi) { xi = xi / 2.0 + x / (xi * 2.0); printf("%f %f\n", x, xi); } return xi; } |
Nous donnons maintenant une structure et une fonction de remplissage d un arbre.
Pour cela, il faut utiliser le tableau tel que vu précédemment, nous
ne redonnons pas les structures et fonctions correspondantes.
Commençons par un type et une fonction qui construit un vecteur.
typedef unsigned int Uint; struct tabf { Uint nb; float * t; } ; typedef struct tabf tabf; |
tabf remplir (Uint nb) { float v, w, * ptr; int i; tabf t; t.t = (float *) malloc (nb * sizeof (float)); t.nb = nb; v = 1.0; w = 0.215; ptr = t.t; for (i=0; i < nb; i++) { *ptr++ = v; v += w; if (v > 2.0) w -= 0.3; if (v < 1.0) w += 0.3; } return t; } |
#define NBF 5 struct noeud { int nb; float val; struct noeud * nxt [NBF]; } ; typedef struct noeud noeud; typedef struct noeud * arbre; |
arbre faitarbre(tabf t) { int i, num; float * ptr; arbre a; a = NULL; num = 0; ptr = t.t + t.nb - 1; while (ptr >= t.t) { a = inserenoeud(a, num, *ptr); num++; ptr--; } return a; } |
arbre inserenoeud (arbre a, int num, float v) { int i, j; arbre b; if (! a) { a = malloc (sizeof (noeud)); for (i = 0; i < NBF; i++) a->nxt[i] = NULL; a->nb = num; a->val = v; return a; } for (i = 0; i < NBF; i++) { if (! (a->nxt[i])) { b = malloc (sizeof (noeud)); for (j = 0; j < NBF; j++) b->nxt[j] = NULL; b->nb = num; b->val = v; a->nxt[i] = b; return a; } } i = rand() % NBF; a->nxt[i] = inserenoeud(a->nxt[i], num, v); return a; } |
uint yest (int n, arbre a) { uint nbf, i, k; if (! a) return (uint) 0; if (n == a->nb) return (uint) 1; for (i = 0; i < NBN ; i++) if (yest (n, a->fils[i])) return (uint) 1; return (uint) 0; } |
D abord les structures les plus simples possibles : la matrice.
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> typedef short unsigned Shu; struct graphe { int nbs; Shu * tab; } ; typedef struct graphe graphe; |
graphe creegraphe (int nbs) { Shu i, j, max, num; float v, taux; graphe g; g.nbs = nbs; max = nbs * nbs; taux = 25.0; num = nbs / 10; while (num > 1) { num /= 5; taux /= 3.0; } taux /= 100.0; printf("taux %g\n", taux); g.tab = (Shu *) malloc (max * sizeof(Shu)); memset(g.tab, 0, max); srand(time(NULL)); for (num = 0, i = 0; i < nbs; i++) for (j = 0; j < nbs; j++) { v = (float) rand () / RAND_MAX; g.tab[num++] = v < taux ? 1 : 0; } return g; } |
void voirgraf (graphe g) { Shu i, j, nb, num; nb = g.nbs; printf("Graphe\n"); for (i = 0, num = 0; i < nb; i++) { for (j = 0; j < nb; j++) printf("%c ", g.tab[num++]? 1 : ); printf("\n"); } } |
Shu nbnonnuls (graphe g) { Shu i, j, nb, num, total; nb = g.nbs; total = 0; printf("Graphe\n"); for (i = 0, num = 0; i < nb; i++) { for (j = 0; j < nb; j++) total += g.tab[num++]; } return total; } int main () { graphe g; int nb; Shu to; nb = 10; g = creegraphe (nb); voirgraf(g); to = nbnonnuls(g); printf("Pour %d il y a %d cases non vides\n soit %f %% \n", nb, to, (to * 100.0)/(nb * nb)); nb = 50; g = creegraphe (nb); to = nbnonnuls(g); printf("Pour %d il y a %d cases non vides\n soit %f %% \n", nb, to, (to * 100.0)/(nb * nb)); nb = 500; g = creegraphe (nb); to = nbnonnuls(g); printf("Pour %d il y a %d cases non vides\n soit %f %% \n", nb, to, (to * 100.0)/(nb * nb)); } /*taux 0.25 Graphe 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Graphe Pour 10 il y a 25 cases non vides soit 25.000000 % taux 0.0833333 Graphe Pour 50 il y a 212 cases non vides soit 8.480000 % taux 0.00925926 Graphe Pour 500 il y a 2333 cases non vides soit 0.933200 % */ |
int chemin (Shu dep, Shu arr, graphe g, Shu flag[]) { Shu new; ligne l; if (dep == arr) return 1; if (flag[dep]) return 0; l = g.tab[dep]; flag[dep] = 1; while (l) { new = l->y; if (! flag[new]) if (chemin(new, arr, g, flag)) return 1; l = l->nxt; } return 0; } int existe_chemin (Shu dep, Shu arr, graphe g) { Shu * flag; flag = (Shu *) malloc (g.nbs * sizeof(Shu)); memset(flag, 0, (size_t) (g.nbs << 1)); return chemin (dep, arr, g, flag); } |
Un brin est l extrémité d une arête, avec le signe moins au départ et
le signe plus à l arrivée. L arête 5 qui va du sommet 3 au sommet 7
est donc composée de deux brins, le -5 lié au sommet 3 et le +5 lié au
sommet 7.
Il faut, pour concentrer davantage les données, mettre en place une
structure avec trois vecteurs :
Puisque nous pouvons travailler avec des pointeurs que ne travaillons-nous avec des pointeurs de fonction ?
Voici d abord un exemple de définition :
typedef void (* ptrfct) (); extern void fcta (); extern void fctb (); extern void g (void (*) ()); |
#include "ptr.h" void fcta () { printf(" a "); } void fctb () { printf(" b "); } void g (void (* fct) ()) { printf("g appelle :"); fct(); printf("\n"); } void fcttest () { g(fcta); g(fctb); } int menu () { int n; n = 0; while (!n) { printf("Choisissez entre la fonction a (tapez 1)\n"); printf("et la fonction b (tapez 2) :\n"); scanf("%d",&n); if (n==1 || n==2) break; } return n-1; } void faire () { int n; ptrfct tf [] = {fcta, fctb}; n = menu(); tf[n](); } |
void Mouse(int button, int state, int x, int y){ switch(button){ case GLUT_LEFT_BUTTON: break; case GLUT_MIDDLE_BUTTON: break; case GLUT_RIGHT_BUTTON: break; } glutPostRedisplay(); } |
int main(int argc, char **argv) { if (argc<2) { fprintf(stderr, "Usage : palette nom_de_fichier\n"); exit(0); } glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowSize(640,480); glutInitWindowPosition(0, 0); glutCreateWindow("VPUP8"); Init(argv[1]); glutCreateMenu(menuFunc); glutAddMenuEntry("Informations", 0); glutAddMenuEntry("Ouvrir", 3); glutAddMenuEntry("Sauver", 4); glutAddMenuEntry("Noir et Blanc", 6); glutAddMenuEntry("Quit", 5); glutAttachMenu(GLUT_LEFT_BUTTON); glutDisplayFunc(Display); glutReshapeFunc(Reshape); glutKeyboardFunc(Keyboard); glutMouseFunc(Mouse); glutMainLoop(); return 1; } |
On crée la C-LUT en s'arrangeant pour que toute couleur déjà rencontrée ne soit pas une nouvelle entrée.
Il ne reste plus, alors, qu'à être capables d'afficher une image à partir de : sa C-LUT et son vecteur.
Pour améliorer le procédé, on peut considérer que si une couleur proche d'une couleur déjà présente dans la C-LUT c'est celle-ci qui sera utilisée pour ce pixel.
Dernière mise à jour : 11/1/2020, 13h