Cours Programmation en Langage C - Chapitre: Les Fonctions

Ce TP présente la notion de fonctions en langage C, leur utilité pour structurer un programme, ainsi que les concepts de portée des variables, passage de paramètres, et manipulation de tableaux via des pointeurs. Il permet d’apprendre à écrire, déclarer, définir et utiliser des fonctions, ainsi qu’à gérer le passage par valeur et par adresse.

D'après le document Cours Programmation en Langage C - Chapitre: Les Fonctions

Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Document source

Cours Programmation en Langage C - Chapitre: Les Fonctions

Computer Science · PDF · 12 pages · 2011

Afficher l'aperçu du document

Consulter le document original →

Ce TP présente la notion de fonctions en langage C, leur utilité pour structurer un programme, ainsi que les concepts de portée des variables, passage de paramètres, et manipulation de tableaux via des pointeurs. Il permet d’apprendre à écrire, déclarer, définir et utiliser des fonctions, ainsi qu’à gérer le passage par valeur et par adresse. Pour réaliser ce TP, un environnement de développement C avec un compilateur standard est nécessaire.

Objectifs

  • Comprendre la modularisation d’un programme en utilisant des fonctions.
  • Définir et déclarer des fonctions avec paramètres et valeurs de retour.
  • Maîtriser la portée des variables locales et globales.
  • Utiliser le passage des paramètres par valeur et par adresse.
  • Manipuler des tableaux à une et deux dimensions via des pointeurs.

Prérequis et installation

  • Connaissances de base en langage C : variables, boucles, conditions.
  • Un compilateur C compatible (gcc, clang, etc.).
  • Un éditeur de texte ou un IDE pour écrire et compiler les programmes.
  • Compréhension des notions de pointeurs et d’adressage mémoire.

Modularisation des programmes avec les fonctions

Les fonctions permettent de structurer un programme en sous-programmes plus simples, améliorant la lisibilité, la réutilisation et la maintenance. Par exemple, pour calculer la factorielle d’un entier, on peut écrire un programme simple puis le modulariser en isolant le calcul dans une fonction dédiée.

#include <stdio.h>
void factorielle(int n)
{
  int i, f=1;
  for (i=2; i<=n; i++)
    f *= i;
  printf("la factorielle de %d est %d\n", n, f);
}

void main()
{
  int n;
  printf("saisir un entier    ");
  scanf("%d", &n);
  factorielle(n);
  printf("fin du travail");
}

Cette étape montre comment extraire un bloc de code répétitif dans une fonction pour plus de clarté et de réutilisation.

Blocs d’instructions et portée des variables

En C, un bloc d’instructions est délimité par des accolades { } et peut contenir des déclarations locales. Les variables déclarées dans un bloc sont visibles uniquement à l’intérieur de ce bloc (variables locales). Une variable locale masque toute variable du même nom dans un bloc englobant.

if (n > 0) {
  int i;
  for (i=0; i<n; i++) {
    // instructions utilisant i
  }
}
// i n’est pas visible ici

Exemple de variables locales dans des fonctions différentes :

#include <stdio.h>
void calculer()
{
  int n=3;
  printf("la valeur de n dans la fonction calculer est %d\n", n);
}

void main()
{
  int n=5;
  printf("la valeur de n avant l'appel de la fonction calculer est %d\n", n);
  calculer();
  printf("la valeur de n apres l'appel de la fonction calculer est %d\n", n);
}

Résultat attendu :

la valeur de n avant l'appel de la fonction calculer est 5
la valeur de n dans la fonction calculer est 3
la valeur de n apres l'appel de la fonction calculer est 5

Variables globales

Les variables déclarées en dehors de toute fonction sont globales et accessibles dans toutes les fonctions du programme.

#include <stdio.h>
int y=3;

void test()
{
  printf("la valeur de y dans test est %d\n", y);
}

void main()
{
  printf("la valeur de y, dans main, avant l'appel de test est %d\n", y);
  test();
  printf("la valeur de y, dans main, apres l'appel de test est %d\n", y);
}

Résultat attendu :

la valeur de y, dans main, avant l'appel de test est 3
la valeur de y dans test est 3
la valeur de y, dans main, apres l'appel de test est 3

Déclaration, définition et appel de fonctions

Une fonction en C est déclarée (prototype), définie (corps) et appelée. La déclaration informe le compilateur du type de retour et des paramètres. La définition contient le code à exécuter. L’appel invoque la fonction.

Syntaxe générale d’une définition :

<TypeRés> <NomFonct>(<TypePar1> <NomPar1>, <TypePar2> <NomPar2>, ...)
{
  <déclarations locales>
  <instructions>
}

Exemple d’un programme utilisant des fonctions saisir() et maximum() :

#include <stdio.h>
int saisir()
{
  int a;
  printf("saisir un entier ");
  scanf("%d", &a);
  return a;
}

int maximum(int a, int b)
{
  int max;
  if (a > b) max = a;
  else max = b;
  return max;
}

void main()
{
  int x, y, max;
  x = saisir();
  y = saisir();
  max = maximum(x, y);
  printf("\n le maximum est %d", max);
}

Fonctions appelant d’autres fonctions

Une fonction peut appeler une autre fonction pour réaliser une tâche plus complexe. Exemple avec les fonctions saisir(), somme() et moyenne() :

#include <stdio.h>
int saisir()
{
  int x;
  printf("saisir un entier    ");
  scanf("%d", &x);
  return x;
}

int somme(int x, int y, int z)
{
  return (x + y + z);
}

float moyenne(int x, int y, int z)
{
  int s;
  s = somme(x, y, z);
  return (float)(s / 3);
}

