|
Index |
Vous devez créer vos projets sur le disque C:. En effet, Visual C++ génère de nombreux et volumineux fichiers lorsqu'il travaille. Un programme élémentaire peut facilement remplir une disquette lorsqu'il est compilé. Nous vous suggérons de toujours travailler sur disque dur (C:). Une fois votre travail terminé ou lorsqu'il vous faut partir, ne copier que les fichiers qui portent les extensions suivantes :
Nous vous suggérons également de conserver le nom du dossier dans lequel votre projet est créé. Par exemple, si nous avons créé un projet nommé MachineÀLaver, un fichier d'entête Laveuse.h et des fichiers sources Trempage.c, Lavage.c, Rinçage.c et Séchage.c. Après compilation du projet (si tout est correct), nous devrions avoir la hiérarchie suivante :
Vous n'avez qu'à conserver ce qui suit sur votre disquette :
NOTE: Vous pouvez changer le nom du répertoire. Par exemple, pour conserver des versions consécutives du programme de machine à laver, je conserverai sur disquette :
Dans chacun de ces répertoires, je conserverai les versions du 8, du 11 et du 20 septembre respectivement. Je conserverai ma version à remettre dans le dernier répertoire.
L'extension du fichier doit être représentative. De par les limitations du MS-DOS, la convention est de la limiter à trois caractères. Vous devriez choisir les extensions suivantes :
| Document PDf | nom_fichier.pdf |
| Document Word | nom_fichier.doc |
| Entête C | nom_fichier.h |
| Entête C++ | nom_fichier.hpp |
| Exécutable | nom_fichier.exe |
| Exécutable Java | nom_fichier.class |
| Fichier texte | nom_fichier.txt |
| Programme C | nom_fichier.c |
| Programme C++ | nom_fichier.cpp |
| Programme Java | nom_fichier.java |
L'entête d'un programme permet de connaître ce qu'il y a dans le programme, qui l'a programmé et quand il a été fait. Il n'est pas nécessaire de s'éterniser dans les commentaires, le style télégraphique faisant l'affaire. Vous avez un exemple d'entête qui suit :
//////////////////////////////////////////////////////////////////////////
// Nom:
exemple.cpp
// Description: Démontre l'entête d'un programme
// Programmeur: Pierre-Martin Tardif, professeur
// Création: 8 septembre 1998
// Modifications: PMT - premiere version
// Notes: Aucune remarque
particulière
//////////////////////////////////////////////////////////////////////////
À la suite de l'entête, nous avons les parties qui suivent :
Ainsi, nous aurions le code qui suit :
////////////////////// INCLUSIONS /////////////////////////////////////
#include "exemple.cpp"
// Inclusion spécifique à
exemple.cpp
#include <iostream.h>
// Classes
d'entrée/sortie
#include <new.h>
// Fonctions pour la gestion de la mémoire
int iExempleGlobale;
char cExempleGlobale;
Pour ce qui est des noms de variable, je vous suggère de commencer vos nom de variables par une(des) lettre(s) minuscule(s) indiquant le type de la variable. Ainsi, nous avons les combinaisons suivantes :
Par la suite, vous utilisez une combinaison de nom(s), adjectif(s) et verbe(s) qui décrivent le plus succinctement possible votre variable. Chaque mot commence par une majuscule et continue par des minuscules. Par exemple, nous aurions :
int iCompteur; // Compteur pour effectuer une boucle
float fDiviseur; // Le diviseur d'une division en virgule flotante
char cJourDeLaSemaine; // Jour de la semaine (0-dimanche...6-samedi)
unsigned char * pucTampon; // Pointeur vers une zone mémoire tampon (1-D)
double **ppdMatrice; // Pointeur vers une matrice (2-D)
L'entête d'une fonction permet de connaître ce qu'il y a dans la fonction, qui l'a programmée et quand elle a été complétée. Il n'est pas nécessaire de s'éterniser dans les commentaires, le style télégraphique faisant l'affaire. Vous avez un exemple d'entête qui suit :
//////////////////////////////////////////////////////////////////////////
// Méthode: AfficheNombre()
// Description: Affiche le nombre calculé
// Programmeur: Pierre-Martin Tardif, professeur
// Création: 8 septembre 1998
// Modifications: PMT - premiere version
// Paramètres: aucun paramètre
// Membres: aucun membre (ou variable
globale)
// Retourne: le nombre calculé sous une valeur
entière
//////////////////////////////////////////////////////////////////////////
Les commentaire servent à décrire soit un fichier (entête de fichier), une fonction (entête de fonction), un bloc de programme ou une seule instruction. Il est important que les commentaires soient significatifs. Il est encore plus important de mettre assez de commentaires pour qu'une autre personne puisse comprendre le déroulement d'un programme, d'une fonction, d'un bloc de programme ou d'une instruction. De plus, il est utile de commenter tout endroit important dans un programme.
En utilisant les conventions qui précèdent, nous aurions le programme qui suit :
//////////////////////////////////////////////////////////////////////////
// Nom:
exemple.cpp
// Description: Démonstration d'un programme (lecture d'une image
TIFF)
// Programmeur: Pierre-Martin Tardif, professeur
// Création: 8 septembre 1998
// Modifications: PMT - premiere version
// Notes: Aucune remarque
particulière
//////////////////////////////////////////////////////////////////////////
////////////////////// INCLUSIONS /////////////////////////////////////
#include "exemple.cpp"
// Inclusion spécifique à
exemple.cpp
#include <iostream.h>
// Classes
d'entrée/sortie
#include <tiff.h>
// Librairie de lecture/écriture du format TIFF
//////////////////////////////////////////////////////////////////////////
// Methode: doLoadTIFF()
// Description: Lit un fichier de format TIFF en utilisant
libtiff.dll
// Programmeur: Pierre-Martin Tardif, professeur
// Creation: 12 septembre 1997
// Modifications: PMT - deuxième version
// Parametres: Nom du fichier
// Membres: aucuns
// Retourne: rien
//////////////////////////////////////////////////////////////////////////
void doLoadTIFF(char *pcFileName) {
TIFF* tTiffFile = TIFFOpen(pcFileName, "r");
if (tTiffFile != NULL) {
int iWidth, iHeight;
size_t tTotalPixels;
uint32* puiData;
TIFFGetField(tTiffFile, TIFFTAG_IMAGEWIDTH,
&iWidth);
TIFFGetField(tTiffFile, TIFFTAG_IMAGELENGTH,
&iHeight);
sHeight = (short) iHeight; //
Hauteur de l'image lue
sWidth = (short) iWidth;
// Largeur de l'image lue (commentaire
d'instruction)
oData[R_INDEX] = Image(sHeight, sWidth);
// Initialise l'image rouge
oData[G_INDEX] = Image(sHeight, sWidth);
// Initialise l'image verte
oData[B_INDEX] = Image(sHeight, sWidth);
// Initialise l'image bleue
tTotalPixels = iWidth * iHeight; //
Dimension totale de l'image
// La ligne qui suit alloue de la
mémoire, il ne faut pas oublier de la libérer (zone importante)
puiData = (uint32*)
_TIFFmalloc(tTotalPixels * sizeof (uint32)); // Alloue la mémoire
if (puiData != NULL) {
if
(TIFFReadRGBAImage(tTiffFile, iWidth, iHeight, puiData, 0)) { // Lit l'image
sur disque
// Convertit l'image lue du format TIFF à
la représentation interne choisie (commentaire de bloc)
for (register short sLine = 0; sLine < sHeight; ++sLine) {
for (register short sCol = 0; sCol < sWidth; ++sCol) {
register uint32 uiData = puiData[(int)sLine * (int)sWidth + (int)sCol];
oData[R_INDEX].setValue((float) TIFFGetR(uiData), sHeight-sLine-1, sCol);
oData[G_INDEX].setValue((float) TIFFGetG(uiData), sHeight-sLine-1, sCol);
oData[B_INDEX].setValue((float) TIFFGetB(uiData), sHeight-sLine-1, sCol);
}
}
} else { //
Erreur lors de la lecture
_TIFFfree(puiData);
} // if
(TIFFRead...
_TIFFfree(puiData);
} // if
(puiData...
TIFFClose(tTiffFile);
} // if (tTiff...
return;
}
//////////////////////////////////////////////////////////////////////////
// Méthode: main()
// Description: Fonction principale, qui est exécutée en premier
// Programmeur: Pierre-Martin Tardif, professeur
// Création: 8 septembre 1998
// Modifications: PMT - premiere version
// Paramètres: arguments standards
// Membres: aucun membre (ou variable
globale)
// Retourne: toujours zéro (0), indiquant que
tout s'est bien passé
//////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
doLoadTIFF("essai.jpg"); // Lit l'image
return 0;
}
Le projet sert à mettre ensemble un ou des fichiers pour produire un exécutable ou une librairie. Pour créer un projet, il suffit de choisir le menu File->New et l'onglet Projects. Dès lors, vous avez la fenêtre suivante :

