Part 2 of this question. I've rewritten most parts of the code, for the better I hope. The code now has some more logic and less readability.
Functions included in the calculator:
Addition
User input2+2
Program output4
Subtraction
User input2-2
Program output0
Multiplication
User input2*2
Program output4
Division
User input2/2
Program output1
Exponentiation
User input2^2
Program output4
#include <iostream>
#include <string>
#include <sstream>
#include <Windows.h>
#include <cmath>
class Math_Functions
{
public:
double addition(double, double);
double subtraction(double, double);
double multiplication(double, double);
void division(double, double);
void exponentiation(double, double);
} math;
class Results_Handler
{
public:
void division(std::string);
void exponentiation(std::string);
} res_handler;
//This function I found somewhere in the deep internet
class Miscellaneous
{
public:
void Pause()
{
std::cout << std::endl << "Press any key to continue . . . ";
std::cin.sync();
std::cin.ignore();
}
void ClearScreen()
{
HANDLE hStdOut;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD count;
DWORD cellCount;
COORD homeCoords = { 0, 0 };
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut == INVALID_HANDLE_VALUE) return;
/* Get the number of cells in the current buffer */
if (!GetConsoleScreenBufferInfo(hStdOut, &csbi)) return;
cellCount = csbi.dwSize.X *csbi.dwSize.Y;
/* Fill the entire buffer with spaces */
if (!FillConsoleOutputCharacter(
hStdOut,
(TCHAR) ' ',
cellCount,
homeCoords,
&count
)) return;
/* Fill the entire buffer with the current colors and attributes */
if (!FillConsoleOutputAttribute(
hStdOut,
csbi.wAttributes,
cellCount,
homeCoords,
&count
)) return;
/* Move the cursor home */
SetConsoleCursorPosition(hStdOut, homeCoords);
}
} misc;
//Handle the result from division and cout correspondingly
void Results_Handler::division(std::string inPut)
{
if (inPut != "Error")
{
std::cout << inPut;
}
else
{
std::cout << "Come on, you know you can't divide by 0...";
}
}
//Handle the result from the exponentiation and cout correspondingly
void Results_Handler::exponentiation(std::string inPut)
{
if (inPut != "Error")
{
std::cout << inPut;
}
else
{
std::cout << "You can't exponentiate by negative numbers.";
}
}
double Math_Functions::addition(double a, double b)
{
return a + b;
}
double Math_Functions::subtraction(double a, double b)
{
return a - b;
}
double Math_Functions::multiplication(double a, double b)
{
return a * b;
}
void Math_Functions::division(double a, double b)
{
//Dividing by 0 = universe explodes
if (b == 0)
{
res_handler.division("Error");
}
else
{
double c = a / b;
std::stringstream result;
result << c;
res_handler.division(result.str());
}
}
void Math_Functions::exponentiation(double a, double b)
{
//If the number you're exponentiating with is 0 the result is always 1
if (b == 0)
{
res_handler.exponentiation("1");
}
//If you're exponentiating with 1 the result is the same number
else if (b == 1)
{
std::stringstream res;
res << a;
res_handler.exponentiation(res.str());
}
else
{
std::stringstream res;
res << pow(a, b);
res_handler.exponentiation(res.str());
}
}
int main()
{
//Declare variables
double a, b;
char function;
std::string line;
while (true)
{
misc.ClearScreen();
std::getline(std::cin, line);
//Check if the input is empty and ignore
if (line.empty())
{
continue;
}
//Check if the input is either 'q' or 'Q' and break loop
else if (line[0] == 'q' || line[0] == 'Q')
{
break;
}
//Else if everything is OK extract data
else
{
std::istringstream inStream(line);
inStream >> a;
inStream >> function;
inStream >> b;
//Check for bad input and print error
if (!inStream || function != '+' && function != '-' && function != '*' && function != '/' && function != '^')
{
std::cerr << "\"" << line << "\" is invalid input";
}
}
//Check what the user wants to do
switch (function)
{
case '+': std::cout << math.addition(a, b); break;
case '-': std::cout << math.subtraction(a, b); break;
case '*': std::cout << math.multiplication(a, b); break;
case '/': math.division(a, b); break;
case '^': math.exponentiation(a, b); break;
}
misc.Pause();
}
return 0;
}
-
\$\begingroup\$ The request for a library is not on-topic here, nor is it anywhere on SE. You may just have to search for something yourself and try to implement it here. \$\endgroup\$Jamal– Jamal2015年01月20日 14:33:22 +00:00Commented Jan 20, 2015 at 14:33
1 Answer 1
The singleton pattern:
Your classes Math_Functions
, Results_Handler
and Miscellaneous
seem like an attempt at the singleton pattern (see 1 and 2). Your approach of declaring a global instance of each class is also valid, but has a few drawback and is not very conventional.
Since your classes hold no member data and the class is really just serving as a name space for the functions, I would use an actual namespace
instead and don't even bother with a full-blown singleton implementation in this case. Example:
namespace math
{
double addition(double, double);
double subtraction(double, double);
double multiplication(double, double);
void division(double, double);
void exponentiation(double, double);
} // namespace
Then to access each function you now have to use the ::
(namespace resolution) operator: math::addition(a, b);
Miscellaneous tips:
Keep parameter names in function prototypes. This adds to the code documentation.
Be consistent with your naming convention. You have both
PascalCase
andcamelCase
names for functions/methods. Choose one and use it consistently.Functions from
<cmath>
, such aspow()
, should be accessed using the fully qualified name with thestd::
prefix. I.e.:std::pow()
.Consider splitting your project in a few separate source files. There is quite a bit of code here already to be kept all in the same source file. You should ideally place each class in its own
.cpp/.h
pair.Returning zero at the end of
main
is optional. If you don't do it explicitly, the compiler will default to areturn 0
.
-
\$\begingroup\$ I really want to separate the code in different files, but the problem is I don't know how (yet). I can include other
.cpp
files in the main, but this way it doesn't make much sense to me. Thanks for the guidelines :) \$\endgroup\$skorpi7478– skorpi74782015年01月20日 17:52:59 +00:00Commented Jan 20, 2015 at 17:52 -
\$\begingroup\$ @skorpi7478, Well, take a look at how to do that in your IDE/compiler. You will then have the class implementation in a .CPP file and the declaration in a header file (.H); Then you include the .H in your other sources files, such as in main.cpp. \$\endgroup\$glampert– glampert2015年01月20日 18:01:59 +00:00Commented Jan 20, 2015 at 18:01