Как улучшить этот Код? (или как передать строку Char в функцию, чтобы она вела себя как переменная)
Извините, я новичок и любитель, когда дело доходит до кодирования, может ли кто-нибудь помочь мне сделать код внутри loop() менее "обезьяньим"? используя правильную функцию?
Я много пробовал, но в какой-то момент у меня закончились идеи о том, как даже сформулировать вопрос в Google.
Моя основная проблема при написании функции для этого случая заключается в том, что я не знаю, как передать переменную в функцию, которая должна быть записана как часть переменной, а также как часть строк символов, если это имеет смысл. .
Если вы посмотрите на код внутри loop(), мне нужно было передать функции только число, например "3" чтобы изменить некоторые переменные и строки символов соответственно. Я мог бы решить проблему с этими строками символов, но я совершенно не знаю, как обращаться с переменной (rmd3, rmd4...).
"3" как в: Переменная: rmd3, строка символов "rmd3 = 1", значение переменной: rotate_mode = 3 и строка символов: "rotary_mode = 3"
Это упрощенная версия моего кода, но она сводится к тому, на чем я застрял. Это относится к поворотному селектору, который я использую, который имеет 6 положений (rmd1 - rmd6). Однако, если бы я знал, как решить эту проблему, я мог бы использовать его и во многих других ситуациях.
Bounce rmd3 = Bounce(45,10); //rotary selector on pos.3
Bounce rmd4 = Bounce(44,10); //rotary selector on pos.4
int rotary_mode = 0; //Rotary Mode
void setup() {
Serial.begin(11520);
pinMode(45, INPUT_PULLUP); //pin of pos.3
pinMode(44, INPUT_PULLUP); //pin of pos.4
}
void loop() {
rmd3.update();
if (rmd3.fallingEdge()) {
Serial.print("rmd3 = 1");
rotary_mode = 3;
Serial.print("rotary_mode = 3");
}
if (rmd3.risingEdge()) {
Serial.print("rmd3 = 0");
rotary_mode = 0;
Serial.print("rotary_mode = 0");
}
rmd4.update();
if (rmd4.fallingEdge()) {
Serial.print("rmd4 = 1");
rotary_mode = 4;
Serial.print("rotary_mode = 4");
}
if (rmd4.risingEdge()) {
Serial.print("rmd4 = 0");
rotary_mode = 0;
Serial.print("rotary_mode = 0");
}
}´´´
Pseudocode:
´´´void loop() {
int rmd_int; //Mode numbers as int from 1 to 6
char rmd_char = [2]; //Mode numbers as char from "1" to "6"
rmd3.update();
rmd_int = 3;
rmd_char = "3";
void selected_mode(rmd_int, rmd_char);
}
void selected_mode(int rmd_int, char rmd_char ){
if (rmd[rmd_int].fallingEdge()) {
Serial.print("rmd[rmd_char] = 1");
rotary_mode = [rmd_int];
Serial.print("rotary_mode = [rmd_char]");
}
if (rmd[rmd_int].risingEdge()) {
Serial.print("rmd[rmd_char] = 0");
rotary_mode = 0;
Serial.print("rotary_mode = 0");
}
}```
@Baka, 👍1
Обсуждение1 ответ
Вопрос несколько запутанный, но, кажется, я понял, что вы имеете в виду. Ваш код страдает от слишком большого количества повторений. Вы только показали обработку два селектора, но вы хотите обрабатывать 6 из них. Повторяю всю логику 6 раз сделали бы код громоздким и сложным в обслуживании. Так что вы хотите поместить логику в функцию и просто вызвать эту функцию шесть раз.
На самом деле мне нужно было только передать номер функции, например "3" к соответствующим образом измените некоторые переменные и строки символов
Вам не нужно передавать число в виде строки: вы можете использовать
Serial.print()
для форматирования числа. И вам не нужно
также напишите функцию: вы можете просто поместить цикл for
внутри
Функция loop()
:
const int rmd_count = 6;
Bounce rmd[rmd_count] = {
Bounce(48, 10), // поворотный переключатель на поз. 0
Bounce(47, 10), // поворотный переключатель на поз. 1
Bounce(46, 10), // поворотный переключатель на поз. 2
Bounce(45, 10), // поворотный переключатель на поз. 3
Bounce(44, 10) // поворотный переключатель на поз. 4
Bounce(43, 10) // поворотный переключатель на поз. 5
};
void loop() {
for (int i = 0; i < rmd_count; i++) {
rmd[i].update();
if (rmd[i].fallingEdge()) {
Serial.print("rmd[");
Serial.print(i);
Serial.println("] = 1");
rotary_mode = i;
Serial.print("rotary_mode = ");
Serial.println(i);
}
if (rmd[i].risingEdge()) {
Serial.print("rmd[");
Serial.print(i);
Serial.println("] = 0");
rotary_mode = 0;
Serial.println("rotary_mode = 0");
}
}
}
Ключом к использованию циклов for
является структурирование данных в виде массивов,
вместо коллекций переменных, названных цифрами. Таким образом, вместо
rmd3
вы должны использовать rmd[3]
. Обратите внимание, что индексы массива начинаются с нуля.
Конечно, вы можете поместить тело цикла for
внутрь функции,
но на данный момент это не сильно поможет упростить код.
Правка. В качестве пояснения и по предложению Delta_G я попытаюсь объяснить разницу между массивом и набором переменных. Каждая определяемая вами переменная отображается компилятором (технически линкер) в область памяти. Вы можете думать об именах переменных как удобные имена, присвоенные этим ячейкам памяти. Если вы пишете:
Bounce rmd0(48, 10), rmd1(47, 10), rmd2(46, 10), ...;
Вы получаете:
┌───────┐ ┌───────┐ ┌───────┐
rmd0: | | rmd1: | | rmd2: | | ...
└───────┘ └───────┘ └───────┘
На рисунке выше прямоугольники — это области памяти. они большие
достаточно для размещения объекта Bounce
, т.е. их размер равен sizeof(Bounce)
.
У каждого есть имя. Вы не можете контролировать, где в памяти
эти переменные выделяются: это вызов компоновщика.
Наоборот, при объявлении массива вы получаете одну переменную. которая отображается на непрерывную область памяти, достаточно большую, чтобы вместить весь массив:
Bounce rmd[6] = { ... };
Дает:
┌───────┬───────┬───────┬───────┬───────┬───────┐
rmd: | | | | | | |
└───────┴───────┴───────┴───────┴───────┴───────┘
У отдельных ячеек нет имени, вместо этого вы используете индексы для
получить к ним доступ. Например, rmd[0]
ссылается на первую ячейку. Пожалуйста,
обратите внимание, что в этом примере нет переменной с именем rmd0
: если вы попробуете
чтобы использовать этот идентификатор, компилятор будет жаловаться, что он не определен.
Опять же, массив — это не «набор переменных»: это один
переменная.
Ячейки массива ведут себя в некотором смысле так же, как отдельные переменные.
(они называются lvalues), так как вы можете использовать rmd[0]
так же, как вы
использовал бы rmd0
в предыдущем коде. Смысл использования массива
заключается в том, что индексы не обязательно должны быть литералами: вы можете использовать переменную
вместо этого (rmd[i]
, где i
— переменная), что удобно, когда вы
хотите перебрать все ячейки.
Эдгар указал, что я могу записать переменную
rmd3
с помощьюint i = 3
иrmd[i]
.
Надеюсь, теперь понятно, что это не так. Нет переменной
с именем rmd3
, если вы не создали его явно. Объявление массива с именем
rmd
не создает такую переменную.
[Могу ли я] "формировать" переменная по "символам"?
Ваш вопрос не очень ясен, но я предполагаю, что вы имеете в виду имена вычисляемых переменных. Это метод программирования, при котором вы получить доступ к переменной, вычислив ее имя во время выполнения. Например, вы объединить строки "rmd" и "3" для того, чтобы построить имя переменная "rmd3". Затем вы используете это вычисленное имя для доступа к переменной с этим именем.
Имена вычисляемых переменных довольно часто поддерживаются интерпретируемыми языки. Например, в PHP это называется переменные-переменные:
$foobar = 42; // переменная, к которой мы хотим получить доступ
$start = "foo"; // одна часть имени
$end = "bar"; // другая часть
$name = $start . $end; // строим имя из его частей
print $name . "\n"; // печатает имя переменной: "foobar"
print $$name . "\n"; // печатает значение переменной: "42"
Имена вычисляемых переменных не поддерживаются C++, т.е. язык, который вы используете для программирования Arduino. И не зря: когда компилятор переводит вашу программу в машинный код, имена переменные теряются, они не попадают в настоящую Arduino. И это хорошо, так как вы не хотите, чтобы эти имена потребляли память на микроконтроллере.
Обратите внимание, что имена присутствуют в файле .elf, так как они могут
полезно для отладки. Если вы программировали для ПК, вы программируете
в принципе мог заглянуть в файл и найти эти имена. В Linux вы
сделал бы это с помощью dlopen()
и dlsym()
функции из библиотеки libdl. Техника libdl, однако, очень
далеки от возможностей вашего типичного Arduino, на порядки
более сложный, чем простой массив, и совершенно бесполезный для вашего использования
дело.
Блестяще, спасибо! Я не знал, что могу сформировать переменную rmd3 с помощью rmd[i] и int i=3. Теперь мне интересно, работает ли это только с числами или будет ли это работать с чем-то вроде char i[] = "3"., @Baka
Я думаю, что этот ответ был бы значительно улучшен, если бы было очевидно, что вы используете массив, а не список переменных, которые были у OP. Из вопроса в этом комментарии может показаться, что ОП все еще не понимает, как это будет работать., @Delta_G
Вы не «формируете переменную» с помощью rmd[i] и 3. Он полностью избавился от ваших переменных и создал массив. С массивом вы можете использовать индекс, чтобы выбрать, о каком элементе массива вы хотите говорить, в данном случае элемент 3, который является четвертым элементом, поскольку подсчет всегда начинается с 0. Обратите внимание на строку, которая начинается «Bounce rmd [rmd_count]» где создается массив. Обратите внимание, что мы ни в коем случае не создаем ничего под названием rmd3. Вместо этого мы создаем массив с простым названием rmd (без номеров), который содержит несколько таких объектов Bounce., @Delta_G
Да, я понял, он использует массив, но английский не мой родной язык, поэтому я не знал, как его еще назвать. Итак, если переменные - это просто адреса, будет ли это как-то работать с указателями? Все, что меня волнует, это результат... я получил более 1800 строк кода для одной и той же хрени, повторяющейся снова и снова, но только с разными переменными. Единственный пункт кода, который я разместил сначала, чтобы сделать его «легким», иначе мне пришлось бы пропустить 1800 строк кода., @Baka
- Получение имени перечисления из экземпляра перечисления
- Использование StringStream в скетче Arduino
- Чтение строки, разделенной запятыми
- Объявленная переменная внутри void setup не видится в void loop
- Преимущества глобальных переменных перед статическими членами класса?
- Возможно ли, чтобы функция возвращала строку ИЛИ число, в зависимости от адреса
- Как на самом деле объединить две строки?
- Использование строк внутри кода расширений mBlock
Я действительно не понимаю, что вы там говорите. Вы говорите о предоставлении строки char в качестве параметра функции, но я не вижу такой функции в вашем коде. Вы не показываете никаких функций, кроме стандартных функций
loop()
иsetup()
. И описание, к сожалению, беспорядок. Я понимаю, что это сложно объяснить, когда у тебя могут быть неверные представления или недостаточное понимание, чтобы подобрать правильные слова. Может быть, вы можете показать нам прямо с вашим кодом, что вы пытаетесь сделать., @chrislВы хотите передать массив символов в качестве аргумента функции?, @Gerben
Иногда может помочь написать «псевдокод», чтобы описать, как вы хотите, чтобы ваша программа работала. Здесь нет правил синтаксиса, и вы ничего не можете сделать — просто пишите свой код так, как будто все, что вы хотите сделать, можно сделать так, как вы хотите. Тогда мы сможем понять, что именно вы собираетесь делать в своем коде., @Majenko
Всякий раз, когда вы начинаете добавлять числа к именам переменных, а затем хотите их использовать, вам действительно нужен массив. С помощью массива вы можете использовать эти числа для обозначения разных вещей. То, что вы хотите сделать с массивом символов, не сработает. Имена Арии меня существуют только в коде, когда вы его пишете. Все они становятся адресами памяти после компиляции кода. Нет концепции имени переменной во время выполнения., @Delta_G
Я добавил псевдокод, чтобы вы могли получить представление о том, что я имею в виду. Сначала пропустил это, потому что я знаю, что это неправильно и может вызвать путаницу., @Baka
Однако все еще неясно, почему вы хотите использовать char. Это просто, чтобы вы могли распечатать число 3? Если это то, что вам нужно, Serial.print(rmd_int); сделает это за вас. И если вы хотите распечатать целое число внутри строки, вы можете использовать Serial.printf("здесь есть int: %i", rmd_int);, @tavis