Les différentes options disponibles (ATL COM AppWizard, Cluster Resource Type Wizard, etc.) correspondent aux différentes applications que vous pouvez créer. Pour créer une application utilisant les fonctions d'entrée-sortie standard du langage C/C++, vous devez absolument choisir l'option Win32 Console Application. Les options Win32 Application et MFC AppWizard (exe) permettent de créer des interfaces graphiques. Les options Win32 Static Library, Win32 Dynamic-Link Library et MFC AppWizard (dll) permettent de créer des librairies. Finalement, la plupart des autres options permettent de créer des programmes Windows ayant une tâche spécifique.
Une fois que vous avez entré votre nom de projet et son emplacement, le bouton OK devient disponible. Dès que vous le cliquez, vous créez votre projet qui se situe dans un espace de travail (workspace). Vous pouvez ajouter des fichiers à votre projet en utilisant File->New, Projet->Add to Project et en cliquant sur le bouton droit de la souris dans la fenêtre de l'espace de travail :

Vous pouvez changer les options de votre projet en utilisant Project->Setting ou Alt+F7. Alors la fenêtre des options apparaîtra :

Les options les plus importantes sont situées dans C/C++ et Link. Vous remarquez que les options de la fenêtre précédente sont pour "Win32 Release". En effet, il existe toujours deux versions d'un projet lors de sa création sous Visual C++. Il y a la version "Win32 Debug" et la version "Win32 Release".
La différence entre ces deux versions est surtout au niveau du déverminage et de l'optimisation. La version "Debug" sert principalement à trouver les problèmes lors de l'exécution d'un programme. La version "Release" ne contient pas les options de déverminage. Elle est plus compacte et plus rapide. C'est habituellement cette version que l'on transmet à notre client ou que l'on utilise tous les jours. Pour passer de la compilation d'une version à l'autre, il faut choisir Build->Set Active Configuration.... Vous remarquerez que les fichiers compilés se trouvent dans les sous-répertoires Debug et Release selon la version que l'on a choisi.
Finalement, il est possible d'avoir plusieurs projets dans un même espace de travail. Par exemple, lorsque vous démarrez Visual C++, essayez File->New. Par la suite, sélectionnez l'onglet Workspaces. Dans le champ Workspace name, entrez test et cliquez OK. Vous êtes maintenant dans un espace de travail sans projet. Il faut maintenant créer un premier projet en choisissant File->New puis l'onglet Projects. Choisissez l'option Win32 Console Application et entrez projet1 comme premier projet. Maintenant, n'oubliez surtout pas de choisir l'option Add to current workspace et cliquez OK. Pour ajouter un second projet, choisissez File->New puis l'onglet Projects. Choisissez encore une fois l'option Win32 Console Application et entrez projet2 comme second projet. Maintenant, vérifiez si l'option Add to current workspace est déjà sélectionnée et cliquez OK. Regardez la fenêtre de l'espace de travail qui devrait ressembler à ceci :

