در قسمت دهم از آموزش آردوینو به بررسی استفاده از رشتههای کاراکتری زبان C و تقسیم متن جدا شده با کاما (Comma-Separated) با استفاده از آرایهها، پرداختیم. در این قسمت قصد داریم درباره تبدیل عدد به رشته (استرینگ) و همچنین، تبدیل رشته (استرینگ) به عدد، صحبت کنیم.
برای نمایش عدد روی LCD یا صفحه نمایشی دیگر، شما باید عدد را به رشته (استرینگ) تبدیل کنید.
تابع ()String اعداد را به رشتهای از کاراکترها تبدیل میکند. دراینخصوص، میتوانید از مقادیر لیترال (literal) یا محتوای یک متغیر استفاده کنید. بهعنوانمثال، کد زیر کار خواهد کرد:
1 | myNumber = String(1234); |
همچنین، میتوان از کد زیر استفاده کرد:
1 2 3 | int value = 127; String myReadout = "The reading was "; myReadout.concat(value); |
یا این:
1 2 3 | int value = 127; String myReadout = "The reading was "; myReadout += value; |
هنگامی که به یک متغیر String، مقادیری اختصاص داده میشود، کلاس آردوینو استرینگ (Arduino String class) بهصورت اتوماتیک، مقادیر عددی را به استرینگ تبدیل میکند. شما میتوانید در پایان یک استرینگ، مقادیر عددی را با استفاده از تابع concat یا operator، پیوند دهید.
اگر در حال تبدیل عدد به متن برای نمایش روی دستگاه LCD یا سریال هستید، سادهترین راهحل استفاده از قابلیت تبدیل تعبیهشده (built into) در کتابخانههای LCD و Serial است. اما شاید دستگاهی که شما از آن استفاده میکنید، این پشتیبانی داخلی را نداشته باشد.
نکته✅
اپراتور + برای انواع اعداد و همچنین، استرینگها استفاده میشود، اما با هر یک، طرز کار متفاوتی دارد.
نتیجه کد زیر ذخیره یک مقدار عددی (۱۳) در متغیر number:
1 2 | int number = 12; number += 1; |
همچنین، با استرینگ (String) کد بهصورت زیر است:
1 2 | String textNumber = "12"; textNumber += 1; |
مقدار textNumber در نهایت رشته “121” است.
قبل از معرفی کلاس رشته (String)، معمول بود که در کدهای آردوینو از تابعهای itoa یا ltoa استفاده شود. نامها از عبارت “integer to ASCII” (itoa) و “long to ASCII” (ltoa) گرفته شدهاند. استفاده از کلاس رشته (String) که قبلاً توضیح داده شد، آسانتر است، اما اگر ترجیح میدهید با آرایههای کاراکتر C کار کنید، میتوانید از موارد زیر استفاده کنید:
توابع itoa و ltoa سه پارامتر دارند: مقدار تبدیل (value to convert)، بافری که استرینگ خروجی را نگه میدارد و پایه عددی (10 برای عدد اعشاری، 16 برای هگز و 2 برای باینری).
اسکچ زیر، نحوه تبدیل مقادیر عددی با استفاده از ltoa را نشان میدهد:
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 | /* * NumberToString * Creates a string from a given number */ char buffer[12]; // long data type has 11 characters (including the // minus sign) and a terminating null void setup() { Serial.begin(9600); while(!Serial); long value = 12345; ltoa(value, buffer, 10); Serial.print( value); Serial.print(" has "); Serial.print(strlen(buffer)); Serial.println(" digits"); value = 123456789; ltoa(value, buffer, 10); Serial.print( value); Serial.print(" has "); Serial.print(strlen(buffer)); Serial.println(" digits"); } void loop() { } |
بافر شما باید بهاندازه کافی بزرگ باشد تا حداکثر تعداد کاراکترها را در استرینگ نگه دارد. برای مقادیر صحیح 16 بیتی، به هفت کاراکتر (پنج رقم، یک علامت منفی احتمالی و یک ترمینال 0 که همیشه نشان دهنده پایان رشته است) نیاز داریم. و برای مقادیر صحیح 32 بیتی به بافرهای 12 کاراکتری (10 رقم، علامت منفی و ترمینال 0) نیاز داریم.
سرریز بافر زمانی رخ میدهد که شما داده بیشتری را نسبت به فضایی که برای آن در نظر گرفته شده است، در یک بافر (حافظه موقت) قرار میدهید. این میتواند منجر به خرابشدن سایر بخشهای حافظه شود که توسط برنامه شما استفاده میشود و باعث ایجاد رفتارهای غیرمنتظره (باگ) میشود.
اگر از اندازه بافر (حافظه موقت) فراتر بروید، هیچ اخطاری به شما داده نمیشود؛ این یک باگ (نقص) است که میتواند باعث پیامدهای بدی شود، زیرا سرریز (overflow) حافظه، بخش دیگری از حافظه را که ممکن است توسط برنامه شما استفاده شود، خراب میکند.
بنابراین، بهتر است از یک بافر 12 کاراکتری و ltoa استفاده کنید؛ زیرا هم روی مقادیر 16 بیتی و هم 32 بیتی کار می کند.
تبدیل استرینگ به عدد
گاهی اوقات ممکن است شما نیاز داشته باشید که استرینگ را به عدد، تبدیل کنید یا مقداری را بهعنوان استرینگ داشته باشید و باید آن را به عدد صحیح (integer) یا مقدار ممیز شناور (floating- Point) تبدیل کنید.
روش دیگر تبدیل استرینگهای متنی که اعداد را نشان میدهند، استفاده از تابع تبدیل زبان C به نام atoi (برای متغیرهای int) یا تابع atol (برای متغیرهای long) است.
این اسکچ هر عددی که وارد شود را با دریافت یک کاراکتر غیرعددی (اگر بافر فول باشد) متوقف میکند. بعد از آپلود کردن اسکچ، سریال مانیتور را باز کنید و چند کاراکتر عددی تایپ کنید، سپس کلید Enter یا Return را بزنید. البته، قبل از این کار باید گزینه newline را در سریال مانیتور فعال کنید یا قبل از زدن دکمه Enter یا Return چند کاراکتر غیرعددی تایپ کنید.
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 | /* * StringToNumber * Creates a number from a string */ int blinkDelay; // blink rate determined by this variable char strValue[6]; // must be big enough to hold all the digits and the // 0 that terminates the string int index = 0; // the index into the array storing the received digits void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); // enable LED pin as output } void loop() { if (Serial.available()) { char ch = Serial.read(); if (index < 5 && isDigit(ch)) { strValue[index++] = ch; // add the ASCII character to the string; } else { // here when buffer full or on the first nondigit strValue[index] = 0; // terminate the string with a 0 blinkDelay = atoi(strValue); // use atoi to convert the string to an int index = 0; } } blink(); } void blink() { digitalWrite(LED_BUILTIN, HIGH); delay(blinkDelay / 2); // wait for half the blink period digitalWrite(LED_BUILTIN, LOW); delay(blinkDelay / 2); // wait for the other half } |
بهطورکلی، Atoi و atol دو تابع در زبانهای برنامهنویسی C و C++ هستند که برای تبدیل رشته (استرینگ)های متنی به اعداد صحیح و طولانی (long) استفاده میشوند.
atoi مخفف ASCII to integer است و برای تبدیل یک رشته متنی به یک عدد صحیح (int) استفاده میشود و atol مخفف ASCII to long است و برای تبدیل یک رشته متنی به یک عدد طولانی (long) استفاده میشود. برای استفاده از این توابع، شما باید کل استرینگ را در آرایهای از کاراکترها دریافت و ذخیره کنید، سپس میتوانید تابع تبدیل را فراخوانی نمایید.
برنامه بالا، یک آرایه از کاراکترها به نام strValue ایجاد میکند که میتواند پنج رقم و یک بایت کاراکتر null را در خود جای دهد. این آرایه با ارقام دریافتی از تابع Serial.read پر می شود تا زمانی که اولین کاراکتری که رقم معتبر نیست را دریافت کند. آرایه با یک null پایان می یابد و تابع atoi برای تبدیل آرایه کاراکتر به متغیر blinkDelay فراخوانی می شود.
تابعی وجود دارد به نام blink که از مقدار ذخیره شده در blinkDelay استفاده میکند.
توجه⚡
شما باید مراقب باشید که از مرزهای آرایه تجاوز نکنید.
تابع parseInt در آردوینو برای دریافت مقادیر صحیح از سریال و اترنت استفاده میکند. کد زیر توالی ارقام عددی را به اعداد تبدیل میکند. این روش مشابه راهحل قبلی است، اما نیازی به بافر ندارد (و تعداد ارقام را به پنج محدود نمیکند):
1 2 3 4 5 6 7 8 9 10 11 | void loop() { if (Serial.available()) { int newValue = Serial.parseInt(); if (newValue != 0) { blinkDelay = newValue; Serial.print("New delay: "); Serial.println(blinkDelay); } } blink(); } |
نکته✅
زمانی که دادهها در فاصله زمانی موردنظر دریافت نمیشوند، روشهای تجزيه جریان داده مانند parseInt از یکزمان خروج (timeout) برای بازگرداندن کنترل به اسکچ شما استفاده میکنند. زمان خروج بهصورت پیشفرض یک ثانیه است، اما با فراخوانی تابع setTimeout میتوان این زمان را تغییر داد.
1 | Serial.setTimeout(1000 * 60); // wait up to one minute |
درصورتیکه هیچ جداکنندهای دریافت نشود، تابع parseInt هر مقداری را که قبل از زمان توقف بهدستآمده است، برمیگرداند. مقدار برگشتی شامل هر مقداری است که جمعآوری شده است؛ اگر هیچ رقمی دریافت نشود، مقدار برگشتی صفر خواهد بود.
برای دسترسی به داکیومنتهای atoi، به سایت زیر مراجعه کنید:
در قسمت بعدی آموزش آردوینو درباره ساختاربندی کد به بلوکهای عملکردی (فانکشنال) توضیح خواهیم داد. پس در ادامه این آموزش حتماً همراه سیسوگ باشید.