1
if (calculation == "help") {
    cout << "add, subtract, multiplication, divide\nsquare root, sin, cos, power\n";
}
else if (calculation == "add") {
    cout << num1 << " + " << num2 << " = " << num1 + num2 << endl;
}
else if (calculation == "subtract") {
    cout << num1 << " - " << num2 << " = " << num1 - num2 << endl;
}
else if (calculation == "multiplication") {
    cout << num1 << " x " << num2 << " = " << num1 * num2 << endl;
}
else if (calculation == "divide") {
    cout << num1 << " / " << num2 << " = " << num1/ num2 << endl;
}
else if (calculation == "square root") {
    cout << "The square root of the first number is " << sqrt(num1) << ". The square root of the second number is " << sqrt(num2) << "." << endl;
}
else if (calculation == "sin") {
    cout << "The sine of the first number is " << sin(num1) << ". The sine of the second number is " << sin(num2) << "." << endl;
}
else if (calculation == "cos") {
    cout << "The cosine of the first number is " << cos(num1) << ". The cosine of the second number is " << cos(num2) << "." << endl;
}
else if (calculation == "power") {
    cout << num1 << " to the power of " << num2 << " = " << pow(num1, num2) << endl;
}

I have an idea for fixing these if statements, such as creating a map or a dictionary. I don't believe you can use strings with switch statements in C++ either. Any help is much appreciated!

EDIT: I was able to use a map.

map<string, int> Choices = {
        { "help", 0 },
        { "add", 1 },
        { "subtract", 2 },
        { "multiply", 3 },
        { "divide", 4 },
        { "square root", 5 },
        { "sine", 6 },
        { "cosine", 7 },
        { "power", 8 }
        };

    it = Choices.find(choice);
    i = it->second;

If there is a faster way of doing this, please tell me. Thanks for all of the responses!

  • 4
    Put them in enum and have a switch instead. Look at [this](https://stackoverflow.com/a/3019195/6530695) answer – Tony Tannous May 27 '20 at 03:29
  • 3
    [Stringly Typed](https://wiki.c2.com/?StringlyTyped) – John Kugelman May 27 '20 at 03:34
  • 2
    Let's assume for your (and the question's) sake that you are stuck with strings from an external source, like a message. Since you are using C++, you can create a map with std::strings (ah, I see that you said that -- yes, that's a good idea) as keys and function-like objects of your choice as values. You can also early on convert them to enums (using a map, too) and then use switches. – Peter - Reinstate Monica May 27 '20 at 03:37
  • Does the keys would be used elsewhere? moving it in `stp::map>` would just move the verbose stuff inside the map initialization. Not sure you really gain in readability. – Jarod42 May 27 '20 at 08:25
  • Have you test performance and compared the solution with a map and if statements. I could be that the map solution is slower compared to ifs. When coding for performance you always need to think of the processor cache and how prefetchers work. If the type of list only stores a few items, arrays are usually faster than maps. – Per Ghosh May 27 '20 at 20:01

4 Answers4

2

If you match the first two characters and cast those to a number it is possible to create a switch. It isn't going to be pretty but it will be fast

EDIT: I did a sample on how to create a switch using "strings" if the first part in string is unique. You could do this with more than two characters if it is needed and you can have switches in case parts if there are duplicates.

Only do this if performance is very important, it will crush other solutions in speed

#include <iostream>
#include <string>

int main()
{
    // first some code to show how to calculate constant from string if the first part in string is unique
    unsigned int uNumber = (unsigned int)'A';
    std::cout << uNumber << std::endl;
    uNumber <<= 8;
    std::cout << uNumber << std::endl;
    uNumber += (unsigned int)'A';
    std::cout << uNumber << std::endl;

    unsigned int uNumberAA = (unsigned int)*(uint16_t*)"AA";
    std::cout << uNumberAA << std::endl;
    uNumberAA = (unsigned int)*(uint16_t*)"AAAA";
    std::cout << uNumberAA << std::endl;


    // How to create a switch with strings

    static constexpr unsigned int he_help = ((unsigned int)'h' << 8) + (unsigned int)'e';           // "help"
    static constexpr unsigned int ad_add = ((unsigned int)'a' << 8) + (unsigned int)'d';            // "add"
    static constexpr unsigned int su_subtract = ((unsigned int)'s' << 8) + (unsigned int)'u';       // "subtract"
    static constexpr unsigned int mu_multiplication = ((unsigned int)'m' << 8) + (unsigned int)'u'; // "multiplication"

    std::string calculation = "subtract";

    uNumber = ((unsigned int)calculation[0] << 8) + (unsigned int)calculation[1];
    switch(uNumber)
    {
    case he_help :
        std::cout << "help" << std::endl;
        break;
    case ad_add :
        std::cout << "add" << std::endl;
        break;
    case su_subtract :
        std::cout << "subtract" << std::endl;
        break;
    case mu_multiplication :
        std::cout << "multiplication" << std::endl;
        break;
    }
}
Per Ghosh
  • 449
  • 5
  • 10
1

You can cleanup them pretty much easily. Consider this example:

#include <stdio.h>

int main(void) {
    int a, b, result;
    char calculation;
    .
    .
    switch (calculation) { // must be a character or integral type
        case 'a': result = a + b; break; // add
        case 's': result = a - b; break; // subtract
        .
        .
        default:
            printf("No such operation.\n"); // when invalid operation
            return -1;
    }
    // valid operation? continue...

    printf("The result is: %d\n", result);

    return 0;
}
Rohan Bari
  • 7,482
  • 3
  • 14
  • 34
0

Read more about C++ programming and about the C++ programming language and How to debug small programs and later the C++11 standard n3337. Consider coding with some functional programming style. The SICP book is an excellent introduction to it.

Remember that C++ has closures, created with lambda expressions. It also has several associative containers, including std::map or std::unordered_map

A possibility could be to set up an associative map of closures:

static std::map<std::string,
                std::function<int(const std::vector<int>&)>> 
       mapclosures= {
  { "add", [](const std::vector<int>& v) { return v[0]+v[1]; }},
  { "mult", [](const std::vector<int>& v) { return v[0]*v[1]; }},
  //// etc...
}

and later use mapclosures[str](v) or mapclosures[str](std::vector({3,5}))

Of course a real code would check that v has two arguments for add and if not throw some exception. For division, take care of division by zero.

Regarding performance, it could be acceptable (but of course, slower than a plain switch). If performance matters a lot and you are willing to spend coding time, learn more about parsing techniques (e.g. with the Dragon book, or your recursive descent parser building some abstract syntax tree) to transform the string "add" to some enum value.

Read more about interpretation techniques and study for inspiration the source code of existing open source interpreters coded in C++ (perhaps Linux fish shell, or others on gitlab or github).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
-1

Using switch for such cases can help you modify your code into a neater one. However, switch is not much different from conditions. It only looks more comprehensive when you have so many conditions based on only one thing which could possibly change. Here's an example of switch for you: imagine I input an int in the range of 1 to 4, and then want to print the number which was given by the user. Here's how you can use switch in such case:

int n;
cin>>n;
switch(n){
   case 1:{cout<<"one";break;}
   case 2:{cout<<"two";break;}
   case 3:{cout<<"three";break;}
   case 4:{cout<<"four";break;}
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
Liana
  • 314
  • 5
  • 15
  • 1
    Switches are very fast, compilers are good at optimizing and there is a reason why C++ only can use numbers in a switch statement. Other languages that can use strings in a switch is more like "if's". Just another way to write them. – Per Ghosh May 27 '20 at 19:22