# Exercices en langage C/Version imprimable

* Si vous imprimez cette page, choisissez « Aperçu avant impression » dans votre navigateur, ou cliquez sur le lien Version imprimable dans la boîte à outils, vous verrez cette page sans ce message, ni éléments de navigation sur la gauche ou en haut.
* Cliquez sur Rafraîchir cette page pour obtenir la dernière version du wikilivre.
* Pour plus d'informations sur les version imprimables, y compris la manière d'obtenir une version PDF, vous pouvez lire l'article Versions imprimables.
Une version à jour et éditable de ce livre est disponible sur Wikilivres, une bibliothèque de livres pédagogiques, à l'URL : https://fr.wikibooks.org/wiki/Exercices_en_langage_C

# Préparation

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]
La préparation consiste à installer un environnement de programmation suivant votre système d'exploitation.

## En ligne de commande
### Linux

Pour les distributions compatibles Debian (comme Ubuntu) :

### Mac

Les systèmes d'exploitation Mac OS X fournissent en standard les compilateurs GCC. tapez la commande suivante pour vérifier :
    gcc --version
donne par exemple :
Si gcc n'est pas présent, installez-le depuis les disques systèmes fournis avec votre machine Mac OS X Install Disc 1 dossier Xcode Tools ou téléchargez la dernière version depuis le site Apple et choisissez Tools Downloads et télécharger (1Gb) puis installer la version adaptée à votre système (10.4 ou 10.5).

### Microsoft Windows

Le compilateur C est fourni dans la suite libre GNU Compiler Collection portée sous Windows dans le paquet MinGW (Minimalist GNU for Windows). Vous pouvez alors utiliser le compilateur gcc dans une fenêtre MS-DOS à condition d'avoir ajouté le chemin du répertoire bin de votre installation MinGW dans la variable d'environnement utilisateur nommée Path.
Vous pouvez aussi utiliser un environnement de développement avec le confort du shell Linux : MSys. Vous pouvez utiliser le compilateur gcc dans une fenêtre ouverte grâce au script msys.bat situé dans un sous répertoire bin d'installation de Msys. MSys créé aussi un raccourci sur votre bureau.

### Remarque pour Windows

Sous Windows, MinGW et Msys sont aussi nécessaires car ils fournissent le compilateur gcc et les outils comme GNU Make.
Pour un lien automatique avec Eclipse, mettre dans une variable d'environnement utilisateur nommée Path le chemin du répertoire qui contient les binaires de MinGW et Msys.

## Eclipse

Eclipse est un environnement de développement intégré (EDI), générique et extensible (site officiel http://www.eclipse.org). Son système de plugins permet d'ajouter des fonctionnalités diverses.
Initialement prévu pour développer en Java, grâce aux plugins il peut maintenant également gérer des projets développés avec d'autres langages de programmation tels que :
* Le C et le C++ grâce à l'ensemble de plugins CDT (C Development Toolkit) (compilateur non intégré).
* Le Python via PyDev.
* Avant l'arrivée d'Android Studio, le développement pour Android se faisait avec Eclipse grâce à l'ensemble de plugins ADT (Android Development Toolkit).
Certains IDE sont basés sur Eclipse, et permettent par exemple le développement de logiciel embarqués pour des systèmes temps réel.

### Installation de Eclipse

La page de téléchargement d'Eclipse permet de récupérer une version déjà adaptée au langage ciblé sur http://www.eclipse.org/downloads/. Mais pour installer un plugin manuellement, il faut :
* Lancer Eclipse, puis dans le menu déroulant :Help>Software Updates>Find and Install...
* Cocher Search for new features to install, bouton Next. Bouton New Remote Site..., entrer l'adresse de téléchargement :
* Bouton Finish, choisir un miroir proche puis continuer l'installation.

### Utilisation de Eclipse

L'interface de l'IDE Eclipse est basée sur différentes perspectives. Une seule perspective n'est visible à la fois, et se compose de plusieurs vues. Exemples :
* La perspective "Java" se compose par défaut de la vue "Package Explorer", de la vue éditeur de code en Java avec un onglet par fichier ouvert, de la vue "Outline" donnant la hiérarchie des éléments composant la classe du fichier ouvert.
* La perspective "Debug" est ouverte automatiquement au lancement d'une application en mode débogage et se compose par défaut de la vue "Debug" affichant la pile d'appel, de la vue des points d'arrêt nommée "Breakpoints", de la vue éditeur de code en Java avec un onglet par fichier ouvert, de la vue "Outline" donnant la hiérarchie des éléments composant la classe du fichier ouvert.
* Deux ou plusieurs perspectives peuvent être affichées conjointement.
Chaque vue est une sous-fenêtre qui a un titre et se place dans un cadre particulier de la fenêtre de l'IDE. Les vues peuvent être déplacées à la souris par drag and drop pour changer la disposition de la perspective. Plusieurs vues peuvent partager le même cadre, auquel cas, une barre d'onglets permet de basculer entre les vues. Un double clic sur le titre d'une vue provoque l'affichage du cadre qui la contient en pleine fenêtre, réduisant les autres cadres à une icône sur les côtés. Un second double clic restaure les cadres.
Le menu "Window" permet de changer de perspective, et d'ajouter des vues à la perspective courante. Une vue peut également être retirée de la perspective affichée en utilisant la croix à droite du titre de la vue.

#### Édition de lignes

L'éditeur de code possède des raccourcis clavier pratiques rendant l'édition des lignes de code plus rapide :
| Touches | Touches | Effet |
| Shift | ↵ Enter | Ajouter une nouvelle ligne après la ligne courante. |
| Ctrl | ↑/↓ | Faire défiler la vue vers le haut/le bas. |
| CtrlShift | ↑/↓ | Déplacer le curseur sur le membre précédent/suivant de la classe. |
| Alt | ↑/↓ | Déplacer la ligne courante ou les lignes sélectionnées vers le haut/le bas dans le texte. |
| CtrlAlt | ↑/↓ | Dupliquer la ligne courante ou les lignes sélectionnées vers le haut/le bas. |
| CtrlShift | : | Commenter/Décommenter la ligne courante. |

#### Complétion de code

L'éditeur de code peut compléter automatiquement le code là où se trouve le curseur :
| Touches | Touches | Effet |
| Ctrl | Espace | Ouvrir la liste des suggestions de complétion. Une fois la suggestion choisie, la validation se fait par l'une des touches suivantes : ↵ Enter, n'ajoute rien derrière la suggestion ; Espace ou ., ajoute également le caractère produit derrière la suggestion. Toute autre touche produit le caractère sans valider (annuler la complétion). |
| AltShift | : | Complète avec la seule possibilité, ou produit un bip s'il y a plusieurs possibilités. |

#### Navigation et autres astuces

* Dans les codes sources dépassant la hauteur de fenêtre de l'éditeur, placez le pointeur de la souris sur l'accolade fermante d'un bloc pour voir apparaître un résumé du code d'ouverture du bloc en bulle d'aide. Ceci est fort utile pour vérifier quel bloc est fermé par l'accolade sans avoir à faire défiler le code.
* Placez le pointeur de la souris sur un identifiant de classe, méthode ou variable et enfoncez la touche Ctrl pour faire apparaître un lien cliquable vers la définition.
* Cliquez sur un identifiant de membre de classe pour faire apparaître toutes les occurrences d'utilisation dans le fichier : à la fois dans le texte et dans la barre de défilement. Les blocs apparaissant dans la barre de défilement sont cliquables pour faire défiler le code à la position de l’occurrence. Il y a deux couleurs distinctes pour les occurrences utilisées en lecture (accès, appel, ...) et celles utilisées en écriture (affectation).
    Il peut arriver que cela ne semble pas fonctionner car l'éditeur peut être dans un mode autre que celui par défaut. Il faut dans ce cas appuyer une ou deux fois la touche Échap pour que cela fonctionne.

### Première utilisation d'Eclipse

* Créez un nouveau projet (File > New > Project) de type Standard Make C Project nommé "Exercices". Ensuite depuis l'arborescence de projet, rajoutez un nouveaux fichier source (New > Source File.
* Après avoir modifié votre source, dans le menu déroulant Project > Build all.
* L'exécution se lance depuis le menu déroulant Run.

## Références

* ↑ Site Apple Xcode Tool : .
* 1 2 Le site du projet libre MinGW et MSys : .
* ↑ Page d'accueil des projets MinGW et Msys : MinGW - Home
* ↑ https://eclipse.org/cdt/
* ↑ (anglais) http://pydev.org/

# Notions de base

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]
Ces exercices sur les notions de base abordent :
* définition de fonction
* la fonction main
* l'appel de fonction
* la bibliothèques standard, l'inclusion avec le préprocesseur
* la sortie formatée avec printf
* les paramètres de main

