C++ 解析参数值字符串并将值(字符串类型)链接到变量(特定类型)

C++ 解析参数值字符串并将值(字符串类型)链接到变量(特定类型),c++,C++,如果参数数据类型不同,您将如何构造一组参数值对 假设您有一组很大的参数绑定在一个较大的软件中,如下所示: string name; int counter; //... float temperature; bool enableState; 要手动设置参数值,应通过命令行接受字符串(例如,“Name=Eric”、“Counter=100”、“Temperature=20.0”、…) 搜索的目的是为参数寻找合适的结构,以便它们(或至少是读/写它们的信息)可以存储在一个数组中。由于值具有不同的数

如果参数数据类型不同,您将如何构造一组参数值对

假设您有一组很大的参数绑定在一个较大的软件中,如下所示:

string name;
int counter;
//...
float temperature;
bool enableState;
要手动设置参数值,应通过命令行接受字符串(例如,“Name=Eric”、“Counter=100”、“Temperature=20.0”、…)

搜索的目的是为参数寻找合适的结构,以便它们(或至少是读/写它们的信息)可以存储在一个数组中。由于值具有不同的数据类型,因此它们不能存储在数组中,但它们的指针(?)是否有目的。 如何将输入字符串的(字符串)值分配给具有固定数据类型的变量

无论我尝试什么都不会带来任何结果,或者这是一个巨大的努力,这让我相信一个可能的(简单的)解决方案可能不会是微不足道的

代码应该在arduino上运行

编辑:
我找到了一种方法,而且似乎效果很好。但我不确定,也许我犯了根本性的错误。你能确认我回答中的代码是合法的,这样我就可以把问题设置为“已解决”了吗?

你可以使用
std::map variableMap
像这样填充lambdas

std::string name;
int counter;
...

variableMap["Name"] = [&](std::string& val) {
    name = val;
}

variableMap["Counter"] = [&](std::string& val) {
    counter = std::stoi(val);
}
然后像这样使用它

//Get the input and parse it, eg "Name=Chris"
std::string variableName; // Holds "Name"
std::string variableValue; // Holds "Chris"

if (variableMap.find(variableName) != variableMap.end())
    variableMap[variableName](variableValue);

您可以使用
std::map variableMap
并像这样用lambda填充它

std::string name;
int counter;
...

variableMap["Name"] = [&](std::string& val) {
    name = val;
}

variableMap["Counter"] = [&](std::string& val) {
    counter = std::stoi(val);
}
然后像这样使用它

//Get the input and parse it, eg "Name=Chris"
std::string variableName; // Holds "Name"
std::string variableValue; // Holds "Chris"

if (variableMap.find(variableName) != variableMap.end())
    variableMap[variableName](variableValue);

您可以让一个结构将数据存储为无符号字符*,然后获得一些元数据,了解如何解码结构中的无符号字符*。差不多

typedef struct FlexibleStruct {
    char * metaData;
    // this data type here doesn't matter because we will cast it to what we want
    unsigned char * data;
} FlexibleStruct;
然后,当您要存储它时:

FlexibleStruct f;
f.metaData = "float";
f.data = (unsigned char *)floatToStore; // This should be a pointer to a float on the heap
以及检索数据:

if(strcmp(f.metaData, "float") == 0) {
    float *retrievedFloat = (float *)f.data;
    printf("%f\n", *retrievedFloat);
}
<>这将适用于任何版本的数据类型(甚至是结构),在任何版本的C或C++中p>
我在GCC6.4.0上对此进行了测试,但我不知道它是否适用于avr-g++。如果您愿意,我可以提供更多信息。

您可以让一个结构将数据存储为无符号字符*,然后在该结构中提供一些有关如何解码无符号字符*的元数据。差不多

typedef struct FlexibleStruct {
    char * metaData;
    // this data type here doesn't matter because we will cast it to what we want
    unsigned char * data;
} FlexibleStruct;
然后,当您要存储它时:

FlexibleStruct f;
f.metaData = "float";
f.data = (unsigned char *)floatToStore; // This should be a pointer to a float on the heap
以及检索数据:

if(strcmp(f.metaData, "float") == 0) {
    float *retrievedFloat = (float *)f.data;
    printf("%f\n", *retrievedFloat);
}
<>这将适用于任何版本的数据类型(甚至是结构),在任何版本的C或C++中p>
我在GCC6.4.0上对此进行了测试,但我不知道它是否适用于avr-g++。如果您愿意,我可以提供更多信息。

请查看
std::variant
std::any
(两者都在C++17中提供)。如果您使用的是早期标准,boost提供了
boost::variant
boost::any
请查看
std::variant
std::any
(两者都在C++17中提供)。如果您使用的是早期的标准,boost提供了
boost::variant
boost::any
,我找到了一种方法,但我不确定我是否会遇到内存分配问题。除其他外,我还需要链接到全局字符串变量的字符串参数。参数也需要是全局的。我将变量链接到带有内存地址的参数,但我不确定这是否合法。。。 我的解决办法是:

#include <iostream>
#include <string>

enum Access {NO_ACCESS,READ,WRITE,READ_WRITE};
enum DataType {INTEGER,FLOAT,STRING,BOOLEAN};

// parameter-class
class Parameter {
  public:
    long int address;
    string (*setEventAddress) ();
    string (*getEventAddress) ();
    string parameterName;
    Access access;
    DataType datatype;

