Передача аргументов в LCD.print через другую функцию

Я бы хотел написать такую функцию:

void lcdPositionPrint(int row, int col,  content) {
    lcdPosition(row, col);
    LCD.print(content);
}

но я не уверен, как объявить "контент", потому что это может быть строка, или целое число, или кто знает что, точно так же, как для функции "Serial.print" или LCD.print( ) функция. Есть простой способ сделать это?

, 👍2


2 ответа


Лучший ответ:

1

Хорошего способа сделать это не существует, но есть несколько способов заставить его работать. Большая часть проблемы здесь заключается в том, что на самом деле для каждого типа данных существует отдельная функция 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, который сразу же завершается, он прекрасно подходит для большего количества ситуаций. Микросхемы плохо масштабируются, но они немного проще для быстрой отладки. Однако код дублируется в каждом месте вызова, а не объединяется в функции.

,

Спасибо; Я не знал, что в языке существуют шаблоны. (Честно говоря, хотя я написал несколько сотен строк, я никогда не понимал, на каком языке я использую — я просто как бы накручиваю его). Мое собственное решение состояло в том, чтобы написать две почти идентичные копии, одну для «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


1

Один из способов сделать это — использовать универсальные шаблоны. И нам также нужно использовать безымянное пространство имен, чтобы обойти "полезность" IDE:

namespace {
    template<typename T>
    void lcdPositionPrint(int row, int col, T content) {
        lcdPosition(row, col);
        LCD.print(content);
    }
}

Это приведет к тому, что компилятор создаст одну функцию для каждого типа, переданного в content, с которым фактически вызывается функция.

,

Большое спасибо. Я не знал, что есть шаблоны для работы!, @John