有没有办法匹配C ++中的字符串集?

时间:2013-09-13 18:32:00

标签: c++

编辑:

我知道如果它是enum会很容易,但我不能在这个特殊场合使用enum。我实际上需要一个字符串进行进一步处理。


例如,我有四个状态字符串:

IDLE, STARTED, STOPPED, PAUSED

和一个吸收其中一种状态的函数:

setState(const std::string &state);

有一种快速方法可以验证输入状态是四个字符串中的一个而不使用像这样的巨大if语句:

if (state == "IDLE" || state == "STARTED" || state == "STOPPED" || state == "PAUSED") { 
// use code
}

5 个答案:

答案 0 :(得分:9)

最好的方法是始终使用枚举。但是如果你必须坚持使用std :: string,那么我会推荐这样的东西:

#include <unordered_set>

static void setState(const std::string &state)
{
    static std::unordered_set<std::string> states {{ "IDLE", "STARTED", "STOPPED", "PAUSED" }};
    if (states.find(state) == states.end())
        throw std::invalid_argument("Invalid state");

    // Continue...
}

答案 1 :(得分:3)

尝试:

std::string tmp[] = {"IDLE", "STARTED", "STOPPED", "PAUSED"};
std::set<std::string> allowedStates(tmp, tmp + sizeof(tmp) / sizeof(tmp[0]));

(可能是静态变量或其他东西)

然后:

if (allowedStates.find(state) == allowedStates.end())
{
  //state is invalid
}

答案 2 :(得分:1)

这取决于你所说的“快捷方式”。如果这是关于效率,我首先打开尺寸:

bool verify_state( const std::string& state ) {
  switch( state.size() )
  {
  case 4: return state=="IDLE";
  case 6: return state=="PAUSED";
  case 7: return state=="STARTED" || state == "STOPPED";
  default: return false;
  }
}

答案 3 :(得分:1)

BartoszKP的STL设置解决方案可能是最简单的解决方案。

如果你真的很热衷,你可以用这样的东西来模拟一个穷人的哈希:

const unsigned nIdle('ELDI');    // "IDLE" with byte order reversed
const unsigned nStarted('RATS'); // "STAR" with byte order reversed
const unsigned nStopped('POTS'); // "STOP" with byte order reversed
const unsigned nPaused('SUAP');  // "PAUS" with byte order reversed

bool Verify(const char *szState)
{
    unsigned nState = *reinterpret_cast<const unsigned *>(szState);

    switch (nState)
    {
        case nIdle:
        case nStarted:
        case nStopped:
        case nPaused:
            return true;

        default:
            return false;
    }
}

int main()
{
    const std::string s[] = {"IDLE", "STARTED", "STOPPED", "PAUSED", "INVALID"};
    for (auto itr=std::begin(s); itr!=std::end(s); ++itr)
    {
        std::cout << *itr << '\t';
        if (Verify(itr->c_str()))
            std::cout << "OK";
        else
            std::cout << "Fail";
        std::cout << std::endl;
    }
    return 0;
}

您需要确定自己的数据。任何短于sizeof(unsigned)的字符串都可能存在风险,您需要确保该字符串的前4个字节是唯一的。例如“STOPPED”和“STOPPING”对于4个字节是相同的。

你可以做一个正确的哈希,但这可能不比比较字符串快。

答案 4 :(得分:0)

不要使用字符串,使用枚举来表示状态机的内部状态,并在需要时转换为字符串:

namespace State
{
    enum Type
    {
        IDLE, STARTED, STOPPED, PAUSED
    };

    std::string names[] = { "IDLE", "STARTED", "STOPPED", "PAUSED" };
}

然后编译器强制您使用有效状态。然后使用names数组从枚举值中获取字符串以进行其他处理。您甚至可以使用静态断言来确保枚举和字符串的数量匹配。

或者boost::enum甚至提供了一种机制来创建这样的枚举类型,其中包含与字符串之间的内置转换。