### Exercice 1 : programme minimal nop

Écrire un programme qui ne fait rien (nop signifie no operation, soit « aucune opération »).
Pour le compiler et l'exécuter :
Remarque qualité :
* L'option -Wall n'est pas obligatoire. Elle demande au compilateur de signaler toutes les fautes qu'il peut détecter. Cela produit quelquefois des warnings ou avertissement que le programmeur, désireux de produire un code de qualité, s'efforcera de comprendre la signification et de corriger.
* Je donne l'extension .exe à l'exécutable produit pour l'identifier plus facilement. Sous Windows l'extension .exe est obligatoire et rajoutée par l'éditeur de lien si oubli.
Notions :
* définition de fonction
* fonction principale main servant de point d'entrée
* valeur retournée par une fonction
Un programme C commence par l'exécution d'une fonction main. Il existe deux prototypes standards pour la fonction main : int main(void) et int main(int argc, char* argv). Nous utilisons le plus simple car nous n'avons pas besoin de argc ni argv. Remarquons que les deux prototypes indiquent que main retourne un entier de type int. Nous retournons 0 (zéro), valeur conventionnelle pour indiquer que le programme est terminé sans erreur. Voici notre définition de la fonction main :
Nous pouvons aussi utiliser pour le code retour la constante EXIT_SUCCESS de stdlib.h plus parlante que 0.

### Exercice 2 : programme false

Dans les faits, le programme précédent retourne toujours le code de succès 0 ; il correspond donc à la commande Unix true. La commande true retourne systématiquement le code de succès 0.
Pour écrire faux (équivalent du programme UNIX false), cet exercice introduit une complication : l'appel d'une fonction contenue dans le même fichier source que la fonction principale main.
Écrire la fonction main d'un programme faux qui appelle la fonction un suivante et retourne sa valeur à la sortie :
La fonction a appeler :
Pour compiler et exécuter :
Notions :
* déclaration de fonction
* appel de fonction
* prototype de fonction
On définit la fonction un avant la fonction main. Dans main, à l'aide de l'opérateur d'appel de fonction, on procède à l'appel de fonction un, dont on retourne immédiatement la valeur.
Remarques qualité :
* Lorsque on définit une fonction de la sorte, elle est par défaut extern (visible de l'extérieur). Dans un projet plus important, elle pourrait donc être appelée à la place d'une autre portant le même nom. Pour limiter sa visibilité en interne, il faudrait utiliser le mot clé static. static int un(void).
* Que se passe-t-il si l'on définit la fonction un après main ? En compilant main, le compilateur va remarquer que l'on appelle une fonction un dont il ne sait rien. Cela ne l'empêche pas de compiler le programme ! (sans l'option -Wall il ne signalera rien !) Le compilateur fait comme si un avait été déclarée par : extern int un. Il y a déclaration implicite de fonction, alors que le compilateur ne sait rien de l'implémentation réelle de la fonction ! Par chance, la déclaration explicite correspond au prototype int un(void) et le programme suivant fonctionne. Il vaut mieux éviter ces mécanismes hasardeux, en demandant au compilateur d'être strict et en utilisant l'option -Wall.
* Ce qui donnera à la compilation
Si l'on souhaite tout de même mettre la fonction main en premier, il aurait fallu avertir le compilateur en utilisant un prototype : la signature de la fonction, placé avant le main.

