DEV Community

Ted Larsson
Ted Larsson

Posted on

School project

So i´m finally done with my calculator, its working and most bugs are done with.
Now i would like to know how to tidy up the code, is there ways to make it more efficient, more user foolproof, simply better ways to code it?



// looped calculator

#include 

//variables
float num1;
float num2;
float sum;
char oper;

//functions


int main()
{
    //greets the user
    std::cout << "welcome to the calculator\n";
    
    //instructions on how to use the program
    std::cout << "press ENTER after each input and please use only + - * / or 'q' to quit\n";       
    
    //Prompts the user to input number
    std::cout << "enter number: ";                                                  
    
    // user inputs number
    while (!(std::cin >> num1))
    {
        std::cout << "enter a number please (enter to confirm): ";
        std::cin.clear();
        std::cin.ignore(100, '\n');
    }
    
    //Prompts the user to input operator or quit the program
    std::cout << "enter operator or quit (enter to confirm): ";                                     
    
    //user inputs operator or quits
    std::cin >> oper;                                                                       
    

    //Prompts the user to input number
    std::cout << "enter number (enter to confirm): ";                                                   
    
    while (!(std::cin >> num2))
    {
        std::cout << "enter a number please (enter to confirm): ";
        std::cin.clear();
        std::cin.ignore(100, '\n');
    }                                                               
    
    //switch loop depending on what operator was chosen
        switch (oper)                                                                           
        {
        case '+':
            sum = num1 + num2;
            break;
        case '-':
            sum = num1 - num2;
            break;
        case '*':
            sum = num1 * num2;
            break;
        case '/':
            sum = num1 / num2;
            break;
        default:
            std::cout << "enter only valid operators + - * /  (enter to confirm) \n";
            break;
        }
        
        

        while (true)
        {
            //outputs the sum
            std::cout << sum << std::endl;                                  
            
            //Prompts the user to input operator
            std::cout << "enter operator or quit (enter to confirm): ";                         
            
            //user inputs operator or quit the program
            std::cin >> oper;                                                       
            
            //Quits the program
            if (oper == 'q')
                break;
            
            // Prompts the user to input number
            std::cout << "enter number (enter to confirm): ";                                   
            
            while (!(std::cin >> num2))
            {
                std::cout << "enter a number please (enter to confirm): ";
                std::cin.clear();
                std::cin.ignore(100, '\n');
            }
            
            //switch loop depending on what operator was chosen
            switch (oper){                                                              
                case '+':
                    sum = sum + num2;
                    break;
                case '-':
                    sum = sum - num2;
                    break;
                case '*':
                    sum = sum * num2;
                    break;
                case '/':
                    sum = sum / num2;
                    break;
                default:
                    std::cout << "enter only valid operators + - * /  (enter to confirm)\n";
                    break;
            }

        }
            

        
        //outputs sum then quits the program
    std::cout << sum;                                                                   
    std::cin.ignore();
    std::cin.get();
    return 0;   
}

I tried making it look pretty but this is the best i could do :P

I´ll gladly accept help with how to make code look nice on here because i think i´ll post some more here in the future :D

Top comments (4)

Collapse
 
codemouse92 profile image
Jason C. McDonald • Edited

Hi Ted,

Welcome to C++, and to dev.to!

Here's some thoughts for you. I'll refer to line numbers in your code. Assume // looped calculator is on line 1.

1) You don't need an empty #include line. That's only needed if you're actually including some other file, such as a header. However, I suspect you actually meant that to be #include <iostream>, yeah?

2) I get twitchity every time I see this much code in int main(). I highly recommend breaking this up into functions. For example, you might have one function for displaying instructions, one for prompting the user and getting their input, and one for the actual calculation.

The reason we do this is to make the code easier to read and maintain. int main() should only handle the main execution flow (e.g. the program loop) and calling the other functions.

3) The other reason you need functions is to make the code DRY (Don't Repeat Yourself). See how you have the same code on 33-68 and 77-114? That's a maintenance nightmare, because any change you make to the code must be replicated in more than one place!

Now, if any bit of code is only a couple of lines long, and only appears 2-4 times, you generally shouldn't worry about breaking it off into a separate function. (There is such a thing as DRY spaghetti.) Use discernment. Still, something as complex as your calculation switch statement should absolutely be abstracted out to a function.

4) cin::get() is pain. Consider using getline instead; it doesn't involve any of the clear() or ignore() madness. (See the documentation)

Collapse
 
larssonted profile image
Ted Larsson

Yes I thought there might be ways to clean it up a bit. I handed it in as it is and I got an A on it so I'm happy. But I would like to learn to do clean coding since I plan to do coding for a living in the future, would you put the functions in a separate header or above main or under main?

Collapse
 
codemouse92 profile image
Jason C. McDonald • Edited

C++, like its predecessor C, is a "top-down" language, so you have to declare a function before you use it. However, as you may know, you have two options.

You could declare the entire function above where it's used...

#include <iostream>

int foo(int l, int r) {
    return l+r;
}

int main() {
    std::cout << add(1, 2) << std::endl;
}

...or, use function prototypes...

#include <iostream>

int foo(int, int); //pre-declare the function here

int main() {
    std::cout << add(1, 2) << std::endl;
}

// implement the function here...
int foo(int l, int r) { 
    return l+r;
}

Which you use is entirely a matter of style and preference. In practice, prototyping is (for me, at least) a bit easier to keep track of, as you don't have to care which functions call which. You can prototype all (but main), and then use them at will. However, the downside to this is that if you change the function's name, argument types, or return types, you have to change it in two places, not just one. (Of course, if you forget, you'll merely get a compiler error.)

You could also move them to separate headers or classes. This can certainly make large code cleaner, but with something this small, it would merely make it spaghetti. There's no hard-and-fast rule for whether code should go in main.cpp or another header, but I think there are a few good guidelines that usually work:

  1. If your function is only used in one file, then it should live in that one file. Don't split things up unnecessarily.

  2. A single header should have one primary purpose. If you were building a more feature-full, production-ready calculator, you would NOT put your user-input functions in the same header as your actual math calculation functions.

  3. Don't get classes involved unless you actually have a need for objects (see Object-Oriented Programming). It's tempting to turn every header file, or header/implementation file pair, into a class. Don't. If the functions don't need their own private data stored between calls, you don't need a class/object.

As you can tell, those guidelines can actually feel contradictory at times. After you've been coding for a while, you'll start to develop an instinct about it (what we call "code smell"). When it's wrong, you'll just sense that it's wrong. (Seriously...it's weird, but it works.)

Collapse
 
gavinfernandes2012 profile image
Gavin Fernandes • Edited

Are you guys allowed to use parsers? Bison and Flex are really well suited to this, and it's pretty simple to implement bodmas/pedmas with it as well, and the user can input everything all in one line.
Although this does mean you have to learn language grammar / BNF / LR parsing, but if you're up for the challenge, you can solve this problem in wayyy fewer lines of code, and get a really good quality program.

EDIT: Just saw the date of this post, dang the cpp community isn't in the best shape here.