A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml...

62
Programmation C Dominique Rossin dominique.rossin@m4x. org

Transcript of A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml...

Page 1: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Programmation C

Dominique Rossin

[email protected]

Page 2: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Première partie

Généralités sur

la syntaxe C

Page 3: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Historique de C

AT&T Bell Labs 1969 : Premiere Unix 1973 Unix écrit en C

– B.Kerninghan, D.Ritchie, The C programming Langage, Prentice Hall, 1978

C ANSI = C ISO (1990) = C« Standard »– Kerningham & Ritchie, the C programming Langage

second edition, Prentice Hall, 1988– SP Harbison, GL Stelle jr, C-A reference Manual,

fourth edition, Prentice Hall 1995

Page 4: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Caractéristiques de C

Compilé Typé avec des types structurés Limité à des primitives de base mais

accompagné d’une librairie standard pour les copies complexes, les entrées/sorties, la gestion de la mémoire …

Interfaçage possible avec tous les langages ATTENTION Langage laxiste à la compilation Débogage parfois difficile

Page 5: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Différences entre C et Java Java a repris une grande partie de C mais :

– C est compilé et utilise un préprocesseur– Certains mots clés changent de définition– Pas d’objets en C, juste des structures– Gestion explicite de la mémoire en C

• En C on demande une taille n de mémoire• En java new s’occupe de cette opération• Il faut libérer la mémoire utilisée quand on utilise plus

une structure de données• En Java, le ramasseur de miettes (GC) s’en occupe

– En C il faut toujours déclarer avant d’utiliser

Page 6: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Exemple très simple en Java Fichier Bonjour.javapublic class Bonjour {

public static void main(String args[]) {System.out.println("Bonjour ");

} // fin de main} // fin de la classe On peut avoir plusieurs fonctions main l'exécution du programme commence par

l'appel à la fonction main du programme appelé.

Page 7: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Un exemple très simple en C

Fichier Bonjour.c (le nom importe peu)#include <stdio.h>int main(void) {

printf("Bonjour\n");return 0;

} /* fin de main */ Il ne peut y avoir qu'une seule fonction main

