Show My First Project: A Complete and Intelligent Calculator

D

Deleted member 205

Guest
Awesome. Great work for a small Project to practice C++.

While I am not a C++ Programmer, I can offer some advice for improving the Style of your Code and making it more readable.

First of, is putting a line between your Headers and your main() Function. What I mean is this:
Code:
#include <iostream>
#include <stdlib.h>
#include "func.h"

int main()
Instead of this:
Code:
#include <iostream>
#include <stdlib.h>
#include "func.h"
int main()
Also, I've noticed big empty gaps in the code. This is around lines 91 and 99, which also contain a Note in the middle. I would discourage from having massive gaps as it just doesn't look right and it means that people need to scroll more when reviewing your Code.

Also, maybe start separating Loops and Conditions. Look at this bit:
Code:
while (std::cin.fail())
                    {
                        std::cout << "Input Y or N" << std::endl;
                        std::cin.clear();
                        std::cin.ignore(256, '\n');
                        std::cin >> operation_Switch_Setting;
                    }
                    if (operation_Switch_Setting == "Y" || operation_Switch_Setting == "y") //checks for yes option
                    {   
                        std::cout << "+ for add, - for subtract, * for multiply, / for divide, and % for modulus. Type one to choose operator" << std::endl;
                        std::cin >> operation_Setting;
                        if (operation_Setting == "+")                 // Way too many if checks, maybe could be shortened
                        {
                            std::cout << "Give another number to add to your previous result, " << past_Output << ":" << std::endl;
                            std::cin >> after_Num;
                            present_Output = add(past_Output, after_Num);
                            std::cout << present_Output << std::endl;
                            didOneOperation = true;
                            past_Output = present_Output;
                            present_Output = 0;
                        }
The While-Loop and the If-Statement do not have an empty line in between them. While there is a brace in the middle of them, it's still better to have an empty line between that If-Statement and that ending-brace.

Also, I've found that your If-Statements and Loops start getting deeply nested and even found a Comment that reaches 200-Columns. First of all, try to avoid nesting your Code so deep. While the nesting isn't bad and doesn't cause an issue, it can if you continue to nest deeper. So, remember that.

As for that Comment that reaches 200-Columns, try to stop your lines from reaching that length. A lot of Coding-Styles advise you or maybe even require you to have your Line-Length at 80, 100, 120 etc. And they usually don't go beyond 120 Columns. Avoid long lines because what happens if a Developer like yourself is working using a vertical-monitor? That one line will end up going off the screen which can be annoying as you don't want your Code going out of view.

This is all of the advice that I can offer for helping to make your Code more readable and better. Take it and it can prove beneficial to writing good Code.

wboycher said:
Also how many people are on this forum? Just wondering.
Well, you're actually the 250th Member, so congrats.
 

williamdev

Coder
Dec 21, 2019
33
15
9
Baton Rouge, Louisiana
Also, I've found that your If-Statements and Loops start getting deeply nested and even found a Comment that reaches 200-Columns. First of all, try to avoid nesting your Code so deep. While the nesting isn't bad and doesn't cause an issue, it can if you continue to nest deeper. So, remember that.

As for that Comment that reaches 200-Columns, try to stop your lines from reaching that length. A lot of Coding-Styles advise you or maybe even require you to have your Line-Length at 80, 100, 120 etc. And they usually don't go beyond 120 Columns. Avoid long lines because what happens if a Developer like yourself is working using a vertical-monitor? That one line will end up going off the screen which can be annoying as you don't want your Code going out of view.
So how do you advise that I fix the nesting? Should I use functions? I took your other feedback and I will use it next time since it is straight to the point but I just don’t know how I would fix nesting. Could I remove some pointless if and while loops since I have read my code and I have found a few useless if loops already. I was implementing a while loop for the first chunk of code separated by the large gap that you talked about. It is controlled by a while(check_Stop > 0) loop and the point of it was to filter out unwanted inputs. But std::cin.fail() does that just fine, so I can definitely cut out that while loop. This feedback will definitely help, and I’ll get back with a revised version of it later.
 
Last edited:
D

Deleted member 205

Guest
wboycher said:
So how do you advise that I fix the nesting? Should I use functions?
Well, you can't generally fix nesting. Besides, all Programmers like myself do it. Although, I mean, I think you should've split-up the Code into smaller Functions in the main file.

There generally seems to be a world-wide rule in Programming and it's that Functions(Procedural and Functional) or Methods(Object-Oriented), should not be just one large block of Code. Programmers seem to prefer and generally want their Code and the Code of others to be split-up into Functions which each do their own task. Then when it's time, the Function can then be called.

Going back to nesting, you can't really fix it unless your doing a Code cleanup. Again, a lot of Programmers around the world and myself do it. Even Bjarne Stroustrup(C++ Creator) and Dennis Ritchie(C Creator) are both guilty of it. The only thing to do when it comes to nesting is just avoid nesting too deep. Preferably, don't go further than 3 levels. More than that and you're going too deep.
 

williamdev

Coder
Dec 21, 2019
33
15
9
Baton Rouge, Louisiana
Ok here's the new code! I think I did this correctly, there is no nesting and none of the code goes outside my code view, and it works the same as before.
Neatly Formatted Calculator:
#include <iostream>
#include <stdlib.h>
#include "func.h"

int main()
{
    int first_Num; //Your First Number
    int second_Num; //Your Second Number
    int after_Num; //Your Other Number to apply to the previous result with a given operator ex: 2+2 = 4 + 10 <- this is the after_num
    std::string operation_Setting; //the setting for which operator you want to use
    std::string operation_Switch_Setting; //the setting for continuing to operate on to previous result, prompted after every operation
    int check_Stop = 10; //check_Stop is used to stop the while loop if the user declines the option to add, subtract, multiply, divide, or modulus the previous result by a subsequently given number.
    int past_Output; //previous output
    int present_Output; //current output
    bool didOneOperation = false; //to check if the program can prompt the user to operate on previous result, is set to true after you do one operation with the first_Num and second_Num

    first_Num_Prompt(first_Num);
    operation_Setting_input(operation_Setting);
    while (didOneOperation != true)
    {
        second_Num_Prompt_add(second_Num, first_Num, past_Output, didOneOperation, operation_Setting);
        second_Num_Prompt_subtract(second_Num, first_Num, past_Output, didOneOperation, operation_Setting);
        second_Num_Prompt_divide(second_Num, first_Num, past_Output, didOneOperation, operation_Setting);
        second_Num_Prompt_multiply(second_Num, first_Num, past_Output, didOneOperation, operation_Setting);
        second_Num_Prompt_modulus(second_Num, first_Num, past_Output, didOneOperation, operation_Setting);
    }

    while(didOneOperation == true)
    {
        operation_Switch_Setting_input(operation_Switch_Setting);

        if (operation_Switch_Setting == "Y" || operation_Switch_Setting == "y")
        {
            operation_Setting_input(operation_Setting);
            add_Onto(past_Output, present_Output, after_Num, didOneOperation, operation_Setting);
            subtract_From(past_Output, present_Output, after_Num, didOneOperation, operation_Setting);
            multiply_By(past_Output, present_Output, after_Num, didOneOperation, operation_Setting);
            divide_By(past_Output, present_Output, after_Num, didOneOperation, operation_Setting);
            modulus_By(past_Output, present_Output, after_Num, didOneOperation, operation_Setting);
        }

        else if (operation_Switch_Setting == "N" || operation_Switch_Setting == "n")
        {
            std::cout << "Ok, shutting down...";
            abort;
            exit;
            return 0;

        }
    }
}
 
Last edited:
  • Like
Reactions: Deleted member 205

williamdev

Coder
Dec 21, 2019
33
15
9
Baton Rouge, Louisiana
And the func.h...
func.h:
#pragma once
void add_Onto(int& past, int& present, int& after, bool& Operate, std::string& setting)
{
    if (setting == "+")
    {
        std::cout << "Give another number to add to your previous result, " << past << ":" << std::endl;
        std::cin >> after;
        present = past + after;
        std::cout << present << std::endl;
        Operate = true;
        past = present;
        present = 0;
    }
}

void subtract_From(int& past, int& present, int& after, bool& Operate, std::string& setting)
{
    if (setting == "-")
    {
        std::cout << "Give another number to subtract from your previous result, " << past << ":" << std::endl;
        std::cin >> after;
        present = past - after;
        std::cout << present << std::endl;
        Operate = true;
        past = present;
        present = 0;
    }
}

void multiply_By(int& past, int& present, int& after, bool& Operate, std::string& setting)
{
    if (setting == "*")
    {
        std::cout << "Give another number to multiply by your previous result, " << past << ":" << std::endl;
        std::cin >> after;
        present = past * after;
        std::cout << present << std::endl;
        Operate = true;
        past = present;
        present = 0;
    }
}

void divide_By(int& past, int& present, int& after, bool& Operate, std::string& setting)
{
    if (setting == "/")
    {
        std::cout << "Give another number to divide by your previous result, " << past << ":" << std::endl;
        std::cin >> after;
        present = past / after;
        std::cout << present << std::endl;
        Operate = true;
        past = present;
        present = 0;
    }
}

void modulus_By(int& past, int& present, int& after, bool& Operate, std::string& setting)
{
    if (setting == "%")
    {
        std::cout << "Give another number to divide by your previous result, " << past << ":" << std::endl;
        std::cin >> after;
        present = past % after;
        std::cout << present << std::endl;
        Operate = true;
        past = present;
        present = 0;
    }
}

void first_Num_Prompt(int& first)
{
    std::cout << "Your First Number?" << std::endl;
    std::cin >> first;
    while (std::cin.fail())
    {
        std::cout << "Input an integer only with no spaces or characters" << std::endl;
        std::cin.clear();
        std::cin.ignore(256, '\n');
        std::cin >> first;
    }
}

void second_Num_Prompt_add(int& second, int& first, int& past, bool& Operate, std::string setting)
{
    if (setting == "+")                       
    {
        std::cout << "Your Second Number?" << std::endl;         
        std::cin >> second;
        while (std::cin.fail())
        {
            std::cout << "Input an integer only with no spaces or characters" << std::endl;
            std::cin.clear();
            std::cin.ignore(256, '\n');
            std::cin >> second;
        }
        past = first + second;
        std::cout << past << std::endl;
        Operate = true;
    }
}

void second_Num_Prompt_subtract(int& second, int& first, int& past, bool& Operate, std::string setting)
{
    if (setting == "-")
    {                    
        std::cout << "Your Second Number?" << std::endl;     
        std::cin >> second;
        while (std::cin.fail())
        {
            std::cout << "Input an integer only with no spaces or characters" << std::endl;
            std::cin.clear();
            std::cin.ignore(256, '\n');
            std::cin >> second;
        }
        past = first - second;
        std::cout << past << std::endl;
        Operate = true;
    }
}

void second_Num_Prompt_multiply(int& second, int& first, int& past, bool& Operate, std::string setting)
{
    if (setting == "*")
    {
        std::cout << "Your Second Number?" << std::endl; 
        std::cin >> second;
        while (std::cin.fail())
        {
            std::cout << "Input an integer only with no spaces or characters" << std::endl;
            std::cin.clear();
            std::cin.ignore(256, '\n');
            std::cin >> second;
        }
        past = first * second;
        std::cout << past << std::endl;
        Operate = true;
    }
}

void second_Num_Prompt_divide(int& second, int& first, int& past, bool& Operate, std::string setting)
{
    if (setting == "/")
    {
        std::cout << "Your Second Number?" << std::endl;         
        std::cin >> second;
        while (std::cin.fail())
        {
            std::cout << "Input an integer only with no spaces or characters" << std::endl;
            std::cin.clear();
            std::cin.ignore(256, '\n');
            std::cin >> second;
        }
        past = first / second;
        std::cout << past << std::endl;
        Operate = true;
    }
}

void second_Num_Prompt_modulus(int& second, int& first, int& past, bool& Operate, std::string &setting)
{
    if (setting == "%")
    {
        std::cout << "Your Second Number?" << std::endl;       
        std::cin >> second;
        while (std::cin.fail())
        {
            std::cout << "Input an integer only with no spaces or characters" << std::endl;
            std::cin.clear();
            std::cin.ignore(256, '\n');
            std::cin >> second;
        }
        past = first % second;
        std::cout << past << std::endl;
        Operate = true;
    }
}

void operation_Setting_input(std::string &z)
{
    std::cout << "+ for add, - for subtract, * for multiply, / for divide, and % for modulus. Type one to choose operator" << std::endl;
    std::cin >> z;
    if (z != "+" && z != "-" && z != "*" && z != "/" && z != "%")
    {
        while (z != "+" && z != "-" && z != "*" && z != "/" && z != "%")
        {
            std::cout << "Error, please input +, -, *, /, or %" << std::endl;
            std::cin >> z;
        }
    }
}

void operation_Switch_Setting_input(std::string& x)
{
    std::cout << "Operate onto this result? Y/N" << std::endl;
    std::cin >> x;
    while (std::cin.fail())
    {
        std::cout << "Error" << std::endl;
        std::cin.clear();
        std::cin.ignore(256, '\n');
        std::cin >> x;
    }
}
 
Last edited:
D

Deleted member 205

Guest
While I didn't say for you to do so, I'm impressed by the Code refactor that you've done. The Code is shorter, nesting doesn't go too far and most of your Code was moved to the Header-File, which for one, I didn't know you could do.

But, in the main file, on line 12, there's still a Comment that reaches the 200 Column mark. Again, it's best to keep lines under 150 Columns and if you keep on going beyond that line-length rule then it will become a habit which Projects that you're working on(Either at your job or on GitHub), will discourage you from doing that. I also noticed that in the Header file at void second_Num_Prompt_add, there's a Comment at the first If-Statement that's at the very side of the screen. Why's that? I also noticed that for other Functions for things like Divide, those very same Comments are there, unmodified. Becareful when copying and pasting Code in files as you can end-up leaving things which do the same as another Function, leave Comments that do not relate to the Function at all or potentially break things and cause the Compiler to get confused on why two of the same Function exists.

That's also a little bit more feedback. But this time it's mainly to do with Comments. Another thing is that remove Comments next to Variables like int first_num;. Writing a Comment telling others that this is the 'first number' is not necessary as people can tell that for themselves. This is unnecessary and counts as "Over-Commenting".
 

williamdev

Coder
Dec 21, 2019
33
15
9
Baton Rouge, Louisiana
While I didn't say for you to do so, I'm impressed by the Code refactor that you've done. The Code is shorter, nesting doesn't go too far and most of your Code was moved to the Header-File, which for one, I didn't know you could do.

But, in the main file, on line 12, there's still a Comment that reaches the 200 Column mark. Again, it's best to keep lines under 150 Columns and if you keep on going beyond that line-length rule then it will become a habit which Projects that you're working on(Either at your job or on GitHub), will discourage you from doing that. I also noticed that in the Header file at void second_Num_Prompt_add, there's a Comment at the first If-Statement that's at the very side of the screen. Why's that? I also noticed that for other Functions for things like Divide, those very same Comments are there, unmodified. Becareful when copying and pasting Code in files as you can end-up leaving things which do the same as another Function, leave Comments that do not relate to the Function at all or potentially break things and cause the Compiler to get confused on why two of the same Function exists.

That's also a little bit more feedback. But this time it's mainly to do with Comments. Another thing is that remove Comments next to Variables like int first_num;. Writing a Comment telling others that this is the 'first number' is not necessary as people can tell that for themselves. This is unnecessary and counts as "Over-Commenting".
Thank you for the feedback. I copy-pasted some stuff and along with it I had comments stating issues that I have now fixed, and I have sort of missed that so I will delete it and revise the comments too. If the name of a variable, function, etc is self-explanatory, then I won't describe what it is / what it does with a comment. That is a good tip. I will edit the posts I have made with the code as well as my GitHub repository of it.
 
  • Like
Reactions: Deleted member 205

williamdev

Coder
Dec 21, 2019
33
15
9
Baton Rouge, Louisiana
The functions make the codebase very modular, and more readable. Thank you for your feedback. I should also watch a video on coding practices and maybe computer science basics like algorithms and such.
 

williamdev

Coder
Dec 21, 2019
33
15
9
Baton Rouge, Louisiana
I want to try another project. If there are any other issues with this project, tell me, but don't expect me to respond immediately as I will be working on a different project to learn more about classes, arrays, objects, for loops, etc.. after rewatching this FreeCodeCamp C++ video since I have forgotten about said topics and how to use them.
 
D

Deleted member 205

Guest
wboycher said:
Thank you for the feedback. I copy-pasted some stuff and along with it I had comments stating issues that I have now fixed, and I have sort of missed that so I will delete it and revise the comments too. If the name of a variable, function, etc is self-explanatory, then I won't describe what it is / what it does with a comment. That is a good tip. I will edit the posts I have made with the code as well as my GitHub repository of it.
You're welcome for the feedback.

As I said about Line-Length, try to keep them at a certain length. Preferably under 150 Columns as most Projects use 120 Columns, 100 Columns and even 80 Columns. But, I myself, prefer 100 Columns.

Going back to Commenting, do not Comment parts of Code that can easily be understood or are just plain obvious. It's unneeded and you're making the file take-up more space on your Disk by adding an unnecessary Comment to the Code.

wboycher said:
The functions make the codebase very modular, and more readable. Thank you for your feedback. I should also watch a video on coding practices and maybe computer science basics like algorithms and such.
That's the core purpose of Functions. Make the Code more modular, smaller and readable and divide tasks into different parts and get the Program to run those tasks when called for.

There are plenty of Books on Coding-Practices and there are as well online. Co-Author of The C Programming-Language, Brian W. Kernighan, has a Book on good Coding-Practices which may come in handy. I myself don't own the Book but I may pick it up sometime. But, there are other resources out there for writing good Code. Take some time searching for how to write good Code. Believe me, your employer will probably love you if you can write Code that is fast, readable, compact and portable.

As for Algorithms, I would only suggest learning them if you plan on getting into Machine-Learning, Data-Science/Analysis or a CS Field that involves heavy usage of Mathematics. But, if you only plan to make and develop Software and Mobile Apps then learning Algorithms may not be worth it but at the same time, can still be beneficial.

Good luck!
 
Jun 26, 2019
72
19
8
Hey there! Good job on your C++ program!

I would suggest keeping function definitions in the .cpp files and function declarations (also known as function prototypes) in the .h files.

A function declaration is:

Code:
void Add(int number1, int number2);
A function definition is:

Code:
void Add(int number1, int number2) {
    return number1 + number2;
}
The difference being that one contains the instructions and one just declares that the function exists.

When you start working with more .cpp files, you will typically have a .cpp/.h pair, where the .cpp contains the function definitions and the .h contains the function declarations. Compiling C++ programs typically involve 2 steps: individual object compiling (creation of .obj or object files) and linking (combining the object files into their intended target: an executable or library). When a .cpp file is compiled, it usually doesn't know about the contents of other .cpp files (and you shouldn't include them in other .cpp files), and it relies on function declarations to decide if a function exists or not. For any given project, you only want one function definition to exist. When you declare a function in a header file, it gets defined in all the .cpp file that it is included into, and when it gets to the linking stage, you will typically get errors related to a function being defined more than once.

