Journal of computing related issues for Web Authoring, and general topics using Mac, Windows and Linux platforms.

Sunday, July 15, 2007

C++ Calculator Prog Mod 5 with input checking for valid number






// kalk-05.cpp
//
// Calculator program that runs in console.
// Type M for menu.
//
// This is the original from PSW book Using C++
// I have used it as a basis to learn C++
//
// I have kept is at the following modifications will
// be easier to understand as the program becomes more sophisticated.
//
// Mods
// 01 Change command short cuts to alpha characters so that they are simple to
// key. Trivial change.
// 02 Add extra functions again trivial.
// 03 Add Memory functions
// MEM IN .. loads memory with current value
// MEM PLUS .. adds current value to memory
// Note: Mem Minus achieved by typing n (negative) to make current
// value negative and MEM PLUS. If required redo n to make current
// value positive.
// MEM SWITCH switches current value and memory.
// 03a Added code to change negative current value to positive when
// Power function AND exponent is less than 1 (e.g. 0.5 for square root)
// as even roots of negative numbers are imaginary
// 04 Add capability to use mem value in function, e.g. to subtract value in
// in memory from current value, but keep memory value.
// This was a bit complicated and required writing function to replace CIN
// and use of STRING to DOUBLE function
// 05 Improve by checking that values entered are numbers and not garbage.
//
// Planned mods
// 06 Capability to undo up to last 5 commands. Code with Vector?
// 07 Log comands to file so that they can be audited.
// Have default log KALKLOG.DAT in C:|MyDATA which is backed up to
// KALKLOG.BAK start of new program, overwriting previous version.
// 08 Allow user to change log file name and locaton.
// 09 Take data file in LOG format and run as batch program.
//
// Also plan to use as test for compiling in Linux and with other systems.
// May try to convert to Java and Ruby??
// When I have learned widows programming may try to convert to windows type.
//
// I know it is all old hat but it helps me to learn and may even help others.
//

#include <iostream>
#include <iomanip>
#include <cmath>
#include <cctype>
#include <string>
using namespace std;

void display_menu();
// int is_menu_choice(char choice);
void process_choice (char choice, // IN
double& num, // IN-OUT
double& mem); // IN-OUT
void cin_number(double& num, // IN-OUT
double& mem); // IN-OUT
char RT_Num_Check(string& digit);

int main()
{
char choice; // menu choice
double curr_val; // current value of calculator
double mem; // Calculator Mem function

display_menu();
cout << setprecision(15);
curr_val = 0;
mem = 0;

do {
cin >> choice;
choice = toupper(choice);
process_choice (choice, curr_val, mem);
}
while (choice != 'Q');
return 0;
}

void display_menu()
{
cout << "Calculator functions:\n"
<< " (A)add, (S)ubtract X(mult), (D)ivide , (N)egative,\n"
<< " (R)eciprocal, (I)nitialize, (P)ower [positive only], Q)uit,\n"
<< " (M)em in, mem p(L)us, mem (O)ut, mem s(W)itch \n"
<< " use mem to refer to memory in calculations"
<< " (H)elp show this menu again.\n\n";
}

void process_choice (char choice, // IN
double& curr_val, // IN-OUT
double& mem) // IN-OUT

{
// double mem;
double work; // required for memory sWitch function
double num; // numeric value entered by user
num = 0;
// mem=0;
switch (choice)
{
case 'A': cin_number(num, mem);
curr_val += num;
break;
case 'D': cin_number(num, mem);
curr_val = curr_val/num;
break;
case 'H': break;
case 'I': cin_number(num, mem);
curr_val = num;
break;
case 'L': mem += curr_val;
break;
case 'M': mem = curr_val;
break;
case 'N': curr_val *= (-1);
break;
case 'O': curr_val = mem;
break;
case 'P': cin_number(num, mem);
if (num < 1) curr_val = fabs(curr_val);
//stops possibilty roots of negative values causing errors
curr_val = pow(curr_val, num);
break;
case 'Q': break;
case 'R': curr_val = 1/curr_val;
break;
case 'S': cin_number(num, mem);
curr_val -= num;
break;
case 'W': work = curr_val;
curr_val = mem;
mem = work;
break;
case 'X': cin_number(num, mem);
curr_val *= num;
break;
default: cout << "\tInvalid operation!\n";
} // end switch
if (choice=='H') display_menu();
if (choice != ('Q' || 'H' ))
cout << setw(16) << ' ' << curr_val
<< endl;
}

void cin_number(double& num,
double& mem) // IN-OUT
{
string input;
char ValidNumber = 'N';
while (ValidNumber == 'N')
{
cin >> input;
if (input == "mem")
{
num = mem;
ValidNumber = 'Y';
}
else
{
ValidNumber=RT_Num_Check(input);
if (ValidNumber=='Y')
num = strtod(input.c_str(), NULL);
else
{
cout << input <<" Not a proper number\n Re-enter number\n";
}
}
}
return;

}
char RT_Num_Check(string& digit)
{
char NumOK; // result
int p; // digit position
char decimal = 'N'; // used to make sure not more than 1 decimal point
string sign = "0"; // used to check for negative
// cout << "The length of str is " << digit.length() << " characters.\n";
if (digit.substr(0,1) == "-") // sign -1
{
digit=digit.substr (1,(digit.length()-1)); // strip sign
sign= "-"; // to check so that neg restored at end
}
for (p=0;p<digit.length();p++)
{

if ((digit.substr(p,1) >="0") && (digit.substr(p,1) <="9"))
NumOK='Y';
else
{
if ((digit.substr(p,1) ==".") && (decimal=='N'))
{
NumOK='Y';
decimal='Y'; // so that later positions checked for erraneous 2nd decimal point
}
else
{
NumOK='N'; // if we reach here must be an incorrect number
break;
}
}
// cout <<"p is " <<p<< " number is "<< digit.substr(p,1)<<endl;
}

if (sign == "-")
digit = sign+digit; // put back negative if necessary
return (NumOK);

}


/*A typical run:

Calculator functions:\n"
(A)add, (S)ubtract X(mult), (D)ivide , (N)egative,\n"
(R)eciprocal, (I)nitialize, (P)ower, Q)uit,\n"
(H)elp show this menu again.\n\n";

I 2.5
2.5
P 3
15.625
R
0.064
x 100
6.4
n
-6.4
a 10
3.6
s 1.12
2.48
H
Calculator functions:\n"
(A)add, (S)ubtract X(mult), (D)ivide , (N)egative,\n"
(R)eciprocal, (I)nitialize, (P)ower, Q)uit,\n"
(H)elp show this menu again.\n\n";

2.48
d 2.5
0.992
i 4
4
p 0.5
2
n
-2
p 0.5
1.4142135623731
i10
10
m
10
r
0.1
w
10
o
0.1
x1000
100
l
100
l
100
o
200.1
i 2
2
m
2
i5
5
amem
7
p mem
49
d mem
24.5
a 5..2
5..2 Not a proper number
Re-enter number
5.2
29.7
q

------------------------

Note you do not need to leave space,
e.g. you can enter "d 2.5" or "d2.5"

*/




No comments:

About Me

Husband, dad and grandad. Physics graduate from London University in late 60s. Retired from IBM company in 2000 after 27 years as both Sytems Engineer and Salesman. Interests include photography, nature, science, maths, walking, travel. I like facts as a basis of opinion and not opinion that is assumed to be fact.