Partie 1 - Bases de C

p1e1 : pointeurs simples et pointeurs sur tableaux

Écrire une fonction division_et_reste qui effectue la division entière de deux entiers positifs a et b.

La fonction ne retourne rien, mais stocke le quotient et le reste dans deux variables passées par adresse.

Écrire une fonction min_et_max qui recherche, dans un tableau d’entiers, le plus petit et le plus grand élément.

Les résultats seront renvoyés par deux variables passées par adresse.

Résultat attendu :

17 / 5 = 3, reste = 2

Tableau : 5, 9, 2, 7, 3
        - min : 2
        - max : 9

p1e2 : pointeurs et structures

Définir une structure Duration contenant 3 entiers non signés (unsigned int) : heures, minutes, secondes.

Dans le main, déclarez et initialisez :

  • d1 à 0h150min500s (volontairement non normalisée, donnera 2h38m20s en normalisé),

  • d2 à 5h35min58s,

  • d3 à 2h45min06s.

Implémentez :

  • void print_duration(const Duration *d) affiche la durée au format hh:mm:ss (ex. 05:35:58, 02:45:06).

  • void normalize_duration(Duration *d) normalise la durée (ex. 75s → 1m15s, 70min130s → 1h12min10s).

  • void add_duration(const Duration *d1, const Duration *d2, Duration *result) calcule result = d1 + d2, puis normalise result.

Testez ces fonctions avec d1, d2, d3 et une variable Duration sum pour stocker les résultats.

Résultat attendu :

$ ./p1e1
d1 brut      : 00:150:500
d1 normalise : 02:38:20
d2           : 05:35:58
d3           : 02:45:06
d1 + d2 = 08:14:18
d2 + d3 = 08:21:04
d1 + d3 = 05:23:26

p1e3 : création de tableau dynamique

Proposer un programme C qui demande :

  • de saisir une taille de tableau. La taille doit être > 0, sinon fin du programme

  • puis alloue dynamiquement un tableau d’entiers de cette taille (voir gestion dynamique de la mémoire)

  • remplit le tableau avec des valeurs aléatoires (voir gestion de l’aléatoire) comprises dans l’intervalle [50, 100[

  • puis affiche le contenu du tableau avec une fonction void print_table(const int* tab, int n).

Vérifier qu’il n’y ait pas de fuites mémoire.

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p1e3.c -o p1e3 && valgrind ./p1e3
... affichage de valgrind
Taille du tableau (>0) : 20
Contenu du tableau : 66 81 75 64 77 73 66 83 59 99 72 83 72 65 98 69 59 99 79 93
... affichage de valgrind sans fuites mémoire

p1e4 : modification de tableau dynamique

Reprendre le code précédent et, en plus, on changera la taille du tableau (en gardant les données initiales) en fonction d’une nouvelle taille saisie par l’utilisateur. Si la taille est plus grande, il faut ajouter de nouvelles valeurs aléatoires.

On affichera le nouveau tableau.

Vérifier qu’il n’y ait pas de fuites mémoire.

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p1e4.c -o p1e4 && valgrind ./p1e4
... affichage de valgrind
Taille du tableau (>0) : 20
Tableau initial : 57 75 71 71 99 91 73 73 81 87 65 76 94 73 78 80 51 56 67 79
Nouvelle taille (>0) : 10
Nouveau tableau : 57 75 71 71 99 91 73 73 81 87
... affichage de valgrind sans fuites mémoire
$ gcc -std=c2x -Wall -Wextra -pedantic -g p1e4.c -o p1e4 && valgrind ./p1e4
... affichage de valgrind
Taille du tableau (>0) : 10
Tableau initial : 51 72 71 50 66 81 55 96 55 83
Nouvelle taille (>0) : 20
Nouveau tableau : 51 72 71 50 66 81 55 96 55 83 90 90 92 50 76 66 87 56 98 58
... affichage de valgrind sans fuites mémoire

p1e5 : tableau de chaînes de caractères

Proposer un programme C qui :

  • saisit un nombre n de chaînes

  • alloue dynamiquement un tableau de n chaînes de caractères

  • le remplit avec des valeurs saisies dans le terminal, les chaînes de caractères doivent aussi être allouées dynamiquement (en utilisant la taille de chaque chaîne entrée)

  • une fois que les n chaînes sont enregistrées, il parcourt toutes les chaînes et regarde si la chaîne "coucou" est présente et affiche son indice

  • pour finir, il affiche les chaînes du tableau

Fonctions utiles (inclure string.h) :

  • strlen(chaîne) pour avoir la taille d’une chaîne

  • strcpy(tableauCible, tableauACopier) pour copier une chaîne

  • fgets(chaîne, maxLength, stream) pour remplacer scanf qui permet de lire des espaces. Dans notre cas, le flux d’entrée (stream) sera stdin

  • atoi(chaîne) pour convertir une chaîne en entier

  • int strcmp(const char *s1, const char *s2) pour comparer deux chaînes. Retourne 0 si elles sont égales.

Voici une fonction read_line qui lit une entrée utilisateur et retire le \n :

/**
* @brief Lit une ligne (y compris espaces) dans buffer, retire le '\n' si
* présent
*
* @param buffer variable dans laquelle écrire les données
* @param cap nombre de caractère maximum
*/
void read_line(char *buffer, size_t cap) {
    if (fgets(buffer, (int)cap, stdin)) {
        size_t len = strlen(buffer);
        if (len && buffer[len - 1] == '\n') {
            buffer[len - 1] = '\0';
        }
    }
}

Vérifier qu’il n’y ait pas de fuites mémoire.

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p1e5.c -o p1e5 && valgrind ./p1e5
... affichage de valgrind
Nombre de chaines : 3
Chaîne 1 : hello
Chaîne 2 : hey
Chaîne 3 : hej

À la recherche de coucou...
coucou n'est pas dans le tableau

Affichage final :
[0] hello
[1] hey
[2] hej

... affichage de valgrind sans fuites mémoire
$ valgrind ./p1e5
... affichage de valgrind
Nombre de chaines : 3
Chaîne 1 : hello
Chaîne 2 : coucou
Chaîne 3 : hej

À la recherche de coucou...
coucou est trouvé à l'indice 1

Affichage final :
[0] hello
[1] coucou
[2] hej
... affichage de valgrind sans fuites mémoire

p1e6 : création de matrice dynamique

Proposer un programme C qui :

  • demande à l’utilisateur un nombre de lignes nb_row et de colonnes nb_col

  • alloue dynamiquement une matrice (int **) d’entiers de taille nb_row*nb_col (strictement positifs) avec l’aide d’une fonction int **alloc_matrix(int rows, int cols)

  • la remplit avec des valeurs aléatoires dans l’intervalle [20,60[

  • puis l’affiche avec une fonction void print_table(const int *tab, int row, int cols) qui met une tabulation entre chaque élément et revient à la ligne à chaque nouvelle ligne

  • puis deux fonctions int *sum_rows(int **matrix, int rows, int cols); et int *sum_columns(int **matrix, int rows, int cols); qui calculent la somme des éléments sur les lignes et les colonnes et retourne un tableau contenant les sommes, que vous afficherez dans le main

Vérifier qu’il n’y ait pas de fuites mémoire.

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p1e6.c -o p1e6 && valgrind ./p1e6
... affichage de valgrind
Nombre de lignes (>0) : 5
Nombre de colonnes (>0) : 3
Matrice 5x3 :
41      54      24
51      57      23
41      32      36
28      39      47
23      33      30
Sum rows :
119     131     109     114     86
Sum cols :
184     215     160
... affichage de valgrind sans fuites mémoire