TD5 - Initiation au C

Initiation au C

Durée : 4h30

Objectifs :

  • Créer son premier programme en C
  • Gérer la validité des saisies d’un utilisateur en C
  • Créer des fonctions/procédures en C
  • Comprendre les chaines de caractères en C
  • Utiliser les boucles en C

Attention :

À chaque étape de programmation, vous devez vérifier si le programme :

  • Compile sans warning
  • Obtient les résultats attendus
  • Avant de coder, il faut écrire un algo avec un papier et un stylo !

    logo

Exercice 0 : Avant de commencer

  1. Depuis le terminal, ajouter l’arborescence suivante :

  1. Déplacer vous dans le répertoire précédement créé
  1. Pour compiler un programme, on utilise l’instruction suivante :
gcc -Wall exo.c -o nomExecutable
  1. Pour executer un programme, on utilise l’instruction suivante :
./nomExecutable

Exercice 1 : Helloworld

  1. Ajouter dans l’arborescence précédement créée le répertoire exo1

  1. À l’interieur du répertoire exo1, créer le fichier helloworld.c

  1. Ajouter dans le fichier helloworld.c, le code suivant :
#include <stdio.h>
#include <stdlib.h>

int main(){
    char prenom[100];
    int a,b;

    printf("Bonjour, comment vous appelez vous ? \n");
    scanf("%s",prenom);

    printf("entrez un entier : \n");
    scanf("%d",&a);

    printf("entrez une entier : \n");
    scanf("%d",&b);

    printf("L'addition de %d et %d est %d",a,b,a+b);

    return 0;
}
  1. Compiler le fichier helloworld.c
  1. Exécuter le code compilé
  1. À quoi sert l’instruction dans les printf* ?

  2. Quelle est la différence entre la compilation et l’exécution ?

  3. Quels sont les différences principales entre ALGO et C ?

Exercice 2 : La saisie

  1. Ajouter dans l’arborescence précédement créée le répertoire exo2

  2. Écrire un exo2.c qui demande la saisie d’un nombre puis l’affiche.

PROGRAMME SaisieNombre
VARIABLES
    nb : entier
DÉBUT
    ECRIRE("veuillez saisir un nombre : ")
    LIRE(nb)
    ECRIRE("le nombre saisie est : " + nb)
FIN
  1. Que se passe-t-il si vous entrez à la place du nombre :
  • un réel,
  • une lettre,
  • une chaîne,
  • une chaîne commençant par un chiffre.
  1. Gérer les cas d’erreurs losrqu’il y en a.

Il faut récupérer la valeur de retour du scanf et si cette valeur de retour est égale à 0 alors il y a une erreur de saisie.

Dans notre cas scanf est une fonction C qui prend 2 paramètres (“%d”, et &nb), et renvoi 0 s’il y a une erreur de typage sinon elle renvoie 1.

  1. À l’endroit de votre programme, créez un fichier texte data.txt dans lequel vous saisissez simplement une valeur (42, par exemple). Puis utilisez les redirections du cours de commandes unix :

Solution 1

./votreProgramme < data.txt

Solution 2

cat data.txt | ./votreProgramme

Exercice 3 : PGCD

  1. Créer un fichier exo4.c contenant le code suivant :
#include <stdio.h>
#include <stdlib.h>


/* exo 3 : le pgcd */
int main(){
    return 0;
}
  1. Ajouter une fonction qui permet de calculer le pgcd de deux entiers passés en paramètres. Ci-dessous vous trouverez l’entête/signature de la fonction en C.

En C

/* Auteur : ... */
/* Date :  ... */
/* Résumé :  ... */
/* Entrée(s) :  ... */
/* Sortie(s) :  ... */
int PGCD (int a, int b);

Rappel du PGCD

Le Plus Grand Commun Diviseur est le plus grand nombre qui divise à la fois a et b.

Exemple

PGCD(48,18)= 6 PGCD(14,17)= 1

Algorithme d’Euclide

On utilise la méthode des divisions successives