### Exercice 3 : programme hello, world

Écrire un programme qui affiche hello, world.
Notions :
* inclusion d'en-tête standard
* passage de paramètres de fonction
* printf
* chaîne de caractères statique
On utilise le préprocesseur pour inclure stdio.h car le prototype de printf se trouve dans stdio.h. On passe la chaîne de caractères "hello, world\n" à l'appel de printf. On remarque que la chaîne est terminée par un caractère de nouvelle ligne (\n). Sans cela, une fois le programme terminé, l'invite de commande risque d'être affichée à la suite du mot world au lieu de se trouver au début d'une nouvelle ligne.
Remarques
* la fonction printf retourne le nombre de caractère écrits dans le flux de sortie, ici j'ai décidé de ne pas utiliser ce code retour, je le signale en castant à void la fonction. L'outil qualité lint signale toute fonction retournant une valeur qui n'est pas affectée à une variable ou ignoré explicitement. Cela permet d'éviter l'erreur qui consiste à oublier de traiter un code retour de fonction.
* Que se passe-t-il si l'on omet le #include <stdio.h> ? Le compilateur va remarquer que l'on appelle une fonction printf dont il ne sait rien. Cela ne l'empêche pas de compiler le programme ! Le compilateur fait comme si printf avait été déclarée par : extern int printf. Il y a déclaration implicite de fonction, alors que le compilateur ne sait rien de l'implémentation réelle de la fonction ! Si l'on omet d'inclure les prototypes des fonctions appelées, on risque donc d'appeler ces fonctions avec des paramètres incompatibles sans avertissement du compilateur :
L'option de gcc -Wall signale ce problème à la compilation par ce message :
Pour détecter le problème, c'est-à-dire que l'entier 123 (de type int) est passé au lieu d'une chaîne de caractères (de type const char*), le compilateur doit voir le prototype de printf, qui est : int printf(const char*, ...). Ce qui nous intéresse avec le #include <stdio.h>, c'est que le préprocesseur génère la sortie suivante en entrée du compilateur :
Notons que certains compilateurs ont une connaissance implicite des fonctions très communes comme printf. Ainsi, même sans voir le prototype de printf, certaines versions de GCC génèrent un avertissement, à moins d'utiliser la commande de compilation suivante : gcc -fno-builtin -o hello.exe hello.c. L'option -Wall active l'option --fno-builtin.

### Exercice 4 : programme comptant les arguments en ligne de commande

Écrire un programme qui affiche le nombre de paramètres en ligne de commande (en anglais, les arguments sont les données passées au programme, ou à une fonction).
Compilation et exécutions attendues :
Notions :
* paramètres de main
* sortie formatée
Pour avoir accès aux arguments en ligne de commande, on utilise la seconde définition standard de main, qui a pour premier paramètre le nombre d'arguments argc, et pour second paramètre le vecteur d'arguments argv. Notons que sur Unix, le nom de l'exécutable lui-même (./arg) est un argument, donc argc vaut au moins 1. Le résultat recherché est argc - 1. Pour afficher un nombre entier, nous utilisons des caractères de conversion dans la chaîne de formatage passée à printf. Le caractère de conversion d suivant le caractère % indique que nous affichons un entier de type int.

# Variables et constantes

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]

## Entrée d'une valeur

Écrivez un programme age.c qui demande l'âge de l'utilisateur, puis qui l'affiche.
Pour lire l'age , vous utiliserez la fonction scanf déclarée dans stdio.h sous la forme (void)scanf("%d", &ageLu);.
* Solution
* Correction
* Nom : age.c
* Auteur : Thierry46
* Role : Demande l'âge de l'utilisateur et l'affiche à l'écran.
* Paramètres : non pris en compte.
* Code retour : 0 (EXIT_SUCCESS)
* Pour produire un exécutable avec le compilateur libre GCC :
* gcc -Wall -o age.exe age.c
* Pour exécuter, tapez : ./age.exe
* Version : 1.0 du 5/1/2008
* Licence : GNU GPL
* #include <stdio.h>
* #include <stdlib.h>
* int main(void)
* /* Déclare la variable entière age qui contiendra la valeur lue */
* int ageLu = 99;
* /* Ecrit la question à l'écran */
* (void)puts("Quel est votre age :");
* /* Lit la réponse de l'utilisateur */
* (void)scanf("%d", &ageLu);
* /* Affiche à l'écran l'entier lu */
* (void)printf("Vous avez %d an(s) !\n", ageLu);
* (void)scanf("%d", &ageLu);
* return EXIT_SUCCESS;
* Exécution
* MacMini-TM:~/Documents/developpement/c thierry$ ./age.exe
* Quel est votre age :
* 43
* Vous avez 43 an(s) !
* Avec valeur illégale (non entière) entrée :
* MacMini-TM:~/Documents/developpement/c thierry$ ./age.exe
* Quel est votre age :
* Vous avez 99 an(s) !
* Remarques
* L'initialisation de ageLu permet d'avoir une valeur par défaut (99) en cas de problème de lecture.
* Le code retour de scanf est volontairement ignoré pour simplifier, ce qui est déconseillé dans un programme opérationnel.
* Il faudrait analyser le code retour et agir en conséquence.
* La fonction scanf permet bien d'autres possibilités, voir sa page de man : man -s3 scanf.
* Voir les autres fonctions de cette famille : fscanf, sscanf...

## Calculer si un nombre est premier

p est premier si et seulement si quel que soit 2<=i<=p-1 on a : i ne divise pas p.
* Solution
* #include<stdio.h>
* #include<conio.h>
* int main
* int i,p;
* (void)printf("Veuillez saisir un nombre entier : ");
* (void)scanf("%d", &p);
* if (p>2)
* for(i=2;i<p;i++)
* if(p%i==0) break;
* if (i==p) printf("%d est premier", p);
* else printf("%d n'est pas premier", p);
* getch;