par programme Elle doit retourner un int (code d'erreur Unix)

Page 8: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Mise en œuvre

En Java– Compilation : javac Bonjour.java– produit un fichier Bonjour.class (bytecode)– commande java Bonjour :

• Interprétation de Bonjour.main(String args[])

En C– prétrait., compilation, éd. de liens : gcc Bonjour.c– produit un fichier a.out (code machine exécutable)– commande ./a.out : exécution de la fonction main

Page 9: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Deuxième exemple

Avec :– formatage des impressions– options de compilation

Page 10: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

public class PGCD {

public static void main(String args[]) {

int a = 257, b = 381;

if (a > 0 && b > 0) {

System.out.println(" PGCD("+a+","+b+")");

while (a != b) {

if (a < b) b = b-a;

else a = a-b;

System.out.println("=PGCD("+a+","+b+")");

}

System.out.println("= "+a);

}

}

}

Page 11: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

#include <stdio.h>int main(void) {

int a= 257, b = 381;if (a > 0 && b > 0) {printf(" PGCD(%3d,%"d)\n",a,b);while (a != b) {if (a < b) b = b-a;else a = a-b;printf("=PGCD(%3d,%3d)\n",a,b);}printf("=%d\n",a);}return 0;

}

Page 12: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Exemple de formatage avec printf

PGCD(257,381) "PGCD(%3d,%3d)"

=PGCD(257,124)

=PGCD(133,124)

=PGCD( 9,124)

=PGCD( 9,115)

Page 13: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Options de compilation Prétraitement, compilation et édition de liens :gcc –Wall –g pgcd.o –lm –o pgcd l'option –Wall demande une compilation avec

des diagnostics sur la propreté du code l'option –g demande que la table des symboles

soit ajoutée à l'exécutable l'option –lm demande de lier la librairie

mathématique l'option –o pgcd demande que le résultat

(l'exécutable) soit nommé pgcd au lieu de a.out

Page 14: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Déclaration de variables

Syntaxe, exemples:– id_type id_variable;– id_type id1,id2;– id_type id = valeur;

Les variables locales ne sont pas initialisées implicitement

Les déclarations ne peuvent être qu'en début de bloc

Des constructions comme for(int i = …) et similaires sont interdites

Page 15: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Types élémentaires

La représentation n'est pas normalisée :– char : entiers, codés sur 8 bits– int : généralement codés sur 32 bits,– float : généralement codés sur 32 bits

(IEEE)– double : généralement codés sur 64 bitsEn C, une affectation peut faire perdre

implicitement de la précision. On a le droit d'écrire int i = 1.5;

Page 16: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Qualificatifs short et long

short int (ou short simplement) : 16 bits long int (ou long simplement) : 32 ou 64 long long int : généralement 64 bits long double : au moins 64 bits

Page 17: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Conversion de types arithmétiques implicites En cas de +,*,<,… sur deux types différents:

– un opérant est long double => long double– un opérant est double => conversion en double– un opérant est float => conversion en float– char et short int sont convertis en int

En cas de = d'une valeur de mauvais type : conversion vers le type de la variable

Page 18: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

sizeof

pseudo-opérateur : sizeof(type) ou sizeof(expr) donne la taille en octets : sizeof(char)=1 nombre entier, calculé à la compilation "retourne" une valeur de type size_t (int ou

long ?)– incorrect :

• printf("%d\n",sizeof(…)); //suppose int• printf("%ld\n",sizeof(…)); // suppose long

– correct• printf("%ld\n",(long)sizeof(…));

Page 19: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Représentation des types numériques sizeof selon les systèmes

C S I L LL F D LD

cw/mac 1 2 4 4 8 4 8 8

gcc/hp 1 2 4 4 8 4 8 8

gcc/pc 1 2 4 4 8 4 8 12

gcc/sun 1 2 4 4 8 4 8 16

gcc/alpha 1 2 4 8 8 4 8 8

char, short, int,long, long long, float, double, long double

Page 20: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Qualificatifs signed et unsigned

pour les types entiers seulement, modifient le domaine représenté mais pas la

taille de la représentation,– signed char : un octet : -128..127– unsigned char :un octet :0..255– char seul : signed ou unsigned ???

int est implicitement signed changent la sémantique des opérations et

affectations

Page 21: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Valeurs booléennes

En C, il n'y a pas de type spécifique aux booléens,

on utilise les int false est représenté par 0 pas de valeur particulière pour true test indicateur :

printf("%d\n",sizeof('a'=='b')==sizeof(int));

Page 22: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Tests, attention !!!!

En C, on a le droit d'écrire :int i;…if (i = 0) …affecte 0 à i et vaut 0, ie. faux

qui est très différent de :…if (i == 0) …compare 0 à i et vaut vrai ou faux selon le cas

Page 23: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Définition de constantes

3 moyens en C– #define– const– enum

Page 24: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

#define

exemples– #define N (1 << 4)– #define DEUX_N ((N)+(N))

Niveau préprocesseur = perte d'information

usage très répandu attention aux parenthèses

Page 25: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

const

Exemples :– const int N = 1 << 4;– const int DEUX_N = N+N;

fondalementalement une déclaration de variable,

symboles utilisables par le débogueur l'affectation est en principe interdite, avec certains compilateurs, on a un simple

warning

Page 26: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Enumérations

Pour disposer de constantes symboliques entières sans #define

Déclarationenum nom_d_enum { const1,const2,…}; Déclaration de variablesenum nom_d_enum nom_de_variable

Page 27: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Fonctions

– Déclaration obligatoire avant toute utilisation

– Récursivité à la Java– void = absence d'argument ou de valeur en

retour Exemples :

Page 28: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

#include <stdio.h>#define DEBUT 0#define FIN 10

static int carre(int);static int cube(int n) {return carre(n)*n;}static int carre(int n) {return n*n;}

int main(void) {int i;for (i = DEBUT; i < FIN; i++)printf("%3d^2=%3d,%3d^3=%3d\n",i,carre(i),cube(i));return 0;

}

Page 29: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

gcc –Wall –g carre.c –o carre ./carre

0^2= 0, 0^3= 0

5^2= 25, 5^3=125

6^2= 36, 6^3=216

7^2= 49, 7^3=343

Page 30: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Les boucles et tests

Même syntaxe qu'en Java Les boucles for, while et do…while

– while (condition) {…}– do {…} while (condition)– for (i = 0; i < 10; i++) {…}

Les structures de tests – if (condition) {} else {}

Page 31: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Tableaux statiques et chaines de caractères Déclaration et allocationtype_des_elements nom_tab[nombre];Initialisation (+declaration et allocation) :int primes[]={2,3,5,7,11}; // int primes[6]char s[] = "abc"; /*char s[4]; s[0]='a'; s[1]='b';s[2]='c';s[3]='\0'*/

Les indices de tableau vont de 0 à N-1 maisIL N'Y A PAS DE VERIFICATION DE DEBORDEMENT

Page 32: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Copie d'un tableau ou d'une chaine

void copie_tableau(char []t1,char []t2,int n) {

while (n --> 0) t1[n]=t2[n];

}

void copie_chaine(char []s1,char []s2) {

int i=0;

do s2=s1[i] while (s1[i++]!='\0');

}

Page 33: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Fonctions simples sur les chaines

strlen(s) : retourne la longueur de la chaine s, sans compter le nul.– Il faut mettre #include <string.h>

strcmp(s1,s2): compare deux chaines et retourne un nombre <0,=0,>0.

atoi(s),atol(s),atof(s) : conversion vers entier, long et double– Librairie stdlib.h

Page 34: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Structures

Déclarationstruct nom {type1 c1; type2 c2;…}; Déclaration de variable :struct nom variable; Exemple

– struct evt {int jour,mois,annee; char evt[50]};– struct evt anniv;– anniv.jour = 14; anniv.annee=1973;– strcpy(anniv.evt,"Anniversaire de Dominique");

Page 35: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Exemple#include <stdio.h>#include <math.h>

struct point {float x; float y} p10 = {0,10};struct rect {struct point p1; struct point p2};static double sqr(double x) {

return x*x;}static double dist(struct point p1,struct point p2){

return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));}

