المسارات
/
Go
Go
/
التمارين
/
سجلات، سجلات، سجلات!
سجلات، سجلات، سجلات!

سجلات، سجلات، سجلات!

تمرين تعلّمي

مقدمة

نوع rune في Go اسم مستعار لـ int32. ونظرًا لأن نوع rune يستند إلى هذا النوع int32، فإنه يحمل قيمة عددية صحيحة ذات إشارة بسعة 32 بت. لكن على خلاف النوع int32، تمثّل القيمة العددية المخزّنة في نوع rune محرف يونيكود واحدًا.

يونيكود ونقاط ترميز يونيكود

يونيكود مجموعة شاملة لـ ASCII، ويمثّل المحارف عبر إعطاء رقم فريد لكل محرف. ويُسمى هذا الرقم الفريد نقطة ترميز يونيكود. يهدف يونيكود إلى تمثيل جميع محارف العالم، بما فيها مختلف الأبجديات والأرقام والرموز وحتى الرموز التعبيرية، على هيئة نقاط ترميز يونيكود.

في Go، يمثّل نوع rune نقطة ترميز يونيكود واحدة.

يعرض الجدول التالي أمثلة على محارف يونيكود مع نقاط ترميزها وقيمها العشرية:

محرف يونيكود نقطة ترميز يونيكود القيمة العشرية
0 U+0030 48
A U+0041 65
a U+0061 97
¿ U+00BF 191
π U+03C0 960
🧠 U+1F9E0 129504

UTF-8

‏UTF-8 هو ترميز محارف متغيّر العرض، يُستخدم لترميز كل نقطة ترميز يونيكود على هيئة 1 أو 2 أو 3 أو 4 بايتات. ولأن نقطة ترميز يونيكود يمكن ترميزها في 4 بايتات كحد أقصى، يحتاج نوع rune إلى القدرة على تخزين ما يصل إلى 4 بايتات من البيانات. ولهذا فإن نوع rune اسم مستعار لـ int32، لأن النوع int32 قادر على تخزين ما يصل إلى 4 بايتات من البيانات.

تُرمَّز ملفات الكود المصدري في Go باستخدام UTF-8.

استخدام rune

تُعرَّف المتغيرات من نوع rune بوضع محرف بين علامتَي اقتباس مفردتين:

myRune := '¿'

ولأن rune مجرد اسم مستعار لـ int32، فإن طباعة نوع rune ستُنتج int32:

myRune := '¿'
fmt.Printf("myRune type: %T\n", myRune)
// Output: myRune type: int32

وبالمثل، فإن طباعة قيمة rune ستُنتج قيمتها العددية الصحيحة (العشرية):

myRune := '¿'
fmt.Printf("myRune value: %v\n", myRune)
// Output: myRune value: 191

لطباعة محرف يونيكود الذي يمثّله الـ rune، استخدم صيغة التنسيق %c:

myRune := '¿'
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿

ولطباعة نقطة ترميز يونيكود التي يمثّلها الـ rune، استخدم صيغة التنسيق %U:

myRune := '¿'
fmt.Printf("myRune Unicode code point: %U\n", myRune)
// Output: myRune Unicode code point: U+00BF

rune والسلاسل النصية

تُرمَّز السلاسل النصية في Go باستخدام UTF-8، ما يعني أنها تحتوي على محارف يونيكود. وتُخزَّن المحارف في السلاسل النصية وتُرمَّز على هيئة 1 أو 2 أو 3 أو 4 بايتات، حسب محرف يونيكود الذي تمثّله.

في Go، تُستخدم الشرائح لتمثيل المتتاليات، ويمكن المرور على هذه الشرائح باستخدام range. وعندما نمرّ على سلسلة نصية، يحوّلها Go إلى متتالية من أنواع rune، كل منها بحجم 4 بايتات (تذكّر أن نوع rune اسم مستعار لـ int32!)

وعلى الرغم من أن السلسلة النصية مجرد شريحة من البايتات، فإن الكلمة المفتاحية range تمرّ على أنواع rune في السلسلة النصية، لا على بايتاتها.

في هذا المثال، يمثّل المتغير index فهرس البداية لتسلسل بايتات الـ rune الحالي، ويمثّل المتغير char الـ rune الحالي:

