Content is user-generated and unverified.

Solutions TD3 - Structures, Pointeurs et Listes chaînées

Exercice 1 : Déclaration de structures

Structure point (coordonnées entières)

Sans typedef :

c
struct point {
    int x;
    int y;
};

Avec typedef :

c
typedef struct point {
    int x;
    int y;
} Point;

Structure rectangle

Sans typedef :

c
struct rect {
    int x1, y1;  // coordonnées du coin supérieur gauche
    int x2, y2;  // coordonnées du coin inférieur droit
};

Avec typedef :

c
typedef struct rect {
    int x1, y1;
    int x2, y2;
} Rectangle;

Exercice 2 : Répertoire téléphonique

Implémentation des structures

c
#include <stdio.h>
#include <string.h>

// Structure date
typedef struct date {
    int jour;
    int mois;
    int annee;
} Date;

// Structure client
typedef struct client {
    char nom[50];
    char prenom[50];
    char ville[50];
    Date datenaiss;
    long numtel;
    float solde;
    Date daterecharge;
} Client;

Exercice 3 : Nombres rationnels

Définition et fonctions

c
#include <stdio.h>

// Structure Rationnel
typedef struct rationnel {
    int numerateur;
    int denominateur;
} Rationnel;

// Fonction de saisie
Rationnel saisir_rationnel() {
    Rationnel r;
    printf("Entrez le numérateur : ");
    scanf("%d", &r.numerateur);
    do {
        printf("Entrez le dénominateur (non nul) : ");
        scanf("%d", &r.denominateur);
    } while (r.denominateur == 0);
    return r;
}

// Fonction d'affichage
void afficher_rationnel(Rationnel r) {
    if (r.denominateur == 1) {
        printf("%d", r.numerateur);
    } else {
        printf("%d/%d", r.numerateur, r.denominateur);
    }
}

// Fonction de multiplication
Rationnel multiplier_rationnels(Rationnel r1, Rationnel r2) {
    Rationnel resultat;
    resultat.numerateur = r1.numerateur * r2.numerateur;
    resultat.denominateur = r1.denominateur * r2.denominateur;
    return resultat;
}

// Fonction d'addition
Rationnel additionner_rationnels(Rationnel r1, Rationnel r2) {
    Rationnel resultat;
    resultat.numerateur = r1.numerateur * r2.denominateur + r2.numerateur * r1.denominateur;
    resultat.denominateur = r1.denominateur * r2.denominateur;
    return resultat;
}

// Fonction principale de test
int main() {
    Rationnel r1, r2, somme, produit;
    
    printf("Saisie du premier rationnel :\n");
    r1 = saisir_rationnel();
    
    printf("Saisie du second rationnel :\n");
    r2 = saisir_rationnel();
    
    printf("Premier rationnel : ");
    afficher_rationnel(r1);
    printf("\nSecond rationnel : ");
    afficher_rationnel(r2);
    
    somme = additionner_rationnels(r1, r2);
    printf("\nSomme : ");
    afficher_rationnel(somme);
    
    produit = multiplier_rationnels(r1, r2);
    printf("\nProduit : ");
    afficher_rationnel(produit);
    
    return 0;
}

Exercice 4 : Structures imbriquées (Wagon et Train)

Solutions complètes

c
#include <stdio.h>
#define MAX_WAGONS 50

// 1. Structure wagon
typedef struct wagon {
    int s;  // nombre de sièges
    int p;  // nombre de passagers
} WAGON;

// 2. Fonction places disponibles
int wagon_places_dispo(WAGON W) {
    return W.s - W.p;
}

// 3. Fonction ajouter passagers
int wagon_ajouter_passagers(WAGON *W, int x) {
    int places_dispo = wagon_places_dispo(*W);
    if (x <= places_dispo) {
        W->p += x;
        return 0;  // tous les passagers ont trouvé place
    } else {
        W->p = W->s;  // wagon plein
        return x - places_dispo;  // passagers sans place
    }
}

// 4. Fonction initialiser tableau de wagons
void wagon_init(WAGON T[], int n) {
    for (int i = 0; i < n; i++) {
        T[i].s = 90;
        T[i].p = 0;
    }
}

// 5. Structure train
typedef struct train {
    int nb_wagons;
    WAGON T[MAX_WAGONS];
} TRAIN;

// 6. Fonction initialiser train
void train_init(TRAIN *Tr) {
    Tr->nb_wagons = 0;
    for (int i = 0; i < MAX_WAGONS; i++) {
        Tr->T[i].s = 90;
        Tr->T[i].p = 0;
    }
}

