Несколько операторов If

Я использую следующий код для своего проекта Arduino, в котором мне нужно управлять двигателем постоянного тока с помощью Arduino Uno с помощью текстовых сообщений. Мой вопрос заключается в том, что я использовал несколько операторов «If» и только один оператор else в конце. Я скомпилировал этот код и не получил никаких ошибок. Можно ли использовать несколько операторов If один за другим, не используя else после каждого if?

#include <LiquidCrystal595.h>
#include <GSM.h>

GSM gsmAccess;
GSM_SMS sms;
char sendernumber[20];  
int Enable_m=11;
int Control_2=12;
int Control_7=10;
LiquidCrystal595 lcd(7,8,9);
void setup() 
{
   Serial.begin(9600);
   pinMode(Enable_m,OUTPUT);
   pinMode(Control_2,OUTPUT);
   pinMode(Control_7,OUTPUT);

   digitalWrite(Enable_m,LOW);
   digitalWrite(Control_2,LOW);
   digitalWrite(Control_7,LOW);

   lcd.begin(16,2);
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Hello");
   lcd.setCursor(0,1);
   lcd.print("Everyone");
   delay(2000);

   while (!Serial) 
      Serial.println("SMS Messages Receiver");
   boolean notConnected = true;
   while(notConnected)
   {
      if(gsmAccess.begin("0000")==GSM_READY)
         notConnected = false;
      else
      {
         Serial.println("Not connected");
         delay(1000);
      }
   }  
   Serial.println("GSM initialized");
   Serial.println("Waiting for messages");
}

void loop() {
   // put your main code here, to run repeatedly:
   char c;
   int val=0;
   val=digitalRead(Enable_m);
   if (val==LOW){
      digitalWrite(Enable_m,HIGH);
   }
   if (sms.available())
   {
      Serial.println("Message received from:");
      sms.remoteNumber(sendernumber, 20);
      Serial.println(sendernumber);

      if(sms.peek()=='#')
      {
         Serial.println("Discarded SMS");
         sms.flush();
      }
      while(c=sms.read())
         if(c=='motoroff'){
            analogWrite(Enable_m, 0);
            digitalWrite(Control_2,LOW);
            digitalWrite(Control_7,LOW);

         }
      if(c=='motoronclockwise'){
         analogWrite(Enable_m, 255);
         digitalWrite(Control_2,LOW);
         digitalWrite(Control_7,HIGH);
      }
      if(c=='motoronanticlockwise'){
         analogWrite(Enable_m, 255);
         digitalWrite(Control_2,HIGH);
         digitalWrite(Control_7,LOW);
      }
      if(c=='speedhalf'){
         analogWrite(Enable_m, 128);
         digitalWrite(Control_2,LOW);
         digitalWrite(Control_7,HIGH);
      }
      if(c=='speedquarter'){
         analogWrite(Enable_m, 65);
         digitalWrite(Control_2,LOW);
         digitalWrite(Control_7,HIGH);
      }
      if(c=='speed75'){
         analogWrite(Enable_m, 192);
         digitalWrite(Control_2,LOW);
         digitalWrite(Control_7,HIGH);
      }
      else{
         digitalWrite(Enable_m,HIGH);
         Serial.print(c);
      }
      Serial.println("\nEND OF MESSAGE");
      sms.flush();
      Serial.println("MESSAGE DELETED");
   }

}

, 👍1

Обсуждение