# Types

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]

## Exercice 1 : longueurs en octet des types du langage C

Écrivez un programme taille.c qui affiche à l'écran la taille des différents types de données en octet du langage C sur votre architecture machine.
Vous utiliserez l'opérateur sizeof(type).
* Solution
* Correction
* Nom : taille.c
* Auteur : Thierry46
* Role : affiche à l'écran la taille en octet des différents types de données
* du langage C sur votre architecture.
* Paramètres : non pris en compte.
* Code retour : 0 (EXIT_SUCCESS)
* Pour produire un exécutable avec le compilateur libre GCC :
* gcc -Wall -pedantic -std=c99 -o taille.exe taille.c
* Pour exécuter, tapez : ./taille.exe
* Version : 1.2 du 10/3/2008
* Licence : GNU GPL
* #include <stdio.h>
* #include <stdlib.h>
* #include <limits.h>
* int main(void)
* /* Affiche les tailles récupérées avec sizeof */
* (void)printf("Taille des types en octet :\n"
* "\t- type char : %zu\n"
* "\t- type short : %zu\n"
* "\t- type int : %zu\n"
* "\t- type long : %zu\n"
* "\t- type long long : %zu\n"
* "\t- type float : %zu\n"
* "\t- type double : %zu\n"
* "\t- type long double : %zu\n",
* sizeof(char)*CHAR_BIT/8,
* sizeof(short)*CHAR_BIT/8, sizeof(int)*CHAR_BIT/8,
* sizeof(long)*CHAR_BIT/8, sizeof(long long)*CHAR_BIT/8,
* sizeof(float)*CHAR_BIT/8, sizeof(double)*CHAR_BIT/8,
* sizeof(long double)*CHAR_BIT/8);
* return EXIT_SUCCESS;
* Résultats affichés sur ma machine :
* MacMini-TM:~/Documents/developpement/c thierry$ ./taille.exe
* Taille des types en octet :
* - type char : 1
* - type short : 2
* - type int : 4
* - type long : 4
* - type long long : 8
* - type float : 4
* - type double : 8
* - type long double : 16
* Remarques :
* L'opérateur sizeof renvoie un résultat de type size_t. L'unité du résultat est de type char. Un char ne mesure pas forcément un octet ou 8 bits sur toutes les architectures. C'est pourquoi, pour des raisons de portabilité, j'utilise la constante CHAR_BIT qui indique le nombre de bits qu'occupe un char.
* Une valeur de ce type size_t s'imprime avec le spécificateur de format %zu de printf.

## Exercice 2 : caractéristiques numériques des types du langage C

Écrivez un programme limites.c qui affiche à l'écran les caractéristiques numériques des différents types du langage C.
Vous utiliserez les constantes symboliques des includes limits.h et float.h.
* Solution
* Correction
* Nom ......... : limites.c
* Role ........ : Imprime les caractéristiques numériques
* pour les types du langage C
* Auteur ...... : Thierry46
* Version ..... : V1.1 du 10/3/2008
* Licence ..... : GNU GPL
* Compilation :
* gcc -Wall -pedantic -std=c99 -o limites.exe limites.c
* Pour exécuter, tapez : ./limites.exe
* #include <stdio.h>
* #include <stdlib.h>
* // Pour les limites lies aux entiers et char
* #include <limits.h>
* // Pour les limites lies aux nombres reels
* #include <float.h>
* int main(int argc, char *argv)
* // Impression des limites pour les nombres entiers
* (void)printf("CHAR_MIN = %d\n", CHAR_MIN);
* (void)printf("CHAR_MAX = %d\n", CHAR_MAX);
* (void)printf("INT_MIN = %d\n", INT_MIN);
* (void)printf("INT_MAX = %d\n", INT_MAX);
* (void)printf("LONG_MIN = %ld\n", LONG_MIN);
* (void)printf("LONG_MAX = %ld\n", LONG_MAX);
* // Impression des limites pour les réels
* (void)printf("FLT_EPSILON = %e\n", FLT_EPSILON);
* (void)printf("FLT_MIN = %e\n", FLT_MIN);
* (void)printf("FLT_MAX = %e\n", FLT_MAX);
* (void)printf("DBL_EPSILON = %le\n", DBL_EPSILON);
* (void)printf("DBL_MIN = %le\n", DBL_MIN);
* (void)printf("DBL_MAX = %le\n", DBL_MAX);
* return EXIT_SUCCESS;
* } /* int main(... */
* Résultats affichés sur ma machine :
* MacMini-TM:~/Documents/developpement/c thierry$ ./limites.exe
* CHAR_MIN = -128
* CHAR_MAX = 127
* INT_MIN = -2147483648
* INT_MAX = 2147483647
* LONG_MIN = -2147483648
* LONG_MAX = 2147483647
* FLT_EPSILON = 1.192093e-07
* FLT_MIN = 1.175494e-38
* FLT_MAX = 3.402823e+38
* DBL_EPSILON = 2.220446e-16
* DBL_MIN = 2.225074e-308
* DBL_MAX = 1.797693e+308