void main()
{
  int a, b, c;
  float m;
  a = saisir();
  b = saisir();
  c = saisir();
  m = moyenne(a, b, c);
  printf("la moyenne est %f", m);
}

Exemple pratique : affichage d’un rectangle d’étoiles

Version simple :

#include <stdio.h>
void main()
{
  int l, c, i, j;
  printf("saisir nombre de lignes et nombre de colonnes");
  scanf("%d%d", &l, &c);
  for (i = 0; i < l; i++)
  {
    for (j = 0; j < c; j++)
      printf("*");
    printf("\n");
  }
}

Version modulaire avec fonctions :

#include <stdio.h>
void ligne(int c)
{
  int j;
  for (j = 0; j < c; j++)
    printf("*");
}

void rectangle(int l, int c)
{
  int i;
  for (i = 0; i < l; i++)
  {
    ligne(c);
    printf("\n");
  }
}

void main()
{
  int l, c;
  printf("saisir nbre de lignes et nbre colonnes");
  scanf("%d%d", &l, &c);
  rectangle(l, c);
}

Passage des paramètres par valeur

Les paramètres d’une fonction sont des variables locales initialisées par la valeur des arguments passés lors de l’appel. Modifier un paramètre dans la fonction n’affecte pas la variable d’origine.

Exemple de permutation qui ne fonctionne pas :

#include <stdio.h>
void permuter(int x, int y)
{
  int aide;
  aide = x;
  x = y;
  y = aide;
}

void main()
{
  int x, y;
  printf(" saisir deux entiers   ");
  scanf("%d%d", &x, &y);
  printf("les valeurs avant permutation: x: %d et y:%d", x, y);
  permuter(x, y);
  printf("\n les valeurs après permutation: x: %d et y:%d", x, y);
}

Résultat :

saisir deux entiers 4
7
les valeurs avant permutation: x: 4 et y:7
les valeurs après permutation: x: 4 et y:7

Passage des paramètres par adresse (pointeurs)

Pour modifier les variables d’origine, il faut passer leur adresse et manipuler des pointeurs dans la fonction.

#include <stdio.h>
void permuter(int *a, int *b)
{
  int aide;
  aide = *a;
  *a = *b;
  *b = aide;
}

void main()
{
  int x, y;
  printf(" saisir deux entiers   ");
  scanf("%d%d", &x, &y);
  printf("les valeurs avant permutation: x: %d et y:%d", x, y);
  permuter(&x, &y);
  printf("\n les valeurs après permutation: x: %d et y:%d", x, y);
}

Résultat attendu :

saisir deux entiers 4
7
les valeurs avant permutation: x: 4 et y:7
les valeurs après permutation: x: 7 et y:4

Passage de l’adresse d’un tableau à une dimension

Un tableau ne peut pas être passé par valeur. On passe l’adresse de son premier élément, soit par un pointeur soit par le nom du tableau.

Exemple d’un programme qui saisit, remplit et affiche un tableau :

#include <stdio.h>
void saisir2(int *a)
{
  printf("saisir nbre d'éléments");
  scanf("%d", a);
}

void remplir(int *p, int n)
{
  int i;
  for (i = 0; i < n; i++)
    scanf("%d", p + i);
}

void afficher(int *p, int n)
{
  int i;
  for (i = 0; i < n; i++)
    printf("%d \t", *(p + i));
}

void main()
{
  int tab[50], n;
  saisir2(&n);
  remplir(tab, n);
  afficher(tab, n);
}

Passage de l’adresse d’un tableau à deux dimensions

Pour un tableau 2D, on passe l’adresse du premier élément en convertissant le tableau en pointeur d’entier. L’accès aux éléments se fait via l’arithmétique des pointeurs avec un décalage calculé.

#include <stdio.h>
void remplir(int *tab, int l, int c)
{
  int i, j;
  for (i = 0; i < l; i++)
    for (j = 0; j < c; j++)
      scanf("%d", tab + i * 50 + j);
}

void afficher(int *tab, int l, int c)
{
  int i, j;
  for (i = 0; i < l; i++)
  {
    for (j = 0; j < c; j++)
      printf("%d", *(tab + i * 50 + j));
    printf("\n");
  }
}

void main()
{
  int mat[50][50];
  int l, c;
  printf("saisir nbre d'éléments");
  scanf("%d%d", &l, &c);
  remplir((int *)mat, l, c);
  afficher((int *)mat, l, c);
}

Résultats attendus

  • Affichage correct des résultats des fonctions (factorielle, maximum, moyenne).
  • Affichage d’un rectangle d’étoiles conforme aux dimensions saisies.
  • Permutation effective des valeurs lors du passage par adresse.
  • Affichage correct des tableaux remplis par l’utilisateur.
  • Respect de la portée des variables locales et globales.

Pièges courants

  • Confondre passage par valeur et passage par adresse : modifier un paramètre passé par valeur ne modifie pas la variable d’origine.
  • Oublier de passer l’adresse avec & lors de l’appel d’une fonction qui attend un pointeur.
  • Déclarer une fonction après son appel sans prototype, ce qui peut causer des erreurs de compilation.
  • Utiliser des variables locales hors de leur bloc de déclaration, ce qui provoque des erreurs.
  • Ne pas initialiser les variables locales avant leur utilisation.
  • Pour les tableaux 2D, mal calculer les indices lors de l’accès via pointeurs.
  • Ne pas respecter le type et le nombre des paramètres lors des appels de fonction.

Partager

Commentaires

Aucun commentaire pour le moment. Posez la première question.

Les commentaires sont relus avant publication. Votre e-mail n'est jamais affiché.

← Toutes les révisions