Dans ce tutoriel, nous découvrons la librairie standard string, qui va nous simplifier la vie.
Liens Vers les autres tutoriels de la série :
Bioopo
Le 31/12/2006
Nous allons commencer ce tutoriel par voir ce qui ne va pas pour l'utilisateur. Nous allons voir les librairies standard du c++, comment les utiliser et pourquoi. Une fois notre projet terminé, nous avons vu qu'il n'y avait pas de bugs, Génial !!!! Mais faire trois saisies clavier pour une opération aussi simple, c'est même plus terrible, c'est catastrophique.
De plus, nous sommes limités, pour le nombre d'opérations, par l'utilisation de variables unique à chaque saisie, vous imaginez, si vous voulez que votre calculatrice puisse effectuer 20 opérations, ça serait aberrant, un code très long et pas forcément fonctionnel.
La troisième chose est le fait que nous ne pouvons saisir qu'une seule opération, pour en faire une seconde, nous devons relancer le programme. Un petit menu serait le bienvenu.
Voilà, ça sera la base pour notre mise a jour. Fixons les buts clairement :
Les connaissances requises sont celles acquises aux tutoriels numéro 1 et 2 : Débutez en c++. Il faut savoir :
Le but du programme est d'afficher le résultat d'une opération saisie par l'utilisateur.
Nous allons utiliser le logiciel dev-c++ avec un nouveau projet en mode console.
Pourquoi le mode console?
Simplement car pour la calculatrice que nous allons programmer, une interface graphique est inutile. Surtout, elle nous rendrait l'apprentissage plus difficile, ce qui n'est pas le but. L'exécutable de la calculatrice ne devra pas dépasser 500 Ko.
Pour notre troisième tutoriel, nous devons modifier les analyses fonctionnelles et structurelles de notre projet initial, nous rajoutons la fonction FA1 : Menu.
Spécificités | Détails |
---|---|
Code d'identification | FP0 |
Nom | Calculatrice |
Objectif | Afficher le résultat d'une opération saisie par l'utilisateur |
Données fournies | Aucune |
Actions utilisateur | Saisie de l'opération |
Données sorties | Résultat de l'opération |
Sous-fonctions | FP1 : Enregistrement saisie FP2 : Calcul FP3 : Affichage du résultat FP4 : Vérification des saisies FA1 : Menu |
Description détaillée | La calculatrice devra, en fonction de la saisie de l'utilisateur, calculer et afficher le résultat de l'opération. |
Spécificités | Détails |
---|---|
Code d'identification | FP1 |
Nom | Enregistrement saisie |
Objectif | Enregistrer les saisies utilisateur |
Données fournies | Aucune |
Actions utilisateur | Saisie de l'opération |
Données sorties | Saisie enregistrée |
Sous-fonctions | Aucune |
Description détaillée | La Fonction devra enregistrer la saisie utilisateur. |
Spécificités | Détails |
---|---|
Code d'identification | FP2 |
Nom | Calcul |
Objectif | Effectuer le calcul de l'opération saisie par l'utilisateur |
Données fournies | Saisie enregistrée |
Actions utilisateur | Aucune |
Données sorties | Résultat du calcul |
Sous-fonctions | Aucune |
Description détaillée | La Fonction devra choisir quel est le calcul a effectuer en fonction de la saisie de l'utilisateur. |
Spécificités | Détails |
---|---|
Code d'identification | FP3 |
Nom | Affichage du résultat |
Objectif | Afficher le résultat de l'opération |
Données fournies | Résultat du calcul |
Actions utilisateur | Aucune |
Données sorties | Résultat affiché |
Sous-fonctions | Aucune |
Description détaillée | La Fonction devra afficher le résultat de l'opération saisie. |
Spécificités | Détails |
---|---|
Code d'identification | FP4 |
Nom | Vérification saisie |
Objectif | Validation de la saisie utilisateur |
Données fournies | Saisie enregistrée |
Actions utilisateur | Aucune |
Données sorties | Saisie validée |
Sous-fonctions | Aucune |
Description détaillée | La Fonction devra vérifier la saisie utilisateur et la valider. Si elle n'est pas valide, l'utilisateur devra saisir une nouvelle opération. |
Spécificités | Détails |
---|---|
Code d'identification | FA1 |
Nom | Menu |
Objectif | Création d'un menu pour la calculatrice |
Données fournies | Aucune |
Actions utilisateur | Saisie utilisateur |
Données sorties | Menu choisi |
Sous-fonctions | Aucune |
Description détaillée | La Fonction devra Choisir le code à exécuter en fonction de la saisie utilisateur. |
Spécificités | Détails |
---|---|
Code d'identification | FP1 |
Nom | Enregistrement saisie |
Objectif | Enregistrer les saisies utilisateur |
Actions utilisateur | Saisie de l'opération |
Données sorties | Saisie enregistrée |
Description détaillée | La Fonction devra enregistrer la saisie utilisateur. |
Nous allons remanier tout le code de cette fonction. Les tableaux que nous avions au tutoriel précédent ne sont pas assez performant et ne répondent pas aux besoins du programme.
Nous allons utiliser une librairie standard du c++. La librairie string.
Les variables de type string servent à enregistrer des chaines de caractères dont la taille n'est pas connue à l'avance.
Une librairie est un ou des fichiers que le compilateur inclut lors de la création du programme, contenant des définitions et des fonctions. Nous en utilisons déjà. La librairie iostream et cstdlib. C'est grâce à elles que nous pouvions utiliser les variables et les fonctions. Elles s'incluent grâce a la commande #include au début du fichier. De plus pour chaque fichier créé, il faut inclure les librairies dont nous avons besoin.
Récapitulatif des variables et fonctions de FP1
Variables et fonctions | Type | Détails |
---|---|---|
strSaisie | string | Enregistre les saisies utilisateur |
cin | Demande la saisie et l'enregistre |
Spécificités | Détails |
---|---|
Code d'identification | FP4 |
Nom | Vérification saisie |
Objectif | Validation de la saisie utilisateur |
Données fournies | Saisie enregistrée |
Données sorties | Saisie validée |
Description détaillée | La Fonction devra vérifier la saisie utilisateur et la valider. Si elle n'est pas valide, l'utilisateur devra saisir une nouvelle opération |
Cette fonction se divise maintenant en trois parties, la vérification de la saisie et le chemin a emprunter en fonction de cette vérification, plus le découpage de la saisie. Si la saisie a passé le test de validation, alors nous découpons les nombres et les opérateurs puis nous calculons, sinon nous redemandons la saisie.
Par contre, le code de vérification sera plus simple car nous utiliserons une fonction de spécifique à la librairie string, et nous vérifierons toute la saisie en une seule fois, opérateurs et nombres en même temps.
Nous ne ferons plus appel au code ascii, mais directement aux nombres et aux opérateurs.
Cette fonction cherche les caractères demandés et retourne leur position dans la chaine. Elle se définit comme suit :
Variable_de_position = variable_String.find_first_of( "caractères à chercher");
Grâce à cette fonction, nous allons chercher les caractères reconnus par le programme, en vérifiant le premier caractère. Si il est un caractère reconnu, la fonction nous renverra sa position. Dans notre programme, comme nous vérifions toujours le premier caractère, ce sera 0 , sinon, c'est qu'il n'est pas un caractère reconnu, et la saisie n'est pas valide.
Cette fonction nous servira aussi à découper les nombres et les opérateurs de l'opération. En cherchant simplement les opérateurs, nous aurons leurs positions.
Cette fonction permet d'effacer des caractères, elle se définit comme suit :
Variable_Nouvelle = variable_String.erase(x,y);
Où x est la position du premier caractère à effacer, et y sa longueur.
Dans notre programme, nous effacerons le caractère validé, ce qui décalera les caractères suivants. Nous pourrons revérifier à partir du premier caractère. Cette fonction est détournée ici de son objectif principal, car nous n'effaçons pas un caractère de la vraie saisie, mais une copie temporaire. Le caractère ainsi effacé sera pour nous la validation de ce caractère.
Cette fonction enregistre une sous-partie de la chaine. Elle se définie comme cela :
Variable_Sous_Chaine = variable_String.substr(x,y);
Où x est la position ou commence la sous-chaine, et y sa longueur.
Grâce à cela, nous pourrons découper nos nombres et nos opérateurs.
Récapitulatif des variables et fonctions de FP1
Variables et fonctions | Type | Détails |
---|---|---|
strSaisie | string | Enregistre la saisie utilisateur |
dblNombre[10] | double | Enregistre les nombres saisis validés |
strOperand[10] | string | Enregistre les opérateurs |
bErreur | Bool | Enregistre la présence d'erreur |
bDecimal | Bool | Enregistre la présence du point décimal |
If | Fonction de test | |
While | Fonction de boucle | |
find_first_of | Fonction de recherche de caractères | |
substr | Fonction de découpages de sous-chaines |
Spécificités | Détails |
---|---|
Code d'identification | FA1 |
Nom | Menu |
Objectif | Création d'un menu pour la calculatrice |
Actions utilisateur | Saisie utilisateur |
Données sorties | Menu choisi |
Description détaillée | La Fonction devra Choisir le code à exécuter en fonction de la saisie utilisateur. |
Cette fonction ne comporte aucune difficulté. C'est une simple saisie, avec un while et un if pour le code à exécuter.
Variables et fonctions | Type | Détails |
---|---|---|
intMenu | int | Enregistre la saisie utilisateur |
while | Fonction de boucle | |
if | Fonction de test | |
Cin | Fonction de demande de saisie | |
cout | Fonction d'affichage |
Comme nous nous servons de la librairie string, nous l'incluons dans le fichier main.cpp
Fichier main.cpp - Début du fichier
.........
#include <cstdlib> #include <iostream> #include <string> #include "main.h"
.........
Vous devez vous demander pourquoi certains include sont avec <> et d'autres avec "".
Les librairies standard sont notées <> et les fichiers que nous créons sont notés "".
Ne vous arrêtez pas à mes explications, je vous dit le minimum de ce que vous devez savoir, cherchez, documentez-vous, c'est le meilleur moyen de progresser.
/********************************** Program : calc2007 Fichier : main.h Créateur : bioopo Creation : 29/12/2006 logiciel : dev-c++ Version : 0.2a Modification : 31/12/2006 **********************************/ /********************************** Ce fichier déclare les fonctions et les variables globales utilisées dans le programme **********************************/ /********************************** Fichiers a inclure **********************************/ //#include <string> /********************************** Définition des variables **********************************/ //Variable contenant la saisie de l'opérateur. std::string strSaisie = ""; //variable contenant le signe de l'opération std::string strOperand[10]= {"","","","","","","","","",""}; //Variable contenant les nombres de l'opération double dblNombre[10]= {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}; //Variable contenant le résultat double dblResultat = 0.0; //variable de présence d'erreur bool bErreur = true; //variable de présence de decimal bool bDecimal = false; /********************************** Déclaration des fonctions **********************************/ //Fonction permettant la saisie utilisateur void Saisie_Utilisateur(); //Fonction permettant la vérification de la saisie utilisateur void Verification_Saisie(); //Fonction permettant d'extraire les différentes partie de l'opération. void Extraction(); //fonction de calcul de l'opération void Calcul();
Voici le fichier main.h en entier, il faut supprimer certaines lignes et les remplacer ou ajouter les nouvelles. Pensez à supprimer les arguments de la fonction Saisie_Utilisateur et Vérification_Saisie, ainsi que la définition et l'initialisation de la variable dblNombre et dblResultat dans le fichier main.cpp. Dans le fichier main.h avant les définitions des variables string ajouter std::, cela signifie que nous utilisons l'espace de nom standard.
Fichier main.cpp - Fonction Saisie_utilisateur
........
system("PAUSE"); return EXIT_SUCCESS; } void Saisie_utilisateur() { cin >> strSaisie; }
La fonction de Saisie_utilisateur ne contient plus qu'une seule ligne, ce qui rend le code plus rapide, est surtout plus clair. Pensez à supprimer les arguments de la fonction Saisie_Utilisateur.
Fichier main.cpp - Fonction main
.......
/********************************** Corps de la fonction **********************************/ //Fonction permettant a l'utilisateur de saisir le premier nombre cout << "Bioopo-vega calculatrice 2007 version 0.2a" << endl; cout << "entrez l'opération" << endl; Saisie_utilisateur();
.....
L'appel de la fonction de saisie utilisateur n'a plus d'argument. Donc nous supprimons le 1 dans les parenthèses, mais ne pas supprimer les parenthèses. Comme la saisie ne se fait plus qu'une fois, pensez à supprimer le code de saisie et vérification des opérateurs et de la seconde saisie des nombres. Voila, la fonction FP1 est terminée, Elle est beaucoup plus simple, moins de code, moins de test.
Fichier main.cpp - Fonction Vérification_Saisie
........
case 2: cin >> chrOperand; break; } } /********************************** Fonction Verification_Saisie Fonction permettant la vérification de la saisie utilisateur **********************************/ void Verification_Saisie() { //Nous définissons qu'il y a une erreur pour la première saisie avant vérification bErreur = true; //Boucle tant qu'il y a une erreur while(bErreur == true) { //Définissons qu'il n'y a pas de décimal de mise avant la vérification bDecimal = false; //Définissons les variables de positions int intPos = 0; //définissons une variable temporaire de travail string strTemp = strSaisie; //Boucle tant que la vérification de la chaine n'est pas finie while(intPos == 0 and strTemp != "") { //Enregistre la position du caractère autorisé en cours intPos = strTemp.find_first_of("0123456789.+-*/"); //Test si Le caractère est autorisé. if(intPos == 0) { bErreur = false; strTemp = strTemp.erase(0,1); } //sinon ne pas valider la saisie else { bErreur = true; break; } } //Si il y a une erreur, nous demandons de rentrez un nouveau nombre if(bErreur == true) { cout << "vous n'avez pas rentré un nombre correct" << endl; cout << "entrez un nombre correct" << endl; Saisie_Utilisateur(); } } }
Vous voyez l'intérêt des librairies standard. Maintenant, Le code prend moins de la moitié de l'ancien. Les fonction de la librairie string facilitent grandement la programmation et de plus, le code s'exécutera plus vite.
Fichier main.cpp - Fonction main
......
/********************************** Corps de la fonction **********************************/ //Fonction permettant à l'utilisateur de saisir le premier nombre cout << "Bioopo-vega calculatrice 2007 version 0.2a" << endl; cout << "entrez le premier nombre" << endl; Saisie_Utilisateur(); //Fonction de vérification de la saisie Verification_Saisie(); //Test pour déterminer le signe de l'opération et calcul l'opération if(chrOperand == '+') { dblResultat = dblNombre[0] + dblNombre[1]; }
......
Nous appelons donc la fonction de vérification. Il nous reste pour cette fonction à découper et enregistrer les différentes partie de l'opération. Pour cela, il faut ajouter une fonction : la fonction extract.
Fichier main.cpp - Fin du fichier
.......
//Si il y a une erreur, nous demandons de rentrez un nouveau nombre if(bErreur == true) { cout << "vous n'avez pas rentré un nombre correct" << endl; cout << "entrez un nombre correct" << endl; Saisie_Utilisateur(); } } } /********************************** Fonction Extraction Fonction permettant d'extraire les différentes partie de l'opération. **********************************/ void Extraction() { //Définissons la variables de positions int intPos = 1,i = 0; //Définissons une variable d'enregistrement temporaire string strTemp = ""; //définissons une variable temporaire de travail string strTempSaisie = strSaisie; //Boucle tant que la l'extraction des nombres est incomplète while(intPos != 0) { //Enregistre la position de l'opérateur intPos= strTempSaisie.find_first_of("+-*/"); //Extraction des nombres if(intPos > 0) { strTemp= strTempSaisie.substr(0,intPos); //enregistrement des nombres valides après conversion std::istringstream Argument(strTemp); Argument >> dblNombre[i]; //enregistrement de l'opérateur strOperand[i]= strTempSaisie.substr(intPos,1); //Suppression des nombres validés strTempSaisie = strTempSaisie.erase(0,(intPos+1)); //incrémentation de la position des tableaux d'enregistrement i++; } else { //enregistrement des nombres valides après conversion std::istringstream Argument(strTempSaisie); Argument >> dblNombre[i]; break; } } }
Nous recherchons les opérateurs et nous faisons une extraction du nombre qui se trouve avant. Puis nous enregistrons l'opérateur, et le nombre après conversion en double.
Puis nous supprimons les données, enregistrons et nous recommençons jusqu'à la fin de chaine.
Il reste a inclure la librairie standard sstream pour pouvoir utiliser la fonction std::istringstream. Cette fonction sert pour la conversion des string vers un autre type, ici un type double.
Fichier main.cpp - Début du fichier
.......
#include <cstdlib> #include <iostream> #include <sstream> #include <string> #include "main.h"
.......
Fichier main.cpp - Fin du fichier
......
/********************************** Fonction Calcul Fonction de calcul de l'opération **********************************/ void Calcul() { //Initialisation de la variable de résultat dblResultat = dblNombre[0]; int i = 0; //Fonction de boucle tant que le compteur est inférieur au nombre d'opérandes de l'opération while(strOperand[i] != "") { //Fonction de test de l'opérande en cours et calcul le résultat en conséquence if(strOperand[i] == "+") dblResultat = dblResultat + dblNombre[i+1]; else if(strOperand[i] == "-") dblResultat = dblResultat - dblNombre[i+1]; else if(strOperand[i] == "*") dblResultat = dblResultat * dblNombre[i+1]; else if(strOperand[i] == "/") dblResultat = dblResultat / dblNombre[i+1]; i++; } }
Pas besoin de commentaire sur cette fonction, à part la fonction sizeof qui permet d'obtenir la taille d'un tableau, comme les élément d'un tableau char ont une taille de 1 caractère, ça nous donne le nombre de caractères, donc ici, le nombre d'opérations.
Nous devons faire un appel à cette fonction.
Fichier main.cpp - Fonction main
......
/********************************** Corps de la fonction **********************************/ //Fonction permettant a l'utilisateur de saisir le premier nombre cout << "Bioopo-vega calculatrice 2007 version 0.2a" << endl; cout << "entrez le premier nombre" << endl; Saisie_Utilisateur(); //Fonction de vérification de la saisie Verification_Saisie(); //Fonction de calcul de l'opération Calcul(); //Fonction affichant le résultat de l'opération à l'écran cout << "Le resultat est" << endl; cout << dblResultat << endl;
.....
Dans la fonction main, effacer tout le code de calcul et placez y l'appel de la fonction. Voila, la fonction de calcul est terminée. Il reste à développer la fonction Fa1 : Menu, que je ne développerais pas ici, je la mettrais dans la partie Compléments, car vous connaissez maintenant toutes les fonctions pour la réaliser.
Voila, la calculatrice fonctionne, le menu aussi. C'est plus sympa, les seuls bugs que j'ai pu rencontrer, c'est dans le choix du menu, si je tapes une opération avec +2 à la fin, il quitte le programme. Le second est encore moins grave, car ce n'est pas un bug, mais nous devons appuyer sur une touche pour quitter après avoir choisi l'option dans le menu. Nous réglerons ça plus tard, car ce ne sont pas des problèmes graves, nous pouvons dire que notre programme est stable, et le passer en version 0.3b.
Bases vues dans ce tutoriel :
Nous avons vu dans ce tutoriel et les précédents:
Voici le code de la fonction FA1 : Menu
Fichier main.h
Il faut déclarer une variable pour le choix du menu.Puis déclarer la fonction de menu
int intMenu = 0; void Menu();
Fichier main.cpp
Il faut coder la fonction à la fin du fichier écrire :
void Menu() { system("cls" ); cout << "saisir une operation tapez 1 ou quitter tapez 2" << endl; cin >> intMenu; }
La fonction system("cls" ) efface l'écran.
Puis dans la fonction main :
int main(int argc, char *argv[]) { /********************************** Définition et initialisation des variables **********************************/ /********************************** Corps de la fonction **********************************/ //Fonction permettant a l'utilisateur de saisir le premier nombre cout << "Bioopo-vega calculatrice 2007 version 0.2a" << endl; Menu(); while(intMenu != 2) { if(intMenu == 1) { system("cls" ); cout << "entrez l'operation" << endl; Saisie_Utilisateur(); //Fonction de vérification de la saisie Verification_Saisie(); //fonction d'extraction des données de l'opération Extraction(); //Fonction de calcul de l'opération Calcul(); //Fonction affichant le résultat de l'operation à l'écran cout << "Le resultat est" << endl; cout << dblResultat << endl; system("PAUSE"); Menu(); } else Menu(); } if(intMenu == 2) { //Appel de la function demandant une pause et de presser une touche pour quitter. system("PAUSE"); return EXIT_SUCCESS; } }
Je finirais ce tutoriel en vous disant de bien assimiler la librairie string et ses fonctions, d'essayer de faire des petits programmes utilisant les connaissances acquises avant de vous lancer dans le tutoriel suivant. Les possibilités de programmes sont déjà plus vastes que pour les deux premiers tutoriels. Essayez à nouveau vos anciennes versions, vous allez voir que les changements apportés sont énormes. Nous avons fait un grand bond en avant entre la version 0.2b et celle-ci.
En espérant que ce tutoriel ai pu vous aider et qu'il vous a plu. Bon courage pour la suite.
Merci a tous.