Logo de kxs.frCours d'informatique pour le lycée et la prépa

Tableaux

Un tableau contient des valeurs stockées consécutivement en mémoire. Cette disposition permet un accès rapide à chaque élément (en temps constant).

Déclaration

La taille d'un tableau est fixe en C. Il faut donc toujours donner l'information de la taille lorsqu'on déclare un tableau. Il faut aussi indiquer le type de valeurs stockées dans le tableau. Voici donc plusieurs façons de déclarer un tableau :

int t[3]; // On indique la taille du tableau entre crochets
t[0] = 1; // Le premier élément possède l'indice 0
t[1] = 2;
t[2] = 4;
printf("%d %d %d\n", t[0], t[1], t[2]);
int t[3] = {1, 2, 4}; // On initialise directement le tableau
printf("%d %d %d\n", t[0], t[1], t[2]);
int t[] = {1, 2, 4}; // Il n'est pas nécessaire de donner explicitement la taille
printf("%d %d %d\n", t[0], t[1], t[2]);

On peut également initialiser tous les éléments du tableau a la même valeur :

int t[3] = {0}; // On initialise le tableau avec des 0
printf("%d %d %d\n", t[0], t[1], t[2]);

Accès aux éléments

On utilise la notation t[i] pour accéder à l'élément i du tableau.

Attention ! Il n'y a aucun garde-fou en C, la taille du tableau n'est stockée nulle part, il est donc possible de faire des accès en dehors du tableau sans provoquer d'erreur. En effet la notation t[i] permet simplement d'accéder aux adresses consécutives du tableau. Voici un exemple d'utilisation de la mémoire pour le tableau précedent initialisé avec des 0 :

mémoire 0 t[0] 0 t[1] 0 t[2] ? t[3]

Essayez le code suivant pour voir qu'il n'y a pas d'erreur :

#include <stdio.h>

int main() {
	int t[3] = {0}; // On initialise le tableau avec des 0
	printf("%d %d %d %d\n", t[0], t[1], t[2], t[3]); // On sort du tableau
}

Par contre si on va trop loin on peut obtenir une erreur de segmentation :

#include <stdio.h>

int main() {
	int t[3] = {0}; // On initialise le tableau avec des 0
	printf("%d %d %d %d\n", t[0], t[1], t[2], t[5321654]); // On sort trop du tableau !
}

1) Écrire un programme qui crée un tableau de 10 éléments (sans l'initialiser) et affiche le contenu de tous les éléments avec une boucle.

#include <stdio.h>

int main() {
	int tab[10];
	for (int i = 0; i < 10; i++){
		printf("%d\n", tab[i]);
	}
}
2
0
395049983
0
719465561
32764
100
0
4096
0

Le contenu du tableau est aléatoire.

2) Écrire un programme qui crée un tableau de 100 éléments, l'initialise avec la position de chaque élément (t[0] = 0 etc.) et affiche le contenu de tous les éléments.

#include <stdio.h>

int main() {
	int tab[100];
	
	for (int i = 0; i < 100; i++){
		tab[i] = i;
	}
	
	for (int i = 0; i < 100; i++){
		printf("%d\n", tab[i]);
	}
}

Passage d'un tableau dans une fonction

La variable d'un tableau est en fait un pointeur vers le premier élément du tableau. Quand on passe un tableau en paramètre d'une fonction, on fournit alors l'adresse du tableau (qui est bien passée par valeur). Ce qui revient à passer le tableau par référence. Il est donc possible de modifier un tableau dans une fonction :

#include <stdio.h>

void met1(int t[]) {
	// Fonction qui met à 1 le premier élément du tableau
	t[0] = 1;
}

int main() {
	int t[3] = {0}; // On initialise le tableau avec des 0
	printf("%d %d %d\n", t[0], t[1], t[2]);
	
	met1(t);
	
	printf("%d %d %d\n", t[0], t[1], t[2]);
}

La taille d'un tableau n'étant pas connue, il faut en général fournir dans un paramètre supplémentaire la taille du tableau à une fonction.

3) Créer une fonction void intTab(int t[], int taille, int valeur); qui initialise à valeur toutes les valeurs du tableau t de taille taille.

#include <stdio.h>

void intTab(int t[], int taille, int valeur) {
	for (int i = 0; i < taille; i++) {
		t[i] = valeur;
	}
}

int main() {
	int t[20];
	intTab(t, 20, 5);
	
	// On affiche le contenu du tableau
	for (int i = 0; i < 20; i++) {
		printf("%d ",t[i]);
	}
	printf("\n");
}

Allocation dynamique

Il est possible d'avoir besoin de définir un tableau avec une taille qui n'est pas connue à la compilation. Il est alors nécessaire de faire ce qu'on appelle une allocation dynamique de la mémoire.

Il est possible avec certains compilateurs de faire une allocation dynamique avec la notation habituelle en utilisant une variable pour la taille :

int a = 10;
int t[a];

Il est déconseillé d'utiliser cette syntaxe car elle n'est pas acceptée par tous les compilateurs. Il faut utiliser malloc qui va allouer le bon nombre de cases mémoire et renverra alors un pointeur vers la première case du tableau :

int a = 10;
int *t = malloc(a * sizeof(int));

De la même façon qu'avec l'allocation statique, on peut accéder aux éléments du tableau avec la notation t[i].

4) Créer un programme qui demande le nombre de notes d'un étudiant puis lui demande ses notes et les enregistre dans un tableau. Enfin le programme lui donne sa moyenne.

#include <stdio.h>
#include <stdlib.h>

int main() {
	int nb;
	
	printf("Combien de notes avez-vous ? ");
	scanf("%d", &nb);
	
	// Allocation dynamique
	int *notes = malloc(nb*sizeof(int));
	
	// On demande les notes
	for (int i = 0; i < nb; i++) {
		int note;
		printf("Note %d : ", i+1);
		scanf("%d", &note);
		notes[i] = note;
	}
	
	// On calcul la moyenne et on l'affiche
	int total = 0;
	for (int i = 0; i < nb; i++) {
		total = total + notes[i];
	}
	printf("La moyenne est %.2f\n", (float)total / (float)nb);
}

Tableau à deux dimensions

On peut créer des tableaux à deux dimensions (même plus) avec la notation suivante pour un tableau de 6 lignes et 7 colonnes :

int t[6][7];

On accède alors aux éléments avec la notation t[i][j].

Un espace mémoire de 6 blocs consécitifs de 7 entiers consécutifs est alors alloué.

Pour effectuer une allocation dynamique il faut d'abord déclarer un tableau de pointeurs vers des entiers puis déclarer chaque élément de ce tableau comme un tableau d'entiers :

int **tab = malloc(6 * sizeof(int*));
for (int i=0; i<6; i++) {
	tab[i] = malloc(7 * sizeof(int));
}

5) Créer un programme qui permet de saisir une matrice d'entiers de taille quelconque puis de l'afficher de manière « esthétique ». On pourra supposer qu'elle contient seulement des chiffres dans un premier temps. On pourra par exemple faire un affichage comme ceci :

┌       ┐
| 1 2 3 |
| 4 5 6 |
| 7 8 9 |
└       ┘