zwyx
Messages postés
146
Date d'inscription
jeudi 22 novembre 2007
Statut
Membre
Dernière intervention
21 mars 2016
31 janv. 2008 à 17:34
Salut trosy
J'avais aussi commencé par développer une petite calculette. Je m'étais effectivement aidé en puisant dans différentes sources disponibles sur ce site, sauf qu'au final, la mienne était plus jolie.
Je vais essayer de schématiser le principe, si ça peut t'aider... Tu as deux nombres mémorisés en variables globales, ou en attributs de la classe qui gère les calculs, ainsi qu'un opérateur, qui peut être de type Char ('+', '-', '*', '/' et '='). Dès que l'utilisateur appuie sur un opérateur ou sur le bouton '=', tu sais que la saisie du nombre en cours est terminée. Enfin, quand tu affiches le résultat suite à un clic sur '=', tu recopies cette valeur dans la première opérande, prête à saisir la deuxième opérande. Ainsi, tu pourras enchainer plusieurs opérations à la suite, comme dans la calculatrice de Billou.
Je copie mon code en tout petit. N'hésites pas si tu as des questions, j'ai débuté il n'y a pas longtemps...
unit UnitCalc;
{ ----------- INTERFACE ----------- }
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, ActnList;
type
TCalculateur = class { effectue les calcul demandés }
private
Op1, Op2 : extended; { opérandes en mémoire }
NbOp : byte; { nombre d'opérandes en mémoire }
Operateur : char; { opérateur de l'opération en cours }
EntreeActuelle : string; { opérande en cours de saisie par l'utilisateur }
public
constructor Create;
procedure Clear;
function GereChiffre(chaine: string): string;
function Conversion(devise: char): extended;
function Operation(chaine: string): string;
function Execute: extended;
end;
TCalculette = class(TForm) { telle qu'elle s'affiche à l'écran }
LabelResultat: TLabel;
PanelControles: TPanel;
PanelChiffres: TPanel;
PanelOperateurs: TPanel;
BoutonOff: TButton;
BoutonClear: TButton;
Bouton0: TButton;
BoutonDecimale: TButton;
Bouton000: TButton;
Bouton1: TButton;
Bouton2: TButton;
Bouton3: TButton;
Bouton4: TButton;
Bouton5: TButton;
Bouton6: TButton;
Bouton7: TButton;
Bouton8: TButton;
Bouton9: TButton;
BoutonEgal: TButton;
BoutonPlus: TButton;
BoutonMoins: TButton;
BoutonFois: TButton;
BoutonSur: TButton;
BoutonFranc: TButton;
BoutonEuro: TButton;
procedure FormCreate(sender: TObject);
procedure FormClose(sender: TObject; var Action: TCloseAction);
procedure BoutonOffClick(sender: TObject);
procedure BoutonClearClick(sender: TObject);
procedure AppuiSurChiffre(sender: TObject);
procedure AppuiSurOperateur(sender: TObject);
procedure Affiche(chaine: string; nbdecimales: byte = 9); { tronque les décimales et décale l'affichage en insérant un espace à droite }
procedure InterceptClavier(sender: TObject; var key: Word; shift: TShiftState); { permet d'utiliser le clavier }
private
calculeur: TCalculateur;
end;
var
calc: TCalculette;
{ ----------- IMPLEMENTATION ----------- }
implementation
{$R *.dfm}
const RapportEuroFranc = 6.55957; { taux de change du franc à l'euro }
const OpInvalide = 123456789; { résultat arbitraire d'une opération non valide comme ZeroDivide }
{ ----------- classe TCalculette ----------- }
procedure TCalculette.FormCreate(sender: TObject); { l'instance calc de TCalculette créée à l'exécution du programme s'instancie un calculeur de classe TCalculateur, c'est en effet lui qui réalisera les calculs }
begin
calculeur:=TCalculateur.Create; { instance de TCalculateur qui réalise les calculs }
end;
procedure TCalculette.FormClose(sender: TObject; var Action: TCloseAction);
begin
calculeur.Free; { libère la mémoire allouée pour l'instance de TCalculateur }
end;
procedure TCalculette.Affiche(chaine: string; nbdecimales: byte = 9);
var indicedec : byte; { indice de la position de la virgule, pour tronquer }
begin
indicedec := ansipos(',',chaine);
if indicedec>0 then { tronque le nombre s'il y a plus de nbdecimales décimales }
chaine := copy(chaine,1,indicedec+nbdecimales);
if StrToFloat(chaine)=OpInvalide then { division par zéro }
chaine := 'invalide';
LabelResultat.caption := chaine+' '; { décalage du bord droit de l'écran }
end;
procedure TCalculette.InterceptClavier(sender: TObject; var key: Word; shift: TShiftState);
begin
case key of
VK_ESCAPE { échappement } : BoutonOffClick(calc.BoutonOff);
VK_BACK { retour arrière }, VK_DELETE { suppr } : BoutonClearClick(calc.BoutonClear);
VK_NUMPAD9 { pavé num 9 } : Affiche(calculeur.GereChiffre('9'));
VK_NUMPAD8 { pavé num 8 } : Affiche(calculeur.GereChiffre('8'));
VK_NUMPAD7 { pavé num 7 } : Affiche(calculeur.GereChiffre('7'));
VK_NUMPAD6 { pavé num 6 } : Affiche(calculeur.GereChiffre('6'));
VK_NUMPAD5 { pavé num 5 } : Affiche(calculeur.GereChiffre('5'));
VK_NUMPAD4 { pavé num 4 } : Affiche(calculeur.GereChiffre('4'));
VK_NUMPAD3 { pavé num 3 } : Affiche(calculeur.GereChiffre('3'));
VK_NUMPAD2 { pavé num 2 } : Affiche(calculeur.GereChiffre('2'));
VK_NUMPAD1 { pavé num 1 } : Affiche(calculeur.GereChiffre('1'));
VK_NUMPAD0 { pavé num 0 } : Affiche(calculeur.GereChiffre('0'));
VK_DECIMAL { pavé num . } : Affiche(calculeur.GereChiffre(','));
VK_DIVIDE { pavé num / } : Affiche(calculeur.Operation('/'));
VK_MULTIPLY { pavé num * } : Affiche(calculeur.Operation('*'));
VK_SUBTRACT { pavé num - } : Affiche(calculeur.Operation('-'));
VK_ADD { pavé num + } : Affiche(calculeur.Operation('+'));
VK_SEPARATOR { pavé num entrée }, VK_RETURN { entrée } : Affiche(FloatToStr(calculeur.Execute),3);
end;
end;
procedure TCalculette.BoutonOffClick(sender: TObject);
begin
close;
end;
procedure TCalculette.BoutonClearClick(sender: TObject);
begin
calculeur.Clear;
Affiche('0');
end;
procedure TCalculette.AppuiSurChiffre(sender: TObject);
begin
Affiche(calculeur.GereChiffre((sender as TButton).caption));
end;
procedure TCalculette.AppuiSurOperateur(sender: TObject);
var key: char;
begin
key := (sender as TButton).caption[1];
case key of
'F','?' : Affiche(FloatToStr(calculeur.Conversion(key)),2); { deux décimales maximum }
'+','-','*','/': Affiche(calculeur.Operation(key));
'=' : Affiche(FloatToStr(calculeur.Execute),3); { trois décimales maximum }
end;
end;
{ ----------- classe TCalculateur ----------- }
constructor TCalculateur.Create;
begin
inherited;
self.Clear;
end;
procedure TCalculateur.Clear;
begin
Op1 := 0;
Op2 := 0;
NbOp := 0;
Operateur := #0;
EntreeActuelle := '';
end;
function TCalculateur.GereChiffre(chaine: string): string;
begin
if chaine = ',' then begin
if EntreeActuelle = '' then { l'utilisateur n'a pas entré le "0" pour un 0<nombre<1 }
EntreeActuelle := '0,';
if ansipos(',',EntreeActuelle) <> 0 then { ne pas mettre une deuxième virgule }
chaine := '';
EntreeActuelle := EntreeActuelle+chaine;
end else if (EntreeActuelle='') or (EntreeActuelle='0') then begin { ne pas écrire 00000... }
if chaine='000' then
chaine := '0';
EntreeActuelle := chaine;
end else begin
EntreeActuelle := EntreeActuelle+chaine;
end;
result := EntreeActuelle;
end;
function TCalculateur.Operation(chaine: string): string;
begin
inc(NbOp); { la saisie de la nouvelle opérande est terminée }
if EntreeActuelle='' then { l'utilisateur n'a entré aucun chiffre }
EntreeActuelle := '0';
case NbOp of
2 : Op1 := Execute;
1 : Op1 := StrToFloat(EntreeActuelle);
else Op1 := 0;
end;
Operateur := chaine[1];
result := FloatToStr(Op1);
EntreeActuelle := ''; { on réinitialise l'opérande en cours de saisie }
end;
function TCalculateur.Conversion(devise: char): extended;
var indicedec : byte; { indice de la position de la virgule, pour tronquer }
begin
if EntreeActuelle='' then { l'utilisateur n'a entré aucun chiffre }
EntreeActuelle := '0';
Op2 := StrToFloat(EntreeActuelle); { la saisie de la deuxième opérande est terminée }
case devise of
'F' : result := Op2*RapportEuroFranc; { conversion euro->franc }
'?' : result := Op2/RapportEuroFranc; { conversion franc->euro }
end;
EntreeActuelle := FloatToStr(result); { le résultat est l'opérande d'un prochain calcul }
Operateur := #0;
indicedec := ansipos(',',EntreeActuelle);
if indicedec>0 then { tronque le nombre s'il y a plus de 2 décimales }
EntreeActuelle := copy(EntreeActuelle,1,indicedec+2);
end;
function TCalculateur.Execute: extended;
begin
Op2 := StrToFloat(EntreeActuelle); { la saisie de la deuxième opérande est terminée }
if NbOp>0 then begin
dec(NbOp);
case Operateur of
'+' : result := Op1+Op2;
'-' : result := Op1-Op2;
'*' : result := Op1*Op2;
'/' : begin
if Op2=0 then begin { évite de diviser par zéro }
self.Clear;
result := OpInvalide; { nombre choisi arbitrairement pour détecter l'erreur }
Exit;
end else
result := Op1/Op2;
end;
end;
EntreeActuelle := FloatToStr(result); { le résultat est l'opérande d'un prochain calcul }
Operateur := #0;
end;
end;
end.