Exercice 01 :
- Pour déclarer et initialiser une chaîne de caractères en C, il faut utiliser une chaîne de caractères entre guillemets et affecter le résultat à un pointeur de type char. Par exemple :
char *chaine = "Bonjour";
-
Pour concaténer une chaîne de caractères et un caractère en C, on peut utiliser la fonction strncat de la bibliothèque string.h. Cette fonction permet de concaténer un nombre donné de caractères à la fin d'une chaîne de caractères.
Voici un exemple d'utilisation de la fonction strncat pour concaténer un caractère à une chaîne de caractères :
#include <string.h>
#include <stdio.h>
int main(void) {
char chaine[10] = "Bonjour";
strncat(chaine, "!", 1);
printf("Chaîne concaténée : %s\n", chaine); // Affiche "Bonjour!"
return 0;
}
-
Pour déclarer un tableau à deux dimensions en C, il faut préciser le type de données des éléments du tableau, ainsi que les dimensions du tableau. Par exemple, pour déclarer un tableau à deux dimensions de 3 lignes et 4 colonnes de nombres entiers, on peut utiliser la syntaxe suivante :
int tab[3][4];
Pour initialiser le tableau, on peut utiliser la syntaxe suivante :
int tab[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
Il est également possible de ne pas préciser toutes les valeurs du tableau et de laisser le compilateur initialiser les valeurs restantes avec 0 :
int tab[3][4] = { {1, 2}, {5, 6, 7} };
Le tableau tab sera alors initialisé comme suit :
1 2 0 0
5 6 7 0
0 0 0 0
Exercice 02 :
#include <stdio.h>
int main(void) {
int a, b;
printf("Entrez deux nombres : ");
scanf("%d %d", &a, &b);
printf("Calcul du PGCD de %d et %d :\n", a, b);
// Algorithme d'Euclide
while (b != 0) {
int r = a % b;
printf("%d = %d * %d + %d\n", a, a / b, b, r);
a = b;
b = r;
}
printf("Le PGCD de %d et %d est %d.\n", a, b, a);
return 0;
}
L'algorithme d'Euclide consiste à diviser récursivement les deux nombres en entrée par leur reste de la division entière jusqu'à ce que le reste soit égal à 0. Le dernier diviseur non nul est alors le PGCD des deux nombres.
Par exemple, pour calculer le PGCD de 1071 et 462 :
1071 = 2 * 462 + 147
462 = 3 * 147 + 13
147 = 11 * 13 + 4
13 = 3 * 4 + 1
4 = 4 * 1 + 0
Probleme :
1)
#include <stdio.h>
#include <string.h>
typedef struct {
char nom[30];
char prenom[30];
int age;
char classe[10];
} Eleve;
void saisir_eleve(Eleve *e) {
printf("Entrez le nom de l'élève : ");
scanf("%s", e->nom);
printf("Entrez le prénom de l'élève : ");
scanf("%s", e->prenom);
printf("Entrez l'âge de l'élève : ");
scanf("%d", &e->age);
printf("Entrez la classe de l'élève : ");
scanf("%s", e->classe);
}
Il est important de noter que cette fonction ne gère pas les erreurs de saisie (par exemple si l'utilisateur entre un âge qui n'est pas un entier). Il pourrait être intéressant de rajouter des vérifications pour éviter les erreurs de saisie.
2)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char nom[30];
char prenom[30];
int age;
char classe[10];
} Eleve;
void ajouter_eleve(Eleve **tab, int *n) {
Eleve e;
printf("Entrez les informations de l'élève à ajouter :\n");
saisir_eleve(&e); // On utilise la fonction précédemment écrite pour saisir les informations de l'élève
// On vérifie si le tableau est plein
if (*n % 10 == 0) {
// Si le tableau est plein, on le réalloue en lui ajoutant 10 éléments supplémentaires
*tab = realloc(*tab, (*n + 10) * sizeof(Eleve));
}
// On ajoute l'élève à la fin du tableau
(*tab)[*n] = e;
(*n)++;
}
3)
#include <stdio.h>
#include <string.h>
typedef struct {
char nom[30];
char prenom[30];
int age;
char classe[10];
} Eleve;
int supprimer_eleve(Eleve *tab, int n, char *nom, char *prenom) {
// On parcourt le tableau à la recherche de l'élève à supprimer
for (int i = 0; i < n; i++) {
if (strcmp(tab[i].nom, nom) == 0 && strcmp(tab[i].prenom, prenom) == 0) {
// Si on a trouvé l'élève, on décale tous les élèves qui suivent d'une position vers la gauche
for (int j = i; j < n - 1; j++) {
tab[j] = tab[j+1];
}
// On décrémente la taille du tableau
n--;
return 0; // On retourne 0 pour indiquer que l'élève a été trouvé et supprimé
}
}
// Si on arrive ici, c'est que l'élève n'a pas été trouvé
return 1; // On retourne 1 pour indiquer que l'élève n'a pas été trouvé
}
4)
#include <stdio.h>
#include <string.h>
typedef struct {
char nom[30];
char prenom[30];
int age;
char classe[10];
} Eleve;
void tri_selection(Eleve *tab, int n) {
// On parcourt le tableau de la première à l'avant-dernière position
for (int i = 0; i < n - 1; i++) {
// On cherche l'élève le plus petit entre i et la fin du tableau
int min = i;
for (int j = i + 1; j < n; j++) {
if (strcmp(tab[j].nom, tab[min].nom) < 0 ||
(strcmp(tab[j].nom, tab[min].nom) == 0 &&
strcmp(tab[j].prenom, tab[min].prenom) < 0)) {
min = j;
}
}
// On échange les éléments un à un
char tmp_nom[30];
strcpy(tmp_nom, tab[i].nom);
strcpy(tab[i].nom, tab[min].nom);
strcpy(tab[min].nom, tmp_nom);
char tmp_prenom[30];
strcpy(tmp_prenom, tab[i].prenom);
strcpy(tab[i].prenom, tab[min].prenom);
strcpy(tab[min].prenom, tmp_prenom);
int tmp_age = tab[i].age;
tab[i].age = tab[min].age;
tab[min].age = tmp_age;
char tmp_classe[10];
strcpy(tmp_classe, tab[i].classe);
strcpy(tab[i].classe, tab[min].classe);
strcpy(tab[min].classe, tmp_classe);
}
}
Cette fonction utilise l'algorithme de tri par sélection pour trier le tableau tab selon le nom et le prénom des élèves. Le tri est effectué en place, c'est-à-dire que les éléments du tableau sont échangés entre eux sans être copiés dans un autre tableau.
Il est important de noter que cette fonction ne vérifie pas si le tableau est déjà trié avant de lancer l'algorithme. Il serait intéressant de vérifier cela pour éviter de trier inutilement le tableau.
5)
#include <stdio.h>
#include <string.h>
typedef struct {
char nom[30];
char prenom[30];
int age;
char classe[10];
} Eleve;
void afficher_classe(Eleve *tab, int n, char *classe) {
// On parcourt le tableau d'élèves
for (int i = 0; i < n; i++) {
// Si l'élève appartient à la classe donnée, on l'affiche à l'écran
if (strcmp(tab[i].classe, classe) == 0) {
printf("%s %s (%d ans)\n", tab[i].prenom, tab[i].nom, tab[i].age);
}
}
}
Cette procédure parcourt le tableau d'élèves et affiche à l'écran les élèves qui appartiennent à la classe passée en paramètre. Elle utilise la fonction strcmp pour comparer les noms de classe des élèves avec la classe donnée. Si les noms sont identiques, l'élève appartient à la classe et il est affiché à l'écran.
Voici un exemple d'utilisation de la fonction afficher_classe sur un tableau d'élèves contenant quatre éléments :
#include <stdio.h>
#include <string.h>
typedef struct {
char nom[30];
char prenom[30];
int age;
char classe[10];
} Eleve;
int main(void) {
// On déclare et initialise le tableau d'élèves
Eleve tab[] = {
{"Yankam", "Joel", 17, "2nde"},
{"Joel", "Yk", 16, "1re"},
{"Panda", "Codeur", 18, "1re"},
{"Alice", "Bob", 16, "2nde"}
};
int n = 4;
// On affiche les élèves de la classe 1re
afficher_classe(tab, n, "1re");
return 0;
}
Ce programme affiche à l'écran les élèves suivants :
Yk Joel (16 ans)
Codeur Panda (18 ans)
Il est important de noter que la fonction afficher_classe ne modifie pas le contenu du tableau tab, elle ne fait que l'afficher à l'écran. Si vous souhaitez trier le tableau avant de l'afficher, vous pouvez utiliser la fonction tri_selection ou tri_insertion que j'ai précédemment proposées.
6)
#include <stdio.h>
#include <string.h>
typedef struct {
char nom[30];
char prenom[30];
int age;
char classe[10];
} Eleve;
void sauvegarder_eleves(Eleve *tab, int n, char *nom_fichier) {
// On ouvre le fichier en mode "écriture"
FILE *fichier = fopen(nom_fichier, "w");
if (fichier == NULL) {
// Si le fichier n'a pas pu être ouvert, on affiche un message d'erreur et on quitte la fonction
fprintf(stderr, "Erreur lors de l'ouverture du fichier %s\n", nom_fichier);
return;
}
// On parcourt le tableau d'élèves
for (int i = 0; i < n; i++) {
// On écrit les informations de l'élève dans le fichier, séparées par des points-virgules
fprintf(fichier, "%s;%s;%d;%s\n", tab[i].nom, tab[i].prenom, tab[i].age, tab[i].classe);
}
// On ferme le fichier
fclose(fichier);
}
// On ferme le fichier
fclose(fichier);
}
La fonction fclose permet de fermer un fichier qui a été précédemment ouvert avec la fonction fopen. Cette étape est importante car elle permet de libérer les ressources utilisées par le fichier et de permettre à d'autres processus d'accéder au fichier si nécessaire.
Il est recommandé de fermer un fichier dès que vous avez fini de l'utiliser, afin d'éviter des fuites de mémoire ou des conflits d'accès au fichier.