myString := "❗hello"
for index, char := range myString {
  fmt.Printf("Index: %d\tCharacter: %c\t\tCode Point: %U\n", index, char, char)
}
// Output:
// Index: 0	Character: ❗		Code Point: U+2757
// Index: 3	Character: h		Code Point: U+0068
// Index: 4	Character: e		Code Point: U+0065
// Index: 5	Character: l		Code Point: U+006C
// Index: 6	Character: l		Code Point: U+006C
// Index: 7	Character: o		Code Point: U+006F

ولأن أنواع rune يمكن تخزينها في 1 أو 2 أو 3 أو 4 بايتات، فقد لا يساوي طول السلسلة النصية دائمًا عدد المحارف فيها. استخدم الدالة المدمجة len للحصول على طول السلسلة النصية بالبايتات، والدالة utf8.RuneCountInString للحصول على عدد أنواع rune في السلسلة النصية:

import "unicode/utf8"

myString := "❗hello"
stringLength := len(myString)
numberOfRunes := utf8.RuneCountInString(myString)

fmt.Printf("myString - Length: %d - Runes: %d\n", stringLength, numberOfRunes)
// Output: myString - Length: 8 - Runes: 6

التعليمات

أُوكلت إليك مهمة إنشاء مكتبة للسجلات تساعدك في إدارة سجلات مؤسستك. ستتيح هذه المكتبة للمستخدمين تحديد التطبيق الذي أصدر سجلًا معينًا، وإصلاح السجلات التالفة، ومعرفة ما إذا كان سطر السجل المعين يقع ضمن حد معين من الأحرف.

1. تحديد التطبيق الذي أصدر السجل

تأتي السجلات من تطبيقات متعددة، ويستخدم كل منها تنسيق سجلات خاصًا به. ويجب تحديد التطبيق الذي أصدر السجل قبل تخزينه في نظام لتجميع السجلات.

نفّذ الدالة Application التي تأخذ سطر السجل وتُرجع التطبيق الذي أصدر هذا السطر.

لتحديد التطبيق الذي أصدر سطر سجل معين، ابحث في سطر السجل عن حرف محدد وفق ما يوضّحه الجدول التالي:

التطبيق الحرف نقطة ترميز Unicode
recommendation ❗ U+2757
search 🔍 U+1F50D
weather ☀ U+2600

إذا لم يحتوي سطر السجل على أي من الأحرف الواردة في الجدول أعلاه، فأرجع default إلى المستدعي. وإذا احتوى سطر السجل على أكثر من حرف من الجدول أعلاه، فأرجع التطبيق المقابل لأول حرف يصادفه السطر من اليسار إلى اليمين.

Application("❗ recommended search product 🔍")
// => recommendation

2. إصلاح السجلات التالفة

بسبب وجود bug نادر لكنه مستمر في البنية التحتية للتسجيل، يمكن أن تتلف أحرف معينة في السجلات. وبعد أن أمضيت وقتًا في تحديد الأحرف التالفة وقيمتها الأصلية، قررت تحديث مكتبة السجلات للمساعدة في إصلاح السجلات التالفة.

نفّذ الدالة Replace التي تأخذ سطر السجل، وحرفًا تالفًا، والقيمة الأصلية، وتُرجع سطر سجل معدّلًا استُبدلت فيه كل حالات ورود الحرف التالف بالقيمة الأصلية.

log := "please replace '👎' with '👍'"

Replace(log, '👎', '👍')
// => please replace '👍' with '👍'"

3. تحديد ما إذا كان يمكن عرض السجل

الأنظمة المسؤولة عن عرض السجلات لها حد أقصى لعدد الأحرف التي يمكن عرضها في سطر السجل الواحد. ولذلك، يطلب المستخدمون أن تضم هذه المكتبة دالة مساعدة تحدّد ما إذا كان سطر السجل يقع ضمن حد معين من الأحرف أم لا.

نفّذ الدالة WithinLimit التي تأخذ سطر السجل وحدّ الأحرف وتُرجع ما إذا كان سطر السجل يقع ضمن حد الأحرف أم لا.

WithinLimit("hello❗", 6)
// => true
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Go Exercism

مستعد لبدء سجلات، سجلات، سجلات!؟

سجّل في Exercism لتتعلّم وتتقن Go عبر 34 مفهومًا165 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.