Pour trouver le PGCD de 48 et 18, nous devons réaliser les étapes suivantes :

  1. \(48 \div 18 = 2\) et il reste 12
  2. \(18 \div 12 = 1\) et il reste 6
  3. \(12 \div 6 =2\) et il reste 0

Le dernier diviseur est le PGCD lorsqu’il reste 0.

PGCD(48,18)= 6

En Algo, nous avions écrit cette entête dans un TD précédent

// FONCTION qui permet de calculer le pgcd entre a et b
// Precondition : Prend en paramètre 2 entiers e et b. Attention : a doit être strictement supérieur à b
// Postcondition : Retourne le PGCD de a et de b.

FONCTION PGCD(a,b:entier):entier
  1. Ecrire le programme principale permettant d’exécuter la fonction pgcd

Solution 1

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

/* Auteur : Inès */
/* Date :  17/07/24 */
/* Résumé :  procédure qui affiche un entier passé en paramètre */
/* Entrée(s) :  un entier */
/* Sortie(s) :  aucune */
void maSuperProcedure (int a);

int main(){
    maSuperProcedure(42);
    return 0;
}

//maSuperFonction
void maSuperProcedure (int a){
    printf("%d",a);
}

Solution 2

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

/* Auteur : Inès */
/* Date :  17/07/24 */
/* Résumé :  procédure qui affiche un entier passé en paramètre */
/* Entrée(s) :  un entier */
/* Sortie(s) :  aucune */
void maSuperProcedure (int a){
   printf("%d",a);
}

int main(){
    maSuperProcedure(42);
    return 0;
}

Exercice 4 : Décliner votre identité

  1. Créer un répertoire exo4 dans lequel on ajoutera le fichier exo4.c contenant le code suivant :
#include <stdio.h>
#include <stdlib.h>

int main(){
    return 0;
}
  1. Créer un programme reproduisant (par exemple) la sortie ci-dessous. Votre programme devra redemander de saisie l’âge jusqu’à ce qu’une saisie soit correcte (un entier, positif, inférieur à 27).
Entrez votre nom : ...
Entrez votre prénom : ...
Entrez votre âge : ...

Voici ce que vous avez entré :
Nom : Cobain
Prénom : Kurt
Âge : 27 ans
  1. Améliorer le programme principale en ajoutant la possibilité de vider le buffer pour éviter un problème. Effectivement, dans la démonstration précédente lorsque l’on saisie une lettre à la place de l’âge, au tour suivant, on ne peut plus remplir son nom. Pour cela, nous pouvons utiliser la fonction qui vide le buffer et permet d’éviter le problème. On l’appelera après le scanf de l’âge.
/* Auteur : Peio */
/* Date :  19/11/20 */
/* Résumé :  procédure qui permet de vider le buffer d'un scanf */
/* Entrée(s) :  aucune */
/* Sortie(s) :  aucune */
void emptyBuffer() {
  char c;
  while (((c = getchar()) != '\n') && (c != EOF));
}

Exercice 5 : Validité d’une date

Il s’agit d’un exercice classique de l’algorithmique permettant de bien comprendre l’utilité du découpage d’un problème selon les différents cas rencontrés. On rappelle que le mois de février compte 28 jours sauf si l’année est bissextile et qu’une année est bissextile si elle est divisible par 4 mais pas par 100 exception faite des années divisibles par 400, qui sont également bissextiles.

Exemple :

  • Les années 2020, 2024 et 2028 sont bissextiles (divisible par 4)
  • Les années 2000 ou 2400 sont bissexstiles (divisible par 400)
  • Les année 1900, 2100, 2200 et 2300 ne sont pas bissextiles (divisible par 100)
  1. Créer un répertoire exo5 dans lequel on ajoutera le fichier exo5.c contenant le code suivant :
#include <stdio.h>
#include <stdlib.h>
/* exo 5 : validité d'une date */
int main(){
    return 0;
}
  1. Écrire un prédicat permettant de tester si une année est bissextile où non.
