Cours Programmation en Langage C: Fonctions, Tableaux et Matrices

Ce laboratoire permet d'apprendre la manipulation des fonctions, des tableaux et des matrices en langage C. Il présente l'utilisation des pointeurs simples et multiples, le passage par adresse, ainsi que la gestion de tableaux unidimensionnels et bidimensionnels.

D'après le document Cours Programmation en Langage C: Fonctions, Tableaux et Matrices

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

Cours Programmation en Langage C: Fonctions, Tableaux et Matrices

Document source

Afficher l'aperçu du document

Consulter le document original →

Ce laboratoire permet d'apprendre la manipulation des fonctions, des tableaux et des matrices en langage C. Il présente l'utilisation des pointeurs simples et multiples, le passage par adresse, ainsi que la gestion de tableaux unidimensionnels et bidimensionnels. Pour réaliser ce TP, il est nécessaire de disposer d'un compilateur C standard et d'un environnement de développement permettant la saisie et l'affichage via la console.

Objectifs

  • Comprendre et utiliser les pointeurs simples, doubles et triples.
  • Apprendre le passage par adresse dans les fonctions.
  • Savoir déclarer, remplir et afficher un tableau unidimensionnel avec des fonctions.
  • Manipuler une matrice (tableau bidimensionnel) en mémoire et via des fonctions.
  • Maîtriser l'adressage des éléments dans une matrice en utilisant l'arithmétique des pointeurs.

Prérequis et installation

  • Connaissances de base en langage C : variables, pointeurs, fonctions.
  • Compilateur C compatible (gcc, clang, etc.).
  • Éditeur de texte pour écrire les programmes.
  • Environnement permettant l'entrée/sortie standard (console).

Manipulation des pointeurs simples, doubles et triples

Dans ce premier exercice, on déclare une variable entière x et des pointeurs m, q et h de niveaux 1, 2 et 3 respectivement :

int x = 5;
int *m;
int **q;
int ***h;
m = &x;
q = &m;
h = &q;

On affiche ensuite la valeur de x et les adresses mémoires associées :

printf("%d", x);      // affiche 5
printf("%p", &x);      // adresse de x, par exemple F800

printf("%p", m);       // adresse stockée dans m, soit adresse de x (F800)
printf("%p", &m);      // adresse de m (par exemple F200)
printf("%p", *m);      // valeur pointée par m, soit 5

printf("%p", q);       // adresse de m (F200)
printf("%p", &q);      // adresse de q (F500)
printf("%p", *q);      // valeur pointée par q, soit adresse de x (F800)
printf("%d", **q);     // valeur pointée par *q, soit 5

printf("%p", h);       // adresse de q (F500)
printf("%p", &h);      // adresse de h (F100)
printf("%p", *h);      // valeur pointée par h, adresse de m (F200)
printf("%p", **h);     // valeur pointée par *(*h), adresse de x (F800)
printf("%d", ***h);    // valeur pointée par **(*h), soit 5

Note : utiliser %d pour afficher un entier et %p pour afficher une adresse mémoire.

Passage par adresse dans les fonctions

Le passage par adresse permet à une fonction de modifier directement la variable passée en argument. Par exemple :

void main()
{
  int x;
  ...
  fct(&x);  // passage par adresse de x
  ...
}

void fct(int *a)  // a est un pointeur sur x
{
  ...
}

Dans cette fonction, a pointe vers x et permet de modifier sa valeur.

Déduction des entêtes de fonctions à partir d'un appel

Considérons le programme suivant :

void main()
{
  int x, y, z;
  int *a, *b;
  int **t, **s;
  fct1(b, t, x, z);
  a = fct2(&b, &s, y);
  s = fct3(y, &z, &a, t);
  z = fct4(y, &b, t, a, &x, &s);
}

Les entêtes des fonctions sont :

  • void fct1(int *b, int **t, int x, int z)
  • int *fct2(int **b, int ***s, int y)
  • int **fct3(int y, int *z, int **a, int **t)
  • int fct4(int y, int **b, int **t, int *a, int *x, int ***s)

Fonctions et tableaux unidimensionnels

Le programme suivant illustre la saisie, le remplissage et l'affichage d'un tableau d'entiers :

#include <stdio.h>

void main()
{
  int tab[50], n;
  n = saisir();
  remplir_tab(tab, n);
  afficher_tab(tab, n);
}

Les fonctions associées sont :

int saisir()
{
  int x;
  printf("saisir une valeur");
  scanf("%d", &x);
  return x;
}

void saisir2(int *a)
{
  printf("saisir une valeur");
  scanf("%d", a);
}

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

