Оператор умножения с фигурными скобками или без них
Я написал простую программу-калькулятор для экрана с ЖК-клавиатурой. Он работает нормально, за исключением случая умножения. Это дает мне ноль. Однако я заметил, что когда я заключаю выражение num1 * num2 в круглые скобки, оно работает. Почему так?
#include <LiquidCrystal.h>
LiquidCrystal lcd (8, 9, 4, 5, 6, 7);
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.clear();
}
void loop() {
float ans = 0;
lcd.print("Starting Calc");
delay(500);
lcd.clear();
lcd.print("Enter 1st Num");
while (Serial.available() == 0) {}
float num1 = Serial.parseFloat();
lcd.clear();
lcd.print("Enter 2nd Num");
while (Serial.available () == 0) {}
float num2 = Serial.parseFloat();
lcd.clear();
lcd.print("Enter Operator");
lcd.setCursor(0, 1);
lcd.print(" R+, U*, D/, L- ");
int val = analogRead(A0);
while (val > 1000) {
val = analogRead(A0);
}
if (val == 0) { // сложение
ans = num1 + num2;
}
if (val >= 97 && val <= 98) { // умножение
ans = num1 * num2;
}
if (val >= 253 && val <= 254) { // деление
ans = num1 / num2;
}
if (val >= 407 && val <= 408) { // вычитание
ans = num1 - num2;
}
lcd.clear();
lcd.print("Answer is = ");
lcd.print(ans);
delay(2000);
}
Измененный код
#include <LiquidCrystal.h>
LiquidCrystal lcd (8, 9, 4, 5, 6, 7);
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.clear();
}
void loop() {
float ans = 0.0;
lcd.print("Starting Calc");
delay(500);
lcd.clear();
lcd.print("Enter 1st Num");
while (Serial.available() == 0) {}
float num1 = Serial.parseFloat();
lcd.clear();
lcd.print("Enter 2nd Num");
while (Serial.available () == 0) {}
float num2 = Serial.parseFloat();
lcd.clear();
lcd.print("Enter Operator");
lcd.setCursor(0, 1);
lcd.print(" R+, U*, D/, L- ");
// здесь мы разделяем нашу логику.. сначала многократно читаем входное значение, пока не будет прочитан действительный оператор
// во-вторых, выполняем арифметическую операцию соответственно
char input = ' '; // пробел = оператор пока не прочитан
int val;
do {
val = analogRead(A0);
// посмотрим, как операторы if написаны лаконично для удобочитаемости
// если только один оператор после условия, вы можете пропустить фигурные скобки
if (val == 0) input = '+';
if (val >= 97 && val <= 98) input = '*';
if (val >= 253 && val <= 254) input = '/';
if (val >= 407 && val <= 408) input = '-';
} while (input == ' ');
Serial.println(input);
Serial.println(num1);
Serial.println(num2);
delay(1000);
// выполняем арифметическую операцию
switch (val) { // написано не стандартно, но очень читабельно
case '+': ans = num1 + num2; break;
case '-': ans = num1 - num2; break;
case '*': ans = num1 * num2; break;
case '/': ans = num1 / num2; break;
}
lcd.clear();
lcd.print("Answer = ");
lcd.print(ans);
delay(2000);
}
@Zaffresky, 👍0
Обсуждение1 ответ
Лучший ответ:
Скобки определенно не должны иметь значения. Я предполагаю, что
то, что вы видели, было просто совпадением. Аналоговые диапазоны, которые вы определили
являются чрезвычайно узкими. Любая нестабильность в цепи может вывести вас из строя.
показания выходят за пределы ожидаемых диапазонов. Если вы получаете чтение, которое не
помещается в любой из этих диапазонов, ни одно из условий if
не будет оцениваться как
true
, и вы получите нулевой результат, так как именно так вы
инициализировал переменную ans
.
Я предлагаю внести в вашу программу два изменения:
- Увеличить диапазоны
- Неоднократно считывайте аналоговый ввод, пока не получите достоверные показания.
Чтобы проиллюстрировать второй пункт, вот фрагмент кода, который разбивает
логика вашей цепочки if
состоит из двух частей: сначала прочитайте оператор
(неоднократно, пока не получим корректное показание), затем выполняем операцию:
// Читаем оператор.
char op = ' '; // пробел = оператор пока не прочитан
do {
int val = analogRead(A0);
if (val == 0) op = '+';
if (val >= 97 && val <= 98) op = '*';
if (val >= 253 && val <= 254) op = '/';
if (val >= 407 && val <= 408) op = '-';
} while (op == ' ');
// Выполнить операцию.
switch (op) {
case '+': ans = num1 + num2; break;
case '*': ans = num1 * num2; break;
case '/': ans = num1 / num2; break;
case '-': ans = num1 - num2; break;
}
Большое спасибо за четкое объяснение. Я полностью согласен с тем, что иногда я получал 0 из-за нестабильности схемы. Я не знал о циклах do... while, но теперь знаю :) Теперь программа должна была работать, но таинственным образом переменная «ans» не обновляется регистром переключателей. Я пробовал это с операторами if, но это также не работает. Интересно, чем это вызвано? Ps Я загрузил модифицированный код в исходный пост., @Zaffresky
@Zaffresky: Ой, мой плохой! «Переключение» должно выполняться на выбранном операторе, а не на аналоговом значении. Я только что отредактировал ответ., @Edgar Bonet
Бинго. Это работает хорошо :) Спасибо, @Zaffresky
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Я думаю, вы ищете не в том месте. Скобки не имеют значения. Вместо этого вы должны смотреть на использование parseFloat., @Majenko
Я также не думаю, что скобки не имеют значения. Однако я не вижу никаких проблем с использованием parseFloat. Кажется, это работает для других операций. Вы видите здесь проблему?, @Zaffresky