Here's one I prepared earlier :).
I originally posted this RPN calculator to batkins' Tk wiki before it got spamblatted. This formed a tutorial in using the grid geometry manager, which unfortunately seems to have been lost. darned spammers :(.
Reverse Polish Notation syntax is easier for computers to deal with, and is easier to code. The Tk display and buttons would be the same for an algebraic calculator - converting this calculator to algebraic is left as an exercise for the reader.
#!/usr/local/bin/perl
use strict;
use warnings;
use Tk;
my $main = MainWindow->new;
my $disp = $main->Label(-text => 0)
->grid('-','-','-',-sticky => 'e');
my %button;
for (0..9,qw!. + - * / En C!) {
$button{$_} = $main->Button(
-text => $_,
-command => [\&click, $_] );
}
$button{C}->grid($button{'/'},$button{'*'},$button{'-'},-sticky=>'nsew
+');
$button{7}->grid($button{8},$button{9},$button{'+'},-sticky=>'nsew');
$button{4}->grid($button{5},$button{6},'^',-sticky=>'nsew');
$button{1}->grid($button{2},$button{3},$button{En},-sticky=>'nsew');
$button{0}->grid('-',$button{'.'},'^',-sticky=>'nsew');
$main->gridColumnconfigure($_, -weight => 1) for (0..3);
$main->gridRowconfigure($_, -weight => 1) for (0..5);
MainLoop;
# Main scoped variables used to keep track of calculator status
my @stack;
my $current; # holds partial number being entered as string
sub click {
local $_ = shift;
# Handle number entry - append to $current
if (/\d|\./) {
defined($current) ? ($current .= $_) : ($current = $_);
# Clear key - first click, clear $current
# second click, clear @stack
# third click, calculator off
} elsif (/C/) {
defined($current) ? undef($current) :
@stack ? (@stack=()) : $main->destroy;
# Any other key, move $current to stack and process
} else {
{
no warnings; # to handle the case when the user has
+
# pushed '.' more than once
push @stack, $current+0 if defined($current) || !@stac
+k;
}
undef $current;
/\+/ and (@stack-1) ? push @stack,(pop(@stack) + pop(@stack))
: push @stack, 2*(pop @stack);
/-/ and (@stack-1) ? push @stack,-(pop(@stack) - pop (@stack))
: push @stack, -(pop @stack);
/\*/ and (@stack-1) ? push @stack,(pop(@stack) * pop (@stack))
: push @stack, (pop @stack)**2;
/\// and (@stack-1) ? push @stack,1/(pop(@stack) / pop (@stack
+))
: push @stack, 1/(pop @stack);
}
$disp->configure( -text => defined($current) ? $current :
@stack ? $stack[-1] : 0);
}
--
Oh Lord, won’t you burn me a Knoppix CD ?
My friends all rate Windows, I must disagree.
Your powers of persuasion will set them all free,
So oh Lord, won’t you burn me a Knoppix CD ?
(Missquoting Janis Joplin)