3
\$\begingroup\$

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 input 2+2 Program output 4

  • Subtraction
    User input 2-2 Program output 0

  • Multiplication
    User input 2*2 Program output 4

  • Division
    User input 2/2 Program output 1

  • Exponentiation
    User input 2^2 Program output 4

#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;
}
asked Jan 20, 2015 at 12:52
\$\endgroup\$
1
  • \$\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\$ Commented Jan 20, 2015 at 14:33

1 Answer 1

1
\$\begingroup\$

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 and camelCase names for functions/methods. Choose one and use it consistently.

  • Functions from <cmath>, such as pow(), should be accessed using the fully qualified name with the std:: 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 a return 0.

answered Jan 20, 2015 at 17:07
\$\endgroup\$
2
  • \$\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\$ Commented 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\$ Commented Jan 20, 2015 at 18:01

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.