language C

Voir le sujet précédent Voir le sujet suivant Aller en bas

language C

Message  Admin le Mer 30 Mar - 7:20

LE LANGAGE C

1. INTRODUCTION

Le langage C a été conçu au début des années 1970 par Dennis Ritchie lors de sa conception du système UNIX, puis a été amélioré par Brian Kernighan. Le langage C de cette époque qui est celui présent sur les systèmes Unix est appelé le C K&R (Kernighan et Ritchie). Une norme a plus tard été établie. Le C ANSI se distingue du C K&R essentiellement dans la déclaration des paramètres de fonction.

Le concept fondamental en langage C est la portabilité. Le langage a été conçu dans ce but et nous rappellerons souvent les règles qui permettent de l'obtenir.

2. LES TYPES

2.1. Les types simples

Il y a plusieurs types entiers :
- short : entier court signé sur un octet
- int : entier signé sur un mot ( 1 ou 2 octets)
- long : entier long signé sur 2 octets
NB: seuls les types short et long sont portables
Pour utiliser un entier non signé, il faut indiquer unsigned devant le type.

Il y a également plusieurs types réels :
- float : réel codé sur 4 octets
- double : réel codé sur 8 octets.

Il y a un type caractère : char

Il n'existe pas de type booléen, il faut utiliser un entier : 0 est faux, toute autre valeur est vraie.

3. Les structures
Le mot clé struct est équivalent à RECORD du pascal, il sert à définir des enregistrements soit en déclarant un type (voir plus loin), soit directement en déclarant la variable.

exemple :
struct OU typedef struct point
{ {
int x; int x;
int y; int y;
} p1, p2; } ;
point p1,p2;


4. Les tableaux et chaines de caractères
La déclaration de tableau a la structure suivante :

