• Aucun résultat trouvé

2.5 Principales fonctions d’entr´ees-sorties standard

2.5.5 La fonction de saisie scanf

La fonction scanf permet de r´ecup´erer les donn´ees saisies au clavier, dans le format sp´ecifi´e. Ces donn´ees sont stock´ees aux adresses sp´ecifi´ees par les argu- ments de la fonction scanf (on utilise donc l’op´erateur d’adressage & pour les variables scalaires). scanf retourne le nombre de valeurs effectivement lues et m´emoris´ees (en ommettant les %*). La syntaxe est la suivante :

scanf("cha^ıne de contr^ole", arg1, . . . , argn);

La chaˆıne de contrˆole indique le format dans lequel les donn´ees lues sont conver- ties. Elle ne contient pas d’autres caract`eres (notamment pas de \n). Comme pour printf, les conversions de format sont sp´ecifi´ees par un caract`ere pr´ec´ed´e du signe %. Les formats valides pour la fonction scanf diff`erent l´eg`erement de ceux de la fonction printf.

Les donn´ees `a entrer au clavier doivent ˆetre s´epar´ees par des blancs ou des <RETURN> sauf s’il s’agit de caract`eres.

Pour ˆetre plus pr´ecis, les sp´ecifications de format ont la forme suivante : %[*][larg][modif]type

* la valeur sera lue mais ne sera pas stock´ee larg pr´ecise le nombre maximal de caract`eres `a lire

modif sp´ecifie une taille diff´erente pour les donn´ees point´ees par l’argument : h: short int

l: long int (pour les entier) ou double (pour les nombres flottants). L: long double

type sp´ecifie le type de donn´ee lue et comment il faut le lire.

La plupart des types de scanf sont les mˆemes que pour printf :

Type Description Argument requis

c caract`ere simple (espace inclu) char * d entier : nombre optionnellement pr´ec´ed´e par un signe int * e,E,

f,g,G

Floating point : nombre d´ecimal pr´ec´ed´e eventuelle- ment d’un signe et suivi ´eventuellement du caract`ere e ou E et d’un nombre d´ecimal. Exemple :-732.103 ou 7.12e4

float *

o entier en notation octale. int *

s Chaˆıne de caract`eres (jusqu’`a la lecture d’un espace) char *

u entier non sign´e unsigned int *

x entier hexadecimal int *

Exemple :

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

int i;

printf("entrez un entier sous forme hexadecimale i = "); scanf("%x",&i);

printf("i = %d\n",i); return 0;

}

Les autres fonctions d’entr´ees/sorties (permettant notamment la manipulation des fichiers) seront abord´ees dans le chapitre 6.

Chapitre 3

Les pointeurs

Toute variable manipul´ee dans un programme est stock´ee quelque part en m´e- moire centrale. Cette m´emoire est constitu´ee d’octets qui sont identifi´es de mani`ere univoque par un num´ero qu’on appelle adresse comme l’illustre la fi- gure 3.1.

Adresse

adresses croissantes

32 bits

(un pointeur vers une zone mémoire)

MEMOIRE CENTRALE p 0x5E00 0x5E04 0x5E08 0x5E0C 0x5E10 0x5E14 0x5E18 0x5E1C 0x5E20

Fig. 3.1 – Illustration de l’adressage de la m´emoire centrale

Par analogie, on peut voir la m´emoire centrale comme une armoire constitu´ee de tiroirs num´erot´es. Un num´ero de tiroir correspond `a une adresse.

Ainsi, lorsqu’on d´eclare une variable var de type T, l’ordinateur r´eserve un espace m´emoire (de sizeof(T) octets) pour y stocker les valeurs de var. Pour retrouver cette variable, il suffit donc de connaˆıtre l’adresse du premier octet o`u elle est stock´ee (ou, s’il s’agit d’une variable qui recouvre plusieurs octets contigus, l’adresse du premier de ces octets).

Un pointeur est une variable de type adresse. Les pointeurs pr´esentent de nombreux avantages :

– Ils permettent de manipuler de fa¸con simple des donn´ees de taille importante (comme les tableaux, les structures etc...). Ainsi, au lieu de passer en para- m`etre `a une fonction un ´el´ement tr`es grand (en taille), on pourra se contenter

de lui fournir un pointeur vers cet ´el´ement... On gagne ´evidemment alors en efficacit´e dans l’ex´ecution du programme.

– Comme on le verra au chapitre 4, les tableaux ne permettent de stocker qu’un nombre fix´e d’´el´ements de mˆeme type. Si les composantes du tableau sont des pointeurs, il sera possible de stocker des ´el´ements de tailles diverses (comme des chaˆınes de caract`eres : voir §4.2.5)

– Il est possible de cr´eer des structures chaˆın´ees (on dit aussi structures auto- r´ef´er´ees) qui sont utilis´ees pour d´efinir des listes chain´ees. De telles listes sont beaucoup utilis´ees en programmation (le nombre d’´el´ements de cette liste peut ´evoluer dynamiquement, ce qui permet une utilisation plus souple que celle des tableaux). Cette notion sera abord´ee en d´etail au §4.3.5.

3.1

D´eclaration d’un pointeur

En C, chaque pointeur est limit´e `a un type de donn´ee. En effet, mˆeme si la valeur d’un pointeur (une adresse) est toujours un entier (ou ´eventuellement un entier long), le type d’un pointeur d´epend du type de l’objet point´e. Cette distinction est indispensable `a l’interpr´etation (en fait la taille) de la valeur point´ee.

On d´eclare un pointeur par l’instruction :

type *nom-du-pointeur ;

o`u type est le type de l’objet point´e. Exemple :

int *pi; // pi est un pointeur vers un int

short int *psi; // psi est un pointeur vers un short int char *pc; // pc pointeur vers un char

A noter aussi l’existence de pointeurs g´en´eriques, c’est `a dire capable de pointer vers n’importe quel type d’objet. On utilise pour cela le type void *.

Sans un tel type, il ne serait pas possible par exemple d’indiquer le type d’objet rendu par les fonctions d’allocation de m´emoire qui rendent un pointeur vers l’objet allou´e, puisque ce type varie d’une invocation `a l’autre de la fonction. Par exemple, la fonction malloc de la biblioth`eque standard est d´efinie de la mani`ere suivante : void *malloc(size_t size);