# Les opérateurs

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]
Pour les besoins de certains exercices, on rappelle le tableau de priorité des opérateurs du C :
| Catégorie d'opérateurs | Opérateurs | Associativité |
| fonction, tableau, membre de structure, pointeur sur un membre de structure | ( ) [ ] . -> | Gauche -> Droite |
| opérateurs unaires | - ++ -- ! ~ * & sizeof (type) | Droite ->Gauche |
| multiplication, division, modulo | * / % | Gauche -> Droite |
| addition, soustraction | + - | Gauche -> Droite |
| décalage | << >> | Gauche -> Droite |
| opérateurs relationnels | < <= > >= | Gauche -> Droite |
| opérateurs de comparaison | == != | Gauche -> Droite |
| et binaire | & | Gauche -> Droite |
| ou exclusif binaire | ^ | Gauche -> Droite |
| ou binaire | ǀ | Gauche -> Droite |
| et logique | && | Gauche -> Droite |
| ou logique | ǁ | Gauche -> Droite |
| opérateur conditionnel | ? : | Droite -> Gauche |
| opérateurs d'affectation | = += -= *= /= %= &= ^= |= <<= >>= | Droite -> Gauche |
| opérateur virgule | , | Gauche -> Droite |
La priorité des opérateurs va décroissante lorsqu'on se déplace du haut du tableau vers le bas du tableau. Quand les opérateurs ont même priorité, c'est la colonne de droite sur la distributivité qui est utilisée.

## Analyse de programmes

Nous allons présenter dans cette section un ensemble d'exercices destinés à se familiariser avec les opérateurs du langage C.

### Exercice 1

* Quelle est la valeur de i après la suite d'instructions :
La série d'instructions donnée est équivalente à :
Donc i vaut -1
* Quelle est la valeur de i après la suite d'instructions :
La série d'instructions donnée est équivalente à :
Donc i vaut 0

### Exercice 2 : la priorité des opérateurs

Enlever les parenthèses des expressions suivantes lorsqu'elles peuvent être retirées.
Évaluer ces expressions pour a=6, b=18 et c=24. On supposera que les valeurs données le sont pour chacune des lignes : il n'y a pas d'exécution séquentielle comme dans un programme.

## Petit programme de calcul

Écrivez un programme calcul.c qui calcule la distance entre deux points d'un plan :
* Lit les coordonnées de deux points : X$_1$ (x$_1$, y$_1$) et X$_2$ (x$_2$, y$_2$).
* Affiche les données lues
* Calcule la distance d entre les deux points X$_1$ et X$_2$, avec la formule :
$d={\sqrt {(x_{2}-x_{1})^{2}+(y_{2}-y_{1})^{2}}}$
* Affiche le résultat à l'écran.

# Structures de contrôle
## Structures conditionnelles
### Analyse de programme : choix multiple