type identificateur [ nb d'elements ] ;

exemple :
int tableau[100];
float sal_mens[12];
double matrice[10][15]; /* 10 lignes et 15 colonnes */

on les adresse de la manière suivante :
tableau[i]
sal_mens[3]
matrice[1][j]


Les chaînes de caractères sont des tableaux de caractères terminés par le caractère de fin de chaîne : \0.

Par conséquent pour stocker un mot de 10 lettres il faut faire la déclaration suivante :
char mot[11];
On ne peut manipuler les chaînes de caractères que par les fonctions de manipulations de chaînes ou caractère par caractère.

5. Les pointeurs

Un pointeur est une variable destinée à recevoir l'adresse d'un élément quelconque du langage (généralement une variable).
On doit indiquer lors de la déclaration du pointeur le type de la variable pointée.

type *identificateur;

ex :
char *pmot;
int *pentier;
client *cl;

La principale utilisation des pointeurs est le passage de paramètres ( voir le paragraphe sur les fonctions)

Les pointeurs sont initialisés avec l'adresse d'une variable.
On écrit :
pentier = &i; /* pentier reçoit l'adresse de i */
k = *pentier; /* k reçoit le contenu de la variable pointée par p */


6. LES INSTRUCTIONS
Il y a en fait très peu d'instructions en langage C. Tous les traitements que l'on a à effectuer se font par l'appel de fonctions définies dans des bibliothèques externes (voir paragraphe sur les fonctions).
7. Les affectations et calculs
L'affectation se fait par le signe = ( a = 2; rep = 'o')

7.0.1. arithmétique :
a = b+ c; /* addition */
a = b - c ; /* soustracion */
a = b*c; /* multiplication */
a = b/c; /* division (division entier si a,b et c sont des entiers) */
a = b%c /* a= b modulo c */

7.0.2. Raccourcis :

i++; <=> i = i+1
i--; <=> i = i-1;
i =+ b; <=> i = i+ b;
8. Les entrées/sorties

Les fonctions d'entrées sorties sont des fonctions standards du langage C, ce qui signifie que l'appel à la bibiliothèque qui les contient ne doit pas être spécifié lors de l'édition de liens. Néanmoins, il faut pour les utiliser inclure le fichier stdio.h qui contient des définitions nécessaires à ces fonctions (voir paragraphe les directives)

printf( format , variable , variable , ...);

Le format est une chaîne de caractères où chaque lettre précédée du caractère % désigne l'emplacement et le format d'affichage d'une des variables.
%d : entier
%l : entier long
%s : chaîne de caractères
%c : un caractère
%f : un réel
%[car1-car2] : une chaîne de caractères dont tous les caractères ont un code ascii compris entre celui de car1 et celui de car2

exemple :
printf("%d %s %c",age,nom,reponse);
printf("la valeur du %dème élément de tab est : %d\n",i,tab[i]);
\n : désigne une fin de ligne
\t : désigne une tabulation
\ inhibe le rôle d'un caractère spécial
"c:\\tp\\article.dat" désigne c:\tp\article.dat
printf("%d\%",pourcent); permet d'afficher le caractère %

9. LES STRUCTURES DE CONTROLE
10. Les conditionnelles

10.0.1. Les conditions

Une condition est fausse si elle vaut 0, ell est vraie sinon.
Une condition peut être :
- une variable
- l'appel d'une fonction
- une instruction
- une expression conditionnelle
Les opérateurs logiques sont les suivants :
== égalité
|| OU
&& ET
! NON

exemple : (a) aux si a est nul
!fin vrai si fin est nul
(a < 0) || b vrai si a négatif ou b non nul
!strcmp(mot1,mot2) vrai si la fonction retourne 0
(a==2) vrai si a vaut 2
(a=2) toujours vrai
(a=0) toujours faux


11. if ... then... else...

if condition then instructions else instructions ;

- le else est facultatif
- si il y a plusieurs instructions, elles sont encadrées par des accolades
- si il n'y a qu'une instruction elle se termine par ;

if (a)
then
i++;
else
{
printf("erreur\n");
i = 0;
}


12. switch
Le switch permet d'orienter les traitements en fonction de la valeur d'une variable ( de type entier ou char exclusivement).

switch variable
{
case valeur1 : instruction;
instruction;
...
break;
case valeur2 : instruction;
...
default : instruction;
instruction;
break;
}
Le mot clé break est facultatif, lorsqu'il est omis les instructions concernant tous les autres cas sont exécutées jusqu'à l'accolade fermante ou jusqu'au prochain break.
12.1. Les blocs d'instructions
Un bloc d'instructions est soit une instruction seule terminée par un point virgule, soit une suite d'instructions séparées par des points virgule et encadrées par des accolades.

instruction ; OU {
instruction;
instruction;
...
}
12.2. Les boucles

12.2.1. while condition bloc_d'instructions;
Le bloc d'instructions est exécuté tant que la condition reste vraie. La condition est évaluée en début de boucle.
exemple : while (!fin) while (epsilon >= 0.01)
jouer(); {
i++;
epsilon = calcul(i);
};

12.2.2. do bloc_d'instructions while (condition);

Le bloc d'instructions est exécuté tant que la condition reste vraie. La condition est évaluée en fin de boucle.
exemple : do do
jouer(); {
while (!fin); i++;
epsilon = calcul(i);
}
while (epsilon >= 0.01) ;


12.2.3. for ( instruction1 ; condition ; instruction2 ) bloc_d'instructions ;

Cela équivaut à l'écriture suivante :
instruction1 ;
while (condition)
{
bloc_d'instructions;
instruction2;
}

La forme la plus courante est la suivante :
for (i=1;i<10;i++)
tab[i] = 0;

Mais on peut écrire
for (r=sqrt(x); (r + d) /2 > fonc2(y); r=1/r) ; /* le bloc d'instruction est vide */

En instruction2 on peut utiliser la notation --i ou ++i qui signifie que l'incrémentation se fera avant le bloc d'instructions et non pas après.






13. LA STRUCTURE DU PROGRAMME
Un programme C comprend 3 parties, qui peuvent être mises dans un ordre a peu près quelconque, mais que je vous conseille de garder dans cette ordre.
- les directives
- les déclarations de variables globales
- les fonctions dont la fonction main
14. Les directives
Les directives commencent par le caractère #. Il y a 3 directives principales #define (constatntes) #include (inclusion de définitions externes) et #ifdef (compilation conditionnelle).
Toutes les directives sont traitées par un précompilateur avant la compilation. Elles génèrent des opérations de traitement de texte sur le fichier source.
15. #define :
La directive #define permet de définir par un terme choisi une valeur ou un morceau de code. Le précompilateur remplacera dans le source toute occurence de ce terme par la valeur associée. C'est donc # define, que l'on utilisera pour définir des constantes.
Par convention on met toujours le terme en majuscules.
exemples
#define PI 3.14116
#define OK ((!fin) && (erreur != -1) && (nbclients < MAXCLIENTS))
#define HYP(a,b) sqrt(a*a + b*b)
16. #include :
La directive #include est suivie d'un nom de fichier, le fichier considéré est inséré par le précompilateur dans le fichier source.

#include "toto.h"
Inclut dans le source le contenu du fichier toto.h, toto.h doit se trouver dans la directory courante.
#include <stdio.h>
Inclut dans le source le fichier stdio.h. Ce fichier doit se trouver dans la directory standard des fichiers d'include (/usr/include sous Unix et dans la directory pointée par la variable INCLUDE sous DOS)

#include "/u/moi/mesinclude/toto.h" /* sous Unix */
#include "a:\\mesinclude\\toto.h" /* sous DOS */
17. #ifdef ...#elseif...#endif
Cette directive permet de faire de la compilation conditionnelle en fonction de la définition ou non d'une constante.
exemple
#ifdef DOS
#include <dos.h>
#endif

#ifdef DOS
fd = open("c:\\monappli\\donnees\\clients.dat","r");
#elseif
fd = open("/u/monappli/donnees/clients.dat","r");
#endif

Cette directive teste si la variable DOS est définie c'est à dire si un "#define DOS" a été fait.

18. Les déclarations de variables
Les déclarations de variables se font de la manière suivante :

type variable1, variable2, ... ;
int i,j,k;
char rep,ok;
int tab[10];
char *pmot;

En théorie on peut déclarer des variables n'importe où, en fait il est conseillé de regrouper les déclarations en tête de fonction pour les variables locales, et avant toutes les fonctions pour les variables globales.
18.1. Les fonctions

En langage C, il n'existe que des fonctions. Elles ont toutes un type (par défaut int). Le programme principal est une fonction particulière : la fonction main.

18.1.1. déclaration de fonction en C K&R :

type identificateur ( param1 , param2, ... , paramn )
type param1;
type param2;
...
type paramn;
{
/* déclarations des variables locales */
instruction;
...
return( valeur );
}
18.1.2. déclaration de fonction en C ANSI :

type identificateur ( type param1 , type param2, ... , type paramn )
{
/* déclarations des variables locales */

instruction;
...
return( valeur );
}
- une fonction qui ne retourne pas de valeur doit être déclarée de type void.
- elle ne peut retourner qu'un type simple ou un pointeur sur un type complexe
- l'ordre dans lequel on déclare les fonctions n'a pas d'importance
- contrairement au Pascal, les fonctions sont toutes au même niveau
- en C ANSI un prototype de chaque fonction doit être déclaré en tête de fichier



18.1.3. Passage de paramètres
Le passage par valeur est analogue à celui du Pascal.
Le passage par nom consiste à passer effectivement l'adresse de la variable, la fonction travaille alors sur des pointeurs.

exemple
int longueur ( char *mot, int *nbblancs)
{
int i;

for (i=0; mot[i] != '\0'; i++)
if (mot[i] == ' ') *nbblancs++;
return(i);
}

A l'appel : lgmot = longueur(message,&nb);

L'adresse d'un tableau est son nom.
L'adresse d'une variable de type simple est obtenue par l'opérateur &.

Voir le document annexe pour bien comprendre le passage de paramètres.

18.1.4. La fonction main
La fonction main est une fonction particulière car elle représente le programme principal. Par défaut, elle retourne une entier.

main (int argc, char *argv[]) /* C ANSI */
main(argc,argv) /* C K&R */
int argc;
char **argv;

argc représente le nombre d'arguments passés au programme sur la ligne de commande, dont le premier est le nom du programme lui même.
argv est un tableau de chaînes de caractères, chacune représente l'un des arguments. argv[0] est le nom de programme.


19. LA COMPILATION ET L'EDITION DE LIENS

La génération d'un exécutable se déroule en trois temps :
19.1. la précompilation

Les fichiers d'include (#include) sont insérés dans la source
Les définitions (# define) sont remplacées dans tout la source
La source est épurée ou complétée en fonction des #ifdef
19.2. la compilation
Le source est interprété de manière à générer un fichier objet (.o sous unix, .obj sous DOS). En C K&R, seule la syntaxe est vérifiée, les références à des fonctions non définies ne sont pas signalées car le compilateur suppose que ce sont des définitions externes.
Il n'y a pas non plus vérification de la cohérence entre la déclaration de fonction et son utilisation.
En C ANSI, il y a vérification par rapport au prototype défini, donc il signale les fonctions non définies et les incohérences entre l'appel et la déclaration.

19.3. l'édition de liens
L'éditeur de liens résoud les références non résolues, c'est à dire les variables externes et les fonctions utilisées mais non définies dans le source même.
L'édition de liens permet de rassembler plusieurs objets (.obj ou .o) et les bibiliothèques éventuelles (.lib ou .a).

Sous unix :
cc annexe.c -c
cc second.c -c
cc -o monprog monprog.c annexe.o second.o -lm -lvidual -lcurses

Sous dos :
Faire un fichier monprog.mak contenant : monprog.c, annexe.c, second.c, vidual.lib

Un cours distinct traitera de la compilation séparée et des règles de programmation.



20. EXERCICES

20.1. Les types et instructions simples
Exercice 1 : On considère un fichier de salariés dont la description est la suivante :
nom : 20 caractères
prénom : 10 caractères
adresse : 80 caractères
code postal : entier
ville : 20 caractères
est-ce un cadre : booléen

Ecrire la déclaration de type permettant de gérer ce fichier.

Exercice 2 : remplir un chaine de caractères d'identificateur titre avec la valeur Rio Grande et la compléter à blanc

20.2. Les boucles

Exercice 3 : ajouter 2 à tous les éléments de rang pair d'un tableau de 15 entiers.

Exercice 4 : Réécrire en utilisant le while les boucles suivantes

DO
{
a = tab[i];
if (a> 0)
printf("tab[%d] = %d\n",i,tab[i]);
}
while ((i>=10) || ( a <= 0));

FOR (i=fonc(a);i+j-k < 20; i=i+5)
{
j = calcul(a,k);
k= fonc2(i);

20.3. Fonctions
Exercice 5 :
On considère une file décrite de la manière suivante :
typedef struct elt_file
{
char message [ MAXCAR];
(elt_file *) suivant;
}

Imprimer tous les messages de la file à l'aide de la fonction imprimer. ( le dernier message de la file est tel que suivant = (elt_file *) 0)

imprimer(chaine)
char * chaine;


Exercice 6 : que font les focntions suivantes ?

fonc1 (entiers, nbelts)
int *entiers;
int nbelts;
{
int i,retour;

retour = 0;
for (i=0;i<nbelts;i++)
if (*(entiers+i) > retour)
retour = *(entiers + i);
return(retour);
}

fonc2(a)
int a;
{
int x;

x = a;
switch(a)
{
case 0 :
case 1 : x++;
break;
case 2 : break;
case 3 : x++;
case 4 : x++;
case 5 : x++;
break;
default : x= 6;
break;
}
return(x);
}

avatar
Admin
Admin

Messages : 219
Points : 48103
Date d'inscription : 14/03/2011

Voir le profil de l'utilisateur http://odbatox.arabstar.biz

Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut


 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum