Оператор умножения с фигурными скобками или без них

Я написал простую программу-калькулятор для экрана с ЖК-клавиатурой. Он работает нормально, за исключением случая умножения. Это дает мне ноль. Однако я заметил, что когда я заключаю выражение 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);
}

, 👍0

Обсуждение

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

Я также не думаю, что скобки не имеют значения. Однако я не вижу никаких проблем с использованием parseFloat. Кажется, это работает для других операций. Вы видите здесь проблему?, @Zaffresky


1 ответ


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

0

Скобки определенно не должны иметь значения. Я предполагаю, что то, что вы видели, было просто совпадением. Аналоговые диапазоны, которые вы определили являются чрезвычайно узкими. Любая нестабильность в цепи может вывести вас из строя. показания выходят за пределы ожидаемых диапазонов. Если вы получаете чтение, которое не помещается в любой из этих диапазонов, ни одно из условий if не будет оцениваться как true, и вы получите нулевой результат, так как именно так вы инициализировал переменную ans.

Я предлагаю внести в вашу программу два изменения:

  1. Увеличить диапазоны
  2. Неоднократно считывайте аналоговый ввод, пока не получите достоверные показания.

Чтобы проиллюстрировать второй пункт, вот фрагмент кода, который разбивает логика вашей цепочки 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