Rmi Nollet et Jean-Jacques BOURDIN
La semaine du 5 avril est consacre vos projets.
Donc pas de cours, mais nous rpondrons sans doute aux mails.
Le 13 avril vous prsentez vos projets. Peut-tre le 14 aussi, si ce n'est pas fini.
Les partiels auront lieu le 20 avril, salle B104 15h, et le 11 mai 15h.
Vous ne pouvez pas participer aux deux partiels.
Bibliographie sommaire
int square (int n) { return n * n; } |
This function has to be linked to another one, the most important
one: the main function.
Cette fonction doit tre accompagne de celle qui la commande, la
grande fonction, la principale, main.
int square (int n) { return n * n; } int main () { printf("le carre de 3 est %d\n",square(2)); } |
otake: cat cours190119.c int square (int n) { return n * n; } main () { printf("le carre de 3 est %d\n",square(2)); } otake: gcc cours190119.c otake: ls -l -rw-r--r-- 1 jj users 103 Jan 18 18:06 cours190119.c -rwxr-xr-x 1 jj users 12264 Jan 18 18:07 a.out |
otake: a.out le carre de 3 est 4 |
You may correct a semantic error.
Vous pouvez corriger afin d'arriver une phrase plus logique.
/* which one is bigger? */ int maxi2 (int a, int b) { if ( a < b ) { return b; } else { return a; } } |
Vous devez crire :
Be careful
Every time one wants to use the recursivity, one has to follow the
following steps:
Attention :
Toute formulation rcursive doit suivre les tapes suivantes :som(n) = 0 + 1 + 2 + 3 + ... + (n-1) + n som(n-1) = 0 + 1 + 2 + 3 + ... + (n-1)Therefore
int som (int n) { if ( n < 1 ) { return 0; } else { return n + som (n-1); } } |
Vous devez crire :
int sec4_2_aux (int a, int b, int c, int d, int min) { if (a == min) return sec3(b, c, d); if (b == min) return sec3(a, c, d); if (c == min) return sec3(a, b, d); return sec3(a, b, c); } int sec4_2 (int a, int b, int c, int d) { return sec4_2_aux(a, b, c, d,ltt4 (a, b, c, d)); } |
You should know about Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, 21...
A formulation can be given as:
La suite de Fibonacci est connue pour sa forte progression. Les premires valeurs sont calcules par :
f(0) = 1 f(1) = 1 f(n) = f(n-1) + f(n-2)
Just write the program and test it.
Vous pouvez maintenant tester cette suite clbre.Il faut la programmer et essayer diffrentes valeurs. On doit obtenir :
1 1 2 3 5 8 13 21 34 55 89 144
A function is tail recursive is the recursive call is the last thing to be evaluated by the function.
On parle de rcursivit terminale lorsque l'appel rcursif est la dernire action de la fonction, c'est--dire lorsque le rsultat obtenu par cet appel est le rsultat de la fonction appelante.
som (int n) { if (n == 0) { return 0; } else { return n + som (n-1); } } |
int somrec (int n) { return somrec_aux (n,0); } int somrec_aux (int n, int s) { if (n <= 0) { return s; } else { return somrec_aux (n-1, s+n); } } |
To obtain a tail-recursive function, one has to add an accumulator
argument which store the computation and tends to the solution.
Voici un exemple de fonction main pour tester somrec :
main () { printf("som(%d)==\t%d\n",4,somrec(4)); printf("som(%d)==\t%d\n",5,somrec(5)); printf("som(%d)==\t%d\n",6,somrec(6)); } |
m(a,0) = 0 m(a,b) = b + m(a-1,b)This expression is an addition so the neutral element is 0. The accumulator starts then at 0.
M(a,b,som) = M(a-1,b,som+b)One can see that the third argument starts with 0 than 0+b, then 0+b+b and so on.
int mulrecter (int a, int b) { return mulrecter_aux (a, b, 0); } int mulrecter_aux (int a, int b, int som) { if (a == 0) { return som; } else { return mulrecter_aux (a-1, b, som + b); } } |
A variable is a tuple of three elements: <name, type, address>
One needs to declare the variables ASAP in the function. Then they can
be set by the operator = (pronounce "receive").
Une variable est un triplet : (nom, type, espace mmoire).
La taille de l'espace mmoire est dfinie par le type comme vu
ci-dessus. On peut modifier le contenu de l'espace mmoire par
l'opration d'affectation.
/* les autres fonctions ne sont pas cites */ main () { int max; /* sert plusieurs fois */ max = 10; printf("%d \t=> \t %d\n",max, serie(max)); max = 50; printf("%d \t=> \t %d\n",max, serie(max)); max = 100; printf("%d \t=> \t %d\n",max, serie(max)); max = 500; printf("%d \t=> \t %d\n",max, serie(max)); max = 1000; printf("%d \t=> \t %d\n",max, serie(max)); } |
Here after you'll find examples of expressions:
On parlera d'expression pour dcrire un ensemble de formules que l'on peut valuer base
d'oprateurs "bien construits" et excutables. Exemples :
3 + 5 * 6 (3 + 5) * 6 6 * 9 / 5 |
3 + 3 + * 6 6 9 5 |
type | taille | genre |
void | 0 | vide |
char | ≥1 | caractre |
short | ≥2 | entier " court " |
long (ou int) | ≥4 | entier "long" |
float | ≥4 | nombre virgule |
double | ≥8 | nombre virgule, plus prcis |
long long int | ≥8 | entier "trs long " |
long double | ≥16 | nombre virgule prcis |
3/2 donne 1 ( 3 * 2.0 ) / 5 donne 1.2 |
float inverse (int n) { if (n == 0.0) { return 0.0; } else { return (1.0 / (float) n); } } int serie (int n) { if (n == 0) { return 0; } else { return inverse(n) + serie (n-1); } } main () { printf("%d \t=> \t %d\n",10, serie(10)); printf("%d \t=> \t %d\n",50, serie(50)); printf("%d \t=> \t %d\n",100, serie(100)); printf("%d \t=> \t %d\n",1000, serie(1000)); } /* ------------------ Essai ----------------- otake: a.out 10 => 1 50 => 1 100 => 1 500 => 1 1000 => 1 ---------------------------------------------*/ |
A statement is a ";", or an expression followed by an
instruction (therefore with a ";" at
the end).
Une instruction est soit ";", soit une expression suivie
d'une instruction (donc aussi de
";")
A statement may also be presented as a { followed by a } and
containing only valable statements.
Une instruction peut aussi tre prsente comme un ensemble
d'instructions entoures par des accolades. On parle alors de bloc.
Operator | Associativity | Arity |
() [] -> . | GD | - |
! ~ ++ -- + - | DG | 1 |
* & (type) sizeof | DG | 1 |
* / % | GD | 2 |
+ - | GD | 2 |
<< >> | GD | 2 |
< <= > >= | GD | 2 |
== != | GD | 2 |
& | GD | 2 |
^ | GD | 2 |
| | GD | 2 |
&& | GD | 2 |
|| | GD | 2 |
? : | DG | 3 |
= += -= *= /= %= <<= >>= &= ^= |= | DG | 2 |
, | GD | 2 |
int fibifif (int n) { if (n == 0) { return 1; } else if (n == 1) { return 1; } else { return fibifif(n-1) + fibifif(n-2); } } } |
int fibsw (int n) { switch (n) { case 0: return 1; case 1: return 1; default: return fibsw(n - 1); } } |
void lecase (int n) { switch (n) { case 0: printf("C est nul\n"); case 1: printf("C est unique\n"); case 2: printf("La paire\n"); case 3: printf("La trinite\n"); } printf("\n"); } int main(){ lecase(5); lecase(3); lecase(1); lecase(2); lecase(0); return 0; } |
neige: a.out La trinite C est unique La paire La trinite La paire La trinite C est nul C est unique La paire La trinite neige: |
int somw (int n) { int i, som; i = 0; som = 0; while (i < n) { som = som + i; i = i + 1; } return som; } |
int somdo (int n) { int i, som; i = 0; som = 0; do { som = som + i; i = i + 1; } while (i < n); return som; } |
int somf (int n) { int i, som; i = 0; som = 0; for (/* void_1*/ ; i < n; /* void_2*/ ) { som = som + i; i = i + 1; } return som; } |
int somf2 (int n) { int i, som; /*void_1*/ som = 0; for ( i = 0 ; i < n; i = i + 1 ) { som = som + i; /* void_2 */ } return som; } |
int sombr (int n) { int i, s; i = 0; s = 0; while (1) { s = s + i; i = i + 1; if (i > n) { break; } } return s; } |
int valeur (int n) { int s; s = 0; switch (n) { case 0: s = 0; case 1: s = s + 1; case 2: s = s + 2; case 3: s = s + 3; default: s = s + n; } return s; } |
valeur (2); valeur (3); valeur (1); valeur (5);Autre version, sans doute plus claire :
int valeur (int n) { int s; s = 0; switch (n) { case 0: s = 0; break; case 1: s = s + 1; break; case 2: s = s + 2; break; case 3: s = s + 3; break; default: s = s + n; break; } return s; } |
int fibstrange (int n) { int i, prec, ante; prec = 1; ante = 1; i = 0; while (i <= n) { i = i + 1; if (i < 3) { continue; } prec = prec + ante; ante = prec - ante; } return prec; } |
#include <stdio.h> int impair (int n) { int i, res; res = 0; for (i = 0; i < n; i = i + 2) ; return i - n; } int somp (int n) { int s, i; s = 0; for (i=0; i <= n; i = i + 1) { if (impair(i)) { printf("%d est impair\n",i); continue; } s = s + i; } return s; } int main () { int a; a = 5; printf("Somme des pairs jusqu a %d : \t %d\n", a, somp(a)); a = 6; printf("Somme des pairs jusqu a %d : \t %d\n", a, somp(a)); a = 7; printf("Somme des pairs jusqu a %d : \t %d\n", a, somp(a)); } |
/* Just let's have mo'fun */ #include <stdlib.h> #include <stdio.h> int funct (int n) { int a, b, c; a = 1; b = 1; c = 2; if (c > n) { return a; } cas_general: a = a + b; b = a - b; c = c + 1; if (c <= n) { goto cas_general; } return a; } int fonct (int n) { int a, b; a = 1; b = 1; do { a = a + b; b = a - b; n = n - 1; if (1 > n) { goto cas_sortie; } } while(1); cas_sortie: return b; } int finct (int n) { int a, b, c; if (n > 23) { a = -1; goto la_sortie; } a = 1; b = 1; c = 2; cas_retour: if (c > n) goto la_sortie; a = a + b; b = a - b; c = c + 1; goto cas_retour; la_sortie: return a; } main () { int i; for (i = 0; i < 10; i = i + 1) { printf("Pour %d on a \t%d\t",i,funct(i)); printf("et\t %d ",fonct(i)); printf("et\t %d\n",finct(i)); } } |
Pour 0 on a 1 et 1 et 1 Pour 1 on a 1 et 1 et 1 Pour 2 on a 2 et 2 et 2 Pour 3 on a 3 et 3 et 3 Pour 4 on a 5 et 5 et 5 Pour 5 on a 8 et 8 et 8 Pour 6 on a 13 et 13 et 13 Pour 7 on a 21 et 21 et 21 Pour 8 on a 34 et 34 et 34 Pour 9 on a 55 et 55 et 55 |
Other examples
#include <stdio.h> float racine (float x) { float y, pas; pas = 0.0001; y = 0.0; // initialisation while ( 1 ) { if ( y * y >= x) { break; } y += pas; //incrmentation } /* y = 0.0; // initialisation while ( y * y < x) { // test // printf(" %f ", y); y += pas; //incrmentation } for (y = 0.0; y * y < x; y += pas) { printf(" %f ", y); } */ printf("\n"); return y; } int impair (int n) { while (n > 1) { n -= 2; } if (n==1) { return 1; } return 0; } int sommepairs (int n) { int i, somp; somp = 0; for (i = 0; i ≤ n; i++) { if (impair(i)) { continue; } somp = somp + i; } return somp; } int sommepairsgt (int n) { int i, somp; somp = 0; i = 0; debut_boucle: if (impair(i)) { goto incrementation; } somp += i; incrementation: i += 1; if (i ≤ n) { goto debut_boucle; } return somp; } int main () { float val, rac; int a, b, c; val = 2.0; rac = racine (val); printf("la racine de %f est %f\n", val, rac); for (a = 0; a < 10; a++) { b = sommepairs(a); c = sommepairsgt(a); printf("jusqu a %d on a %d ou %d\n", a, b, c); } } |
While lots of programmers don't apply that rule, lots of programmers spend more time than necessary on debugging.
Si cette rgle n'est pas applique, ne vous tonnez pas de passer plus de temps en debugging que les autres...
/* On va essayer de trouver deux exemples d enumeration */ enum sema {lundi, mardi, mercredi, jeudi, vendredi, samedi, dimanche}; enum week {sunday, monday, tuesday, wednesday, thursday, friday, saturday}; void affiche_day (enum week d) { switch(d) { case sunday: printf("sunday"); break; case monday: printf("monday"); break; case tuesday: printf("tuesday"); break; case wednesday: printf("wednesday"); break; case thursday: printf("thursday"); break; case friday: printf("friday"); break; case saturday: printf("saturday"); break; } } void affiche_jour (enum sema j) { switch(j) { case lundi: printf("lundi"); break; case mardi: printf("mardi"); break; case mercredi: printf("mercredi"); break; case jeudi: printf("jeudi"); break; case vendredi: printf("vendredi"); break; case samedi: printf("samedi"); break; case dimanche: printf("dimanche"); break; } } main () { enum sema jour; enum week day; for (jour = lundi; jour <= dimanche; jour++) { day = (enum day) jour; affiche_day(day); printf(" \t = \t"); affiche_jour(jour); printf("\n"); } } /* sunday = lundi monday = mardi tuesday = mercredi wednesday = jeudi thursday = vendredi friday = samedi saturday = dimanche */ |
#include <stdio.h> enum boole {vrai, faux}; enum boole non (enum boole v) { switch (v) { case vrai : return faux; case faux : return vrai; } } enum boole et (enum boole v, enum boole w) { if (v == faux) return faux; if (w == faux) return faux; return vrai; } enum boole ou (enum boole v, enum boole w) { if (v == vrai) return vrai; if (w == vrai) return vrai; return faux; } void afficheb (enum boole v) { if (v == vrai) printf("vrai"); else printf("faux"); printf(" "); } int main () { enum boole a, b, c, d, e, f; printf(" a\t b\t c\t et\t ou\t b+1\n"); f = 0; for (a = vrai; a ≤ faux; a = a + 1) { c = non (a); for (b = vrai; b ≤ faux; b = b + 1) { d = et (a, b); e = ou (a, b); f = f + 1; printf("%2d\t %2d\t %2d\t %2d\t %2d\t %2d\t \n",a, b, c, d, e, f); } } f = 0; printf("\n a\t b\t c\t et\t ou\t b+1\n"); for (a = vrai; a ≤ faux; a = a + 1) { c = non (a); for (b = vrai; b ≤ faux; b = b + 1) { d = et (a, b); e = ou (a, b); f = f + 1; afficheb(a); afficheb(b); afficheb(c); afficheb(d); afficheb(e); afficheb(f); printf("\n"); } } printf(" Taille de cet enum : %d\n", (int) sizeof(enum boole)); } |
int somvec (int n) { int t [100]; int i; t [0] = 0; if (n > 99) { return -1; } for (i=1; i <= n; i++) { t[i] = t[i-1] + i; } return t[n]; } int main () { int v, res; v = 5; res = somvec(v); printf("som(%d)=%d\n",v,res); v = 6; res = somvec(v); printf("som(%d)=%d\n",v,res); v = 7; res = somvec(v); printf("som(%d)=%d\n",v,res); } |
#include<stdio.h> void remplir (float vec [100], int nb) { float x, eps; int i; if (nb >= 100) return; x = 1.5; eps = 0.173; for (i = 0; i < nb; i = i + 1) { vec [i] = x; x = x + eps; if (x > 2.0) eps = 0.01 - eps; if (x < 0.5) eps = 0.015 - eps; } } void voirvec (float vec [100], int nb) { int i; if (nb >= 100) return; for (i = 0; i < nb; i = i + 1) { printf("vec[%3d] == %f\n",i, vec [i]); } } int main () { int n; float vec [100]; n = 20; remplir(vec, n); voirvec(vec, n); } |
vec[ 0] == 1.500000 vec[ 1] == 1.673000 vec[ 2] == 1.846000 vec[ 3] == 2.019000 vec[ 4] == 1.856000 vec[ 5] == 1.693000 vec[ 6] == 1.530000 vec[ 7] == 1.367000 vec[ 8] == 1.204000 vec[ 9] == 1.041000 vec[ 10] == 0.878000 vec[ 11] == 0.715000 vec[ 12] == 0.552000 vec[ 13] == 0.389000 vec[ 14] == 0.567000 vec[ 15] == 0.745000 vec[ 16] == 0.923000 vec[ 17] == 1.101000 vec[ 18] == 1.279000 vec[ 19] == 1.457000 |
Another function, with integers this time.
Autre fonction de remplissage d'un vecteur, d'entiers cette fois.
void remplirv (int nb, int vec[100]) { int crt, pre, new, i; crt = 1; pre = 1; vec[0]=pre; vec[1]=crt; for (i=2; i <= n; i = 1 + i) { new = (crt + pre) % 23; // reste de la division vec[i] = new; pre = crt; crt = new; } } |
Refaire tous les exercices itratifs en remplissant un vecteur au fur et mesure et en utilisant les valeurs dj dans le vecteur pour calculer les nouvelles.
Coninuez avec :
vecteur initial : [8, 13, 21, 11, 9, 20, 6, 3, 9, 12]
Vecteur final : [21, 20, 13, 12, 11, 9, 9, 8, 6, 3]
/* jjb */ void replaceminparmaj (int nbc, char txt [1000]) { int i, diff; if (nbc > 999) { printf("\n\ntrop de texte\n\n"); return; } for (i = 0; i < nbc; i++) { diff = txt[i] - 'a'; if (diff >= 0) { if (diff < 26) { txt[i] = (char) ('A' + diff); } } } } void affitxt (int nbc, char t [1000]) { int i; for (i= 0; i < nbc; i++) { printf("%c",t[i]); } printf("\n"); } void remplirtxt (int nbc, char t [1000]) { int i; for (i=0; i < 50; i++) { t[i] = (char) 'a' + (i % 26); } for (i=50; i < 60; i++) { t[i] = ' '; } for (i=60; i < 110; i++) { t[i] = (char) 'A' + (i % 26); } for (i=110; i < nbc; i++) { t[i] = ' '; } } /* on peut utiliser ce remplissage aussi */ int remplirchaine(char ch [1000]) { ch [0] = 'J'; ch [1] = 'e'; ch [2] = ' '; ch [3] = 'F'; ch [4] = 'a'; ch [5] = 'i'; ch [6] = 's'; ch [7] = ' '; ch [8] = 'S'; ch [9] = 'o'; ch [10] = 'u'; ch [11] = 'v'; ch [12] = 'e'; ch [13] = 'n'; ch [14] = 't'; ch [15] = ' '; ch [16] = '\0'; return 16; } int main () { int nbc; char t [1000]; nbc = 120; remplirtxt(nbc,t); affitxt(nbc, t); replaceminparmaj(nbc, t); affitxt(nbc, t); nbc = remplirchaine(t); affitxt(nbc, t); replaceminparmaj(nbc, t); affitxt(nbc, t); } } |
Just try it.
Il ne reste plus qu' essayer :
neige: gcc ex16.c neige: a.out abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF Je Fais Souvent JE FAIS SOUVENT |
As one might see, you always associate the number of elements of a
vector to the vector itself when it is passed as argument.
Remarquez bien que quand on veut transmettre un vecteur comme argument
il est trs important de transmettre aussi le nombre d'lments
utiliss de ce vecteur.
void remplirc (int nbc, char vc [1000]) { int i, j, k; char c; c = 'a'; j = 3; k = 1; for (i = 0; i < nbc; i = i + 1) { vc[i] = c ; c = c + j; if (c > 'z') { c = ' '; } else { if (c < 'a') { c = 'a' + k; k = k + 1; } } if (k > 10) { k = 2; } } } void affichechars (int nbc, char vc [1000]) { int i; printf(" Les caracteres sont\n"); for (i = 0; i < nbc; i = i + 1) { printf ("%c",vc[i]); } printf("\n"); } |
We'll need typedef to help us understand.
Nous rajoutons ici la commande "typedef" qui permet de dfinir
un nouveau type donnes partir des types dj connus.
typedef float tablef [100];
Et, au lieu d'crire partout float t [100] on crira
tablef t.
A table is only a vector of vectors.
Un tableau deux dimensions est simplement un vecteur de vecteurs.
exemple :
Example
Nous allons travailler avec des tableaux d'altitude. Sur une grande
carte, carre, nous donnons l'altitude de chacune des cases,
c'est--dire l'altitude moyenne pour toute la surface
qu'elle reprsente sur le terrain.
Pour gnrer le tableau, il faut utiliser cette fonction en donnant
comme paramtres, le tableau, le nombre de colonnes et le nombre de
lignes :
/* exo sur les altitudes JJ'2012 */ typedef float table [100] [100]; /* desormais table est un synonyme de float [100][100]*/ void remplirt (table t, int sx, int sy) { int x, y, sxy; float v, eps, add, pas; pas = 0.5; v = pas; add = 5.0; sxy = sx * sx + sy * sy; eps = 1.0 / (float) (sxy); for (x = 0; x < sx; x += 1) { for (y = 0; y < x; y += 1) { t[x][y] = (float) (x * x - y * y + add) * eps; } for (y = x; y < sy; y += 1) { t[x][y] = (float) ( y * y - x * x + add) * eps; } add += v; if (add > 10.0) v = - pas; if (add < 0.1) v = pas; } } |
/* exo sur les tableaux a trois dimensions */ typedef float table3 [50] [50] [50]; void remplirt (table3 t, int sx, int sy, int sz) { int x, y, sxy, z; float v, eps, add, pas; pas = 0.5; v = pas; add = 5.0; sxy = sx * sx + sy * sy; eps = 1.0 / (float) (sxy); for (x = 0; x < sx; x += 1) { for (y = 0; y < x; y += 1) { for (z = 0; z < sz; z += 1) { t[x][y][z] = (float) (x * x - y * y + z + add) * eps; } } for (y = x; y < sy; y += 1) { for (z = 0; z < sz; z += 1) { t[x][y][z] = (float) ( y * y - x * x + z + add) * eps; } } add += v; if (add > 10.0) v = - pas; if (add < 0.1) v = pas; } } |
struct duo { int quot; int rest; } ; typedef struct duo duo; |
duo division (int a, int b) { duo d; d.quot = 0; d.rest = 0; if (b == 0) return d; while (a >= b) { a = a - b; d.quot = d.quot + 1; } d.rest = a; return d; } |
int main () { duo res; int a, b; res = division(a,b); printf(" when dividing %d by %d, one gets a result of %d with a reminder of %d\n", a, b, res.quot, res.rest); } |
All the type definitions are to be placed at the start of the file, in the "head" of the file.
On place toujours la dfinition en tte de fichier
Vous trouverez ci-dessous une dclaration permettant de systmatiser
les tableaux d'altitudes, avec non seulement les valeurs, mais aussi
les largeurs et hauteurs de la table.
Example:
Nous mettons en place une structure de vecteur de nombres entiers.
struct vecint { int nbele; int vec[100]; }; typedef struct vecint vecint_t; |
vecint_t remplirv (int nb) { int crt, pre, new, i; vecint_t w; crt = 1; pre = 1; w.vec[0]=pre; w.vec[1]=crt; for (i=2; i <= nb; i = 1 + i) { new = (crt + pre) % 23; // reste de la division w.vec[i] = new; pre = crt; crt = new; } w.nbele = nb; return w; } |
Refaire quelques exercices de vecteurs d'entiers avec cette structure.
New example:
struct table_alt { int larg; int haut; float t[100][100]; }; typedef struct table_alt table_alt_t; |
Reprendre quelques exercices avec ces tableaux et les crire en utilisant la structure ad hoc.
table_alt_t remplirt (int sx, int sy) { int x, y, sxy; float v, eps, add, pas; table_alt_t tt; tt.larg = sx; tt.haut = sy; pas = 0.5; v = pas; add = 5.0; sxy = sx * sx + sy * sy; eps = 1.0 / (float) (sxy); for (x = 0; x < sx; x += 1) { for (y = 0; y < x; y += 1) { tt.t[x][y] = (float) (x * x - y * y + add) * eps; } for (y = x; y < sy; y += 1) { tt.t[x][y] = (float) ( y * y - x * x + add) * eps; } add += v; if (add > 10.0) v = - pas; if (add < 0.1) v = pas; } return tt; /* ici on doit renvoyer la structure */ } |
x == y * y
If x≥0 then 0≤ y <x+ 1.
Commenons
par cette constatation : si ce nombre, x, est positif ou nul
alors la racine est comprise entre 0 et x+1, toujours.
Let's call inf and sup these values (0 and
x+1). Let's call med the average of them. it is easy to find
if y is greater than med or not. If y>med then y belongs to
]med,sup], if not, y belongs to [inf, med]. One just has to set one of
the two values inf or sup and carry on, and on, and on...
When does it stop? When the value is close enough to the square
root. Close enough is when the difference is smaller than a given value.
Mais entre ces deux valeurs, inf et sup, il y en a
beaucoup. Coupons par le
milieu, mil. Comment savoir si la racine est plus grande ou
plus petite que mil ? Et si elle est plus petite, ne
pouvons-nous pas rduire l'intervalle de recherche ? De mme si
elle est plus grande.
Vous pouvez faire tourner longtemps cet algorithme, mais attention,
vous n'avez pas besoin d'une infinit de chiffres, il faut donc vous
arrter quand la prcision requise est acquise !
Write this function square root.
Faites une fonction qui calcule ainsi la racine carre d'un nombre positif virgule.
As seen in class a structure for complex numbers can be:
struct complex { float real; float imag; }; typedef struct complex complex; |
struct complex mulc (struct complex a, struct complex b) { struct complex res; res.real = a.real + b.real; res.imag = b.imag + a.imag; return res; } |
Donnez une fonction qui permet de comparer en grandeur deux nombres complexes (on compare en fait leur module).
If we add this definition to bring a vector of complex numbers:
struct vecc { int nbe; complex tab [100]; }; typedef struct vecc vecc_t ;this is a function to create such a vector:
/* pour travailler les structures */ vecc_t remplirc (int nbc) { int i; vecc_t t; float x, y; t.nbe = nbc; x = 4.0; y = nbc / 10.0 + 0.1; for (i = 0; i < nbc; i++) { t.tab[i].real = x; t.tab[i].imag = y; x = x + 0.1; y = y - 0.1; } return t; } void affic (vecc_t t) { int i; printf("Voici les %d nombres complexes\n", t.nbe); for (i= 0; i < t.nbe; i++) { printf("(%6.3f,%6.3f) ", t.tab[i].real, t.tab[i].imag); } printf("\n"); } int main () { vecc_t ta; int n; n = 10; ta = remplirc(n); affic (ta); ta.tab[2] = addc(ta.tab[0],ta.tab[1]); ta.tab[3] = multc(ta.tab[0],ta.tab[1]); affic (ta); } |
/* pour s amuser avec des unions */ typedef unsigned short ushort; typedef unsigned long ulong; union etrange { ushort sh; ulong lg; char c; } ; typedef union etrange strange_t; void voir (strange_t s) { printf("short %d\t long %d\t char %d\t car %c \n", s.sh, s.lg, (int) s.c, s.c); } int main () { strange_t v; v.lg = 1024; voir (v); v.lg = 1024 * 1024; voir (v); for (v.lg = 1; v.lg < 128; v.lg++) voir (v); } /* short 1024 long 1024 char 0 car short 0 long 1048576 char 0 car short 1 long 1 char 1 car short 2 long 2 char 2 car short 3 long 3 char 3 car short 4 long 4 char 4 car short 5 long 5 char 5 car short 6 long 6 char 6 car short 7 long 7 char 7 car short 8 long 8 char 8 car short 9 long 9 char 9 car short 10 long 10 char 10 car short 127 long 127 char 127 car La suite, vous la verrez en faisant tourner le programme ! */ |
Nous allons maintenant crer plusieurs fichiers et les compiler
sparment.
Le premier fichier contient les prototypes des fonctions. Il
s'agit du fichier "fac.h":
/* les prototypes des fonctions */ int fac (int); int fac_acc (int, int); void affiche (int, int); |
Ensuite nous avons un fichier qui s'occupe des entres sorties, le fichier "io.c":
#include "fac.h" void affiche (int a, int b) { printf("Vous avez donne \t%d\n",a); printf("Sa factorielle est \t%d\n",b); } |
Le fichier suivant contient la fonction du
calcul de la factorielle, c'est le fichier "fac.c":
#include "fac.h" /* le calcul de la fonction factorielle */ int fac (int n) { return fac_acc (n, 1); } int fac_acc (int n, int acc) { if (n < 2) { return acc; } else { return fac_acc (n-1, n*acc); } } |
Enfin, le fichier "main.c" contient le reste du code (ici la
fonction main):
#include "fac.h" main () { int n, f; n = 5; f = fact(n); affiche(n,f); n = 6; f = fact(n); affiche(n,f); } |
Il reste les compiler sparment. Ceci se gnralise grce au fichier "Makefile":
# Compilation generique par Bourdin CC=gcc fac: io.o main.o fac.o fac.h $(CC) io.o main.o fac.o -o fac main.o: main.c fac.h io.o: io.c fac.h fac.o: fac.c fac.h clean: @rm -f *.o @rm -f core @rm -f *~ |
Attention, il faut remettre des "tabulations" la main, sous emacs.
Dans ce fichier on trouve trois sortes de lignes : les affectations de
variables (ici "CC=gcc") qui permettent d'utiliser des variables par
la suite, les dclarations de dpendance (comme "io.o: io.o fac.h",
qui annonce que la compilation de io.o dpend de l'existance des deux
autres fichiers) et les ordres (comme " @rm -f *.o" ou
" $(CC)
io.o main.o fac.o -o fac") qui sont des
lignes commenant par une tabulation.
Prenons la ligne 5:
fac est nomm "cible".
io.o main.o fac.o fac.h sont les dpendances.
Sous shell, il ne reste plus qu' demander la compilation
alpha5: make fac predecessor cycle (io.o) gcc -O -c io.c predecessor cycle (main.o) gcc -O -c main.c predecessor cycle (fac.o) gcc -O -c fac.c gcc io.o main.o fac.o -o fac ld: ERROR 33: Unresolved text symbol "fact" -- 1st referenced by main.o. Use linker option -v to see when and which objects, archives and dsos are loaded. ld: INFO 152: Output file removed because of error. *** Error code 1 (bu21) |
Aprs correction (la fonction est nomme "fac" et pas "fact"!):
alpha5: make fac predecessor cycle (io.o) predecessor cycle (main.o) gcc -O -c main.c predecessor cycle (fac.o) gcc io.o main.o fac.o -o fac alpha5: fac Vous avez donne 5 Sa factorielle est 120 Vous avez donne 6 Sa factorielle est 720 alpha5: |
On peut amliorer ce fichier de make, en utilisant des variables et des rgles :
# Meilleure compilation par Bourdin # # Attention, les tabulations doivent tre refaites vous-mmes, la # main # OBJ=io.o main.o fac.o CC=gcc fac: $(OBJ) fac.h $(CC) $(OBJ) -o fac %.o : %.c $(CC) -c $< clean: @rm -f *.o @rm -f core @rm -f *~ |
Vous remarquerez que les fichiers qui finissent par ".o" sont obtenus par compilation avec l'option "-c" c'est l'objet des lignes 14 et 15.
Quelques variables par dfaut
A variable is a set of three things: a name, a type and a
location.
It is in this location that one can find the value of
the variable. The address is known by the operator &.
Une variable est un triplet < nom, type, emplacement>. C'est cet emplacement que, selon le type, on trouve la valeur. On peut connatre l'emplacement, l'adresse, de la variable "a" en utilisant l'oprateur & :
void voirou1 () { int i, j; printf("i est en %u, j est en %u\n", (int)&i, (int)&j); } |
/* une petite question sur les allocations */ #include <stdio.h> void nrut (int * px, int * py) { * px = * px + * py; * py = * px - * py; * px = * px - * py; } void lookatit (int n) { int i, j, k, l; int * pi, * pj; i = 2; j = 3; k = 4; l = 5; pi = & i; pj = & j; printf("adresses de i %d et j %d\n",pi, pj); printf("adresses de i %p et j %p\n",pi, pj); nrut(pi,pj); printf("valeurs de i %d et j %d\n",i, j); pi = & k; pj = & l; printf("adresses contenues dans pi %d et pj %d\n",pi, pj); printf("adresses contenues dans pi %p et pj %p\n",pi, pj); } int main () { lookatit(5); } /* adresses de i -317351240 et j -317351244 adresses de i 0x7ffeed159ab8 et j 0x7ffeed159ab4 valeurs de i 3 et j 2 adresses contenues dans pi -317351248 et pj -317351252 adresses contenues dans pi 0x7ffeed159ab0 et pj 0x7ffeed159aac */ |
void voirou () { int *pi, *pj; int i, j; printf("i est en %d, j est en %u\n",(int) &i,(int) &j); pi = & i; pj = & j; i = 7; j = 9; printf("En %u il y a %d\n", (int) pi, * pi); printf("En %u il y a %d\n", (int) &j, j); } |
void iv (int * pa, int * pb) { * pa = * pa + * pb; * pb = * pa - * pb; * pa = * pa - * pb; } int main () { int a, v; a = 5; v = 8; voirou1(); voirou(); printf("a = %d\t v = %d\n",a,v); iv (&a, &v); printf("a = %d\t v = %d\n",a,v); } /* dhcp13.ai.univ-paris8.fr: a.out i est en 1344117452, j est en 1344117448 i est en 1344117436, j est en 1344117432 En 1344117436 il y a 7 En 1344117432 il y a 9 a = 5 v = 8 a = 8 v = 5 */ |
/* Fait par JJ B en 2010 */ typedef int * pint; void fct (int nb, int rg, pint a, pint b) { if (nb > rg) { *a = *a + *b; *b = *a - *b; fct (nb, rg + 1, a, b); } } main () { int i, n, a, b; n = 10; for (i = 0; i <= n; i++) { a = 1; b = 1; fct (i, 0, &a, &b); printf("%d => %d\n", i, b); } } |
/* Fait par JJ B en 2014 */ #include <stdio.h> #include <stdlib.h> struct vecteur { int nbe; float tab [100]; } ; typedef struct vecteur vecteur_t; typedef float * pfloat; float somv (vecteur_t v) { int i; float som, *p; p = v.tab; som = 0; for (i = 0; i < v.nbe; i++) { som = som + *p; p ++; } return som; } |
Il vous reste reprendre quelques exercices faits avec des vecteurs, mais cette fois, en utilisant les pointeurs.
Exemple avec les altitudes
#include <stdio.h> typedef float table [100] [100]; void affichet (table t, int sx, int sy) { int x, y; printf("Tableau \n"); for (x = 0; x < sx; x += 1) { for (y = 0; y < sy; y += 1) { printf ("%3.3f ", t[x][y]); } printf("\n"); } } void afficheptr (table t, int sx, int sy) { int x, y; float * ptr; printf("Tableau pointeurs\n"); for (x = 0; x < sx; x += 1) { ptr = (float *) &(t[x]); /* mais pourquoi ? */ for (y = 0; y < sy; y += 1) { printf ("%3.3f ", *ptr++); } printf("\n"); } } void afficheadr (table t, int sx, int sy) { int x, y; float * ptr; printf("Adresses Tableau \n"); for (x = 0; x < sx; x += 1) { ptr = (float *) &(t[x]); for (y = 0; y < sy; y += 1) { printf ("%d ", (int) ptr++ % 10000); } printf("\n"); } } void remplirt (table t, int sx, int sy) { int x, y, sxy; float v, eps, add; v = 0.1; add = 0.0; sxy = sx * sx + sy * sy; eps = 1.0 / (float) (sxy); for (x = 0; x < sx; x += 1) { for (y = 0; y < x; y += 1) { t[x][y] = (float) (x * x - y * y + add) * eps; } for (y = x; y < sy; y += 1) { t[x][y] = (float) ( y * y - x * x + add) * eps; } add += v; if (add > 2.0) v = - 0.1; if (add < 0.1) v = 0.1; } } int main () { table t; int sizex, sizey; sizex = 10; sizey = 10; remplirt(t, sizex, sizey); affichet(t, sizex, sizey); afficheptr(t, sizex, sizey); afficheadr(t, sizex, sizey); } |
0.000 0.005 0.020 0.045 0.080 0.125 0.180 0.245 0.320 0.405 0.005 0.001 0.015 0.041 0.075 0.120 0.175 0.240 0.315 0.400 0.021 0.016 0.001 0.026 0.061 0.106 0.161 0.226 0.301 0.386 0.047 0.041 0.026 0.002 0.036 0.081 0.136 0.201 0.276 0.361 0.082 0.077 0.062 0.037 0.002 0.047 0.102 0.167 0.242 0.327 0.127 0.122 0.107 0.082 0.047 0.002 0.057 0.122 0.197 0.282 0.183 0.178 0.163 0.138 0.103 0.058 0.003 0.068 0.143 0.228 0.249 0.243 0.228 0.204 0.169 0.124 0.068 0.004 0.078 0.163 0.324 0.319 0.304 0.279 0.244 0.199 0.144 0.079 0.004 0.089 0.410 0.405 0.389 0.364 0.329 0.285 0.229 0.164 0.089 0.005 Tableau pointeurs 0.000 0.005 0.020 0.045 0.080 0.125 0.180 0.245 0.320 0.405 0.005 0.001 0.015 0.041 0.075 0.120 0.175 0.240 0.315 0.400 0.021 0.016 0.001 0.026 0.061 0.106 0.161 0.226 0.301 0.386 0.047 0.041 0.026 0.002 0.036 0.081 0.136 0.201 0.276 0.361 0.082 0.077 0.062 0.037 0.002 0.047 0.102 0.167 0.242 0.327 0.127 0.122 0.107 0.082 0.047 0.002 0.057 0.122 0.197 0.282 0.183 0.178 0.163 0.138 0.103 0.058 0.003 0.068 0.143 0.228 0.249 0.243 0.228 0.204 0.169 0.124 0.068 0.004 0.078 0.163 0.324 0.319 0.304 0.279 0.244 0.199 0.144 0.079 0.004 0.089 0.410 0.405 0.389 0.364 0.329 0.285 0.229 0.164 0.089 0.005 Adresses Tableau -7648 -7644 -7640 -7636 -7632 -7628 -7624 -7620 -7616 -7612 -7248 -7244 -7240 -7236 -7232 -7228 -7224 -7220 -7216 -7212 -6848 -6844 -6840 -6836 -6832 -6828 -6824 -6820 -6816 -6812 -6448 -6444 -6440 -6436 -6432 -6428 -6424 -6420 -6416 -6412 -6048 -6044 -6040 -6036 -6032 -6028 -6024 -6020 -6016 -6012 -5648 -5644 -5640 -5636 -5632 -5628 -5624 -5620 -5616 -5612 -5248 -5244 -5240 -5236 -5232 -5228 -5224 -5220 -5216 -5212 -4848 -4844 -4840 -4836 -4832 -4828 -4824 -4820 -4816 -4812 -4448 -4444 -4440 -4436 -4432 -4428 -4424 -4420 -4416 -4412 -4048 -4044 -4040 -4036 -4032 -4028 -4024 -4020 -4016 -4012 |
Le "pourquoi" vient simplement du fait que, lorsque le tableau est cr, il contient 100x100 entiers. Donc, pour passer la ligne suivante, il faudrait avancer de 400 octets...
typedef int * pint; typedef int table [100]; void fcttab (int nb, table t) { int i; pint p1, p2, p3; p3 = t; p2 = t + 1; p1 = t + 2; *p3 = 1; *p2 = 1; for (i = 2; i <= nb; i+=1) { *p1 = *p2 + *p3; p3 = p2; p2 = p1; p1+= 1; } } void seetab (table t, int nb) { pint p; p = t; while (nb > 0) { printf("%d\t", *p); p++; nb--; } printf("\n"); } main () { table tt; pint pt; int n, nbele; n = 18; nbele = n + 1; /* ici, la methode classique ou tt est un tableau */ fcttab(n, tt); seetab(tt, nbele); n = 10; nbele = n + 1; /* la, la methode dynamique de "creation" d'un tableau */ pt = (pint) malloc ((size_t) (nbele * sizeof(int))); fcttab(n, pt); seetab(pt, nbele); free(pt); /* c'est plus joli, plus souple, plus dynamique */ } |
Refaire toutes les fonctions dj vues sur les tableaux mais avec des tableaux dynamiques.
Voici un exemple de corrig, l'ensemble du programme qui cre un tableau d'altitudes (la topographie d'un terrain) et l'affiche (on trouve le mme, " l'ancienne" un peu plus haut sur cette page).
Let's see some new types to work on the altitude field.
typedef unsigned int uint; typedef float * tabalt ; struct tableau { tabalt t; unsigned int nbc; unsigned int nbl; } ; typedef struct tableau tableau; |
tableau creetableau (uint nbc, uint nbl) { tableau t; t.nbc = nbc; t.nbl = nbl; t.t = (tabalt) malloc ((size_t) (nbc * nbl * sizeof(float))); return t; } |
void puttab (tableau t, uint i, uint j, float amettre) { if (i < t.nbc && j < t.nbl) { *(t.t + i + j * t.nbc) = amettre; } } float valtab (tableau t, uint i, uint j) { if (i < t.nbc && j < t.nbl) { return *(t.t + i + j * t.nbc); } return -1.0; } |
void remplirtab (tableau t) { uint i, j; float val; for (i = 0; i < t.nbc; i++) for (j = 0; j < t.nbl; j++) { val = (float) (30 * i + 20 * i * j + 15 * j); while (val > 2000.0) val = val - 2000.0; if (val > 1000.0) val = 2000.0 - val; puttab(t, i, j, val); } } |
void voirtab (tableau t) { uint i, j; for (j = 0; j < t.nbl; j++) { printf ("%6d", j); } printf("\n"); for (i = 0; i < t.nbc; i++) { printf ("%4d |", i); for (j = 0; j < t.nbl; j++) { printf ("%6.2f ", valtab(t, i, j)); } printf("\n"); } } |
int main () { uint sx, sy; tableau t; sx = 10; sy = 10; t = creetableau (sx, sy); remplirtab (t); voirtab(t); } |
0 1 2 3 4 5 6 7 8 9 0 | 0.00 15.00 30.00 45.00 60.00 75.00 90.00 105.00 120.00 135.00 1 | 30.00 65.00 100.00 135.00 170.00 205.00 240.00 275.00 310.00 345.00 2 | 60.00 115.00 170.00 225.00 280.00 335.00 390.00 445.00 500.00 555.00 3 | 90.00 165.00 240.00 315.00 390.00 465.00 540.00 615.00 690.00 765.00 4 |120.00 215.00 310.00 405.00 500.00 595.00 690.00 785.00 880.00 975.00 5 |150.00 265.00 380.00 495.00 610.00 725.00 840.00 955.00 930.00 815.00 6 |180.00 315.00 450.00 585.00 720.00 855.00 990.00 875.00 740.00 605.00 7 |210.00 365.00 520.00 675.00 830.00 985.00 860.00 705.00 550.00 395.00 8 |240.00 415.00 590.00 765.00 940.00 885.00 710.00 535.00 360.00 185.00 9 |270.00 465.00 660.00 855.00 950.00 755.00 560.00 365.00 170.00 25.00 |
Voici une fonction qui construit une liste de n nombres entiers. Elle est en Lisp, il faut donc la transcrire.
(define (creerl n) (if (< n 1) '(0) (cons n (creerl (- n 1))))) |
struct cell { int nb; struct cell * nxt; } ; typedef struct cell cell_t; typedef struct cell * liste; |
int estvide (liste l) { if (l == (liste) 0) { return 1; } return 0; } int estnonvide (liste l) { if (l == (liste) 0) { return 0; } return 1; } |
int soml (liste l) { if (estvide(l)) { return 0; } return (*l).nb + soml((*l).nxt); } |
int howmany (liste l) { if (estvide(l)) { return 0; } return 1 + howmany ((*l).nxt); } |
liste cons (int nb, liste l) { liste new; new = (liste) malloc (sizeof(cell_t)); assert(new); (*new).nb = nb; (*new).nxt = l; return new; } liste creer (int nb) { liste debut; int i, j, k, t; j = 13; k = 21; debut = (liste) 0; for (i = 0; i < nb; i++) { debut = cons (j, debut); t = (j + k) % 33; k = j; j = t; } return debut; } |
void affl (liste l) { if (estvide (l)) { printf("\n"); } else { printf("%3d ", (*l).nb); affl ((*l).nxt); } } |
void affll (liste l) { if (estvide (l)) { printf("\n"); } else { printf("%3d ", l->nb); affll (l->nxt); } } void affw (liste l) { while (estnonvide (l)) { printf("%3d ", l->nb); l = l->nxt; } printf("\n"); } |
#include<stdio.h> #include<stdlib.h> #include<assert.h> |
int main () { liste l; int nb, s; nb = 10; l = creer(nb); affw(l); s = soml(l); printf("Total : %d\n", s); s = howmany(l); printf("Il y a %d elements\n", s); } |
int plusgrandliste (liste l, int candidat) { if (l) { if (l->nb > candidat) return plusgrandliste (l->next, l->nb); return plusgrandliste (l->next, candidat); } return candidat; /* il n'y a plus d'autre possible*/ } int plusgrandl (liste l) { if (l) return plusgrandliste (l->next, l->nb); return INT_MIN; /* impose d'avoir inclus limits.h */ } |
Pour faire Quicksort, nous avons besoin de faire une fonction qui trie les toutes petites listes.
liste tril2(liste l) { liste crt ; if (!l) return l; if (! l->nxt) return l; crt = l->nxt; if (l->nb < crt->nb) return l; crt->nxt = l; l->nxt = NULL; return crt; } |
liste qs (liste l) { liste petits, grands, pivot, crt; if (!l) return l; if (! l->nxt) return l; if (! l->nxt->nxt) return tril2(l); pivot = l; l = l->nxt; pivot->nxt = NULL; petits = NULL; grands = NULL; while (l) { crt = l->nxt; if (l->nb < pivot->nb) { /* il est petit */ l->nxt = petits; petits = l; } else { /* il est grand */ l->nxt = grands; grands = l; } l = crt; } grands = qs(grands); petits = qs(petits); pivot->nxt = grands; if (! petits) return pivot; crt = petits; while (crt->nxt) crt = crt->nxt; crt->nxt = pivot; return petits; } |
(define (re l) (ifn (cdr l) l (cons (car (re (cdr l))) (re (cons (car l) (re (cdr (re (cdr l))))))))) |
Quelques solutions vues en cours
int moyl (liste l) { int val, nb; liste crt; if (! l) return 0; val = 0; nb = 0; crt = l; while (crt) { val += car(crt); crt = cdr(crt); nb++; } return val/nb; } |
"La beaut des arbres est de crotre." (qui ?)
Nous prsentons une structure pour des arbres binaires. We start by defining some structures.
/* Arbres binaires tout simplement */ #include <stdio.h> #include <stdlib.h> #include <time.h> struct noeud { int num; float val; struct noeud * fg; struct noeud * fd; } ; typedef struct noeud noeud; typedef struct noeud * arbre; |
arbre ajout (arbre a, int v, float x) { arbre new; int rande; if (! a) { new = (arbre) malloc (sizeof (noeud)); new->num = v; new->val = x; new->fg = (arbre) 0; new->fd = (arbre) 0; return new; } rande = rand (); /* printf(" insere %d en %d avec %2d\n", v, a->num, rande %10); */ if (rande % 2) { /* on le met gauche*/ if (! (a->fg)) { /* s'il ny a pas de fils gauche */ a->fg = (arbre) malloc (sizeof (noeud)); a->fg->num = v; a->fg->val = x; a->fg->fg = (arbre) 0; a->fg->fd = (arbre) 0; return a; } a->fg = ajout(a->fg, v, x); return a; } /* on le met donc a droite*/ if (! (a->fd)) { /* s'il ny a pas de fils droit */ a->fd = (arbre) malloc (sizeof (noeud)); a->fd->num = v; a->fd->val = x; a->fd->fg = (arbre) 0; a->fd->fd = (arbre) 0; return a; } a->fd = ajout(a->fd, v, x); return a; } /* To create the tree, you add, one after the other, the values in the tree.*/ arbre creation (int n) { arbre a; float x, y; x = 1.5; y = 0.21; a = (arbre) 0; srand(time(NULL)); while (n--) { a = ajout (a, n, x); printf("\n"); x += y; y += 0.06; if (x > 3.0 || x < -2.0) { y = - y; } } return a; } |
void afficharbre (arbre a) { if (a) { afficharbre (a->fg); printf("%d %3.2f ", a->num, a->val); afficharbre (a->fd); } } |
int appartient (int nu, arbre a) { if (! a) return 0; if (a->num == nu) return 1; if (appartient (nu, a->fd)) return 1; return appartient (nu, a->fg); } |
int main () { int n; arbre a, b; float x; /* srand(time(NULL)); */ n = 20; a = creation (n); printf("\n Vois \n"); voisarbre (a,0); x = 0.72; printf("%f dedans %s\n", x, appartient(a,x) ? "Oui" : "Non"); } |
0.720000 dedans Non |
int fappartient (arbre a, float x) { if (! a) return 0; if (fabs(a->val - x) < 0.0001) return 1; return fappartient(a->fg, x) || fappartient (a->fd, x); } |
int main () { int n; arbre a, b; float x; /* srand(time(NULL)); */ n = 20; a = creation (n); printf("\n Vois \n"); voisarbre (a,0); x = 0.72; printf("%f dedans %s\n", x, appartient(a,x) ? "Oui" : "Non"); printf("%f dedans %s\n", x, fappartient(a,x) ? "OUI" : "NON"); } |
0.720000 dedans Non 0.720000 dedans OUI |
arbre ajout (arbre a, int v, float x) { arbre new; if (! a) { new = (arbre) malloc (sizeof (noeud)); new->num = v; new->val = x; new->fg = (arbre) 0; new->fd = (arbre) 0; return new; } if (x < a->val) { /* on le met gauche*/ if (! (a->fg)) { /* s'il ny a pas de fils gauche */ a->fg = (arbre) malloc (sizeof (noeud)); a->fg->num = v; a->fg->val = x; a->fg->fg = (arbre) 0; a->fg->fd = (arbre) 0; return a; } a->fg = ajout(a->fg, v, x); return a; } /* on le met donc a droite*/ if (! (a->fd)) { /* s'il ny a pas de fils droit */ a->fd = (arbre) malloc (sizeof (noeud)); a->fd->num = v; a->fd->val = x; a->fd->fg = (arbre) 0; a->fd->fd = (arbre) 0; return a; } a->fd = ajout(a->fd, v, x); return a; } arbre creation (int n) { arbre a; float x, y; x = 1.5; y = 0.21; a = (arbre) 0; while (n--) { a = ajout (a, n, x); x += y; y += 0.06; if (x > 3.0 || x < -2.0) { y = - y; } } return a; } |
int appartient (arbre a, float x) { if (! a) return 0; if (a->val == x) return 1; if (a->val > x) return appartient (a->sg, x); return appartient (a->sd, x); } int appartientf (arbre a, float x) { if (! a) return 0; if (fabsf(a->val - x) < 0.0001) return 1; if (a->val > x) return appartientf (a->sg, x); return appartientf (a->sd, x); } |
It obeys to orders starting with #. Examples:
Les directives qui commencent par # et elles seules sont vallues par
le prcompilateur. Il les excute. Parmi ces directives nous verrons
essentiellement les :
#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)); } |
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); } |
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 |
#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)); } |
jj@mu $ a.out MAX( 2, 5, 6) == 6 MAX( 2, 5, 6) == 5 jj@mu $ |
jj@mu $ gcc -E ex.c # 1 "ex.c" # 1 " |
Dcimal Binaire 3 11 6 110 12 1100 24 11000 48 110000 96 1100000 192 11000000 4 100 8 1000 16 10000 13 1101 26 11010Remarquons que, en dcimal, 1230 et dix fois plus grand que 123. Donc, en binaire, 101010 et deux fois plus grand que 10101. L'oprateur de dcalage gauche
<<permet donc de dcaler 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"); } |
01011010 & 00011100 ------------ 00011000 01011010 & 00000001 ------------ 00000000S'crit avec &.
int imper (int i) { return i & 0x01; } |
int nonul (int i) { while (i) { if (i | 0x01) return 1; i = i << 1; } return 0; } /* completement inutile, non */ |
int differ (int i, int j) { if (i ^ j) return 1; return 0; } |
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)); } |
#include <stdio.h> #include <stdlib.h> #include <assert.h> struct vect { int nbele; int * v; } ; typedef struct vect vect_t; |
void afficv(vect_t v) { int i; for (i = 0; i < v.nbele; i++) printf("%d ",v.v[i]); printf("\n"); } |
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; } |
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"); } |
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 dbut dbut fin fin non err err creation ftell(fd) -> le numro de la case du fichier (0 c'est le dbut, 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 */ |
#include <stdio.h> #include <stdlib.h> struct vectd { int nb; double * v; } ; typedef struct vectd vectd_t; |
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"); } |
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); } |
vectd_t creer (int nb) { vectd_t v; int i; double x, eps; 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); } 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; } |
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; } |
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; } } |
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 dfinitions, c'est le fichier mydef.h :Version plus rapide
The prototypes and definitions are given at first:
Nous donnons ici simplement les fichiers direct.h, qui contient les dcalrations 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); } } |
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' copiler.