2017-03-02 88 views
0

的返回值这是我的问题: 从来就定义了一些值:地址阵列枚举

enum HarmCons 
{ 
    val1 = 0, 
    val2 = 2, 
    val3 = 4, 
    val4 = 6 
}; 

,我有一个数组

int foo [7] = { 16, 2, 77, 40, 1222, 34, 5}; 

这是我从一个输入文件中读取。我也有这样的:

char types[15] = "val1,val3,val4"; 

现在我想单独由commata和地址字符串(在一个循环中)的条目foo。所以字符串的第一部分应该是val1,它应该返回16。 我试过foo[val1] 它工作正常。问题是,通过分隔字符串,我总是会得到一个字符串或某些东西,我无法用字符串来寻址数组。 有没有可能以一种我可以使用结果来解决数组的方式来分隔字符串?

+0

这些名称是否总是按照'val1,val2,val3'的顺序排列,或者它们可能存在空位或未被排序或不遵循这种固定模式? –

+0

在C++中没有反射字符串来枚举,你可以看看库[更好的枚举](https://github.com/aantron/better-enums)来帮助那部分。 – Jarod42

+0

有13个可能的名称,它不是固定数量的名称,它们也没有订购。 – WinterMensch

回答

1

看来你试图用锤子将螺丝。数组是一个很好的数据结构,但不适合所有问题。

总是会得到一个字符串或东西,我不能被串

实际上解决一个数组,你不能。所以你需要一个非数组的东西。看起来你有一个从字符串到整数值的映射。这种映射的数据结构是...映射(也称为关联数组,字典......)

标准库为您提供了一个实现:std::map<std::string, int>。根据您的使用情况,您可能需要将枚举或阵列替换为地图。

+0

事实上,摆脱枚举和使用地图直接解决这个没有任何麻烦。 +1 –

1

下面介绍一种方法。

一些注意事项:在专门的函子方面实现

  1. 转换功能。

  2. 以小函数表示的逻辑。

  3. 评论直列

-

#include <type_traits> 
#include <string> 
#include <cstring> 
#include <algorithm> 
#include <sstream> 
#include <vector> 
#include <iostream> 
#include <iomanip> 

// general concept of value conversion 
template<class From, class To> 
struct converter; 

// helper function to select correct converter class 
template<class To, class From> 
To convert(From&& from) 
{ 
    return converter<std::decay_t<From>, To>()(std::forward<From>(from)); 
}; 

enum HarmCons 
{ 
    val1 = 0, 
    val2 = 2, 
    val3 = 4, 
    val4 = 6 
}; 

// specialise for converting from string to our enum 
template<> 
struct converter<std::string, HarmCons> 
{ 
    HarmCons operator()(std::string in) const { 
     using namespace std::literals; 
     std::transform(std::begin(in), std::end(in), std::begin(in), [](auto&& c) { return std::tolower(c); }); 
     if (in == "val1") return HarmCons ::val1; 
     if (in == "val2") return HarmCons ::val2; 
     if (in == "val3") return HarmCons ::val3; 
     if (in == "val4") return HarmCons ::val4; 
     throw std::invalid_argument("out of range: "s + in); 
    } 
}; 

// helper functions 
template<class Sequence, class F> 
void for_each_comma(Sequence&& seq, F&& f) 
{ 
    std::istringstream splitter(std::forward<Sequence>(seq)); 
    std::string name; 
    while(std::getline(splitter, name, ',')) 
    { 
     f(name); 
    } 
}; 

std::vector<int> read_int_array(std::istream& is) 
{ 
    std::vector<int> values; 
    int N; 
    is >> N; 
    values.resize(N); 
    for (int i = 0 ; i < N ; ++i) { 
     is >> values[i]; 
    } 
    return values; 
} 

std::string dequoted_string(std::istream& is) 
{ 
    std::string result; 
    is >> std::quoted(result); 
    return result; 
} 

// test against any istream 
void test(std::istream& input) 
{ 
    // read in test data 
    input.exceptions(std::ios_base::badbit); 
    auto values = read_int_array(input); 

    // read in comma- delimted string 
    auto value_names = dequoted_string(input); 

    // perform conversion and lookup 
    for_each_comma(value_names, [&](auto&& name){ 
     auto cons = convert<HarmCons>(name); 
     std::cout << values.at(cons) << '\n'; 
    }); 
} 

// our test 
int main() 
{ 

    std::istringstream testinput(R"__(
7 
16 2 77 40 1222 34 5 
"val1,val3,val4" 
)__"); 

    test(testinput); 
} 

预期输出:

16 
1222 
5 
-1

如果你真的希望分割字符串,你可以这样做,并简单地比较最后的字符和数字描述为字符。
排序是这样的:

If (char1 == '1') 
    Then set a int var to 1 

并与一个循环做同样的事情,但随着0号为数十,数百,等等加入,当您去。
然后,您可以使用该int var访问数组。
然而,switch语句可能会比if语句更好地实现它。