Ces exercices d'analyses doivent être réalisés sans compilateurs, à la main à l'aide d'un crayon et d'une feuille de papier.
Soit le programme suivant :
Qu'est ce qui sera affiché à l'écran lors de l'exécution de ce programme ?
Même question pour le programme :
* pour le premier programme :
Comme i vaut 7 au début du programme, on pourrait penser que i/2 donne 3.5 qui est arrondi à 4 (puisqu'affecté à une variable entière sur un octet). Mais il n'en est rien : 8/3 = 2.66 ne donne pas plus 3 mais seulement 2... parce que 8/3 donne un quotient de 2 avec 2 comme reste et que l'on s'intéresse à ce quotient justement ! C'est cela la division entière. Don quand on arrive au switch, i vaut 3 et donc
s'affiche à l'écran.
* Pour le deuxième programme, c'est
qui s'affiche car :
est la même chose que :
Remarquons que
donnerait exactement le même résultat (dans le switch).
La suppression des break a des conséquences importantes. Par exemple
afficherait :

### Test simple : programme non complet

Écrire la partie de programme réalisant la structure de contrôle demandée. On ne demande pas le programme en entier : pas les "include" pas le main...
Un test sur une valeur dans la variable i : si i vaut 19 on écrit "OK" autrement on écrit "Rejet"
Cet exercice n'est qu'un échauffement pour l'exercice suivant.
L'erreur la plus fréquente est d'écrire :
qui affichera toujours OK quelle que soit la valeur de i ! Pouvez-vous comprendre pourquoi ? Parce que i=19 met 19 dans i qui n'est pas zéro et donc est vrai... et toujours vrai !!!

### Tester votre âge

Écrire un programme testage.c contenant une fonction main qui :
* lit sur le clavier l'âge de l'utilisateur avec la fonction scanf;
* teste si la réponse est valide par analyse du code retour de scanf et teste si la valeur est comprise entre 0 et 130;
* affiche si l'utilisateur est majeur (>= 18 ans) ou mineur.

## Structures répétitives
### Analyse de programme : boucle simple

Cet exercice d'analyse doit être réalisé sans compilateur, à la main à l'aide d'un crayon et d'une feuille de papier. Soit le programme suivant :
Qu'affichera à l'écran l'exécution de ce programme ?
La seule difficulté de ce programme est la division entière, d'ailleurs précisée dans le commentaire. C'est la division que l'on a appris à l'école primaire : 5 / 2 : quotient = 2 et reste =1. La division entière donne le quotient c'est à dire 2 (et non pas 2,5 !!!)

### Analyse de programme : boucle simple et tableau

Cet exercice d'analyse doit être réalisé sans compilateur, à la main à l'aide d'un crayon et d'une feuille de papier.
Soit le programme suivant :
Qu'affichera à l'écran l'exécution de ce programme ?
Tableau de 5 cases numérotées de 0 à 4. Le programme affiche tout simplement son contenu :
Remarque : Il est possible de remplacer :
par
Voir même par :
pour lequel on déclare un tableu de 10 case mais on en initialise que 5 ! Les autres seront initialisées à 0 !

### Somme d'entiers (boucle simple)

Écrire un programme somme demandant à l'utilisateur de taper 10 entiers et qui affiche leur somme. Le programme ne devra utiliser que 3 variables et ne devra pas utiliser de tableau.
Remarques qualité sur la correction proposée :
* Un cartouche d'entête indique des informations utiles dont les particularités de la compilation (-std=c99), la version.
* Les messages guident l'utilisateur : il sait ou il en est dans sa saisie.
* Utilisation d'une constante symbolique NB_ENTIERS au lieu de valeurs littérales 10 : si le nombre d'entier à demander change, il n'y aura qu'une seule ligne à modifier au lieu de 3 dans notre cas.
* for (int i = 0 : c'est une syntaxe autorisée en C99. Avec les anciennes normes C, La variable aurait dû être déclarée hors de la boucle. Cette nouvelle syntaxe permet d'avoir des variables d'itération locales à la boucle for.
* (void)printf(... : la fonction printf retourne le nombre de caractères écrit dans le flux de sortie. Comme j'ai décidé de ne pas utiliser ce code retour, je le signale en castant à void la fonction. L'outil qualité lint signale toute fonction retournant une valeur qui n'est pas affectée à une variable ou ignoré explicitement. Cela permet d'éviter l'erreur qui consiste à oublier de traiter un code retour de fonction.
* Le code retour de scanf est ignoré. Il renvoie le nombre de valeurs correctement récupérée. Dans un code opérationnel robuste, tous les codes retours doivent être traités et un traitement doit être prévu en cas d'erreur. Le type void n'existait pas en C K&R.

### Analyse de programme (double boucle)

Ces exercices d'analyses doivent être réalisés sans compilateurs, à la main à l'aide d'un crayon et d'une feuille de papier.
* Soit le programme suivant :
Que sera-t-il affiché à l'écran lors d'une exécution de ce programme ?
* Même question pour le programme suivant :
* Pour le premier programme :
* Pour le deuxième programme :
À noter la ligne vide en tout début.

### Triangle d'étoiles (double boucles)

Compléter la fonction afficherTriangle dans le programme ci-dessous : cette fonction devra afficher un triangle rempli d'étoiles (*) sur un nombre de lignes donné passé en paramètre, exemple :
* 1ère version : sans utiliser de tableau à l'aide de deux boucles for imbriquées.
* 2ème version : avec une seule boucle for et un tableau de chaîne de caractère où vous accumulerez des étoiles.
1ère version : sans utiliser de tableau à l'aide de deux boucles for imbriquées.
Remarque :
* for (int i = 0 : c'est une syntaxe introduite en C99. Avec les anciennes normes C, La variable aurait dû être déclarée hors de la boucle. Cette nouvelle syntaxe permet d'avoir des variables d'itération locales à la boucle for.
* (void)putchar('*'); : la fonction putchar retourne le caractère écrit dans le flux de sortie ou EOF en cas d'erreur. Comme j'ai décidé de ne pas utiliser ce code retour, je le signale en castant à void la fonction. L'outil qualité lint signale toute fonction retournant une valeur qui n'est pas affectée à une variable ou ignoré explicitement. Cela permet d'éviter l'erreur qui consiste à oublier de traiter un code retour de fonction.
Dans un code opérationnel robuste, tous les codes retours doivent être traités et un traitement doit être prévu en cas d'erreur. Le type void n'existait pas en C K&R.
2ème version : avec une seule boucle for et un tableau de chaîne de caractère où vous accumulerez des étoiles.
Remarque :
* Le tableau chaineEtoiles est de type VLA (Variable-Length Arrays) introduite par C99. Avec les versions de C précédente, il aurait fallu allouer dynamiquement le tableau au début du programme, puis le désalloué à la fin.

# Tableaux statiques

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]

## Parcours d'un tableau

Écrire un programme nommé argv.c qui affiche :
* son nom de lancement (argv[0]);
* le nombre des ces arguments;
* la valeur de chaque argument reçu.
Rappels : La fonction main d'un programme C reçoit en argument :
* un entier argc indiquant le nombre d'élément du tableau argv;
* un tableau de chaînes de caractère argv avec :
** argv[0] : Nom d'appel du programme.
** argv[i] : Valeur de l'argument de rang i.
* Solution
* Le fichier source en c99 :
* Nom : argv.c
* Auteur : Thierry46
* Rôle : Affiche le nom de lancement du programme
* le nombre et les valeurs des paramètres passés passés à ce programme.
* Paramètres :
* - argc : nombre de paramètres
* - argv : tableau de chaînes de caractère contenant les paramètres
* Code retour : 0 (EXIT_SUCCESS)
* Pour produire un exécutable avec le compilateur libre GCC :
* gcc -Wall -std=c99 -o argv.exe argv.c
* Pour exécuter, tapez : ./argv.exe
* Version : 1.0 du 16/1/2008
* Licence : GNU GPL
* #include <stdio.h>
* #include <stdlib.h>
* int main(int argc, char *argv)
* // Affiche le nom de lancement du programme
* (void)printf("Nom d'appel du programme (argv[0]) : %s\n", argv[0]);
* // Affiche le nombre de paramètres passés au programme
* (void)printf("Nombre de paramètres passés au programme : %d\n", argc-1);
* // Affiche la valeur des paramètres
* for (int i=1; i<argc; i++)
* (void)printf("Paramètre %d : %s\n", i, argv[i]);
* return EXIT_SUCCESS;
* } // int main(...
* MacMini-TM:~/Documents/developpement/c thierry$ gcc -Wall -std=c99 -o argv.exe argv.c
* MacMini-TM:~/Documents/developpement/c thierry$ ./argv.exe dudule 1
* Nom d'appel du programme (argv[0]) : ./argv.exe
* Nombre de paramètres passés au programme : 2
* Paramètre 1 : dudule
* Paramètre 2 : 1

## Position d'un élément dans un tableau

Écrire un programme position.c contenant une fonction principale main déterminant si un entier est contenu dans un tableau statique par l'appel à une fonction position.
La fonction main :
* définira et initialisera le tableau d'entier
* récupérera dans son tableau d'argument argv le nombre à chercher.
* appellera la fonction position.
* affichera l'indice de l'élément dans le tableau ou un message indiquant que le nombre n'a pas été trouvé.
La fonction position :
* aura pour prototype : static int position(int t, int taille, int x).
* donnera l'indice d'un élément x dans le tableau t, ou -1 si x n'est pas trouvé.
* Solution
* Le fichier source en C99 :
* Nom : position.c
* Rôle : Affiche le nom de lancement du programme
* le nombre et les valeurs des paramètres passés passés à ce programme.
* Paramètres :
* - argc : nombre de paramètres
* - argv : tableau de chaînes de caractères contenant les paramètres
* Code retour : 0 (EXIT_SUCCESS)
* Pour produire un exécutable avec le compilateur libre GCC :
* gcc -Wall -std=c99 -o position.exe position.c
* Pour exécuter, tapez : ./position.exe
* Version : 1.0 du 16/1/2008
* Licence : GNU GPL
* #include <stdio.h>
* #include <stdlib.h>
* static int position(int t, int taille, int x);
* int main(int argc, char *argv)
* int tableau = { 2, 5, 45, 3, 9 };
* int taille;
* int x = 0;
* int cr = 0;
* int resultat;
* // Détermination de la taille du tableau
* taille = (int)(sizeof(tableau)/sizeof(tableau[0]));
* // Contrôle nombre de paramètre et affiche usage
* if (argc != 2)
* (void)fprintf(stderr,
* "%s : Cherche un entier x passe en paramètre\n"
* "usage : %s x\n",
* argv[0], argv[0]);
* (void)fputs("Valeurs contenues dans le tableau : ", stderr);
* for (int i=0; i<taille; i++)
* (void)fprintf(stderr, "%d ", tableau[i]);
* (void)fputs("\n",stderr);
* exit(EXIT_FAILURE);
* } // if (argc != 2)
* // Récupère le nombre passé en paramètre et le convertit
* cr = sscanf(argv[1], "%d", &x);
* if (cr != 1)
* (void)fprintf(stderr,
* "Erreur : parametre \"%s\" invalide : doit etre un entier.\n",
* argv[1]);
* exit(EXIT_FAILURE);
* } // if (cr != 1)
* // Appel de la fonction position et affichage du résultat.
* resultat = position(tableau, taille, x);
* if (resultat != -1)
* (void)printf("La position de %d est : %d\n", x, resultat);
* else
* (void)printf("%d non trouve !\n", x);
* return EXIT_SUCCESS;
* Fonction ...... : position
* Rôle .......... : Retourne la position de l'entier x dans la tableau t
* Paramètres .... :
* - t : tableau d'entiers passé en entier.
* - taille : nombre d’éléments du tableau
* - x : valeur a rechercher.
* Retour : L'indice dans le tableau de l'élément x ou -1 si non trouve.
* static int position(int t, int taille, int x)
* // On commence la recherche à partir de la fin du tableau
* int indice = taille - 1;
* while ((indice >= 0) && (t[indice] != x))
* indice--;
* return indice;
* } // static int position(...
* MacMini-TM:~/c thierry$ gcc -Wall -std=c99 -o position.exe position.c
* MacMini-TM:~/c thierry$ ./position.exe
* ./position.exe : Cherche un entier x passe en paramètre
* usage : ./position.exe x
* Valeurs contenues dans le tableau : 2 5 45 3 9
* MacMini-TM:~/c thierry$ ./position.exe a
* Erreur : parametre "a" invalide : doit etre un entier.
* MacMini-TM:~/c thierry$ ./position.exe 5
* La position de 5 est : 1
* MacMini-TM:~/c thierry$ ./position.exe 99
* 99 non trouve !