Présentement, c'est le projet2 qui est sélectionné. Pour avoir projet1 sélectionné, il suffit de choisir Project->Set Active Projet->projet1.
En résumé, pour vos travaux demandant plusieurs exercices, vous pourriez utiliser un seul espace de travail contenant tous les projets que vous avez à faire.
Une librairie est simplement un ensemble de fonctions rassemblées dans un même fichier. Par exemple, dans le langage C, il y a les fonctions printf(), scanf(), sin(), cos(), strlen(), strcpy(), etc. Ces fonctions ne font pas partie des mots clés (ou mots réservés) du langage C. Cependant, elles sont disponibles sur la majorité des compilateurs C, car elles font parties de la librairie standard du langage C (crt.dll ou libc.lib sous Windows).
Pour pouvoir compiler ces fonctions dans votre programme, il faut inclure les fichiers d'entêtes où elles sont déclarées. Ainsi, le compilateur saura si les paramètres que vous donnez à ces fonctions sont valides. Pour utiliser strlen(), il faut include string.h. Pour utiliser sin(), il faut inclure math.h. Ces inclusions se font de la façon suivante :
#include <string.h>
#include <math.h>
Après la compilation, c'est l'étape de l'édition des liens. L'édition des liens consiste à prendre tous les fichiers compilés de votre projet et de les lier avec les librairies. Si une des fonctions que vous avez utilisée dans votre programme n'existe ni dans vos fichiers de votre projet, ni dans les librairies standards, il y aura un erreur de l'éditeur de liens (error LNK2001: unresolved external symbol). Si tout va bien, l'éditeur créera votre exécutable (.exe) ou votre librairie (.lib, .dll) selon la définition de votre projet.
Finalement, nous allons faire la distinction entre l'édition de liens statique et dynamique. L'édition de liens statique permet de créer des exécutables autonomes. Cependant, la taille de ces fichiers sera assez élevée. De plus, si l'une des librairie utilisée est mise à jour, il faut recompiler l'exécutable pour utiliser la mise à jour. Finalement, l'édition des liens n'a lieu qu'une fois, après la compilation du programme. Lorsque le programme est chargé en mémoire, aucune édition des liens n'est nécessaire.
L'édition des liens dynamique permet de créer des exécutables de tailles réduites. De plus, il n'y a habituellement aucun besoin de recompiler le programme si une des librairies utilisée a été mise à jour. Cependant, à l'exécution du programme, le système d'exploitation recherchera les librairies dynamiques (.dll sous Windows) pour faire la liaison des liens finale. Il s'écoulera un certain temps lors du chargement de l'application. De plus, si l'une des librairies est manquante (fichier dll non trouvé), le programme ne pourra pas s'exécuter.
Par exemple, le programme qui écrit "Bonjour" à l'écran en C, prend 32Ko en version statique et 16Ko en version dynamique. Un autre exemple est une application Windows qui prend 256Ko en version statique et 40Ko en version dynamique.
Dans un fichier .h ou .hpp, il faut habituellement mettre :
//////////////////////////////////////////////////////////////////////////
// Nom: exemple.h
// Description: Démontre l'entête d'un fichier d'inclusion
// Programmeur: Pierre-Martin Tardif, professeur
// Création: 8 septembre 1998
// Modifications: PMT - premiere version
// Notes: Aucune remarque
particulière
//////////////////////////////////////////////////////////////////////////
#define ETIQUETTE VALEUR_ETIQUETTE
#define MACRO(a,b) cout << "La valeur de " << a << " est " << b << endl;
#include <nom_fichier.h>
typedef unsigned char byte;
typedef int MATRICE_ENTIERE[100][100];
int MaPremiereFonction(void);
void PresseTouche(void);
const int NOMBRE_COLONNE = 3;
const float PI = 3.1415926536;
Voici le fichier math.h dans À CORRIGER quelque peu décortiqué:
ENTÊTE DU FICHIER
/***
*math.h - definitions and declarations for math library
*
* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
* This file contains constant definitions and external subroutine
* declarations for the math subroutine library.
* [ANSI/System V]
*
* [Public]
*
****/
COMMANDES AU COMPILATEUR
#if _MSC_VER > 1000
#pragma once
#endif
#ifndef _INC_MATH
#define _INC_MATH
#if !defined(_WIN32) && !defined(_MAC)
#error ERROR: Only Mac or Win32 targets supported!
#endif
#ifdef _MSC_VER
/*
* Currently, all MS C compilers for Win32 platforms default to 8 byte
* alignment.
*/
#pragma pack(push,8)
#endif /* _MSC_VER */
MACROS
/* Define _CRTIMP */
#ifndef _CRTIMP
#ifdef _DLL
#define _CRTIMP __declspec(dllimport)
#else /* ndef _DLL */
#define _CRTIMP
#endif /* _DLL */
#endif /* _CRTIMP */
/* Definition of _exception struct - this struct is passed to the matherr
* routine when a floating point exception is detected
*/
DÉFINITIONS DE TYPE
/* Definition of a _complex struct to be used by those who use cabs and
* want type checking on their argument
*/
CONSTANTES
/* Constant definitions for the exception type passed in the _exception struct
*/
#define _DOMAIN 1 /* argument domain error */
#define _SING 2 /* argument singularity */
#define _OVERFLOW 3 /* overflow range error */
#define _UNDERFLOW 4 /* underflow range error */
#define _TLOSS 5 /* total loss of precision */
#define _PLOSS 6 /* partial loss of precision */
#define EDOM 33
#define ERANGE 34
DÉCLARATIONS DE FONCTION (PROTOTYPES)
/* Function prototypes */
int __cdecl abs(int);
double __cdecl acos(double);
double __cdecl asin(double);
double __cdecl atan(double);
double __cdecl atan2(double, double);
double __cdecl cos(double);
double __cdecl cosh(double);
double __cdecl exp(double);
double __cdecl fabs(double);
double __cdecl fmod(double, double);
long __cdecl labs(long);
double __cdecl log(double);
double __cdecl log10(double);
double __cdecl pow(double, double);
double __cdecl sin(double);
double __cdecl sinh(double);
double __cdecl tan(double);
double __cdecl tanh(double);
double __cdecl sqrt(double);
MACROS
/* Macros defining long double functions to be their double counterparts
* (long double is synonymous with double in this implementation).
*/
#define acosl(x) ((long double)acos((double)(x)))
#define asinl(x) ((long double)asin((double)(x)))
#define atanl(x) ((long double)atan((double)(x)))
#define atan2l(x,y) ((long double)atan2((double)(x), (double)(y)))
#define _cabsl _cabs
#define ceill(x) ((long double)ceil((double)(x)))
#define cosl(x) ((long double)cos((double)(x)))
#define coshl(x) ((long double)cosh((double)(x)))
#define expl(x) ((long double)exp((double)(x)))
#define fabsl(x) ((long double)fabs((double)(x)))
#define floorl(x) ((long double)floor((double)(x)))
#define fmodl(x,y) ((long double)fmod((double)(x), (double)(y)))
#define frexpl(x,y) ((long double)frexp((double)(x), (y)))
#define _hypotl(x,y) ((long double)_hypot((double)(x), (double)(y)))
#define ldexpl(x,y) ((long double)ldexp((double)(x), (y)))
#define logl(x) ((long double)log((double)(x)))
#define log10l(x) ((long double)log10((double)(x)))
#define _matherrl _matherr
#define modfl(x,y) ((long double)modf((double)(x), (double *)(y)))
#define powl(x,y) ((long double)pow((double)(x), (double)(y)))
#define sinl(x) ((long double)sin((double)(x)))
#define sinhl(x) ((long double)sinh((double)(x)))
#define sqrtl(x) ((long double)sqrt((double)(x)))
#define tanl(x) ((long double)tan((double)(x)))
#define tanhl(x) ((long double)tanh((double)(x)))
#endif /* _MSC_VER */
#endif /* _INC_MATH */
Comme nous le voyons, les fichiers d'inclusion peuvent être très complexes. L'exemple précédant (math.h) a été écourté !
Pour obtenir de l'aide, il suffit d'enforcer l'icône
à l'aide de la souris ou d'aller dans le menu help.
Cette aide (et plus encore) est également disponible sur http://premium.microsoft.com/msdn/library/.
Vous y trouverez toutes les fonctions, les mots clés et les structures du langage C
(aller dans Visual C++ Documentation -> Reference -> C/C++ language reference).