Page 36: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

int main(void) {

struct rect r = {{0,5},{25,20}};

return 0;

}

Page 37: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Format d'affichageprintf(format, arg1, arg2,…);format = chaine de caractères : %c : caractère %d : entier %f : float %s : chaine de caractères %u : entier non signéchar msg_erreur[20][100];void erreur(int no) {

printf("erreur numero %d:%s",no,msg_erreur[no]);}

Page 38: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Divers

Types synonymes :

typedef type nom_nouveau_type;

typedef struct {int re; int im;} Complexe;

Complexe z;

Page 39: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Macros avec arguments

#define mauvais_carre(x) x*x

#define carre(x) ((x)*(x))

#define max(a,b) ((a)<(b)?(b): (a))

max(mauvais_carre(x+1),carre(x+1));

((x+1*x+1)<(((x+1)*(x+1)))?…

Page 40: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Références

La référence :– Kerningham, Ritchie, The C Programming

Language, second edition, Prentice Hall, 1988

Page 41: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Programmation C

Deuxième Partie

Page 42: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Pointeurs et adresses Mémoire = Collection de cellules numérotées consécutivement

et contenant chacun un octet Adresse = Localisation d'une variable dans la mémoire Pointeur = variable contenant l'adresse d'une variable Typage d'es pointeurs : T* est le type "adresse d'un objet de

type T".

Objectifs:– Passage par référence pour modifier un paramètre– efficacité dans la transmission des paramètres et du résultat– référencer des objets dont la localisation est inconnue à la

compilation

Page 43: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Référencement et déréférencement&var est l'adresse de (une référence à) la variable var

*ptr est la variable pointée par le pointeur ptr.

int age;

printf("entrez votre age : ");

scanf("%d",&age);

int i=2,j=5;

static void echanger(int *p1,int *p2) {

int t=*p1; *p1 = *p2; *p2 = t;

}

echanger(&i,&j); /* i==5 et j==2*/

Page 44: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

L'adresse NULL

Un pointeur dont la valeur est ((void *) 0), noté par la constante symbolique NULL ne pointe vers aucune cellule mémoire

DEREFERENCER NULL provoque une erreur !!!!

int main(void) {int *p;printf("%p,%p\n",p,NULL);return 0;

}

0xbffffc58,(nil)

Page 45: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

int x = 1, y=2, z[4], *ip;

ip = & x; /* ip pointe sur x*/

y = *ip; /* y==1*/

*ip = 0; /* x==0*/

*ip = *ip+10; /*x==10*/

ip = &z[2]; /*ip pointe sur z[2]*/

ip=&y; /*ip pointe sur y*/

++*ip; /*y==2*/

(*ip)++; /*y==3*/

x y z[0] z[1] z[2] z[3] ip

100 104 108 112 116 120 124 1 2 1 2 100 1 1 100 0 1 100 10 1 100 10 1 116 10 1 104 10 2 104 10 3 104

Page 46: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Tableaux et pointeurs

Le nom d'un tableau t s'évalue à l'adresse de t[0]Si un pointeur p pointe sur t[0], p+i pointe par définition sur

t[i]

Ainsi,après int t[N], *p=t; /*p==&t[0]*/

on a : p+i == &t[i], *(p+i) == t[i],

et même t+i == &t[i], *(t+i) == t[i]

Mais on ne peut pas affecter à un nom de tableau

Page 47: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Usage idiotique des pointeurs

static int somme(int *t, int n) {

int i,s;

for(s=0,i=0; i < n; i++)

s = s+t[i];

return s;

}

est équivalent à :

static int somme(int *t, int n) {

int s = 0;

while (n-- > 0) s+=*t++; /* lire *(t++) */

return s;

}

Page 48: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Déréférencements et type struct

ptr->champ = (*ptr).champ

typedef struct {int re; int im;} Complexe;

Complexe *addition(Complexe *a,Complexe *b) {

b->re=a->re+b->re;

b->im=a->im+b->im;

return b;

} /* permet addition(u,addition(v,w)) */

Page 49: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Liste chaînées

typedef struct cell {

int val;

struct cell *suivant;

} cell,*liste;

void affiche(liste l) {

for (;l;l=l->suivant) printf("%d, ",l->val);

}

Page 50: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Allocation dynamique mallocvoid *malloc(size_t)

Permet la réservation de mémoire à l'exécution pour une variable inconnue à la compilation.

malloc(n) renvoie: l'adresse de début d'un bloc de n octets NULL si plus aucune mémoire n'est disponible

Schéma typique :/*typ p[N]; dynamique*/typ *p=(typ *) malloc(N*sizeof(typ));if (!p) erreur(…)

Page 51: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Constructeurs#include <stdio.h>#include <stdlib.h>

typedef struct cell{int val; struct cell *next; } *List;

List new_List(int v,List n) {List tmp = (List) malloc(sizeof(struct cell));if (!tmp) {

fprintf(stderr,"Plus de memoire ");exit(1);

}tmp->val = v;tmp->next=n;return tmp; }

Page 52: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Constructeurs suite

int main(int argc, char **argv) {

int i;

List l=NULL,v;

for(i = 1,i < argc; i++)

l = new_List(atoi(argv[i]),l);

for (v=l;v;v=v->next) printf("%d\n",v->val);

return 0;

}

Page 53: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Désallocation void free(void *)

Bloc perdu = plus aucun pointeur ne permet d'y accéder

Pas de ramasseur de miettes Il faut restituer explicitement les blocs qui ne sont

plus utilisés

l'argument doit être une adresse obtenue par malloc

on ne doit restituer qu'une seule fois il ne faut plus utiliser aucune adresse vers ce bloc

Page 54: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Tableaux multidimensionnelsStatiquement : type[N][M] réserve N*M

variables, dans l'ordreT[0][0],…T[0][M-1],T[1][0],…,T[N-1][M-1]

Dynamiquement :typ **T=(typ **)malloc(N*sizeof(typ*));if (!T) erreur();for(i=0; i<N;i++) {

T[i] = (typ *) malloc(M*sizeof(typ));if (!T[i]) erreur();

}

Page 55: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Taille 7 x 3

0 1 2 3 4 5 6

0,0 0,1 0,2

1,0 1,1 1,2

2,0 2,1 2,2

3,0 3,1 3,2

4,0 4,1 4,2

5,0 5,1 5,2

6,0 6,1 6,2

Page 56: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Tableau version deux

int **t = (int **)malloc(N*sizeof(int*));

if (!t) erreur();

t[0] = (int *) malloc(N*M*sizeof(int));

for (i=1; i < N; i++) {

t[i]=t[i-1]+M;

if (!t[i]) erreur();

}

Page 57: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Fichiers et entrées / sorties

FILE * = type de descripteur de fichierFILE *stdin,*stdout,*stderr sont ouverts automatiquement au

début du programmeexit (de n'importe ou) et return dans main font

automatiquement fclose de tous les fichiers ouverts. (ce n'est pas le cas lors d'un plantage en cours du programme utiliser fflush)

/* Filtre ^M ^J */#include <stdio.h>int main(void) {

int c;while ((c=getchar())!=EOF) putchar(c==13?10:c);

Page 58: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Ouverture et fermeture de fichier

FILE *fopen(const char * nom,const char *mode); nom=chemin d'accès au fichier mode=="r" pour ouvrir en lecture mode=="w" pour ouvrir en écriture (création ou remplacement) mode=="a" opur ouvrir en écriture à la fin du fichier retourne NULL si erreurint fflush(FILE *); force l'écriture des tampons renvoie 0 ou EOF en cas d'erreurint fclose(FILE *); ferme le fichier après un fflush éventuel renvoie 0 ou EOF en cas d'erreur

Page 59: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Lecture de fichiers

char getc(FILE *); lit un caractère et retourne sa valeur getchar() est équivalent à getc(stdin) renvoie EOF si fin de fichier ou erreurint fscanf(FILE *,const char *format,…); scanf(…) est équivalent à fscanf(stdin,…) renvoie EOF si fin de fichier ou erreurchar *fgets(char *line,int max,FILE *); lit une ligne dans le buffer line de taille max renvoie NULL si fin de fichier ou erreurint feof(FILE *); renvoie 1 si la fin de fichier est atteinte,0 sinon

Page 60: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Ecriture de fichiers

int putc(int c,FILE *f); Ecrit le caractère c renvoie sa valeur ou EOF si problème putchar(c) est équivalent à putc(c,stdout)

int fprintf(FILE *,const char *format,…); printf(…) est équivalent à fprintf(stdout,…) renvoie le nombre de caractères écrits ou

EOF si erreur

Page 61: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

Divers

Arithmétique des pointeurs :typ t[20],*p1=t+13,*p2=t+17;int n=p2-p1; /* n==4*/

Pointeurs sur des fonctions :double x,y;double (*f)(double);f=sin;y=f(x);Permet le passage de fonctions en paramètre

Page 62: A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1 –distribué ce matin Le polycopié de Caml Partie 2 Le polycopié de C.

static int add(int a, int b) {return a+b;

}static int mul(int a, int b) {

return a*b;}static int reduce(int *t,int n,int v, int (*f)(int,int)) {

int i;for (i = 0; i < n; i++) v=f(v,t[i]);return v;

}int main(void) {

int t[] = {1,3,7};printf("%d\n",reduce(t,3,0,add)); /* 11 */printf("%d\n",reduce(t,3,1,mul)); /* 21 */return 0;

}