    string set(string value) {
      if(!(access==WRITE || access==READ_WRITE)){
        return "ERROR: no write access";
      }
      string response="";
      switch (datatype){
        case INTEGER:
          response = setInteger(value,address);
          break;
        case FLOAT:
          response = setFloat(value,address);
          break;
        case STRING:
          response = setString(value,address);
          break;
        case BOOLEAN:
          response = setBool(value,address);
          break;
        default:
          response = "ERROR: unknown data type";
          break;
      }
      if(setEventAddress!=NULL){
        string eventResponse=setEventAddress();
      }
      return response;
    }
    string get(){
      if(!(access==READ || access==READ_WRITE)){
        return "ERROR: no read access";
      }
      string response="";
      switch (datatype){
        case INTEGER:
          response = getInteger(address);
          break;
        case FLOAT:
          response = getFloat(address);
          break;
        case STRING:
          response = getString(address);
          break;
        case BOOLEAN:
          response = getBool(address);
          break;
        default:
          response = "ERROR: unknown data type";
          break;
      }
      if(setEventAddress!=NULL){
        string eventResponse=setEventAddress();
      }
      return response;
    }

    string setInteger(string valueRaw, long int address) {
      int value = stoi(valueRaw);
      *(int*)(address)=value;
      return "Done";
    }
    string setFloat(string valueRaw, long int address) {
      float value = stof(valueRaw);
      *(float*)(address)=value;
      return "Done";
    }
    string setString(string valueRaw, long int address) {
      string value = valueRaw;
      *(string*)(address)=value;
      return "Done";
    }
    string setBool(string valueRaw, long int address) {
      bool value = true;
      if (valueRaw.compare("true") == 0) {
        *(bool*)(address)=true;
      } else {
        *(bool*)(address)=false;
      }
      return "Done";
    }

    string getInteger(long int address) {
      int& i = *reinterpret_cast<int*>(address);
      return to_string(i);
    }
    string getFloat(long int address) {
      float& f = *reinterpret_cast<float*>(address);
      return to_string(f);
    }
    string getString(long int address) {
      string& s = *reinterpret_cast<string*>(address);
      return s;
    }
    string getBool(long int address) {
      bool& b = *reinterpret_cast<bool*>(address);
      return to_string(b);
    }

    Parameter(string n, Access a, DataType d, long int varPointer, string (*setFuncPointer)(), string (*getFuncPointer)());
};

// constructor for parameter
Parameter::Parameter(string n, Access a, DataType d, long int varPointer, string (*setFuncPointer)()=NULL, string (*getFuncPointer)()=NULL) {
  parameterName=n;
  access=a;
  datatype=d;
  address=varPointer;
  setEventAddress=setFuncPointer;
  getEventAddress=getFuncPointer;
}

// functions optionally executed when parameter becomes set/get
string exampleSetEvent() {
  // do anything when parameter is set
  return m;
}

string exampleGetEvent() {
  // do anything when parameter is read
  return m;
}


// a parameter constists of the variable and an object of the parameter-class
// and is simply introduced by adding only two lines
string name;
Parameter Name ("Name", READ_WRITE, STRING, (long int) &name);

int counter;
Parameter Counter ("Counter",READ_WRITE, STRING, (long int) &counter, exampleSetEvent, example);


float temperature;
Parameter Temperature ("Temperature", READ_WRITE, STRING, (long int) &temperature);


bool enableState;
Parameter EnableState ("EnableState", READ_WRITE, STRING, (long int) &enableState);
#包括
#包括
枚举访问{NO_Access,READ,WRITE,READ_WRITE};
枚举数据类型{INTEGER,FLOAT,STRING,BOOLEAN};
//参数类
类参数{
公众:
长整数地址;
字符串(*setEventAddress)();
字符串(*getEventAddress)();
字符串参数名;
准入;
数据类型数据类型;
字符串集(字符串值){
if(!(访问==写入| |访问==读写)){
返回“错误:无写访问”;
}
字符串响应=”;
交换机(数据类型){
大小写整数:
响应=setInteger(值、地址);
打破
案例浮动:
响应=设置浮点(值、地址);
打破
大小写字符串:
响应=设置字符串(值、地址);
打破
大小写布尔值:
响应=setBool(值、地址);
打破
违约:
response=“ERROR:未知数据类型”;
打破
}
if(setEventAddress!=NULL){
字符串eventResponse=setEventAddress();
}
返回响应;
}
字符串get(){
如果(!(访问==读| |访问==读|写)){
返回“错误:没有读取权限”;
}
字符串响应=”;
交换机(数据类型){
大小写整数:
响应=getInteger(地址);
打破
案例浮动:
响应=getFloat(地址);
打破
大小写字符串:
响应=getString(地址);
打破
大小写布尔值:
响应=getBool(地址);
打破
违约:
response=“ERROR:未知数据类型”;
打破
}
if(setEventAddress!=NULL){
字符串eventResponse=setEventAddress();
}
返回响应;
}
string setInteger(字符串值原始,长整数地址){
int value=stoi(valueRaw);
*(int*)(地址)=值;
返回“完成”;
}
字符串setFloat(字符串值原始,长整数地址){
浮动值=stof(原始值);
*(浮点*)(地址)=值;
返回“完成”;
}
字符串设置字符串(字符串值原始,长整数地址){
字符串值=valueRaw;
*(字符串*)(地址)=值;
返回“完成”;
}
字符串设置工具(字符串值原始,长整数地址){
布尔值=真;
if(valueRaw.compare(“true”)==0){
*(bool*)(地址)=真;
}否则{
*(bool*)(地址)=假;
}
返回“完成”;
}
字符串getInteger(长整数地址){
int&i=*重新解释(地址);
返回到_字符串(i);
}
字符串getFloat(长整型地址){
float&f=*重新解释(地址);
返回到_字符串(f);
}
字符串getString(长整型地址){
string&s=*重新解释(地址);
返回s;
}
s