/* Auteur : ... */
/* Date :  ... */
/* Résumé :  predicat qui permet de vérifier si une annee est bixestille  */
/* Entrée(s) :  1 entier : l'année */
/* Sortie(s) :  0 => si c'est faux || 1 => si c'est vrai */
int estBissexstile(int annee);
  1. Tester dans le programme principal si votre prédicat int estBissexstile(int annee) est correct.
  1. Écrire un predicat permettant de tester la validité d’une date.
/* Auteur : ... */
/* Date :  ... */
/* Résumé :  predicat qui permet de vérifier si une date est valide  */
/* Entrée(s) :  3 entiers :
   - le jour (il doit être compris entre 1 et 31),
   - le mois (il doit être compris entre 1 et 12),
   - l'année */
/* Sortie(s) :  0 => si c'est faux || 1 => si c'est vrai */
int estValide(int jour, int mois, int annee);
  1. Écrire le programme principal qui demande à l’utilisateur de saisir une date sous la forme jour, mois et année.

Exercice 6 : Approximation de PI

  1. Créer un répertoire exo6 dans lequel on ajoutera le fichier exo6.c contenant le code suivant :
#include <stdio.h>
#include <stdlib.h>
/* exo 6 :  Approximation de PI */
int main(){
    return 0;
}
  1. Écrire une fonction permettant de calculer l’aproximation de \(\pi\) selon la méthode de Leibniz en utilisant le critére d’arrêt par nombre d’étapes.
/* Auteur : ... */
/* Date :  ... */
/* Résumé :  fonction permettant de calculer l'aproximation de pi selon la méthode de Leibniz en utilisant le critére d'arrêt par nombre d'étape */
/* Entrée(s) :  Le nombre d'étape que l'on souhaite réaliser */
/* Sortie(s) :  Le réel de l'approximation de pi */
double approximationPiNbEtape(int nbEtape);

Leibniz

  \(\pi\) = 4 \(\times\) (\(\frac{1}{1}\) - \(\frac{1}{3}\) + \(\frac{1}{5}\) - \(\frac{1}{7}\) + …)

Astuce pour alterner entre positif et négatif

On peut utiliser la puissance de (-1) sur l’itérateur i.

  • pour les valeurs de i paire la puissance  \(-1^i\)  donnera un 1
  • pour les valeurs de i impaire la puissance  \(-1^i\)  donnera un -1

On pourra donc alterner et respecter la formule d’approximation.

Comment calculer la puissance en C ?

Attention

  • Il faut importer la bibliothèque math.h
#include <stdio.h>
#include <stdlib.h>

#include <math.h>

/* exo 6 :  Approximation de PI */
int main(){
    return 0;
}
  • À la compilation, il faut rajouter l’extension lm
gcc -Wall exo6.c -o exo6 -lm
  • Dans le code, il faut utiliser l’instruction pow(leNombre,àLaPuissance)
#include <stdio.h>
#include <stdlib.h>

#include <math.h>

/* exo 6 :  Approximation de PI */
int main(){
    int nb;
    nb= pow(4,2); /* 4 à la puissance 2 */
    return 0;
}
  1. Écrire une fonction permettant de calculer l’aproximation de \(\pi\) selon la méthode de statistique.
/* Auteur : ... */
/* Date :  ... */
/* Résumé :  fonction permettant de calculer l'aproximation de pi selon la méthode de statistique en utilisant */
/* Entrée(s) :  Le nombre de points que l'on souhaite utiliser */
/* Sortie(s) :  Le réel de l'approximation de pi */
double approximationPiMethodeStat(int nbPoints);

Explication de la méthode statistique

Traçons un carré dont le demi-côté mesure une unité et inscrivons y un cercle de rayon unitaire. La surface du carré est de 4 et celle du cercle est de π. Si on choisi au hasard un point dans le carré, la probabilité qu’il se trouve dans le cercle est de  \(\frac{\pi}{4}\) . Et par conséquent, en recommençant de plus en plus souvent le choix aléatoire d’un point du carré, le rapport entre le nombre de points se trouvant dans le cercle (dont la distance à l’origine est inférieure à 1) et le nombre de points choisis doit s’approcher de π.

Comment faire de l’aléatoire en C ?

  • Il faut importer la bibliothèque time.h