// 7. Fonction fusionner deux trains
TRAIN train_ajouter_train(TRAIN Tr1, TRAIN Tr2) {
    TRAIN nouveau_train;
    train_init(&nouveau_train);
    
    // Copier les wagons du premier train
    for (int i = 0; i < Tr1.nb_wagons; i++) {
        nouveau_train.T[i] = Tr1.T[i];
    }
    nouveau_train.nb_wagons = Tr1.nb_wagons;
    
    // Ajouter les wagons du second train
    for (int i = 0; i < Tr2.nb_wagons && nouveau_train.nb_wagons < MAX_WAGONS; i++) {
        nouveau_train.T[nouveau_train.nb_wagons] = Tr2.T[i];
        nouveau_train.nb_wagons++;
    }
    
    return nouveau_train;
}

// 8. Fonction ajouter wagon à un train
void train_ajouter_wagon(TRAIN *Tr, WAGON W) {
    if (Tr->nb_wagons < MAX_WAGONS) {
        Tr->T[Tr->nb_wagons] = W;
        Tr->nb_wagons++;
    }
}

// 9. Fonction ajouter passagers au train
void train_ajouter_passagers(TRAIN *Tr, int x) {
    int passagers_restants = x;
    
    // Remplir les wagons existants
    for (int i = 0; i < Tr->nb_wagons && passagers_restants > 0; i++) {
        passagers_restants = wagon_ajouter_passagers(&Tr->T[i], passagers_restants);
    }
    
    // Ajouter de nouveaux wagons si nécessaire
    while (passagers_restants > 0 && Tr->nb_wagons < MAX_WAGONS) {
        WAGON nouveau_wagon;
        nouveau_wagon.s = 90;
        nouveau_wagon.p = 0;
        
        passagers_restants = wagon_ajouter_passagers(&nouveau_wagon, passagers_restants);
        train_ajouter_wagon(Tr, nouveau_wagon);
    }
}

// 10. Fonction tri des wagons par nombre de passagers
void train_tri_wagon(TRAIN *T) {
    // Tri par sélection
    for (int i = 0; i < T->nb_wagons - 1; i++) {
        int min_idx = i;
        for (int j = i + 1; j < T->nb_wagons; j++) {
            if (T->T[j].p < T->T[min_idx].p) {
                min_idx = j;
            }
        }
        // Échanger les wagons
        WAGON temp = T->T[i];
        T->T[i] = T->T[min_idx];
        T->T[min_idx] = temp;
    }
}

Exercice 5 : QCM

Réponses :

  1. Étapes d'allocation dynamique :
    • Réponse correcte : malloc, vérification de la validité du pointeur, utilisation de la mémoire, free
  2. malloc(25*sizeof(int)) :
    • Réponse correcte : Cela réserve de la mémoire pour un tableau d'int de 25 cases

Exercice 6 : Nombres complexes

Solution complète

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

// 1. Structure Complexe
typedef struct complexe {
    float reel;
    float imaginaire;
} Complexe;

// 2. Fonction saisir complexe
Complexe saisir_complexe() {
    Complexe c;
    printf("Entrez la partie réelle : ");
    scanf("%f", &c.reel);
    printf("Entrez la partie imaginaire : ");
    scanf("%f", &c.imaginaire);
    return c;
}

// 3. Fonction afficher complexe
void afficher_complexe(Complexe c) {
    if (c.imaginaire >= 0) {
        printf("%.2f + %.2fi", c.reel, c.imaginaire);
    } else {
        printf("%.2f - %.2fi", c.reel, -c.imaginaire);
    }
}

// 4. Fonction créer tableau dynamique
Complexe* creer_tableau_complexes(int N) {
    Complexe *T = (Complexe*)malloc(N * sizeof(Complexe));
    if (T == NULL) {
        printf("Erreur d'allocation mémoire\n");
        exit(1);
    }
    return T;
}

// 5. Fonction remplir tableau
void remplir_tableau_complexes(Complexe *T, int N) {
    for (int i = 0; i < N; i++) {
        printf("Complexe %d :\n", i + 1);
        T[i] = saisir_complexe();
    }
}

// 6. Fonction afficher tableau
void afficher_tableau_complexes(Complexe *T, int N) {
    printf("Tableau des complexes :\n");
    for (int i = 0; i < N; i++) {
        printf("Complexe %d : ", i + 1);
        afficher_complexe(T[i]);
        printf("\n");
    }
}

