EXERCICE 01 :
A) --------------
1) La déclaration int tab[4][5] crée un tableau à deux dimensions de 4 lignes et 5 colonnes, contenant des entiers. Chaque élément du tableau est identifié par deux indices, le premier pour la ligne et le second pour la colonne. Voici une représentation schématique du tableau :
2) Le contenu de tab est un ensemble de valeurs entières, stockées dans la mémoire de l'ordinateur. En C, un tableau à deux dimensions est en fait un tableau de tableaux, c'est-à-dire que chaque élément de tab est lui-même un tableau d'entiers. Le nom tab représente l'adresse du premier élément du tableau, c'est-à-dire le tableau tab[0].
3) tab[i][j] désigne la valeur de l'élément situé à la ligne i et à la colonne j du tableau tab, avec 0<=i<4 et 0<=j<5. Par exemple, tab[2][3] désigne la valeur de l'élément en troisième ligne et quatrième colonne.
4) tab[i] désigne le tableau d'entiers situé à la ligne i du tableau tab, avec 0<=i<4. Par exemple, tab[1] désigne le tableau [tab[1][0], tab[1][1], tab[1][2], tab[1][3], tab[1][4]]. Le nom tab[i] représente l'adresse du premier élément du tableau, c'est-à-dire tab[i][0].
5) (tab[i]+j) désigne l'adresse de l'élément situé à la ligne i et à la colonne j du tableau tab, avec 0<=i<4 et 0<=j<5. Par exemple, (tab[2]+3) désigne l'adresse de l'élément tab[2][3]. Cette expression est équivalente à &tab[i][j].
6) *(tab[i]+j) désigne la valeur de l'élément situé à la ligne i et à la colonne j du tableau tab, avec 0<=i<4 et 0<=j<5. Par exemple, *(tab[2]+3) désigne la valeur de l'élément tab[2][3]. Cette expression est équivalente à tab[i][j].
7) Oui, on peut modifier la valeur de tab[i][j] en utilisant une instruction d'affectation, comme par exemple tab[i][j] = 42;. Cela va remplacer la valeur précédente de l'élément par la nouvelle valeur.
8) &(tab[i][j]) désigne l'adresse de l'élément situé à la ligne i et à la colonne j du tableau tab, avec 0<=i<4 et 0<=j<5. Par exemple, &(tab[2][3]) désigne l'adresse de l'élément tab[2][3]. Cette expression est équivalente à (tab[i]+j).
B) ---------------
1) Deux syntaxes possibles pour désigner l'adresse de début de la ligne i sont :
- tab[i] : le nom du tableau correspondant à la ligne i
- &tab[i][0] : l'adresse du premier élément de la ligne i
2) Deux syntaxes possibles pour désigner l'adresse de la case située à l'intersection de la ligne i et de la colonne j de tab sont :
- (tab[i]+j) : l'addition de l'adresse de début de la ligne i et de l'indice j
- &tab[i][j] : l'opérateur d'adressage appliqué à l'élément tab[i][j]
3) Deux syntaxes possibles pour désigner le contenu de la case située à l'intersection de la ligne i et de la colonne j de tab sont :
- tab[i][j] : l'accès direct à l'élément du tableau par ses deux indices
- *(tab[i]+j) : la déréférenciation de l'adresse de la case.
C)-------------
1) Valide , ptint=tab1;
Nous savons que le nom d'un tableau donne accès à l'adresse de la zone occupée par le tableau. Cette instruction est donc correcte.
2) inValide, ptint=&tab1;
tab1 est un tableau de taille fixe, réservé au moment de la compilation. L'utilisation du nom donne accès à l'adresse de la zone réservée. Demander l'adresse de cette adresse par l'emploi de l'opérateur n'a pas de sens, car cette valeur est une constante adresse.
L'utilisation de l'opérateur & n'a pas de signification. Dans ce cas, le compilateur gcc signale cette utilisation inadéquate et l'ignore. C'est pourquoi une telle instruction ne provoque pas l'arrêt de la compilation.
3)valide, ptint=&tab1[0];
Cette instruction permet d'affecter à ptint l'adresse du 1er élément du tableau.
Elle est équivalent à ptint=&tab1.
4) valide, ptint1=tab3;
Affectation simple entre 2 pointeurs de même type.
5) invalide, ptint1=&tab3;
tab3 est un pointeur sur un entier. &tab3 est donc l'adresse d'un tableau d'entiers. Le type de cette donnée est int **. Les types des opérandes de l'affectation sont différents et aucune conversion implicite n'est possible. C'est une erreur !
6) tab1, tab2 et tab3 sont des tableaux de 6 entiers.
Valide, tab1 et tab2 sont des tableaux et, à ce titre, leurs adresses sont des constantes. tab3 est un pointeur sur un entier qui peut être modifié. Il existe une conversion implicite entre pointeur et tableau permettant d'utiliser l'opérateur [ ] sur un pointeur.
7)++tab1;
non valide, tab1 est un tableau. Le nom peut être utilisé pour l'application de l'opérateur [ ] ou dans une expression adresse. Une expression ne peut être incrémentée.
8) valide, ++tab3;
tab3 est une variable pointeur qui peut être incrémentée.
EXERCICE 2 :
Nom le plus long
#include <stdio.h>
#include <string.h>
int main() {
char nom[100]; // un tableau pour stocker le nom saisi
char plus_long[100] = ""; // un tableau pour stocker le nom le plus long
int longueur; // une variable pour stocker la longueur du nom saisi
int max = 0; // une variable pour stocker la longueur maximale
printf("Entrez une serie de noms terminee par le marqueur \"fin\":\n");
do {
scanf("%s", nom); // lire le nom saisi
longueur = strlen(nom); // calculer la longueur du nom
if (longueur > max && strcmp(nom, "fin") != 0) { // si le nom est plus long que le maximum et n'est pas le marqueur
max = longueur; // mettre à jour le maximum
strcpy(plus_long, nom); // copier le nom dans le tableau plus_long
}
} while (strcmp(nom, "fin") != 0); // répéter tant que le nom n'est pas le marqueur
printf("Le nom le plus long est : %s\n", plus_long); // afficher le nom le plus long
return 0;
}
2------
- Le principe du produit scalaire est de multiplier les coefficients correspondants de deux vecteurs de même taille et de faire la somme des produits obtenus. Le résultat est un nombre réel. Par exemple, si $$\vec{u} = (u_1, u_2, u_3)$$ et $$\vec{v} = (v_1, v_2, v_3)$$, alors le produit scalaire de $$\vec{u}$$ et $$\vec{v}$$ est $$\vec{u} \cdot \vec{v} = u_1v_1 + u_2v_2 + u_3v_3$$.
- Un programme qui lit les coefficients de deux vecteurs de taille N=5 et retourne la valeur de leur produit scalaire est :
#include <stdio.h>
#define N 5 // la taille des vecteurs
int main() {
double u[N]; // le premier vecteur
double v[N]; // le deuxième vecteur
double ps = 0; // le produit scalaire
int i; // une variable pour parcourir les vecteurs
printf("Entrez les coefficients du premier vecteur:\n");
for (i = 0; i < N; i++) { // pour chaque coefficient du premier vecteur
scanf("%lf", &u[i]); // lire la valeur saisie
}
printf("Entrez les coefficients du deuxième vecteur:\n");
for (i = 0; i < N; i++) { // pour chaque coefficient du deuxième vecteur
scanf("%lf", &v[i]); // lire la valeur saisie
}
for (i = 0; i < N; i++) { // pour chaque coefficient des deux vecteurs
ps += u[i] * v[i]; // ajouter le produit des coefficients au produit scalaire
}
printf("Le produit scalaire des deux vecteurs est : %lf\n", ps); // afficher le produit scalaire
return 0;
}
3----------
- La matrice identité est une matrice carrée dont tous les éléments sont nuls sauf ceux de la diagonale principale qui sont égaux à 1. Par exemple, la matrice identité d'ordre 3 est :
$$
\begin{pmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{pmatrix}
$$
- Un programme qui déclare une matrice carrée d'ordre N=10 et l'initialise à la matrice identité est :
#include <stdio.h>
#define N 10 // l'ordre de la matrice
int main() {
int mat[N][N]; // la matrice carrée
int i, j; // des variables pour parcourir la matrice
for (i = 0; i < N; i++) { // pour chaque ligne de la matrice
for (j = 0; j < N; j++) { // pour chaque colonne de la matrice
if (i == j) { // si on est sur la diagonale principale
mat[i][j] = 1; // mettre la valeur 1
} else { // sinon
mat[i][j] = 0; // mettre la valeur 0
}
}
}
printf("La matrice identite d'ordre %d est :\n", N);
for (i = 0; i < N; i++) { // pour chaque ligne de la matrice
for (j = 0; j < N; j++) { // pour chaque colonne de la matrice
printf("%d ", mat[i][j]); // afficher l'élément de la matrice
}
printf("\n"); // passer à la ligne suivante
}
return 0;
}
4---------
Egalité matricielle
- Deux matrices sont égales si elles ont la même taille et les mêmes coefficients. Par exemple, les matrices $$A = \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{pmatrix}$$ et $$B = \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{pmatrix}$$ sont égales, mais les matrices $$C = \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 10 \end{pmatrix}$$ et $$D = \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{pmatrix}$$ ne le sont pas.
- Un programme qui lit les coefficients de deux matrices carrées d'ordre N=3 et dit si elles sont égales est :
#include <stdio.h>
#define N 3 // l'ordre des matrices
int main() {
int A[N][N]; // la première matrice
int B[N][N]; // la deuxième matrice
int egal = 1; // une variable pour indiquer si les matrices sont égales
int i, j; // des variables pour parcourir les matrices
printf("Entrez les coefficients de la premiere matrice:\n");
for (i = 0; i < N; i++) { // pour chaque ligne de la première matrice
for (j = 0; j < N; j++) { // pour chaque colonne de la première matrice
scanf("%d", &A[i][j]); // lire la valeur saisie
}
}
printf("Entrez les coefficients de la deuxieme matrice:\n");
for (i = 0; i < N; i++) { // pour chaque ligne de la deuxième matrice
for (j = 0; j < N; j++) { // pour chaque colonne de la deuxième matrice
scanf("%d", &B[i][j]); // lire la valeur saisie
}
}
for (i = 0; i < N; i++) { // pour chaque ligne des matrices
for (j = 0; j < N; j++) { // pour chaque colonne des matrices
if (A[i][j] != B[i][j]) { // si les coefficients sont différents
egal = 0; // mettre la variable à 0
break; // sortir de la boucle
}
}
if (egal == 0) { // si la variable est 0
break; // sortir de la boucle
}
}
if (egal == 1) { // si la variable est 1
printf("Les matrices sont egales.\n"); // afficher que les matrices sont égales
} else { // sinon
printf("Les matrices ne sont pas egales.\n"); // afficher que les matrices ne sont pas égales
}
return 0;
}
5---------
#include <stdio.h>
#define N 10
int main() {
int A[N][N], X[N], result[N];
// Entrée : Saisie des coefficients de la matrice A et du vecteur X
// Affichage de la matrice A
printf("Matrice A:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
// Saisie des coefficients pour A[i][j]
scanf("%d", &A[i][j]);
printf("%d ", A[i][j]);
}
printf("\n");
}
// Affichage du vecteur X
printf("\nVecteur X:\n");
for (int i = 0; i < N; i++) {
// Saisie des coefficients pour X[i]
scanf("%d", &X[i]);
printf("%d\n", X[i]);
}
// Calcul du produit matrice-vecteur
printf("\nRésultat du produit matrice-vecteur AX:\n");
for (int i = 0; i < N; i++) {
result[i] = 0;
for (int j = 0; j < N; j++) {
result[i] += A[i][j] * X[j];
}
printf("%d\n", result[i]);
}
return 0;
}
6----------
#include <stdio.h>
#define N 10
int main() {
int A[N][N], B[N][N], result[N][N];
// Entrée : Saisie des coefficients des matrices A et B
// Affichage de la matrice A
printf("Matrice A:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
// Saisie des coefficients pour A[i][j]
scanf("%d", &A[i][j]);
printf("%d ", A[i][j]);
}
printf("\n");
}
// Affichage de la matrice B
printf("\nMatrice B:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
// Saisie des coefficients pour B[i][j]
scanf("%d", &B[i][j]);
printf("%d ", B[i][j]);
}
printf("\n");
}
// Calcul du produit matrice-matrice
printf("\nRésultat du produit matrice-matrice AB:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
result[i][j] = 0;
for (int k = 0; k < N; k++) {
result[i][j] += A[i][k] * B[k][j];
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%d ", result[i][j]);
}
printf("\n");
}
return 0;
}
7---------
#include <stdio.h>
#define N 10
int main() {
int A[N][N], B[N][N];
int countEqual = 0;
// Entrée : Saisie des coefficients des matrices A et B
// Comparaison des coefficients
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
// Saisie des coefficients pour A[i][j] et B[i][j]
scanf("%d", &A[i][j]);
scanf("%d", &B[i][j]);
if (A[i][j] == B[i][j]) {
countEqual++;
}
}
}
// Affichage du nombre de coefficients égaux
printf("Nombre de coefficients égaux : %d\n", countEqual);
return 0;
}