void afficher_tab(int *tab, int n)
{
  int i;
  for (i = 0; i < n; i++)
    printf("%d", *(tab + i));
}

Une autre version utilisant un pointeur q pour parcourir le tableau :

void remplir_tab(int *tab, int n)
{
  int *q;
  for (q = tab; q < tab + n; q++)
    scanf("%d", q);
}

void afficher_tab(int *tab, int n)
{
  int *q;
  for (q = tab; q < tab + n; q++)
    printf("%d", *q);
}

Les matrices en langage C

Une matrice est un tableau bidimensionnel. Par exemple :

int mat[20][30];

Cette déclaration réserve 600 cases mémoire consécutives (20 lignes × 30 colonnes). Chaque élément possède sa propre adresse mémoire.

Les indices i et j correspondent respectivement aux lignes et colonnes :

  • mat[i][j] accède à l'élément à la ligne i et colonne j.
  • L'adresse de cet élément peut s'écrire mat + i*30 + j ou &mat[i][j].
  • La valeur de cet élément peut s'écrire *(mat + i*30 + j) ou mat[i][j].

Par exemple, pour une matrice de 2 lignes et 3 colonnes :

12  13  14
22  23  24

En mémoire, les éléments sont stockés de manière contiguë :

mat[0][0] = 12
mat[0][1] = 13
mat[0][2] = 14
mat[1][0] = 22
mat[1][1] = 23
mat[1][2] = 24

Remplissage et affichage d'une matrice sans fonctions

Le programme suivant demande à l'utilisateur le nombre de lignes et de colonnes, puis remplit et affiche la matrice :

#include <stdio.h>

void main()
{
  int l, c, mat[20][30], i, j;
  printf("saisir nombre de lignes et nombre de colonnes");
  scanf("%d%d", &l, &c);

  printf("remplissage de la matrice");
  for (i = 0; i < l; i++)
    for (j = 0; j < c; j++)
      scanf("%d", &mat[i][j]);

  printf("affichage de la matrice");
  for (i = 0; i < l; i++)
  {
    for (j = 0; j < c; j++)
      printf("%d", mat[i][j]);
    printf("\n");
  }
}

On peut aussi saisir l et c avec des fonctions :

l = saisir3(&c);

// ou bien
saisir2(&l);
saisir2(&c);

Remplissage et affichage d'une matrice avec fonctions

Le programme suivant utilise des fonctions pour saisir, remplir et afficher une matrice :

#include <stdio.h>

void main()
{
  int l, c, mat[20][30];
  l = saisir();
  c = saisir();
  remplir((int *)mat, l, c);
  afficher((int *)mat, l, c);
}

Les fonctions associées sont :

int saisir()
{
  int x;
  printf("saisir une valeur");
  scanf("%d", &x);
  return x;
}

void saisir2(int *a)
{
  printf("saisir une valeur");
  scanf("%d", a);
}

int saisir3(int *a)
{
  int b;
  printf("saisir nombre de lignes et nombre de colonnes");
  scanf("%d%d", &b, a);
  return b;
}

void remplir(int *mat, int l, int c)
{
  int i, j;
  printf("remplissage de la matrice");
  for (i = 0; i < l; i++)
    for (j = 0; j < c; j++)
      scanf("%d", mat + i*30 + j);
}

void afficher(int *mat, int l, int c)
{
  int i, j;
  printf("affichage de la matrice");
  for (i = 0; i < l; i++)
  {
    for (j = 0; j < c; j++)
      printf("%d", *(mat + i*30 + j));
    printf("\n");
  }
}

Résultats attendus

  • Affichage correct des valeurs et adresses mémoire dans la manipulation des pointeurs simples, doubles et triples.
  • Modification effective d'une variable passée par adresse dans une fonction.
  • Remplissage et affichage corrects d'un tableau unidimensionnel, avec les valeurs saisies par l'utilisateur.
  • Remplissage et affichage corrects d'une matrice de dimensions l × c, avec les valeurs saisies.
  • Compréhension claire de l'adressage des éléments dans une matrice via l'arithmétique des pointeurs.

Pièges courants

  • Confondre le contenu d'un pointeur et son adresse : utiliser %d pour les entiers et %p pour les adresses.
  • Ne pas respecter le passage par adresse dans les fonctions, ce qui empêche la modification des variables appelantes.
  • Lors du remplissage ou affichage d'un tableau ou matrice, dépasser les limites du tableau (indices hors bornes).
  • Oublier que la matrice est stockée en mémoire de façon contiguë, ce qui implique que l'arithmétique des pointeurs doit tenir compte du nombre de colonnes (ici 30).
  • Confondre les niveaux de pointeurs (simple, double, triple) et leurs déférencements.

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