View
218
Download
0
Category
Preview:
Citation preview
Informatique 1 ©É. Taillard, 2018 1
INFORMATIQUE 1
PROF. ÉRIC TAILLARD
Informatique 1 ©É. Taillard, 2018 2
ORGANISATION DU COURS
Coordonnées
Prof. É. Taillard
eric.taillard@heig-vd.ch
Assistant : Dr Thé-Van Luong
the-van.luong@heig-vd.ch
Support de cours
http://mistic.heig-vd.ch/taillard/bachelor/
Durant les cours
Présentation des notions à connaître, acquisition de la théorie
Langage de programmation : C
Poser des questions
Exercices d’assimilation pour les points importants à connaître
Informatique 1 ©É. Taillard, 2018 3
Travaux écrits
Au minimum 2 totalisant 3 périodes
Pondération : 25%
Rendu des travaux de laboratoires
Après chaque séance, glisser votre programme dans le répertoire :
\\eistore1\cours\tin\ETD\info1\laboyymmjj
où yymmjj est l’année, le mois et la date du jour
Le nom du fichier de votre programme devra comprendre votre nom et le numéro du
laboratoire
Par exemple si Pierre de la Vallée rend le 2 octobre une version améliorée du 3e laboratoire
encadrée durant la séance du 28 septembre 2018, il nommera son fichier
de_la_Vallee_labo3b.c et le déposera dans le répertoire ...\labo20180928
Pondération : 25%
Informatique 1 ©É. Taillard, 2018 4
EXAMEN
Commun avec les autres classes, compte pour 50%
Généralement 5 problèmes, par exemple :
Question théoriques vrai-faux
Impression et lecture formatées (fonctionnement de printf et scanf)
Évaluation d’expressions arithmétiques
Fonctionnement de structures de contrôle et de fonctions
Écriture d’un programme complet (lecture de données, vérification, transformation,
affichage)
Écriture d’une fonction réalisant une tâche particulière (tableau)
Analyse, correction d’un code fourni
Informatique 1 ©É. Taillard, 2018 5
TABLE DES MATIÈRES
1 Introduction, bases de l’informatique, de l’arithmétique et de la programmation
2 Types de base
3 Opérateurs et expressions
4 Structures de contrôle
5 Tableaux
6 Sous-programmes
7 Pointeurs et manipulation de chaînes de caractères
8 Entrées-sorties
9 Structures
Annexes
Tout ce qui doit être connu dans info1 (et même plus…) est rassemblé dans ces chapitres
Organisés pour faciliter la recherche d’une information
Informatique 1 ©É. Taillard, 2018 6
LES CHAPITRES SERONT PARCOURUS 3 FOIS
Marque a : bases introductives, dialogue utilisateur
Informatique, codage de l’information, processeurs, mémoires
Structure d’un programme, commentaires, identificateurs
Types int, double et char
Opérateurs =, +, -, *, /, %, conversion de type
usage élémentaire de printf et scanf (%d, %c, %f, %lf)
Marque b : bases de la programmation
Opérateurs de relation <, <=, >, >=, ==, !=
Opérateurs booléens !, &&, ||
Instructions de contrôle if, do…while, while, for
Tableaux
Fonctions
Principes de bonne programmation
Informatique 1 ©É. Taillard, 2018 7
Sans marque : compléments vu dans info1
Autres types de base
Autres opérateurs ++, --, +=, sizeof, &, *, ^, | …
Instructions switch, break
Manipulation de chaînes de caractères
Gabarits pour les fonctions printf et scanf
Structures
Marque c : compléments, ne faisant pas formellement partie de info1
Récursivité
Pointeurs
Gestion de la mémoire
Classes de déclaration
Préprocesseur
Informatique 1 ©É. Taillard, 2018 8
AUTRES SUPPORTS
Texte de B. Cassagne
Une copie est sur : http://mistic.heig-vd.ch/taillard/bachelor/
Livres
Claude Delannoy Le livre du C premier langage Eyrolles
Claude Delannoy Programmer en langage C Eyrolles
Stephen Kochan, Didier Cassereau Programmation en langage C Pearson
Jean-Michel Léry Algorithmique — Applications en C Pearson
Plein de sites web
…
Informatique 1 ©É. Taillard, 2018 9
I.
INTRODUCTION ET BASES
Informatique 1 ©É. Taillard, 2018 10
Informatique a
Définition (Larousse)
Science du traitement automatique et rationnel de l’information considérée comme le support des
connaissances et des communications.
Ensemble des applications de cette science, mettant en œuvre des matériels (ordinateurs) et des
logiciels (programmes).
Système informatique
Ensemble des moyens de saisie, de traitement et de transmission de l’information mis en œuvre pour
une application donnée.
Informatique 1 ©É. Taillard, 2018 11
Cheminement des données a
Captage
Clavier
Microphone
Sonde de température
Capteurs
Codage et transmission
Présence/absence de signal électrique (0/1, Binary digiT)
8 bits : octet, byte, kilo- (k), méga- (M), giga- (G), téra- (T)
Fibre optique
Ondes électromagnétiques (WiFi)
Bus
Informatique 1 ©É. Taillard, 2018 12
Cheminement des données a
Stockage
SSD (solid state drive, disque à semi-conducteurs)
Disque dur
Clé USB (universal serial bus, bus universel en série)
CD (disque compact), DVD (disque vidéo digital), BD (Blue-ray Disk)
Mémoires (Random Access Memory, Read-Only Memory)
Caches
Traitement
Processeur (Central Process Unit, CPU)
Restitution à l’utilisateur
Écran, haut-parleur, imprimante, etc.
Informatique 1 ©É. Taillard, 2018 13
Classification de l’informatique a
Informatique théorique :
Analyse numérique, théorie de l’information, langages et grammaires, automates, théorie de la
complexité
Informatique des systèmes :
Architecture des ordinateurs et des systèmes d’exploitation, hiérarchie des ressources,
communication entre processeurs, réseaux
Informatique matérielle :
Composants électroniques, semi-conducteurs, mémoires et mémoires auxiliaires, enregistrements
sur divers supports, organes périphériques d’entrée-sortie
Informatique logicielle :
Compilation, langages, analyse, programmation structurée, traitement automatique de l’information
Informatique 1 ©É. Taillard, 2018 14
Codage de l’information a
L’ordinateur consomme des données, les transforme et produit de l’information
Exemple : ordinateur du service académique de l’école
Contient le nom des étudiants et leurs notes
Calcule les moyennes de notes
L’ordinateur est une machine électronique
Constituée de circuits intégrés contenant des millions de
transistors fonctionnant comme des interrupteurs
L’information est codée par 2 niveaux de tensions électriques.
Absence de tension = chiffre 0
Présence de tension = chiffre 1
Informatique 1 ©É. Taillard, 2018 15
Codage de l’information a
Données véhiculée par un seul fil
Très rudimentaire, offre peu de possibilités
Principe du voyant lumineux
Représentation électrique sur plusieurs fils
Avec 2 fils, 4 états possibles :
00, 01, 10, 11, représentant les entiers 0, 1, 2, 3
Avec 3 fils, 8 états possibles
000 001 010 011 100 101 110 111
0 1 2 3 4 5 6 7
Informatique 1 ©É. Taillard, 2018 16
Le codage binaire a
N’utilise que les chiffres 0 et 1
Chiffre binaire = BInary digiT = BIT
Utilisé dans tous les ordinateurs
Il permet de représenter des nombres entiers
Les bits sont généralement regroupés par 8 = 1 octet (byte)
Exemple :
Poids 27 26 25 24 23 22 21 20
128 64 32 16 8 4 2 1
Octet 0 0 1 0 0 0 1 1
Valeur décimale 32 + 2 + 1 = 35
Informatique 1 ©É. Taillard, 2018 17
Codage binaire a
Avec 1 octet, on peut coder à peu près tous les caractères typographiques utilisés en anglais
Avec 4 octets, en réservant 1 bit pour le signe, on peut représenter les nombres entiers de
–2 milliards à 2 milliards
Avec 8 octets, on peut représenter des nombres rationnels dont l’ordre de grandeur varie de
10–300 à 10300 avec une quinzaine de chiffres significatifs
Représentation hexadécimale
Les nombres écrits en binaires sont peu lisibles, car trop long
On les regroupe par 4, donc avec 16 valeurs distinctes
0000 0 0001 1 0010 2 ...1001 9 1010 A ... 1111 F
Un octet s’écrit avec 2 symboles
01101100 6C
Informatique 1 ©É. Taillard, 2018 18
Numérotation binaire a
Informatique 1 ©É. Taillard, 2018 19
Pour un nombre représenté sur n bits, les calculs se font modulo 2n
01
2
3
4
5
6
78
9
10
11
12
13
14
15
01
2
3
4
5
6
7–8
–7
–6
–5
–4
–3
–2
–1
+1
–1
0000
0001
0010
0011
0100
010101100111
1000
10011010
1011
1100
1101
1110 11
11
Nombres signés
Nombres non signés
Représentation binaire
Arithmétique :
4 – 1 = 34 + 1 = 5
15 + 1 = 00 – 1 = 15
7 + 1 = –8–8 – 1 = 7
1111+ 0001
(1)0000
(avec 4 bits)
L’addition binaire entre signéset non signés est la même, seule l’interprétation du résultat diffère.
Informatique 1 ©É. Taillard, 2018 20
Exercice I.1 Représentation de nombres
Compléter le tableau ci-dessous (sans calculatrice)
Binaire Octal Décimalnon signé Décimal signé Hexadécimal
0
00000001
–1
F9
7
-7
10101011
CC
00110011
Informatique 1 ©É. Taillard, 2018 21
Exercice I.2 Additions binaires
Effectuer en binaire les additions suivantes. Traduire les opérandes en binaire (sur 8 bits, s’inspirer du
tableau précédent).
a) 1 + 51
b) 51 – 7
c) 204 + 51
d) 204 + 204
Informatique 1 ©É. Taillard, 2018 22
Exercice I.3 Unités informatiques
1. Quel est le nombre de valeurs différentes pouvant être représentées avec 10 bits ?
2. Les informaticiens ont choisi comme unité pour la taille mémoire le kilo octet. Étonnamment, 1 kilo
octet ne représente pas exactement 1000 octets, mais 1024. Pourquoi avoir choisi une telle
convention ?
3. Sachant qu’un méga 1 M = 1k x 1k, quelle est la taille du méga octet utilisé ? Combien de bits faut-
il pour représenter toutes les valeurs possibles allant jusqu’à 1 Méga informatique ?
4. Mêmes questions pour Giga 1 G = 1 M x 1 k. Quelle est le nombre de bits stockés dans 1 Go de
disque dur (1 Giga octet) ?
5. On dispose d’une mémoire RAM ayant les caractéristiques suivantes : bus d’adresses de 27 bits,
bus de données de 32 bits. Quelle est la capacité en octets (ou kilo, méga, giga) de cette mémoire ?
Informatique 1 ©É. Taillard, 2018 23
Structure interne de l’ordinateur a
Le processeur (CPU)
Traite les informations « chef d’orchestre »,« le cerveau »
Les mémoires
Retiennent les informations binaires sous forme électrique
RAM : Random Access Memory
Peut être lue et modifiée
ROM : Read Only Memory
Lecture seule, contenu figé par le constructeur
Les contrôleurs de périphériques
Gèrent un dispositif externe ou périphérique
Clavier, souris, écran, disque dur, USB, ethernet, …
Informatique 1 ©É. Taillard, 2018 24
Échange de données a
Les circuits périphériques
Sont reliés par de nombreux fils électriques
Ces fils véhiculent l’information binaire
Un ensemble de fils dédiés à l’échange d’information est un bus
Bus
Adresses
Contrôle
Données
Pro
cess
eur
Mém
oir
e R
OM
Mém
oir
e R
AM
Contr
ôle
ur
souri
s
Contr
ôle
ur
clavie
r
Contr
ôle
ur
écr
an
Contr
ôle
ur
dis
que d
ur
Informatique 1 ©É. Taillard, 2018 25
Les différents bus aUn ordinateur comporte généralement 3 bus
Bus d’adresse
Dans votre ordinateur portable : 64 bits
Le processeur applique un nombre sur ce bus.
Ce nombre désigne l’élément auquel le processeur veut parler, ou le numéro de la case
mémoire qu’il veut utiliser.
Bus de contrôle
Quelques bits
Indiquer la direction du transfert
Depuis ou vers le processeur
Signaux de début et de fin transfert.
Bus de données
Dans votre ordinateur portable : 64 bits
Selon le sens du transfert indiqué sur le bus de contrôle :
Le processeur ou le circuit adressé y place un nombre
Informatique 1 ©É. Taillard, 2018 26
Le processeur (CPU) aLe processeur contrôle les bus et gère le déroulement des opérations.
Il exécute une suite d’opérations spécifiées dans un programme
Ces opérations s’appellent des instructions
Ces instructions sont représentées par des nombres binaires
L’ensemble des instructions comprise par le processeur est le langage machine
Exemple
Adresse Contenu Signification
Assembleur Français
123 1010 0110 MOVA Charger le registre A
124 0000 1100 12 avec la valeur 12
125 1011 0110 MOVB Charger le registre B
126 0010 1011 43 avec la valeur 43
127 1100 1001 ADD A, B Additionner contenu
des registre A et B,
Informatique 1 ©É. Taillard, 2018 27
Structure simplifiée du processeur a
Registre PC, compteurde programme (adresseprochaine instruction)
Registre de données A
Registre de données B
Unité de calcul
SéquenceurLire la prochaine instructionExécuter cette instructionAjouter 1 à PC
Contrôle desbus bus
Informatique 1 ©É. Taillard, 2018 28
Caractéristiques du processeur a
Traite des instructions très élémentaires.
Exécute bêtement une suite d’instructions
Peut paraître peu puissant.
Vitesse de calcul (votre ordinateur portable)
Un milliard d’instructions par secondes
Sa rapidité lui permet de traiter des problèmes complexes en utilisant des instruc-
tions simples
Informatique 1 ©É. Taillard, 2018 29
Types de mémoires aROM (mémoire morte)
Informations stockée durant le processus de fabrication
Permanente
Très petite taille (quelques kilo-octets)
Lance le programme de démarrage (programmé par le fabricant de la carte mère)
RAM (mémoire vive)
Information stockée électriquement
Non permanente, nécessite une alimentation électrique
Mémoire ordinaire
Taille moyenne (quelques giga-octets)
Accès rapide
Mémoire cache
Taille petite (méga-octets)
Accès très rapide
Informatique 1 ©É. Taillard, 2018 30
Types de mémoires a
Disque dur
Information stockée sous forme magnétique
Permanente, accès lent, débit séquentiel moyen, débit aléatoire lent
Très grande taille (téra-octets)
Les informations transitent par la RAM pour être utilisées par le processeur
Mémoire flash
Permanente, grande taille, accès moyen, débit moyen
Nombre limité d’écritures
CD, DVD, Blue-Ray
Permanente, taille moyenne
Accès séquentiel
Nombre très limité d’écritures
Informatique 1 ©É. Taillard, 2018 31
Gestion des périphériques aGérés par des circuits électroniques spéciaux
Le contrôleur de clavier mémorise le numéro de la touche enfoncée
Le contrôleur d’écran mémorise la couleur à afficher pour chaque point de l’écran
Le processeur va lire et écrire des valeurs dans les registres des contrôleurs de périphériques
Le système d’exploitation
Un ordinateur sans programme ne sait rien faire
Le système d’exploitation est un programme chargé automatiquement au démarrage
Rôle
Gérer correctement les périphériques de l’ordinateur
Offrir des fonctions évoluées
Organisation des fichiers sur le disque dur
Gestion du clavier et de la souris
Affichage de fenêtres à l’écran
Démarrage des programmes utilisateur
Souvent complexe, plusieurs millions de lignes de code
Informatique 1 ©É. Taillard, 2018 32
Démarrage d’un ordinateur aRegistre compteur de programme du processeur initialisé à une adresse donnée (0)
Cette adresse concerne normalement la ROM, dont le contenu n’est jamais perdu
Exécution du programme (en ROM) débutant à cette adresse
Sur PC, ce programme de démarrage est le BIOS (Basic Input Output System)
Le programme de démarrage copie un emplacement fixe du disque dur dans la RAM
Cette zone du disque dur est appelée BOOT (ficelle)
Elle contient un programme qui charge en RAM tout le système d’exploitation
Ensuite, le système d’exploitation :
Surveille les actions de l’utilisateur
Affiche des informations à l’écran via son contrôleur
Lit l’état du contrôleur de clavier et de souris
Traite les actions de l’utilisateur
Reflète le résultat en mémoire, à l’écran, sur le disque dur, …
Informatique 1 ©É. Taillard, 2018 33
Le système de fichiers aLe disque dur peut contenir beaucoup de données
Comment s’y retrouver au milieu de tous ces nombres ?
Notion de fichier
Paquet d’informations, identifié par un nom (et une extension)
Gérée par le système d’exploitation
Un fichier est codé en binaire
L’extension donne une information sur l’organisation de ces données et quels programmes
sont en mesure de les exploiter
Exemple
Un fichier texte reçoit en principe une extension .txt
Chaque nombres binaires qu’il contient correspond à un caractère
Un programme « éditeur de texte » sait afficher ces caractères à l’écran, les modifier, les
enregistrer sur disque
Il donne un sens au contenu du fichier
Informatique 1 ©É. Taillard, 2018 34
Notion de dossier (ou répertoire) a
Un disque dur peut contenir des millions de fichiers
Très difficile de s’y retrouver sans un peu d’ordre
Organisation hiérarchique
Un dossier permet de ranger des fichiers
Un dossier peut contenir des fichiers ou d’autres dossiers
Informatique 1 ©É. Taillard, 2018 35
Niveaux de programmation aMatériel
Le processeur a besoin d’informations électriques
Programmation à l’aide du fer à souder
Séparation entre les données et le programme
Nouveau processeur tout reprogrammer
Machine de von Neumann
Programme = suite de bit on peut le charger en mémoire comme les données
Assembleur
Mnémotechnique (traduction symbolique) des instructions du processeur
MOV A5MOV B6ADD A, B
Fourni par les constructeurs de processeurs
⇒
⇒
Informatique 1 ©É. Taillard, 2018 36
Langage de haut niveau a
Pascal
Ada
C Diverses normalisations:
C K&R
C89 ou ansi ou C90
C99
C11
C++
C#
Python
Java
Beaucoup plus proches de l’esprit humain!
Informatique 1 ©É. Taillard, 2018 37
Premier programme en C a
/************************************************//* Premier programme: *//* But: afficher un texte à l'écran *//* Date: 18.09.2016 *//* Fichier: salut.c *//* Auteur: Arsène Lupin *//************************************************/
#include <stdio.h>#include <stdlib.h>
int main(void){ printf("Bonjour !"); return EXIT_SUCCESS;}
Résultat de l'exécution :
Bonjour !
S’écrit dans une console
Informatique 1 ©É. Taillard, 2018 38
Explications du premier programme aCommentaires
Tout texte encadré par /* … */ est un commentaire qui a pour but d’expliquer les intentions
du programmeur à un lecteur (humain)
Un commentaire n’engendre aucune instruction pour le processeur
#include <stdio.h>
Certaines séquences d’instructions, utilisées très souvent, très utiles mais qui sont
fastidieuses à programmer, comme par exemple une séquence d’instructions permettant
l’affichage d’un texte à l’écran, sont incorporées dans des fichiers séparés
stdio.h met à disposition, entre autres, une suite d’instructions appelée printf pour
l’affichage de texte
int main(void)
Début du programme principal (main)
Ce dernier n’attend pas de données avant de s’exécuter (void) et retournera un code entier
(int) au système d’exploitation à la fin de son exécution
Informatique 1 ©É. Taillard, 2018 39
Explications du premier programme a
{…}
Marque de début et de fin d’un groupe d’instructions, ou bloc
printf(…)
Permet d’afficher un texte à l’écran
return EXIT_SUCCESS;
Terminer l’exécution de main en revoyant un code de succès au système d’exploitation
Informatique 1 ©É. Taillard, 2018 40
Exercice I.4 Analyse de programme
Décrire ce que fait le programme suivant et ce que l’utilisateur verra à l’écran.
#include <stdio.h>#include <stdlib.h>#include <math.h>int main(){ double angle_degre, angle_radian, distance, hauteur; printf("Quel angle mesurez-vous en visant le sommet du batiment " "(en degres) :"); scanf("%lf", &angle_degre); angle_radian = angle_degre * M_PI / 45.0; printf("A quel distance vous trouvez vous du batiment (en metres) :"); scanf("%f", &distance); hauteur = distance / tan(angle_radian); printf("La hauteur du batiment est : %g metres.\n", hauteur);}Le programme ne réalise vraisemblablement pas exactement les intentions du programmeur.
Essayer de corriger les erreurs qu’il comporte.
Exercice I.5 Calcul de temps de parcours
En s’inspirant du programme précédent, écrire un programme qui demande à l’utilisateur une
distance et une vitesse moyenne et qui calcule le temps de parcours correspondant.
Informatique 1 ©É. Taillard, 2018 41
Processus de compilation a
Un programme écrit en C n’est pas directement exécutable par le processeur
C’est un fichier de texte, édité par exemple avec Nodepad, gedit, etc.
Traduction en langage machine longue, fastidieuse et répétitive
Réalisée par un programme appelé compilateur
Exemples de compilateurs
gcc
Disponible d’office sous Mac OS, Linux, Unix
Installable (avec MinGW) sous Windows, gratuit
cl
Installé dans l’environnement intégré de Visual Studio (Windows)
D’autres langages sont interprétés
Le code binaire est généré et exécuté au fur et à mesure de la lecture du code source
Informatique 1 ©É. Taillard, 2018 42
Étapes de la compilation a
1. Préprocesseur
Supprimer les textes inutiles pour la génération du code (comme les commentaires)
Concaténer (mettre bout-à-bout) tous les fichiers de texte
stdio.h, stdlib.h et salut.c
Lire et interpréter des directives pour le compilateur
Résultat :
Code source complet (ou un rapport d’erreur)
La commande gcc -E salut.c -o salut.i
crée le fichier source complet salut.i
Informatique 1 ©É. Taillard, 2018 43
Étapes de la compilation a
2. Vérification syntaxique et sémantique
S’assurer que les mot ont été correctement saisis (syntaxe)
Par exemple main et non mani
S’assurer que les instructions ont un sens (sémantique)
Par exemple printf("Bonjour !") et non printf(Bonjour !)
"Bonjour !" est une chaîne de caractères (entourée d’apostrophes)
Bonjour serait un objet non encore défini
! serait un opérateur pour lequel il manque l’opérande
La plupart des erreurs que l’on fait sont détectées lors de cette étape
Informatique 1 ©É. Taillard, 2018 44
Étapes de la compilation a
3. Traduction des instructions en assembleur
L’assembleur est un langage de bas niveau, lisible par l’humain (expert!)
dont les instructions sont calquées sur celles exécutables par le processeur
La commande
gcc -S salut.i
crée le fichier assembleur salut.s en voici un extrait :
movl $.LC0, %edimovl $0, %eaxcall printfmovl $0, %eax
Informatique 1 ©É. Taillard, 2018 45
Étapes de la compilation a4. Génération du code objet
Traduction des instruction assembleur en code binaire (non lisible)
La commande gcc -c salut.s crée le fichier objet salut.o
5. Édition de liens
Le fichier salut.o ne contient que le code propre au programme salut.c mais pas le code
de la fonction printf, généré une fois pour toute et disponible dans une bibliothèque qui a
été copiée à l’installation du compilateur
La commande gcc salut.o rassemble les bout de codes compilés séparément et produit un
fichier binaire exécutable a.out (ou un rapport d’erreur)
Toutes ces étapes s’enchaînent automatiquement (ouf!) lorsqu’on exécute la commande
gcc salut.c
Le compilateur essaie d’aller le plus loin possible avant de produire un message d’erreur
Une petite erreur peut donner lieu à des messages difficile à interpréter par un débutant !
Informatique 1 ©É. Taillard, 2018 46
Commentaires a
/* Ceci est un commentaire */
/* Ceci en est ... ... aussi un ! */
/* Cette construction /* n'est pas valide */ le commentaire s'arrêtant avant les 2 derniers caractères de la ligne qui précède */
Commentaire de ligne
i = 1; // Ceci est un commentaire de ligne
À partir du « // » tout le reste de la ligne est considéré comme un commentaire, sauf si l’on est déjà
dans un commentaire ou dans une chaîne de caractères
Remarque
Le commentaire de ligne n’existe que depuis la norme C99
Informatique 1 ©É. Taillard, 2018 47
Structure d’un programme a
main(/* paramètres éventuels */){
/* Corps du programme */Instruction 1;Instruction 2;…
}
Le nom du programme principal doit toujours être
main
Pour l’instant, on considérera des programmes principaux qui n’ont pas de paramètres.
(void)
Le corps du programme comporte un bloc
{}
Un bloc est composé de déclarations et d’instructions.
Un bloc est lui-même une instruction particulière
Informatique 1 ©É. Taillard, 2018 48
Séquence d’instructions a
Les instructions sont placées les unes à la suite des autres et s’exécutent séquentiellement
Une instruction se termine par ;
instruction_1;
instruction_2;…instruction_n;
Instruction composée ou bloc
{instruction_1;instruction_2;…instruction_n;
}
instruction_1;
instruction_n;
instruction_2;
…
Informatique 1 ©É. Taillard, 2018 49
Instruction vide a
;
est une instruction vide, n’effectuant aucune action
{ }
est un bloc vide, n’effectuant aucune action
Informatique 1 ©É. Taillard, 2018 50
Instructions déclaratives a
La gestion des adresses mémoires pour pouvoir stocker des données serait trop
fastidieuse à réaliser manuellement
Un langage de programmation évolué permet de déclarer des abstractions pour désigner des
emplacement mémoire
Ces abstractions sont appelés identificateurs
Le programmeur doit :
Choisir le nom
Préciser le type des données à mémoriser
Le compilateur se charge de :
Choisir l’adresse en mémoire
Réserver une taille de mémoire appropriée
Coder les données sous forme binaire
Mettre la valeur de la donnée s’il s’agit d’une constante
Informatique 1 ©É. Taillard, 2018 51
Instructions déclaratives a
Restrictions
Le langage se réserve un certain nombre de mots qui ne pourront pas être utilisés comme
identificateur, les mots-clés ou mots réservés (cf. annexe)
01001110100110000111110001001110
Adresse Nom logique
Symbole_lu
x_23
123412351236
… Type
double
int
char
1243
01011110100110010111010001001110
01001110100110000111110001001111
010011111001100000111100010011111237
12381239123A123B123C
124212411240123F123E123D
Nombre_personnes
(identificateur)
Informatique 1 ©É. Taillard, 2018 52
Identificateurs a
Construction
Les identificateurs doivent être construits avec des lettres minuscules des lettres majuscules, des
chiffres ou le caractère souligné
La casse (majuscule, minuscule) est significative
On ne peut pas utiliser les mots-clés comme identificateur
Diagramme syntaxique
Lettre Lettre
Chiffre
Identificateur
_
_
Informatique 1 ©É. Taillard, 2018 53
Exemples d’identificateurs : a
identificateurUnidentificateur1id_1__id_1__ // très très très déconseillé !
Contre-exemples:
L’espace est un séparateur en C, il ne peut y en avoir dans un identificateur
identificateur Un
Seules les lettres (majuscule, minuscule) peuvent être utilisées
carré
Ne peut pas commencer par un chiffre
1iste
Mots réservés
longcase
Informatique 1 ©É. Taillard, 2018 54
Exercice I.6 Identificateurs
Pour chacune des suites de caractères ci-dessous, indiquer si c'est un identificateur valide utilisable
dans un programme en langage C. Justifier les réponses négatives.
1) 2_pi2) x_23) x___34) x 25) positionRobot6) piece_presente7) _commande_vanne8) -courant_sortie9) _alarme_10) panne#211) int12) défaillance13) f’14) pied15) main16) si17) do18) Int
Informatique 1 ©É. Taillard, 2018 55
Structure générale d’un programme a
[Fichiers à inclure (directive #include)]
[Zone déclarative globale]
int main(void){
[Zone déclarative locale (du bloc de la fonction main)]
[Instructions]
}
En pratique, les directives d’inclusion et les déclarations peuvent se mettre n’importe où dans le
programme
Informatique 1 ©É. Taillard, 2018 56
Pratiques recommandées a
Mettre les directives d’inclusion en tout premier
On aime bien connaître d’emblée ce dont on a besoin
Zone déclarative avant main(void)
Permet de déclarer des types, des constantes et des variables globales (connues partout
dans le programme)
À n’utiliser en principe que pour des constantes, types et fonctions !
Déclarer les objets localement, uniquement là où on en a besoin
Commenter chaque déclaration
Le panachage entre instructions et déclaration n’est autorisé que depuis la norme C99
Informatique 1 ©É. Taillard, 2018 57
Zone déclarative bDéclaration de variables simple
nom_de_type identificateur_variable;
int i;
Déclaration multiple
int i, j, k;Permet de déclarer plusieurs variables de même type
Initialisation à la déclaration
int i = 0, j = 5;Permet de donner une valeur initiale aux variables juste déclarées
Attention !
int i, j = 0;N’initialise que la variable j
Autres déclarations
structures (struct)
énumérations (enum)
types synonymes (typedef)
fonctions
Informatique 1 ©É. Taillard, 2018 58
PORTÉE DES IDENTIFICATEURS
Tout identificateur cesse d’être visible à la fin du bloc où il a été déclaré
On ne peut plus utiliser cet identificateur
Tout identificateur défini dans un bloc est visible à partir du point où il a été déclaré
Mais pas au-dessus dans le même bloc
On utilise toujours la définition la plus récente
Au cas ou un même nom d’identificateur apparaît dans deux blocs imbriqués
On ne peut pas déclarer deux variables de même nom dans un même bloc
Même si elles ont des types bien distincts
Informatique 1 ©É. Taillard, 2018 59
VISIBILITÉ : EXEMPLE
#include <stdlib.h>
#include <stdio.h>
int main(void){
int i = 2, j = 3; // premier i, premier j {
// printf("%c", k); serait invalide: k non encore visible
char i = 'a', k = 'b'; // nouveau i, masque le premier printf("%c %d %c \n", i, j, k); // a 3 b
i = 88; // code ascii de X
printf("%c %d %c \n", i, j, k); // X 3 b
{
int j = 4; // masque le premier j printf("%c %d %c \n", i, j, k); // X 4 b
j = i; // transformation de type implicite !
printf("%c %d %c \n", i, j, k); // imprime: X 88 b
}
}
return EXIT_SUCCESS;}
Informatique 1 ©É. Taillard, 2018 60
Exercice I.7 Erreurs de programmation
Le programme ci-dessous comporte 13 erreurs. Le trouver et les corriger.
/* /* Programme exemple */*/
#include <std_io.h>#jnclude <stdlib.h>
INT Main(){ int a, somme; printf("Addition de 2 entiers a et b.\n"); // saisir le 1er entier printf("a:"); / afficher "a :" scanf("%d", a); // saisir le 2eme entier printf("b:"); scanf("%d", &b); // calculer la somme et l'afficher some = a + b; Printf("%d + %d = %d\n", a, b, somme); retturn EXIT_SUCCESS;}}
Informatique 1 ©É. Taillard, 2018 61
II.
LES TYPES DE BASES
Informatique 1 ©É. Taillard, 2018 62
Type entier natif aMot-clé : int
Pour représenter des nombres entiers
Valeur minimale : –2n–1 valeur maximale 2n–1 – 1, n = 16, 32, …
Dépend du processeur et/ou du système d’exploitation, mais au moins sur 16 bits
On trouve dans limits.h les valeurs minimales et maximales des entiers :
INT_MAX 2147483647INT_MIN (-INT_MAX - 1)
Pour autant que l’on ne demande pas d’opérations dépassant ces bornes, l’arithmétique est exacte,
Par exemple les valeurs suivantes sont les mêmes
a + b + c et a + c + b
a*(b + c) et a*b + a*c
Si on dépasse les bornes, le programme ne s’arrêtera pas avec un message d’erreur, mais continuera
avec une valeur non forcément désirée !
Informatique 1 ©É. Taillard, 2018 63
Écriture de constantes entières b
En base 10
2
–432
En octal (groupe de 3 bits)
Faire précéder du chiffre 0
010 // Valeur décimale: 8
En hexadécimal (groupe de 4 bits)
Faire précéder de 0X ou 0x
0X10 // Valeur décimale: 16
Informatique 1 ©É. Taillard, 2018 64
Type caractère natif aMot-clé : char
Pour représenter des caractères ou des nombres entiers
Pratiquement toujours codés sur 1 octet
Formellement : plus petite unité adressable
Peut être signé ou non, selon l’implantation du compilateur
Généralement, le code ASCII ou ISO-8859
Écriture de constantes de type caractère
On entoure le caractère entre 2 apostrophes, le compilateur se charge de trouver la
valeur numérique correspondante dans une table
’a’ ’A’ ’*’ ’"’
Informatique 1 ©É. Taillard, 2018 65
Constantes spéciales de type char bPrécédées de la barre oblique inverse \
’\a’ alerte (sonnerie)
’\b’ espace arrière
’\f’ saut de page
’\n’ nouvelle ligne
’\r’ retour de ligne
’\t’ tabulateur horizontal
’\v’ tabulateur vertical
’\\’ le caractère \
’\’’ le caractère ’
’\"’ le caractère " identique à ’"’
’\?’ le caractère ? identique à ’?’
’\117’ le caractère de code octal 117
’\xab’ le caractère de code hexadécimal ab
Informatique 1 ©É. Taillard, 2018 66
Exercice II.1 Constantes de type char
Indiquez si les constantes ci après sont correctes ou non. Si non, précisez pourquoi.
1) 'a'2) 'A'3) 'ab'4) '\x41'5) '\041'6) '\0x41'7) '\n'8) '\w'9) '\t'10)'\xp2'11)"abcdef"12)"\abc\ndef"13)"\'\"\\"14)"Hello \world !\n"
Informatique 1 ©É. Taillard, 2018 67
Type virgule flottante natif aMot-clé double
Pour représenter des nombres à virgule
Permet de manipuler des nombres de la forme : 1.234 · 10–12
Le nombre de chiffres significatifs, les valeurs minimales et maximales supportées dépendent du
processeur et/ou du système d’exploitation
On trouve dans <float.h> des valeurs utiles :
Nombre de chiffres significatifs
DBL_DIG 15
Plus petite valeur positive ε telle que 1.0 + ε ≠ 1.0
DBL_EPSILON 2.2204460492503131E-16
Plus petite valeur strictement positive
DBL_MIN 2.2250738585072014E-308
Informatique 1 ©É. Taillard, 2018 68
Écriture de constantes de type double a
1.234e–12 Vaut environ 1,234 · 10–12
2.0 Vaut 2 (mais avec une autre représentation que pour le type int !)
2. Idem
0.3 Vaut environ 0,3
.3 Idem
2.e4 Vaut 20000
.4e5 Vaut 40000
1E2 Vaut 100
Attention avec les nombres en virgule flottante : même s’il n’y a pas de dépasse-
ment de limites, l’arithmétique n’est pas exacte
0.5 + 0.2 + 0.1 ne donne pas la même valeur que 0.1 + 0.2 + 0.5
Informatique 1 ©É. Taillard, 2018 69
Exercice II.2 Types de variables
Pour chaque problème ci dessous, indiquer le nom et le type des variables à utiliser pour représenter
les données dans le programme.
1) Gestion d'un parking : nombre de voitures présentes.
2) Station météo : température moyenne de la journée, nombre de valeurs utilisées pour calculer la
moyenne.
3) Montant disponible sur un compte en banque.
4) Programme de calcul de résistance équivalente à 2 résistances en parallèle.
5) Programme de calcul de résistance équivalente à 2 résistances en série.
6) Programme de conversion décimal ↔ hexadécimal ↔ binaire.
7) Produit scalaire de 2 vecteurs du plan.
8) Nombre d'impulsions reçues par un capteur de position incrémental.
Exercice II.3 Durée d’un trajet
Écrire un programme pour calculer la durée d’un trajet en train. Le programme doit demander l’heure
de départ et l’heure d’arrivée et afficher le résultat sous la forme heures:minutes.
Informatique 1 ©É. Taillard, 2018 70
Représentation binaire du type double c
Normalisée sur 64 bits
IEEE 754
Les bits b0 à b51 donnent la fraction
Les bits 52 à 62 donnent l’exposant e
Le bit 63 donne le signe s
Calcul de la valeur représentée
Un exposant e de valeur 0 indique
la valeur 0 (si la fraction vaut 0)
un dépassement de capacité (valeur proche de 0) si la faction n’est pas nulle
Un exposant de valeur 2047 représente
L’infini si la fraction vaut 0
Un nombre indéfini (par exemple le résultat de 0/0 ou de ) sinon
1–( )s 1 b52 i–
2i–⋅
i 1=
52
∑+
2e 1023–⋅ ⋅
1–
Informatique 1 ©É. Taillard, 2018 71
Fonctions de la bibliothèque <math.h> b
Toutes les fonctions retournent une valeur de type double ; on suppose x et y de type double
sin(x) sinus de x (exprimé en radians !)
cos(x) cosinus
tan(x) tangente
asin(x) sin–1(x), définie pour x ∈ [–1, 1], retourne une valeur dans [–π/2, π/2]
acos(x) cos–1(x), définie pour x ∈ [–1, 1], retourne une valeur dans [0, π]
atan(x) tan–1(x), retourne une valeur dans [–π/2, π/2]
atan2(x, y) tan–1(x/y), retourne une valeur dans [–π, π]
sinh(x) sinus hyperbolique
cosh(x) cosinus hyperbolique
tanh(x) tangente hyperbolique
exp(x) exponentielle de x (en base e)
log(x) logarithme népérien de x, définie pour x > 0
log10(x) logarithme en base 10 de x, définie pour x > 0
Informatique 1 ©É. Taillard, 2018 72
pow(x, y) xy, erreur si x = 0 et y ≤ 0 ou si x < 0 et y non entier
sqrt(x) , définie pour x ≥ 0
ceil(x) Plus petit entier ≥ x
floor(x) Plus grand entier ≤ x
fabs(x) Valeur absolue de x
fmod(x,y) Reste de x/y, retourne une valeur de même signe que x
La bibliothèque dispose d’autres fonctions arithmétiques plus spécifiques
Des compilateurs intègrent encore d’autres fonctions (non normalisées !)
Quelques constantes symboliques mises à disposition par <math.h>
# define M_E 2.7182818284590452354 /* e */# define M_LN10 2.30258509299404568402 /* log_e 10 */# define M_PI 3.14159265358979323846 /* pi */# define M_PI_2 1.57079632679489661923 /* pi/2 */# define M_PI_4 0.78539816339744830962 /* pi/4 */# define M_1_PI 0.31830988618379067154 /* 1/pi */# define M_2_PI 0.63661977236758134308 /* 2/pi */# define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */# define M_SQRT2 1.41421356237309504880 /* sqrt(2) */# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
x
Informatique 1 ©É. Taillard, 2018 73
Exercice II.4 Calcul d’un angle
Écrire un programme qui calcule l'angle d'incidence des rayons du soleil (mesuré entre les rayons du
soleil et l'horizontale). Ce programme demande à l'utilisateur la hauteur connue d'un bâtiment, ainsi
que la longueur de son ombre. Ensuite, il doit calculer et afficher l’angle d'incidence des rayons du
soleil en degrés.
Informatique 1 ©É. Taillard, 2018 74
TYPES DE BASE
Il y a d’autres types de base supportés par les compilateurs, la plupart obtenus à l’aide de qualificatifs
signed, unsigned, long, short préfixant le nom du type natif
signed et unsigned
Ne s’applique qu’aux types entiers (char, short, int, long), pour spécifier s’ils sont signés ou non
int, signed, signed int sont synonymes
unsigned, unsigned int sont synonymes
long
Permet potentiellement de représenter des entiers ou des nombres en virgule flottante avec au moins
autant, généralement plus de chiffres ou une plus grande précision
Ne s’applique qu’aux types int et double
un nombre de type long int sera représenté sur au moins 32 bits et aura au moins autant de
chiffres qu’un nombre de type int, mais pas forcément strictement plus
Informatique 1 ©É. Taillard, 2018 75
long, long int, signed long, signed long int sont synonymes
unsigned long, unsigned long int sont synonymes
long long, long long int, signed long long, signed long long int sont synonymes
unsigned long long, unsigned long long int sont synonymes
Représentent des entiers sur au moins 64 bits ; pas forcément supporté
long double n’est pas forcément supporté par tous les compilateurs et n’est pas normalisé
short
Permet potentiellement d’éviter de gaspiller de la mémoire si on n’a pas besoin d’autant de chiffres
significatifs que les types natifs
Ne s’applique qu’au type int
short int n’utilise pas forcément moins de place que int et sera représenté sur au moins 16 bits
short, short int, signed short, signed short int sont synonymes
unsigned short, unsigned short int sont synonymes
Informatique 1 ©É. Taillard, 2018 76
_Bool
Entier valant 0 (interprété comme faux) ou 1 (vrai)
float
Type virgule flottante, de précision généralement inférieure au type double
Connaît un regain d’intérêt en raison de cartes graphiques (GPU) travaillant sur ce type
size_t
Un type entier non signé suffisamment grand pour représenter toutes les adresses du
système sur lequel on travaille
La plus grande des adresses dépasse généralement largement la mémoire réellement
installée !
ptrdiff_t
Un type entier signé suffisamment grand pour représenter une différence entre deux
adresses du système sur lequel on travaille
Informatique 1 ©É. Taillard, 2018 77
Bibliothèque <stdint.h> c
Met à disposition des entiers de taille fixée
Permet de travailler avec des nombres dont on connaît le nombre de bits et leur
représentation
Signés, avec représentation en complément à 2
int8_tint16_tint32_tint64_t
Non signés
uint8_tuint16_tuint32_tuint64_t
Usage fortement recommandé si l’on veut produire du code robuste et portable
Informatique 1 ©É. Taillard, 2018 78
QUALIFICATION DES CONSTANTES
Par défaut, une constante ’v’ est de type char
345 de type int
2.0 de type double
On peut explicitement forcer le type d’une constante en ajoutant un suffixe
Ceci est nécessaire si on dépasse la capacité du type par défaut
type unsigned 1U 1u -234u 012u 0x2FUtype long int 1L 1l -234L 012L 0x2FLtype unsigned long 1Ul 1ul 0xCUL 0XcUl type long long int 1LL 1ll -234LL 012LL 0x2FLLtype unsigned long long 1ULL 1ull 0xFULLtype _Bool 1b 0Btype long double 1.0L -234.5e6L -234.5e6ltype float 1.f -234.5e6F
Informatique 1 ©É. Taillard, 2018 79
Exercice II.5 Constantes numériques
Indiquer si les constantes suivantes sont correctes ou non. Dans le cas où la constante est correcte,
indiquer son type; dans le cas contraire, expliquer pourquoi elle est fausse.
1) 12.32) 12E033) 12u4) 12.0u5) 1L6) 1.0L7) .98) 9.9) .10) 0x3311) 0xefg12) 0xef13) 0xeF14) 0x0.215) 0216) 09
Informatique 1 ©É. Taillard, 2018 80
Informatique 1 ©É. Taillard, 2018 81
III.
OPÉRATEURS ET EXPRESSIONS
Informatique 1 ©É. Taillard, 2018 82
Opérateur d’affectation = a
Permet d’introduire une valeur dans une variable
La variable doit être placée à gauche (lvalue) du signe =
À droite du signe = on doit avoir une expression dont la valeur est compatible avec le type de la
variable
Exemple de séquence d’un programme :
int a; // Déclare une abstraction d’une portion de la mémoire nommée// « a », à interpréter comme un nombre entier
int b; // Idem pour « b »
a = 3; // Mettre la valeur 3 dans la portion de mémoire représentée par a
b = a + 5; // Prend la valeur actuelle de a (c’est-à-dire 3), lui ajoute 5 // et met le résultat dans la portion de mémoire représentée par b
a = a - 11;b = a; // b et a contiennent maintenant chacun -8
Note : Il existe d’autres opérateurs d’affectation
Informatique 1 ©É. Taillard, 2018 83
Exercice III.1 Séquence d’affectations
On considère les déclarations suivantes :
int a, b, c;double x;
Notez après chaque affectation le contenu des différentes variables.
Exercice III.2 Échange de deux variables
Soient 2 variables entières a et b, chacune contenant une valeur différente.
Écrire les instructions permettant d'échanger les valeurs de a et de b. À la fin de cette séquence
d'instruction, la valeur initiale de a doit être dans b, la valeur initiale de b doit être dans a.
Instruction a b c x
a = 5;
b = c;
x + 2.0 = 7.0;
a = a + 1;
c = a % 4;
Informatique 1 ©É. Taillard, 2018 84
Opérateurs arithmétiques multiplicatifs a* Multiplication
a * b
/ Division
Pour les entiers positifs, il y a troncation si le résultat n’est pas entier
8/3 donne la valeur 2
Lorsqu’au moins un des opérandes est négatif, le résultat dépend du compilateur
7/-4 vaut soit -1 soit -2
Il y a 2 conventions :
% Reste de la division
Ne s’applique qu’aux types entiers
Propriété, si b n’est pas nul : l’expression b*(a/b) + a%b vaut toujours a
N’est pas normalisé, puisque la division ne l’est pas
Appelé presque toujours improprement « modulo »
a b, 0> a–( ) b⁄ a b–( )⁄ a b⁄ ou–
a b⁄–
= =
Informatique 1 ©É. Taillard, 2018 85
Opérateurs arithmétiques additifs a+ Addition
a + b
- Soustraction
a - b
Les opérateurs multiplicatifs (* / %) sont prioritaires par rapport aux opérateurs additifs (+ –)
Tous les opérateurs arithmétiques sont évalués de gauche à droite
Exemple
a - b - c * d / a + b / c * d
est évalué comme
((a - b) - ((c * d) / a)) + ((b / c) * d)
Remarque
Lorsqu’on applique des opérateurs à des opérandes de type char, les opérandes sont
convertis en int avant le calcul; ils peuvent être convertis en double s’ils sont des float
Informatique 1 ©É. Taillard, 2018 86
Exercice III.3 Erreur dans un calcul de pourcentage
On considère le cas d'un système de vision industrielle, qui inspecte des pièces fabriquées dans une
ligne d'assemblage. Le programme de ce système de vision comporte les variables internes
suivantes, pour mémoriser le décompte des pièces analysées :
int nombre_pieces_inspectees, nombre_pieces_mauvaises;double pourcentage_pieces_bonnes;// simulation des valeurs des compteurs de pieces :nombre_pieces_inspectees = 2000;nombre_pieces_mauvaises = 200; // calcul du pourcentage :pourcentage_pieces_bonnes = (nombre_pieces_inspectees - nombre_pieces_mauvaises) / nombre_pieces_inspectees;
Quel résultat espérait le programmeur de cette application ?
Qu'obtient-il dans la pratique ?
Expliquer le défaut constaté.
Corriger ce programme pour obtenir un résultat correct.
Informatique 1 ©É. Taillard, 2018 87
Exercice III.4 Expressions arithmétiques
Donnez la valeur et le type des expressions ci dessous.
25 + 10 + 7 - 3 5 / 224 + 5 / 2 (24 + 5) / 225 / 5 / 2 25 / (5 / 2)72 % 5 - 5 72 / 5 - 58 % 3 -8 % 38 % -3 -8 % -325. + 10. + 7. - 3. 5. / 2.24. + 5. / 2. 25. / 5. / 2.25. / (5. / 2.) 2. * 13. % 7.1.3E30 + 1
Exercice III.5 Écriture d’expressions
Écrire des expressions, uniquement avec des opérateurs arithmétiques, qui permettent de
déterminer si :
un nombre n entier non négatif est impair (1 si impair, 0 sinon)
un nombre n entier est pair
un nombre n entier non négatif est un multiple de 3
Exercice III.6 Construction d’expression
Soit α, l’angle, mesuré en radians, que fait l’aiguille des heures d’une horloge par rapport à
l’horizontale. Construire des expression permettant de retrouver l’heure.
Informatique 1 ©É. Taillard, 2018 88
Exercice III.7 Affectations
Donnez les valeurs de x, n, p après l'exécution des instructions ci dessous.
double x;int n, p;p = 2;x = 15 / p;n = x + 0.5;
Même question pour le code ci-dessous.
double x;int n, p;p = 2;x = 15./ p;n = x + 0.5;
Informatique 1 ©É. Taillard, 2018 89
Opérateurs arithmétiques monadiques a
Monadique : unaires, à un seul opérande
Prioritaires par rapport aux opérateurs multiplicatifs (* / %) qui sont eux-même prioritaires par
rapport aux opérateurs additifs dyadiques (à 2 opérandes)
- Opposé
-a
+ Neutre
Ajouté par souci d’orthogonalité
Permet de s’assurer qu’une expression est évaluée avant une autre
Informatique 1 ©É. Taillard, 2018 90
Transformation implicite d’un type à un autre a
Lorsqu’on a une variable d’un certain type et qu’on lui fournit une valeur d’un autre
type, le compilateur transforme implicitement le type de cette dernière
On passe toujours à un type en principe plus fort :
char → short → int → long → float → double → long double
int i, j, k;double x, y, z;i = 2;j = 3;
x = i/j; // i/j est évalué (= 0) puis converti. x vaut 0.0// Message d’avertissement seulement avec option -Wconversion
y = i; // i converti en double, puis affecté à yz = j;k = y/z; // y/z est évalué (0.6666…), ensuite est converti en int; k vaut 0
Informatique 1 ©É. Taillard, 2018 91
Exercice III.8 Expressions mixtes
Soient les instructions suivantes :
int n, p;double x;n = 10;p = 7;x = 2.5;
Donner le type et la valeur des expressions suivantes :
1) x + n % p2) x + p / n3) (x + p) / n4) .5 * n5) .5 * (float)n6) (int).5 * n7) (n + 1) / n8) (n + 1.0) / n
Informatique 1 ©É. Taillard, 2018 92
Exercice III.9 Promotion numérique
Représentez les promotions numériques qui surviennent lors de l'évaluation des expressions ci-
dessous :
char c;short sh;int i;float f;double d;c * sh - f / i + d;c * (sh - f) / i + d;c * sh - f - i + d;c + sh * f / i + d;
Informatique 1 ©É. Taillard, 2018 93
TRANSFORMATIONS IMPLICITES PROBLÉMATIQUES
float n’occupe souvent pas plus de bits que long ou int
Par conséquent, il peut y avoir une perte de précision lors des conversions implicites
float f;int i = 111111111;f = i;i = f; // i peut valoir maintenant 111111112
Conversion entre entiers signés et non signés
Les entiers non signés sont considérés comme plus grands que les entiers signés
Un entier signé est donc promu vers l’entier non signé
L’expression -1 > 9223372036854775807ULL est donc toujours vraie !
Se méfier lorsque l’on a une expression comportant l’opérateur sizeof, qui retourne un
entier non signé
Informatique 1 ©É. Taillard, 2018 94
Exercice III.10 Conversions de types
On considère les déclarations suivantes :
double x;short i;unsigned short j;long k;unsigned long l;
Identifier les conversions problématiques qui vont survenir lors de l’enchaînement des instructions ci-
dessous.
x = 1e6;i = x;j = -20;k = x;l = k;k = -20;l = k;
Informatique 1 ©É. Taillard, 2018 95
Transformation explicite d’un type à un autre :opérateur de « Casting » a
On peut procéder à des changements de types explicites
Opérateur de « casting »
(type_destination)expression
Exemple
(int)2.4 // donne la constante 2(int)2.9 // donne encore 2: troncation
Principes de bonne programmation
En principe, on ne mélange pas les types
Lorsqu’on y est obligé, il est recommandé d’utiliser l’opérateur de conversion explicite même si le
compilateur aurait procédé correctement
Cela montre qu’on est conscient de la conversion de type et qu’elle est bien désirée
En compilant avec l’option -Wconversion, on a des messages avertissant des conversions implicites
Informatique 1 ©É. Taillard, 2018 96
Exemple de conversion explicite a
int i = 2, j = 3;double x;x = (double)(i/j);
Il est clair que i/j est évalué en premier
Le lecteur sera incité à chercher le type retourné par l’opération (int)
Il se rendra compte de la valeur du résultat (= 0)
Ensuite on convertit en double
En écrivant cette instruction
x = i/j;
Les opérations sont exactement les mêmes
Mais le lecteur risque d’être induit en erreur
Par défaut, le compilateur ne signale rien
Informatique 1 ©É. Taillard, 2018 97
Exemple de manipulation de nombres a/* Transformation en pouces et pieds d’une longueur exprimée en mètres*/#include <stdlib.h>#include <stdio.h>
#define POUCES_PAR_PIED 12#define METRE_PAR_POUCE 0.0254int main(void){ double longueur; // Longueur entrée par l'utilisateur printf("Longueur en metres a transformer en pieds et pouces: "); scanf("%lf", &longueur); /* arrondir la longueur en pouces uniquement*/ int pouces = (int)(longueur/METRE_PAR_POUCE + 0.5); /* calculer le nombre de pieds */ int pieds = pouces/POUCES_PAR_PIED; /* soustraire les pieds aux pouces */ pouces = pouces % POUCES_PAR_PIED; /* Afficher le résultat */ printf("%f metres font environ : %d pieds et %d pouces\n", longueur, pieds, pouces); printf("Transformation inverse pour vefification : %f\n", (pieds*POUCES_PAR_PIED + pouces)*METRE_PAR_POUCE); return EXIT_SUCCESS; }
Informatique 1 ©É. Taillard, 2018 98
Opérateurs de relation bPermet de comparer des expressions numériques
Les opérateurs de relation retournent 1 (= true) si la relation est vraie, et 0 (= false) sinon
< strictement plus petit
<= plus petit ou égal
> strictement plus grand
>= plus grand ou égal
== égal
!= différent de
Attention à la différence entre les opérateurs d’affectation (=) et de comparaison (==)
Comme tout opérateur en C retourne une valeur, (y compris l’opérateur d’affectation), cette dernière
peut être interprétée comme vraie ou fausse
a = b = c La variable b est modifiée ; a contient la valeur de c
a = b == c La variable b n’est pas modifiée ; a contient 0 ou 1, selon le résultat de b == c
< <= >= et > sont prioritaires par rapport à == et !=
Informatique 1 ©É. Taillard, 2018 99
Exercice III.11 Opérateurs de relation et opérateurs logiques
Soient les déclarations de variables suivantes :
int x, y, condition;
Écrire l'expression ci-dessous en mettant des parenthèses montrant l'ordre d'évaluation.
condition = x >= 0 && x <= 20 && y > x || y == 50 && x == 2 || y == 60;
Donner la valeur de « condition » évaluée avec les valeurs suivantes de x et y.
1) x = -1; y = 60;2) x = 0 ; y = 1;3) x = 19 ; y = 1;4) x = 0 ; y = 50; 5) x = 2 ; y = 50; 6) x = -10 ; y = 60;
Informatique 1 ©É. Taillard, 2018 100
COMPARAISON À L’ÉGALITÉ DE DEUX RÉELS
Rappel : l’arithmétique avec des nombres en virgule flottante n’est pas exacte
Exemple
double a = 0.1, b = 0.4, c = 0.2, x, y;x = a + b + c; y = a + c + b;
printf("%d %d %d %d\n", x==y, x != y, x <= y, x >= y);
Peut imprimer 0 1 1 0
Il faut donc s’abstenir d’utiliser ces opérateurs sur des réels
Sauf éventuellement x == 0.0, car 0 n’a qu’une représentation
Alternative :
Utiliser la constante DBL_EPSILON de float.h et la fonction valeur absolue fabs(x) de math.h
Informatique 1 ©É. Taillard, 2018 101
Opérateurs booléens b! Non logique (monadique)
!a vaut 0 pour toute valeur numérique a non nulle (quel que soit son type)
!a vaut 1 si, et seulement si a est nul
&& et logique
Si l’opérande de gauche d’un && est fausse, la partie droite n’est pas évaluée (et le résultat est 0)
|| ou logique
Si l’opérande de gauche d’un || est vraie, la partie droite n’est pas évaluée (et le résultat est 1)
Ces trois opérateurs sont donnés dans un ordre de priorité décroissant
À part le !, ils ont une priorité inférieure aux opérateurs de relation (== > >= ...)
Usuellement, on met des parenthèses pour les expressions logiques comportant plusieurs opérateurs
différents, même si ce ne serait pas nécessaire
b1 || (!b2 && b3) Pourrait s’écrire plus simplement b1 || !b2 && b3
Informatique 1 ©É. Taillard, 2018 102
Exercice III.12 Recherche d’expressions logiques
Écrire des expressions sous la forme d’expressions logiques qui prendront la valeur vrai si, et
seulement si la proposition énoncée est évaluable et vraie. On suppose que a, b et c sont des
nombres entiers.
1) a est positif
2) a est non négatif
3) a est positif ou nul
4) a est nul
5) a est strictement plus petit que b
6) a est un multiple de 3 et non plus grand que b
7) a est plus grand que b mais plus petit que c
8) a est strictement compris entre b et c
9) le code de a représente une lettre majuscule
10) le code de a représente une lettre
11) a est un multiple de 7 ou de 11
12) a/b donne un résultat plus grand que c
Informatique 1 ©É. Taillard, 2018 103
Opérateurs d’incrémentation et de décrémentation b
++ incrémente une variable
-- décrémente une variable
Les deux opérateurs peuvent se placer avant ou après la variable (forme préfixée ou postfixée)
Lorsqu’ils sont utilisés dans une expression, les deux formes ont des comportements différents:
int i = 4, a, b, c, d;
i++; // est équivalent à i = i + 1;++i; // est aussi équivalent à i = i + 1;i--; // est équivalent à i = i - 1;
a = i++; // est équivalent à a = i; i++;b = ++i; // est équivalent à i++; b = i;c = i--; // est équivalent à c = i; i--;d = --i; // est équivalent à i--; d = i;
Informatique 1 ©É. Taillard, 2018 104
L’OPÉRATEUR SIZEOF
Permet de connaître le nombre d’octets utilisé par une variable ou un type donné
char c;size_t taille = sizeof c; // taille toujours égal à 1
sizeof(int); // nombre d’octets d’un entiersizeof(double); // nombre d’octets d’un doublesizeof(void*); // Taille des adresses
Exemple pour des système 32 et 64 bits
char 1 1int 4 4double 8 8void* 4 8
short int 2 2long int 4 8long long int 8 8
float 4 4long double 12 16
Est principalement utilisé pour la réservation dynamique de mémoire
Informatique 1 ©É. Taillard, 2018 105
Exercice III.13 Taille de différents types
Écrire un programme qui affiche la taille des différents types char, short, int, long, long long,
float, double et long double sur votre machine.
Informatique 1 ©É. Taillard, 2018 106
OPÉRATEUR D’ADRESSAGE
& adresse
&i retourne l’adresse (position en mémoire vive) de la variable i
Est utilisé typiquement lors de l’appel à des fonctions devant modifier la valeur d’une variable
passée en paramètre, comme scanf
scanf("%d", &i);
* Indirection
Retourne la valeur contenue dans l’adresse passée comme opérande
Est utilisé typiquement à l’intérieur de fonctions devant modifier la valeur d’une variable
passée en paramètre
Informatique 1 ©É. Taillard, 2018 107
EXEMPLE DE PROGRAMME UTILISANT LES OPÉRATEURS D’ADRESSAGE
void incrementer(int *adresse_variable){ *adresse_variable += 1;}
main(void){ int i = 0; incrementer(&i); incrementer(&i); // i vaut maintenant 2}
Informatique 1 ©É. Taillard, 2018 108
OPÉRATEURS DE DÉCALAGE DE BITS
Opérations de bas niveau
Ne s’applique qu’aux types entiers
Il faut connaître la représentation interne des entités que l’on manipule
<< Décalage à gauche
i = i << 2;Les deux bits de gauche sont perdus
Les deux bits de droite sont des 0
Dans l’exemple, multiplie i par 4 (si c’est un entier)
>> Décalage à droite
i = i >> 3;Les deux bits de droite sont perdus
Les deux bits de gauche sont des 0 si i est non signé
sinon, il peut y avoir soit des 0, soit le bit de signe
11101100 << 3→ 01100000
11101100 >> 3→ ???11101
Informatique 1 ©É. Taillard, 2018 109
OPÉRATEURS DE MANIPULATION DE CHAMPS DE BITS
~ complément à un ou inversion bit à bit (monadique)
& Et bit à bit
| Ou bit à bit
^ Ou exclusif bit à bit
~1 1 1 0 1 1 0 0→ 0 0 0 1 0 0 1 1
1 1 1 0 1 1 0 0 & 0 1 0 1 0 1 1 0
→ 0 1 0 0 0 1 0 0
1 1 1 0 1 1 0 0 | 0 1 0 1 0 1 1 0
→ 1 1 1 1 1 1 1 0
1 1 1 0 1 1 0 0 ^ 0 1 0 1 0 1 1 0
→ 1 0 1 1 1 0 1 0
Mettre le N + 1e bit de i à 0 :
i = i & ~ ( 1 << N );
Informatique 1 ©É. Taillard, 2018 110
Exercice III.14 Calcul de masques binaires
Soient les déclarations suivantes :
char m, n = 2, d = 0x55, e = 0xAA;
Représentez en binaire et en hexadécimal la valeur de tous les bits de la variable m après exécution
de chacune des instructions suivantes.
1) m = 1 << n;2) m = ~(1 << n);3) m = d | (1 << n);4) m = e | (1 << n);5) m = d ^ (1 << n);6) m = e ^ (1 << n);7) m = d & ~(1 << n);8) m = e & ~(1 << n);Pour chaque expression, exprimer en français la fonction qu’elle remplit. Par exemple l'expression 1
calcule un nombre binaire m dont seul le n + 1e bit est à 1.
Exercice III.15 Programmation d'un registre système
On dispose de variables entières n et v. Écrire les instructions permettant de :
Mettre à 1 le bit numéro n de v.
Mettre à 0 le bit numéro n de v.
Inverser le bit numéro n de v.
Informatique 1 ©É. Taillard, 2018 111
OPÉRATEURS D’AFFECTATION
L’opérateur d’affectation = vu plus haut retourne une valeur : celle de la valeur
affectée
Exemple :
a = (c = b - 1) + 3;Dans ce cas, on fait d’abord
c = b - 1;
On ajoute ensuite 3 à la valeur de cette expression (qui est contenue maintenant dans c) et
on met le résultat dans la variable a
Souvent, on ignore la valeur retournée, comme dans l’expression :
a = b * 2;
Les opérateurs + - * / % >> << | & ^ peuvent être associés à l’affectation
Exemple
x += 8; // raccourci équivalent à x = x + 8;x %= 8; // raccourci équivalent à x = x % 8;// etc.
Informatique 1 ©É. Taillard, 2018 112
Exercice III.16 Opérateur d’affectation
On considère les déclarations suivantes :
int i, j, k;
Donner les valeurs des variables i, j, k après l'exécution de chacune des expressions ci-dessous.
i = (k = 2) + (j = 3); i = (k = 2) + (j = 2) + j * 3 + k * 4; i = (i = 3) + (k = 2) + (j = i + 1) + (k = j + 2) + (j = k - 1);
Informatique 1 ©É. Taillard, 2018 113
Exercice III.17 Erreur de programmation
On considère le programme suivant :
#include <stdio.h>#include <stdlib.h>
int main(){ int n; printf("Testeur de nombre.\n"); printf("n:"); scanf("%d", &n); if (n = 0) printf("n est nul\n"); else if (n > 0) printf("n est positif\n"); else printf("n est negatif\n"); return EXIT_SUCCESS;}
Qu’affiche ce programme lorsqu’on saisit la valeur 0 ? et lorsqu’on saisit la valeur 10 ?
Quelle correction faut-il apporter pour que ce programme fonctionne ?
Informatique 1 ©É. Taillard, 2018 114
AUTRES OPÉRATEURS
[] Accès aux éléments d’un tableau
. Accès aux membres d’une structure
-> Accès aux membres pour un pointeur vers une structure
, Opérateur d’enchaînement
Retourne la valeur de l’opérande de droite
Est utilisé pour regrouper plusieurs expressions dont seule la valeur de la dernière
(la plus à droite) importe
? : Opérateur conditionnel
Seul opérateur triadyque du langage.
condition ? expression_1 : expression_2
Retourne la valeur de expression_1 si condition est vrai; expression_2 sinon
Utilisation typique i = max(a, b) s’écrit : i = a > b ? a : b;
Informatique 1 ©É. Taillard, 2018 115
Exercice III.18 Opérateur conditionnel
1) Simplifier l'expression suivante
z = (a > b ? a : b) + (a <= b ? a : b) ;
2) Donner une expression qui prend la valeur de m + n si l’opération n’entraîne pas de dépassement
de capacité, LLONG_MAX s’il y a un débordement positif et LLONG_MIN si le débordement est négatif;
on suppose m et n de type long long int.
3) Donner une expression qui prend la valeur : -1 si n est négatif; 0 si n est nul; 1 si n est positif.
Informatique 1 ©É. Taillard, 2018 116
ASSOCIATIVITÉ DES OPÉRATEURS
Seuls les opérateurs
monadiques + - & * ! ~ sizeof
d’affectation = += <<= etc.
conditionnel ? :
d’enchaînement ,
s’évaluent de droite à gauche, tous les autres s’évaluent de gauche à droite
L’ordre d’évaluation des opérandes est fixé par le langage uniquement pour les opérateurs
&& || ?: ,
Informatique 1 ©É. Taillard, 2018 117
PRIORITÉ DES OPÉRATEURS
Priorité Description
16 ++ -- Incrémentation, décrémentation postfixées
16 ( ) [ ] Modification de priorité, accès à un élément d’un tableau
16 -> . Accès aux membres de structures
15 sizeof ++ -- Taille en octets, incrémentation, décrémentation préfixées
15 ~ ! NON bit à bit, NON logique
15 + - * & plus, moins modadiques, indirection, adresse de
14 ( ) Conversion de type, casting
13 *, /, % Multiplication, division, reste
12 +, - Addition, soustraction
11 <<, >> Décalage bit à bit
10 <,<=,>,>= Opérateurs relationnels
9 ==, != Egalité, Inégalité
8 & ET bit à bit
Informatique 1 ©É. Taillard, 2018 118
PRIORITÉ DES OPÉRATEURS
7 ^ OU EXCLUSIF bit à bit
6 | OU bit à bit
5 && ET logique
4 || OU logique
3 ? : Opérateur conditionnel
2 = *= /= Opérateurs d'affectation
%= += -=
<<= >>=
&= |= ^=
1 , Opérateur d’enchaînement
Informatique 1 ©É. Taillard, 2018 119
Exercice III.19 Morceaux de codes
Écrire des morceaux de codes permettant de :
1) Mettre dans la variable c le minimum entre la valeur de a et celle de b
2) Intervertir les valeurs contenues dans deux variables a et b si la valeur de a est plus grande
que la valeur de b
3) Mettre dans la variable d le maximum entre les valeurs de a, b et c
4) Trier par ordre croissant le contenu de trois variables a, b et c
5) Calculer a modulo b, dans le sens que le résultat doit toujours être compris entre 0 (compris)
et sgn(b)|b|(non compris)
Informatique 1 ©É. Taillard, 2018 120
Exercice III.20 Quelques casse-tête
Volontairement compliqués, ce ne sont pas des exemples de bonne programmation ! On suppose
pour la suite que le type short est implanté sur 16 bits.
1) Quelle est la valeur de i après l'exécution des instructions suivantes ?
unsigned short i = 32767;i++;
2) Quelle est la valeur de i après l'exécution des instructions suivantes ?
short i = 32767;i++;
3) Quelle est la valeur de i après l'exécution des instructions suivantes ?
short i = 0;i = i--;i = --i;i = i--;
4) Quelle est la valeur de i après l'exécution de l’instruction suivante ?
short i = 'A' > 'B' ? 'C' : 'D';
5) Quelle est la valeur de i après l'exécution des instructions suivantes ?
short i = 0;i = (++i, i++, ++i, i++);
Informatique 1 ©É. Taillard, 2018 121
6) Quelle est la valeur de i, j et k après l'exécution des instructions suivantes ?
short i = 0, j = 1, k;k = k = 5, i++ >= j ? i++ : --j;
7) Quelle est la valeur de i, j et k après l'exécution des instructions suivantes ?
short i = 0, j = 1, k;k = (k = 5, i++ >= j ? i++ : --j);
8) Quelle est la valeur de i, j et k après l'exécution des instructions suivantes ?
short i = 0, j = 1, k;k = (k = 5, ++i >= j ? i++ : --j);
9) Quelle est la valeur de i, j et k après l'exécution des instructions suivantes ?
short i = 0, j = 1, k;k = (k = 5, i = j ? i++ : --j);
10) Quelle est la valeur de i, j et k après l'exécution des instructions suivantes ?
short i = 2, j = 1, k;k = i >= j << 1 ? i++ << 2 : --j << 3;
Informatique 1 ©É. Taillard, 2018 122
Exercice III.21 Valeurs de variables
Avec les déclarations:
double f1, f2 = 7.0;int i1, i2 = 7;
Donner la valeur des variables modifiées par les expressions suivantes (elles ne dépendent pas les
unes des autres, donc pour chacune, les déclarations ci-dessus sont valables !) :
i2 = 1 + ( i1 = i2 + 1); i1 = i2 = i2 + 1;i1 = i2 + 1, i1 = i2 + i1; i1 = 5 + - i2;f1 = i2 / 2 + i2; f1 = i2 / 2 + f2;i1 = i2 / 2 + f2 + .5; i1 = i2 / 2 + f2 + 1.9;i1 = (int) f2 + 1.9; i1 = (int) f2 % i2;i1 = i2 >= i2 + 1; i1 = ( i2 = 7 ) + 1;i1 = ( i2 == 7 ) + 1; i1 = i2 < 3 || f2 > 3;i1 = i2 && f2; i1 = !!!i2;i1 = 5 << 3; i1 = -1 >> 1;i1 = -5 >> 1; i1 = ( ( i2 + i2 ) * 2 ) >> 2;i1 = i2 | 1; i1 = i2 & 1;i1 = i2 ^ 1; i1 = ~0;f1 = f2++; f1 = ++f2;i1 = +++i2; f1 = i2==0 ? 0 : i2<0 ? -1 : 1;i1 = ++i2 == 8 ? i2++ : --i2; i2 += ++i2;i1 ^= i1;
Informatique 1 ©É. Taillard, 2018 123
Exercice III.22 Recherche d'expressions
On suppose n et m des variables entières. Donner :
3 expressions différentes permettant de multiplier la valeur de n par 8
2 expressions pour ajouter 2 à m
2 expressions pour affecter la valeur de m à n si m est positif et mettre n à 0 sinon
2 expressions pour mettre n à 0 si m est pair et à 1 sinon
2 expressions pour mettre n à 1 si m est pair et à 0 sinon
3 expressions pour affecter à m la valeur 2m + 2n
4 expressions pour incrémenter n
1 expression pour prendre l’opposé de n uniquement si m est négatif
4 expressions pour mettre dans n la valeur de ses 4 bits de poids faible
1 expression pour calculer le volume d’une sphère de rayon n
Informatique 1 ©É. Taillard, 2018 124
Exercice III.23 Opérateurs combinés
En reprenant à chaque fois les valeurs suivantes pour i et j :
int i = 1, j = 3, z;
Calculer les valeurs de i, j et le cas échéant z après l'exécution des instructions suivantes :
1) i += j;2) i += -j;3) i -= j;4) i -= -j;5) i *= j;6) i *= -j;7) i /= j;8) z = i * j == 6;9) z = i++ * j == 6;10) z = ++i * j == 6;
Informatique 1 ©É. Taillard, 2018 125
Exercice III.24 Opérateurs incorrects
On suppose avoir déclaré :
double f1, f2 = 7.0;int i1, i2 = 7;Indiquer ce qui est incorrect dans les expressions suivantes :
1) int(f2) + 1.92) f2 % i23) i1 = 1 + i2 = i2 / 24) f1 = f2 << 25) i1 = ++i2++6) i2++ = ++i2
Informatique 1 ©É. Taillard, 2018 126
Exercice III.25 Analyse de la promotion numérique
1) Qu’imprime le programme suivant :
#include <stdio.h>int main(){ unsigned char c = 255, d = 1, e; signed char f = 1, g = 255, h; int x, y; e = c + d; x = e; y = c + d; if (y - x > 3) { h = f + g; x = h; y = f + g; } else x = 3; printf("%d %d\n", x, y); return 0;}
Informatique 1 ©É. Taillard, 2018 127
Exercice III.26 Valeur et type d’expressions
On considère les déclarations suivantes :
char c = 65;short sh = 8;int i = 3;long lg = 23L;float f = 2.fdouble d = 23.9;
Quel est le type et la valeur des expressions suivantes :
d*shc*1d > 25 ? lg : shc > 25 ? c-1 : c+1f/sh(int) f + lgsh * (c == 0)f > d && lg < ci ^ id - (int) di-d-sh!(3-i)!sh*~shf/=fi&sh
Informatique 1 ©É. Taillard, 2018 128
Informatique 1 ©É. Taillard, 2018 129
IV.
STRUCTURES DE CONTRÔLE
Informatique 1 ©É. Taillard, 2018 130
Instruction de sélection if sans alternative b
if (expression)
instruction;
Permet d’effectuer une unique instruction si
l’expression retourne le booléen vrai
(n’importe quoi différent de 0)
Si on a besoin d’effectuer plusieurs instructions, il faut créer un bloc, donc une instruction composée
Exemples
if (a > 0)a--;
if (b < 0){
b++;b = b*b;
}
Expression
instruction
Vrai (≠ 0)Faux (= 0)
Suite du programme
Informatique 1 ©É. Taillard, 2018 131
Exercice IV.1 Instruction « if »
Avec la déclaration:
int i = 8;Indiquer pour chaque groupe d'instructions ci-dessous s'il permet effectivement d'afficher que i vaut
8. Si ce n'est pas le cas, expliquer la nature de l'erreur.
//1if (!(i < 8) && !(i > 8)) then printf("i vaut 8\n");
//2if (!(i < 8) && !(i > 8)) printf("i vaut 8"); printf("\n");
//3if !(i < 8) && !(i > 8) printf("i vaut 8\n");
//4if (!(i < 8) && !(i > 8)) printf("i vaut 8\n");
//5if (i = 8) printf("i vaut 8\n");
//6
Informatique 1 ©É. Taillard, 2018 132
if (i & (1 << 3)) printf("i vaut 8\n");
//7if (i ^ 8) printf("i vaut 8\n");
//8if (i - 8) printf("i vaut 8\n");
//9if (i == 1 << 3) printf("i vaut 8\n");
//10if (!((i < 8) || (i > 8))) printf("i vaut 8\n");
Informatique 1 ©É. Taillard, 2018 133
Instruction if avec alternative b
if (expression)instruction_1;
elseinstruction_2;
Effectue instruction_1 si expression est vraie (≠ 0) ou instruction_2 sinon
Exemple
if (q < 2) { // Utiliser un bloc systématiquement permet parfois
r = 5; // d’éviter des erreurs}else{
r = 3;v = 2;
}
Expression
Instruction_1 Instruction_2
Vrai (≠ 0) Faux (= 0)
Suite du programme
Informatique 1 ©É. Taillard, 2018 134
Sélection avec plusieurs alternatives bif (expression_1)
instruction_1;else if (expression_2)
instruction_2;else if (expression_3)
instruction_3;else
instruction_4;
Attention au cas où on a moins de else que de if
Un else porte toujours sur le if le plus proche au-dessus
Exemple
if (a < b) if (b < c) a = c; else a = b;b = c + 1;
Si a >= b, on saute tout de suite à l’instruction b = c + 1;
Recommandation
Ajouter des else{} pour avoir le même nombre que de if ou créer un bloc
Informatique 1 ©É. Taillard, 2018 135
Erreurs classiques, syntaxiquement correctes bif (a = b) au lieu de if (a == b)
if (a =! b) au lieu de if (a != b)
if (a > b); a = b;au lieu de
if (a > b) a = b;
if (a < b) if (b < c) a = c; else a = b;au lieu de
if (a < b) // Ou encore mieux : if ((a < b) && (b < c)) { // a = c; if (b < c) // else a = c; // a = b; } else a = b;
Informatique 1 ©É. Taillard, 2018 136
Exercice IV.2 Opérations arithmétiques
Écrire un programme qui demande la saisie de 2 valeurs entières, puis qui affiche la somme, la
différence, le produit, le quotient et le modulo de ces deux entiers. Attention au cas où le diviseur
vaut 0 ! Dans ce cas, il ne faut pas calculer le quotient et le modulo, mais afficher un message à
l'utilisateur.
À l’aide de ce programme déterminer la convention utilisée sur votre machine pour définir les
opération de division et du reste de la division lorsqu’un des opérandes est négatif.
Exercice IV.3 Conversion Celsius/Fahrenheit
Écrire un programme permettant de convertir des températures données en degrés Celsius vers des
degrés Fahrenheit et vice-versa. Le programme devra donner le choix du sens de la conversion à
l’utilisateur avant de demander la valeur à transformer. On rappelle que la transformation est donnée
par : Celsius = 5*(Fahrenheit – 32)/9
Informatique 1 ©É. Taillard, 2018 137
Instruction de répétition do … while bRépéter une Instruction tant qu’une condition est vraie
Instruction est faite au moins une fois
doInstruction;
while (Expression);
Remarque :
L’évaluation de Expression peut induire un effet de bord comme dans : while(i=i+1)…
Expression
Instruction
Faux (=0)Vrai (≠ 0)
Suite du programme
Informatique 1 ©É. Taillard, 2018 138
Exercice IV.4 Boucle do … while
Discuter de la validité des affirmations suivantes :
1. Les instructions de la boucle do … while sont toujours exécutées au moins une fois.
2. Comme un mot réservé spécifique commence et termine la boucle, on n'a pas besoin de
créer un bloc lorsque l'on a plusieurs instructions.
3. La condition se trouvant en fin de boucle, on sort de la boucle lorsque la condition est vraie.
4. Le type de la condition peut être char.
5. Les instructions de la boucle ne peuvent pas être une autre boucle do … while.
Informatique 1 ©É. Taillard, 2018 139
Instruction de répétition while bRépéter une instruction tant qu’une condition est vraie
Ne rien faire si la condition est d’emblée fausse
while (Expression)Instruction;
Exemple
int i, n;while (1) { scanf("%d", &n); i = 2; while (i < n/i && n % i != 0)
i++;...
}Attention à l’instruction vide
while(i < 10); // ne s’arrête jamais si i < 10 i = i + 2;
Expression
Instruction
Faux (=0)
Vrai (≠ 0)
Suite du programme
Informatique 1 ©É. Taillard, 2018 140
Exercice IV.5 Boucle while
Avec la déclaration:
int i;Indiquer pour chaque groupe d'instructions ci-dessous ce qui sera affiché à l'exécution:
//1 i = 0; while (i - 10) { i = i + 2; printf ( "%d\n", i ); }//2 i = 0; while ( i - 10 ) i = i + 2; printf ( "%d\n", i );
//3 i = 0; while ( i < 11 ) { i = i + 2; printf ( "%d\n", i ); }
//4 i = 11; while ( i-- ) { printf ( "%d\n", i-- ); }
Informatique 1 ©É. Taillard, 2018 141
//5 i = 12; while ( i-- ) { printf ( "%d\n", --i ); }
//6 i = 0; while ( i++ < 10 ) { printf ( "%d\n", i-- ); }
//7 i = 1; while ( i <= 5 ) { printf ( "%d\n", 2 * i++ ); }
//8 i = 1; while ( i != 9 ) { printf ( "%d\n", i = i + 2 ); }
//9 i = 1; while ( i < 9 ) { printf ( "%d\n", i += 2 ); break; }
Informatique 1 ©É. Taillard, 2018 142
//10 i = 0; while ( i < 10 ) { continue; printf ( "%d\n", i = i + 2 ); }
//11i = -20;do
i * 117 % 51;while (++i);printf("i: %d\n", i);
Exercice IV.6 Calcul de la moyenne et de l’écart-type
Écrire un programme qui calcule la moyenne et l’écart-type d’une suite de valeurs (de type double)
fournies par l’utilisateur. Ce dernier introduit ses valeurs les unes à la suite des autres et indique au
programme qu’il a fini d’introduire ses valeurs par une saisie ne pouvant pas être interprétée comme
une valeur numérique (par exemple q). Par défaut, si aucune valeur est entrée, la moyenne et
l’écart-type sont nuls.
Informatique 1 ©É. Taillard, 2018 143
Exercice IV.7 Test de primalité
Écrire un programme permettant de dire si le nombre entier fourni par l’utilisateur est premier. Si ce
n’est pas le cas, il faudra donner un de ses diviseurs.
Informatique 1 ©É. Taillard, 2018 144
Instruction de répétition for bConcentre tous les éléments de contrôle d’une boucle dans une seule instruction
for (Expression_1; Expression_2; Expression_3)Instruction;
Est équivalent à :
{Expression_1;while (Expression_2){
Instruction;Expression_3;
}}
Utilisation habituelle et recommandée :
Expression_1 Pour déclarer et initialiser la variable de boucle
Expression_2 Pour tester la condition de sortie de la boucle
Expression_3 Pour modifier la variable de boucle
Exemple
int somme = 0;for (int i = 1; i <= 20; i++)
somme = somme + i;
Informatique 1 ©É. Taillard, 2018 145
Exercice IV.8 Boucle for
Indiquer ce que chaque groupe d'instructions ci-dessous provoque comme affichage si l’on suppose
avoir déclaré :
int i, k;//1for (i = 'a'; i < 'd'; printf ("%d\n", ++i));
//2for (i = 'a'; i < 'd'; printf ("%c\n", ++i));
//3for (i = 'a'; i++ < 'd'; printf ("%c\n", i ));
//4for (i = 'a'; i <= 'a' + 25; printf ("%c\n", i++ ));
//5for (i = 1 / 3; i ; printf("%d\n", i++ ));
//6for (i = 0; i != 1 ; printf("%d\n", i = i + 1 / 3 ));
//7for (i = 12, k = 1; k++ < 5 ; printf("%d\n", i-- ));
//8for (i = 12, k = 1; k++ < 5 ; k++,
Informatique 1 ©É. Taillard, 2018 146
printf("%d\n", i-- ));
//9for (i=1 ; printf("Resultat: ") , ++i<5 ; printf("%d\n",i));
//10k = 0;for (;;){
k++;if (k < 20) continue;k = k * 2;break;
}printf("k: %d\n", k);
Exercice IV.9 Intérêts composés
Écrire un programme permettant de calculer des intérêts composés. Le programme doit demander le
montant d’une somme, le taux d’intérêt annuel et le nombre d’années pendant laquelle la somme est
placée sans retraits.
Informatique 1 ©É. Taillard, 2018 147
Exercice IV.10 Entiers divisibles par 3 et 5 entre 2 bornes
Écrire un programme qui demande la saisie de 2 nombre entiers, et qui affiche ensuite (sans utiliser
le caractère '\b') les entiers divisibles par 3 ou par 5 dans cet intervalle sur une même ligne,
séparés par une virgule. La ligne se termine par un point.
Exemple : Saisie des bornes 4 et 13.
Résultat attendu : 5, 6, 9, 10, 12.
Informatique 1 ©É. Taillard, 2018 148
INSTRUCTION BREAK
Permet de sortir prématurément d’une boucle
S’applique à toutes les boucles
while
do…
while
for
Le programme continue à l’instruction qui suit celle de la boucle
Ne pas en abuser, éviter les sorties à de multiples endroits dans une boucle
S’applique également à l’instruction switch où elle est indispensable…
Informatique 1 ©É. Taillard, 2018 149
INSTRUCTION DE SÉLECTION SWITCH
switch permet de construire une table de branchement avec traitement spécifique
de cas
Alternative à une suite de if successifs où les différents cas sont traités en faisant
appel à une instruction de saut
switch (expr_ent){ case (expr_cste_1): instr_1a; instr_1b;…; case (expr_cste_2): instr_2a; instr_2b;…; case (expr_cste_3): case (expr_cste_4): case (expr_cste_5): instr_3; instr_4; instr_5; default: instr_6; instr_7;…;}
Limitations :
On ne peut brancher que sur une expression entière (char, int, etc.)
L’expression constante d’un cas doit être évaluable à la compilation
Toutes les expressions constantes doivent être différentes
Informatique 1 ©É. Taillard, 2018 150
SWITCH
Pour interrompre le flot, utiliser l’instruction break
Par exemple, si on veut effectuer uniquement la suite d’instructions suivant un case mais pas les
suites d’instructions ultérieures, terminer toute les suites d’instructions par break;
Expression_1case:
switch
Expression_2case:
case:
…
Expression_n
Instructions_1
Instructions_2
Instructions_n
…
default: Instruct_defaut
vrai
vrai
vrai
faux
fauxbreak;
Expression
faux
Informatique 1 ©É. Taillard, 2018 151
EXEMPLE D’UTILISATION DE SWITCH
Compter les voyelles, les mots, les phrases et le nombre de caractères d’un texte
#include <stdio.h>#include <stdlib.h>int main(void){ int voyelles = 0, autres = 0, mots = 0, phrases = 0, caracteres = 0; int caractere_lu; // getchar retourne un entier while ((caractere_lu = getchar()) != EOF) { caracteres++; switch(caractere_lu) { case 'a': case 'A': case 'e': case 'E': case 'i': case 'I': case 'o': case 'O': case 'u': case 'U': case 'y': case 'Y': voyelles++; break; case ' ': mots++; break; case '.': phrases++; break; default: autres++; } } printf("Nb voyelles: %d, autres caracteres: %d, mots: %d, phrases: %d\n", voyelles, autres, mots, phrases); printf("Nombre total de caracteres: %d\n", caracteres); return EXIT_SUCCESS;}
Informatique 1 ©É. Taillard, 2018 152
Instructions de saut cIl existe encore des structures de contrôle, en principe plus employées
goto
Pour sauter n’importe où dans un programme (mais pas en dehors d’un sous-programme)
continuePour interrompre l’instruction(-bloc) en cours d’exécution dans une boucle, mais sans terminer la
boucle, comme le fait l’instruction break.
do{ …
switch (expression) {case (cas1) : instr_cas1;case (cas2) : continue; // Équivalent à goto fin_boucle;case (cas3) : break; // Équivalent à goto apres_switch;
}apres_switch :
…continue; // Équivalent à goto fin_boucle
…fin_boucle : ; //Instruction vide : dernière instruction de la boucle
} while (condition)
Informatique 1 ©É. Taillard, 2018 153
Exercice IV.11 Table ASCII
Écrire un programme qui affiche la table des caractères ASCII à partir du numéro 32. Cette table doit
comporter 4 colonnes, correspondant respectivement au codes décimal, octal et hexadécimal puis le
caractère imprimé entre apostrophes :
Decimal|Hexa|Octal|Caractere-------+----+-----+--------- 65| 41| 101| 'A' 66| 42| 102| 'B'
Exercice IV.12 Somme d’entiers
Écrire un programme permettant d’afficher un tableau de la somme des nombres de 1 à i, pour i
allant de 0 à 20.
Exercice IV.13 Tableau de la factorielle
Écrire un programme permettant d’afficher un tableau de i!, pour i allant de 0 à 20.
Exercice IV.14 Somme des chiffres impairs
Écrire un programme calculant la somme des chiffres impairs d’un nombre entier donné par
l’utilisateur.
Informatique 1 ©É. Taillard, 2018 154
Exercice IV.15 Table de multiplication et suite de Fibonacci
Écrire un programme proposant le menu suivant :
0: Quitter1: Table de multiplication2: Suite de Fibonacci
Si l’utilisateur ne désire pas quitter le programme, ce dernier demande un nombre n et affiche à
l’écran soit la table de multiplication de tous les nombres de 1 à n, soit la valeur du nième nombre de
Fibonacci (défini par : f0 = 0, f1 = 1 et fi = fi -2 + fi -1)
Si l’utilisateur fait un choix incorrect, un message le signale avant de réafficher le menu. La table de
multiplication doit être affichée sous la forme suivante (pour n = 5) :
x | 1| 2| 3| 4| 5-----+-----+-----+-----+-----+----- 1| 1| 2| 3| 4| 5-----+-----+-----+-----+-----+----- 2| 2| 4| 6| 8| 10-----+-----+-----+-----+-----+----- 3| 3| 6| 9| 12| 15-----+-----+-----+-----+-----+----- 4| 4| 8| 12| 16| 20-----+-----+-----+-----+-----+----- 5| 5| 10| 15| 20| 25
Informatique 1 ©É. Taillard, 2018 155
Exercice IV.16 Factorisation d’un nombre entier
Écrire un programme permettant de factoriser un nombre entier.
Exercice IV.17 Analyse d’une fonction
Décrire la fonction que pourrait avoir le programme suivant :
#include <stdio.h>int main(){ int i, n; scanf("%d",&n); for (i = 2; n%i && i <= n/i; i++); if (i > n/i) printf("%d\n", n); else printf("%d\n", i); return 0;}
Informatique 1 ©É. Taillard, 2018 156
Exercice IV.18 Instruction de branchement
Indiquer si les affirmations suivantes sont justes ou fausses. Dans les cas où elles sont fausses,
expliquer ce qui serait correct.
Dans une instruction switch :
1. Après le mot réservé case, on peut donner une liste de valeurs séparées par des virgules.
2. Après le mot réservé case on peut donner un intervalle de valeurs.
3. La branche default peut venir n'importe où dans la liste des cas.
4. Les cas dans les différentes branches doivent être donnés dans un ordre croissant des
valeurs.
5. Les valeurs de cas peuvent être données par des variables.
6. Si la valeur n'est pas prévue dans les différentes branches de cas et qu'il n'y a pas de branche
default, le programme continue simplement la séquence d’instructions.
7. Si une branche comporte plusieurs instructions, il faut les mettre entre { }.
8. Toutes les valeurs possibles de l'expression doivent être prévues dans les différentes
branches du switch.
9. Sans instruction particulière, après le traitement d'une branche, on passe à la branche
suivante.
Informatique 1 ©É. Taillard, 2018 157
10. Deux branches différentes peuvent comporter la même valeur de cas.
11. Une instruction switch peut toujours remplacer une instruction if.
12. Une instruction if peut toujours remplacer une instruction switch.
Informatique 1 ©É. Taillard, 2018 158
Exercice IV.19 Analyse de code
Qu’impriment les morceaux de codes suivants :
int i = 2; int t[] = {2, 11, 1, 7, 9, 3}; for (int i = 0; !i; i = t[i]) printf("a%d\n", i);
//////////////////////////////
for (int i = 1; i < 4;) { if (!(i-3)){ printf("b%d ", i); i++; } if (i % 4) { printf("bb%d ", i); i++; } else printf("bbb%d\n", i); i++; }
Informatique 1 ©É. Taillard, 2018 159
//////////////////////////////
for (double d = 2.3456; d > 1; d -= .9) printf("c%.2f\n", d); for (int j = 4, i=1; j > 1; j--, i++) printf("d%d\n",i);
//////////////////////////////
i = 18; while (i--, i > 12); printf("e%d\n",i);
//////////////////////////////
i = 18; while (--i > 0) printf("f%d\n", i/=3);
Informatique 1 ©É. Taillard, 2018 160
//////////////////////////////
i = 0; while (i < 12) { switch(i) { case 0 : i+=2; case 1: break; case 2: i++; case 3: ++i; continue; case 4 : i++; break; default : i*=2; } } printf("g%d\n", i); i = 13; while(i =! 0) printf("h%d\n", --i);
Informatique 1 ©É. Taillard, 2018 161
V.
TABLEAUX
Informatique 1 ©É. Taillard, 2018 162
Généralités sur les tableaux bBut
Permettre de représenter une collection d’éléments du même type
Déclaration d’un tableau
Faire suivre le nom de la variable du nombre d’éléments entre []
Exemples
int t[5];Tableau de 5 entiers dont les éléments sont :
t[0], t[1], t[2], t[3] et t[4]
Représentation schématique d’un tableau :
Les indices sont des entiers (de type int) et commencent toujours à 0
Attention, aucune vérification de la validité des indices
t[–1] et t[5] ne vont pas générer de message d’erreur à la compilation et pourraient donner
l’impression de fonctionner à l’exécution !
t0 t1 t2 t3 t4
Informatique 1 ©É. Taillard, 2018 163
Exercice V.1 Remplissage d’un tableau
Écrire un programme déclarant un tableau de dix entiers, et les initialisant avec les carrés des
nombres de 1 à 10.
1) On utilisera une boucle for() pour l’initialisation du tableau.
2) Écrire le même programme en utilisant une boucle while.
3) Écrire le même programme en utilisant une boucle do … while.
Exercice V.2 Palindrome
Écrire un programme permettant de déterminer si un texte donné est un palindrome.
Exercice V.3 Fréquence de symboles dans un texte
Écrire un programme permettant de donner des statistiques sur la fréquence d’apparition de chaque
symbole typographique d’un texte fourni par l’utilisateur.
Exercice V.4 Moyenne avec exclusion des extrêmes
Pour éviter qu’un des 9 membres d’un jury ne favorise trop ou au contraire défavorise un candidat à
une épreuve, les 2 notes les plus extrêmes proposées sont éliminées avant de calculer la note
moyenne que recevra le candidat. Écrire un programme permettant de saisir les notes et de calculer
la moyenne, avec et sans exclusion des extrêmes.
Informatique 1 ©É. Taillard, 2018 164
Dimensionnement des tableaux bDepuis C99 la taille du tableau n’a pas besoin d’être connue à la compilation
Le compilateur ne peut donc pas réserver de place dans l’exécutable pour mémoriser les
éléments du tableau ; il va uniquement générer le code nécessaire pour procéder à cette
réservation qui sera faite lors de l’exécution
Avec la notation [] (VLA, Variable Length Array) les éléments du tableau sont stockés
sur la pile (de taille limitée)
À l’exécution, il faut donc connaître la taille de la portion mémoire à réserver
Exemple
int nombre_notes;printf("Donnez le nombre de notes\n");scanf("%d", &nombre_notes);double notes[nombre_notes];
À noter
Les tableaux sont intimement liés à la notion de pointeur
L’identificateur d’un tableau contient en réalité un pointeur constant
(l’adresse vers lequel il pointe ne peut changer)
Informatique 1 ©É. Taillard, 2018 165
Exercice V.5 Calcul de n! avec tous les chiffres
Écrire un programme demandant à l’utilisateur un nombre entier non négatif n et affichant la valeur
de n! avec tous les chiffres. Indications : calculer le nombre de chiffres c de n! puis déclarer un
tableau de c entiers initialisé avec la représentation de la valeur de 0! (0, 0, 0, …, 0, 1). Dans la
boucle principale, où i varie de 2 à n, on commence par multiplier les c composantes du tableau par i
avant de faire les reports vers les cases du tableau de poids plus élevé pour ramener chaque case à
une valeur comprise entre 0 et 9.
Exercice V.6 Affichage de nombres premiers
Écrire un programme permettant d’afficher tous les nombres premiers jusqu’à 100000 en utilisant la
technique du crible d’Ératosthène.
Informatique 1 ©É. Taillard, 2018 166
Chaînes de caractères b
Les tableaux de caractères sont si fréquemment utilisés que des fonctionnalités
supplémentaires ont été prévues en C
Une chaîne de caractères est un tableau de caractères avec une marque de fin de
chaîne représentée par le caractère ’\0’
Exemple
char texte[10];texte[0] = 'F'; texte[1] = 'i'; texte[2] = 'n'; texte[3] = '\n'; texte[4] = '\0';printf(texte);
Affichera le message Fin à l’écran, suivi d’un retour de ligne
À noter dans cet exemple que les valeurs du tableau texte d’indices 5 à 9 ne sont pas initialisées ni
accédées par la fonction printf
Informatique 1 ©É. Taillard, 2018 167
Initialisation d’un tableau de caractères à la déclaration b
À la déclaration (mais plus par la suite), il est possible d’initialiser un tableau de caractères de façon
plus commode :
char texte[10] = "Fin";
La marque de fin ’\0’ est automatiquement ajoutée dans texte[3]
Les entrées 4 à 9 ne sont pas initialisées.
On peut également laisser le compilateur se charger de compter le nombre de caractères de la chaîne
char texte[] = "Fin";
Déclare un tableau de 4 caractères (4, et non 3)
Informatique 1 ©É. Taillard, 2018 168
Tableaux à plusieurs dimensions bLes éléments d’un tableau peuvent être des tableaux.
Dans ce cas, on a un tableau à deux dimensions ou bidimensionnel
Déclaration
double m[2][5];Tableau de 2 tableaux composés chacun de 5 réels
Représentation
m est une matrice 2×5
m[1] désigne le deuxième tableau de 5 réels, soit le tableau unidimensionnel
m[1][3] désigne l’entier m13
m00 m01 m02 m03 m04
m10 m11 m12 m13 m14
m10 m11 m12 m13 m14
Informatique 1 ©É. Taillard, 2018 169
Initialisation d’un tableau à la déclaration b
À la déclaration, il est possible d’initialiser le contenu du tableau
int poids[] = {4, 3, 9, 8}; // sizeof poids donne 4 * sizeof(int) (= 16)
int somme_poids[25] = {}; // 25 éléments intialisés à 0
int nb_jour_mois[2][13] = { {0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31} };
int nb_jours_mois[][13] = { {0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31} };
Attention à ne pas confondre
la dimension d’un tableau (= le nombre d’indices) et
sa taille (= le nombre de ses éléments)
En C, on peut déclarer des tableaux de n’importe quelle dimension
int T[10][20][30][40];
Déclare un tableaux à 4 dimensions comportant en tout 240’000 entiers
Informatique 1 ©É. Taillard, 2018 170
STOCKAGE ET REPRÉSENTATION D’UN TABLEAU
Lorsqu’on déclare un tableau :
int t[][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {0, 4, 2} };
Le compilateur génère un pointeur constant t vers un entier et réserve de la place mémoire pour 12
entiers à partir de l’adresse pointée par t
À l’initialisation, il compte le nombre de fois que l’on spécifie un groupe de 3 entiers
Les 12 entiers sont placés à des adresses consécutives
À noter que les 2 déclarations suivantes vont initialiser la mémoire exactement de la même manière
int v[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 4, 2 };int w[][6] = { {1, 2, 3, 4, 5, 6}, {7, 8, 9, 0, 4, 2} };
Pour accéder à l’élément de valeur 6 :
Pour v, le compilateur n’a besoin que de connaître l’indice 5
En revanche il a besoin de connaître a) la taille pour le second indice (3 pour t, 6 pour w)
b) le premier indice (1 pour t, 0 pour w) et c) le second indice (2 pour t, 5 pour w)
Informatique 1 ©É. Taillard, 2018 171
Tri des éléments d’un tableau c
Tri par valeur croissante de n éléments
Les algorithmes intuitifs de tri, tel que
— Chercher l’indice j du plus petit élément, échanger t[0] et t[j]
— Recommencer avec le 2e plus petit, l’échanger avec t[1]
— etc. jusqu’au nième
Effectuent un nombre d’opérations proportionnel à n2
Dès que n dépasse quelque dizaine de milliers, le temps de tri devient prohibitif
Informatique 1 ©É. Taillard, 2018 172
Tri efficace d’un tableau cLa librairie standard <stdlib.h> met à disposition une fonction qsort qui permet d’effectuer un tri
beaucoup plus efficacement.
Cette fonction fait appel à une autre fonction, programmée et fournie par l’utilisateur, qui a pour but
d’indiquer si un élément a doit être considéré comme plus grand, plus petit ou égal à un élément b
Pour un tableau de double, la fonction à fournir par l’utilisateur est, par exemple :
int plus_grand(const void *a, const void *b){
if (*(double*)a > *(double*)b) return 1; else if (*(double*)a < *(double*)b) return -1; else return 0;
}
Pour trier du plus petit au plus grand le tableau t déclaré ainsi :
double t[n];
L’appel de qsort sera :
qsort(t, n, sizeof(double), plus_grand);
Informatique 1 ©É. Taillard, 2018 173
Exercice V.7 Concaténation de chaînes
Écrire un programme permettant de concaténer deux chaînes de caractères (d’au maximum 80
caractères) fournies par l’utilisateur et de mettre le résultat dans un tableau.
Écrire une fonction retournant 0 si deux chaînes de caractères (d’au maximum 80 caractères)
fournies par l’utilisateur sont identiques, ou le numéro du premier caractère où elles diffèrent.
Exercice V.8 Suppression des espaces
Écrire une fonction qui supprime les espaces dans une chaîne de caractères fournie en paramètre.
Exercice V.9 Transposition de matrice
Écrire une fonction permettant de transposer une matrice.
Informatique 1 ©É. Taillard, 2018 174
Exercice V.10 Simulation d’une calculatrice
Écrire un programme simulant une calculatrice fonctionnant avec la notation polonaise inverse.
Implanter seulement les 4 opérations arithmétiques de base et considérer que la calculatrice ne peut
stocker que 20 nombres.
La notation polonaise inverse, ou notation post-fixée, permet d’écrire des formules sans utiliser de
parenthèses. Les opérandes sont d’abord introduits et mémorisés dans un tableau (pile). Ensuite,
lorsqu’un opérateur est introduit, le calcul se fait en retirant les 2 derniers opérandes stockés dans la
pile puis en mémorisant le résultat sur la pile. Par exemple, le calcul de 3*(4+5*7) se fait en
introduisant successivement:
5, 7, *, 4, +, 3, *
ou encore 3, 4, 5, 7, *, +, *
S’assurer que l’utilisateur ne puisse pas entrer des opérateurs ou des opérandes invalides. Éliminer
les opérations invalides tout en affichant un message d’erreur et en vidant la pile. Cette dernière peut
également être vidée par l’utilisateur au moyen de l’opérateur ’c’.
Informatique 1 ©É. Taillard, 2018 175
VI.
SOUS-PROGRAMMES
Informatique 1 ©É. Taillard, 2018 176
Fonctions bButs
Représenter une suite d’instructions par une abstraction
Cette abstraction pourra s’utiliser comme un nouvelle instruction
Permet d’éviter d’écrire plusieurs fois la même section de code
Simplifie la lecture des programmes
Structure le code
Meilleure maîtrise et facilite la mise au point des programmes :
Découper les opérations à effectuer en sections «simples»
Programmer chaque section
Mettre le tout ensemble dans le programme principal
Informatique 1 ©É. Taillard, 2018 177
Synopsis b
type_retour identificateur_fonction(liste de paramètres formels){
Déclarations et instructions propresà la fonction
return objet_retour;}
Exemple
double factorielle(int n){
double valeur = 1.0;
for (int i = 2; i <=n; i++)valeur *= (double)i;
return valeur;}
S’il y a plusieurs paramètres, ils sont séparés par , et on doit spécifier le type de chacun
Informatique 1 ©É. Taillard, 2018 178
Appel à une fonction bEffet de l’appel à une fonction
#include <stdio.h>#include <stdlib.h>
int main(void){ int a; printf("Entrez la valeur de a : "); scanf("%d", &a); printf("a! = %f\n", factorielle(a)); return EXIT_SUCCESS;}
double factorielle(int n){ double valeur = 1.0; for (int i = 2; i <=n; i++) valeur *= (double)i;
return valeur;}
Copier a dans n
Informatique 1 ©É. Taillard, 2018 179
Fonctions à plusieurs paramètres b
Les paramètres sont séparés par des virgules dont ont doit spécifier le type
double binomiale(int n, int k){ return factorielle(n)/factorielle(k)/factorielle(n-k);}
Dans cet exemple, n et k sont les paramètres formels
Lors d’un appel à la fonction factorielle, la fonction appelante doit leur donner une valeurs et ils
sont appelés paramètres effectifs
L’ordre dans lequel les paramètres effectifs sont évalués n’est pas spécifié
Ne jamais écrire quelque chose du style : binomiale(++n, n);
Informatique 1 ©É. Taillard, 2018 180
Mécanisme d’appel de fonction bAvant l’appel
Les paramètres effectifs sont évalués et empilés
Appel
L’adresse de retour est empilée
L’adresse d’exécution courante est modifiée pour pointer vers les instructions de la fonction
appelée
Entrée dans la fonction
Les éventuelles variables locales à la fonction sont empilées
Exécution du retour de fonction
Le pointeur de pile est déplacé pour libérer les variables locales
L’adresse de retour est dépilée
L’adresse courante est modifiée vers l’adresse de retour
Informatique 1 ©É. Taillard, 2018 181
Retour à la fonction appelante b
Le pointeur de pile est déplacé pour libérer l’espace utilisé par les variables locales, l’adresse
de retour et les paramètres
La fonction appelante dispose alors en sommet de pile (ou dans un registre donné) de la
valeur retournée par la fonction
Valeur // Local à !
i // Local à !
Adresse retourn // Paramètre de !
1.0
–132.456
A340Zone propre à factorielle
Zone libre, à disposition
Zone utilisée
Valeur de retour
8
2Sommet de pile
Informatique 1 ©É. Taillard, 2018 182
Particularités des fonctions b
Les fonctions sont toutes déclarées au dessus du programme principal (main)
Un seul mécanisme de passage de paramètres en C : par valeur
Il y a toujours copie de la valeur des paramètres effectifs lors de l’appel de la fonction
On travaille sur les copies
Les valeurs originales ne peuvent pas être modifiées directement
Il n’est pas possible de déclarer une fonction imbriquée dans une autre fonction
Les identificateurs déclarés à l’intérieur d’une fonction ne sont visibles que dans cette fonction
Informatique 1 ©É. Taillard, 2018 183
Particularités des fonctions bSeules les variables globales déclarées au-dessus de deux fonctions sont visibles simultanément dans
ces deux fonctions
La valeur retournée par une fonction est celle de l’expression qui suit le premier return rencontré
Lorsqu’un return est rencontré, le flux d’instructions de la fonction est interrompu et on retourne au
flux d’instructions qui était exécuté juste avant l’appel de la fonction
La dernière instruction exécutée d’une fonction retournant une valeur doit être un return, sinon la
valeur retournée est indéfinie
On peut aussi utiliser return; dans une fonction sans valeur de retour
Contrairement au C++ ou dans d’autres langages, il n’est pas possible de surcharger une fonction
(avoir deux définitions pour un même identificateur de fonction) ou de surcharger des opérateurs
Informatique 1 ©É. Taillard, 2018 184
Exercice VI.1 Fonction moyenne
Écrire une fonction « moyenne » qui reçoit 3 paramètres réels et qui retourne leur moyenne.
Exercice VI.2 Fonction min
Écrire une fonction « min » qui reçoit 3 paramètres réels et qui retourne la plus petite valeur.
Exercice VI.3 Test de tri
Écrire une fonction « trie » qui reçoit 3 paramètres réels et qui indique s’ils sont triés dans l’ordre
croissant.
Exercice VI.4 Calcul d’un polynôme
Écrire une fonction qui calcule la valeur d’un polynôme du second degré. La fonction reçoit 4
paramètres de type double correspondant aux facteurs du polynôme et à la valeur de sa variable.
Exercice VI.5 Nombre de racines d’un polynôme
Écrire une fonction qui reçoit 3 paramètres entiers correspondant aux facteurs d’un polynôme du
second degré et qui retourne le nombre de 0 que ce polynôme a dans l’espace des nombres réels.
Informatique 1 ©É. Taillard, 2018 185
Exercice VI.6 Test d’appartenance à l’ensemble de Mandelbrot
Écrire une fonction qui reçoit un nombre complexe c et qui indique le nombre d’itérations nécessaires
pour vérifier si ce nombre ne fait pas partie de l’ensemble de Mandelbrot. Si le nombre d’itérations est
supérieur à 255, on considérera que c fait partie de l’ensemble. Pour déterminer qu’un nombre c ne
fait pas partie de l’ensemble de Mandelbrot, on calcule (avec z0 = c) jusqu’à ce que la
norme de zn dépasse 2.
Exercice VI.7 Distance entre 2 points
Écrire une fonction qui reçoit les coordonnées de 2 points du plan (x1, y1) et (x2, y2) et qui retourne la
distance séparant ces points.
zn
zn 1–
2c+=
Informatique 1 ©É. Taillard, 2018 186
Fonction sans valeur de retour bUne fonction sans valeur de retour (une procédure) retourne le type void
#include <stdio.h>#include <stdlib.h>
/* dessine un triangle avec des astérisques */void dessiner_triangle(int dimension){ for (int i = 1; i <= dimension; i++) { for (int j = 1; j <= i; j++) putchar(’*’); putchar(’\n’); }}
void dessiner_demi_sapin(int nb_branches){ for (int i = 1; i <= nb_branches; i++) dessiner_triangle(i);}
int main(void){ dessiner_demi_sapin(6); return EXIT_SUCCESS;}
Informatique 1 ©É. Taillard, 2018 187
Fonction sans paramètres bOn spécifie une fonction sans paramètres par void comme liste de paramètres
#include <stdio.h>#include <stdlib.h>
// fonction générant des nombres pseudo-aléatoires entre 0.0 (non compris) et// 1.0 (compris), de période m = 2^31 - 1double aleatoire(void) // (void) ou () obligatoires {int m = 2147483647; // paramètres du générateur aléatoire int a = 16807; int b = 127773; int c = 2836; // variable globale protégée par "static" pour le germe static int germe = 12345678; // Fixe le début de la séquence int kl = germe / b; germe = a * ( germe % b ) - kl * c; if (germe < 0) germe = germe + m; return (double)germe/(double)m; }
int main(void){ // afficher 10 nombres pseudo-aléatoires for (int i = 1; i <= 10; i++) printf("%f\n", aleatoire()); return EXIT_SUCCESS;}
Informatique 1 ©É. Taillard, 2018 188
Exercice VI.8 Lecture d’un nombre binaire avec conversion
Écrire une fonction qui lit une ligne de texte caractère par caractère tant que ces derniers sont des 0
et des 1 et qui retourne l’entier correspondant au code binaire saisi.
Exercice VI.9 Lecture d’un nombre entier
Écrire une fonction qui ne fait pas appel à « scanf » et qui retourne la valeur du nombre entier
introduit par l’utilisateur
Informatique 1 ©É. Taillard, 2018 189
Procédure sans paramètre bTypiquement utilisée pour structurer un programme et en simplifier la lecture
Exemple :
void decrire_programme(void){ printf("Ce programme imprime la partie droite d'un\n"); printf("sapin a n branches; chaque branche est\n"); printf("constituee d'un triangle fait avec des ** \n"); printf("L'utilisateur doit specifier le nombre de\n"); printf("branches a imprimer\n");}
void terminer_programme(void){ printf("Pour terminer le programme, pressez <return>\n"); while (getchar() != ’\n’){} getchar();}
// ...int main(void){ decrire_programme(); // ... terminer_programme(); return EXIT_SUCCESS;}
Informatique 1 ©É. Taillard, 2018 190
Simulation en C du passage de paramètres par référence bDans certains cas, on aimerait qu’une fonction ou une procédure puisse modifier la
valeur de certains paramètres. Exemple : échanger les valeurs de deux variables.
On aimerait pouvoir déclarer une procédure echanger qui puisse être utilisée de la façon suivante :
echanger(x, y); // ne fonctionne pas en C
Contrairement à C++ ou d’autres langages plus modernes, C ne propose pas le passage de
paramètres par référence. Il faut donc simuler ce mécanisme à l’aide d’un passage de paramètre par
valeur. Ceci peut être fait en passant l’adresse des paramètres que l’on veut modifier.
void echanger(int *adresse_a, int *adresse_b){ int temp = *adresse_a; *adresse_a = *adresse_b; *adresse_b = temp;}
int main(void){ int x, y; echanger(&x, &y); }À noter ici int *adresse_a qui spécifie que adresse_a est un « pointeur vers un
entier » et l’utilisation intensive des opérateurs & « adresse de » et * « valeur
d’une adresse pointée »
Informatique 1 ©É. Taillard, 2018 191
Passage de tableaux en paramètre bOn peut également passer des tableaux en paramètre :
double produit_scalaire(int n, const double vecteur1[n],const double vecteur2[n])
{double produit = 0.0;for (int i = 0; i < n; i++)
produit += vecteur1[i] * vecteur2[i];return produit;
}
Particularités
La taille du tableau ne peut être connue de la fonction que si on la passe en paramètre
Avec ce mécanisme VLA, le paramètre entier indiquant la taille doit précéder le paramètre-tableau
Si cette taille n’a pas besoin d’être connue par la fonction (par exemple chaîne de caractère avec une
marque de fin), on peut ne pas la spécifier dans les paramètres (char[] texte)
Informatique 1 ©É. Taillard, 2018 192
Passage de tableaux en paramètres bPour les tableaux à plusieurs dimensions, seul la taille du premier indice peut ne pas être spécifiée
Sinon, le compilateur ne peut pas savoir à quel élément il faut accéder en mémoire
Les paramètres-tableaux ne sont pas copiés dans la fonction, seule leur adresse l’est
Les composantes du tableau d’origine peut alors être modifié à l’intérieur de la fonction si on ne
l’empêche pas par le qualificatif const
Il est donc possible de passer des tableaux directement par adresse :
double produit_scalaire(int n, const double *vecteur1, const double *vecteur2)
Dans cet exemple, on peut modifier la copie de la valeur passée en premier paramètre (n)
On ne peut pas modifier les composantes des autres paramètres (on modifierait les
valeurs originales des entrées de vecteur1 ou vecteur2)
Une fonction ne peut pas retourner un tableau (une collection de valeurs)
Elle peut en revanche retourner un pointeur vers le début d’un tableau
Informatique 1 ©É. Taillard, 2018 193
Exercice VI.10 Plus grand entier d’un tableau
Écrire une fonction acceptant un tableau d’entiers comme paramètre, et retournant comme résultat
l’entier le plus grand du tableau.
Exercice VI.11 Recherche d’un élément dans un tableau
Écrire une fonction qui reçoit une valeur et un tableau d’entiers en paramètre et qui retourne la
position de la première occurrence de cette valeur, ou –1 si elle ne figure pas dans le tableau.
Exercice VI.12 Résolution d’un système d’équations
Écrire une fonction permettant de résoudre un système de 2 équations linéaires à 2 inconnues:
a11 x1 + a12 x2 = b1
a21 x1 + a22 x2 = b2
La fonction doit prendre en paramètres : la matrice A (2x2), le vecteur b et le vecteur x.
Elle doit retourner une indication sur le nombre de solutions du système.
Informatique 1 ©É. Taillard, 2018 194
Récursivité c
Une fonction peut s’appeler elle-même : on parle de récursion
unsigned binomiale(unsigned n, unsigned k){ if (n == k || n == 0 || k == 0) return 1; else return binomiale(n-1,k) + binomiale(n-1,k-1);}
Attention :
Il faut briser la récursion à un moment donné
Vérifier que la récursion n’engendre pas une explosion combinatoire inutile, ce qui est
malheureusement le cas pour la fonction ci-dessus : tant qu’on ne tombe pas dans un cas d’arrêt de
récursion, 1 appel à la fonction en engendre 2 nouveaux
Informatique 1 ©É. Taillard, 2018 195
Exemple de procédure récursive c
Impression d’un nombre dans n’importe quelle base valide
Analyse :
Il faut imprimer les chiffres de poids fort en premier, précédés du signe – si nécessaire
Si le nombre ne se réduit pas à un seul « chiffre », il faut :
Imprimer tous les premiers chiffres, puis
Imprimer le dernier chiffre
Pour transformer un chiffre en un caractère valide :
Si le chiffre ne dépasse pas 10
on utilisera les caractères ’0’ à base – 1
Sinon
on utilisera les caractères ’A’, ’B’, …
Informatique 1 ©É. Taillard, 2018 196
Impression d’un nombre dans une base donnée c
void imprimer(const int n, const int base){ if (base < 2 || base > 36) { puts("Impossible d’ecrire "); imprimer(n, 10); puts(" en base "); imprimer(base, 10); return; }
if (n < 0) { putchar('-'); imprimer(-n, base); } else { if (n >= base) imprimer(n/base, base); if (n%base >= 10) putchar(n%base - 10 + 'A'); else putchar(n%base + '0'); }}
Informatique 1 ©É. Taillard, 2018 197
Exercice VI.13 Sous-programmes
Pour chacun des sous-programmes ci-après, expliquer :
a) Dans le cas où il n'est pas correct, la nature de l'erreur
b) Dans le cas où il est correct, indiquer le ou les effet(s) du sous-programme et expliquer les
situations particulières
void sp1(int i){ printf("Le carre de %d vaut %d\n", i, i*i);}
void sp2(int i){ printf("Le carre de %d vaut %d\n", i, i= i*i);}
sp3(int i){ return i*i;}
int sp4(double i){ return i*i;}
int sp5(int *i)
Informatique 1 ©É. Taillard, 2018 198
{ return i = i*i;}
int sp6(int *i){ return *i = *i**i;}
int sp7(int *i){ return i = 2;}
int sp8(int I){ return i*i;}
double sp9(double i){ return i*i;}
Informatique 1 ©É. Taillard, 2018 199
Exercice VI.14 Appels de sous-programmes
Avec les déclarations:
int i;double d;
et définitions des sous-programmes de l’exercice qui précède, indiquer si les appels des suivant sont
corrects ou non; justifier les situations un peu particulières.
sp1(i);sp1(&i);sp1(d);sp2(3);sp2(i + 2);d = sp9(i + 2);i = sp9(i + 2);sp8(i + 2);i = sp6(&i);i = sp6(&i + 1);i = sp6(1);
Exercice VI.15 Affichage en binaire
Écrire une procédure qui reçoit un nombre entier en paramètre et qui affiche sa représentation
binaire à l’écran.
Informatique 1 ©É. Taillard, 2018 200
Exercice VI.16 Calcul du sinus
Écrire une fonction retournant la valeur du sinus, en utilisant son développement en série :
Comparer les valeurs et le temps de calcul de cette fonction avec celle fournie par math.h
Exercice VI.17 Rendu de monnaie
On considère le cas d'une caisse automatique de parking qui délivre des billets au prix unique de CHF
0.50. Cette caisse dispose d'un certain nombre de pièces de 10 et 20 centimes pour rendre la
monnaie.
On connaît la somme introduite par l'usager, qui est comprise entre 0.50 et 1 CHF.
Écrire une fonction qui affiche comment rendre la monnaie, en tenant compte du nombre de pièces
de 10 et 20 centimes restant. Le nombre de pièces à disposition ainsi que la somme introduite (en
centimes) sont passés en paramètres d’une fonction.
La fonction retourne le solde dû à l’usager (qui est nul s’il y a suffisamment de pièces disponibles dans
la caisse automatique).
xsin 1–( )i x
2i 1+
2i 1+( )!---------------------⋅
i 0=
∞
∑=
Informatique 1 ©É. Taillard, 2018 201
Exercice VI.18 Compréhension du passage par adresse
Dire ce qu’imprime le programme ci-dessous.
#include <stdio.h> int test(int a, int *b, int *c, int *d){ a = *b; *b = *b + 5; *c = a + 2; d = c; return *d; }int main(){ int a = 0, b = 100, c = 200, d = 300, e = 400; e = test(a, &b, &c, &d); printf("a:%d, b:%d, c:%d, d:%d, e:%d\n", a, b, c, d, e); return 0;}
Exercice VI.19 Comptabilité
Une association comportant n personnes veut présenter de manière claire sa comptabilité annuelle.
Elle a rempli un tableau avec des valeurs (fij) indiquant les frais de la personne j pour le mois i.
Écrire une procédure permettant d’afficher sa comptabilité. Cette procédure prend en paramètre le
tableau des frais de chaque personne ainsi que la liste des noms des personnes.
L’affichage doit se faire comme suit :
Informatique 1 ©É. Taillard, 2018 202
— Dans la première colonne, on aura le nom de chaque mois
— La dernière colonne devra indiquer le total des frais du mois
— Dans la première ligne, on mettra le nom des personnes, ainsi que le titre « Total »
— Les 12 lignes suivantes indiqueront pour chaque mois les dépenses de chaque personne ainsi
que le total du mois
— La dernière ligne devra indiquer le total des dépenses annuelles de chaque personne ainsi que
le total de toutes les dépenses de l’association.
Informatique 1 ©É. Taillard, 2018 203
Exercice VI.20 Analyse de code
Qu’imprime le programme suivant :
#include <stdio.h>int n = 5;void afficher(int p);
int main(){
int n = 3;afficher(n);return 0;
} void afficher(int p){
printf("%d, %d\n", n, p);}
Exercice VI.21 Nombre d’appels d’une fonction
Écrire une fonction qui imprime le nombre de fois qu’elle a été appelée, uniquement lorsque ce
nombre est une puissance de 10.
Exercice VI.22 Tri de 3 valeurs
Écrire une fonction qui reçoit 3 valeurs réelles en paramètres et qui les trie par ordre croissant.
Informatique 1 ©É. Taillard, 2018 204
Exercice VI.23 Intersection de segments de droite
Écrire une fonction qui reçoit en paramètre les coordonnées (entières) des extrémités de 2 segments
de droite et qui indique si ces segments ont une intersection commune.
Exercice VI.24 Simulation d’un jeu
Dans un premier temps, écrire une fonction permettant de trouver un nombre choisi par l’utilisateur.
Ce nombre doit être compris entre deux bornes fournies en paramètre à la fonction. L’utilisateur ne
fournit pas ce nombre, mais répond respectivement ’<’, ’>’ ou ’=’ à une valeur proposée par la
fonction, si cette dernière est respectivement plus petite, plus grande ou égale au nombre choisi par
l’utilisateur. La fonction retourne le nombre d’essais qu’il lui a fallu pour trouver le nombre.
Dans un second temps, faire jouer l’ordinateur contre lui-même et donner des statistiques sur le
nombre d’essais nécessaires à la fonction pour trouver le nombre. Essayer de trouver une stratégie
permettant de deviner le nombre avec le moins d’essais possible.
La bibliothèque stdlib.h met à disposition une fonction rand(), retournant un entier pseudo-
aléatoire compris entre 0 et RAND_MAX.
Informatique 1 ©É. Taillard, 2018 205
Exercice VI.25 Analyse de fonction
Que réalise la fonction ci-dessous, si elle s’arrête ?
double f(double x) {double f_courant = x, f_avant = 0.0; while (f_avant != f_courant) {f_avant = f_courant; f_courant = 0.5*(x/f_courant + f_courant); } return f_approche;}
Exercice VI.26 Calcul de la valeur d’un polynôme
Écrire une fonction retournant la valeur en x du polynôme a0 + a1x + … + anxn de degré n spécifié
par ses coefficients a0, …, an
Informatique 1 ©É. Taillard, 2018 206
VII.
POINTEURS
CHAÎNES DE CARACTÈRES
Informatique 1 ©É. Taillard, 2018 207
POINTEURS
Déjà utilisés informellement :
int n;scanf("%d", &n);
La fonction scanf, comme toute fonction en C, fait une copie de la valeur de ses paramètres
avant de s’exécuter
Les paramètres ne peuvent donc pas être directement modifiés
Astuce :
On transmet l’adresse de la variable n à scanf à l’aide de l’opérateur & « adresse de »
scanf fait une copie locale de cette adresse et l’utilise pour aller placer en mémoire, à l’adresse de n,
la valeur lue au clavier
La variable n contient maintenant la valeur lue
Informatique 1 ©É. Taillard, 2018 208
Pointeur cDéfinition
Un pointeur est une variable qui contient l’adresse d’une autre donnée
Quelle que soit le type de cette autre donnée, l’adresse a une taille identique, dépendant du
système d’exploitation
Opérateur & (adresse de)
Permet d’extraire l’adresse d’une variable
Opérateur * (indirection, déréférencement, valeur de)
Permet d’accéder à la donnée contenue à une certaine adresse
Déclaration
int *pt_1, *pt_2;int a, b;a = 12; b = 5;
Ne pas confondre l’adresse d’un objet avec l’objet lui-même !
12a
5b
pt_1
pt_2
indéfini
indéfini
Informatique 1 ©É. Taillard, 2018 209
Manipulation avec des pointeurs cpt_1 = &a; pt_2 = &b;
*pt_1 = *pt_2; // équivalent à a = b;
*pt_1 = 8;pt_1 = pt_2;
12a
5b
pt_1
pt_2
5a
5b
pt_1
pt_2
8a
5b
pt_1
pt_2
Informatique 1 ©É. Taillard, 2018 210
Déclaration de pointeur c
Comme pour une variable du type que l’on veut pointer, mais en la faisant précéder de *
double *pt_vers_double;
Mnémotechnique
*pt_vers_double est une valeur de type double
Exemples de déclarations
int *pt_i, i; // un pointeur vers un entier et une variable entière
char **pt_chaine_caracteres; // un pointeur vers un pointeur de char
Déclaration d’une variable de type pointeur
nom_type *nom_variable;
c AL ’\0’pt_chaine_caracteres
Informatique 1 ©É. Taillard, 2018 211
Danger des pointeurs c
Un pointeur contient n’importe quelle adresse, y compris celle
d’un objet que vous ne voulez absolument pas modifier
d’un objet d’un autre type
d’une portion de code de votre programme
d’une portion de code d’un autre programme chargé
d’une portion de code du système d’exploitation
d’une zone mémoire inexistante
d’une zone de la ROM
En oubliant un opérateur &, on a vite fait d’obtenir un pointeur contenant une telle adresse
a = 0; pt_a = a; // au lieu de pt_a = &a;
pt_a pointe maintenant vers l’adresse 0, typiquement invalide
Informatique 1 ©É. Taillard, 2018 212
Effets d’erreurs avec des pointeurs c
Tout à l’air de fonctionner car, par chance, on pointe vers une portion de la mémoire valide et
momentanément inutilisée
Le système d’exploitation intercepte un accès ou une instruction invalide et stoppe le programme
Le programme, ou un autre programme (par exemple le système d’exploitation) commence à avoir
un comportement bizarre
Informatique 1 ©É. Taillard, 2018 213
Pointeurs et tableaux cUn tableau est un pointeur constant vers le premier élément du tableau
Par conséquent, les trois affectations de texte sont valides et ont exactement le même effet
char debut[7] = "DEBUT";char fin[7];char *texte;
texte = debut;texte = &debut[0];texte = (char *)&debut;
À noter que &debut est un pointeur constant vers un objet contenant 7 caractères ; il est donc d’un
type différent de celui de texte qui est un pointeur vers un seul caractère, d’où la conversion
explicite (char *)
debut et fin ne peuvent pas être utilisés exactement comme des pointeurs ou des variables
debut = fin; // Invalide !debut = texte; // Invalide !
'D''E''B''U''T' 0 ?debut
texte
A380 A381 A382 A383 A384 A385 A386
A380
fin A388
Informatique 1 ©É. Taillard, 2018 214
Arithmétique sur les pointeurs cPar définition, si pt_a pointe vers un élément particulier d’un tableau, alors pt_a + 1
pointe vers l’élément suivant de ce tableau
Si on a :
int a[10];int *pt_a;int i;pt_a = a;
Alors :
*pt_a est équivalent à a[0]
pt_a + i est équivalent à &a[i]
a[i] est équivalent à *(pt_a + i)
i + pt_a est équivalent à pt_a + i
a[i] est équivalent à i[a]
a
pt_a
a[i]a[0]
pt_a + i
Informatique 1 ©É. Taillard, 2018 215
MANIPULATION DE CHAÎNES DE CARACTÈRES
La bibliothèque <string.h> met à disposition de nombreuses fonctions pour la
manipulation de chaînes de caractères
Pour illustrer le fonctionnement de quelques-unes de ces fonctions, on supposera avoir déclaré
char debut[15] = "DEB";char fin[3] = "UT";
size_t strlen(const char *);
strlen(debut) retourne le nombre de caractères de la chaîne debut, marque de fin non
comprise, c’est-à-dire 3
int strcmp(const char *, const char *);strcmp(debut, fin) compare les chaînes debut et fin et retourne 0 si elles sont identiques, un
entier négatif si debut est lexicographiquement inférieur à fin et un entier positif sinon
strcmp(debut, "DEB") retourne 0
strcmp(debut, "DE") > 0
strcmp(fin, "UTILE") < 0
Informatique 1 ©É. Taillard, 2018 216
MANIPULATION DE CHAÎNES DE CARACTÈRES
int strncmp(const char *, const char *, size_t);
strncmp(debut, fin, 2)Même chose que strcmp, mais ne compare au plus que les 2 premiers caractères de chaque chaîne
char *strcat(char *, const char *);
strcat(debut, fin) concatène la chaîne fin à la fin de la chaîne debut ; après sont appel, printf(debut) affichera donc DEBUT ; retourne un pointeur vers le début de debutAttention : Le tableau donné en premier paramètre doit être suffisamment grand !
char *strcpy(char *, const char *);texte = strcpy(debut, fin) recopie la chaîne contenue dans fin dans la chaîne debut,
marque de fin comprise et retourne dans texte un pointeur vers debut
char *strncpy(char *, const char *, int);Même chose que strcpy, mais seulement pour les premiers caractères ; si la chaîne à copier est plus
petite que le paramètre entier, complète avec des ’\0’
strcpy(debut, "commencement");strncpy(debut, "debut", 8);Après ceci, debut contiendra "debut\0\0\0ment\0…"
Informatique 1 ©É. Taillard, 2018 217
MANIPULATION DE CHAÎNES DE CARACTÈRES
char *strstr(char *, const char *);
strstr(debut, "en") Retourne un pointeur vers la première occurence (NULL si non trouvée) de
"en" dans debut
char *strchr(char *, int c);strchr(debut, ’w’) Retourne un pointeur vers la première occurence (NULL si non trouvée) de
’w’ dans debut
char *strrchr(char *, int c);Même chose que ci-dessus, mais pour la dernière occurrence
etc.
À noter
Le dimensionnement des tableaux debut et fin doit être approprié, car ces fonctions ne peuvent
procéder à aucune vérification sur leur taille
Informatique 1 ©É. Taillard, 2018 218
Exercice VII.1 Majuscules
Écrire une fonction qui reçoit en paramètre une chaîne de caractères, et qui transforme les
minuscules en majuscules dans cette chaîne.
Exercice VII.2 Recherche d'un séparateur
Écrire une fonction qui reçoit en paramètres 2 chaînes de caractères :
la première est une chaîne dans laquelle on doit rechercher un séparateur.
la deuxième est une chaîne contenant un ou plusieurs caractères, correspondant aux séparateurs à
rechercher.
Cette fonction doit retourner un entier correspondant à la position du premier séparateur trouvé dans
la première chaîne, ou –1 si non trouvé.
Exercice VII.3 Recherche de la position d'une sous chaîne dans un texte
Écrire une fonction recherchant la position d'une sous-chaîne dans une chaîne de caractères. La
chaîne principale et la sous-chaîne à rechercher sont passées en paramètres. En cas de succès, la
fonction retourne la position du premier caractère de la sous-chaîne dans la chaîne principale. Elle
renvoie –1 si non trouvé.
Lorsque la sous-chaîne passée en paramètres est plus longue que la chaîne principale, renvoyer –1.
Informatique 1 ©É. Taillard, 2018 219
Exercice VII.4 Remplacement dans un texte
En utilisant les fonctions de la bibliothèque string.h, écrire une fonction qui reçoit en paramètre un
texte, un mot à remplacer et un texte de remplacement, et qui place dans un tableau de caractères
également reçu en paramètres le texte après remplacement.
Informatique 1 ©É. Taillard, 2018 220
Exercice VII.5 Analyse de code
Qu’imprime le programme suivant :
#include <stdio.h>#include <stdlib.h>#include <string.h>
#define NBR_MOT 5#define TAILLE_MOTS 20
int modifier(char str[][TAILLE_MOTS], int *tab, int *i, int j, int *k){
strcpy(&str[0][0], "Bonjour");str[1][4] = 'e';str[1][5] = 's';str[4][0] = '!';str[4][1] = '\0';strcat(str[2], "s");strcpy(&str[3][1], "amies");tab[4] = ++j;j = *i * *i;i = k;tab[1] = *i;tab[2] = *i + *k;return j;
}
Informatique 1 ©É. Taillard, 2018 221
int main(){
char str[NBR_MOT][TAILLE_MOTS] = { "Hello", "tout", "le", "monde" };int tab[5] = {1, 2, 3};int i = 10, j = 20, k = 30, result;
result = modifier(str, tab, &i, j, &k);printf("1) %d \n", tab[1]);printf("2) %d \n", tab[2]);printf("3) %d \n", tab[4]);printf("4) %d \n", i);printf("5) %d \n", result);printf("6) %s \n", str[0]);printf("7) %s \n", str[1]);printf("8) %s \n", str[2]);printf("9) %s \n", str[3]);printf("10) %c \n", str[4][0]);return EXIT_SUCCESS;
}
Informatique 1 ©É. Taillard, 2018 222
VIII.
ENTRÉES-SORTIES STANDARD
Informatique 1 ©É. Taillard, 2018 223
Entrées-sorties standards aLorsqu’on met dans un programme :
#include <stdio.h>
Le fichier stdio.h contient entre autres les fonctions :
int getchar(void)int putchar(int)int puts(char *)int printf(char *format, …)int scanf(char *format, …)
getchar()
Retourne le code (entier entre 0 et UCHAR_MAX) du prochain caractère lu au clavier (ou dans
un fichier, si on utilise l’exécutable dans une ligne de commande avec redirection < des
entrées à partir d’un fichier) ou retourne EOF (–1) en cas d’erreur
À noter que le code n’est pas forcément celui de l’ASCII
putchar(code_de_c)
Imprime le caractère de code code_de_c à l’écran
(ou dans un fichier, si on redirige les sortie avec > en ligne de commande)
Retourne 1 si tout c’est bien passé, 0 sinon
Informatique 1 ©É. Taillard, 2018 224
Sortie formatée : printf a
printf convertit, formate et imprime ses arguments sur la sortie standard (l’écran,
si non spécifié autrement) ;
Retourne le nombre de caractères imprimés
Synopsis
printf ("Chaine controle", liste_de_valeurs);
Chaine controle : est une chaîne de caractères représentant le texte que l'on veut afficher
À l'intérieur, aux endroits désirés dans le texte, on ajoute des descripteurs de format, débutant par le
caractère %, pour l’affichage de chacun des paramètres de la liste_de_valeurs
liste_de_valeurs : 0, 1 ou plusieurs paramètres (expressions) dont on désire afficher les valeurs.
Exemple d’impression avec liste d’argument vide
printf("Bonjour’\’"); // ou mieux: puts("Bonjour");
Informatique 1 ©É. Taillard, 2018 225
Format simples aAfficher un entier int
Descripteur : %d
int nombre_personnes = 25;printf ("%d\n", nombre_personnes); // affiche 25printf ("Il y a %d personnes\n", nombre_personnes); // affiche Il y a 25 personnes
Afficher un nombre réel double
Descripteur : %f
double temperature = 25.3;printf ("Il fait %f degres\n", temperature); // affiche : Il fait 25.300000 degres
Afficher un caractère char
Descripteur : %c
char unite = ’F’;printf ("Il y a %d personnes\nIl fait %f degres %c\n", nombre_personnes, temperature, unite); // affiche : Il y a 25 personnes // Il fait 25.300000 degres F
Informatique 1 ©É. Taillard, 2018 226
Descripteurs des formats de base pour printf b
%d Pour un int (en base 10)
%i Idem à %d
%c Pour un caractère donné par son code de type int
%f Pour un double, par défaut, 6 chiffres significatifs
%e Pour un double en notation scientifique
%E Idem à %e mais avec un E pour la puissance de 10
%g Choix automatique entre %f et %e
%G Choix automatique entre %F et %E
%s Pour une chaîne de caractères (terminée par 0)
%u Pour un unsigned int
%o Pour un int affiché en octal
%x Pour un int affichée en hexadécimal
%X Idem à %x mais avec des lettres majuscules
%p Pour une adresse
%% Pour afficher le caractère % lui-même
Informatique 1 ©É. Taillard, 2018 227
Exercice VIII.1 Comptage de caractères
Écrire un programme qui lit une ligne de texte caractère par caractère et qui affiche le nombre de
caractères saisis.
Exercice VIII.2 Test de saisie correcte
Écrire un programme déclarant des variables réelles x y et z, permettant de saisir leur valeur en une
seule instruction, et vérifiant que les 3 valeurs ont bien été assignées. Dans le cas contraire, afficher
un message du type « données invalides ».
Exercice VIII.3 Saisie d’un nombre avec vérification
Écrire un programme qui demande la saisie d’un nombre entier avec vérification: si l’utilisateur
introduit quelque chose d’autre, un message d’erreur le signale avant de redemander une nouvelle
saisie à l’utilisateur. Entre 2 saisies, tout ce que l’utilisateur avait pu introduire précédemment doit
être supprimé.
Informatique 1 ©É. Taillard, 2018 228
DESCRIPTEURS D’AUTRES FORMATS PRINTF
On peut faire précéder d, i, u, o, x, X d’un
l pour afficher des entiers de type long
ll pour long long
h pour short
hh pour char (affichage du code numérique et non du caractère)
On peut faire précéder f, e, E, g, G d’un
L pour afficher des réels de type long double
Il doit y avoir le même nombre de descriptions de formats dans la chaîne de contrôle qu'il y a
d'éléments dans la liste de valeurs
Ils doivent se correspondre en types, ou tout au moins en types compatibles
Informatique 1 ©É. Taillard, 2018 229
GABARIT
Juste après le %, on peut mettre, dans l’ordre :
– Pour aligner à gauche (par défaut, l’alignement est à droite)
+ Pour toujours afficher le signe des nombres
Un nombre w
Spécifiant qu’il faut utiliser au minimum w caractères pour l’affichage de l’argument, au besoin en
ajoutant des espaces (à gauche ou à droite selon le choix d’alignement)
Ce nombre peut être remplacé par *, qui doit alors être donné dans la liste des paramètres
Un point .
Séparant la spécification de la largeur de la précision
Un nombre p
Pour une chaîne de caractères : Nombre maximum p de caractères à imprimer (troncation si
nécessaire, puis rajout d’espaces si w > p)
Pour un nombre en virgule flottante : le nombre de chiffres après la virgule
Pour un entier le nombre minimum de chiffres à afficher (ajout de 0 à gauche, si nécessaire).
Informatique 1 ©É. Taillard, 2018 230
EXEMPLES D’UTILISATION DE PRINTF (CASSAGNE)
printf("|%d|",1234); |1234|printf("|%d|",-1234); |-1234|printf("|%+d|",1234); |+1234|printf("|%+d|",-1234); |-1234|printf("|% d|",1234); | 1234|printf("|% d|",-1234); |-1234|printf("|%x|",0x56ab); |56ab|printf("|%X|",0x56ab); |56AB|printf("|%#x|",0x56ab); |0x56ab|printf("|%#X|",0x56ab); |0X56AB|printf("|%o|",1234); |2322|printf("|%#o|",1234); |02322|printf("|%10d|",1234); | 1234|printf("|%10.6d|",1234); | 001234|printf("|%.6d|",1234); |001234|printf("|%*.6d|",10,1234); | 001234|printf("|%*.*d|",10,6,1234); | 001234|printf("|%f|",1.2345678901234567e5); |123456.789012|printf("|%.4f|",1.23456789012345e5); |123456.7890|printf("|%.20f|",1.234567890123456789e5); |123456.78901234567456413060|printf("|%20.4f|",1.234567890123e5); | 123456.7890|printf("|%e|",1.234567890123456e5); |1.234568e+05|printf("|%.4e|",1.2345678901234e5); |1.2346e+05|printf("|%.20e|",1.234567890123456789e5); |1.23456789012345674564e+05|printf("|%20.4e|",1.23456789012e5); | 1.2346e+05|printf("|%.4g|",1.2345678901234e-5); |1.235e-05|printf("|%.4g|",1.2345678901234e5); |1.235e+05|printf("|%.4g|",1.234567890123e-3); |0.001235|printf("|%.8g|",1.234567890123e5); |123456.79|
Informatique 1 ©É. Taillard, 2018 231
Lecture avec format : scanf aLa fonction scanf permet de lire des caractères introduits par l’utilisateur
La suite de caractère introduite est ensuite interprétée selon les directives de formats
Finalement la valeur obtenue est placée dans la variable spécifiée
Le principe est à peu près le même que pour printf, mais :
Il faut mémoriser le résultat de la lecture, donc le mettre dans une variable
Dû à une particularité du langage C (pas de passage par référence) on doit spécifier l’adresse
de la variable (faire précéder l’identificateur de la variable de &)
On peut lire plusieurs données introduites sur la même ligne, séparées par des blancs
Les directives de format de base sont :
%d pour les entiers int
%lf pour les réels double
%c pour les caractères char
Exemple
int nombre_personnes;double temperature;char unite;printf("Nbre de personnes, temperature et unite? "); scanf("%d%lf%c", &nombre_personnes, &temperature, &unite);
Informatique 1 ©É. Taillard, 2018 232
Lecture avec format : scanf b
scanf
Lit des caractères depuis l’entrée standard (le clavier si non spécifié autrement, par exemple
par une redirection < en ligne de commande)
Interprète ces caractères selon les formats spécifiés et enregistre le résultat en mémoire aux
adresses spécifiées dans la liste des pointeurs
Retourne le nombre d’objets convertis ou EOF si la fin du fichier ou une erreur est survenue
Synopsis
scanf ("Chaine controle", liste_de_pointeurs);
Chaine controle : Contient des descripteurs de formats analogues (mais attention ! différents)
de ceux de printf
liste_de_pointeur : généralement des identificateurs de variables, précédés de l’opérateur
d’adressage & (si les variables ne sont pas déjà des pointeurs)
Informatique 1 ©É. Taillard, 2018 233
Comportement de scanf b
Mange les caractères « blanc » (espace, tabulateur, retour de chariot, fin de ligne, tabulateur vertical,
saut de page), également pour le format %s, mais pas si on veut lire un unique caractère (format %c)
La conversion s’arrête au prochain blanc ou au prochain caractère ne correspondant pas au format
Si la chaîne comporte autre chose que des descripteurs de formats, ces caractères sont explicitement
attendus (à l’exception des caractères blancs)
Si l’entrée ne correspond pas au descriptif de la chaîne de contrôle, scanf s’arrête
Si après % on trouve le caractère *, cela signifie que la valeur suivante en entrée (en fonction du
format spécifié) doit être ignorée (sautée)
Si après % on trouve un nombre, ce dernier spécifie le nombre maximum de caractères consommés
avant conversion (par exemple %1s revient à lire le prochain caractère non blanc)
Informatique 1 ©É. Taillard, 2018 234
Différences entre formats de printf et scanf b
N’existent pas dans scanf :
%X, %E, %F, %G
Ont une signification différente dans scanf
%i int en octal (précédé de 0)
ou hexadécimal (précédé de 0x ou 0X)
%c char (et non int)
%e, %f, %g float (et non double)
N’existent pas dans printf
%le, %lf, %lg double
Informatique 1 ©É. Taillard, 2018 235
SAUT DE CERTAINS CARACTÈRES
%[c1c2c3…] chaîne de caractères ne contenant que les
caractères appartenant à l’ensemble c1c2c3…
c1 peut être le caractère ] mais pas ^
%[^c1c2c3…] chaîne de caractères ne contenant aucun des
caractères de l’ensemble c1c2c3…
seul c1 peut être le caractère ]
Exemples :
Lire une ligne d’au maximum 1000 caractères
char ligne[1000]; /*Chaîne de 1000 caractères*/scanf("%1000[^\n]", ligne);
Vider le tampon d’entrée
scanf("%*[^\n]%*[\n]");
ou, plus simplement:
while (getchar() != ’\n’) {}
Informatique 1 ©É. Taillard, 2018 236
Exercice VIII.4 Facture
Écrire un programme permettant d'éditer une facture. Ce programme doit effectuer la saisie d’une
quantité et d'un prix hors taxe. Il doit ensuite calculer le prix hors taxe total, puis le prix TTC total
(TVA = 7.5 %), et afficher les résultats sous la forme suivante :
QUANTITE: 10PRIX HT : 20.00 CHFTOTAL HT: 200.00 CHFTVA: 15.20 CHFTOTAL TTC: 215.20 CHF
Exercice VIII.5 Impressions erronées
Indiquer les erreurs que comportent les instructions ci-dessous.
printf("%d%d\n", 10, 20);printf("%d, %d, %d\n", 10, 20);printf("%d, %d, %d, %d\n", 10, 20, 30, 40.);printf("%*d, %*d\n", 10, 20);printf("%6.2f\n", 10);printf("%10s\n", 0x9f);
Informatique 1 ©É. Taillard, 2018 237
Exercice VIII.6 Chaînes de formatage
Pour les instructions ci dessous, indiquer quel est l'affichage obtenu. Mettre en évidence les espaces.
char a = 'a';short sh1 = 5;double f1 = 7.0;int i1 = 7, i2 = 'a'; 1) printf("Caractère suivant:%c.\n", a + 1); 2) printf("Caractère:%3c.\n", a); 3) printf("Caractère:%-3c.\n", a); 4) printf("Caractères:\n-%c.\n-%c.\n", a, 'z' - 1); 5) printf("Somme:%i\n", i1 + i2 - a); 6) printf("Taux d'erreur\t%i %%\n", i1); 7) printf("Quel charabia horrible:\\\a\a\a%g\b\a%%\a\\\n", f1); 8) printf("Inventaire:%i4 pieces\n", i1); 9) printf("Inventaire:%i %s\n", i1, "pieces");10) printf("Inventaire:%4i pieces\n", i1);11) printf("Inventaire:%-4i pieces\n", i1);12) printf("Somme mixte:%f\n", sh1 + i1 + f1);13) printf("Tension:%5.2f mV\n", f1);14) printf("Tension:%5.2e mV\n", f1);15) printf("Code:%X\n", 12);16) printf("Code:%x\n", 12);17) printf("Code:%o\n", 12);18) printf("Valeur:%i\n", -1);19) printf("Valeur:%hi\n", 65535u);20) printf("Valeur:%hu\n", -1);
Informatique 1 ©É. Taillard, 2018 238
Exercice VIII.7 Affichage d’un tableau à 2 dimensions
Soit un tableau A d’entiers à m lignes et n colonnes. Donner un code permettant d’écrire A en
numérotant les lignes et les colonnes, comme donné en exemple ci-dessous pour un tableau 3 x 4.
| 1 2 3 4-|-----------------------1| 23 456 7 982| 987 54 87654 13| 2 6 9 4
Exercice VIII.8 Saisies de valeur
On considère les déclarations suivantes.
int i = 0, j = 0, n = 0;double x = 0;
Indiquer la valeur des variables après l'exécution des instructions scanf suivantes, après que
l'utilisateur ait tapé la chaîne d'entrée mentionnée (on suppose que les variables sont remises à 0
avant chaque scanf).
Instruction Chaîne entrée par l’utilisateur
n = scanf("%1d%1d", &i, &j);12
n = scanf("%d%d", &i, &j); 1 , 2
n = scanf("%d%d", &i, &j); -1 -2
Informatique 1 ©É. Taillard, 2018 239
n = scanf("%d%d", &i, &j); - 1 - 2
n = scanf("%d,%d", &i, &j); 1 , 2
n = scanf("%d ,%d", &i, &j); 1, 2
n = scanf("%4d %2d", &i, &j); 1 234
n = scanf("%4d %2d", &i, &j); 1234567
n = scanf("%d%*d%d", &i, &j); 123 456 789
n = scanf("i=%d , j=%d", &i, &j); 1 , 2
n = scanf("i=%d , j=%d", &i, &j); i=1 , j=2
n = scanf("%d%d", &i, &j); 1.23 4.56
n = scanf("%d.%d", &i, &j); 1.23 4.56
n = scanf("%x%x", &i, &j); 12 2a
n = scanf("%x%x", &i, &j); 0x12 0X2a
n = scanf("%o%o", &i, &j); 12 018
n = scanf("%lf", &x); 123
n = scanf("%lf", &x); 1.23
Informatique 1 ©É. Taillard, 2018 240
n = scanf("%lf", &x); 123E4
n = scanf("%le", &x); 12
Exercice VIII.9 Spécification de formats d’entrée
Ecrire les instructions permettant de :
1) Saisir 3 caractères consécutifs dans des variables c1 c2 et c3.
2) Saisir 3 nombres de type float séparés par un point-virgule et un nombre quelconque d'espaces
dans des variables x y et z.
3) Saisir 3 nombres de type double dans des variables t u et v en affichant, avant chaque saisie, le
nom de la variable et un signe =
Informatique 1 ©É. Taillard, 2018 241
Exercice VIII.10 Entrées-sorties erronée
Parmi les instructions ci dessous, indiquer celles qui sont correctes et celles qui comportent des
erreurs. Pour celles comportant des erreurs, détailler la nature des anomalies.
short i;long j;unsigned short u;float x;double y;
printf(i);scanf(&i);printf("%d", &i);scanf("%d", &i);printf("%d%ld", i, j, u);scanf("%d%ld", &i, j);printf("%u", &u);scanf("%d", &u);printf("%f", x);scanf("%f", &x);printf("%f", y);scanf("%f", &y);
Informatique 1 ©É. Taillard, 2018 242
Exercice VIII.11 Produit scalaire
Écrire un programme effectuant les opérations suivantes :
— Saisir les coordonnées réelles x1 et y1 d'un vecteur v1.
— Saisir les coordonnées réelles x2 et y2 d'un vecteur v2.
— Calculer le produit scalaire. Afficher un message indiquant si les vecteurs sont orthogonaux ou non.
Ce programme risque-t-il de ne pas bien détecter l'orthogonalité de certains vecteurs ?
Si oui, comment pallier à ce problème ?
Informatique 1 ©É. Taillard, 2018 243
IX. STRUCTURES
Informatique 1 ©É. Taillard, 2018 244
GÉNÉRALITÉS SUR LES STRUCTURES
But :
Réunir sous un même nom des éléments composant un objet plus complexe
Les éléments de cet objet forment un tout, logiquement structuré
Chacun de ces éléments est appelé membre ou champ
Exemple
Les données concernant une personne comportent
nom, prénom et date de naissance
Une structure déclare un nouveau type de données
struct personne { char nom[20]; char prenom[20]; int jour; int mois; int annee;};
Pour déclarer des variables, il faut répéter le mot-clé struct
struct personne Marie, Jean, Xamax[11];
Informatique 1 ©É. Taillard, 2018 245
MANIPULATION D’UNE STRUCTURE
Pour accéder aux membres d’une variable de type structure
Opérateur .
Marie.jour = 13;Marie.mois = 4;Marie.annee = 5;strcpy(Marie.nom, "Magdalena");strcpy(Marie.prenom, "Marie-Madeleine");
strcpy(Xamax[7].nom, "Lang");
Affectation
Comme d’habitude, mais tous les champs sont copiés (y compris les tableaux)
Jean = Marie;La taille des tableaux contenus dans une structure doit donc être connue à la compilation
Pointeurs vers une structure
struct personne *pt_jean = &Jean;
Attention, l’opérateur . est plus prioritaire que *
(*pt_jean).jour peut s’abréger pt_jean->jour
Informatique 1 ©É. Taillard, 2018 246
STRUCTURES IMBRIQUÉES
Il est possible d’imbriquer des structures les unes dans les autres
struct date {int jour;int mois;int annee;
};
struct personne {char nom[20];char prenom[20];struct date date_naissance;
};
struct personne Luc;
Luc.date_naissance.jour = 18;Luc.date_naissance.mois = 10;
Structure auto-référencée
struct liste_chainee {int element;struct liste_chainee *suivant;
};Soit le modèle type de structure suivant :
Informatique 1 ©É. Taillard, 2018 247
struct s_point{ char c ;
int x, y;} ;
Écrire une fonction qui reçoit en argument une structure de type struct s_point et qui affiche le
contenu sous la forme « point B de coordonnées 10 12 ».
a) En transmettant en argument la valeur de la structure concernée ;
b) En transmettant en argument l'adresse de la structure concernée ;
Écrire une fonction qui « met à zéro » les différents champs de cette structure, qui lui est transmise
en argument.
Écrire une fonction qui reçoit en argument l'adresse de cette structure et qui renvoie en résultat une
structure du même type correspondant à un point de même nom et de coordonnées opposées.
Écrire la déclaration d'un tableau (nommé ligne_brisee) de n points ainsi qu’une procédure
affichant les différents points d’une ligne brisée transmise en argument.
Informatique 1 ©É. Taillard, 2018 248
Exercice IX.1 Saisie des champs d’une structure
Soient les deux modèles de structure date et personne déclarés ainsi :
#define LG_NOM 30struct date{
int jour ;int mois ;int annee ;
} ;struct personne{
char nom[LG_NOM+1] ;struct date date_embauche ;struct date date_poste ;
} ;
Écrire une fonction qui reçoit en argument une structure de type personne et qui remplit les différents
champs avec un dialogue se présentant sous l'une de deux formes suivantes :
nom : DUPONTdate embauche (jj mm aa) : 22 1 1998date poste = date embauche ? (O/N) : O
nom : DUPONTdate embauche (jj mm aa) : 10 10 1994date poste = date embauche ? (O/N) : Ndate poste (jj mm aa) : 23 10 1995
Informatique 1 ©É. Taillard, 2018 249
Informatique 1 ©É. Taillard, 2018 250
ANNEXE A. MOTS RÉSERVÉS
asm auto break case char const
continue default case do double else
enum extern float for goto if
inline int long register restrict return
short signed sizeof static struct switch
typedef union unsigned void while _Bool
_Complex _Imaginary
Informatique 1 ©É. Taillard, 2018 251
Informatique 1 ©É. Taillard, 2018 252
ANNEXE B. CLASSES DE DÉCLARATION
Il est possible de faire précéder la déclaration d’une variable du mots-clé :
const
Indique au compilateur que la variable ne peut pas changer de valeur (elle doit donc recevoir une
valeur lors de sa création)
Informatique 1 ©É. Taillard, 2018 253
Autres classes de déclaration cauto
Classe de déclaration par défaut
auto int i;est équivalent à
int i;
registerPour indiquer au compilateur qu’il doit essayer de garder la variable dans un registre (mais il peut ne
rien faire)
But : tentative inutile d’optimisation de code, à oublier…
volatilePour indiquer qu’à chaque utilisation de la variable, il faut recharger sa valeur (même si elle était déjà
dans un registre du processeur)
But : gérer des informations pouvant être modifiées à l’extérieur du programme (comme par
exemple une horloge, l’état d’une touche ou de capteurs)
extern et static
Informatique 1 ©É. Taillard, 2018 254
Référence extern c
Le mot clé extern indique au compilateur que l’objet est déclaré dans un autre
module, compilé séparément.
L’objet référencé par extern peut être une fonction ou une variable globale
Dans le cas d’une variable compilateur ne réserve pas de mémoire.
C’est l’éditeur de lien qui est chargé de faire correspondre la définition de la variable (là où sa valeur
sera stockée) et sa ou ses références dans d’autres modules.
Informatique 1 ©É. Taillard, 2018 255
Spécification static c
static appliqué à une variable (locale à une instruction-bloc ou à une fonction)
implique que la variable :
A une durée de vie égale à la durée du programme
Reste invisible en dehors du bloc ou du fichier où elle est déclarée
N’est intialisée qu’une seule fois
Utilité
Permet de se passer de variables globales engendrant un style de programmation dangereux
Informatique 1 ©É. Taillard, 2018 256
Exemples d’utilisation de static c
a) Une procédure qui doit savoir combien de fois elle a été appelée
void proc(void){ static int nb_appel = 0; nb_appel++;
...}
b) Un générateur aléatoire qui doit modifier la valeur de germes
static appliqué à une variable globale ou à une fonction
Indique à l’éditeur de lien qu’il ne doit pas exporter la variable ou la fonction dans le cas de
compilation séparée
Permet donc de masquer les objets que l’on ne veut pas exporter.
Informatique 1 ©É. Taillard, 2018 257
Informatique 1 ©É. Taillard, 2018 258
ANNEXE C. LE PRÉPROCESSEUR
Permet de manipuler le fichier source avant compilation
Le préprocesseur ne fait que substituer des chaînes de caractères
Les directives au préprocesseur sont données par des lignes débutant par #
Remplacer une chaîne par une autre
#define PI 3.141
Supprimer la définition d’une définition
#undef PI /*On peut redéfinir PI plus loin*/
Inclure le contenu d’un fichier
#include <stdio.h> /* recherché dans l’environnement */#include "mon_fichier.h" /*recherché aussi dans le répertoire courant*/
Déclarer des macro-instructions avec liste de paramètres
#define MAX(a,b) ((a) > (b) ? (a) : (b)) // Peut être dangereux
Informatique 1 ©É. Taillard, 2018 259
COMPILATION CONDITIONNELLE
Usage :
Inclure des instructions de trace en cours de développement
Générer du code adapté à l'environnement
Générer des messages en fonction de la langue
#if condition_1/* partie compilée si condition_1 est vraie */...
#elif condition_2/* partie compilée si condition_1 est fausse *//* mais condition_2 est vraie */
...#else
/* Zone compilée si toutes les conditions quiprécèdent sont fausses */
...#endif
Les conditions doivent être évaluables par le compilateur (et non à l’exécution) et peuvent utiliser la
directive defined qui est vraie si un symbole est défini ainsi que les opérateurs booléen ! && ||
#if ( !defined TOTO ) && ( TRUC > 3 )#define TOTO TRUC#endif
Informatique 1 ©É. Taillard, 2018 260
ANNEXE D. PRINCIPES DE BONNE PROGRAMMATION
Buts:
Augmenter la lisibilité, la qualité et la robustesse du code
Éviter des pertes de temps lors de la programmation
KISS (Keep It Simple, Stupid ; Keep It Simple and Straightforward)
La simplicité augmente la robustesse ; éviter des complications inutiles
Commenter et aérer les programmes
Le code sera ainsi plus lisible
Éviter de trop commenter : de bons choix pour les identificateurs permettent
d’auto-commenter le code
Indiquer le nom du programmeur, la date, le but du programme, les modifications au début
Informatique 1 ©É. Taillard, 2018 261
S’en tenir à un style d’écriture unique
Suggestions :
Écrire les types et constantes en majuscule
MAXIMUM
Écrire les autres identificateurs en minuscule
borne_inf ou borneInf mais éviter la notation hongroise : arpszMotsCles
Aligner les instructions d’un même bloc
Indenter proprement et systématiquement vos structures, aligner les accolades
int main(void) int main(void) { // Autre style compact{ int i = 1;
int i = 1; do {do printf("%d\n", i);{ i = 2*i; }
printf("%d\n", i); } while (i > 0);i = 2*i; }
}while (i > 0);
}
Utiliser une fonte à chasse fixe
Indenter avec 2 ou 3 espaces ; les tabulateurs sont déconseillés
Informatique 1 ©É. Taillard, 2018 262
Choisir des identificateurs avec des noms significatifs
Commenter correctement votre code
Éviter les commentaires qui n’apportent rien ou l’absence de commentaires dans les parties délicates
int a; // !!X!! "déclaration de l’entier a" : on le sait! x = y += x+y/(4-23**z%234); // !!X!! "prochaine instruction" : Fait quoi?!
Ne pas utiliser de chiffres magiques
Déclarer des constantes symboliques à la place
Si leur valeur doit être adaptée, on ne doit modifier le code qu’à une seule place
Ne pas utiliser de variables globales
Peuvent être modifiées partout dans le programme, difficile de repérer les erreurs
Par contre, on peut abuser de constantes symboliques globales !
Ne pas optimiser le code
Exception, pour les experts uniquement : Ne pas optimiser le code !
Le compilateur optimise mieux qu’un expert
Étudier la complexité de l’algorithme
Informatique 1 ©É. Taillard, 2018 263
Éviter les fonctions et procédures trop longues
Dès qu’un bloc dépasse une page, le décomposer en procédures ou fonctions
Éviter les imbrications trop profondes
Éviter d’allouer et de désallouer la mémoire dans des modules différents
Détecter et gérer les erreurs à l’exécution
Utiliser les valeurs de retour des fonctions (scanf, malloc, fopen, …)
Sécuriser le code
while (scanf("%d%d", &n, &m) != 2) { printf("Erreur! introduire de nouveau 2 entiers\n"); while (getchar() != ’\n’) {} }
Informatique 1 ©É. Taillard, 2018 264
Le code doit respecter les normes ISO et compiler sans message d’avertissement
Le code pourra être porté sur une machine différente de celle du programmeur
et sera plus robuste.
Le compilateur donne souvent des messages d’avertissement très pertinents !
Exemple de compilation avec gcc
gcc -Wall -Wconversion -Wpedantic -std=c11 toto.c
Ne pas utiliser d’expressions dont le comportement n’est pas défini
Exemples
j = --i * i++; // !!X!! -- fait avant ou après ++ ?fflush(stdin); // !!X!! fflush prévu pour les tampons de sortie
i = -5/3; // Se méfier: pas défini par les anciens standards
La séquence de caractères /* ne doit pas être utilisée dans un commentaire
En retirant les /* et */ du premier commentaire, on peut en créer un autre
/* i = j+2; !!X!! /* partie du code à corriger j = i - 1; */ i = i + 3;/* tester si ça va mieux avec simplement i = i + 2 */
// Les commentaires de ligne n’existent pas en C90
Informatique 1 ©É. Taillard, 2018 265
Documenter explicitement les comportements dépendants de l’implantation
Exemples :
/* En-tête fichier tiff; Le nombre magique 2771273 correspond à la convention "little-endian" et représente les caractères II 42 */ uint32_t id_tiff = 2771273; /* À faire: tester si on est bien en little */
/* Aligner les structures sur chaque octet */ #pragma pack(push, 1) /* ... */ #pragma pack(pop) /* Fin de l’alignement forcé */
Documenter l’ensemble de caractères utilisés
Un programme peut être écrit avec un ensemble de caractères et s’exécuter avec un autre ensemble
Exemple :
printf("Pas de problème si on se limite à l’ISO/CEI 646 (appelé ASCII) \n");
Ne pas spécifier de constantes en octal, à l’exception de ’\0’
code[1] = 109; code[2] = 100; code[3] = 052; // !!X!! valeur décimale de 42 code[4] = '\100'; // !!X!! valeur différente de code[2] code[5] = '\109'; // !!X!! constante multi-caractères, non standard
Informatique 1 ©É. Taillard, 2018 266
Ne pas utiliser les trigraphes
printf("Donner la date (sous la forme ??-??-??)\n"); // !!X!! ??- devient ~
Ne pas utiliser des identificateurs de plus de 31 caractères
La norme ne requiert que de différencier les identificateurs sur les 31 premiers caractères
Le code risque de devenir difficile à lire
Ne pas utiliser des identificateurs qui ont le même nom dans des blocs différents ou
qui diffèrent par des caractères graphiquement proches
Risque élevé de confusion
Contre-exemples :
int variable_10, variable_1O, variab1e_10, variabIe_10; { int variable_1, variable_10; /* !!X!! une autre variable_10 */ }
Informatique 1 ©É. Taillard, 2018 267
Le nom d’un struct, union ou typedef doit être unique
{ typedef unsigned char uint8_t; } { typedef unsigned char uint8_t; /* !!X!! Redéfinition */ } { unsigned char uint8_t; /* !!X!! Réutilisation */
}
Le type char doit être utilisé uniquement pour des caractères
La norme ne spécifie pas si char est signé ou non
Utiliser signed char et unsigned char si on veut travailler avec des valeurs numériques
Utiliser des types numériques dont la taille et le signe sont connus
int8_t, uint16_t, int64_t, etc. sont définis dans <stdint.h>
Ne rien supposer sur la représentation interne des types standards
Informatique 1 ©É. Taillard, 2018 268
Les fonctions doivent avoir un prototype visible à la fois à la définition de la fonc-
tion et à son appel
Le compilateur peut ainsi vérifier la compatibilité entre la définition de la fonction et son appel
Mettre le prototype dans le fichier d’en-tête .h qui sera inclus à la fois dans le fichier de définition de
la fonction et dans le fichier où la fonction est appelée
Ne pas utiliser le type int implicite, ni un type implicite
toto(i) // !!X!! int implicites en paramètre et en sortie{ const j = 4.0; // !!X!! int implicite extern x; // !!X!! Type de x inconnu return i+j+x; // !!X!! Conversion implicite possible}
Le type de chaque paramètre d’une fonction doit être le même dans la déclaration
et dans la définition, de même que le type de l’objet retourné; les paramètres doi-
vent être nommés et avoir le même nom dans la déclaration et la définition
unsigned long f(const int k); size_t f(int j) // !!X!! pas le même type, pas le même nom{ printf("%d\n", j++);
return j;}
Informatique 1 ©É. Taillard, 2018 269
Un fichier d’en-tête ne doit pas contenir de définitions, seulement des déclarations
int f(const int k); // OK: déclarationdouble pi = 3.14159265358979323846; // !!X!! définition d’une variable
Déclarer les objets dans le bloc le plus interne possible
for (int i = 0; i < n; i++) // NB: Construction pas possible en C90…
Un objet externe doit être défini dans un et un seul fichier
Lorsqu’un identificateur n’est utilisé qu’à l’intérieur d’un fichier compilé séparé-
ment, le masquer aux autres fichiers avec static
Toute variable doit être initialisée avant d’être utilisée
Se méfier de certains environnements (ne respectant pas la norme) qui n’initialisent pas les
variables static à 0
Par contre, ne pas initialiser une variable à une valeur qui n’a rien à voir avec celle
de sa première utilisation
Informatique 1 ©É. Taillard, 2018 270
Des accolades doivent être utilisées pour indiquer la structure des initialisations à
la déclaration (sauf pour les initialisations globales à 0)
int x[3][2] = { 0 }; // OK: tout est mis à 0int y[3][2] = { 1, 2, 3, 4, 5, 6 }; // !!X!! structure non respectéeint z[3][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 } }; // OK
Faire des conversions de types explicites entre entiers signés et non signés, entre
entiers et flottants, lorsqu’on passe vers un type plus petit, pour les paramètres
effectifs de fonctions, pour les valeurs de retour ou dans les expressions complexes
Les règles de conversions sont complexes et parfois contre-intuitives
Utiliser le suffixe U pour les constantes non signées
La constante 50000 diffère dans des environnements ou int est sur 16 ou 32 bits
Ne pas faire de conversion d’un pointeur qui supprimerait la qualification const ou
volatile
Informatique 1 ©É. Taillard, 2018 271
La valeur d’une expression doit être identique quelle que soit l’ordre d’évaluation
des opérandes permis par le standard
Attention aux effets de bord
Ne se fier à l’ordre que pour les opérateurs (), &&, ||, ?: et ,
Ne pas utiliser sizeof avec une expression contenant un effet de bord
L’opérateur sizeof n’est pas une fonction, il n’y a pas de code généré pour l’expression
C’est le compilateur qui évalue la valeur (constante) du résultat
sizeof pour un tableau passé en paramètre retourne la taille d’une adresse
L’opérande droit des opérateurs && et || ne doit pas avoir d’effets de bord
Selon la valeur de l’opérande gauche, il est ou n’est pas évalué
N’utiliser les opérateurs bit-à-bit qu’avec des entiers non signés
Ces opérateurs ne sont en principe pas utiles pour les entiers signés et dépendent de
l’environnement
Informatique 1 ©É. Taillard, 2018 272
Ne pas utiliser l’opérateur monadique - à un type non signé
Éviter l’opérateur d’enchaînement
Rend le code peu lisible
Ne pas utiliser les opérateurs d’affectation dans des expressions booléennes
Pour éviter la confusion entre = et ==
Ne pas tester les flottants à l’égalité == ou à l’inégalité !=
Le résultat dépend des imprécisions numériques
L’expression de contrôle d’une boucle for ne doit pas contenir de flottants
Le nombre de répétitions peut dépendre de l’environnement
Les 3 expressions d’une boucle for doivent concerner seulement le contrôle de la
boucle
Lisibilité du code
Informatique 1 ©É. Taillard, 2018 273
La variable de contrôle d’une boucle for ne doit pas être modifiée dans le corps de
la boucle
Éviter de rendre le code abscons ; source d’erreurs
Ne pas introduire d’expressions booléennes dont le résultat est invariant
if ((char) x > 255) … // !!X!! toujours fauxif (x > 10)
if (x > 5) … // !!X!! toujours vrai
Il ne doit pas y avoir de code non atteignable ou sans effet
if ((unsigned) i < 0) i++; // !!X!! i++ jamais exécutéelse 3*i; // !!X!! code sans effet
L’utilisation de l’instruction nulle doit être mise en évidence
if (…)
{ } /* Cas spécial: ne rien faire */
else if (…)
{ … }
else
{ … }
Informatique 1 ©É. Taillard, 2018 274
Ne pas utiliser goto ni continue, inclure au plus un break dans le corps d’une boucle
Lisibilité du code ; break traite un seul cas particulier en principe
Utiliser l’instruction composée {} après while, do…while, switch, for, if, else
Évite les mauvaises indentations, notamment lors de retouche de code
Exception : construction … else if … (voir ci-dessus)
Terminer toutes les clauses non vides d’un switch avec break; terminer un switch
avec default ; un switch doit avoir au moins deux case
Fiabilité et lisibilité du code
Utiliser une structure de contrôle pour ce à quoi elle a été conçue
switch (n > 0) // !!X!! Utiliser if{ case 0 : n--; break; default : n++; break; // break : au cas où default est modifié en case}
Une fonction sans valeur de retour doit retourner le type void ; une fonction sans
paramètre doit être spécifiée par la liste void
void terminaison_programme(void) …
Informatique 1 ©É. Taillard, 2018 275
Le nombre d’arguments passés en paramètres doit correspondre au nombre de
paramètres
Utiliser le qualificatif const pour les paramètres qui sont des pointeurs non utilisés
pour modifier le contenu de l’adresse qu’ils pointent
Fiabilité du code et aide à l’interprétation sémantique
Toute fonction avec valeur de retour doit avoir un return explicite avec une expres-
sion ; le type de cette expression doit correspondre à celui déclaré
L’identificateur d’une fonction doit être suivi de () ou précédé de &
x = f; est identique à x = &f si x est un pointeur vers une fonction; pas d’appel à f()
Si une fonction retourne une information précisant une erreur, cette information
doit être testée
Exemples : fopen, fclose, …
Informatique 1 ©É. Taillard, 2018 276
L’arithmétique sur les pointeurs ne doit être utilisée que sur les éléments d’un
tableau
Une autre utilisation serait peu claire et/ou dépendante de l’environnement
Ne pas affecter l’adresse d’un objet à un autre qui pourrait continuer à exister
après que le premier ait cessé d’exister
int* f(int n){ return &n; } // !!X!! n est local à f et cesse d’exister après son appel
Deux objets ne doivent pas se superposer en mémoire
Un espace mémoire ne doit pas être réutilisé pour stocker des données qui n’ont
pas de lien entre elles
Même s’il est tentant de s’épargner une redéclaration pour une place mémoire plus utilisée
Regrouper tous les #include en début de fichier
Pour appréhender l’environnement complet dont on a besoin
Informatique 1 ©É. Taillard, 2018 277
Ne pas utiliser de caractères non standards dans les noms de fichiers
Certains environnements gèrent mal ou différemment ces caractères
Utiliser une fonction plutôt qu’une macro
Source de problèmes, le code sera plus robuste ; le compilateur se charge des optimisations
Éviter l’inclusion multiple d’un en-tête
#ifndef XXX /* Standard */
#define XXX
…
#endif
#pragma once /* Plus simple, mais non standard */
#else, #elif et #endif doivent figurer dans le même fichier que le #if ou #ifdef
dont ils dépendent
Sinon, le programmeur risque de ne plus rien comprendre
Informatique 1 ©É. Taillard, 2018 278
Ne pas (re)définir des identificateurs réservés, des macros et fonctions des biblio-
thèques standards ou utiliser ces noms comme identificateur
double sqrt; // !!X!! Masque la fonction sqrt de math.h
Ne pas appeler des fonctions standards avec des valeurs invalides
Certaines fonctions ne testent pas la valeur des paramètres
Informatique 1 ©É. Taillard, 2018 279
Informatique 1 ©É. Taillard, 2018 280
ANNEXE E. ERREURS CLASSIQUES
#define TOTO 3; au lieu de #define TOTO 3
int nb_mois = 012; au lieu de int nb_mois = 12;
scanf("%f", nb_double); au lieu de scanf("%lf", &nb_double);
if (d > 0 & n/d > 3) au lieu de if (d > 0 && n/d > 3)
for (i = 0; i < n; i++); au lieu de for (i = 0; i < n; i++)
if (*pt_v != 0) a = a/*pt_v; /* on peut diviser par *pt_v */;
au lieu de
if (*pt_v != 0) a = a/ *pt_v; // on peut diviser par *pt_v
while (c = getchar() != EOF) {…} // Priorité des opérateurs !while ((c = getchar) != EOF) {…} // Adresse de la fonction getchar !
au lieu de
while ((c = getchar()) != EOF) {…}
Informatique 1 ©É. Taillard, 2018 281
switch(methode) { case 1 : algorithme_1(); case 2 : algorithme_2(); default : algorithme_3();}au lieu de
switch(methode) { case 1 : algorithme_1(); break; case 2 : algorithme_2(); break; default : algorithme_3();}
switch(methode) { case 1 : algorithme_1(); break; case 2 : algorithme_2(); break; defau1t : algorithme_3();}au lieu de
switch(methode) { case 1 : algorithme_1(); break; case 2 : algorithme_2(); break; default : algorithme_3();}ta
Recommended