Arduino std::map, возвращающий случайные значения
Я работаю с Arduino UNO. Я хотел бы иметь возможность отправлять ему команды set
и get
через последовательный порт и обновлять члены класса данных класса соответственно по паре значений ключа. Я разговаривал с пользователями в комнате cpp, и они предложили мне попробовать использовать карту для сопоставления каждого ключа со значением.
структура команды
команда:ключ:значение
пр. set:key1:20
бывший. get:key2
Я создал класс Uno, назначил все свои ключи частным членам данных и определил функции set и get. Однако у меня наблюдается непредвиденное поведение.
Непреднамеренное поведение
В конечном итоге функция set устанавливает для key1
и key2
одно и то же значение, а функция get
возвращает случайное целочисленное значение, которое не было присвоено.
#include <ArduinoSTL.h>
#include <string.h>
#include <map>
class Uno{
//частный
int key1;
int key2;
std::map<String, int Uno::*> keys;
public:
//Конструктор
Uno(){
key1 = 0;
key2 = 0;
keys["key1"] = &Uno::key1;
keys["key2"] = &Uno::key2;
}
bool setKey(String key, int value){
if (keys.count(key)) {
this->*keys[key] = value;
return true;
}
return false;
}
int getKey(String key){
if (keys.count(key)) {
return this->*keys[key];
}
}
};
String inputString = ""; // строка для хранения входящих данных
bool stringComplete = false; // является ли строка полной
bool scan = false; // выполняется ли сканирование
Uno myMS; // глобальное объявление класса Mass Spec
void setup() {
// инициализируем серийный номер:
Serial.begin(9600);
// резервируем 250 байт для входной строки:
inputString.reserve(250);
}
void loop() {
if (stringComplete) {
t(inputString); // токенизация и обработка строки
//СБРОС СТРОКИ
inputString = "";
stringComplete = false;
}
}
void serialEvent() {
while (Serial.available()) {
// получаем новый байт:
char inChar = (char)Serial.read();
// добавляем его во входную строку:
inputString += inChar;
// если входящий символ является новой строкой, установите флаг, чтобы основной цикл мог
// делаем что-нибудь с этим:
if (inChar == '\n') {
stringComplete = true;
}
}
}
void t(String inputString) {
//получить команду
String command = getValue(inputString, ':', 0);
if(command == "set"){
// получаем ключ, получаем значение
String key = getValue(inputString, ':', 1);
int value = (getValue(inputString, ':', 2)).toInt();
Serial.println(myMS.setKey(key,value));
}
else if(command == "get"){
String key = getValue(inputString, ':', 1);
int value = myMS.getKey(key);
Serial.println(value);
}
else if(command == "stop"){
scan = false;
}
else if(command == "scan"){
scan = true;
while(scan){
// Serial.println(myMS.scan());
}
}
else{
Serial.println("not recognized");
}
}
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
РЕДАКТИРОВАТЬ: Вот рабочая демонстрация концепции REPL IT, предоставленная nwp. https://repl.it/repls/AntiqueProductiveMineral
Пример вывода
set:key1:10 ===> 1 (GOOD)
get:key1 ===> 32512
@ex080, 👍2
Обсуждение1 ответ
Лучший ответ:
Вы получаете случайные значения, потому что, если ключ не найден в getKey, оператор возврата отсутствует.
Вы прикрепляете \n к ключу в SerialEvent(), тогда ключом для getKey является «key1\n», и он не найден.
void serialEvent() {
while (Serial.available()) {
// получаем новый байт:
char inChar = (char)Serial.read();
if (inChar == '\n') {
stringComplete = true;
} else {
inputString += inChar;
}
}
}
Если в последовательном мониторе установлен CR/LF, то также отправляется символ \r и анализируемый ключ — «key1\r\n».
В вашем коде есть устаревшие элементы, например this->* или Uno::. Создайте карту std::map<String, int> клавиши;
, потому что теперь вы смешиваете указатели и целые числа.
У меня есть только Newline, и он все равно не работает, @KIIV
измените серийное событие, чтобы не прикреплять \n к строке, @Juraj
Да, он не пропускает это в этом парсере :D, @KIIV
Хорошо, мне нравится ваш подход, он работает!, @ex080
- C++ против языка Arduino?
- Как использовать SPI на Arduino?
- Какие накладные расходы и другие соображения существуют при использовании структуры по сравнению с классом?
- Ошибка: expected unqualified-id before 'if'
- Что лучше использовать: #define или const int для констант?
- Функции со строковыми параметрами
- Библиотека DHT.h не импортируется
- ошибка: ожидаемое первичное выражение перед токеном ','
почему вы думаете, что это вопрос Arduino? ... похоже, это вопрос C/C++, @jsotola
@jsotola Это вопрос об Arduino, потому что я запускаю код на Arduino, используя тип String arduino. Я также использую Serial на Arduino. Я открыт для других методов Arduino для хранения пар ключ-значение., @ex080
32512 — это возвращаемое значение getKey, если он не нашел ключ, @Juraj
Хорошо, но это сбивает с толку, потому что я использую тот же метод для установки. Я знаю, что функция set работает правильно, потому что если я выполню
Serial.println(key1);
изнутри класса, она напечатает правильное значение., @ex080