• الإعلانات

    • فيصل الحربي

      تسجيل عضوية جديدة في المنتدى   01/31/2016

      السلام عليكم ورحمة الله وبركاته  عزيزي العضو الجديد :  حاليا رسالة الإيميل لتأكيد صحة إيميلكم تذهب للبريد العشوائي ( جاري حل المشكلة )  فإذا لم تجد رسالة التحقق من إيميلكم في صندوق الوارد لديكم إتجه للبريد العشوائي ( JUNK)  وقم بتفعيل إشتراككم من هناك   

محمد علاء الدين

المشرفون
  • عدد المشاركات

    2,494
  • تاريخ الانضمام

  • تاريخ اخر زياره

كل شيء نشر بواسطة محمد علاء الدين

  1. هل تستطيع معرفة عدد الخانات برقم معين

    حل السؤال الأول: توجد أكثر من طريقه لمعرفة عدد خانات الرقم سأعرض إثنان منها هنا. 1 - الحصول على عدد الخانات بإستخدام الـ bit shift: هذه الطريقه تصلح فقط مع أنظمة الأعداد التى يمكن تمثيل أكبر رقم يأخذ خانه واحده بعدد معين من البتات التى تكون جميع قيمها بواحد فمثلا النظام الثمانى اكبر رقم فيه هو 7 و يمثل ثنائيا بالرقم 111 أى 3 بت، النظام السداسي عشرى أكبر رقم فيه هو F و يمثل ثنائيا بالرقم 1111 أى 4 بت، النظام الثنائى لا يحتاج اى مجهود حيث اكبر رقم به هو 1 و يمثل 1 بت. النظام العشرى لا يمكن الحصول على عدد خاناته بإستخدام هذه الطريقه و السبب فى ذلك هو ان اكبر رقم به هو 9 و يمثل ثنائيا بالرقم 1001 و كما ترى يحتوى ليست جميع البتات بواحد. متطلبات هذه الطريقه: 1 - الرقم لابد و أن يكون موجب حيث ان الأرقام السالبه لها ترميز مختلف. 2 - الرقم لابد و أن يكون ترميزه Little Endian. سنعتبر اننا نتعامل مع النوع int32 (هو signed int داخل بيئة 32bit). سنأخذ النظام السداسى عشرى كتطبيق هنا، الخطوات كالتالي: 1 - على اعتبار ان موقع أول بت من اليسار هو 32 و أول بت من اليمين هو 1، قم بالحصول على موقع اول بت من اليسار بقيمة 1. 2 - الرقم الناتج من النقطه 1 هو عدد البتات الفعليه التى تمثل الرقم، قم بقسم الرقم الناتج من النقطه واحد على 4 (و هو عدد البيات التى تمثل خانه واحده بالنظام السداسى العشرى). 3 - قم بالحصول على باقى القسمه للرقم الناتج من النقطه 1 مع الرقم 4 (و هو عدد البيات التى تمثل خانه واحده بالنظام السداسى العشرى) إذا كان الناتج أكبر من صفر قم بإضافة 1 إلى الرقم الناتج من 2. 4 - الرقم الناتج من 3 هو عدد الخانات المطلوبه الخطوات السابقه يمكن تطبيقها على النظام الثنائى و السداسى عشرى بكل بساطه فقط بإستبدالك الرقم 4 بالخطوه الثانيه و الثالثه بأى من الرقمين 3 و 1 للنظامين الثمانى و الثنائى على التوالي. الكود التالي هو تطبيق على الخطوات السابقه للأنظمه السابق ذكرها: typedef signed int int32;#define DEC 0#define HEX 1#define OCT 2#define BIN 3int32 digitCount2(int32 value, int32 base){ if (base == DEC) return -1; value *= value < 0? -1: 1; static const int32 size[] = {0, 4, 3, 1}; int32 bit_loc = sizeof(int32) * CHAR_BIT; for (; bit_loc >= 0; bit_loc--) if (value & (1 << (bit_loc - 1))) break; return (bit_loc / size[base]) + (bit_loc % size[base] > 0? 1: 0);} الداله Main لإختبار الداله السابقه: #include <iostream>using namespace std;typedef signed int int32;#define DEC 0#define HEX 1#define OCT 2#define BIN 3const char* system_name[] = { "decimal", "hexadecimal", "octal", "binary" };int32 digitCount2(int32 value, int32 base);int main(){ char input = 0; do { int32 value = 0; cout << "Enter Number: "; cin >> value; cout << "Select output number system\n"; cout << " 1) Hexadecimal 2) Octal 3) Binary E) Exit\n";CHOICE: cout << "\nEnter your choice: "; cin >> input; if (input == 'E') break; if(input < '1' || input > '3') { cout << "Invalid Choice.\n"; goto CHOICE; } input -= '0'; cout << "\nNumber of Placeholder needed to hold " << value << " in " << system_name[input] << " system is " << digitCount2(value, input) << endl;EXIT: cout << "Do yo want to continue (Y\\N)? "; cin >> input; if(input != 'Y' && input != 'N') { cout << "Invalid Choice.\n"; goto EXIT; } } while (input != 'N');} 2 - الحصول على عدد الخانات بإستخدام اللوغارتم يمكنك الحصول على عدد الخانات رقم ما بأى نظام تريد بإستخدام اللوغارتم، و لمن هم لا يعرفون اللوغارتم إليكم شرح مبسط للأمر: اللوغارتم هو وسيله للحصول على عدد مرات تواجد مضاعفات رقم داخل أخر فى نظام عددى معين و الصيغه العامه له هى كالتالي: و تقرأ أو ما هو الرقم الذى إذا تم إستخدامه كأس للرقم x يعطينا y، الداله log تعيد رقم عشرى و ليس صحيح، أيضا الداله log الموجوده بـ cmath تتعامل مع النظام العشرى و هو الوضع الإفتراضى و لتحويلها للنظام السداسى العشرى سنقوم بقسمة الرقم الناتج منها على للتحويل لنظام الثمانى قم بإستبدال الرقم 16 بالرقم 8. كما نعلم فإن عدد مرات تواجد مضاعفات الرقم 10 داخل الرقم 1000 هى 3 و هذا هو الرقم الذي ستعيده لنا الداله log بالمكتبه القياسيه - أو أى مكتبه أخرى - و كما نعلم ان الرقم 10 بالنظام العشرى يعنى خانتين و ليس واحده و بالتالي عندما تعيد لنا الداله log الرقم 3 سنعرف انه توجد خانه واحده اضافيه لرقم أخر (فى حالتنا هذه 1)، مثلا الرقم 7 تمريرها للداله log ستعيد لنا رقم كسرى أقل من الصفر و ذلك لأن الرقم 7 أقل من 10، الرقم صفر بالنسبه لنا يعنى انه يوجد رقم اقل من 10 و هذا يعنى تواجد خانه واحده فقط. الخلاصه: بعد تنفيذ الداله log لأى نظام عددى قم دائما بزيادة 1 للحصول على عدد الخانات. الكود بإستخدام اللوغارتم: #include <cmath>using namespace std;typedef signed int int32;#define DEC 0#define HEX 1#define OCT 2#define BIN 3int32 digitCount(int32 value, int32 base){ static const double base_value[] = {10.0, 16.0, 8.0, 2.0}; if (base > BIN) return -1; if (value == 0) return 1; value *= value < 0? -1: 1; return (int32)(log10((double)value) / log10(base_value[base]) + 1);} الداله Main للداله السابقه: قم بتعديل السطر: cout << " 1) Hexadecimal 2) Octal 3) Binary E) Exit\n"; إلى التالي: cout << " 0) Decimal 1) Hexadecimal 2) Octal 3) Binary E) Exit\n"; قم بتعديل السطر التالي: if(input < '1' || input > '3') إلى التالي: if(input < '0' || input > '3') حل السؤال الثاني: سنبدأ بالنظام العشرى كمثال، الأعداد الموجوده بالنظام العشرى تبدأ من 0 كأقل عدد و تنتهي عند 9 كأكبر عدد يمكن تخزينه داخل خانه واحده، لذا عندما أسئلك اي العددين أكبر بشكل إفتراضى ستجيب العدد 9 و ذلك لأنه يستطيع تمثيل كميات أكبر من العدد 0، و لكن برمجيا كيف يمكننا تحديد أى الرمزين أكبر؟ كل الـ code pages المعروفه تحدد رقم معين للرموز من 0 إلى إلى 9 فعندما تستخدم الحرف 0 داخل نص فعليا يتم حفظه برقم يمثله و فى حالتنا هذه هو 48 و الحرف 9 يمثله الرقم 57 لذا عندما نريد المقارنه بين الحرفين 0 و 9 بكتابة الكود التالي: if ('0' > '9') cout << " 0 > 9 !!!";else cout << " 9 > 0 !!!"; فإن ذلك الكود يصبح كالتالي: if (48 > 57) cout << " 0 > 9 !!!";else cout << " 9 > 0 !!!"; لذا السؤال الذى يطرح نفسه كيف نستطيع المقارنه بين رقمين مثل "1234-" و "362" و كيف يمكننا تحديد أيهما أكبر و أيهما أقل؟ إذا أفترضنا ان هاذين النصين يمثلوا أرقام حقيقيه و طلبت منك أن تجيبنى انت على هذا السؤال فأعتقد انك ستقول الرقم 1234- أقل من الرقم 362، نعم كلامك صحيح و لكن ما يهمنى هو ليس إجابة السؤال و لكن كيف توصلت لها. السبب فى انك قلت أن الرقم 1234- أقل من 362 هو أنك رأيت الإشارة السالبه بالأول و لم تراها بالثاني لذا علمت انه مهما كانت الكميه التى يمثلها الرقم الأول فهي بالتأكيد أقل من الكميه التى يمثلها الرقم الثاني و لهذا كانت اجابتك بأن الرقم الأول أقل من الرقم الثاني. حسنا لنأخذ مثال أخر، الرقم "9645" و الرقم "365"؟ الإجابه هي الرقم الأول أكبر من الرقم الثاني، تعال لنحلل كيف توصلنا لهذه النتيجه، فى البدايه نحن لم نجد أى اشاره بالرقمين و بالتالي أى منهم يمكن أن يكون أكبر من أو أقل من الأخر او قد يكون كلاهما متساوى لذا سنحتاج أن نطور طريقة تفكيرنا، بالطبع لن نقوم بعدّ الكميه التى يمثلها كل منهم و لكن سنستخدم طريقه ابسط و هي عدّ الخانات العشريه فكما نعلم عندما يكون رقم أكبر من أخر حينها لابد أن يكون عدد خاناته أكبر من عدد خانات الأخر و فى حالتنا هذه فإن الرقم الأول له عدد خانات أكبر من الرقم الثاني و حيث ان كلاهما لا يحتويان على إشاره سالبه حينها نستطيع أن نجزم أن الرقم الأول أكبر من الرقم الثاني. قد يدور الحوار التالي بينى و بين أحدكم: "ماذا عن الصفر، فالنفترض وجود مثل هاذين الرقمين "3654" و "0125"، كما ترى كلاهما موجب و كلاهما له نفس عدد الخانات فكيف سنعرف أيهم أكبر و أيهم أصغر؟" كما تعلم أن الصفر الموجود بالجانب الأيسر لا يعنى شيئا لذا إن أستطعنا بطريقه ما تجاهل كل الأصفار الموجوده باليسار لكلا الرقمين سنجد اننا نستطيع تطبيق طريقة حساب عدد الخانات لمعرفة اي الرقمين أكبر من الأخر كما حدث فى المثال الثاني. "و لكن ماذا يحدث إن كان عدد الخانات الموجوده بالرقمين بعد تجاهل الأصفار متساويه كما فى الرقمين "567" و "561"، ماذا سنفعل حينها؟" الحل بسيط أولا نحن نعلم ان كلاهما لا يحتوى على إشاره و ايضا نعلم ان كلاهما له نفس عدد الخانات و أن كلاهما لا يحتوى على أصفار من اليسار لذا سنقوم بمقارنة الرقم الذى يمثل كل حرف منهم من اليسار لليمين و الحرف صاحب الرقم الأكبر يكون رقمه هو صاحب القيمه الأكبر. "لماذا من اليسار لليمين؟ و هل لك ان تفصل الخطوات على المثال السابق؟" كما تعلم ان أول خانه على اليمين هى خانة الأحاد و كل عدد بها يساوى نفس الكميه التى يمثلها ذلك العدد و الخانه التى تليها هى خانة العشرات و كل عدد بها يماثل نفس الكميه التى يمثلها ذلك العدد مضروبا فى 10 و بالتالي كلما تحركنا لليسار كلما ذات الكميه بشكل أكبر و بالتالي أول عدد موجود على اليسار هو من يستطيع أن يحدد لنا ما إذا كان هذا الرقم أكبر من أول أقل من أو يساوى رقم أخر له نفس العدد من الخانات. مثلا فى مثالك الرقم "567" حروفه تأخذ القيم التاليه 55 54 53 و الرقم "561" حروفه تأخذ الأرقام التاليه 49 54 53 عندما نقارن خانة المئات سنجد انهم متساويين (53 = 53) و عندما ننتقل لخانة العشرات سنجد انهم ايضا متساويين (54 = 54) لذا سنذهب لخانة الأحاد و سنجد أن الرقم الذى يمثل الحرف 7 أكبر من الرقم الذى يمثل الحرف 1 (49 < 55) و بالتالي الرقم "567" أكبر من الرقم "561". التحليل النظرى أنتهى لذا لنطبق مثال عملي على النوع signed int، من الملف limits.h نعلم أن أكبر و أقل قيمة لهذا النوع هى كالتالي: #define INT_MIN -2147483648#define INT_MAX 2147483647 أنظر للكود التالي و من ثم تابع معي: (الكود التالي يتعامل على اساس ان النص المدخل يحتوى فقط على رموز الأعداد من 0 و حتى 9 و قد يتتواجد الإشاره السالبه فى اقصي اليسار مره واحده فقط) typedef signed char int8;typedef signed int int32;bool isOverflow(const char* value){ // maximum and minimum number of int32 // INT_MAX INT_MIN static const char* max_numbers[] = { "2147483647", "2147483648" }; // input string size int32 str_len = strlen(value); // is sign mark exist in input string int32 signExist = (*value == '-'); // first non zero digit in input number int32 non_zero_index = signExist; // locate first non zero index while(non_zero_index < str_len && value[non_zero_index] == 0) non_zero_index++; // if non_zero_index equal length then all digits are zero if (non_zero_index == str_len) return false; // get number of digits that actually represent the number int32 diff = str_len - non_zero_index; // if difference less than 10 digits then no overflow will happened if (diff < 10) return false; // if difference greater than 10 digits then overflow will happened if (diff > 10) return true; // left digit in input and search strings int8 left1 = 0, left2 = 0; // if digits equal to 10 then loop over digits from left to right and compare for (int32 i = 0; non_zero_index < str_len; non_zero_index++, i++) { // get input digit left1 = value[non_zero_index]; // get match digit left2 = max_numbers[signExist][i]; // if digits not equal then if left1 is greater overflow will occurred, false otherwise if (left1 != left2) return left1 > left2; } // overflow won't happened return false;} فى البدايه تم تعريف المصفوفه max_numbers و التى تحتوى على نصين يمثلوا اكبر و أقل قيمه يمكن تخزينها داخل متغير من نوع int32 و كما تلاحظ لم أضع الإشاره و سأشرح لك لماذا بعد قليل، الخطوه التاليه هى الحصول على عدد الحروف داخل النص المدخل و حفظها داخل المتغير str_len بعدها يتم التحقق إذا ما كان النص المدخل أول حرف به هو الإشاره السالبه أم لا و يتم تخزين النتيجه داخل المتغير signExist، كما ترى نوع هذا المتغير هو int32 و ليس bool و السبب فى ذلك يرجع إلى انى احتاج القيمة 0 أو 1 لتعبر عن عدم وجود او وجود الإشاره و التى سأستفاد بها فيما بعد عند تمريرها للمصفوفه max_numbers لأعرف أى النصين سأقوم بالمقارنه معه فإن كانت الإشاره موجوده فستكون قيمة signExist بواحد و بالتالي الرقم المدخل سأقوم بمقارنته مع العنصر الثاني فى المصفوفه و الذى يقابل INT_MIN و إذا كانت الإشاره غير موجوده ستكون قيمة signExist بصفر و سأقارن مع العنصر الأول فى المصفوفه و الذى يقابل INT_MAX. الخطوه التاليه هى بتجاهل الأصفار و كما ترى تم تعريف المتغير non_zero_index و وضع قيمته الإفتراضيه من قيمة signExist حيث إذا كانت الإشاره غير موجوده ستصبح قيمة non_zero_index صفر و البحث عن الإصفار سيبدأ من أول عنصر أما إذا كانت الإشاره موجوده ستصبح فقيمة non_zero_index بواحد و سيتم البحث عن الأصفار من العنصر الثاني. بعد ذلك يتم الدوران على النص و سيتم زيادة المتغير non_zero_index بواحد طالما ان الموقع الذى يمثله قبل الزياده يحتوى على صفر و ايضا طالما انه قيمة non_zero_index اقل من عدد الحروف بالنص المدخل. بعد ذلك إذا كان قيمة non_zero_index تساوى عدد الحروف فهذا يعنى ان النص يحتوى كله على اصفار و سيتم العوده بـ false و التى تعنى انه لن يتم حدوث overflow. بعد ذلك اقوم بالحصول على عدد الحروف التى تمثل الرقم بدون الأصفار و الإشاره و اقوم بحفظ الناتج داخل المتغير diff. الأن أقوم بالتحقق من قيمة diff حيث إذا كانت أقل من 10 خانات (و هو عدد الخانات التى يستغلها أى من الرقمين داخل المصفوفه) فهذا يعنى ان الرقم المدخل أقل من الرقم الموجود بالمصفوفه و سيتم العوده بـ false و إذا كان أكبر من 10 فهذا يعنى انه سيحدث overflow و سيتم العوده بـ true. إذا كان diff يساوى 10 فهذا يعنى اننا لابد و أن نقارن الرقم المدخل مع اى من الرقمين الموجودين فى المصفوفه و الذى سيتم تحديده من خلال قيمة المتغير signExist. بعد ذلك تبدأ عملية الدوران للمقارنه بين الحرفين بالمصفوفه بنفس الموقع فإن كان الرقمين متساويين فسيتم إكمال الدوران للحرف التالي أما إن كانوا غير متساويين فسيتم الرجوع بـ true إذا كانت قيمة الحرف بالنص المدخل أكبر من الحرف الموجود بالنص الذى يتم المقارنه معه - النص الموجود بالمصفوفه - و سيتم العود بـ false غذا حدث العكس. إذا انتهت حلقة الدوران فهذا يعنى ان النص المدخل يساوى اكبر رقم يمكن للنوع int32 ان يحفظه و هذا يعنى عدم حدوث overflow و بالتالي يتم العوده بـ false. قد تتسائل و ماذا عن أختبار الـ overflow للنوع int32 مع النظام الثماني و السداسى عشرى و الثنائى؟ الفكره واحده فى جميع الحالات و التطبيق واحد و لكن مع النظام السداسى العشرى تحتاج للإحتياط حيث انه لديك الحروف A-F و ايضا الحروف من a-f و على اعتبار ان الداله ستتعامل مع النوع السداسى عشرى و الرقم المدخل يحتوى فقط على الرموز المقبوله لهذا النظام حينها يمكنك استخدام الرموز من a-f بدلا من الرموز A-F و ذلك حتى إذا قام المستخدم بإدخال الحروف الكبيره فستقوم دالتك بالتعامل مع الموقف بشكل سليم. الداله التاليه تقوم بالتحقق من حدوث overflow للنوع int32 لكل الأنظمه العديده و لاحظ ان النظامين العشرى و الثماني هم فقط من يسمحوا بوجود إشاره سالبه فى اقصى اليسار، ايضا الداله تفترض على الأقل وجود حرف واحد بالنص: typedef signed char int8;typedef signed int int32;#define DEC 0#define HEX 1#define OCT 2#define BIN 3bool isOverflow(const char* value, int32 base){ // left-most digit for maximum and minimum number static const char* max_numbers[4][2] = { // INT_MAX INT_MIN { "2147483647", "2147483648" }, // decimal { "7fffffff", "80000000" }, // hexadecimal { "17777777777", "20000000000" }, // octal { "01111111111111111111111111111111", "10000000000000000000000000000000" } // binary }; // size of strings in max_numbers array static const int32 number_sizes[] = { 10, 8, 11, 32 }; // input string size int32 str_len = strlen(value); // is sign mark exist in input string int32 signExist = ((base == DEC || base == OCT) && *value == '-'); // first non zero digit in input number int32 non_zero_index = signExist; // locate first non zero index while(non_zero_index < str_len && value[non_zero_index] == 0) non_zero_index++; // if non_zero_index equal length then all digits are zero if (non_zero_index == str_len) return false; // get number of digits that actually represent the number int32 diff = str_len - non_zero_index; // if difference less than 10 digits then no overflow will happened if (diff < number_sizes[base]) return false; // if difference greater than 10 digits then overflow will happened if (diff > number_sizes[base]) return true; // left digit in input and search strings int8 left1 = 0, left2 = 0; // if digits equal to 10 then loop over digits from left to right and compare for (int32 i = 0; non_zero_index < str_len; non_zero_index++, i++) { // get input digit left1 = value[non_zero_index]; // get match digit left2 = max_numbers[signExist][i]; // if digits not equal then if left1 is greater overflow will occurred, false otherwise if (left1 != left2) return left1 > left2; } // overflow won't happened return false;} قد تتسائل، الأن و قد عرفنا كيف نقوم من التحقق من حدوث overflow لرقم صحيح، ماذا عن الأرقام العشريه؟ الأرقام العشريه أسلوب التحقق منها مختلف كثيرا و اعقد من الأرقام الصحيحه و يتطلب معرفه جيده بترميزها فى الذاكره، قد اشرحها يوما ما و لكن بالتأكيد لن يكون اليوم. و الله ولي التوفيق
  2. ترميز الحروف

    بسم الله الرحمن الرحيم العقل الذى وهبه الله للإنسان يستطيع التفرقة بين الكلمات المكتوبة بلغته و أى لغه أخرى و هذا على خلاف الأله التى تحتاج لوسيله محدده للتفرقة بين حروف اللغات التى يتم الكتابة بها. هذه الوسيلة تسمى بترميز الحروف و هى محور هذا الموضوع[1]. فى هذا الموضوع مقدمةترميز ASCIIصفحة المحارف Codepageصفحة المحارف ذات الحجم المتغير Multi-byte Codepageترميز Unicodeترميز UTF-8ترميز UTF-16ترميز UTF-32علامة BOMمكتبة charsetخاتمةمقدمة اللغات الطبيعية القائمة على حروف، كل حرف بها له 3 خصائص: صوت: و هو الطريقة التى يتم نطق الحرف بها.ترتيب: و هو موقع الحرف داخل السلسة الهجائية الخاصه باللغه.شكل: و هو الهيئة التى يتم رسم هذا الحرف بها اثناء الكتابة.فى علوم الحاسب العلم الذى يختص بدراسة أصوات الكلام هو Speech Processing و العلم الذى يختص بدراسة شكل الحرف و رسمه هو Typography. أما ترتيب الحرف فالمفهوم داخل الحاسب يختلف على ما هو عليه فى اللغات الطبيعية و المجال الذى يختص بدراسته هو Character encoding. يعتبر مجال Character encoding من أهم مجالات الحاسب التى لا يهتم بها الكثيرون، فبسببه أمكن رسم الحروف و طباعتهم و التعامل معهم، و قد مر هذا المجال بالعديد من المراحل إلى أن وصل لمرحلة الإستقرار التى نشهدها حاليا. فى الماضى دعت الحاجه لوجود وسائل لإرسال و إستقبال الرسائل النصية و أول هذه الوسائل هى شفرة مورس و التى قامت بإعطاء كل حرف سلسلة من الحالات المنطقيه التى تتكون من قيمتين فإما (صفر و واحد) أو (نقطه و شرطه) أو (مضاء و مطفي) و هكذا. شفرة مورس تمثل ببت واحد - One Bit - و ذلك لطبيعة اى عنصر فى السلسلة. أحد المشاكل فى شفرة مورس هى انها ديناميكية حيث ان كل حرف لا يستغل مساحه ثابته و لكن متغيره و تحدد بالحرف نفسه و ايضا لابد من وجود شخصين مدربين عليها ليستطيعوا إرسال و استقبال الرسائل بها. مر بعض الوقت و تم إبتكار شفرة بودت التى أستخدمت مساحه ثابته للحرف - تسمى كود الحرف - و كانت 5 بت و استطاعت تمثيل 32 حرف منهم حروف اللغه الإنجليزية الكبيرة فقط. بعدها بفترة قام دونالد ميوراى بإجراء بعض التعديلات على شفرة بودت و أضاف إليها بعض الحروف الغير مرئية و سميت شفرة ميوراى و قام بإستخدام الشفرة المعدلة داخل اله كاتبه بسيطه ذات ازرار تكتب بها و عندما تضغط على زر نهاية السطر يتم إرسال محتويات السطر دفعة واحده[2]. شفرة ميوراى كانت خطوة كبيرة فى عالم إرسال البيانات حيث من بعد نشره لها بفترة ليست كبيرة تم إضافة العديد من الحروف الغير المرئية مثل المسافه الخالية للفصل بين الكلمات و حرف أخر لإحداث جرس عند إتمام إرسال السطر، هذه الشفرة المعدلة إستخدمت 6 بت فقط و أستطاعت تمثيل 64 حرف و ظل إستخدام هذه الشفرة المعدلة لفترة طويلة. عندما تم توسيع المساحه المستخدمه للحرف إلى 6 بت تم إبتكار العديد من وسائل لترميز الرسائل و أكثرها إنتشارا وقتها كان من تصميم IBM و إسمه Binary-Coded Decimal حيث تم تقسيم الـ 6 بت إلى جزئين و كل منهم يمثل الأرقام من صفر و حتى 7 و بعدها تم إستخدام هذه الأرقام فى مجموعات ذات معنى متشابه. بعد فترة من الزمن تم إقتراح إضافة الكود shift للحروف الموجوده و ذلك ليعطى معنى أخر لكل كود موجود و بالتالي يتم مضاعفة الحروف المستخدمه فبدلا من 64 حرف يصبحوا 128 و أصحاب الفكرة أقروا بأن هذه الوسيلة ستسمح بتمثيل الحروف الكبيرة و الصغيرة بالإضافة لأكواد التنسيق و الأرقام و أضافوا أن القيم المرسلة ستكون صغيرة، و لكن بعد التصويت تم رفض هذا الإقتراح و السبب الذى أجمتعوا عليه أنه إذا حدث خطأ فى إرسال البيانات فوجود الكود shift سيجعل الرسالة بأكملها تالفه و لا يمكن إسترجاع أى شئ منها[3]. رفض إضافة الكود shift أدى إلى إضافة بت جديد للمساحه الموجوده لتصبح 7 بت و هذا أدى إلى ميلاد ASCII.     ترميز ASCII وجدت العديد من المحاولات لتصميم ترميز بمساحة 7 بت و أنجح هذه المحاولات كان فى عام 1963 حيث قامت منظمة American Standards Association بتصميم ترميز يحتوى على 128 رمز بمساحة 7 بت للرمز الواحد و سمي بـ American Standard Code for Information Interchange و إختصارا ASCII. السبب فى إستخدام الكلمه رمز و ليس الكلمة حرف عائد إلى أن تصميم ASCII الأصلي كان يحتوى على أكواد لرموز غير مرئية و حروف و علامات ترقيم و أرقام و غيرهم و لهذا فالكلمه رمز تعطي معنى أدق و أعم من غيرها. التصميم الأصلي قام بحجز أول 32 كود للعمليات الغير مرئية و البقية لتمثيل الحروف و الأرقام و علامات الترقيم و غيرهم، و لكن فى ذلك التصميم لم يتم تحديد طبيعة معظم الأكواد الـ 32 الأولى و هذا سبب تضارب بين الأجهزة التى صممتها بعض الشركات حيث بعضهم كان يستخدم هذه الأكواد لتعنى شئ فى حين أخرين يستخدموا نفس الأكواد لتعنى شئ أخر[4]. بالإضافة لهذه المشكلة ظهرت مشكلة إرسال بعض الأكواد الغير مرئية ليتم تنفيذها على الجهاز الهدف بدل من تنفيذها على جهاز المصدر، هذه المشكلة تم حلها بإستخدام الكود ESC و الذى يتم إرساله و بعده سلسلة من الحروف بهيئة معينه و التى عندما يتم إستقبالها على الجهاز الهدف يتم تحويلها لكود و يتم تنفيذه. الكود ESC أظهر سلسلة جديدة من الأكواد عرفت بالإسم ANSI Escape code. تصميم ASCII كان يحتوى على الحروف الإنجليزية فقط و هذا أدى العديد من الدول بتغيير قيم بعض الحروف لأخرين ليستطيعوا تمثيل لغاتهم، و هذا جعل التضارب يزيد و جعل ASA فى عام 1967 تقوم بتثبيت بعض رموز ASCII و ترك البعض ليتم إستبدالهم من خلال اللغات الأخرى. التوثيق الذى تم إصداره فى 1967 تم ترك بعض الحروف من ASCII للإستخدام الدولي و الذى أدى لظهور بعض المشاكل منها عدم قيام بعض الدول بتحديد حروف للاماكن المتاحه. من الأكواد التى تركت للإستخدام الدولي رمز القوس المفتوح و المغلق و الذى جعل مصممي لغة الـ C و بعض اللغات الأخرى بإضافة ما يسمى Trigraph Sequence داخل تصميم لغاتهم و ذلك ليتم إستخدامهم بدلا من بعض الرموز الغير مدعومه فى ترميز لغة معينه. فى عام 1968 تم إستخدام الإسم US-ASCII للإشارة للنسخه التى تحتوى على الحروف الإنجليزية و الرموز التى تم وضعها من قبل ASA و تم تشيجع إستخدام هذا الإسم حيث كان يوجد وقتها بعض النسخ الأخرى من ASCII مثل German-ASCII و French-ASCII و غيرهم. فى عام 1986 تم الإستقرار على محتوى US-ASCII و الذى يتم إستخدامه حتى يومنا هذا، و هو كالتالي: ╔═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╗║ NUL ║ SOH ║ STX ║ ETX ║ EOT ║ ENQ ║ ACK ║ BEL ║ BS ║ HT ║ LF ║ VT ║ FF ║ CR ║ SO ║ SI ║║ 001 ║ 001 ║ 002 ║ 003 ║ 004 ║ 005 ║ 006 ║ 007 ║ 008 ║ 009 ║ 00A ║ 00B ║ 00C ║ 00D ║ 00E ║ 00F ║╠═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╣║ DLE ║ DC1 ║ DC2 ║ DC3 ║ DC4 ║ NAK ║ SYN ║ ETB ║ CAN ║ EM ║ SUB ║ ESC ║ FS ║ GC ║ RS ║ US ║║ 010 ║ 011 ║ 012 ║ 013 ║ 014 ║ 015 ║ 016 ║ 017 ║ 018 ║ 019 ║ 01A ║ 01B ║ 01C ║ 01D ║ 01E ║ 01F ║╠═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╣║ SPC ║ ! ║ " ║ # ║ $ ║ % ║ & ║ ' ║ ( ║ ) ║ * ║ + ║ , ║ - ║ . ║ / ║║ 020 ║ 021 ║ 022 ║ 023 ║ 024 ║ 025 ║ 026 ║ 027 ║ 028 ║ 029 ║ 02A ║ 02B ║ 02C ║ 02D ║ 02E ║ 02F ║╠═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╣║ 0 ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6 ║ 7 ║ 8 ║ 9 ║ : ║ ; ║ < ║ = ║ > ║ ? ║║ 030 ║ 031 ║ 032 ║ 033 ║ 034 ║ 035 ║ 036 ║ 037 ║ 038 ║ 039 ║ 03A ║ 03B ║ 03C ║ 03D ║ 03E ║ 03F ║╠═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╣║ @ ║ A ║ B ║ C ║ D ║ E ║ F ║ G ║ H ║ I ║ J ║ K ║ L ║ M ║ N ║ O ║║ 040 ║ 041 ║ 042 ║ 043 ║ 044 ║ 045 ║ 046 ║ 047 ║ 048 ║ 049 ║ 04A ║ 04B ║ 04C ║ 04D ║ 04E ║ 04F ║╠═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╣║ P ║ Q ║ R ║ S ║ T ║ U ║ V ║ W ║ X ║ Y ║ Z ║ [ ║ \ ║ ] ║ ^ ║ _ ║║ 050 ║ 051 ║ 052 ║ 053 ║ 054 ║ 055 ║ 056 ║ 057 ║ 058 ║ 059 ║ 05A ║ 05B ║ 05C ║ 05D ║ 05E ║ 05F ║╠═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╣║ ` ║ a ║ b ║ c ║ d ║ e ║ f ║ g ║ h ║ i ║ j ║ k ║ l ║ m ║ n ║ o ║║ 060 ║ 061 ║ 062 ║ 063 ║ 064 ║ 065 ║ 066 ║ 067 ║ 068 ║ 069 ║ 06A ║ 06B ║ 06C ║ 06D ║ 06E ║ 06F ║╠═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╣║ p ║ q ║ r ║ s ║ t ║ u ║ v ║ w ║ x ║ y ║ z ║ { ║ | ║ } ║ ~ ║ DEL ║║ 070 ║ 071 ║ 072 ║ 073 ║ 074 ║ 075 ║ 076 ║ 077 ║ 078 ║ 079 ║ 07A ║ 07B ║ 07C ║ 07D ║ 07E ║ 07F ║╚═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╝و الـ Control Characters هم: 00 = NUL = Null character01 = SOH = Start of Header02 = STX = Start of Text03 = ETX = End of Text04 = EOT = End of Transmission05 = ENQ = Enquiry06 = ACK = Acknowledgment07 = BEL = Bell08 = BS = Backspace09 = HT = Horizontal Tab0A = LF = Line feed0B = VT = Vertical Tab0C = FF = Form feed0D = CR = Carriage return0E = SO = Shift Out0F = SI = Shift In10 = DLE = Data Link Escape11 = DC1 = Device Control 112 = DC2 = Device Control 213 = DC3 = Device Control 314 = DC4 = Device Control 415 = NAK = Negative Acknowledgment16 = SYN = Synchronous idle17 = ETB = End of Transmission Block18 = CAN = Cancel19 = EM = End of Medium1A = SUB = Substitute1B = ESC = Escape1C = FS = File Separator1D = GS = Group Separator1E = RS = Record Separator1F = US = Unit Separator7f = DEL = Delete      صفحة المحارف Codepage كانت أحد المشاكل فى ASCII انه لا يوجد توثيق للنسخ المعدله حيث كل دوله كان لها نسختها الخاصه من ASCII التى تطورها و ترعاها، هذا التشتت جعل ISO تصدر اول توثيق لها فى مجال تبادل المعلومات و أسمته ISO 646 توثيق ISO 646 كان يماثل توثيق ASCII مع ترك بعض الأماكن المحدده للإستخدام الدولي، و كل من استخدم هذا التوثيق و تقيد بقيوده تم تثبيت نسخه تماثل التى قام بتحديدها. مع العلم أن IBM كانت من المشتركين فى تصميم ASCII إلا أن تصميم أجهزتها كان يستخدم 6bit BCD و الذى كان من الصعب إستبداله بـ ASCII لذا قامت IBM بمد المساحه من 6bit إلى 8 بت و أقترحت توسيع ASCII لتصبح 8 بت و لكن تم رفض هذا الإقتراح. قامت IBM بتطوير نظام BCD إلى 8 بت و هذا ادى إلى توسيع كل خانة لتشمل الأرقام من 0 إلى 9 و قامت بتطوير أجهزتها للعمل به. هذا التصرف من IBM أدى لتطوير العديد من المنشئات لخطوط أنتاجهم لجعلها 8 بت بدلا من 7 بت و تم جعل البت الثامن بصفر[5] و ذلك لإتمام التوافق مع ASCII. مع وجود معالجات تقوم بنقل 8 بت دفعه واحدة قامت العديد من المنشئات بإستغلال البت الثامن لأغراضهم الخاصه فى منتجاتهم لتوسيع المساحه المستخدمه لترميز الحروف، مع إنتشار هذا الإسلوب ظهر المسمى Extended ASCII و الذى يعنى إستخدام البت الثامن لترميز عناصر أخرى مع وجود ASCII داخل المدى 0 إلى 127. المسمى Extended ASCII أدى البعض للإعتقاد أن ASCII تم تطويرها لتصبح 8 بت لتشمل بعض الرموز الجديده و هذا غير صحيح. فى الماضي تم إستخدام المصطلح Page للإشارة إلى مساحه ثابته من الذاكرة، و حيث أن الـ 8 بت تنقسم لجزئين متساويين كل منهم يستطيع تمثيل 128 قيمة فتم ترك الجزء العلوى فى المدى 0 إلى 127 لـ ASCII و تم تسمية الجزء الأخير بالإسم Code page. كانت IBM هى من أبتكر المصطلح[6] Code page و أول إستخدام له كان مع تطوير ترميز BCD إلى EBCDIC و بعدها تم إستخدامه داخل نظام التشغيل PC DOS و من وقتها و أصبح المصطلح شائع من شركات كبرى مثل مايكروسوفت و غيرها. مع أن EBCDIC لم يكن ذات شهره عالية إلا أن الـ Code pages التى تم إستخدامها داخل نظام PC DOS أصبح لها شهره عالية لأنها قامت بتمثيل العديد من اللغات و أولهم و أشهرهم هى Code page 437، هذه الـ code pages كان لها العديد من الأسماء مثل CP-n و OEM-n و PC-n حيث n هو مجرد رقم و مع العلم ان الثلاث مسميات قد يشيروا إلى صفحة محارف واحدة إلا أن الرقم قد يكون مختلف و هذا عائد إلى انه توجد العديد من نسخ DOS و كل منهم موجه لبيئة محدده و من هنا جاء إختلاف المسميات. قامت منظمة ISO بإعادة النظر فى توثيقها القديم ISO 646 و قامت بإصدار توثيق جديد بالإسم ISO 8859 ليواكب التطورات و قامت فيه بإستخدام البت الثامن لبعض من اللغات الأخرى و أعطتها الإسم ISO 8859-n حيث n هو رقم من 1 إلى 16 ماعدا 12 فلم يتم كتابة صفحة محارف له. عندما قامت ميكروسوفت بتصميم نظام تشغيل ويندوز قامت بكتابة صفحات محارف خاصه بنظامها و تأخذ الإسم Windows-125n حيث n هو رقم الصفحة فى المدى من 0 إلى 8. أيضا داخل نظام ويندوز ستجد صفحات المحارف التى صممت لـ DOS و لكنها بالإسم OEM-n بدلا من الإسم CP-n. و لكن حتى مع كل هذه التطورات وجدت لغات تحتوى على رموز بالألاف و التى كان من المستحيل ترميزها داخل 8 بت و هذا أدى إلى ظهور مصطلح جديد يسمى Multi-byte Codepage.     صفحة المحارف ذات الحجم المتغير Multi-byte Codepage الحل المقترح كان بجعل ترميز الحروف على قسمين كالتالي: ترميز بحجم ثابت: و أى رمز به يتم تمثيله بمساحه ثابته. هذا الترميز يسمى بـ Fixed-width Character Encoding، مثال على هذا الترميز ASCII.ترميز بحجم متغير: و أى رمز به يتم تمثيله فى مساحه ثابته و يمكن تكرار هذه المساحه عدد معين من المرات. هذا الترميز يسمى بـ Variable-width Character Encoding.لحل مشكلة اللغات التى تحتوى على أكثر من 128 رمز تم إستخدام إسلوب الترميز بحجم متغير و تطبيقه على المدى FF-80 حيث تم تقسيم هذا المدى إلى ثلاثة أقسام: singleton: وهى أكواد قيمتها تمثل رمز محدد، مثل أن الكود 5916 يمثل الحرف Y داخل ASCII.lead-units: و هو كود أو أكثر يمثل بداية سلسلة من عدة أكواد و هم مجتمعين يمثلوا الرمز. (سيتم تفصيل هذه النقطه لاحقا).trail-units: و هو كود أو أكثر يمثل نهاية السلسلة التى بدءت بالـ lead-units.مع العلم أن الـ lead-units قد تكون كود واحد أو أكثر إلا أن أغلب صفحات المحارف ذات الحجم المتغير إن لم يكن جميعهم يستخدم كود واحد فقط لتيسير عملية التكويد. لنأخذ مثال لتقريب الفكرة، لنفترض ان لدينا الحروف (أ ت ج ح م ي لأ) و نريد إستخدام صفحة محارف ذات حجم متغير، حيث الأكواد بها لابد أن تكون عبارة عن سلسلة من lead-units و trail-units لذا قيمة هذه الحروف ستكون كالتالي: أ : EE 80 01 FFت : EE 80 0E EFج : EE 80 11 99ح : EE 80 11 9Fم : EE 80 1F 6Aي : EE 80 2A 3Bلأ : EE 83 05 0Aصفحات المحارف ذات الحجم المتغير تقوم بتحديد كود البداية (ذات اللون الأزرق) و الذى عند تحديده يتم تحميل صفحة محارف داخلية ليتم من خلالها تحديد الرمز المطلوب بناءا على أكواد النهاية (ذات اللون الأخضر) و مع كل كود يتم قرائته يتم معرفة أحتمالات القيم القادمة و أيهم قد يكون هو كود نهاية السلسلة. أكواد الحروف التى تراها بالأعلى هى من محض خيالي حيث فى الأغلب ستجد أن أكبر حرف فى صفحة محارف ذات حجم متغير يأخذ ثلاثة أكواد فقط و لكني أحببت كتابتهم بهذا الإسلوب لإعطائك فكرة تصميمهم، أيضا تصميم أكواد الرموز يكون فى الأغلب عشوائي و حسب الأكواد التى لم يتم إستخدامها. مع أن هذا الإسلوب نجح فى تمثيل كافة رموز اللغات إلا أن له عيوب كثيره منها: الأكواد لا تمثل قيمة رقمية صحيحه يمكن الوصول بها للرمز المطلوب، فمثلا داخل ASCII الكود 5916 هو رقم صحيح يمثل الحرف Y، أما الأكواد المستخدمه فى هذا الترميز فلا معنى لها.الوسيلة الوحيده للبحث داخل نص يحتوى على هذه الأكواد هو بقرائتهم بالكامل لإنك لا تعرف طول السلسلة و هذا يسبب بطء كبير فى عمليات معالجة النصوص.وجود خطأ فى أحد الأكواد يتلف النص بأكمله لأنه كما ترى الـ trail-units قد تحتوى على أكواد إذا تم قرائتهم وحدهم فإنهم يمثلوا حروف موجوده أو أكواد بداية لسلسلة أخرى.هذا بالإضافة لبعض العيوب الأخرى. و لكن حتى مع النجاح الذى حققته هذه الطريقه إلا أنه لازالت مشكلة إستخدام أكثر من لغه داخل نص واحد موجوده و لا حل لها. كل هذه المشاكل و غيرهم تم إيجاد لهم حلول مرنة و يسيرة من خلال منظمة Unicode.     ترميز Unicode فى عام 1988 قام جو بيكر بطياعة توثيق مبدئي و أطلق عليه الإسم Unicode و الذى محتواه كان يهدف إلى إيجاد ترميز موحد لكل الرموز بكل لغات العالم و ذلك بمد المساحه المستخدمه لـ ASCII من 8 بت إلى 16 بت و أطلق إسم مجازى على المساحه الموسعه و هو "wide ASCII" و أوضح أن إسم التوثيق يعني "Unique, Unified, Universal encoding". فى عام 1990 تم إنشاء مجموعة بالإسم Unicode group و قام أعضائها بالإضافه لأعضاء من ISO بالعمل على إعطاء كافة حروف لغات العالم وصف و كود محدد داخل Unicode. فى عام 1991 تم إنشاء منظمة غير ربحية بالإسم Unicode Consortium و إختصارا Unicode، و تم إصدار أول توثيق لها فى نفس العام و تم تحديد به أن المساحه التى يستهلكها الحرف الواحد هى 16 بت. و فى الإصدار الثانى تم إضافة كافة حروف Han ليكتمل توثيق كافة الحروف المستخدمه عالميا. العمل على تطوير الإصدار الثاني تم بالتعاون بين Unicode و ISO، و بعد إصدار ذلك التوثيق من Unicode قامت ISO بإصدار توثيق خاص بها بالإسم Universal Character Set و له الكود ISO/IEC 10646 و كلاهما يتماثل فى المضمون مع إختلاف بعض المصطلاحات، أيضا كلاهما له نفس قاعدة بيانات الحروف زاد الأول أو نقص عن الأخير ببعضهم. قاعدة بيانات الحروف لها الإسم UCD و هذا الإسم مع توثيق Unicode يعنى Unicode Character Database و مع ISO فإنه يعني Universal Character set Database و مع أن مصطلح الإختصار مختلف إلا أن كلاهما يشير إلى نفس البيانات. داخل قاعدة بيانات الحروف كل حرف له رقم فريد لا يتكرر فى المدى من 016 إلى 10FFFF16، هذا الرقم يسمى Unicode scalar value أو character value طبقا لـ ISO أى القيمة الصحيحه للحرف، و كل حرف يتم إعطائه وصف محدد غير مرتبط بشكل حيث أن الحرف الواحد داخل لغه معينه قد يكون له أكثر من شكل و لكن له وصف واحد فريد مرتبط به. تبعا لذلك التعريف فإنك ستجد بداخل قاعدة البيانات حرفين قد يكون لهم نفس الشكل و لكن لأن كل منهم فى لغه مختلفه فإن وصف الحرف مختلف و بالتالي كل منهم هو حرف مختلف.   فى التوثيق الأول من Unicode تم إستخدام ترميز بمساحة 2 بايت و تم إعطائه الإسم UCS-2 و أستطاع تمثيل كافة القيم الصحيحه للحروف فى المدى من 016 و حتى FFFF16 و تم نبذ هذا الترميز عندما تم توسيع قاعدة البيانات من FFFF16 إلى 10FFFF16. القيمة الصحيحه للحرف تستخدم للوصول إليه داخل قاعدة البيانات و حيث أن أكبر قيمة يتم حفظها داخل 4 بايت فإن التعامل المباشر مع هذه القيمه فى الحفظ و الإسترجاع و المعالجه داخل الذاكرة غير عملى و لهذا تم إيجاد طريق لترميز تلك القيمه و التى من شأنها جعل عملية الحفظ و الإسترجاع تتم لمساحه أصغر و ايضا عملية إستخلاص قيمة الحرف من الترميز يسيرة و سريعة، الترميز الإفتراضي المستخدم فى عملية الترميز فى كلا التوثيقان هو UTF-16 أو Unicode Transformation Format 16-bit.   داخل توثيق ISO تم تحديد ترميزان و هم UCS-2 و UCS-4، أما الأول فقد ذكرت أنه تم نبذه و الأخير يستخدم لحفظ القيمة الصحيحه للحرف داخل 4 بايت. داخل توثيق Unicode تم تحديد الترميز UTF-16 كبديل لـ UCS-2 و أيضا ترميز UTF-32 كتضمين لـ UCS-4، بالإضافة لهؤلاء تم إضافة ترميز أخر و هو UTF-8 و الذى تم إبتكاره كبديل لـ ASCII. فى الوقت الحالي توثيق ISO يستخدم UTF-8 -16 -32 لترميز القيمة الصحيحه للحرف و داخل التوثيق تم إستخدام المصطلح code-point ليعنى القيمة الصحيحه للحرف فى المدى المسموح به داخل الترميز. كل ما ذكرناه ينطبق على التعامل مع قاعدة بيانات الحروف و ترميز القيمة الصحيحه لكل حرف بها و إلى هنا هذا هو أقصى ما يصل إليه توثيق ISO، أما توثيق Unicode فيستمر إلى أبعد من ذلك حيث يحتوى على وسائل للبحث داخل النصوص التى تحتوى على أكثر من لغه بالإضافة لقواعد كتابة أكثر من لغة معا و غيرها[7]. داخل Unicode الترميز UTF-X - حيث X هو عدد البتات - يتم الإشارة إليه بعدد البتات التى يتم إستخدامها داخل الترميز كوحدة بيانات واحدة و تسمى code-unit، أيضا يمكن ان يتم حفظ قيمة الـ code-point داخل وحدة واحدة أو أكثر من الـ code-unit. مع العلم أن المساحات المستخدمه هى عدد البتات بكل من 1 و 2 و 4 بايت إلا أن إستخدام عدد البتات يرجع إلى أن العمليات فى كل ترميز تتم على مستوى البت. التصميم الأصلى لـ Unicode كان يحتوى على 65536 حرف داخل قاعدة بياناته، و عندما تم زيادة هذا المدى إلى 10FFFF16 حينها تم تسمية المدى الأصلي بالإسم Basic Multilingual Plane و إختصارا BMP، ذلك المدى يأخذ الترتيب صفر و يحتوى على أغلب حروف العالم، و باقي المساحه تم تقسيمها 16 جزء كل منهم بمساحة 65536 حرف و هم كالتالي[8]: Plane 0: Basic Multilingual Plane 0000-FFFFPlane 1: Supplementary Multilingual Plane 10000-1FFFFPlane 2: Supplementary Ideographic Plane 20000-2FFFFPlane 3-13: Unassigned 30000-DFFFFPlane 14: Supplementary Special-purpose Plane E0000-EFFFFPlane 15-16: Supplementary Private Use Area F0000-10FFFF      ترميز UTF-8 الهدف من وراء تصميم هذا الترميز[9] هو أن يكون بديل لـ ASCII، حيث من خلاله يمكن إستخدام ASCII و باقي حروف Unicode بدون مشاكل، هذا الترميز يستهلك 8 بت أو one-octet للـ code-unit الواحده و هو ديناميكي حيث عدد الـ code-unit المستخدم يكون فى المدى من 1-4 و ذلك حسب قيمة الـ code-point تبعا للجدول التالي:   +---------------------+-------------------------------------+| character code point| UTF-8 octet sequence |+---------------------+-------------------------------------+| 0000 0000-0000 007F | 0xxxxxxx |+---------------------+-------------------------------------+| 0000 0080-0000 07FF | 110xxxxx 10xxxxxx |+---------------------+-------------------------------------+| 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx |+---------------------+-------------------------------------+| 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |+---------------------+-------------------------------------+من الجدول السابق تجد أنه إذا كان الحروف المستخدم فى المدى من 016 إلى 7F16 - و هو المدى الخاص بـ ASCII - فإن الحرف يتم ترميزه داخل code-unit واحده و عندما تكون قيمة الحرف فى المدى من 8016 إلى 10FFFF16 فإن البتات الخاصه بتلك القيمه يتم توزيعها بناءا على الجدول السابق و أن أول code-unit يحتوى داخل الـ Most significant bits الخاصه به على عدد code-units التى تمثل code-point فتجد ان المدى 8016-7FF16 أول بايت به يحتوى على 2 بت و هذا يعنى وجود two code-units و نفس الامر ينطبق على كل مدى تم تحديده بالجدول. عملية توزيع البتات الخاصه بالـ code point داخل Code Units لها ترتيب محدد و يتم كالتالي: قم بمعرفة عدد الـ Code Units التى تحتاجها لترميز الـ code point.قم بإعداد قيمة البتات الخاصه بالـ Code Units كما هو موجود بالجدول.داخل قيمة الـ Code point قم بأخذ البتات الموجوده بـ lowest-order و ضعها فى المكان المقابل لها داخل lowest-order bits الموجوده بأخر code unit و بعد ان تملء الـ code-unit قم بالذهاب للتي تسبقها مباشرة و قم بتكرار هذه العملية حتى تمتلء كافة الـ x.مثال الحرف "م" يأخذ القيمه U+0645 و لتحويلها لـ UTF-8 نعلم أن هذه القيمة تقع فى المدى الثاني و هذا يعنى أننا نحتاج two code units: 110xxxxx 10xxxxxxالخطوه التالية هي بتوزيع البتات الخاصه بقيمة الحرف و تتم كالتالي: 06 4500000110 01000101 -------> 110xxxxxx 1000010100000110 01 --- ---> 11011001 10000101D9 85كما ترى قيمة الحرف "م" داخل UTF-8 هى D916 8516. للتحويل من UTF-8 لقيمة الحرف code point نحتاج لمساحه أقصاها 21 بت (و هم عدد البتات التى يتم توزيعهم على كافة code units)، الخطوات تتم كالتالي: نقوم بحجز مساحه بحد أقصى 21 بت و نجعل قيمتهم صفر.نقوم بمعرفة عدد الـ code units التى تمثل الـ code point.نقوم بإستخلاص البتات من الـ code units من أقصي اليمين إلى اليسار و يتم و ضعهم داخل البتات (من الخطوه 1) بدءا من lowest-order bit و صلا لـ highest-order bit.الأن لنقوم بإستخلاص الـ code point من القيمه EF16 B716 BD16: EF B7 BD0xEF starts with 1110 which result 3 code-units which means we need 16-bits for target code-pointcp = 0000000000000000-> 11101111 10110111 10111101 ------cp = 0000000000111101 -------> 11101111 10110111 10111101 ------cp = 0000110111111101 -------> 11101111 10110111 10111101 ----cp = 1111110111111101 ----cp = 11111101 11111101 = FD FDالكود FDFD16 هو قيمة الحرف الذى يمثل البسلمة. عندما تكون الـ code units أكثر من واحده حينها تسمى الـ code-unit الأولي بالإسم lead-unit و الباقيين trail-unit و فى هذه الحالة توجد بعض الـ lead-unit التى إذا تم إستخدامها فهذا يعني invalid UTF-8 sequence و هم: C0, C1, F5-FFحيث الأولى و الثانية تسمح بتكويد code point فى المدى 0016-7F16 داخل وحدتين و الأكواد فى المدى F516-FF16 تسمح بتكويد code points فى مدى أكبر من 10FFFF16، أيضا الكود F416 يسمح بتكويد قيم أكبر من المدى المسموح به و لابد من التحقق من القيمه النهائية لتحديد إذا كانت صحيحه أو خاطئة. أحد المزايا الموجوده فى UTF-8 هو انه دائما يمكن معرفة بداية السلسلة و بالتالي إذا وجدت وحدة بداية بقيمه غير صحيحة يمكن بعدها تخطى البقية حتى الوصول لوحدة بداية أخرى (لاحظ ان الوحدات التى ليست بوحدات بداية تبدء دائما بـ 0b10).     ترميز UTF-16 عندما تم تصميم Unicode 1.0 تم إستخدام مساحة مقدارها 16 بت ليتم من خلالها ترميز كافة الحروف و سميت UCS-2، و مع الإصدار الثاني من Unicode تم توسيع مدى الاكواد و معه تم نبذ ذلك الترميز و تم إبتكار ترميز أخر[10] ليكون له بديلا. عند وضع تصميم Unicode 2.0 تم الأخذ فى الحسبان إمكانية إستخدام الترميز UTF-16 مع قيم أكبر من FFFF16، لهذا السبب و لجعل عملية ترميز أكواد الحروف من و إلى ذلك الترميز يسيرة تم حجز مساحه محدوده من أكواد الحروف ليتم إستخدامها بشكل خاص مع هذا الترميز للتعامل مع الحروف التى تحتاج مساحه أكبر من FFFF16. داخل UTF-16 أى code-point يمكن ترميزها داخل عدد two code-units بحد أقصى حيث إذا كانت قيمة الـ code-point أقل من أو تساوى FFFF16 حينها يتم حفظ قيمة الـ code-point داخل وحدة واحده - أى code-unit واحده - و إذا كانت قيمة الـ code-point أكبر من FFFF16 حينها يتم إستخدام وحدتان لترميز الـ code-point، هاتان الوحدتان يطلق على يطلق على الوحدة الأولي - التى توضع يسارا - الإسم High Surrogates، و يطلق على إسم الوحده الأخيره - التى توضع يمينا - الإسم Low Surrogates. بهذا أصبحت أكواد الحروف داخل Unicode تأخذ المساحات التالية: المدى 00DB7F16 - 00000016: يستخدم لتكويد الحروف.المدى 00DBFF16 - 00D80016: يستخدم مع ترميز UTF-16 فى مدى أكبر من FFFF16 داخل الوحده الأولى.المدى 00DFFF16 - 00DC0016: يستخدم مع ترميز UTF-16 فى مدى أكبر من FFFF16 داخل الوحده الأخيره.المدى 10FFFF16 - 00E00016: يستخدم لتكويد الحروف.لتحويل كود فى المدى من 10FFFF16 - 1FFFF16 نقوم بالأتي: يتم طرح القيمه 1000016 من قيمة الكود المدخل.القيمه الباقيه تتكون من 20 بت يتم تقسيمها إلى 10 بت و 10 بت.الـ 10 بت الموجودين على اليسار يتم إضافتهم على القيمه D80016 و القيمه الناتجه ستكون فى المدى من D80016 إلى DBFF16 و هذه قيمة الوحده الاولى.الـ 10 بت الموجودين على اليمين يتم إضافتهم على القيمه DC0016 و القيمه الناتجه ستكون فى المدى من DFFF16 إلى DC0016 و هذه قيمة الوحده الثانية.الخطوات بإسلوب أخر: If (Codepoint <= FFFF) return CodepointU = Codepoint - 10000U = xxxxxxxxxxyyyyyyyyyyA = xxxxxxxxxxB = yyyyyyyyyyCU1 = D800 + ACU2 = DC00 + Breturn CU1, CU2للحصول على قيمة الـ code-point من UTF-16 code-units: إذا كانت قيمة الوحده ليست فى المدى DFFF16 - D80016 حينها قيمة code-unit هى قيمة الـ code-point.إذا كانت قيمة الوحده الاولى ليست فى المدى DBFF16 - D80016 فالترميز خاطئ، و إذا كانت قيمة الوحدة الثانية ليست فى المدى DFFF16 - DC0016 فالترميز خاطئ.قم بطرح القيمه D80016 من الوحده الأولى و القيمه DC0016 من الوحده الثانية و قم بحجز مساحة 20 بت و ضع الناتج من الوحده الأولى فى الـ 10 بت الموجودين يسار الـ 20 بت و الناتج من الوحده الثانية فى الـ 10 بت الموجودين يمين الـ 20 بت.أضف القيمه 1000016 لقيمة الـ 20 بت و الناتج سيكون بحد أقصي 21 بت و هو قيمة الـ code-point.إذا كنت تتسائل لماذا تم تحديد القيمه 10FFFF16 لتكون أقصي قيمة لكود حرف فها هي الإجابه امامك، لأن حينها ستصبح الـ 20 بت تحتوى القيمة FFFFF16 و التى عندما يتم توزيعها ستعطينا الوحدتان DBFF-DFFF16. الإجابه بإسلوب أخر: أقصي قيمة يمكن ترميزها داخل UTF-16 هى القيمه 10FFFF16 و لهذا جعلت أقصى قيمة لأى كود داخل Unicode و Universal Character Set. عملية حفظ الـ 16 بت داخل الذاكره تختلف بإختلاف المعمارية المستخدمه حيث ترتيب الـ 2 بايت الممثلين للـ 16 بت يختلف بين Little-Endian و Big-Endian لذا إستخدام Byte Order Mark مع ترميز UTF-16 أمر أساسي     ترميز UTF-32 يمكنك اعتبار هذا الترميز أبسط ترميز حيث يستطيع تمثيل كافة أكواد Unicode داخل وحدة واحدة بمساحة 32 بت، و هذا يجعل عملية ربط قيمة الحرف و الكود لا تحتاج لأى عمليات. هذا الترميز قلما تجد المحررات أو البرامج تدعمه لأنه المساحه التى يستخدمها مكلفه جدا، و أغلب ما يتم إستخدامه داخليا فى البرامج التى تقوم بقراءة ملفات بصيغة Unicode مثل المترجمات (فى الغالب).     علامة BOM هى إختصار لـ Byte Order Mark و هى إسم للقيمة 0000FEFF32 و تستخدم كأول كود فى سلسلة أكواد بترميز محدد[11] لتقوم بتحديد الترميز المستخدم. UTF-8 عندما يتم إستخدام هذا الترميز فمن الأفضل عدم إستخدام BOM لأن هذا الترميز تم تصميمه ليحوى ASCII بالإضافه لباقي أكواد Unicode و إستخدامك للـ BOM سيجعل البرامج القديمه (desktop - web) تحتاج للتعديل و هذا قد يكون غير متاح، بالإضافه إلى انه إذا تم تمرير سلسلة من الأكواد بهذا الترميز لأى برنامج يدعم UTF-8 فسيستطيع التعرف عليه مباشرة لأن هذا الترميز يسهل التعرف على وحداته بسهوله كما ذكر من قبل. و لكن إذا دعت الحاجه لوجود BOM حينها سيتم تحويل الكود المذكور لـ UTF-8 ليصبح EF BB BF، لاحظ ان هذا الترميز مبني على وحدة مساحتها 8 بت و لهذا فمشاكل ترتيب الوحدات Endianness غير موجوده بهذا الترميز.UTF-16 الوحده الواحدة داخل هذا الترميز تحفظ داخل وحدتين بمساحة 8 بت لكل منهم، و هنا تظهر مشكلة ترتيب الوحدات عند قراءة سلسلة أكواد لأنك إن حفظتهم من ألة تعمل بنمط Big-Endian فإنك لابد من أن تقرأهم بهذا النمط بغض النظر عن طبيعة الأله التى تقوم بالقرأه منها. حل هذه المشكلة يتم بوضع القيمه FEFF16 بأى سلسلة يتم حفظها بهذا الترميز، و عندما تكون السلسلة بنمط Big-Endian فترتيب وحدات هذه القيمه سيكون FE FF - تقرأ من اليسار لليمين - و عندما تكون السلسلة بنمط Little-Endian فترتيب وحدات هذه القيمه سيكون FF FE - تقرأ من اليسار لليمين - و السؤال الذى يتبادر إلى الذهن هو: ماذا يحدث إذا تم حفظ السلسلة من BE و تم قرائتها من LE بترتيب وحدات LE؟ فى هذه الحالة القيمه التى سيتم قرائتها هى FFFE16 و هى تقابل حرف من الحروف الممنوع إستخدامها فى تبادل المعلومات و ايضا احد اوصافه هو انه يمكن استخدامه لمعرفة ترتيب الوحدات مع FEFF16، و هذا يعنى ايا كان الأله التى تقرأ منها فإنه يوجد لديك إحتمالين و هم قراءة FEFF16 أو FFFE16 و إحداهما تدل على ان السلسلة بترميز LE و الأخرى تدل على ان السلسلة بترميز BE.UTF-32 بالمثل مع UTF-16 و لكن فى هذه الحالة سيتم كتابة الأصفار، و بالتالي عند كتابة BOM بنمط Little-Endian فترتيب الأكواد سيكون FF FE 00 00 - تقرأ من اليسار لليمين - و عندما يكون النمط Big-Endian فترتيب الأكواد سيكون 00 00 FE FF - تقرأ من اليمين لليسار.مكتبة charset مكتبة charset قمت بكتابتها بلغة ++C و لها ثلاثة إستخدامات: التحويل code-unit بين من ترميز لأخر.تحويل حرف من character-set إلى Unicode و العكس.تحويل stream كاملة من character-set إلى Unicode و العكس.تحويل stream كامله من character-set لأخرى أو من ترميز Unicode لترميز Unicode أخر.لا يمكن القول على هذه المكتبه انها تدعم Unicode بشكل كامل حيث هذا التعريف يشمل إمكانية تحديد خصائص الحروف مثل حالو الحرف و نوعه و تحويله من حالة لأخرى و غيرها من الخصائص، و لكن يمكنك إعتبار هذه المكتبه كأداة يسيرة يمكن إستخدامها للتحويل من ترميز لأخر.     خاتمة تعرفنا فى هذه المقالة عن الطرق الأوليه فى تبادل البيانات من شفرة موريس إلى شفرة ميوراى إلى ASCII و من ثم ظهور الألات التى تستهلك 8 بت بدلا من 7 بت و معهم ظهور مفهوم صفحة المحارف الواحده و المتعدده و من بعدهم تم جمع محاسن كل هذه الأفكار فى منظومة جيده محدوده المعالم أظهترها Unicode للعالم فى شكل أفكار محدده تم تطبيقها ليظهر لنا أكثر من ترميز للتعامل مع البيانات. قليل ما ذكرته فى هذه المقالة و كثير ما بقي لك لتستكشفه بنفسك و أول خطواتك فى هذا الطريق هي بتحميل الإصدار الأخير من Unicode و القراءه منه و بعدها تحميل اى مكتبه تدعم Unicode للغتك و ابدء بالتطبيق. و الله ولي التوفيق [1]مع العلم أن عنوان الموضوع هو ترميز الحروف إلا أن الهدف منه هو تعريفك بترميز Unicode و كيفية إستخدامه و الإستفاده منه و لهذا سيتم إهمال العديد من الاحداث التاريخية و ذكر أخرين بشكل مجمل حتى لا نقوم بالتركيز على نقاط جانبية اكثر مما ينبغي. [2]هذا السلوك موجود حتى يومنا هذا فى مكتبة الإدخال و الإخراج بلغة السي و يعتبر هو السلوك الإفتراضي حيث لا يتم حفظ المحتويات التى يتم كتابتها داخل stream إلا بعد كتابة علامة السطر الجديد. [3]مع العلم انه تم رفض الكود shift إلا أن بعض المنشئات قامت بتصميم ترميز خاص بها و أستخدمته و لكن ليس لقترة طويلة. [4]راجع جزء ASCII Control characters من مقال Wikipedia. [5]بالإضافة إلى أن IBM هى أول من صنع أجهزة بمعالجات 8 بت فإنها أيضا أول من طبق مفهوم Byte Address بدلا من Bit Address (و يعنى التعامل مع الذاكرة على مستوى البت). [6]المصطلح Code Page يقابل الكلمه صفحة محارف باللغه العربية. [7]يمكنك معرفة كافة هذه الإختلافات من Appendix C بتوثيق Unicode أو بعضها من Wikipedia. [8]يمكنك معرفة تفاصيل أكثر عن هذه المساحات و طبيعة محتواها من Wikipedia أو من توثيق Unicode أو من توثيق ISO. [9]راجع المقالة التى تتحدث عن UTF-8 داخل Wikipedia، أو أقرأ عن هذا الترميز بالتفصيل فى وثيقة من RFC. [10]راجع المقالة التى تتحدث عن UTF-16 داخل Wikipedia، أو أقرأ عن هذا الترميز بالتفصيل فى وثيقة من RFC. [11]يوجد أكثر من ترميز غير المذكورين هنا و لكنهم غير مدعومين من Unicode.
  3. ما هي الكائنات الثابتة والدوال الثابتة

    السطر: Rectangle() = default ;يعنى انك تريد من المترجم ان يقوم بتوليد كود المشيد الإفتراضي بدلا من ان تكتبه بنفسك، وهو يماثل عدم وجود أى مشيد داخل الفئه أو ان تكتب مشيد ذات محتوى فارغ (أى لا يقوم بفعل اى شئ).   هذا الكود يعمل مع مترجمات C++11 فما بعد.       و الله ولي التوفيق
  4. ما هي الكائنات الثابتة والدوال الثابتة

    "الكائنات الثابته" لها اكثر من معني، فقد تكون كائنات معرفة داخل فئه أو داخل دالة و يوجد اختلاف بينهم، أيضا الدوال الثابته هى التى يتم تعريفها داخل الفئه و يتم تحديد انها const و هى لا تقوم بتغيير حالة الكائن التى يتم إستخدامها منه.   الكائنات الثابته داخل الدوال: عند التصريح عنها لابد من وضع قيمة افتراضية لها كالتالي: struct bag{ int value; bag() : value(0) {} bag(int i) : value(i) {}};int main(){ //const int i; // ERROR: incomplete definition const int i2 = 10; // OK const int i3(); // ERROR: it thinks that i3 is a function // that return const int and takes no argument const bag o; // OK: calling default constructor const bag o2(); // ERROR: it thinks that o2 is a function // that return const bag and takes no argument const bag o3(7); // OK: calling overloaded constructor}الكائنات الثابته داخل الفئات: هذه الشرح فيها يطول لأن لها حالات بين نوع مركب و نوع أولي (و حتى النوع الأولي إما مشتق من رقم صحيح أو غير ذلك) و إذا كان تم تعريفه بـ static أو لا، يفضل أن تقرأ فضل يتحدث عن ثوابت الفئات لهذا الأمر.   الدوال الثابته: يتم تعريفها داخل الفئات ليتم الإعلام انها لا تغير من حالة الكائن و تستخدم مع الكائنات العاديه و هى الوحيده التى يمكن استدعائها من كائن معرف بأنه ثابت: #include <iostream>using namespace std;struct bag{ bag() : value(0) {} bag(int i) : value(i) {} void set_value(int i) { value = i; } int get_value() const { return value; } private: int value;};int main(){ bag b(10); cout << "b = " << b.get_value() << endl; b.set_value(15); cout << "b = " << b.get_value() << endl; const bag b2(13); cout << "b2 = " << b2.get_value() << endl; // b2.set_value(17); // ERROR: b2 has type 'const bag' and set_value is not marked const}و الله ولي التوفيق
  5. لغز بسيط

    الكود المكتوب ينتج unspecified behavior و ذلك لأن ترتيب الحصول على نتيجة الدالة inci يحدده المترجم، أنظر هذا المثال.     و الله ولي التوفيق
  6. دالة لتحويل double إلى money string

    هى أحد الإضافات الجديدة للإصدار C++11.     و الله ولي التوفيق
  7. طلب مساعدة في كتابة كود برمجي

    أنظر موضوع تمرين على استخدام القوائم بإستخدام ++C     و الله ولي التوفيق
  8. قراءة شطر من السطر

      أنظر شرح الدالة و المثال موجود فى أخر الشرح     و الله ولي التوفيق
  9. السلام عليكم و رحمة الله   الموضوع هو طلب شرح Segmented Sieve of Eratosthenes، قرأت مواضيع عديده و أكواد كثيرة لها و لكن حتى الأن لا أستطيع فهمها؟!!   إن استطاع أحد أن يضع شرح لها هنــا - مع مثال بسيط إن كان بالإمكان - فجزاه الله خيرا.     و الله ولي التوفيق
  10. إستخدام مصفوفة كجزء من مصفوفة

    لغة C لا تحتوى على مرجع و لنها تحتوى على المؤشرات، لذا لا يمكن.     و الله ولي التوفيق
  11. عنوان الموضوع بالإنجليزية سيعطى المعنى بشكل أفضل : Array view into array.   يمكنك تخيل الأمر كالتالي أنت تقف فى غرفه و هى تحتوى على العديد من الأشياء و فى يديك كاميرا تنظر من خلالها لذا فى أى لحظه ما تراه من خلال الكاميرا هو جزء من الواقع و إذا حدث ان قمت و انت تمسك الكاميرا بتغيير اى شئ فستراه من خلال الكاميرا و ايضا سيتغير داخل الغرفه و بالمثل إن تم تغيير شئ داخل الغرفه فستراه عبر الكاميرا أيضا.   فى الكود التالي: int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};نوع المصفوفة arr هو [int[10 و المطلوب هو وجود المصفوفة arr2 بحيث يكون نوعها [int[5 و أول عنصر بها هو العنصر رقم 3 بالمصفوفة arr - و قيمته 2 - بحيث عند تنفيذ الكود التالي: const int arr2_len = sizeof(arr2)/sizeof(int);for(int i=0; i<arr2_len; ++i) arr2[i] += 5;و طباعة عناصر المصفوفة arr قبل و بعد تنفيذ الكود السابق بإستخدام الكود التالي: cout << "arr[0]=" << arr[0]for(int i=1; i<10; ++i) cout << ", arr[" << 1 << "]=" << arr[i];cout << endl;تكون النتيجة: arr[0]=0, arr[1]=1, arr[2]=2, arr[3]=3, arr[4]=4, arr[5]=5, arr[6]=6, arr[7]=7, arr[8]=8, arr[9]=9arr[0]=0, arr[1]=1, arr[2]=7, arr[3]=8, arr[4]=9, arr[5]=10, arr[6]=11, arr[7]=7, arr[8]=8, arr[9]=9أيضا عند إستخدام الكود التالي: cout << "arr2[0]=" << arr2[0];for(int i=1; i<arr2_len; i++) cout << ", arr2[" << i << "]=" << arr2[i];cout << endl;يتم طباعة: arr2[0]=7, arr2[1]=8, arr2[2]=9, arr2[3]=10, arr2[4]=11يحتاج السؤال إلى معرفة أساسيات اللغه جيدا (المؤشرات و المراجع و المصفوفات) فإن لم تستطع إجابة هذا السؤال على الأقل لنفسك فعلم ان مستواك ضعيف فى أساسيات اللغه أو أنك لم تركز عليها بالقدر الذى كانت تحتاجه.       و الله ولي التوفيق
  12. ما هي HLA ?

    هو Assembler و كان الهدف منه تعليم مبرمجي اللغات عالية المستوى لغة الأسمبلي بشكل مبسط، يمكنك القراءة عنه من هنا.   ملحوظة: إن اردت تعلم الأسمبلي بشكل جيد فقم بتحميل نفس الكتاب - The Art of Assembly Language - نسخة 16 بت، حيث فيه يستخدم كود الأسمبلي فعليا و ليس HLA.       و الله ولي التوفيق
  13. ترتيب بيانات قائمة عادية

    الحل الذى أراه هو بعد ان يتم ملء القائمه، قم بحجز مصفوفه من بنوع *student و قم بالدوران على القائمه وقم بحفظ عنوان كل عنصر بها داخل هذه المصفوفه و من ثم قم بترتيب عناصر المصفوفه و بعد ان تقوم بترتيبهم قم بتحديث العنصر suivant بناءا على الترتيب الموجود المصفوفه و بهذا فقد قمت بترتيب القائمه و لا تنسى تحرير ذاكرة المصفوفه.     و الله ولي التوفيق
  14. إستخدام مصفوفة كجزء من مصفوفة

    عندما كتبت هذا السؤال كنت أعلم ان القليل من سيقوم بالرد عوضا عن الحل لأن مثل هذه الأسئلة قلما تحتاج إليها، و لكن المشكلة هنا ليست فى احتياجك إليها من عدمه و لكن المشكلة تكمن فى ان فهمك الراسخ لبعض الأساسيات أمر هام جدا و هو ما اغلبنا يقوم بتجاوزه او الأسوء ان اغلب الكتب البرمجيه - إن لم يكونوا جميعهم - يتجاوزوا عن شرحهم. فإن كنت درست ++C لفتره طويله فستعرف ما اتكلم عنه من خلال قرائتك للأسطر التالية.   عندما نتكلم عن المصفوفات فأغلب ما تجد نفسك تتعامل معه هو المصفوفات الديناميكية، لأنها فى النهايه مؤشر ذات نوع محدد يمكنك تحويله لمؤشر ذات نوع أخر و التلاعب به كما تشاء، و لكن المصفوفات العاديه - التى توضع فى الـ stack - قليل ما يتم التلاعب بها.   قبل ان اضع الحل لابد ان تفهم كيفية عمله، فى المعتاد عندما تقابل الكود التالي: int* pفأنت تقرأه p هو مؤشر لقيمة أو أكثر من نوع int، و إذا سُئلت عن نوع المتغير p ستقول مؤشر لـ int، التعريف التالي: int p[7];يقرأ p هو مصفوفة من 7 عناصر بنوع int، الصعوبه هنا تكمن فى نوع المتغير p حيث العديد يجيب بأن نوع p هو int و ذلك لأنهم اعتادوا أن النوع دائما يكون تعريفه فى أقصى اليسار من المتغير - مثل المؤشرات و المراجع - و لكن من درس اللغه جيدا سيعرف ان نوع p هو مصفوفة من 7 عناصر بنوع int، و يمكنك كتابة typedef لوصف المصفوفة كالتالي: typedef int array7[7];و عند إستخدامه: array7 p;و هو يماثل نفس تعريف المصفوفة الذى نستخدمه طول الوقت.     لنأت لموضوع تحويل الأنواع، عند إستخدام المؤشرات يمكنك تحويل نوع مؤشر لنوع مؤشر أخر كالتالي: int* a = new int[10];char* p = (char*)a;كما ترى المؤشر p سيسمح لك بالتعامل مع المكان الذى يشير إليه المؤشر a على مستوى البايت[1]، و لكن ماذا سيحدث إذا تحرير و إعادة حجز الذاكره التى يشير إليها المتغير a، حينها المؤشر p أصبح تالف لأن قيمة المؤشر p هى موقع الذاكره الذى تم حجزه أول مره - الموجود بالكود - و ليس موقع المتغير a داخل الذاكره حيث إذا كان p هو موقع a بالذاكرة حينها مهما كانت عنوان الذاكره الموجود بـ a فسيكون نفس العنوان داخل p.   يمكن إستخدام مؤشر لمؤشر لإتمام هذه العملية كالتالي: int* a = new int[10];char** p = (char**)&a;إستخدام مؤشر لمؤشر هو الإسلوب الأمثل فى هذه الحالة، و لكن لازال يعيبه انه يشير لمكان محدد فإذا كان محتوى المؤشر a هو عنوان لمكان أخر فستحتاج لمستوى جديد من المؤشرات. لغة ++C لديها إضافه جميله لهذا الأمر تسمى مرجع، و المرجع يختلف كثيرا عن المؤشرات و توجد بعض الامور داخل اللغه لا يمكن تنفيذها إلا بإستخدام المراجع.   على خلاف المؤشر فالمرجع لا عنوان له، أى أنه لا يحجز مساحه بالذاكره، أنظر الكود التالي: int a = 10;int& b = a;b = 12;cout << boolalpha << (&a == &b) << endl;السبب فى ان المرجع لا عنوان له يعود ان قيمة المرجع النهائية هي قيمة المتغير الغير مرجع الذى يشير له: int a = 10;int& b = a;int& c = b;int& d = c;d = 12;cout << hex << &a << endl;cout << hex << &b << endl;cout << hex << &c << endl;cout << hex << &d << endl;فى هذا المثال سترى ان كل مرجع يشير للمرجع الذى قبله فإذا حدث و أن كان المرجع له عنوان حينها المتغيران c و d لن يشيران لقيمة المتغير a و إنما لسلسلة المراجع التى قبلهم، و لكن هذا سيصبح خاطئ لأنك حينها ستحتاج للأنواع مرجع و مرجع و لمرجع و هكذا، أى اننا اصبح لدينا مسمسى جديد للمؤشرات و لكن بإستخدام المراجع.   لهذا السبب كان المرجع لا عنوان له و بهذا اصبح مجرد مسمى أخر للمتغير الذى له عنوان و يحتوى على قيمه، و لهذا فى المثال السابق المرجع b هو نفسه المتغير a و بالتالي عند إسناد قيمة b إلى c فأنت فعليا تسند قيمة a إلى c و نفس الأمر مع d حيث أصبح هو a.   لتتأكد من ان المرجع لا عنوان له أنظر المثال  التالي: int a = 1;int b = 2;int& c = a;int& d = c;d = 10; // value of a became 10c = b; // c refer to bd = 13;cout << a << endl << b << endl;فى هذا المثال c يشير لـ a و d يشير لـ c، بعدها تم تغيير قيمة d لتصبح 10 و من تسلسل المرجع فهذا يعنى ان قيمة a أصبحت 10، بعدها تم جعل c يشير لـ b و من ثم تم تغيير قيمة d، الأن إذا كان المرجع له عنوان فإن d يشير لـ c و بالتبعيه فإن d يشير لـ b و بهذا عند تغيير قيمة d إلى 13 فإننا نغير قيمة b إلى 13.   عند تشغيل البرنامج ستجد أن قيمة a هى تغيرت دائما و هذا يعنى ان المرجع لا عنوان له.   لأن المرجع لا عنوان له لابد دائما ان يشير لشئ ما، و لهذا عند تعريفه لابد من وضع قيمه له.   هل تذكر المثال الذى استخدمنا فيه مؤشر لمؤشر، أنظر إليه الأن: int* a = new int[10];char*& p = (char*&)a;نوع المتغير p يقرأ من اليمين لليسار ليصبح مرجع لمؤشر من نوع char، لاحظ أيضا ان قيمة المتغير a لابد من ان يتم تحويلها لهذا النوع حتى تستطيع إسناده إلى p.   لنعود للمصفوفات.   عندما نقوم بتعريف مرجع فإننا نكتب النوع يليه علامة & و هذا يعطينا نوع جديد بالإسم مرجع لنوع و هذا يعنى ان المترجم عندما يرى هذه الصيغه - مرجع لنوع - فإنه يعلم انه سيقوم بربط إسم لمتغير موجود، المشكله تظهر عندما تقوم يكتابة الكود التالي: int& p[10];لنقرأ الإسم معا، p هو مصفوفة من 10 عناصر بنوع مرجع لـ int، و لكن أنتظر عناصر المصفوفه لكل منها عنوان بالذاكره فكيف يمكن إنشاء مصفوفه بعناصر كل منها مرجع و لا يوجد لها عنوان و هنا يتوقف المترجم و يظهر رسالة خطأ تشبه التاليه: arrays of references are illegalو لكن p هو متغير من نوع مصفوفه و شانه شان كافة المتغيرات و أريد ان اقوم بتعريف مرجع له فكيف أفعلها؟   لتعرف كيف تقوم بهذا الأمر إسمح لى أن أعطيك مراجعه سريعه فى تعريف المتغيرات، أنظر المثال التالي: int a, b ,c;int &ar = a, &br = b, &cr = c;int *ap, *bp, *cp;int x[10];int (*sum)(int a, int b);أما السطر الأول فيقوم بتعريف ثلاثة متغيرات من نوع int، و السطر الثاني يقوم بتعريف ثلاثة مراجع للمتغيرات التى تم تعريفها بالسطر الأول، السطر الثالث يقوم بتعريف ثلاثة مؤشرات لـ int، السطر الرابع يعرف مصفوفه بالإسم x من عشرة عناصر بالنوع int، السطر الأخير يعرف مؤشر دالة إسمه sum و يأخذ معاملين كلاهما نوعه int.   ما يهمنى هنا تذكريك بالسطر الثاني و الثالث و الأخير حيث الأوليين تم ربط علامة مالرجع و المؤشر بإسم المتغير و ليس بإسم النوع و بالمثل عندما تم تعريف إسم مؤشر الدالة فإن علامة المؤشر لإسم الدالة.   قبل أن تقفذ للإستنتاجات، الكود السابق يمكن كتابته بالشكل التالي: int (a), (b), (c);int (&ar) = a, (&br) = b, (&cr) = c;int (*ap), (*bp), (*cp);int (x)[10];int (x2[10]);int (*sum)(int a, int b);هل بدءت فى شد شعرك بعد!!   بشكل عام كل شئ بعد إسم النوع و إلى نهاية إسم المتغير يطلق عليه declarators - و هو الفصل الثامن فى توثيق اللغه - و حيث انه توجد العديد من أشكال تعريف المتغيرات فإن المترجم أحيانا يختلط عليه الأمر و لا يعرف كيف يربط بين المعاملات المستخدمه مع الإسم او لا يعرف ماذا تقصد بإستخدام لمعامل معين مع إسم معين لذا يتم إستخدام الأقواس لجعل الصيغه التى تستخدمها لا تحتمل أكثر من معني.   هل تذكر لماذا استخدمنا الأقواس مع تعريف مؤشرات الدوال؟ السبب يعود لأن إن لم تستخدم الأقواس لتغليف معامل المؤشر مع الإسم سيتم ربط علامة المؤشر مع النوع و ستعطي مسمى مختلف حيث بدلا من تعريف مؤشر دالة ستقوم بالتصريح عن دالة تعيد مؤشر.   الأن هل عرفت الهدف الذى يستخدم من أجله الأقواس فى تعريف المتغيرات (لا اعتقد انه يوجد كتاب - قراته على الاقل - يتكلم عن هذه النقطه أو بعض مما سبق).   لنعود للمصفوفات مره أخرى: هل تذكر المشكله بهذا الكود: int& p[10];أعتقد أنك تعرف الحل الان: int (&p)[10];لاحظ انك لو ضممت عدد عناصر المصفوفه داخل الأقواس كالتالي: int (&p[10]);فإن هذا التعريف يطابق التعريف الذى يصدر الخطأ لأنه فى هذه الحالة - كما التى تصدر الخطأ - يتم ربط إسم المصفوفه بعدد العناصر قبل الربط على المرجع (يمكنك تخيل العملية أنها تبدأ من إسم المتغير ثم اليمين بالكامل فاليسار و هكذا حتى يتم الإنتهاء من التعريف) و فى حاتنا هذه فيتم قراءة إسم المصفوفه يليها عدد العناصر يليها المرجع و هنا يتم ربطه على العناصر و ليس إسم المصفوفه ثم العنوان، و يقرأ p هو مصفوفه من 10 عناصر مرجعيه بنوع int.   أما التى فيها عدد العناصر خارح الأقواس فيتم قراءة الإسم و اليمين فارغ و اليسار يحتوى على علامة المرجع و بهذا يعلم المترجم ان الإسم p هو مرجع ويخرج من الأوقاس و يقرأ العناصر العشره فيعلم ان الإسم p هو مرجع لمصفوفة من عشر عناصر ثم يقرأ النوع int فيعلم ان p هو مرجع لمصفوفه من عشر عناصر بنوع int   الأن قمنا بربط كافة الأساسيات التى نحتاجها معا و بقي لنا التطبيق فى الإجابه على السؤال الأصلي:   السؤال يحدد أن المصفوفه arr و arr2 يحتلا نفس المساحه من الذاكره، لذا الأمر الإفتراضي الذى لابد ان يتطرق إلى الأذهان هو ان كلا المصفوفتين موجودين داخل union و لكن السؤال يحدد أن المصفوفه arr2 لها عدد عناصر أصغر و تبدأ من العنصر الثاني داخل المصفوفه arr و هذا يعنى اننا سنقوم بعمل إزاحة للمصفوفه arr و من ثم الحصول على مرجع بدءا من هذا العنصر و بعدد العناصر التى نحتاجها.   دعنى افصلها لك خطوه خطوه:   1- سنقوم بعمل إزاحة للمصفوفه arr للموقع المحدد، الإزاحه ليست كما تتوقع و لكن هى فقط الحصول على العنصر الذى نريد أن نجعله أول عنصر فى المصفوفه الجديده: int& item = arr[2];لاحظ ان المرجع item مربوط على العنصر ذات الترتيب الثاني فى المصفوفه arr.   2- سنقوم بتعريف مرجع للمصفوفه arr2: int (&arr2)[5];هذا التعريف غير كامل و لابد من وضع قيمه له حتى يصبح فعال.   3- سنقوم بربط المصفوفه arr2 على العنصر item بعد تحويله لنوع المصفوفه arr2: int (&arr2)[5] = ( int(&)[5] )item;صيغة النوع الذى سيتم التحويل إليه قد تكون غريبه إليك و لكن إن فكرت بها قليلا ستجدها منطقيه حيث انك تقوم بتحويل إلى مرجع لمصفوفه من 5 عناصر بنوع int و هذا ما تعنيه صيغة التحويل.   المثال بالكامل: #include <iostream>using namespace std;int main(){ int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int (&arr2)[5] = (int(&)[5])(arr[2]); cout << "arr[0]=" << arr[0]; for(int i=1; i<10; i++) cout << ", arr[" << i << "]=" << arr[i]; cout << endl; const int arr2_len = sizeof(arr2)/sizeof(int); for(int i=0; i<arr2_len; ++i) arr2[i] += 5; cout << "arr[0]=" << arr[0]; for(int i=1; i<10; i++) cout << ", arr[" << i << "]=" << arr[i]; cout << endl; cout << "arr2[0]=" << arr2[0]; for(int i=1; i<arr2_len; i++) cout << ", arr2[" << i << "]=" << arr2[i]; cout << endl;}الفكره التى طبقناها هنا تسمى بـ array view و التى تسمح لك بالتعامل مع جزء من المصفوفه كانها مصفوفه منفصله، هذه الفكره لها تطبيقات عديده مثل التعامل مع جزء من النص كأنه نص منفصل.       و الله ولي التوفيق     [1] المسمى الصحيح هنا ليس البايت و إنما الوحدة حيث ان مساحة النوع char تساوى 1، و هذا الواحد مهما كان عدد البتات به فيطلق عليه إسم الوحده و مساحة كافة أنواع اللغه تقاس بالنسبه له، فالنوع signed short يستطيع ترميز قيم ضعف التى يستطيع ترميزها النوع signed char و بالتالي فحجم النوع signed short ضعف حجم النوع signed char و حيث ان الأنواع char و signed char و unsigned char كل منهم مساحته 1 وحدة بالتالي مساحة النوع signed short و unsigned short هو 2 وحدة و هى النتيجه التى من المفترض ان يعيدها مترجمك عند إستخدام اى النوعين مع المعامل sizeof.
  15. إستخدام مصفوفة كجزء من مصفوفة

    سأترك الموضوع حتى غدا ثم أضع الحل.     و الله ولي التوفيق
  16. إستخدام مصفوفة كجزء من مصفوفة

    يمكنك تخيل وجود مصفوفتان بنفس موقع الذاكرة و المصفوفة A تتكون من 10 عناصر و المصفوفة B تتكون من 5 عناصر، و المصفوفة B أول عنصر بها موقعه فى الذاكره مموقع العنصر الثاني فى المصفوفة A و بالتالي قيمة العنصر الأول بالمصفوفة B هى قيمة العنصر الثاني بالمصفوفة A و بالتالي تغيير تلك القيمه من اى من المصفوفتين سيؤثر على الأخرى لأنه فى النهاية القيمة موجوده بمكان واحد فى الذاكرة و لكن يتم تعديلها من خلا مصفوفتين.     و الله ولي التوفيق
  17. 1- أغلب الشركات تستخدم MSI Barcode مع منتجاتها، إقرأ المقال جيدا و سيوضح لك العديد من الأمور. 2- بالنسبة لتوليد الأرقام فبإختصار لا توجد وسيلة محدده و يمكنك إستخدام مولد أرقام عشوائية.   إقرأ المقال المشار إليه و ستعلم العديد من التفاصيل.     و الله ولي التوفيق
  18. بعض الأمور تستطيع إنجازها فى الجافا بشكل أيسر و أبسط مما ستكون عليه فى ++C و العكس صحيح، و كما أن لكل مقام مقال فلكل لغة برمجة نمط محدد من البرامج تعمل فيه افضل من غيرها.     و الله ولي التوفيق
  19. إنتهيت من أساسيات السي

    و ما هى الأساسيات التى تعتقد انك انتهيت منها؟ و ما هو مفهومك للإنتهاء هل بالمعرفه و التطبيق مرة واحدة او التجربة فى مشاكل حقيقة و محاولة حلها أكثر من مرة؟   الأساسيات هى قواعد اللغه بالكامل و عندما تقرءها و تطبقها لمرة او اثنان لا يعنى انك انتهيت منها.   إجعل سؤالك أكثر وضوحا حتى نساعدك بأفضل شكل ممكن.     و الله ولي التوفيق
  20. هذه مقارنة بين منصة DotNet و Java، و هذه مقارنة بين لغة #C و Java.     و الله ولي التوفيق
  21. ترميز الحروف

    ملحوظة: كل الأكواد  التالية تهدف للتوضيح و إن اردت إستخدامها داخل برامجك يمكنك إجراء تحسينات كثيرة عليها.   قد يتسائل أحدكم: ما هى الطريقه التى يمكنني بها التحويل بين الـ code-pages بدون إستخدام أى مكتبات خارجية أو المكتبة الإفتراضية التى تأتى مع لغتي؟   الإجابه: بمعرفة أن أى صفحة محارف تحتوى فقط على 256 كود و الـ 128 الأوليين هما لـ ASCII، يمكننا كتابة مصفوفة من 128 عنصر و قيمة كل عنصر يساوى كود Unicode لذلك العنصر، بمعني الحرف 'م' من صفحة محارف 'windows-1526' له الكود 227 و بالتالي داخل مصفوفتنا سيأخذ الكود 99 (227-128) و قيمة ذلك العنصر ستكون قيمة الحرف 'م' داخل Unicode و هو U+0645 (و هذا يجعل نوع هذه المصفوفه Unisgned 16-bit Integer)، و شكلها فى لغة C++/C كالتالي: const unsigned short windows1256[] ={ 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643, 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2};هذه المصفوفة تحتوى على كود UTF-32 للحروف، و حيث أن حروف صفحة المحارف هذه يمكن حفظه داخل 16 بت دون مشاكل فكانت هذه المساحة التى أستخدمتها.   لتحويل محتوى نص من صفحة المحارف windows-1256 ليونيكود كل ما تحتاجه هو الحصول على موقع كود الحرف داخل المصفوفة ثم العودة به: (الكود التالي بفترض ان النص قد يحتوى على حروف ASCII أيضا) unsigned short to_unicode (char c){ unsigned char uc = (unsigned char)c ; if (uc < 128) return uc; return windows1256[uc-128];}الكود السابق يقوم بتحويل حرف بصفحة محارف windows-1256 ليونيكود و يمكنك كتابة حلقو تكرار لإستدعاء الدالة و الحصول على محتوى النص بأكمله داخل ترميز يونيكود.   قبل حفظ قيمة الحرف يمكنك كتابة دوال لتحويل قيمة الحرف من UTF-32 إلى UTF-16 أو UTF-8 كما تريد.   سؤال أخر: ماذا يحدث لو أردت التحويل بين صفحتان محارف مثل windows-1256 و oem720 حيث كلاهما يحتوى على حروف العربية؟ الإجابه: الحل يكون فى كتابتك مصفوفتين كل منهم يحتوى على 128 عنصر، أما الأولي فستكتبها بنفسك، و الأخرى ستقوم بتوليدها تلقائيا: unsigned short oem720[] ={ 0xffff, 0xffff, 0x00E9, 0x00E2, 0xffff, 0x00E0, 0xffff, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0xffff, 0xffff, 0xffff, 0xffff, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0};المصفوفه oem720 تم تحديد محتوياتها كما تم تحديد محتويات المصفوفة windows1256 و يوجد هنا أمر جديد و هو القيمة 0xffff حيث هذه القيمة انا استخدمتها خصيصا لسبيبن: يونيكود تؤكد ان هذا الكود غير مرتبط بحرف و لا يمكن استخدامه داخل سلسلة أكواد. أثناء التحويل إذا وجد هذا الكود فإن عملية التحويل فاشلة لإن المصفوفة oem720 لا تستطيع ترميز كل الحروف الموجوده بالمصفوفه (صفحة المحارف) التى تقوم بالتحويل منها.المصفوفة الثانية التى سنقوم بتوليدها سنعطيها الإسم WinToOem حيث موقع كل عنصر بها هو موقع حرف داخل صفحة المحارف windows-1256 و قيمة ذلك الحرف هى موقع العنصر داخل صفحة محارف oem720، و بالتالي إذا اردنا تحويل نص من صفحة محارف windows1256 إلى oem720 كل ما سنفعله هو تمرير الكود للمصفوفة WinToOem و الناتج سيكون قيمة الحرف داخل صفحة محارف oem720. char WinToOem[128];int find(unsigned short* array, unsigned short value){ for(int i=0; i<128; ++i) { if (array[i] == value) return i; } return -1;}void gen_array(){ for(int i=0; i<128; ++i) { int r = find(oem720, windows1256[i]); if (r == -1) WinToOem[i] = 0; else WinToOem[i] = i + 128; }}كل عنصر بالمصفوفة WinToOem يحتوى على صفر و هذا يعنى انه الحرف لا يوجد له مثيل فى oem720 (تذكر المصفوفة لا تحتوى على أكواد ASCII و الكود صفر لا يتم إستخدامه أبدا داخل اى صفحة محارف ماعدا للحرف NULL و هذا مؤكد) أو كود الحرف داخل oem720.   الإسلوب السابق هو ما اتبعته داخل مكتبة charset مع بعض التعميم لتطبيق الطريقة على العديد من صفحات المحارف.     و الله ولي التوفيق
  22. بخلاف أمر اللغات، البرمجة للغة الدوت نت لا تنتهى بتعلم مبادئ اللغه التى تستخدمها و لكن تنتهى بمعرفتك للـ Framework التى تستخدمها بشكل تام، بالإضافة إلى أن لغة الفيجوال بيسك تحتوى على نفس الإمكانيات الموجوده بالـ #C زادت الأولى عن الأخيره أو نقصت ببعض الإمكانيات للتمييز بينهم.   تعلم لغة البرمجة أمر سهل و لكن إتقانها بإستخدام مكتباتها هو الذى يأخذ الوقت ففكر جيدا لأنك تنتقل من بيئة و لغة إلى لغة أخرى ببيئة أخرى، و دعك من الأقوال التى تقول بتشابه اللغتتان جافا و #C، حيث توجد إختلافات كثيرة بينهم بالإضافة للمكتبات و بيئة العمل، و أضف عليهم الـ Interoperability و طبيعة الملف التنفيذي الناتج و غيرها من الأمور.     و الله ولي التوفيق
  23. عدد الإحتمالات

    أنظر هذا و هذا.     و الله ولي التوفيق
  24. ترميز الحروف

    من قرائتي لم يرد ذكر أى من الدول العربية.     و الله ولي التوفيق
  25. سرعة البديهة . . والبرمجة

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