# Fonctions

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]
Ces exercices concernent l'utilisation des fonctions de la bibliothèque standard du langage C.

## Filtre qui passe le texte en majuscule
### Problème à résoudre

Écrivez un programme majuscule.c qui lit des données sur le flux stdin et écrits sur stdout après avoir transformé les caractères lus en majuscules. Vous utiliserez les fonctions getchar, putchar (stdio.h) et toupper (ctype.h).
Vous testerez votre programme en lui faisant convertir son propre fichier source majuscule.c.
    majuscule.exe < majuscule.c

### Solution proposée
## Lire une ligne longue avec fgets
### Problème à résoudre

La fonction fgets de la bibliothèque standard du langage C permet de lire une chaîne de caractère de longueur limitée dans un flux.
Vous allez compléter une fonction lire_ligne répondant au spécifications suivantes :
* Retour d'une ligne lue dans un flux texte passé en paramètre.
* Vous éliminerez les caractères de saut de ligne lus.
* La longueur des lignes lues n'est pas limitée.
* Contrôle des paramètres et retour des codes d'erreurs systèmes, détection de la fin du fichier.
* Vous utiliserez au maximum les fonctions de la bibliothèque standard du langage C : allocation mémoire, chaînes de caractères...
* Son prototype est donné par lire_ligne.h.
* Vous utiliserez le programme de main_lire_ligne.c pour lire_ligne.
* Vous devrez traiter le fichier test_lire_ligne.txt fourni.
* Les instructions de compilation et d'édition de lien sont dans les commentaires des fichiers fournis.

### Remarques sur l'exercice

* Le test des paramètres dans la solution est expéditif.
* Pour obtenir des programmes robustes, le langage C oblige à une gestion pénible des erreurs. Avec le langage Java par exemple, les mécanismes d'exception facilitent la tâche du programmeur.
* L'utilisation de l'allocation dynamique de mémoire est risquée : fuite mémoire. Avec le langage Java par exemple, le ramasse miettes (Garbage collector) se charge de la libération de la mémoire.
* En Java des classes comme String et StringBuffer prennent en charge les chaines de caractères longues.

## Test d'un générateur de nombre aléatoire
### Problème à résoudre

La bibliothèque standard du langage C offre au programmeur plusieurs fonctions pour générer des nombres aléatoires. La plus connue est rand.
Vous allez écrire un programme verifrand.c qui estime la répartition des nombres aléatoires générés : moyenne et dispersion. Nous allons traiter l'ensemble des nombres générés comme une série discrète regroupée.
* Générez 1 million (NB_TIRAGE) notes (x$_i$) entre 0 et 20 (N) comprises (NB_NOTE = 21) à l'aide de la fonction rand.
* Répartissez-les dans le tableau effectif (n) où n$_i$ représente l'effectif (nombre d'occurrences cumulées) de la note x$_i$.
* calculez et affichez la moyenne arithmétique : ${\overline {x}}={\frac {\sum _{i=0}^{N}(n_{i}*x_{i})}{\sum _{i=0}^{N}n_{i}}}={\frac {\sum _{i=1}^{N}(n_{i}*i)}{NB\_TIRAGE}}$
* calculez et affichez l'écart moyen de la série : $Em={\frac {\sum _{i=0}^{N}(n_{i}*|x_{i}-{\overline {x}}|)}{\sum _{i=0}^{N}n_{i}}}={\frac {\sum _{i=1}^{N}(n_{i}*|i-{\overline {x}}|)}{NB\_TIRAGE}}$

