النصوص في Kotlin: String وأهم دوالها
رسالة ترحيب، واسم مستخدم، ونص إشعار: تطبيقات أندرويد تتعامل مع النصوص في كل شاشة. تعرّفت على String وعلى قوالب النصوص بعلامة $ في درس المتغيرات. في هذا الدرس ستتعلم أهم دوال النصوص في Kotlin: كيف تقطع النص وتبحث فيه وتنظفه وتحوّله إلى أرقام بأمان.
طول النص وحروفه
Section titled “طول النص وحروفه”النص سلسلة حروف، ولكل حرف رقم يبدأ من صفر:
val word = "Kotlin"println(word.length)println(word[0])println(word.first())println(word.last())println(word.reversed())6KKnniltoKlength: عدد الحروف، وهي خاصية بدون أقواس.word[0]: الحرف الأول، بنفس طريقة القوائم.first()وlast(): أوضح في القراءة من حساب رقم آخر حرف.
تخيّل النص مثل قطار: كل عربة فيها حرف واحد، والعربات مرقمة من المقدمة.
يمكنك أيضاً المرور على الحروف بحلقة for:
var vowels = 0for (ch in "education") { if (ch in "aeiou") vowels++}println(vowels)5النصوص لا تتغير
Section titled “النصوص لا تتغير”النص في Kotlin غير قابل للتعديل (Immutable). أي دالة «تغيّر» النص تُرجع نصاً جديداً، والأصلي يبقى كما هو:
val name = "sara"name.uppercase()println(name)
val upper = name.uppercase()println(upper)saraSARAالسطر الثاني بلا فائدة، لأن النتيجة لم تُخزَّن في متغير.
التقطيع والتنظيف
Section titled “التقطيع والتنظيف”val text = " Hello Kotlin "val clean = text.trim()println("[$clean]")println(clean.substring(6))println(clean.substring(0, 5))println(clean.take(3))println(clean.takeLast(3))println(clean.lowercase())println(clean.replace("Kotlin", "World"))[Hello Kotlin]KotlinHelloHellinhello kotlinHello Worldtrim(): تحذف المسافات من الطرفين. استخدمها دائماً مع ما يكتبه المستخدم.substring(0, 5): من الموضع 0 إلى ما قبل الموضع 5.take(n)وtakeLast(n): أول أو آخرnحروف، ولا تسببان خطأ إذا كان النص أقصر.
البحث داخل النص
Section titled “البحث داخل النص”println(email.contains("@"))println("@" in email)println(email.indexOf("@"))println(email.startsWith("omar"))println(email.endsWith(".org"))println(email.substringBefore("@"))println(email.substringAfter("@"))truetrue4truefalseomarexample.comالكلمة in طريقة مختصرة لكتابة contains. والدالتان substringBefore و substringAfter من هدايا Kotlin: تستخرجان ما قبل الفاصل أو ما بعده دون حساب أي مواضع.
المقارنة
Section titled “المقارنة”هنا تختلف Kotlin عن Java اختلافاً مريحاً: العلامة == تقارن محتوى النصين مباشرة:
val a = "kotlin"val b = "KOTLIN".lowercase()println(a == b)println(a.equals("Kotlin", ignoreCase = true))println("apple" < "banana")println("".isEmpty())println(" ".isBlank())truetruetruetruetrue==: هل المحتوى متطابق؟ (في Java كانت تحتاجequals).ignoreCase = true: مقارنة تتجاهل حالة الحروف.<و>: مقارنة أبجدية.isEmpty(): النص بلا أي حرف. وisBlank(): النص فارغ أو كله مسافات، وهي الأنسب لفحص حقول الإدخال.
التقسيم والدمج
Section titled “التقسيم والدمج”val line = "تفاح,موز,عنب"val fruits = line.split(",")println(fruits)println(fruits.size)println(fruits.joinToString(" - "))[تفاح, موز, عنب]3تفاح - موز - عنبsplit تقطع النص عند الفاصل وتُرجع قائمة List، و joinToString تفعل العكس.
النصوص متعددة الأسطر
Section titled “النصوص متعددة الأسطر”لكتابة نص طويل على عدة أسطر، استخدم ثلاث علامات تنصيص:
val name = "ليلى"val message = """ مرحباً $name، تم تسجيلك بنجاح. رقم طلبك: ${100 + 23}""".trimIndent()println(message)مرحباً ليلى،تم تسجيلك بنجاح.رقم طلبك: 123trimIndent() تحذف الإزاحة المشتركة من أول كل سطر، فيبقى كودك مرتباً والنص نظيفاً. والقوالب $name و ${...} تعمل داخلها كالمعتاد.
التحويل من نص إلى رقم
Section titled “التحويل من نص إلى رقم”ما يكتبه المستخدم يصلك نصاً دائماً. الدالة toInt() تحوّله إلى عدد، لكنها ترمي خطأ إذا لم يكن رقماً. البديل الآمن هو toIntOrNull():
val inputs = listOf("42", "abc", " 7 ")for (input in inputs) { val number = input.trim().toIntOrNull() if (number != null) { println("العدد: $number وضعفه ${number * 2}") } else { println("«$input» ليس رقماً") }}العدد: 42 وضعفه 84«abc» ليس رقماًالعدد: 7 وضعفه 14buildString: بناء نص داخل حلقة
Section titled “buildString: بناء نص داخل حلقة”لأن النص لا يتغير، فكل + داخل حلقة ينشئ نصاً جديداً كاملاً. الدالة buildString تبني النص بكفاءة:
val stars = buildString { for (i in 1..3) { append("*".repeat(i)) append("\n") }}print(stars)println("=".repeat(10))println("7".padStart(3, '0'))******==========007append: تضيف إلى النص الجاري بناؤه.repeat(n): تكرر النصnمرات.padStart(3, '0'): تكمل النص من البداية حتى يصل طوله إلى 3.
جرّب بنفسك
Section titled “جرّب بنفسك”- خزّن جملة في متغير، واطبع عدد حروفها وعدد كلماتها باستخدام
split(" "). - خزّن اسم ملف مثل
photo.png، واستخرج الاسم والامتداد بـsubstringBeforeوsubstringAfter. - اكتب دالة
initials(fullName: String)تُرجع الحرف الأول من كل كلمة:"Omar Ali"تصبح"OA". - تحدٍّ: اكتب دالة
isPalindrome(word: String)تُرجعtrueإذا كانت الكلمة تُقرأ من الجهتين بنفس الشكل مثلlevel، مع تجاهل حالة الحروف.
أخطاء شائعة
Section titled “أخطاء شائعة”- تجاهل القيمة المُرجعة:
text.trim()وحدها لا تغيّرtext. خزّن النتيجة:val clean = text.trim(). - موضع خارج الحدود:
"Kotlin"[6]يرميStringIndexOutOfBoundsException، فآخر موضع هو 5. الدالةgetOrNull(6)تُرجعnullبدلاً من الخطأ. - toInt مع إدخال المستخدم:
"abc".toInt()يرميNumberFormatException. استخدمtoIntOrNull(). - نسيان الأقواس في القالب:
"$user.name"تطبع الكائن ثم.nameحرفياً. الصحيح"${user.name}".
اختبر نفسك
Section titled “اختبر نفسك”سؤال
ما ناتج "Hello".substring(1, 3)؟
التقطيع يبدأ من الموضع 1 وينتهي قبل الموضع 3، فيأخذ الحرفين e و l فقط.
سؤال
ما ناتج "12a".toIntOrNull()؟
النص ليس رقماً صحيحاً كاملاً، فتُرجع الدالة null بدلاً من رمي خطأ.
الخلاصة
Section titled “الخلاصة”- النص سلسلة حروف مرقمة من صفر:
lengthو[i]وfirst()وlast(). - النصوص لا تتغير: كل دالة تُرجع نصاً جديداً يجب أن تخزنه.
==تقارن المحتوى مباشرة، وisBlank()تفحص الحقول الفارغة.splitوjoinToStringللتقسيم والدمج، و"""..."""للنصوص متعددة الأسطر.toIntOrNull()للتحويل الآمن، وbuildStringلبناء النصوص داخل الحلقات.