// Programme de test
int main() {
    int N;
    printf("Entrez le nombre de complexes : ");
    scanf("%d", &N);
    
    Complexe *tableau = creer_tableau_complexes(N);
    remplir_tableau_complexes(tableau, N);
    afficher_tableau_complexes(tableau, N);
    
    free(tableau);
    return 0;
}

Exercice 7 : Fonctions avec pointeurs

Solutions

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

// Fonction afficher tableau
void Affiche_Tableau(int *T, int N) {
    printf("Tableau : ");
    for (int i = 0; i < N; i++) {
        printf("%d ", T[i]);
    }
    printf("\n");
}

// Fonction afficher matrice
void Affiche_Matrice(int **M, int L, int C) {
    printf("Matrice %dx%d :\n", L, C);
    for (int i = 0; i < L; i++) {
        for (int j = 0; j < C; j++) {
            printf("%d ", M[i][j]);
        }
        printf("\n");
    }
}

// Fonction fusionner tableaux
int* Fusionner(int A[], int N, int B[], int M, int *taille_F) {
    int *F = (int*)malloc((N + M) * sizeof(int));
    int k = 0;
    
    // Copier les éléments de A
    for (int i = 0; i < N; i++) {
        int existe = 0;
        for (int j = 0; j < k; j++) {
            if (F[j] == A[i]) {
                existe = 1;
                break;
            }
        }
        if (!existe) {
            F[k++] = A[i];
        }
    }
    
    // Copier les éléments de B (sans redondance)
    for (int i = 0; i < M; i++) {
        int existe = 0;
        for (int j = 0; j < k; j++) {
            if (F[j] == B[i]) {
                existe = 1;
                break;
            }
        }
        if (!existe) {
            F[k++] = B[i];
        }
    }
    
    *taille_F = k;
    return F;
}

Exercice 8 : Tableau de float

Solution

c
#include <stdio.h>

int main() {
    float T[50];
    int N;
    
    printf("Entrez la dimension du tableau (max 50) : ");
    scanf("%d", &N);
    
    if (N > 50) {
        printf("Dimension trop grande !\n");
        return 1;
    }
    
    printf("Entrez les %d valeurs :\n", N);
    for (int i = 0; i < N; i++) {
        printf("T[%d] = ", i);
        scanf("%f", &T[i]);
    }
    
    printf("Tableau saisi :\n");
    for (int i = 0; i < N; i++) {
        printf("T[%d] = %.2f\n", i, T[i]);
    }
    
    return 0;
}

Exercice 9 : Somme et moyenne

Solution

c
#include <stdio.h>

int main() {
    int N;
    printf("Entrez la taille du tableau : ");
    scanf("%d", &N);
    
    long T[N];
    long somme = 0;
    double moyenne;
    
    printf("Entrez les %d éléments :\n", N);
    for (int i = 0; i < N; i++) {
        printf("T[%d] = ", i);
        scanf("%ld", &T[i]);
        somme += T[i];
    }
    
    moyenne = (double)somme / N;
    
    printf("Somme = %ld\n", somme);
    printf("Moyenne = %.2f\n", moyenne);
    
    return 0;
}

Exercice 10 : Maximum et minimum

Solution

c
#include <stdio.h>

int main() {
    int N;
    printf("Entrez la taille du tableau : ");
    scanf("%d", &N);
    
    int A[N];
    
    printf("Entrez les %d éléments :\n", N);
    for (int i = 0; i < N; i++) {
        printf("A[%d] = ", i);
        scanf("%d", &A[i]);
    }
    
    int max = A[0], min = A[0];
    int pos_max = 0, pos_min = 0;
    
    for (int i = 1; i < N; i++) {
        if (A[i] > max) {
            max = A[i];
            pos_max = i;
        }
        if (A[i] < min) {
            min = A[i];
            pos_min = i;
        }
    }
    
    printf("Maximum : %d à la position %d\n", max, pos_max);
    printf("Minimum : %d à la position %d\n", min, pos_min);
    
    return 0;
}

Exercice 11 : Occurrences d'un caractère

Solution

c
#include <stdio.h>

int main() {
    int N;
    char x;
    
    printf("Entrez la taille du tableau : ");
    scanf("%d", &N);
    
    char T[N];
    
    printf("Entrez les %d caractères :\n", N);
    for (int i = 0; i < N; i++) {
        printf("T[%d] = ", i);
        scanf(" %c", &T[i]);
    }
    
    printf("Entrez le caractère à rechercher : ");
    scanf(" %c", &x);
    
    int count = 0;
    for (int i = 0; i < N; i++) {
        if (T[i] == x) {
            count++;
        }
    }
    
    printf("Le caractère '%c' apparaît %d fois\n", x, count);
    
    return 0;
}

