مكتبة تفقيط الأرقام باللغة العربية مفتوحة المصدر بلغة السي

هناك حلول برمجية كثيرة لتفقيط الأرقام باللغة العربية (إعطاء قراءة الرقم باللغة العربية). المشكلة في هذه الحلول المتوفرة أنها محدودة باللغة التي كتبت بها ويصعب استخدامها في لغات أو بيئات تطوير أخرى، وقد بات من المعروف اليوم أنه من النادر أن تستخدم لغة واحدة في تطوير المشاريع الحقيقية، فالحاجة إلى تقديم حل برمجي حديث، متكامل، وبجودة عالية، وضمن زمن محدد سوف يحتّم على المبرمج استخدام أكثر من لغة أو أداة تطوير. هذا يعني أنه إذا اضطر لاستخدام التفقيط في مشروعه فإنه سيستخدم أكثر من حل/منتج للقيام بعمل واحد وهو تفقيط الأرقام، وعند حاجته إلى تعديل/تصحيح ما في عملية التفقيط فإنه سيضطر لتنفيذ هذا التعديل في أكثر من لغة. المشكلة الأخرى الموجودة في حلول التفقيط الحالية هي أنها مخصصة بشكل كبير لتفقيط الأرقام/المبالغ المالية، وبعضها محدد بعملة/عملات معينة وتحتاج لتعديل برمجي لإضافة عملة أخرى.

هذه المشاكل التي عرضتها دفعتني لكتابة/برمجة مكتبة التفقيط num2a. لقد قمت بكتابة هذه المكتبة بلغة C لأنها من وجهة نظري اللغة الأكثر "محمولية" portability، حيث تستطيع ترجمة (compile) أي نص مصدري في C على منصات مختلفة وباستخدام مترجمات (compilers ) مختلفة وقد لاتضطر في كثير من الأحيان سوى إلى إجراء تعديلات طفيفة. ولزيادة محمولية مكتبة التفقيط num2a تعمدت في برمجتها عدم الاستعانة أو استخدام إي مكتبة خارجية، بما فيها المكتبة الرياضية math.h.

نشرت هذه المكتبة على موقع github بترخيص مفتوح المصدر MIT . يمكنكم تحميل المكتبة من هذا الرابط . كما يمكنكم تجريب المكتبة وتجريب التفقيط من خلال هذه الصفحة التي تستخدم مكتبة num2a.

