如果参数数据类型不同,您将如何构造一组参数值对?
假设您有一大组参数绑定在较大的软件中,如下所示:
string name;
int counter;
//...
float temperature;
bool enableState;
要手动设置参数值,应通过命令行接受字符串(例如" Name = Eric"," Counter = 100"," Temperature = 20.0& #34; ......)
搜索适用于参数的结构,以便它们(或至少读取/写入它们的信息)可以存储在数组中。由于值具有不同的数据类型,因此它们不能存储在数组中,但是它们的指针(?)是否有用。 如何将输入字符串的(字符串)值分配给具有修复数据类型的变量?
无论我尝试做什么都不会导致任何事情,或者这是一项巨大的努力,这让我相信一个可能(简单)的解决方案可能并不是一件容易的事。
代码应该在arduino上运行。
修改 我找到了一种方法,它似乎工作得很好。但我不确定,也许我做了根本性的错误。您能否确认我的答案中的代码是合法的,因此我可以将问题设置为“已解决”?
答案 0 :(得分:1)
你可以使用std::map<std::string, std::function<void(std::string&)>> 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);
答案 1 :(得分:1)
你可能有一个struct将数据存储为unsigned char *,然后有一些关于如何解码struct中unsigned char *的元数据。像
这样的东西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 ++中的任何数据类型(甚至结构)!
我在gcc 6.4.0上对此进行了测试,但我不知道它是否适用于avr-g ++。如果您愿意,我可以提供更多信息。
答案 2 :(得分:1)
查看import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
# AES Cipher implementation by Mariano Guezuraga
BS = 16
def pad(s):
return s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
def unpad(s):
return s[0:-s[-1]]
def encrypt(raw, key):
key = hashlib.sha256(key.encode('utf-8')).digest()
raw = pad(raw)
iv = Random.new().read(AES.block_size)
localcipher = AES.new(key, AES.MODE_CBC, iv)
return base64.b64encode(iv + localcipher.encrypt(raw)).decode("utf-8")
def decrypt(enc, key):
key = hashlib.sha256(key.encode('utf-8')).digest()
enc = base64.b64decode(enc)
iv = enc[:16]
localcipher = AES.new(key, AES.MODE_CBC, iv)
return unpad(localcipher.decrypt(enc[16:])).decode("utf-8")
或std::variant
(两者均可在C ++ 17中找到)。如果您使用的是早期标准,则会提供std::any
和boost::variant
。
答案 3 :(得分:0)
我找到了一种方法,但我不确定是否会遇到内存分配问题。除了其他人,我还需要链接到全局字符串变量的字符串参数。参数也必须是全局的。我将变量与其内存地址的参数相关联,但我不确定这是否合法...... 我的解决方案是:
#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);
有没有人看到任何问题? 根据我的理解,全局对象的内存地址必须在整个运行时期间保持不变。那是对的吗? 字符串怎么样?由于没有明确给出字符串的大小,如何在编译时分配字符串的内存?我猜,只有字符串的起始地址被分配。