Exercice 12 : Palindrome

Solution

c
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main() {
    int L;
    printf("Entrez la taille du tableau : ");
    scanf("%d", &L);
    
    char T[L];
    
    printf("Entrez les %d caractères :\n", L);
    for (int i = 0; i < L; i++) {
        printf("T[%d] = ", i);
        scanf(" %c", &T[i]);
    }
    
    int est_palindrome = 1;
    for (int i = 0; i < L/2; i++) {
        if (tolower(T[i]) != tolower(T[L-1-i])) {
            est_palindrome = 0;
            break;
        }
    }
    
    if (est_palindrome) {
        printf("Le tableau est un palindrome\n");
    } else {
        printf("Le tableau n'est pas un palindrome\n");
    }
    
    return 0;
}

Exercice 13 : Matrice

Solution

c
#include <stdio.h>

int main() {
    int NL, NC;
    printf("Entrez le nombre de lignes : ");
    scanf("%d", &NL);
    printf("Entrez le nombre de colonnes : ");
    scanf("%d", &NC);
    
    if (NL > 50 || NC > 50) {
        printf("Dimensions trop grandes !\n");
        return 1;
    }
    
    int M[50][50];
    
    printf("Entrez les éléments de la matrice :\n");
    for (int i = 0; i < NL; i++) {
        for (int j = 0; j < NC; j++) {
            printf("M[%d][%d] = ", i, j);
            scanf("%d", &M[i][j]);
        }
    }
    
    printf("Matrice saisie :\n");
    for (int i = 0; i < NL; i++) {
        for (int j = 0; j < NC; j++) {
            printf("%4d ", M[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

Exercice 14 : Manipulation de deux tableaux

Solution

c
#include <stdio.h>
#define N 10

int main() {
    char T[N], P[N];
    
    // 1. Saisir le tableau T
    printf("Saisissez %d caractères pour le tableau T :\n", N);
    for (int i = 0; i < N; i++) {
        printf("T[%d] = ", i);
        scanf(" %c", &T[i]);
    }
    
    // 2. Afficher le tableau T
    printf("Tableau T : ");
    for (int i = 0; i < N; i++) {
        printf("%c ", T[i]);
    }
    printf("\n");
    
    // 3. Transférer T vers P
    for (int i = 0; i < N; i++) {
        P[i] = T[i];
    }
    
    // 4. Afficher le tableau P
    printf("Tableau P : ");
    for (int i = 0; i < N; i++) {
        printf("%c ", P[i]);
    }
    printf("\n");
    
    // 5. Comparer les tableaux
    int identiques = 1;
    for (int i = 0; i < N; i++) {
        if (T[i] != P[i]) {
            identiques = 0;
            break;
        }
    }
    
    if (identiques) {
        printf("Les deux tableaux sont identiques !\n");
    } else {
        printf("Les deux tableaux ne sont pas identiques\n");
    }
    
    return 0;
}

Exercice 15 : Analyse du programme

Programme donné :

c
#include<stdio.h>
main()
{
    int val; //déclaration de la variable "val"
    val = 25; //affectation de la variable
    int *ptr; //déclaration du pointeur
    ptr = &val; // affectation du pointeur
    printf ("A : %d \n", val);
    printf ("B : %d \n \n", *ptr);
    printf ("C : %x \n ", &val);
    printf ("D : %x \n", ptr );
}

Sortie attendue :

A : 25
B : 25

C : [adresse de val en hexadécimal]
D : [même adresse que C]

Exercice 16 : Analyse avec pointeurs

Programme donné :

c
#include<stdio.h>
main()
{
    int n=5,m=3,*p;
    p=&n; printf("n=%d m=%d \n",n,m);
    (*p)++; printf("n=%d m=%d \n",n,m);
    n++; printf("n=%d m=%d \n",n,m);
    p=&m; printf("n=%d m=%d \n",n,m);
    m+=n; printf("n=%d m=%d \n",n,m);
    *p=7; printf("n=%d m=%d \n",n,m);
}

Sortie attendue :

n=5 m=3
n=6 m=3
n=7 m=3
n=7 m=3
n=7 m=10
n=7 m=7

Exercice 17 : Listes chaînées de fichiers

Solutions complètes

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

typedef struct fichier{
    char nom[30];
    char type[30];
    int taille;
    struct fichier *suiv;
} Fichier;

// 1. Créer fichier - retourne Fichier*
Fichier* CreerFichier() {
    Fichier *nouveau = (Fichier*)malloc(sizeof(Fichier));
    if (nouveau == NULL) {
        printf("Erreur d'allocation mémoire\n");
        return NULL;
    }
    
    printf("Nom du fichier : ");
    scanf("%s", nouveau->nom);
    printf("Type du fichier : ");
    scanf("%s", nouveau->type);
    printf("Taille du fichier : ");
    scanf("%d", &nouveau->taille);
    nouveau->suiv = NULL;
    
    return nouveau;
}

// 2. Ajouter au début - retourne Fichier*
Fichier* Ajouter_Debut(Fichier *F) {
    Fichier *nouveau = CreerFichier();
    if (nouveau == NULL) return F;
    
    nouveau->suiv = F;
    return nouveau;
}

// 3. Ajouter à la fin - retourne Fichier*
Fichier* Ajouter_Fin(Fichier *F) {
    Fichier *nouveau = CreerFichier();
    if (nouveau == NULL) return F;
    
    if (F == NULL) return nouveau;
    
    Fichier *courant = F;
    while (courant->suiv != NULL) {
        courant = courant->suiv;
    }
    courant->suiv = nouveau;
    
    return F;
}

// 4. Rechercher par taille - retourne Fichier*
Fichier* Rechercher_Taille(Fichier *F, int x) {
    Fichier *courant = F;
    while (courant != NULL) {
        if (courant->taille == x) {
            return courant;
        }
        courant = courant->suiv;
    }
    return NULL;
}

// 5. Rechercher par nom - retourne Fichier*
Fichier* Rechercher_Nom(Fichier *F, char *nomF) {
    Fichier *courant = F;
    while (courant != NULL) {
        if (strcmp(courant->nom, nomF) == 0) {
            return courant;
        }
        courant = courant->suiv;
    }
    return NULL;
}

// 6. Ajouter après un fichier - retourne Fichier*
Fichier* Ajouter_Apres(Fichier *F, char *nomF) {
    Fichier *trouve = Rechercher_Nom(F, nomF);
    if (trouve == NULL) {
        printf("Fichier %s non trouvé\n", nomF);
        return F;
    }
    
    Fichier *nouveau = CreerFichier();
    if (nouveau == NULL) return F;
    
    nouveau->suiv = trouve->suiv;
    trouve->suiv = nouveau;
    
    return F;
}

// 7. Ajouter avant un fichier - retourne Fichier*
Fichier* Ajouter_Avant(Fichier *F, char *nomF) {
    if (F == NULL) return F;
    
    // Si c'est le premier élément
    if (strcmp(F->nom, nomF) == 0) {
        return Ajouter_Debut(F);
    }
    
    Fichier *courant = F;
    while (courant->suiv != NULL && strcmp(courant->suiv->nom, nomF) != 0) {
        courant = courant->suiv;
    }
    
    if (courant->suiv == NULL) {
        printf("Fichier %s non trouvé\n", nomF);
        return F;
    }
    
    Fichier *nouveau = CreerFichier();
    if (nouveau == NULL) return F;
    
    nouveau->suiv = courant->suiv;
    courant->suiv = nouveau;
    
    return F;
}

// 8. Ajouter en gardant l'ordre croissant - retourne Fichier*
Fichier* Ajouter(Fichier *F) {
    Fichier *nouveau = CreerFichier();
    if (nouveau == NULL) return F;
    
    // Liste vide ou insertion au début
    if (F == NULL || nouveau->taille <= F->taille) {
        nouveau->suiv = F;
        return nouveau;
    }
    
    // Trouver la position d'insertion
    Fichier *courant = F;
    while (courant->suiv != NULL && courant->suiv->taille < nouveau->taille) {
        courant = courant->suiv;
    }
    
    nouveau->suiv = courant->suiv;
    courant->suiv = nouveau;
    
    return F;
}

// Fonction d'affichage pour test
void AfficherListe(Fichier *F) {
    Fichier *courant = F;
    printf("Liste des fichiers :\n");
    while (courant != NULL) {
        printf("Nom: %s, Type: %s, Taille: %d\n", 
               courant->nom, courant->type, courant->taille);
        courant = courant->suiv;
    }
}

Notes importantes :

  • Toutes les fonctions de manipulation de listes retournent un pointeur vers le début de la liste
  • L'allocation dynamique est vérifiée à chaque création de nouveau nœud
  • Les fonctions de recherche retournent NULL si l'élément n'est pas trouvé
  • La fonction de tri maintient l'ordre croissant des tailles lors de l'insertion
Content is user-generated and unverified.
    Solutions complètes TD3 - Structures, Pointeurs et Listes chaînées | Claude