Как улучшить этот Код? (или как передать строку 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");
             }
}```

, 👍1

Обсуждение

Я действительно не понимаю, что вы там говорите. Вы говорите о предоставлении строки char в качестве параметра функции, но я не вижу такой функции в вашем коде. Вы не показываете никаких функций, кроме стандартных функций loop() и setup(). И описание, к сожалению, беспорядок. Я понимаю, что это сложно объяснить, когда у тебя могут быть неверные представления или недостаточное понимание, чтобы подобрать правильные слова. Может быть, вы можете показать нам прямо с вашим кодом, что вы пытаетесь сделать., @chrisl

Вы хотите передать массив символов в качестве аргумента функции?, @Gerben

Иногда может помочь написать «псевдокод», чтобы описать, как вы хотите, чтобы ваша программа работала. Здесь нет правил синтаксиса, и вы ничего не можете сделать — просто пишите свой код так, как будто все, что вы хотите сделать, можно сделать так, как вы хотите. Тогда мы сможем понять, что именно вы собираетесь делать в своем коде., @Majenko

Всякий раз, когда вы начинаете добавлять числа к именам переменных, а затем хотите их использовать, вам действительно нужен массив. С помощью массива вы можете использовать эти числа для обозначения разных вещей. То, что вы хотите сделать с массивом символов, не сработает. Имена Арии меня существуют только в коде, когда вы его пишете. Все они становятся адресами памяти после компиляции кода. Нет концепции имени переменной во время выполнения., @Delta_G

Я добавил псевдокод, чтобы вы могли получить представление о том, что я имею в виду. Сначала пропустил это, потому что я знаю, что это неправильно и может вызвать путаницу., @Baka

Однако все еще неясно, почему вы хотите использовать char. Это просто, чтобы вы могли распечатать число 3? Если это то, что вам нужно, Serial.print(rmd_int); сделает это за вас. И если вы хотите распечатать целое число внутри строки, вы можете использовать Serial.printf("здесь есть int: %i", rmd_int);, @tavis


1 ответ


3

Вопрос несколько запутанный, но, кажется, я понял, что вы имеете в виду. Ваш код страдает от слишком большого количества повторений. Вы только показали обработку два селектора, но вы хотите обрабатывать 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