Cours programmation en langage C - Fonctions, Tableaux et Matrices

Ce cours aborde les concepts fondamentaux de la programmation C : pointeurs multiples, passage par adresse, ainsi que le remplissage et l'affichage de tableaux et matrices via des fonctions.

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 cours porte sur la programmation en langage C, plus précisément sur les fonctions, les tableaux et les matrices. Il permet d'apprendre à manipuler les pointeurs, à passer des variables par adresse, à remplir et afficher des tableaux et matrices, ainsi qu'à écrire les entêtes de fonctions complexes. Pour réaliser ces exercices, il est nécessaire de disposer d'un compilateur C et d'un environnement de développement permettant la saisie et l'exécution de programmes C.

Objectifs de la formation

  • Comprendre et utiliser les pointeurs simples, doubles et triples.
  • Apprendre le passage par adresse dans les fonctions.
  • Savoir écrire les entêtes de fonctions avec différents types de paramètres pointeurs.
  • Remplir et afficher des tableaux unidimensionnels en utilisant des fonctions.
  • Remplir et afficher des matrices (tableaux à deux dimensions) en utilisant des fonctions.
  • Manipuler les adresses mémoire et comprendre la correspondance entre indices et adresses dans les matrices.

Prérequis techniques

  • Connaissance de base du langage C (variables, types, fonctions).
  • Compréhension des pointeurs et du passage par adresse.
  • Un compilateur C standard (gcc, clang, etc.).
  • Un éditeur de texte pour écrire les programmes.
  • Connaissance de l'utilisation de la console pour saisir et afficher des données.

Manipulation des pointeurs simples, doubles et triples

La déclaration de pointeurs de différents niveaux permet d'interagir directement avec la mémoire et de comprendre les liens entre adresses et valeurs.

Déclarez les variables suivantes :

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

Affichez les valeurs et les adresses avec les commandes suivantes :

printf("%d", x);      // Affiche 5
printf("%p", &x);      // Affiche l'adresse de x (exemple F800)

printf("%p", m);       // Affiche l'adresse de x (F800)
printf("%p", &m);      // Affiche l'adresse de m (exemple F200)
printf("%d", *m);      // Affiche la valeur pointée par m : 5

printf("%p", q);       // Affiche l'adresse de m (F200)
printf("%p", &q);      // Affiche l'adresse de q (exemple F500)
printf("%p", *q);      // Affiche l'adresse de x (F800)
printf("%d", **q);     // Affiche la valeur pointée par q : 5

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

Cette étape sert à bien visualiser la chaîne de pointeurs et la correspondance entre les adresses et les valeurs. Un résultat correct montre que les adresses correspondent et que la valeur finale est bien 5.

Passage par adresse dans une fonction

Le passage par adresse permet à une fonction de modifier la valeur d'une variable définie dans la fonction appelante.

Exemple de mise en œuvre :

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

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

Dans cette fonction, la variable a pointe vers x de main. Modifier *a dans fct modifie directement x.

Déduction des entêtes de fonctions complexes

L'analyse des arguments passés lors des appels de fonctions permet de déterminer leurs prototypes exacts.

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);
}

Prototypes déduits des fonctions :

  • 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 pour remplir et afficher un tableau unidimensionnel

La modularisation via des fonctions facilite le traitement et la manipulation dynamique de tableaux en C.

#include <stdio.h>

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

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

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));
}

Alternative utilisant l'arithmétique des pointeurs directe avec un pointeur mobile q :

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);
}

Manipulation des matrices (tableaux à deux dimensions)

Une matrice déclarée par int mat[20][30] réserve un espace contigu de 600 cases mémoire en C.

Organisation mémoire et calcul d'adresses :

  • mat[i][j] désigne l'élément situé à la ligne i et à la colonne j.
  • L'adresse de cet élément s'obtient via la formule mat + i*30 + j ou avec l'opérateur d'adresse &mat[i][j].

Exemple d'implémentation directe sans passage de fonctions :

#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");
  }
}

Alternatives pour la saisie des dimensions :

l = saisir3(&c);

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

Remplissage et affichage d'une matrice avec fonctions

L'utilisation de fonctions pour les matrices nécessite un cast explicite pour convertir la structure bidimensionnelle en pointeur simple.

#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);
}

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

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");
  }
}

La conversion (int *)mat est indispensable pour transmettre le premier élément du tableau à une fonction dont le paramètre est de type int *.

Résultats attendus

  • Affichage correct des valeurs et adresses lors de la manipulation des pointeurs simples, doubles et triples.
  • Modification effective d'une variable passée par adresse dans une fonction.
  • Entêtes de fonctions correctes correspondant aux appels donnés.
  • Tableau rempli et affiché correctement avec les valeurs saisies.
  • Matrice remplie et affichée avec les bonnes dimensions et valeurs, respectant la correspondance entre indices et adresses.

Erreurs fréquentes

  • Confusion entre les différents niveaux de pointeurs (ex. utiliser * au lieu de ** ou ***).
  • Oublier de passer l'adresse d'une variable avec & lors d'un passage par adresse.
  • Utiliser un mauvais format dans printf : toujours utiliser %d pour les entiers et %p pour les adresses.
  • Ne pas respecter la taille du tableau ou de la matrice lors des boucles de saisie ou d'affichage, ce qui peut provoquer des dépassements.
  • Passer la matrice à une fonction sans la convertir en pointeur simple (int *)mat lorsque la fonction attend un int *.
  • Oublier d'initialiser les pointeurs avant de les utiliser.

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