در قسمت یازدهم از آموزش آردوینو به بررسی ساختاردهی کد با استفاده از بلوکهای تابع و برگرداندن بیش از یک مقدار از تابع، پرداختیم. در این قسمت قصد داریم درباره مقایسه کاراکترها و مقادیر عددی، مقایسه استرینگها و همچنین، انجام مقایسههای منطقی (Logical Comparisons) صحبت کنیم.
در ابتدای این مطلب رابطه بین مقادیر را بررسی میکنیم.
شما میتوانید مقادیر صحیح را با استفاده از عملگرهای رابطهای نشان داده شده در جدول زیر مقایسه کنید.
مثال | کاربرد | عملگر |
---|---|---|
2 == 3 // evaluates to false | مساوی بودن | == |
2 != 3 // evaluates to true | مساوی نبودن | != |
2 > 3 // evaluates to false | بزرگ تر بودن | > |
2 < 3 // evaluates to true | کوچک تر بودن | < |
2 >= 3 // evaluates to false | بزرگ تر یا مساوی بودن | >= |
2 <= 3 // evaluates to true | کوچک تر یا مساوی بودن | <= |
جدول 1: عملگرهای رابطه ای و برابری
اسکچ زیر نتایج استفاده از عملگرهای مقایسهای را نشان میدهد:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | /* * RelationalExpressions sketch * demonstrates comparing values */ int i = 1; // some values to start with int j = 2; void setup() { Serial.begin(9600); } void loop() { Serial.print("i = "); Serial.print(i); Serial.print(" and j = "); Serial.println(j); if (i < j) Serial.println(" i is less than j"); if (i <= j) Serial.println(" i is less than or equal to j"); if (i != j) Serial.println(" i is not equal to j"); if (i == j) Serial.println(" i is equal to j"); if (i >= j) Serial.println(" i is greater than or equal to j"); if (i > j) Serial.println(" i is greater than j"); Serial.println(); i = i + 1; if (i > j + 1) { delay(10000); // long delay after i is no longer close to j } else { delay(1000); // short delay } |
خروجی به صورت زیر است:
1 2 3 4 5 6 7 8 9 10 11 12 | i = 1 and j = 2 i is less than j i is less than or equal to j i is not equal to j i = 2 and j = 2 i is less than or equal to j i is equal to j i is greater than or equal to j i = 3 and j = 2 i is not equal to j i is greater than or equal to j i is greater than j |
نکته✅
عبارت زیر مقدار i را با 3 مقایسه می کند:
1 | if(i == 3) // test if i equals 3 |
اما فرض کنید این کد را در اسکچ زیر قرار دهیم:
1 | if(i = 3) // single equals sign used by mistake!!!! |
این عبارت همواره مقدار True برمیگرداند. زیرا مقدار i به 3 تنظیم میشود و در نتیجه هنگام مقایسه با 3، مقدارها برابر خواهند بود.
1 | if ('b' > 'a') |
همچنین، این عبارت نیز همواره مقدار True برمیگرداند. زیرا مقدار a در مجموعهی کاراکترهای ASCII که Arduino از آن استفاده میکند، برابر با 97 است.
1 | if ('a' == 97) |
با این حال، استرینگها را نمیتوان مستقیماً با مقادیر عددی مقایسه کرد:
1 | String word1 = String("Hello"); char word2[] = "World"; if (word1 > 'G') // This will not compile { Serial.println("word1 > G"); } if (word2 >= 'W') // This also will not compile { Serial.println("word2 >= W"); } |
اما شما همیشه میتوانید یک عدد یا کاراکتر را با یک کاراکتر تکی از یک رشته (استرینگ) مقایسه کنید:
1 2 3 4 5 6 | if (word1.charAt(0) > 'G') { Serial.println("word1[0] > G"); } if (word2[0] >= 'W') { Serial.println("word2[0] >= W"); } |
برای کسب اطلاعات بیشتر درباره عملگرهای شرطی و مقایسهای میتوانید به لینک زیر مراجعه کنید:
https://www.arduino.cc/reference/en/language/structure/control-structure/if/
مقایسه استرینگها
در ادامه یاد خواهیم گرفت که آیا دو استرینگ کاراکتری یکسان هستند یا خیر.
یک تابع به نام strcmp (مخفف string compare) وجود دارد که به مقایسه استرینگها میپردازد. در اینجا یک فرگمنت استفاده از آن آورده شده است:
1 2 3 4 5 | char string1[] = "left"; char string2[] = "right"; if (strcmp(string1, string2) == 0) { Serial.println("strings are equal"); } |
تابع strcmp، مقایسهی دو رشته کاراکتری را انجام میدهد. این تابع دو رشته (آرایه کاراکتری) را مقایسه کرده و سپس نتیجهی مقایسه را بهعنوان 0، 1 یا -1 برمیگرداند.
در این خصوص، تابع strcmp، در صورت مساوی بودن استرینگها، مقدار 0 را برمیگرداند و اگر اولین کاراکتر nonmatching استرینگ اول مقدار بیشتری نسبت به استرینگ دوم داشته باشد، این تابع مقداری بزرگتر از صفر را برمیگرداند. همچنین، اگر مقدار اولین کاراکتر nonmatching استرینگ اول کمتر از کاراکتر متناظر در استرینگ دوم باشد، تابع strcmp مقداری کمتر از صفر را برمی گرداند.
نکته مهم✅
بهخاطر داشته باشید که استرینگهایی با طول نابرابر به صورت یکسان در نظر گرفته نمیشوند؛ حتی در صورتی که استرینگ کوتاهتر در استرینگ بلندتر باشد.
بنابراین:
1 | if (strcmp("left", "leftcenter") == 0) // this will evaluate to false |
با استفاده از تابع strncmp، میتوان استرینگها را تا تعداد معینی از کاراکترها مقایسه کرد. همچنین، شما میتوانید از تابع strncmp برای مقایسه تعداد مشخصی از کاراکترها استفاده کنید.
1 | if (strncmp("left", "leftcenter", 4) == 0) // this will evaluate to true |
برخلاف استرینگهای کاراکتری، استرینگهای آردوینو را میتوان مستقیماً به صورت زیر مقایسه کرد:
1 2 3 4 5 6 7 | String stringOne = String("this"); if (stringOne == "this") { Serial.println("this will be true"); } if (stringOne == "that") { Serial.println("this will be false"); } |
برای کسب اطلاعات بیشتر به آموزش مقایسه استرینگهای آردوینو مراجعه کنید.
انجام مقایسههای منطقی (Logical Comparisons)
در ادامه میخواهیم رابطه منطقی بین دو یا چند عبارت را بررسی کنیم.
در جدول 2 عملگرهای منطقی (Logical operators) بررسی شدهاند.
توضیحات | تابع | نماد |
---|---|---|
اگر عبارات شرطی هر دو طرف عملگر &&، درست (true) باشند، نتیجه true می شود. | Logical And | && |
اگر عبارت شرطی حداقل یک طرف از عملگر ||، درست (true) باشد، نتیجه true می شود. | Logical Or | || |
اگر عبارت شرطی عملگر ! نادرست (false) باشد، نتیجه true و اگر عبارت شرطی این عملگر درست (true) باشد، نتیجه false می شود. | Not | ! |
جدول 2: عملگرهای منطقی (Logical operators)
عملگرهای منطقی مقادیر true یا false را بر اساس رابطه منطقی برمیگردانند.
عملگر AND (&&) در صورتی که دو عملوند (Operand) آن، true باشند، مقدار true و در غیر این صورت، مقدار false را برمیگرداند:
1 2 | if( digitalRead(2) && digitalRead(3) ) blink(); // blink if both pins are HIGH |
عملگر OR (||) در صورتی که هر دو عملوند (Operand) آن true باشند، مقدار true و اگر هر دو عملوند (Operand)، false باشند، مقدار false را برمیگرداند:
1 2 | if( digitalRead(2) || digitalRead(3) ) blink(); // blink if either pin is HIGH |
عملگر Not فقط یک عملوند (Operand) دارد که مقدار آن معکوس است؛ یعنی اگر عملوند (Operand) آن true باشد، مقدار false و اگر عملوند (Operand) آن false باشد، مقدار true را برمیگرداند.
1 2 | if( !digitalRead(2) ) blink(); // blink if the pin is not HIGH |
انجام عملیات بیتی
در ادامه درباره تنظیم یا پاک کردن بیتهای خاصی در یک مقدار، صحبت خواهیم کرد.
در جدول 3 توضیحات مربوط به عملگرهای بیتی مختلف آورده شده است. در این جدول، پیشوند 0b نمایش باینری اعداد را نشان می دهد و به منظور جدا کردن اعداد اعشاری و باینری استفاده می شود.
مثال | نتیجه | تابع | نماد |
---|---|---|---|
3 & 1 equals 1 (0b11 & 0b01 equals 0b01) | .اگر هر دو بیت 1 باشند، بیت ها را روی 1 قرار می دهد. در غیر این صورت، بیت ها روی 0 تنظیم می شوند | Bitwise And | & |
3 | 1 equals 3 (0b11 | 0b01 equals 0b11) | .اگر هر یک از بیت ها 1 باشند، بیت ها را روی 1 تنظیم می کند | Bitwise Or | | |
3 ^ 1 equals 2 (0b11 ^ 0b01 equals 0b10) | .تنها در صورتی که یکی از دو بیت 1 باشد، بیت ها را روی 1 تنظیم می کند | Bitwise Exclusive Or | ^ |
~1 equals 254 (~00000001 equals 11111110) | .مقدار هر بیت را معکوس می کند. نتیجه به تعداد بیت ها در دیتابیس بستگی دارد | Bitwise Negation | ~ |
جدول 3: عملگرهای بیتی
در زیر یک اسکچ آمده است که مقادیر نمونه جدول 2 را نشان می دهد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /* * bits sketch * demonstrates bitwise operators */ void setup() { Serial.begin(9600); } void loop(){ Serial.print("3 & 1 equals "); // bitwise And 3 and 1 Serial.print(3 & 1); // print the result Serial.print(" decimal, or in binary: "); Serial.println(3 & 1 , BIN); // print the binary representation of the result Serial.print("3 | 1 equals "); // bitwise Or 3 and 1 Serial.print(3 | 1 ); Serial.print(" decimal, or in binary: "); Serial.println(3 | 1 , BIN); // print the binary representation of the result Serial.print("3 ^ 1 equals "); // bitwise exclusive or 3 and 1 Serial.print(3 ^ 1); Serial.print(" decimal, or in binary: "); Serial.println(3 ^ 1 , BIN); // print the binary representation of the result byte byteVal = 1; int intVal = 1; byteVal = ~byteVal; // do the bitwise negate intVal = ~intVal; Serial.print("~byteVal (1) equals "); // bitwise negate an 8-bit value Serial.println(byteVal, BIN); // print the binary representation of the result Serial.print("~intVal (1) equals "); // bitwise negate a 16-bit value Serial.println(intVal, BIN); // print the binary representation of the result delay(10000); } This is what is displayed on the Serial Monitor: 3 & 1 equals 1 decimal, or in binary: 1 3 | 1 equals 3 decimal, or in binary: 11 3 ^ 1 equals 2 decimal, or in binary: 10 ~byteVal (1) equals 11111110 ~intVal (1) equals 11111111111111111111111111111110 |
عملگرهای بیتی برای تنظیم یا تست بیتها استفاده میشوند. هنگامی که دو مقدار “And” یا “Or” دارید، عملگر روی هر بیت به صورت جداگانه کار میکند. با نگاه کردن به نمایش باینری مقادیر، متوجه نحوه کار آنها خواهید شد.
عدد صحیح اعشاری 3 باینری 11 است و عدد صحیح اعشاری 1 باینری 1 است. سمت راست ترین بیت ها هر دو 1 هستند؛ بنابراین نتیجه And-ing ،1 است. با حرکت به سمت چپ، بیت های بعدی 1 و 0 می باشند و بیتهای باقیمانده And-ing ،0 هستند؛ بنابراین نتیجه بیتی آن ها 0 خواهد بود.
به عبارت دیگر، برای هر موقعیت بیت که در هر دو مکان یک عدد 1 وجود دارد، نتیجه عدد 1 و در غیر این صورت، 0 خواهد شد؛ بنابراین، 11 و 01 برابر است با 1.
اعداد باینری اغلب با صفرهای ابتدایی نوشته میشوند؛ البته این صفرهای ابتدایی اهمیتی ندارند و فقط، ارزیابی عملیات بیتی را آسانتر میکنند.
Bit 1 and Bit 2 | Bit 2 | Bit 1 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 1 |
1 | 1 | 1 |
جدول 4: Bitwise And
Bit 1 or Bit 2 | Bit 2 | Bit 1 |
---|---|---|
0 | 0 | 0 |
1 | 1 | 0 |
1 | 0 | 1 |
1 | 1 | 1 |
جدول 5: Bitwise Or
Bit 1 ^ Bit 2 | Bit 2 | Bit 1 |
---|---|---|
0 | 0 | 0 |
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
جدول 6: Bitwise Exclusive Or
تمام عبارات بیتی بر روی دو مقدار عمل میکنند، به جز عملگر negation. این عملگر به راحتی هر بیت را برمیگرداند، بنابراین 0 تبدیل به 1 و 1 تبدیل به 0 میشود.
برای مثال، مقدار بایت (8 بیتی) 00000001 به 11111110 تبدیل می شود. مقدار int دارای 16 بیت است؛ بنابراین وقتی هر کدام از آن ها برگردانده می شوند، نتیجه 15 تا 1 و یک عدد 0 می شود.
در ادامه در جدول 7، عملگرهای ترکیبی را بررسی کرده تا شما یاد بگیرید که چگونه از آن ها استفاده کنید.
عبارت معادل | مثال | عملگر |
---|---|---|
value = value + 5; // add 5 to value | value += 5; | += |
value = value – 4; // subtract 4 from value | value -= 4; | -= |
value = value * 3; // multiply value by 3 | value *= 3; | *= |
value = value / 2; // divide value by 2 | value /= 2; | /= |
value = value >> 2; // shift value right two places | value >>= 2; | >>= |
value = value << 2; // shift value left two places | value <<= 2; | <<= |
mask = mask & 2; // binary-and mask with 2 | mask &= 2; | &= |
mask = mask | 2; // binary-or mask with 2 | mask |= 2; | |= |
جدول 7: عملگرهای ترکیبی (Compound operators)