Список' операторов if должен быть реализован как оператор switch/case; он используется, когда у одной переменной много возможностей, и допускает случай default', который делает то, что *вы думаете*, что делает ваш последний оператор else`. Однако, как говорит Маженко, вы не можете напрямую сравнивать строки, как вы это делаете., @CharlieHanson

@CharlieHanson, то есть я могу заменить if-ы на метки и установить значение переменной, равное входящему сообщению?, @Awais Saifi


3 ответа


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

1
#include <LiquidCrystal.h>
#include <GSM.h>

GSM gsmAccess;
GSM_SMS sms;
char sendernumber[20]; 
int Enable_m=11;
int Control_2=12;
int Control_7=10;
LiquidCrystal lcd(7,8,9,8,1,2,3,4,5,6);

void setup() 
{
   Serial.begin(9600);
   pinMode(Enable_m,OUTPUT);
   pinMode(Control_2,OUTPUT);
   pinMode(Control_7,OUTPUT);

   digitalWrite(Enable_m,LOW);
   digitalWrite(Control_2,LOW);
   digitalWrite(Control_7,LOW);

   lcd.begin(16,2);
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Hello");
   lcd.setCursor(0,1);
   lcd.print("Everyone");
   delay(2000);

   while (!Serial) 
      Serial.println("SMS Messages Receiver");
   boolean notConnected = true;
   while(notConnected)
   {
      if(gsmAccess.begin("0000")==GSM_READY)
         notConnected = false;
      else
      {
         Serial.println("Not connected");
         delay(1000);
      }
   }  
   Serial.println("GSM initialized");
   Serial.println("Waiting for messages");
}

void loop() {
   // put your main code here, to run repeatedly:

   // I chose 160 since that is max size for sms
   char message [160]; 
   // this fills message with null characters
   memset( message, '\0', sizeof(char)*160 ); 

   int val=0;
   val=digitalRead(Enable_m);
   if (val==LOW){
      digitalWrite(Enable_m,HIGH);
   }
   if (sms.available())
   {
      Serial.println("Message received from:");
      sms.remoteNumber(sendernumber, 20);
      Serial.println(sendernumber);

      // you used single qoutes properly here
      // single qoutes denote a char which is a single character
      if(sms.peek()=='#')
      {
         Serial.println("Discarded SMS");
         sms.flush();
      }


      // this will add the characters to messages[]
      for(int i = 0; message[i] = sms.read(); i++){}

      // I changed this to double qoutes since you need double
      // qoutes to denote a string literal
      if(strcmp(message, "motoroff") == 0){
         analogWrite(Enable_m, 0);
         digitalWrite(Control_2,LOW);
         digitalWrite(Control_7,LOW);
      }
      else if(strcmp(message, "motoronclockwise") == 0){
         analogWrite(Enable_m, 255);
         digitalWrite(Control_2,LOW);
         digitalWrite(Control_7,HIGH);
      }
      else if(strcmp(message, "motoronanticlockwise") == 0){
         analogWrite(Enable_m, 255);
         digitalWrite(Control_2,HIGH);
         digitalWrite(Control_7,LOW);
      }
      else if(strcmp(message, "speedhalf") == 0){
         analogWrite(Enable_m, 128);
         digitalWrite(Control_2,LOW);
         digitalWrite(Control_7,HIGH);
      }
      else if(strcmp(message, "speedquarter") == 0){
         analogWrite(Enable_m, 65);
         digitalWrite(Control_2,LOW);
         digitalWrite(Control_7,HIGH);
      }
      else if(strcmp(message, "speed75") == 0){
         analogWrite(Enable_m, 192);
         digitalWrite(Control_2,LOW);
         digitalWrite(Control_7,HIGH);
      }
      // This else will only be executed if the previous if and else if statements are false
      else{
         digitalWrite(Enable_m,HIGH);
         Serial.print(message);
      }
      Serial.println("\nEND OF MESSAGE");
      sms.flush();
      Serial.println("MESSAGE DELETED");
   }

}

Итак, я внес некоторые изменения в ваш код. Например, этот код 'motoronanticlock' неверен. Одинарные кавычки используются для типов данных char, а двойные кавычки используются для строковых литералов. Вам следует использовать двойные кавычки, поскольку есть несколько символов "motoronanticlock". Также, как сказал Маженко, вам придется использовать strcmp() для сравнения c-строок c-строки — это массивы char, которые имеют нулевой терминатор '\0'. Также strcmp() возвращает 0, если две строки равны.

Ваш последний оператор else будет выполнен только в том случае, если предыдущий оператор if будет false. Похоже, вы хотите, чтобы он выполнялся только в том случае, если все предыдущие операторы if будут ложными. Для этого вы создаете первый оператор if, а затем создаете цепочку операторов if else, за которыми следует один оператор else. Вы можете иметь один оператор if без операторов else или if else, однако, если вы хотите операторы else или if else, вам нужно иметь оператор if. Я уже внес необходимые изменения в ваш код.

Наконец, эта часть программы является самой большой проблемой while(c=sms.read()) Это потому, что sms.read() возвращает char, поэтому вы можете читать sms-сообщение только по одному символу за раз. Чтобы сделать это правильно, вам следует создать массив символов и сохранить в нем значения, возвращаемые sms.read(). Это можно сделать так

char message [160]; // Я выбрал 160, так как это максимальный размер для смс
memset( message, '\0', sizeof(char)*160 ); // это заполняет сообщение нулевыми символами
// это добавит символы в messages[]
for(int i = 0; message[i] = sms.read(); i++){}

Я использую цикл for для перебора message[].

Попробуйте сделать все вышеперечисленное и свяжитесь со мной, если возникнут какие-либо проблемы.

,

Прошу прощения за поздний ответ и благодарю за то, что уделили время ответу на мой вопрос. Я проверю код на оборудовании и сообщу вам. Ещё раз спасибо за помощь, я очень ценю это., @Awais Saifi

sketch_oct16a.ino: В функции 'void loop()': sketch_oct16a:81: ошибка: «сообщения» не были объявлены в этой области sketch_oct16a:114: ошибка: «messsage» не был объявлен в этой области Что это значит? Я проверил, и возникла эта ошибка., @Awais Saifi

Я ошибся, это просто опечатки. Я отредактировал код в своём ответе., @Chris

Да, я так и думал. Теперь всё в порядке, проверено. Ура!, @Awais Saifi


1

Две вещи:

  1. else будет зависеть только от последнего if, остальная часть if операторов полностью отделена и не может повлиять на else никаким образом. Чтобы сцепить их, вам нужно if (...) { blah blah } else if (...) { blah blah } и т. д.
  2. Вы не можете сравнивать символы и строки таким образом (и на самом деле это даже не строки, а множество символов, сжатых в один символ с помощью использования неправильных кавычек).

Так что, по сути, нет, вся ваша программа совершенно неверна и не будет делать то, что вы ожидаете, и вам нужно полностью переосмыслить, как она работает.

Несколько советов:

  • Используйте strcmp() для сравнения строк.
  • Если считывать строки из последовательного порта, то сохранять их в массивах символов, а не в отдельных символах.

Вам может быть полезно:

  • http://hacking.majenko.co.uk/reading-serial-on-the-arduino
  • http://hacking.majenko.co.uk/the-evils-of-arduino-strings
,

Итак, вы говорите, что мне нужно создать массив строк, а затем использовать функцию strcmp() для их сравнения. Как тогда назначить каждой строке отдельную функцию?, @Awais Saifi

Нет, я говорю, что *каждая* строка должна быть массивом *символов*. Погуглите руководства по «строкам C»., @Majenko

тогда мне придется определять каждый массив, как в начале, и просто ссылаться на него в условном выражении?, @Awais Saifi

Попросите Google показать вам. Он справится с этим лучше, чем я, пытаясь научить вас основам в комментариях. Существует буквально миллиард примеров и обучающих программ. Зайдите и прочтите их., @Majenko

Я перешёл по этой ссылке, и она оказалась весьма полезной. Спасибо., @Awais Saifi


0

Если вы хотите, чтобы каждый оператор if выполнялся независимо от того, выполнялись ли предыдущие операторы, то да, они не требуют предложений else.

Если вы хотите проверить каждое условие, пока не найдете то, которое является истинным, и выполнить его и только его, то второй и последующие if должны быть else if. Последний может быть просто else, если вам нужно предложение catch-all; или else if, если возможно, что ни одно из предложений не нужно будет выполнять.

Обновление: чтобы выполнить максимум одно предложение, вам нужно использовать if, несколько else if и, возможно, финальный else.

Если вы пытаетесь сопоставить строки, вы можете использовать массив строк или использовать литеральные строки, как вы пытались сделать. Однако строки должны быть заключены в двойные кавычки ("), а не в одинарные, которые вы использовали. А переменная char c;, которую вы пытались использовать для хранения SMS-сообщения, на самом деле состоит только из одного символа. Вам нужно будет сделать ее массивом символов, например char c[140+1];, размером самого длинного SMS-сообщения + еще один для нулевого символа-терминатора строки. C напрямую не сравнивает строки как простые переменные, поэтому == и != здесь не сработают. Вам нужно будет сравнить их с помощью strcmp().

,

из всех условий только одно должно быть истинным. поэтому при совпадении строки следует выполнить только это условие и ждать прибытия следующего сообщения., @Awais Saifi