The #pragma once line at the start of your header file is typically a Microsoft C thing and may not be supported in other compilers (especially older C++ compilers, or even embedded compilers). There is a Wikipedia entry about it (https://en.wikipedia.org/wiki/Pragma_once) but I'm old school and usually use #ifndef macros.

Will be interested in seeing how you go with the object oriented side of things!
 
Jun 26, 2019
72
19
8
Something else: I noticed you're using abort and exit in your code. You would usually only use those in extreme circumstances and just rely on the main function to complete naturally. You would typically use abort to signal to the calling process (a command shell script perhaps?) that something went wrong during program operation. exit can affect how the program is terminated.
 

williamdev

Coder
Dec 21, 2019
33
15
9
Baton Rouge, Louisiana
I will make a new project that takes into consideration all of the feedback I have received from the start. Thank you for the feedback Daniel and eeflores, you are the people who make me feel like coding is worth it since I have someone to show it to who understands it and can give feedback.
 
  • Like
Reactions: Deleted member 205
D

Deleted member 205

Guest
wboycher said:
I will make a new project that takes into consideration all of the feedback I have received from the start. Thank you for the feedback Daniel and eeflores, you are the people who make me feel like coding is worth it since I have someone to show it to who understands it and can give feedback.
Again, you're welcome for the feedback provided by myself and @eeflores.

Programming is something that takes skill and practice. Execute it and learn it well then you can become a Programmer who writes good Code that can be ported to any system and run fast on any hardware.

Good luck!