هذا فيديو يظهر تجارب "حية" لمكتبة num2a بلغات وأدوات تطوير مختلفة (C, C++, Delphi, PHP, C#, Java, Qt, GTK) وعلى أنظمة تشغيل مختلفة (Windows, Linux, Mac OS X, Android)

(تحديث 3-12-2016) قمت باضافة مثال جديد يوضح كيفية استخدام مكتبة التفقيط في اكسل. المثال موجود ضمن الدليل examples كما يمكنك تحميله بشكل مستقل من هذا الرابط. وهذا أيضاً فيديو يوضح استخدام مكتبة التفقيط num2a لتفقيط الأرقام في إكسل

مكتبة التفقيط num2a تدعم ترميز اليونيكود (unicode) عن طريق الاعتماد على نوع المتحول/التخزين wchar_t (wide char). طبعاً المبرمجين بلغة C/C++ يعلمون جيداً أن wide char ليس ترميزاً بل هو مجرد نوع/وسيط تخزين لا أكثر. لقد فضلت دعم اليونيكود بهذا الأسلوب بدلاً من تضمين هذه المكتبة آلية كاملة للترميز أو بدل الاستعانة بمكتبة خارجية للترميز لأني أولاً أرغب بإبقاء حجم النص المصدري Source Code للمكتبة صغيراً قدر الأمكان، وثانياً لأني لا أرغب بأن أجعل المكتبة معتمدة على أي مكاتب خارجية كما ذكرت في البداية، ناهيكم أن هذا هو الأسلوب الأكثر شيوعاً في حالة المكاتب صغيرة أو متوسطة الحجم كهذه المكتبة. بالاضافة إلى أن هذا الأسلوب – حسب رأيي الشخصي - يعطي المبرمج الذي سيستخدم المكتبة مرونة وحرية أكبر حسب أداة التطوير ومنصة التشغيل التي يستخدمها، هذا الأمر قد توضحه الأمثلة المرفقة مع المكتبة وقد كتبتها بعدة لغات وحزم تطوير (C, C++, C#, Delphi, Java, php, Qt, gtk). إن حزم التطوير/لغات البرمجة العالية المستوى (C#, Delphi, Qt, …) تملك توابع جاهزة لإظهار ال Wide Char بترميز اليونيكود وفي بعض اللغات/الأدوات يكون الأمر بشكل آلي وبدون تدخل المبرمج وقد يكون هذا هو سبب اعتقاد بعض المبرمجين أن ال Wide Char هو ترميز يونيكود، راجع أمثلة (C#, Qt, Delphi) الموجودة ضمن مجلد examples ،أما بالنسبة للغات الأدنى مستوى (Low Level Languages ) كلغة ال C مثلاً وعلى بعض المنصات أو عند استخدام بعض الحزم الرسومية الأمر سيكون بحاجة إلى تدخل المبرمج لتحويل ال Wide Char إلى ترميز يونيكود المطلوب، والأمر هنا أيضاً ليس معقداً فالمبرمج لن يضطر سوى إلى كتابة سطر واحد في معظم الأحيان للقيام بعملية التحويل، والمبرمج هنا أيضاً حر في أن يستخدم التوابع التي تقدمها منصة التشغيل للقيام بعملية التحويل Platform API أو ان يعتمد على مكتبات تقدم توابع جاهزة لإجراء عملية التحويل مثل مكتبات (iconv, glib …). في الأمثلة المرفقة والمكتوبة بلغة C قمت باستخدام مكتبة glib. إن مكتبة ال glib هي مكتبة "عريقة" وواحدة من أكثر المكاتب شيوعاً. إن glib مكتبة شائعة ليس بسبب توابع/خدمة الترميز التي تقدمها فقط بل بسبب الخدمات والتقنيات والتوابع الكثيرة الأخرى التي تقدمها مما يجعل توفرها على أي حاسب أمراً شائعاً وطبيعياً جداً، راجع أمثلة (gtk, php) ضمن مجلد examples وهي أمثلة مكتوبة بلغة C –لاستخدام مكتبة num2a في PHP نحن بحاجة لحاضنة wrapper للتخاطب مع محرك الـ ZEND وقد قمت بكتابة هذه الحاضنة بلغة C أيضاً- لترى كيف قمت باستخدام توابع glib للتحويل بين تراميز (utf8, utf16, ucs4) . يمكن أيضأ لمبرمجي C في بعض الحالات الاستفادة من بعض المزايا التي توفرها البيئة التي يتعاملون معها لكتابة اجرائيات التحويل/الترميز بأنفسهم وبطريقة سهلة وبدون الاستعانة بمكاتب خارجية، هذا الأمر يوضحه مثال الجافا الموجود ضمن الأمثلة المرفقة، حيث أنه لاستخدام num2a في جافا نحتاج أيضا إلى كتابة حاضنة wrapper تستخدم Java Native Interface أو ما يعرف بـ JNI لكي تؤمن لنا التخاطب مع آلة الجافا وقد قمت بكتابة هذه الحاضنة بلغة الـ C أيضأ لكني هنا لم استخدم مكاتب خارجية للقيام بعملية الترميز بل اعتمدت على توابع جافا في تفكيك سلاسل المحارف إلى مصفوفات بايت Byte Arrayحسب ترميز اليونيكود و حسب ترتيب البايت Bytes Order الذي يستخدمه النظام ومن ثم تقديم نتيجة التفقيط بنفس الاسلوب لتقوم جافا بإعادة ترميزها وفق نفس الترميز الذي يستخدمه النظام، طبعا أنا أفترض هنا أن يكون المبرمج على علم بالترميز الذي يستخدمه النظام الذي يستهدفه. ستلاحظ ضمن نص الجافا JavaNum2aExample.java أنني أشرت إلى هذه النقطة، حيث أنني اعتمدت في هذا المثال على أن ترميز اليونيكود في ويندوز هو UTF-16 وترتيب البايت Little-Endian بينما في باقي الأنظمة هو UTF-32 وترتيب البايت Little-Endian طبعا رغم صحتها لكنها مجرد فرضية، فأنظمة التشغيل الأكثر شهرة عدا ويندوز تستخدم UTF-32LE بالفعل (Linux, OS X, Android)، لكن هذا ليس بقاعدة لبقية الانظمة، فمن المحتمل أن تواجه نظام تشغيل يستخدم ترميز مختلف عندها يجب عليك تعديل كود الجافا. طبعاً الافضل كما قلنا أن تستخدم مكتبة خارجية متخصصة في الترميز (iconv, glib, …) لكن بما أن مثال الجافا المرفق يمكن استخدامه بقليل من التعديل في تطبيقات الأندرويد ولأن مبرمجي الهواتف المحمولة لايفضلون –في العادة- الاستعانة بمكاتب خارجية، فقد اضفت هذا الخيار/الحل، خصوصاً أن مبرمجي تطبيقات الهواتف يعرفون جيدا ماهي الأجهزة والأنظمة التي يستهدفونها وبالتالي هذا الحل قد يكون مناسباً لهم أكثر. بالنسبة لمبرمجي C++ الذين يستخدمون مترجمات Compilers تدعم معايير C++ الحديثة فأمورهم أفضل بوجود توابع وأنماط تخزين data type جديدة لتسهيل عملية الترميز ضمن المكتبة الرئيسية Standard Library.

لإعطاء مرونة أكثر لتوابع التفقيط في المكتبة num2a لم أقم بتثبيت Hardcoded اسم معدود معين (اسم عملة أوغيره) بل اتحت الفرصة للمبرمج الذي سيستخدم المكتبة أن يقوم هو بتحديده أو تثبيته إذا شاء ذلك. هذا سيسمح باستخدام المكتبة ليس لتفقيط المبالغ المالية فقط بل لتفقيط قيم أخرى (درجات حرارة، أوزان، مسافات ...) بسهولة وبدون الحاجة لأي تعديل على المكتبة. من أجل دقة نتيجة التفقيط (نحوياً) اتحت المجال أيضا للمبرمج أن يمرر لتوابع التفقيط اسم المعدود منوناً بالاضافة إلى مثنى وجمع المعدود. طبعاً كان من الممكن اضافة خوارزمية لاضافة التنوين إلى المعدود و خوارزمية أخرى لاستخراج المثنى والجمع منه. وبالتالي اختصار بارامترات توابع التفقيط، لكن نظراً لطبيعة اللغة العربية واحتمال وجود اسماء معدود أجنبية أو مركبة مع قسم أجنبي فالأمر سيكون شائكاً وغير مضمون من الناحية النحوية لإيضاح المسألة سأطرح مثالين متعاكسين:
مثال1: لو كان المعدود "درجة سليسيوس"
في حالة التنوين نقول: خمس و عشرون درجةً سيلسيوس (لانستطيع القول خمس و عشرون درجةً سيلسيوساً!!)
مثال2: لو كان المعدود "كيلو غرام"
في حال التنوين نقول: خمسة وعشرون كيلو غراماً (لا نستطيع القول خمسة و عشرون كيلواً غرام!! بعكس المثال الأول)

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

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

بما أنني أتوقع أن المستفيدين من هذه المكتبة هم إما عرب أو يجيدون اللغة العربية لذلك فقد كتبت ملف التوثيق والمساعدة باللغة العربية، يمكن أن تجدوه ضمن مجلد الـ doc كما أنني أضفت ملفات readme باللغة العربية لإعطاء معلومات أكثر عن بعض الأمثلة المرفقة مع المكتبة، طبعاً يمكن الاطلاع على ملف num2a.h لمزيد من المعلومات حول توابع المكتبة وبارامتراتها. الملاحظات/الشروح ضمن النصوص المصدرية ربما ليست بالكثيرة - هذه قد تكون عادة سيئة عند مبرمجي C - لكن مع نصوص بسيطة لاتحتوي على الكثير من البهلوانيات البرمجية أعتقد ان الملاحظات والشروح الموجودة هي أكثر من كافية.

ملاحظة: مراجعاتكم وملاحظاتكم البرمجية والنحوية على هذه المكتبة هي دائماً موضع ترحيب.

- عصام علي
سوريا - بانياس

Articles Categories: 

إضافة تعليق جديد