#include <stdio.h>
#include <stdlib.h>

#include <time.h>
  • Il faut initialiser la “GRAINE” et le faire UNE SEULE ET UNIQUE FOIS dans le programme principal. L’instruction est la suivante : srand(time(NULL));. Si on ne met pas cette instruction, une fois, alors le nombre aléatoire généré sera toujours le même.
/* exo 6 :  Approximation de PI */
int main(){

    srand(time(NULL));

    return 0;
}
  • Pour générer un nombre aléatoire, l’instruction est la suivante :
    int a = rand() % 5; /* génération d'un entier aléatoire entre 0 et 5 */
    double x = (rand()/(double)  RAND_MAX * 2.0 - 1.0);     /* génération d'un réél aléatoire entre -1 et 1.*/

Exercice 7 : Un palindrome

  1. Créer un répertoire exo7 dans lequel on ajoutera le fichier exo7.c contenant le code suivant :
#include <stdio.h>
#include <stdlib.h>

/* exo 7 :  Palindrome */
int main(){
    return 0;
}
  1. Ecrire un prédicat permettant de savoir si un mot est un palindrome
/* Auteur : ... */
/* Date :  ... */
/* Résumé :  prédicat permettant de savoir si un mot est un palindrome */
/* Entrée(s) :  Le mot que l'on souhaite tester */
/* Sortie(s) :  0 => si ce n'est pas un Palindrome | 1 => si c'est un Palindrome */
int estPalindrome(char mot[100]);

Quelle est la fonction en C pour connaître la taille d’une chaîne ?

L’équivalent de longueur(ch) que nous utilisions en Algo est strlen(ch)

Exemple d’utilisation *attention, n’oubliez pas d’inclure la bibliothèque string.h

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

/* exo 7 :  Palindrome */
int main(){
    int taille;
    char monMot[100];

    printf("entrez un mot \n");
    scanf("%s",monMot);

    taille=strlen(monMot);

    return 0;
}
  1. Ecrire le programme principal qui demande à l’utilisateur de saisir un mot.

Exercice 8 : Le triangle

  1. Créer un répertoire exo8 dans lequel on ajoutera le fichier exo8.c contenant le code suivant :
#include <stdio.h>
#include <stdlib.h>

/* exo 8 :  le triangle */
int main(){
    return 0;
}
  1. Créer une procédure qui prend en entrée un entier n positif, représentant un nombre de ligne et affiche le triangle correspondant.
/* Auteur : ... */
/* Date :  ... */
/* Résumé : Procédure permettant d'afficher un triangle de taille n */
/* Entrée(s) :  La taille du triangle */
/* Sortie(s) :  aucunes  */
void triangle(int n);
  1. Écrire le programme principal qui demande à l’utilisateur de saisir un nombre de ligne.

Exercice 9 : Le menu

  1. Créer un répertoire exo9 dans lequel on ajoutera le fichier exo9.c contenant le code suivant :
#include <stdio.h>
#include <stdlib.h>

/* exo 9 :  Le menu */
int main(){
    return 0;
}
  1. Créer une procédure qui affiche le menu suivant :
/* Auteur : ... */
/* Date :  ... */
/* Résumé : Procédure permettant d'afficher un menu */
/* Entrée(s) :  aucunes */
/* Sortie(s) :  aucunes  */
void afficherMenu();
1 - Exercice 1 : Helloworld
2 - Exercice 2 : La saisie
3 - Exercice 3 : PGCD
4 - Exercice 4 : Décliner votre identité
5 - Exercice 5 : Validité d’une date
6 - Exercice 6 : Approximation de PI
7 - Exercice 7 : Un palindrome
8 - Exercice 8 : Le triangle
0 - Quittez
  1. Créer le programme principal qui permet à un utilisateur de réaliser une fonctionnalité dans le menu. Dès que l’utilisateur écrit 0, le programme s’arrête. Attention si l’utilisateur indique un choix qui n’existe pas dans le menu, alors il lui redemande la saisie.

Exemple

Vous pouvez télécharger ici, un exemple de gestion de menu

TD