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