将参数值 - 字符串和链接值(类型为字符串)解析为变量(特定类型)

时间:2018-02-27 22:27:29

标签: c++

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

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

string name;
int counter;
//...
float temperature;
bool enableState;

要手动设置参数值,应通过命令行接受字符串(例如" Name = Eric"," Counter = 100"," Temperature = 20.0& #34; ......)

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

无论我尝试做什么都不会导致任何事情,或者这是一项巨大的努力,这让我相信一个可能(简单)的解决方案可能并不是一件容易的事。

代码应该在arduino上运行。

修改 我找到了一种方法,它似乎工作得很好。但我不确定,也许我做了根本性的错误。您能否确认我的答案中的代码是合法的,因此我可以将问题设置为“已解决”?

4 个答案:

答案 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::anyboost::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);

有没有人看到任何问题? 根据我的理解,全局对象的内存地址必须在整个运行时期间保持不变。那是对的吗? 字符串怎么样?由于没有明确给出字符串的大小,如何在编译时分配字符串的内存?我猜,只有字符串的起始地址被分配。