I am trying to change multiple if-else
statement in my program with either switch and enum
or some other object-oriented approach. My purpose is in my code there should not be if-else
or very less.
class myClass
{
void readFile();
}
void myClass :: readFile()
{
std::string lineByLine;
std::ifstream myfile;
myfile.open(file path);
if (myfile.is_open())
{
while (std::getline(myfile, lineByLine))
{
std::pair<std::string, std::string> p1 = FindFirstWord(lineByLine);
// FindFirstWord --> will break the line into 2 words, First word and remaining words
while (p1.first.compare("}")) {
if (!p1.first.compare("SCALE")) {
// calling some function
} else {
if (!p1.first.compare("symbol")) {
// calling some function
} else {
if (!p1.first.compare("set_minimum_boundary")) {
// calling some function
} else {
if (!p1.first.compare("line")) {
// calling some function
} else {
if (!p1.first.compare("circle")) {
// calling some function
} else {
if (!p1.first.compare("arc")) {
// calling some function
} else {
if (!p1.first.compare("pin")) {
// calling some function
}
}
}
}
}
}
}
I want to remove the chain of if-else
statement using either by switch and enum
or some other object oriented approach.
CodePudding user response:
If you want to use an enum
with a switch
, you can do it in the following way:
Define an enum
for your action types:
enum class ActionType
{
Scale,
Symbol,
SetMinimumBoundary,
//...
INVALID
};
Add a function for converting a string
to the action type enum:
#include <string>
ActionType StringToActionType(std::string const & actionTypeStr)
{
if (actionTypeStr == "SCALE") return ActionType::Scale;
if (actionTypeStr == "symbol") return ActionType::Symbol;
if (actionTypeStr == "set_minimum_boundary") return ActionType::SetMinimumBoundary;
// ...
return ActionType::INVALID;
}
Then use it as shown below (you can add similar logic to myClass::readFile
) :
int main()
{
std::string someActionTypeStr; // Initialized to your p1.first
ActionType actionType = StringToActionType(someActionTypeStr);
switch (actionType)
{
case ActionType::Scale: // calling some function
break;
case ActionType::Symbol: // calling some function
break;
case ActionType::SetMinimumBoundary: // calling some function
break;
// ...
default:
// report error ...
break;
}
return 0;
}
CodePudding user response:
Use a mapping from keyword to handling functions, this is a quick draft of that idea. (You might want to lookup lambda functions)
#include <functional>
#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>
std::istringstream filestream
{
"SCALE\n"
"symbol\n"
};
class myClass
{
public:
myClass() :
m_handlers
{
{"SCALE", [=]() { HandleScale(); }},
{"symbol", [=]() { HandleSymbol(); }}
}
{
};
void readFile(std::istream& myfile)
{
std::string keyword;
while (myfile >> keyword)
{
// skipped line parsing, to show minimal sample
// lookup if there is a handler for read keyword
auto it = m_handlers.find(keyword);
if ( it != m_handlers.end())
{
auto& callback = it->second;
callback();
}
}
}
void HandleScale()
{
std::cout << "handling scale\n";
}
void HandleSymbol()
{
std::cout << "handling symbol\n";
}
private:
std::unordered_map<std::string, std::function<void()>> m_handlers;
};
int main()
{
myClass object;
object.readFile(filestream);
return 0;
}