HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Quadratic Functions Calculator/Table (Simple console app)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
simpleappconsolefunctionsquadraticcalculatortable

Problem

Built so that it doesn't depend on DLLs: http://s000.tinyupload.com/?file_id=25464905355948914118

My goal is to make a console calculator with a subset of the functions that are available on a scientific calculator. This source is WIP, the dependencies that are used by this are the ones that Visual Studio 2015 gives you when you create a Win32 console app.

```
// MathFunction_Table.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include
#include

using namespace std;
//string to integer variables
string astr, bstr, cstr, r1str, r2str, stepsstr;
int a, b, c, r1, r2;
int step = 0; //steps are on 0 by default
//
//variables
int x;
string selection;
//

int main() {
// while (true) Makes sure that it doesn't exit console application unless the user intends to
while (true) {
system("cls");
cout ";
getline(cin, selection);

if (selection == "quit") {
break;
}

else if (selection == "q") {
//quadratic
system("cls");
cout ";
//user input for a
getline(cin, astr);
a = atoi(astr.c_str()); // atoi(astr.c_str()); is just a function I use to convert from string to int
cout ";
//
//user input for b
getline(cin, bstr);
b = atoi(bstr.c_str());
cout ";
//
//user input for c
getline(cin, cstr);
c = atoi(cstr.c_str());
//
//user input 2 numbers for a range of X values
while (true) {
cout x R2 )\n"
"\n"
"\t R1 must be greater than R2. \n"
"\n"
"\n \t R1 --> ";
//range
getline(cin, r1str);
r1 = atoi(r1str.c_str());
cout ";
getline(cin, r2str);
r2 = at

Solution

Your code has several issues that make it very hard to read.

Remove stdafx.h

Remove the #include "stdafx.h" line as that is a Windows-only precompiled header which hampers portability. Also, you aren't using any of the functionality inside that header.

Remove the global variables

//string to integer variables
string astr, bstr, cstr, r1str, r2str, stepsstr;
int a, b, c, r1, r2;
int step = 0; //steps are on 0 by default
//
//variables
int x;
string selection;
//


All of these variables are NOT necessary to have as global variables. You should always declare your variables in the smallest scope possible. This allows you to take advantage of C++'s resource management effectively while allowing you (or the programmer reading your code) to more easily identify the variables. I found myself having to scroll up and down many times throughout your code to remember what was declared where. It also has the nice effect of not cluttering the global namespace with variables.

Main function and if-elseif-else

I generally believe that the main function should be as small as possible while handling most of the I/O requests of a program. In this case, your main function houses all of the logic of the program which isn't a good thing. You can split up your main into a switch statement and have each case call a helper function to do the heavy lifting. Also, you use the following logic a lot in your program:

read an integer from input and store it in a string. Convert the string to a number

Why not wrap this up into a function?

int GetUserNum(istream &is = std::cin)
{
    string val;
    getline(is, val);
    is.ignore();
    return stoi(val);
}


You also have what's called "spaghetti logic" with all those continue and break statements. These should be replaced with do-while loops that keep prompting the user for new values if some condition isn't met. Finally, your quadratic table printing is unnecessarily complicated and filled with bugs. For example, it seems that your steps variable is to allow the x value to be incremented by some user-defined number yet you're letting x be incremented every time by the loop. This will cause you to miss some steps on the graph. Moreover, you never actually check whether r1 is cleanly divisible by steps in your code. You can express your table drawing logic in a single small loop.

for (int x = r2; x <= r1; x += steps) {
     cout << (a * x * x) + (b * x) + c << "\n";
}


After cleaning up the code a bit, your general program logic could then be this:

int GetUserNum(istream &is = std::cin)
{
    string val;
    getline(is, val);
    is.ignore(); // needed for multiple istream reads
    return stoi(val);
}

// TODO: implement
void HandleLinear()
{

}

void PrintQuadraticTable(int r1, int r2, int steps, int a, int b, int c)
{
    for (int x = r2; x  R2\n";
        r1 = GetUserNum();

        cout << "R2?\n";
        r2 = GetUserNum();
    } while (r1 <= r2);

    int steps = 0;
    do {
        cout << "Steps? Make sure steps divides cleanly into R1.\n";
        steps = GetUserNum();
    } while (r1 % steps != 0);

    PrintQuadraticTable(r1, r2, steps, a_val, b_val, c_val);
}

int main()
{
    while (true) {
        /* Give user some prompt */
        string answer;
        getline(cin, answer);
        switch (answer) {
        default:
            cout << "Invalid option!\n";
            return 1;
        case "quit":
            cout << "Quitting\n";
            return 0;
        case "l":
            HandleLinear();
            break;
        case "q":
            HandleQuadratic();
            break;
        }
    }
}


Notice that by having a few helper functions around, we were able to:

  • Get rid of duplicate code



  • Remove many unnecessary comments by giving functions good, descriptive names



  • Organize our code into logical units



  • Keep the main function clutter-free and allow the reader to have a better idea of the high-level logic of the program.



  • Get rid of all the global values and allow us to declare variables only when we needed to.

Code Snippets

//string to integer variables
string astr, bstr, cstr, r1str, r2str, stepsstr;
int a, b, c, r1, r2;
int step = 0; //steps are on 0 by default
//
//variables
int x;
string selection;
//
int GetUserNum(istream &is = std::cin)
{
    string val;
    getline(is, val);
    is.ignore();
    return stoi(val);
}
for (int x = r2; x <= r1; x += steps) {
     cout << (a * x * x) + (b * x) + c << "\n";
}
int GetUserNum(istream &is = std::cin)
{
    string val;
    getline(is, val);
    is.ignore(); // needed for multiple istream reads
    return stoi(val);
}

// TODO: implement
void HandleLinear()
{

}

void PrintQuadraticTable(int r1, int r2, int steps, int a, int b, int c)
{
    for (int x = r2; x <= r1; x += steps) {
        cout << (a * x * x) + (b * x) + c << "\n";
    }
}

void HandleQuadratic()
{
    cout << "A value?\n";
    int a_val = GetUserNum();

    cout << "B value?\n";
    int b_val = GetUserNum();

    cout << "C value?\n";
    int c_val = GetUserNum();

    int r1 = 0, r2 = 0;
    do {
        cout << "R1? Make sure R1 > R2\n";
        r1 = GetUserNum();

        cout << "R2?\n";
        r2 = GetUserNum();
    } while (r1 <= r2);

    int steps = 0;
    do {
        cout << "Steps? Make sure steps divides cleanly into R1.\n";
        steps = GetUserNum();
    } while (r1 % steps != 0);

    PrintQuadraticTable(r1, r2, steps, a_val, b_val, c_val);
}

int main()
{
    while (true) {
        /* Give user some prompt */
        string answer;
        getline(cin, answer);
        switch (answer) {
        default:
            cout << "Invalid option!\n";
            return 1;
        case "quit":
            cout << "Quitting\n";
            return 0;
        case "l":
            HandleLinear();
            break;
        case "q":
            HandleQuadratic();
            break;
        }
    }
}

Context

StackExchange Code Review Q#115090, answer score: 4

Revisions (0)

No revisions yet.