Не удается получить ввод с клавиатуры 4x4
Я бы хотел сделать какой-нибудь простой калькулятор. В настоящее время я борюсь с входными данными. Я хотел получить от пользователя некоторые числовые данные, затем я хотел бы иметь информацию о том, какой тип вычислений он собирается выполнить. Я не уверен почему, но я не могу получить никаких числовых данных от пользователя, потому что программа "перескакивает" вперед к типу операции. Вот некоторый код:
void loop(){
int a = getNumber();
if(a != NO_KEY){
do{
operationType = getOperationType();
}while(!operationType);
}
}
Получить номер
int getNumber(){
char userInput = customKeypad.getKey();
int value;
if (userInput == '0' || userInput == '1' || userInput == '2' || userInput == '3' || userInput == '4' || userInput == '5' ||
userInput == '6' || userInput == '7' || userInput == '8' || userInput == '9'){
value = userInput - '0';
Serial.println("value");
Serial.println(value);
}
return value;
}
getOperationType getOperationType
char getOperationType(){
char userInput = customKeypad.getKey();
switch (userInput){
case '+':
// add(a , b);
Serial.println("add");
break;
case '-':
// subtract(a , b);
Serial.println("subtract");
break;
case '*':
// multiply(a , b);
Serial.println("multiply");
break;
case '/':
// divide(a , b);
Serial.println("Divide");
break;
case 'C':
// TODO
break;
}
return userInput;
}
Могу ли я получить какой-нибудь намек на то, почему я не могу просто получать простые вводы с клавиатуры?
@user851242, 👍-1
Обсуждение1 ответ
Лучший ответ:
Вам нужно следить за тем, что вы возвращаете, и инициализированы ли ваши переменные. Итак, что здесь происходит:
В loop()
вы вызываете getNumber()
. Там вы объявляете две переменные:
userInput
, который вы инициализируете возвращаемым значениемcustomKeypad.getKey()
. Таким образом, эта переменная будет иметь значениеNO_KEY,
если ни одна клавиша не нажата.значение
, которое вы не инициализируете. Таким образом, его значение равно тому, что было в пространстве памяти переменных до того, как оно было выделено. Это может быть что угодно, но в большинстве случаев это не случайно. Это зависит от того, что ваша программа делала до этого, но у вас нет никакого контроля над этим.
Затем вы проверяете, является ли userInput
цифрой ASCII. Поскольку вы не нажимали клавишу, это, очевидно, равно false, поэтому значение переменной никогда не записывается. А затем вы возвращаете эту переменную.
В loop()
вы проверяете, не равно ли возвращаемое значение getNumber()
NO_KEY
. И поскольку вы не инициализировали значение
, вероятно, так оно и есть. Таким образом, программа переходит непосредственно к части типа операции.
Что же теперь делать?
Первое: всегда инициализируйте каждую переменную, которую вы объявляете в функции. Глобальные переменные инициализируются неявно, но не локальные переменные. Чтобы быть уверенным, что я не совершу ошибку, я просто всегда инициализирую ВСЕ свои переменные при их объявлении.
Во-вторых: текущее значение
не будет равно NO_KEY,
поскольку вы не присваиваете это значение переменной. Но это не соответствовало бы логике вашей программы. значение
- это реальное числовое значение, а не его представление в формате ASCI. И NO_KEY
определяется в библиотеке клавиатуры
как \0
(нулевой символ с числовым значением ноль). Таким образом
, NO_KEY на самом деле равно 0
. И ноль также является допустимым вводом для вашего калькулятора.
Вместо этого я бы предложил вернуть значение -1
, если ни одна клавиша не была нажата, а затем в loop()
проверить это. Итак, что-то вроде этого:
int getNumber(){
char userInput = customKeypad.getKey();
int value;
if (userInput == '0' || userInput == '1' || userInput == '2' || userInput == '3' || userInput == '4' || userInput == '5' || userInput == '6' || userInput == '7' || userInput == '8' || userInput == '9'){
value = userInput - '0';
Serial.println("value");
Serial.println(value);
} else {
return -1;
}
return value;
}
void loop(){
int a = getNumber();
if(a != -1){
do{
operationType = getOperationType();
}while(!operationType);
}
}
Тем не менее, у меня есть несколько предложений для вас, чтобы пойти дальше:
Для проверки того, является ли возвращаемый ключ цифрой ASCII, на самом деле существует простая функция для этого:
isDigit()
. Таким образом, вместо ваших прикованных равных условий вы можете просто использоватьif(isDigit(userInput))
Если вы продолжите в этом стиле, вы обнаружите, что оборачиваете несколько циклов друг в друга, так как вам нужно выполнить цикл для ожидания нажатия клавиши. Это может стать довольно запутанным, и будет сложно добавить дополнительные функциональные возможности. Вместо этого вы могли бы реализовать конечный автомат (FSM). Здесь код в
loop()
состоит в основном из структуры switch case , где каждый case - это одно состояние вашей программы. Например, у вас могут быть состояния NUMBER1_INPUT, OPERATION_INPUT, NUMBER2_INPUT, DISPLAY_RESULT. Структура коммутатора использует единственную переменную int в качестве маркера состояния. Например, когда вы устанавливаете для этой переменной состояния значение NUMBER1_INPUT, она останется там и будет зацикливаться. Когда пользователь выполнит ввод числа, вы можете изменить переменную состояния на OPERATION_INPUT и позволить ей продолжаться там. Это важная концепция, и она изменит ваш способ кодирования Arduino к лучшему.Существует множество ресурсов для изучения того, как программировать FSM. Я когда-то писал более длинный ответ на этотвопрос, но вы можете поискать что-то вроде "Конечного автомата" на этом сайте или в Интернете, чтобы узнать больше.
Большое вам спасибо за такое объяснение. Я посмотрю на ваш ответ о FSM. Я действительно ценю ваши усилия., @user851242
- Как вызвать функции C из скетча ардуино?
- max7219 связанный дисплей, показывающий зеркальный текст
- Пиринговая коммуникация
- Запуск С для ардуино
- Как связаться с ESP8266 ESP01, отправив данные через программный сериал на Arduino Uno?
- Прерывание ардуино при смене контакта
- GSM-модуль IOT-GA6 Arduino + ошибка CME 58
- Разница между массивом char и массивом unsigned char
логика вашей программы предполагает, что ваша программа ожидает нажатия клавиши .... сократите свой код до "получить нажатие клавиши, напечатать значение нажатия клавиши`... это покажет вам, с чем вы имеете дело, @jsotola