Передача аргументов в LCD.print через другую функцию
Я бы хотел написать такую функцию:
void lcdPositionPrint(int row, int col, content) {
lcdPosition(row, col);
LCD.print(content);
}
но я не уверен, как объявить "контент", потому что это может быть строка, или целое число, или кто знает что, точно так же, как для функции "Serial.print" или LCD.print( ) функция. Есть простой способ сделать это?
@John, 👍2
2 ответа
Лучший ответ:
Хорошего способа сделать это не существует, но есть несколько способов заставить его работать. Большая часть проблемы здесь заключается в том, что на самом деле для каждого типа данных существует отдельная функция LCD.print
. На самом деле вы вызываете не одну и ту же функцию, а разные функции с одним и тем же именем.
Вы можете использовать шаблоны. Это мощная система, встроенная в C plus plus для создания функций, и avr-gcc хорошо их поддерживает. С их помощью вы можете заставить компилятор сгенерировать для вас все необходимые версии вашей функции. Тогда ваша функция будет выглядеть так:
template<typename T>
void lcdPositionPrint(int x, int y, T content) throw() {
lcdPosition(row, col);
LCD.print(content);
}
Эта часть о throw()
ничего не делает, кроме того, что препроцессор ".ino" не испортит функцию шаблона. Вы можете вызвать шаблонную функцию, как обычно, или с явным типом
lcdPositionPrint(0,0,"hello");
lcdPositionPrint<float>(0,0,32.0f);
Вы также можете использовать препроцессор. Ваша функция очень проста, поэтому вы можете так же легко сделать ее макросом препроцессора, который просто помещает нужный вам код в файл всякий раз, когда ваш "вызов функции" появляется. Это выглядит так:
#define lcdPositionPrint2(row,col,content) \
do { lcdPosition(row, col); LCD.print(content); } while (0)
Там \
сообщает препроцессору, что следующая строка также является частью макроса, и вам потребуется по одному макросу в каждой строке, кроме последней, в вашей функции. Оборачивая его в цикл do
, который сразу же завершается, он прекрасно подходит для большего количества ситуаций. Микросхемы плохо масштабируются, но они немного проще для быстрой отладки. Однако код дублируется в каждом месте вызова, а не объединяется в функции.
Один из способов сделать это — использовать универсальные шаблоны. И нам также нужно использовать безымянное пространство имен, чтобы обойти "полезность" IDE:
namespace {
template<typename T>
void lcdPositionPrint(int row, int col, T content) {
lcdPosition(row, col);
LCD.print(content);
}
}
Это приведет к тому, что компилятор создаст одну функцию для каждого типа, переданного в content
, с которым фактически вызывается функция.
Большое спасибо. Я не знал, что есть шаблоны для работы!, @John
- Будет ли бесконечный цикл внутри loop() работать быстрее?
- Будет ли .ino-скетч ардуино компилироваться непосредственно на GCC-AVR?
- Поскольку double и float представляют один и тот же тип данных (обычно), что предпочтительнее?
- Как писать скетчи, совместимые с makefile?
- Преимущества глобальных переменных перед статическими членами класса?
- Новый язык — взаимодействие с AVR
- Как объявить массив переменного размера (глобально)
- Программирование Arduino с использованием Python, а не C/C ++
Спасибо; Я не знал, что в языке существуют шаблоны. (Честно говоря, хотя я написал несколько сотен строк, я никогда не понимал, на каком языке я использую — я просто как бы накручиваю его). Мое собственное решение состояло в том, чтобы написать две почти идентичные копии, одну для «int content» и одну для «String content», и это охватывало все мои основы., @John
Еще одна мысль: улучшенная версия вашего препроцессора заключает в фигурные скобки {lcdPosition(row, col); LCD.print(content);} строки, чтобы «if (x < 10) lcdPositionPrint(r, c, 14); <other code>» не всегда приводило к печати «14» либо в (r, c) или в текущем местоположении курсора., @John
Вот для чего нужно обернуть его в
do { ... } while (0)
(и все другие проблемы, которые могут возникнуть при простом использовании фигурных скобок)., @Ignacio Vazquez-Abrams