### Solution proposée

Résultats obtenus :

### Remarques sur l'exercice

* La série générée avec rand sur ma machine est bien centrée sur la moyenne théorique 10/20 : les nombres de notes en dessous et au dessus de 10 sont quasi-identiques. L'écart moyen de la série est proche de 5 ce qui indique que les notes sont bien réparties.
* La fonction rand est pseudo-aléatoire : deux exécutions du programme donnent exactement la même série de note.
* Vous pouvez tester d'autres fonctions comme random ou arc4random. Cette dernière, de qualité cryptographique, utilise l'algorithme nommé ARC4. Elle est aléatoire.

# Chaines

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]

## Longueur d'une chaîne de caractères (pour manipuler)

Écrire une fonction C calculant la longueur en octets d'une chaîne de caractères, donnée en argument.
À titre d'exercice, ne pas utiliser la fonction strlen du fichier d'entête string.h.
La fonction doit recevoir une chaîne de caractères. Une chaîne de caractères en C est un tableau de caractères, finissant par le caractère nul. La fonction doit donc recevoir un pointeur vers le premier élément du tableau, de type char *, et chercher l'élément nul.
La fonction recevant un pointeur, il faut donc s'assurer qu'il est valide. On doit donc tester si le pointeur est nul ou non avant de regarder ce qui se trouve dans le tableau de caractères.
Ici, on a choisi de retourner la valeur -1 si le pointeur est nul.
La boucle de recherche de l'élément nul peut être aussi écrite avec un for :
Fichier source lg.c :
Résultats d'exécution :

## Longueur d'une chaîne de caractères (par une fonction)

Écrire un programme lgChaine.c :
* qui lit des chaînes de caractères tapées au clavier (flux stdin) ;
* qui calcule la longueur de chaque chaîne entrée et l'affiche ainsi que sa longueur ;
* qui s'arrête si l'utilisateur ne frappe que la touche Entrée ou si le fichier est fini (Ctrl-D tapé par l'utilisateur).
Vous utiliserez :
* une des fonctions déclarée dans stdio.h.
* la fonction strlen, ainsi que d'autres si nécessaire, déclarée dans string.h.
Remarques :
* L'utilisation de fgets est plus sûre que gets ou scanf : fgets permet de limiter le nombre de caractère (octet) lu et de ne pas déborder de la variable reponse. Les débordements mémoire sont une source d'erreur fréquente en C.
* Ce programme peut ne pas donner les résultats attendus si on redirige sur l'entrée standard un fichier comportant des terminateurs de ligne \r (Mac).
* La fonction strlen de string.h retourne une valeur de type size_t : type non signée donc toujours >=0, unsigned int ou unsigned long selon l'implémentation.

# Pointeurs

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]
Soit un texte donné par une chaîne de caractères. Le but est de compter le nombre d'occurrences de chaque lettre sans distinction entre minuscules et majuscules.

## Exercice 1
### Question 1

Déclarer le texte comme un tableau statique initialisé par une chaîne de caractères constante, un tableau d'entiers statique pour compter les occurrences dont la taille est fixée par une constante et un pointeur pour parcourir le texte.
* Solution
* #include <stdio.h>
* #include <stdlib.h>
* const int nb_lettres = 26;
* int main(void)
* /* déclaration d'une chaîne <=> tableau de caractères. */
* char ch="ceci est une chaîne de test";
* printf("Chaîne en mémoire : %s\n",ch);
* /* déclaration d'un pointeur sur une chaîne de caractères. */
* char *p = ch;
* /* déclaration d'un tableau de 26 cases correspondant
* aux lettres de l'alphabet, contenant les occurrences
* des lettres trouvées dans la chaîne.*/
* int occ[nb_lettres];

### Question 2

Initialiser le vecteur d'entiers avec un parcours par indice.

### Question 3

Compter les occurrences en utilisant la conversion entre le type char et le type int (la conversion d'un caractère donne son code dans le standard américain).

### Question 4

Afficher le résultat sur la sortie standard.

## Exercice 2
### Pointeurs et références

Donner et expliquer le résultat de l'exécution du programme suivant :

# Préprocesseur

* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
* Préparation
* Notions de base
* Les variables et constantes
* Les types
* Les opérateurs
* Les structures de contrôle
* Les tableaux statiques
* Les fonctions
* Les chaînes de caractères
* Les pointeurs
* Le préprocesseur C
[ Modifier le sommaire ]

## Exercice 1

Écrire un fichier source hello.c. Les résultats du programme exécutable seront différents selon les options passées au préprocesseur sur la ligne de commande de compilation. Ce programme affichera :
* "Hello World", si la constante symbolique WORLD est définie.
* "Hello Fof", si FOF est définie.
* "Hello Nobody", si aucune de ces constantes n'est définie.
Lignes de Compilation avec gcc :
* gcc -D WORLD -o hello.exe hello.c
* gcc -D FOF -o hello.exe hello.c
* gcc -o hello.exe hello.c
Exécution : ./hello.exe
* Solution
* #include <stdio.h>
* #include <stdlib.h>
* int main(void)
* #if defined(WORLD)
* (void)puts("Hello World");
* #elif defined(FOF)
* (void)puts("Hello Fof");
* #else
* (void)puts("Hello Nobody\n");
* #endif
* return EXIT_SUCCESS;