Использование StringStream в скетче Arduino
Я узнал о StringStream потоке сегодня на работе.
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <string.h>
using namespace std;
char* getSql() {
float outdoorTempInC = 15;
int outoorHumidity = 23;
float indorTempinC = 20;
int humidity = 22;
int val = 400; // soil sensor reading
int avgVal = 38; // avaerage of 10 values of soils sensor
char statusMsg[50] = {"Hello World"} ;
std::stringstream sqlQuery;
sqlQuery << "INSERT INTO arduinoSensorData.sensorLog (out_temperature, "
<< "out_humidity, drwngRoom_temperature, drwngRoom_humidity, "
<< "pot1_soilMoisture, pot1_avg_SoilMoisture, wateringPot1) VALUES ('"
<< outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
<< "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
<< statusMsg << "');";
char *mychar = new char[sqlQuery.str().length() + 1];
strcpy(mychar, sqlQuery.str().c_str());
return mychar;
}
string getSqlStream() {
float outdoorTempInC = 15;
int outoorHumidity = 23;
float indorTempinC = 20;
int humidity = 22;
int val = 400; // soil sensor reading
int avgVal = 38; // avaerage of 10 values of soils sensor
char statusMsg[50] = {"Hello World"} ;
std::stringstream sqlQuery;
sqlQuery << "INSERT INTO arduinoSensorData.sensorLog (out_temperature, "
<< "out_humidity, drwngRoom_temperature, drwngRoom_humidity, "
<< "pot1_soilMoisture, pot1_avg_SoilMoisture, wateringPot1) VALUES ('"
<< outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
<< "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
<< statusMsg << "');";
return sqlQuery.str();
}
int main() {
string sql = getSqlStream();
cout << getSql() << "\n";
cout << sql.c_str() << "\n";
return 0;
}
Я был очень счастлив, пока не обнаружил, что не могу использовать StringStream в Arduino, поэтому я порылся в Интернете и наткнулся на это.
Поэтому, если я попытаюсь использовать приведенную выше связанную строку gist, как я использовал в своем примере кода, я получу эту ошибку:
error: no match for 'operator<<' (operand types are 'StringStream' and 'const char [60]')
sqlQuery << "INSERT INTO arduinoSensorData.sensorLog (out_temperature, "
^
webServer_Displaying_everything_v01:24: error: 'outdoorTempInC' was not declared in this scope
<< outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
^
webServer_Displaying_everything_v01:24: error: 'outoorHumidity' was not declared in this scope
<< outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
^
webServer_Displaying_everything_v01:24: error: 'indorTempinC' was not declared in this scope
<< outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
^
webServer_Displaying_everything_v01:25: error: 'humidity' was not declared in this scope
<< "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
^
webServer_Displaying_everything_v01:25: error: 'val' was not declared in this scope
<< "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
^
webServer_Displaying_everything_v01:25: error: 'avgVal' was not declared in this scope
<< "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
^
webServer_Displaying_everything_v01:28: error: 'class StringStream' has no member named 'str'
char *mychar = new char[sqlQuery.str().length() + 1];
^
webServer_Displaying_everything_v01:29: error: 'class StringStream' has no member named 'str'
strcpy(mychar, sqlQuery.str().c_str());
Или я делаю это совершенно неправильно? Мне кажется, что я все еще не могу использовать его так, как я сделал в примере. Пожалуйста, помогите.
@Ciasto piekarz, 👍0
Обсуждение2 ответа
Лучший ответ:
Прямой ответ
Программа на C++ и кросс-компиляция в Arduino Yún. Язык скетчей Arduino представляет собой тонкий слой поверх C++, но пространство имен std:: не является легким в той степени, в какой это необходимо для того, чтобы вместить то, что вы цените из стандартной библиотеки C++, в объем памяти небольшой встроенной платы процессора. Смотрите среду Arduino Yun C++? Мост + Кросс-Компилятор.
Серьезное программирование на Arduino
Если вы хотите открыть дверь элегантности C++ на небольших встроенных процессорных платах, таких как более простые ардуино, вам нужно будет выйти за рамки языка скетчей Arduino. Возможно, вам будет и интересно, и полезно научиться перекрестной компиляции и связыванию с помощью набора инструментов GNU, предназначенного для процессора Atmel, который у вас на борту.
Этот более профессиональный подход не для слабонервных, но он делается постоянно. Мы делаем это здесь, в лабораториях TranSeed, каждый день.
Для начала вам не нужно загружать или устанавливать что-либо, кроме программного обеспечения Arduino. Набор инструментов, предназначенный для архитектуры AVR Atmel (используется несколькими платами Arduino), находится в подкаталоге в домашнем каталоге Arduino IDE. Набор инструментов, предназначенный для архитектуры SAM Atmel для Arduino Due, помещается в подкаталог вашего домашнего каталога при настройке IDE для загрузки скетчей в Due.
Возвращаясь к вопросу в этом контексте C++
Как только вы научитесь компилировать и связывать с помощью g++ из цепочки инструментов GNU1 и использовать инструменты загрузки2 вашей программы через USB-порт, вы сможете создать класс шаблонов, чтобы получить элегантность, доступную в C++, например, перегрузку оператора, которая вам нравится.
Проблема с попыткой использовать библиотеку C++ со встроенными целями заключается в том, что система распределения и другие зависимости, вероятно, исчерпают большую часть, если не всю память вашей программы. Класс ostringstream из библиотеки C++ со всеми включенными в него зависимостями не является чрезвычайно скудным.
Подход, который потребляет очень мало памяти и не требует циклов динамического выделения ЦП, заключается в создании шаблона C++, который обертывает статический массив. Размер его буфера может быть одним из параметров шаблона.
Затем вы можете перегрузить оператор << класса, используя эти примеры в качестве руководства. Вы получаете свою элегантность и резко снижаете требования к вычислительным ресурсам.
[1] Как перекрестная компиляция, так и перекрестные ссылки выполняются с помощью g++ (gcc для файлов Aruino и Atmel C в библиотеке). Для плат Arduino, использующих процессоры Atmel на базе AVR, используйте цепочку инструментов AVR GNU. Для Due, в котором используются процессоры Atmel на базе SAM, используйте цепочку инструментов SAM5X GNU.
[2] Программа bossac используется для загрузки в Due. Программа avrdude используется для загрузки в Mega 2560.
ну, у меня нет Arduino Yun, но я скорее собирался купить [Arduino Yun Shield][1], я бы предположил , что это не должно иметь значения, поправьте меня, если я ошибаюсь, пожалуйста ! [1]: https://www.arduino.cc/en/Main/ArduinoYunShield, @Ciasto piekarz
Yun board != Yun shield, @Douglas Daseeco
Спасибо Дуглас, лучший ответ, который я принял, однако я был бы признателен, если бы в вашем ответе вы могли связать текст "перекрестная компиляция", "ссылка с помощью инструмента GNU" и "установка, предназначенная для процессора Atmel", например, в Интернете. Это положит начало процессу обучения. Однако я бы воздержался от прямого перехода на более высокую ступень., @Ciasto piekarz
Этот ответ почти точно соответствует тому пути, по которому мы идем здесь, в лаборатории, и он работает очень хорошо. Большинство серьезных встраиваемых программистов используют микроэмаки для разработки. Мы пытались использовать пространство имен std:: в скетчах для контейнеров и строк, но преимущество перехода на g++ и файл makefile стало очевидным в первую неделю написания реальных программ. Описанный здесь способ работает уже три года и утрояет скорость нашего развития., @Douglas Daseeco
Это не имеет ничего общего с перекрестной компиляцией или связыванием с помощью инструмента GNU. Потоки ввода-вывода действительно присутствуют в Arduino, но попытка включить их приводит к слишком большому двоичному файлу. Это просто не укладывается в память чипа.
Существует несколько решений этой проблемы. Один из них заключается в использовании библиотеки под названием ard-потоки. Другой вариант-использовать облегченную, упрощенную версию stringstream, которой
достаточно для компиляции вашего кода.
#include <string>
namespace ard
{
struct ostringstream
{
ostringstream() = default;
ostringstream(std::string arg) : s(std::move(arg)) {}
const std::string& str() const {
return s;
}
// Arithmetic types: int, float, ...
template <class T>
auto operator<<(T arg) -> decltype(std::to_string(arg), *this) {
s.append(std::to_string(arg));
return *this;
}
// String types: std::string, const char*
template <class T>
auto operator<<(const T& arg) -> decltype(std::string().append(arg), *this) {
s.append(arg);
return *this;
}
// Single char: 'a', '\n', ...
ostringstream& operator<<(char arg) {
s.append(1, arg);
return *this;
}
private:
std::string s;
};
}
Теперь просто замените std::stringstream
на ard::ostringstream
, и он будет работать так, как ожидалось.
- Чтение строки, разделенной запятыми
- Как на самом деле объединить две строки?
- Использование строк внутри кода расширений mBlock
- Как улучшить этот Код? (или как передать строку Char в функцию, чтобы она вела себя как переменная)
- Еще один простой и глупый вопрос о строках C++
- Какие накладные расходы и другие соображения существуют при использовании структуры по сравнению с классом?
- Что лучше использовать: #define или const int для констант?
- Функции со строковыми параметрами
Этот класс не является “потоком” в смысле C++, это "Поток" в смысле Arduino, т. Е. Он предоставляет интерфейс, аналогичный "Последовательному". Вы можете, например, добавить к нему "print()` и" println ()"., @Edgar Bonet
@EdgarBonet итак, в таком случае, как я могу использовать метод "SqlQuery" для хранения переменной в arduino без необходимости использовать " print ()", "println" или "sprintf"?, @Ciasto piekarz
Вся цель этого "строкового потока" состоит в том, чтобы позволить вам ввести в него "print ()" и " println ()"., @Edgar Bonet
Ссылка на StringStream-это "#include<sstream>", который в значительной степени является потоком в смысле C++, а не в смысле Arduino. ОП хочет использовать std C++ в Arduino. Ответ заключается в использовании цепочек инструментов GNU, используемых (и установленных вместе с) средой разработки Arduino, но без препроцессора ino. Нет никакого класса StringStream. Класс является ostringstream, и его цель состоит в том, чтобы предоставить методы добавления с помощью << оператор. Println никогда не используется. \n, \r\n или предпочтительно std::endl используется для завершения строки, а sprintf может использоваться или не использоваться в методах ostringstream., @Douglas Daseeco