在C ++中读取不同类型的数据

时间:2019-05-15 01:32:20

标签: c++

我想让程序读取类似以下的字符串:

integer_value    1

double_value     1.0

string_value     one

我实现以下功能以阅读这些功能:

void read_val_int( 
    std::vector<std::string> str_vec,
    std::string str,
    int& val){
    if(str_vec[0]==str) val= std::stoi(str_vec[1]);
}

void read_val_dbl( 
    std::vector<std::string> str_vec,
    std::string str,
    double& val){
    if(str_vec[0]==str) val= std::stoi(str_vec[1]);
}

void read_val_str( 
    std::vector<std::string> str_vec,
    std::string str,
    std::string& val){
    if(str_vec[0]==str) val= str_vec[1];
}

str_vec是一个包含两个字符串值的向量,例如{“ integer_value”,“ 1”}。

str包含一个我想与str_vec[0]比较的字符串

val是一个整数,双精度或字符串,如果str_vec[1]为真,则对应于str_vec[0]==str

我将这些功能用作read_val_int(my_str_vec,"integer_value",my_int_val)

我的问题是:有没有一种方法可以使用单个函数来执行此操作?我尝试使用模板,但是由于我需要引用val,因此这似乎是不可能的。


注意:我知道this post,但它在C语言中,对我来说有点混乱。也许有一种更简单的方法可以在C ++中实现。

2 个答案:

答案 0 :(得分:2)

如果您在C ++ 17之前,因此无法使用std::variant,则只能使用模板来使用一个功能。

您对函数进行如下声明:

template <typename T>
void read_val(const std::string & data, T & val);

然后您将其专门用于三种类型:

template <>
void read_val<int>(const std::string & data, int & val)
{
    val = std::stoi(data);
}
template <>
void read_val<double>(const std::string & data, double & val)
{
    val = std::stod(data);
}
template <>
void read_val<std::string>(const std::string & data, std::string & val)
{
    val = data;
}

工作完成后,您可以通过调用只有一个函数来使用三种类型的函数:read_val()

您可以按以下方式使用它:

std::string data_int("5");
std::string data_double("2.5");
std::string data_string("Hello");

int int_val;
double double_val;
std::string string_val;

read_val(data_int, int_val);
read_val(data_double, double_val);
read_val(data_string, string_val);

std::cout << int_val << std::endl;
std::cout << double_val << std::endl;
std::cout << string_val << std::endl;

如您所见,通过使用模板专业化,可以将相同的函数用于不同的类型。

此外,它将自动确保您传递了允许的类型。确实,如果您给函数赋予intdoublestd::string之外的其他东西,则编译将失败,因为它没有专门的功能。

希望对您有帮助。

答案 1 :(得分:1)

如Dave的注释中所建议,您应该检查变量的类型,以分析向量的第一个元素。 在if-else链中,您可以使用正确的变量类型来满足您的需求。

您还可以使用单个函数使用std :: variant e返回值,然后使用c ++ 17 std :: visit打印值(或执行所需的任何操作)。

可能是这样的:

#include <vector>
#include <string>
#include <variant>
#include <iostream>

using my_variant = std::variant<int, double, std::string>;
my_variant read_val(
    const std::vector<std::string> &str_vec)
{
    if(str_vec[0]=="integer_value") 
    {
        return std::stoi(str_vec[1]);
    }
    else if(str_vec[0]=="double_value") 
    {
        return std::stod(str_vec[1]);
    }
    else if(str_vec[0]=="string_value") 
    {
        return str_vec[1];
    }

    //notify error in some way, maybe throw
}

void print_variant(const my_variant &v)
{
    std::visit([](my_variant &&var)
    {
        if (std::holds_alternative<int>(var))
            std::cout<<"int->"<<std::get<int>(var)<<"\n";
        else if (std::holds_alternative<double>(var))
            std::cout<<"double->"<<std::get<double>(var)<<"\n";
        else if (std::holds_alternative<std::string>(var))
            std::cout<<"string->"<<std::get<std::string>(var)<<"\n";
    }, v);
}

int main()
{
    std::vector<std::string> vec_int {"integer_value", "1"};
    std::vector<std::string> vec_dbl {"double_value", "1.5"};
    std::vector<std::string> vec_str {"string_value", "str"};

    print_variant(read_val(vec_int));
    print_variant(read_val(vec_dbl));
    print_variant(read_val(vec_str));

    return 0;
}