[MUSIC PLAYING]
ديفيد ج. مالان: حسنًا.
هذه هي دورة CS50 وهذه بداية الأسبوع الثاني.
وسنتذكر أنه على مدار الأسبوعين الماضيين،
كنا نقوم بمرحلة التأسيس.
أولاً بدايةً من لغة سكراتش، لغة البرمجة الرسومية
التي قمنا فيما بعد، تحديدًا الأسبوع الماضي، بترجمتها إلى البرنامج المكافئ NC.
وبالطبع، يوجد الآن بناء جملة على نحو أكبر بكثير.
إنه نص بالكامل لكن الأفكار، كما نتذكر، في الأساس هي ذاتها.
والجانب السلبي هو أن أجهزة الكمبيوتر لا تفهم هذا.
فما اللغة التي تفهمها فقط؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: أصفار وواحدات أو النظام الثنائي.
وبالتالي هناك خطوة ضرورية لنا للوصول من هذه التعليمة البرمجية إلى النظام الثنائي.
وما هو الاسم الذي كان يُطلق على تلك الخطوة أو ذلك البرنامج أو الإجراء؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: أجل، إذن هو التحويل البرمجي.
وبالطبع، تذكرون بما أنكم الآن قد خضتم التجربة
مع هذا الإجراء في الأسبوع الماضي فإنه لإجراء التحويل البرمجي لبرنامج،
يمكنكم استخدام أداة التحويل البرمجي clang الخاصة بلغة C.
يمكنكم فقط قول clang ثم اسم الملف
الذي تريدون تحويله برمجيًا.
وتلك المخرجات بشكلٍ افتراضي تسمى على نحو غريب جدًا باسم برنامج.
Just a dot out.
والتي تشير إلى مُخرَج برنامج التجميع.
علاوةً على ذلك أنه يتم في الحال.
لكن تذكروا أيضًا أنكم تستطيعون تجاوز هذا السلوك الافتراضي.
ويمكنكم في الواقع أن تقولوا، Output "مخرَج" بدلاً من program "برنامج"
ويُسمى، hello بدلاً من just a dot out.
لكن يمكنكم القيام بخطوة أخرى إضافية، ويمكنكم بالفعل استخدام أداة Make.
وأداة Make في حد ذاتها ليست أداة تحويل برمجي، بل إنها أداة بناء مساعدة.
لكن بمصطلح غير المتخصصين، ما الذي تفعله لنا؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: تقوم بتحويله برمجيًا.
وهي في الأساس تكتشف كل وسيطات سطر الأوامر تلك
ذات المظهر التشفيري.
مثل -o "شرطة o" شيء ما، وما إلى ذلك.
لذلك يتم بناء البرنامج تمامًا بالطريقة
التي نريدها دون أن نضطر لتذكر
تلك الطلاسم السحرية كما تبدو.
وبالرغم من أن هذا يعمل فقط على برامج بسيطة مثل هذا.
إلا أنه في الواقع، فربما واجه البعض منكم من ذوي المشكلات الأخيرة
أخطاء في التجميع والتي في الواقع
لم تصادفنا عن قصد في الفصل لأن أداة Make كانت تساعدنا.
في الواقع، بمجرد قيامك بتحسين برنامج ما
ليأخذ بالفعل مدخلات المستخدم باستخدام مكتبة CS50 بتضمين CS50 نقطة H،
فربما يكون البعض منكم قد أدرك أن أداة تحديد الوصول، وبشكل أعمّ أداة Clang،
إذ فجأةً، لم تكن تعرف ما هو get_string.
وبصراحة، ربما لم تكن أداة Clang حتى تعرف ما هي السلسلة.
وذلك لأن هاتين الأداتين هما ميزتان لمكتبة CS50
واللتين يجب عليك تعليمهما لأداة Clang.
ولكن لا يكفيك تعليم أداة Clang كيف تبدوان، من خلال تضمين CS50.h.
يتضح أن هناك خطوة ناقصة تساعدنا أداة Make في حلها
لكن يمكنك أيضًا حلها يدويًا إذا أردت.
وبذلك فأنا أعني هذا، بدلاً من التحويل البرمجي لبرنامج فقط باستخدام Clang،
hello.c.
عندما تريد استخدام مكتبة CS50، تحتاج بالفعل
لإضافة وسيط سطر الأوامر الإضافي هذا.
على وجه التحديد في النهاية، لا يمكن الانتقال في البداية مثل dash-O.
وتشير dash-L إلى الرابط.
وهذه طريقة لإخبار Clang، وبالمناسبة عند التحويل البرمجي للبرنامج الخاص بي،
فيُرجى الربط في مستوى الأصفار والواحدات في CS50 والتي كتبناها نحن طاقم العمل
قبل بضعة أسابيع وقمنا بتثبيتها لك في أداة تحديد الوصول.
إذن فقد حصلتَ على الأصفار والواحدات الخاصة بك ومن ثم
حصلتَ على الأصفار والواحدات الخاصة بنا إذا جاز التعبير.
ويتم نطق dash-LCS50 لربطها معًا.
لذا فأيًا ما كنتَ تحصل نوعًا ما على خطأ مرجعي غير معرّف إلى get_string
أو لم تحصل--
فقد تعذر علينا إجراء تحويل برمجي لبرنامج استخدم للتو أيًا من دوالّ get
من مكتبة CS50.
والاحتمالات هي، ربما قد تم إصلاح هذا التغيير البسيط dash-LCS50.
لكن بالطبع، هذا ليس شيئًا مثيرًا للاهتمام لكي نتذكره، فما بالك
بتذكر كيفية استخدام dash-0 كذلك، عند النقطة التي
يصبح الأمر فيها مملاً حقًا للكتابة.
لذا هنا تأتي، أداة Make مجددًا.
تقوم أداة Make بالتشغيل التلقائي لكل هذا لأجلنا.
وفي الواقع، إذا كنتَ من الآن فصاعدًا ستبدأ في تشغيل أداة Make ثم
تولي مزيدًا من الاهتمام لسطر المخرجات الطويل تمامًا والذي تقوم الأداة بإخراجه،
فسترى فعليًا إشارةً لـ dash-LCS50،
سترى إشارة كذلك إلى dash-LM، والتي تشير إلى الرياضيات.
لذا إذا كنت تستخدم جولة، على سبيل المثال، فربما اكتشفتَ
أن الجولة الثانية أيضًا
لا تعمل خارج الصندوق إلا إذا استخدمت أداة Make نفسها
أو هذا النهج الأكثر دقة.
لذا فكل ما يمكن قوله هو أن التحويل البرمجي ما هو إلا كذبة بيضاء.
مثلاً، نعم لقد قمتَ بالتحويل البرمجي وكنتَ تنتقل من التعليمة البرمجية للمصدر
إلى التعليمة البرمجية للآلة.
ولكن يتضح أنه كان هناك عدد من الخطوات الأخرى التي تحدث
لك والتي سنقوم فقط بوضع بعض التسميات عليها اليوم.
في نهاية اليوم، سنقوم فقط بكسر التجريد.
لذا فإن التحويل البرمجي هو هذا التجريد من التعليمة البرمجية للمصدر إلى التعليمة البرمجية للآلة.
دعونا نقوم فقط نوعًا ما بالتكبير لفترة وجيزة لتقدير
ما يجري هنا على أمل أن يجعل التعليمة البرمجية
التي نقوم بتحويلها برمجيًا أكثر قابلية للفهم.
لذا فالخطوة الأولى من أربعة، والتي تتعلق بتحويل برمجي لبرنامج بالفعل
تُسمى مرحلة المعالجة المسبقة.
لذلك تذكروا أن هذا البرنامج الذي اطّلعنا عليه للتو كان فيه زوج
من التضمينات بأعلى الملف.
وهما يعرفان عامةً باسم توجيهات المعالجة المسبقة.
ليس مصطلحًا مثيرًا للاهتمام بشكل خاص ولكن يتم
ترسيمه بواسطة علامة التجزئة في بداية هذه السطور.
وتلك إشارة إلى Clang أنه يجب معالجة هذه الأشياء أولاً.
أن تتم معالجتها مسبقًا.
المعالجة قبل أي شيء آخر.
وفي الواقع، فإن السبب وراء هذا قد ناقشناه في الأسبوع الماضي، ضمن CS50.h
ما هو، على سبيل المثال؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: على وجه الخصوص، إعلان دوالّ get string.
لذلك توجد بعض سطور التعليمة البرمجية، النموذج الأولي إذا كنتم تذكرون،
الذي يكون هو سطر التعليمة البرمجية الذي يعلّم Clang ما هي المدخلات لـ get_string
وما هي المخرجات.
نوع الإرجاع ونوع الوسيطات، إذا جاز التعبير.
وهكذا عندما تقوم بتضمين CS50.h في أعلى الملف، فما
يحدث عندما تقوم بتشغيل Clang لأول مرة خلال ما يسمى بخطوة المعالجة المسبقة،
هو أن أداة Clang تبحث على القرص الصلب عن الملف المسمى حرفيًا باسم CS50.h.
وهي تمسك بمحتوياتها وتقوم أساسًا بالعثور على هذا السطر واستبداله هنا.
لذا يوجد في مكان ما في CS50.h خط كهذا الأصفر الظاهر هنا
يقول إن get_string، هي دالّة تقوم بإرجاع سلسلة.
كما يأخذ كمُدخَل، سلسلةً سنطلق عليها prompt "مطالبة"،
والتي تسمى وسيطة.
وفي الوقت نفسه، مع تضمين الإدخال/الإخراج القياسي. فما الهدف من تضمين ذلك؟
ما المفترض أن يُعلن عنه بداخل ذلك الملف؟
أجل؟
الجمهور: إنها المدخلات والمخرجات القياسية.
ديفيد ج. مالان: المدخلات والمخرجات القياسية.
وبصورةٍ أكثر تحديدًا، ما هو المثال الموجود هناك؟
أي دالة؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: إذن هي printf.
الدالّة الأخرى التي نستمر باستخدامها.
لذا فضمن io.h القياسي، في مكان ما على القرص الصلب الخاص بأداة تحديد الوصول
يوجد بالمثل سطر من التعليمة البرمجية يبدو بصراحة غامضًا بدرجة أكثر قليلاً
لكننا سنعود لهذا النوع من الأشياء
في الطريق، والذي يقول إن printf هي دالّة.
يحدث رجوع إلى int، لكن بأكثر من ذلك في وقتٍ آخر.
يحدث أخذ تنسيق char*.
لكن أكثر من ذلك في وقتٍ آخر.
في الواقع، هذا هو أحد الأسباب التي تجعلنا نُخفي
هذه التفاصيل في وقت مبكر نظرًا لوجود بناء جملة ما لا يمثل
إلا تشتيتًا في الوقت الراهن.
لكن هذا كل ما يحدث.
تقوم علامة التضمين الحاد فقط بالعثور على المحتويات واستبدالها.
زائد نقطة، نقطة، نقطة، مجموعة من أشياء أخرى في تلك الملفات كذلك.
لذا عندما نقول مرحلة المعالجة المسبقة، فإننا نعني فقط
أن يتم استبدالها حتى لا تضطر إلى النسخ واللصق
لهذا النوع من الأشياء يدويًا بنفسك.
لذا، فإن "التحويل البرمجي" هي كلمة لها في الواقع معنى محدد جيدًا.
فبمجرد إجرائك لمرحلة المعالجة المسبقة، فستبدو التعليمة البرمجية لديك في الأساس كهذه،
دون علمك، ثم تأتي خطوة التحويل البرمجي الفعلية.
وتتحول هذه التعليمة البرمجية هنا إلى هذه التعليمة البرمجية هنا.
يبدو هذا الآن مخيفًا، وهذا شيء نوعًا ما يشبه
كأن تحصل على دورة دراسية مثل CS61 في جامعة هارفارد،
أو، بشكلٍ أعمّ، برمجة الأنظمة، إذا جاز التعبير،
فقد ترى شيئًا مشابهًا لهذا.
هذه هي تعليمات تجميعة x86 64-bit.
والشيء الوحيد المثير للاهتمام هو بشأن هذا الادعاء في الوقت الحالي
بأن تلك التجميعة--
وقد أشرتُ نوعًا ما إلى ذلك من قبل-- هي مُخرَج برنامج التجميع، a.out.
هناك بالفعل علاقة هنا، ولكن خلاصة القول، هذه
هي التعليمات من المستوى الأدنى التي تفهمها فقط وحدة المعالجة المركزية (CPU)،
العقل الموجود داخل جهاز الكمبيوتر لديك.
وحدة المعالجة المركزية الخاصة بك لا تفهم لغة C. وهي لا تفهم Python أو C++
أو Java أو أي لغة قد تكون مألوفة لديك.
إنها تفهم فقط هذا الشيء الذي يبدو غامضًا.
ولكن بصراحة، بمجرد النظر إليها، فقد تكتشف أن البرمجة في هذه الوحدة ربما
ليست بالأمر الممتع.
أعني، يمكن القول، إنها ليست على هذا القدر الممتع للبرمجة في لغة C،
لذلك فهذا يبدو أكثر غموضًا.
ولكن لا مشكلة.
فلُغة C والكثير من اللغات هي مجرد هذه التجريدات
الموجودة بأعلى برامج المستوى الأدنى التي تفهمها وحدات المعالجة المركزية بالفعل
لذا فلا داعي لأن نقلق بشأن هذا الموضوع إلى هذا الحد.
ولكن إذا سلطنا الضوء على بضعة مصطلحات، سترى بعض الأشياء المألوفة هنا.
لذا فالمصطلح الأساسي تتم الإشارة إليه في هذا المعروف باسم التعليمة البرمجية للتجميع.
ترون الإشارة إلى دالتي get string و printf،
لذا فنحن لا نضيّع المعلومات.
إنه يُقدَّم حقًا بلُغة مختلفة، لغة التجميع.
الآن يمكنكم اكتشاف، ربما، من بعض من أسماء هذه التعليمات،
هذا ما يعنيه شعار Intel Inside.
فعندما تتمكن Intel أو أي علامة تجارية من وحدات المعالجة المركزية من فهم التعليمات،
فهذا يعني أشياء مثل الدفع والتحريك والطرح والاتصال.
وهذه كلها دوالّ وأفعال منخفضة المستوى،
إذا جاز التعبير، ولكن في مستوى وحدة المعالجة المركزية.
ولكن لتفاصيل أكثر من ذلك، يمكنكم الحصول على دورات كاملة.
ولكن فقط لكشف النقاب عن هذا اليوم،
فهذه خطوة كانت تحدث لنا بطريقة سحرية دون علم أحد،
بفضل Clang.
إذن التجميع-- الآن وقد حصلتَ على هذه التعليمة البرمجية التي تبدو غامضة والتي لن
نراها مجددًا-- لن تحتاج إلى مُخرَج مجددًا--
فما الذي ستفعله به؟
حسنًا، قلتم سابقًا إن أجهزة الكمبيوتر تفهم فقط الأصفار والواحدات،
إذن فالخطوة الثالثة هي في الواقع تحويل لغة التجميع هذه إلى أصفار وواحدات فعلية
تبدو الآن هكذا.
لذا تحدث خطوة التجميع، دون علمك،
في كل مرة تقوم فيها بتشغيل Clang أو، بدورها، بتشغيل
أداة make، فنحصل على أصفار وواحدات من التعليمة البرمجية للتجميع،
وسنحصل على التعليمة البرمجية للتجميع في C-code لديك.
لكن إليكم الخطوة الرابعة والأخيرة.
تذكروا أننا نحتاج للربط مع الأصفار والواحدات لدى أشخاص آخرين.
إذا كنت تستخدم دالة printf فأنت لم تكتب تلك الدالة.
إنما قام شخصٌ آخر بإنشاء تلك الأصفار والواحدات، وهي الأنماط
التي يفهمها الكمبيوتر.
أنت لم تنشيء get string.
نحن فعلنا، لذا تحتاج للوصول إلى تلك الأصفار والواحدات
حتى يتمكن برنامجك من استخدامها أيضًا.
لذا الربط، في الأساس، يفعل هذا.
إذا كنت قد كتبت برنامجًا-- على سبيل المثال، hello.c--
وحدث وأن استخدم زوجًا من المكتبات الأخرى،
وهي الملفات التي كتبها أشخاص آخرون لتعليمة برمجية مفيدة
لك، مثل cs50.c، والتي تجدها في مكانٍ ما،
وحتى stdio.c، والذي يوجد بالفعل في مكانٍ ما،
أو من الناحية التقنية، فالإدخال/الإخراج القياسي هو كمكتبة كبيرة،
قاموا فيها بوضع دالّة printf في ملف سُمّي خصيصًا printf.c.
ولكن في مكانٍ ما في محرك الأقراص الثابت لأداة تحديد الوصول، في كل أجهزة Mac وأجهزة الكمبيوتر الشخصي،
إذا كانت تدعم التحويل البرمجي، فهي، على سبيل المثال، مثل هذه الملفات.
ولكن كان علينا تحويل هذا إلى أصفار وواحدات، وهذا، وهذا،
ثم نقوم بدمجها بطريقةٍ ما.
لذلك، بالصور، يبدو هذا مثل هذا نوعًا ما.
وهذا كله يحدث تلقائيًا بواسطة Clang.
Hello.c، التعليمة البرمجية التي كتبتها، يتم تحويلها برمجيًا
للتجميعة، والتي يتم تجميعها بعد ذلك إلى أصفار وواحدات، والتي تُسمى باسم التعليمة البرمجية
للآلة أو التعليمة البرمجية للكائن.
Cs50.c-- فعلنا هذا لكم قبل بدء الفصل الدراسي.
تم إنشاء Printf قبل أن يبدأ أحدنا بعقود
مضت ويبدو مثل هذا.
هذه ثلاثة ملفات منفصلة، على الرغم من ذلك، فإن خطوات الربط حرفيًا
تعني، ربط كل هذه الأشياء معًا، وجمع الأصفار
والآحاد من، مثلاً، ثلاثة ملفات منفصلة، على الأقل،
ودمجهم فقط بطريقة تعرفها الآن
وحدة المعالجة المركزية عن كيفيه استخدام ليس فقط تعليماتك البرمجية لكن أيضًا printf وget string
وهكذا.
في الأسبوع الماضي، قدمنا التحويل البرمجي على هيئة عمليات تجريد،
إذا جاز التعبير، وهذا هو كل ما عنيناه حقًا طوال هذا الوقت.
لكن الآن رأينا ماذا يحدث تحت الغطاء،
ويمكننا تحديد أن وحدة المعالجة المركزية والتي تبدو بصورة مادية
مثل هذا، وإن كانت تبدو أصغر في الكمبيوتر المحمول أو أجهزة كمبيوتر سطح المكتب،
تعرف كيف تتعامل مع كل هذا.
أية أسئلة حول هذه الخطوات الأربع--
ما قبل المعالجة، والتحويل البرمجي، والتجميع ، والربط؟
ولكن بشكل عام، الآن، يمكن أن نطلق فقط عليهم تحويل برمجي، كما يفعل معظم الناس.
أية أسئلة؟
أجل.
الجمهور: كيف تعرف وحدة المعالجة المركزية أن هناك [INAUDIBLE]؟
هل هذا [INAUDIBLE]؟
DAVID J. MALAN: ليس في خطوة ما قبل المعالجة،
وبالتالي فإن السؤال هو، كيف يعرف الكمبيوتر
أن printf هي الدالة الوحيدة الموجودة هناك؟
بشكل أساسي، عندما تقوم بالربط في التعليمات البرمجية،
فقط الأصفار والآحاد الضرورية عادةً هي التي ترتبط.
أحيانًا، تحصل على أكثر مما تحتاج إليه بالفعل، إذا كانت مكتبة كبيرة،
لكن هذا جيد، أيضًا.
تلك الأصفار والواحدات لا تستخدمها وحدة المعالجة المركزية أبدًا.
سؤال جيد.
أية أسئلة أخرى؟
لا بأس، جسنًا.
بما أننا نعرف أن هذا ممكن، فلنبدأ
في تصميم طريق العودة الخاص بنا، لأن الجميع هنا
ربما يعرف الآن أنه عند الكتابة بلغة C، والتي
نوعًا ما من الناحية النظرية، يبدو أنها، لا تخلو
من العقبات والمشاكل والأخطاء والغلطات.
لذلك دعونا نقدم بعض التقنيات والأدوات التي يمكنكم من الآن فصاعدًا،
من بداية هذا الأسبوع وما بعده، محاولة استكشاف هذه الأخطاء وإصلاحها بأنفسكم
بدلاً من مجرد محاولة قراءة رسائل الخطأ التي تبدو مشفرة
أو طلب مساعدة شخص آخر.
دعونا نرى ما إذا كان البرنامج يستطيع في الواقع الإجابة عن بعض هذه الأسئلة لكم.
لذا دعوني أمضي قُدمًا وأفعل هذا.
دعوني أمضي قدمًا وأفتح أداة تحديد وصول هنا،
وسأمضي قدمًا وأُنشئ ملفًا جديدًا باسم
buggy0.c والذي سأرتكب فيه، هذه المرة، خطأً عن عمد.
وسأمضي قدمًا وأُنشئ دالة خاصة بي باسم
main، والتي، تعد بمثابة الحالة الافتراضية، مثل النقر على العلم الأخضر.
وسأمضي قدمًا وأقول printf، علامة اقتباس، علامة اقتباس خاتمة،
"Hello world/m."
حسنًا.
يبدو هذا جيدًا جدًا.
سأمضي قدمًا وأحول buggy0 برمجيًا، وأضغط Enter،
وبالطبع، لدي مجموعة من رسائل الخطأ هنا.
دعوني أقوم بتكبيرها.
لحسن الحظ، لدي اثنتان فقط، ولكن تذكروا، يجب عليكم،
دائمًا التمرير لأعلى للبحث في البداية،
لأنه قد يكون هناك تأثير متسلسل مزعج من
الخطأ السابق على الخطأ اللاحق.
إذن، buggy0.c، السطر 5، هي ما يعنيه هذا، الحرف 5، إذن كمثل 5 مسافات بالداخل،
لتعلن ضمنيًا عن دالّة مكتبة printf مع نقطة، نقطة، نقطة.
إذن ستبدؤون في رؤية هذا في كثير من الأحيان إذا قمتم
بهذا الخطأ المعين أو السهو.
الإعلان ضمنيًا عن شيء ما يعني أنك نسيت
أن تخبر Clang بوجود شيء ما.
وربما تعرفون من التجربة، ربما الآن، ما هو الحل.
ما أول خطأ ارتكبتُه هنا؟
الجمهور: [INAUDIBLE].
ديفيد ج. مالان: أجل، لم أقم بتضمين ملف الرأس،
إذا جاز التعبير، للمكتبة.
لا أجد، في أعلى الملف، تضمين stdio.h،
التي يتم فيها تعريف printf.
ولكن دعونا نقول إنكم لم تكونوا متأكدين تمامًا من كيفية الوصول إلى تلك المرحلة،
وكيف يمكننا، فعليًا، الحصول على بعض المساعدة في هذا الأمر؟
اسمحوا لي في الواقع بزيادة حجم النافذة الطرفية الخاصة بي
هنا، وتذكروا أنه قبل دقيقة فقط، قمت بتشغيل makebuggy0،
والذي أسفر عن الأخطاء التي رأيتُها.
من الواضح أنه تم تثبيت أمر في أداة تحديد الوصول
قمنا بكتابته، نحن طاقم العمل، ويسمى help50.
وهذا مجرد برنامج قمنا بكتابته يأخذ أي رسالة خطأ
أخرجتها التعليمة البرمجية لديك أو برنامج ما كإدخال.
فنحن نوعًا ما نبحث عن العبارات والكلمات المألوفة،
تمامًا مثلما يفعل رفيق التدريس في ساعات العمل، وإذا تعرفنا على رسالة خطأ ما،
فسنحاول تقديم، سواء بشكل بياني أو صريح،
نصيحة ما حول كيفية التعامل معها.
لذا إذا مضيت قدمًا وشغّلت هذا الأمر الآن، فلاحظوا أن هناك المزيد من المخرجات بشكل قليل.
أنا أرى بالضبط المخرج نفسه بالأبيض والأخضر والأحمر كما كان من قبل،
لكن في الأسفل يوجد بعض الأصفر، والذي يأتي تحديدًا من help50.
وإذا مضيت قدمًا وقمت بتقريب الصورة على هذا، سوف
ترون أن سطر الإخراج الذي تعرفنا عليه
هو هذا السطر، السطر نفسه الذي قمت حرفيًا بلفت الانتباه
إليه من قبل-- buggy0.c، السطر 5، خطأ، ليعلن ضمنيًا عن دالة المكتبة
printf، وهكذا.
إذن هنا، بدون تمييز الخلفية، لكنها تظل باللون الأصفر،
هي نصيحتنا أو سؤال قد يطرحه عليك رفيق تدريس أو مساعد في دورة تدريبية في ساعات العمل.
حسنًا، هل نسيت تضمين stdio.h الذي يتم الإعلان عن printf
فيه في أعلى ملفك؟
ونحن نأمل، أن تكون أسئلتنا، سواء بشكل بياني أو بخلاف ذلك، صحيحة،
لأن هذا سيجعلكم تحققون المزيد.
لذا دعونا نمضي قدمًا ونجرّب تلك النصيحة.
إذن ضمّنوا stdio.h.
الآن اسمحوا لي بالمضي قدمًا والعودة إلى أسفل هنا.
وإذا كنتم لا تحبون الفوضى، فيمكنكم كتابة "clear،"
أو الضغط على Control+L في النافذة الطرفية لترتيبه باستمرار كما أفعل.
إذا أردت المضي قدمًا الآن وتشغيل makebuggy0، Enter، أخطاء أقل،
أحرزنا تقدمًا، ولكنه ليس الأمر نفسه.
لذا هذه الدالة، ربما، تكون أسهل قليلاً.
قراءة السطر، ما هو سطر التعليمة البرمجية الذي به أخطاء هنا؟
الجمهور: نسيت الفاصلة المنقوطة.
ديفيد ج. مالان: أجل، من الواضح أن، الخطأ ما زال في السطر 5،
لكن لسبب آخر.
يبدو أنني نسيت فاصلة منقوطة.
ولكن يمكن أن أسأل بالمثل help50 للمساعدة في ذلك
ونأمل أن يكتشف خطئي.
لذا يجب أن يبدأ هذا، أيضًا، في أن يكون حدسكم الأول.
إذا لم تفهموا من الوهلة الأولى حقًا
ماذا تفعل رسالة الخطأ، حتى ولو قمتم
بالتمرير إلى أول رسالة، كمثل طلب الحصول حرفيًا على مساعدة من هذا البرنامج
بإعادة تشغيل الأمر نفسه تحديدًا الذي قمت للتو
بتشغيله، لكن ابدأه بـ help50 ومسافة،
وسيقوم هذا بتشغيل help50 لك.
هل هناك أسئلة حول هذه العملية؟
حسنًا، دعونا نلقي نظرة على برنامج آخر،
على سبيل المثال، فذلك في، هذه المرة، به خطأ آخر مضمّن فيه.
لذا ماذا عن-- اسمحوا لي بالمضي قدمًا وإعداد برنامج سريع هنا.
سأسمي هذا buggy2.c للتناسق مع بعض النماذج
التي لدينا على الإنترنت لكم في وقت لاحق.
وفي هذا المثال، سأمضي قدمًا وأكتب الشيء الصحيح
أولاً، stdio.h، ثم سيكون لدي int (main) void، والذي
سيجعل برنامجي بالكامل يبدأ التشغيل.
وبعد ذلك سيكون لدي تكرار حلقي، وسأذكر--
[CLEARS THROAT] معذرةً-- ماريو أو برنامج ما آخر،
ربما قد تكون قمت بشيء مثل int i get 0، حيث i أقل من أو يساوي--
دعونا نقوم بذلك 10 مرات، ثم i++.
وكل ما أريد القيام به في هذا البرنامج هو طباعة قيمة i، مثلما يمكنني القيام بها،
باستخدام العنصر النائب %i-- إذن برنامج بسيط.
فقط أريده أن يعد من 0 إلى 10.
لذا دعونا نمضي قدمًا ونشغّل buggy2، أو بالأحرى، فأنا أرغب في--
دعونا لا نقوم بالطباعة--
بالترجيع.
دعونا نمضي قدمًا ونطبع فقط رمز علامة التجزئة
ولا نقوم بإفساد الحل بهذه الطريقة.
إذن هنا، أنا أمضي قدمًا وأطبع buggy2.
هدفي الآن هو أنني سأحدد طباعة 10 علامات تجزئة فقط، بمعدل رمز واحد في السطر،
وهو ما أريد القيام به هنا.
والآن سأمضي قدمًا وأشغّل ./buggy2، على أمل، أن أرى،
10 علامات تجزئة.
وأنا أفسدت هذا قليلاً نوعًا ما، لكن ماذا أرى بدلاً من ذلك؟
أجل، أعتقد أنني أرى أكثر مما أتوقع.
ويمكننا نوعًا ما القيام بالتكبير هنا والتحقق مرة أخرى، إذن 1، 2، 3، 4، 5، 6، 7،
8، 9، 10، أوه، 11.
11.
الآن قد تشير عيون بعضكم بالفعل إلى الحل الذي ينبغي أن يكون،
لكن دعونا فقط نقول إن هذا غير واضح.
وإذا كان بالفعل غير واضح، وذلك أفضل، فكيف يمكنك
التعامل مع تشخيص نوع المشكلة هذه، فقط ما لم
تتواصل مع أحد وتطلب منه المساعدة.
ليست هذه المشكلة التي يمكن لـ help50 مساعدتك فيها،
لأنها ليست رسالة خطأ.
برنامجك يعمل.
إنه فقط لا يقوم بإخراج ما أردت أن يخرجه،
لكنه ليس رسالة خطأ من المحول البرمجي الذي يمكن لـ help50 أن يساعده فيها.
إذن أن تريد نوعًا ما مراقبة ما يقوم به البرنامج،
وتريد فهم، لماذا يطبع 11 عندما تقوم بالفعل
بإعداد هذا من 0 إلى 10؟
حسنًا، إحدى التقنيات الأكثر شيوعًا في لغة C أو أي لغة،
بصراحة، هو استخدام printf فقط لأغراض أخرى- أغراض تشخيصية.
على سبيل المثال، لا يوجد الكثير من الأشياء في هذا البرنامج،
لكن قد أزعم أنه من المهم لي معرفة،
برنامجي وبالتالي فهمه، فقط عن طريق،
دعونا نطبع قيمة i هذه في كل تكرار،
بتنفيذ سطر من التعليمة البرمجية التي قمتُ بها سابقًا،
وقول شيء حرفيًا مثل i تساوي %i.
سأقوم بإزالة هذا نهائيًا، لأنه
سيجعل برنامجي يبدو سخيفًا بعض الشيء،
لكنه سيساعدني في فهم ماذا يحدث.
اسمحوا لي بالمضي قدمًا وإعادة التحويل البرمجي لـ buggy2, ./bugg2، وهذه المرة،
أرى الكثير جدًا من المخرجات.
ولكن إذا قمت بالتكبير، الآن نوعًا ما--
الآن الكمبيوتر في الأساس يساعدني على فهم ماذا يحدث.
عندما تكون i 0، ها هو واحد منهم.
عندما تكون i 1، ها هو واحد آخر.
I تكون 2، 3، 4، 5، 6، 7، 8، 9، وهذا يبدو جيدًا.
ولكن إذا انتقلنا أبعد قليلاً، تشعر أن الأمر مُشكل قليلاً
أن i يمكن أن تكون 10 أيضًا.
فما هو الخطأ منطقيًا في هذا البرنامج؟
الجمهور: [INAUDIBLE].
ديفيد ج. مالان: أجل.
أنا أستخدم أقل من أو يساوي، لأنني نوعًَا ما أخلط بين النمط.
يميل المبرمجون لبدء العد من الصفر،
على ما يبدو، ولكن أريد أن أفعل هذا 10 مرات، وفي العالم البشري،
إذا كنت أريد أن أفعل شيئًا 10 مرات، يمكنني العد إلى 10 وتضمينها.
لكنك لا يمكن أن تحصل عليها بكلا الطريقتيتن.
لا يمكنك البدء من الصفر والانتهاء في 10 إذا كنت
تريد أن تفعل شيئًا بالضبط 10 مرات.
لذا فإن هناك احتمالين هنا.
كيف يمكننا إصلاح هذا؟
نعم، يمكننا بالتأكيد تغييره إلى أقل من.
ما هو النهج الصحيح الآخر؟
نعم، قد نتمكن من ترك هذا بمفرده ونبدأ فقط بالعد الآن من واحد،
وإذا كنت لا تطبع في الواقع القيم في برنامجك الفعلي،
قد يكون ذلك معقولاً تمامًا، أيضًا.
إنه ليس تقليديًا فقط.
يحصل على الراحة من خلال العد، بسرعةٍ،من الصفر، لأن هذا فقط
ما يفعله معظم الناس في هذه الأيام.
لكن التقنية هنا هي مجرد استخدام printf.
مثل، في حالة الشك، استخدم حرفيًا printf في هذا السطر، في هذا السطر،
في هذا السطر.
في أي مكان قد يحدث شيء مثير للاهتمام في برنامجك،
فقط استخدمه لطباعة السلاسل الموجودة في المتغيرات الخاصة بك،
اطبع الأعداد الصحيحة الموجودة في المتغيرات الخاصة بك، أو أي شيءٍ آخر.
ويسمح لك نوعًا ما برؤية، إذا جاز التعبير،
ماذا يحدث داخل البرنامج، printf.
أداة واحدة أخيرة-- لكنها ليست شائعة، عند كتابة التعليمات البرمجية،
ربما تحصل على شيءٍ سيئ في وقت مبكر، وخاصةً عندما لا تكون
على دراية تامة بالأنماط.
على سبيل المثال، إذا مضيت قدمًا وفعلت ذلك
عن طريق حذف مجموعة كاملة من المسافات، حتى بعد إصلاح هذا الخطأ
بالانتقال من صفر إلى 10، هل يُعد هذا البرنامج صحيحًا الآن،
إذا كان الهدف هو طباعة 10 رموز شباك؟
أجل، لقد سمعت نعم.
لماذا يُعد صحيحًا؟
بأي منطق؟
نعم، بالضبط.
لا يزال يعمل.
إنه يطبع رموز الشباك العشرة، واحد في كل سطر،
لكنه كُتب بطريقة ضعيفة في ما يخص الأسلوب.
لذلك أذكر أننا نميل إلى التقييم، والعالم
يميل إلى التفكير في التعليمات البرمجية بثلاثة طرق على الأقل.
الأولى، الصواب-- هل يفعل ما يتوجب عليه فعله،
مثل طباعة 10 رموز شباك؟
ونعم، إنه يفعل ذلك، لأن كل ما فعلته كان حذف المسافات.
لم أغير في الواقع التعليمات البرمجية أو أكسرها، بعد ذلك الإصلاح.
الثانية هي التصميم، ما مدى كون هذه التعليمات البرمجية مدروسة، ومكتوبة بصورةٍ جيدة؟
وبصراحة، إن كتابة هذا أمر صعب نوعًا ما من نواح كثيرة جدا،
لأنها أسطر قليلة جدًا.
ولكن سترى مع مرور الوقت، مع نمو برامجك،
أن زملاء التدريس والموظفون يمكنهم أن يقدموا لك الملاحظات
حول تصميم التعليمات البرمجية الخاصة بك.
لكن يُعد الأسلوب سهلاً نسبيًا.
وقد قمت بتدريسه في الغالب بضرب الأمثلة، إذا صح التعبير،
لأنني كنت منهجيًا جدًا في اتباع التعليمات البرمجية الخاصة بي
والتأكد من أن كل شيء يبدو جيدًا جدًا، أو على الأقل جيد
للعين المدربة.
لكن هذه، دعونا فقط نقول، إنها ليست جيدة.
مثل، محاذاة كل شيء إلى اليسار، هو أمر صحيح،
لكنه يبدو رديئًا في الأسلوب.
وماذا ستكون الحجة لعدم كتابة تعليمات برمجية
مثل هذه، وبدلاً من ذلك، كتابة تعليمات برمجية بالطريقة
التي قمت بها منذ لحظة، وإن كان بعد إصلاح الخطأ؟
نعم.
الجمهور: ستساعدك في تحديد كل روتين فرعي
ينتقل من خلال الشيء، لذا تعلم أن هذا القسم هنا.
ديفيد ج. مالان: أجل.
الجمهور: [INAUDIBLE] التالي، حتى تعرف مكان كل شيء.
ديفيد ج. مالان: بالضبط.
دعوني ألخّص هذا.
إنها تسمح لكم برؤية، بطريقة بصرية أكثر، ما الذي
يفعله الروتين الفرعي الفردي أو كتل التعليمات البرمجية
المرتبطة ببعضها البعض؟
برنامج سكراتش مليء بالألوان، ويحتوى على أشكال، مثل شكل العناق
والذي تقوم به الكثير من كتل التعليمات البرمجية،
بالتوضيح بصريًا إلى المبرمج أن هذه الكتلة تشمل الآخرين،
وبالتالي، أن كتلة repeat أو كتلة forever
تفعل هذه الأشياء مرارًا وتكرارًا.
هذه هي القاعدة التي تعمل بها هذه الأقواس المتعرجة، والمسافات البادئة
في هذا وفي سياقات أخرى فإنها فقط تساعد في
أن يصبح أكثر وضوحًا للمبرمج ماذا بداخل ماذا
وماذا يحدث أين.
لذا هذا أفضل في الكتابة، لأنه
يمكنك رؤية أن التعليمات البرمجية داخل main هي كل شيء موجود هنا.
التعليمات البرمجية الموجودة داخل التكرار الحلقي for هي كل شيء موجود هنا.
لذا إنه فقط لنا كقارئين بشريين، وزملاء التدريس
في حالة الدورة التدريبية، أو الزملاء في حالة العالم الحقيقي.
لكن لنفترض أنك ترى أن هذه الأنماط عسيرة القراءة في البداية.
هذا، أيضًا، جيد.
لدى CS50 على موقعها على شبكة الإنترنت ما نسميه دليل الأسلوب.
إنه مجرد ملخص عما يجب أن تكون عليه التعليمات البرمجية الخاصة بك
عند استخدام ميزات معينة من C-- التكرار الحلقي،
الشروط، والمتغيرات، والدوال، وما إلى ذلك.
وهو مرتبط بموقع الدورة الإلكتروني.
لكن هناك أيضًا أداة يمكنك استخدامها عند
كتابة التعليمات البرمجية التي ستساعدك في تنظيفها وجعلها متسقة،
ليس فقط من أجل جعلها تتماشى مع دليل الأسلوب،
ولكن فقط لجعل التعليمات البرمجية الخاصة بك أكثر قابلية للقراءة.
على سبيل المثال، إذا مضيت قدمًا وقمت بتشغيل أمر يسمى
style50 على هذا البرنامج، buggy2.c، ثم ضغطت على Enter،
فسأرى بعض المخرجات المليئة بالألوان.
أرى التعليمات البرمجية الخاصة بي بالأبيض، ثم أرى مسافات خضراء، في
الأماكن التي كان يتعين علي وضع مسافات بادئة فيها، مسافات خضراء
تشجعني نوعًا ما لوضع مسافة، مسافة، مسافة، مسافة هنا.
ضع مسافة، مسافة، مسافة، مسافة هنا.
ضع ثمانِ مسافات هنا، وأربع مسافات هنا، وما إلى ذلك،
وهذا يذكرني بأنني يجب أن أضيف تعليقات إيضًا.
هذا برنامج قصير-- لا يحتاج بالضرورة
إلى الكثير من التعليقات لشرح ماذا يحدث.
لكن واحد فقط //، مثل ما رأيناه الأسبوع الماضي للشرح،
ربما في أعلى الملف أو أعلى كتلة التعليمات البرمجية،
يمكن أن يجعل style50 سعيدًا أيضًا.
لذا دعونا نفعل ذلك.
دعوني أمضي قدمًا وآخذ نصيحته وأضع مسافة قبلها باستخدام مفتاح Tab،
هذه باستخدام مفتاح Tab، وهذه باستخدام مفتاح Tab، وهذه باستخدام مفتاح Tab، ومجددًا مرة أخرى.
وستلاحظ ذلك على لوحة المفاتيح الخاصة بك، حتى لو كنت تضغط على مفتاح Tab،
إنه في الواقع يحوله لك، لما هو شائع، أربع مسافات،
حتى لا يجب عليك الضغط على مفتاح المسافة لأربع مرات.
فقط اعتد على استخدام Tab.
ودعوني أمضي قدمًا وأكتب تعليقًا هنا.
"اطبع 10 رموز شباك."
بهذه الطريقة، لا يتعين على زملائي، وزملاء التدريس، وعليّ في أسبوع
قراءة التعليمات البرمجية الخاصة بي مجددًا واكتشاف ما تفعله.
يمكنني قراءة التعليقات بمفردي لكل //.
إذا قمت بتشغيل style50 مجددًا، الآن يبدو جيدًا.
إنها تتفق مع دليل الأسلوب، و هي مكتوبة بشكل جميل،
إذًا سيصبح مطبوع بشكلٍ جميل مصطلحًا فنيًا في البرمجة
عندما تبدو التعليمات البرمجية الخاصة بك جيدة وليست فقط صحيحة.
أية أسئلة أخرى؟
نعم.
الجمهور: حاولت استخدام [INAUDIBLE] هذا الأسبوع الماضي
وقال إنني أحتاج برنامجًا جديدًا.
ديفيد ج. مالان: هذا--
لم يكن ممكّنًا للأسبوع الأول من الصف الدراسي.
تم تمكينه من الآن فصاعدًا.
أي أسئلة أخرى؟
لا.
حسنًا، إذًا فقط للتخليص، هناك الآن ثلاث أدوات لتحصل عليها من مجموعة الأدوات
الشهيرة وهي help50 ويستخدم في أي وقت تشاهد رسالة خطأ لا تفهمها،
سواء كان ذلك مع make أو Clang، أو ربما، شيء آخر.
Printf-- عندما يكون لديك برنامج منطقي--
خطأ في البرنامج الخاص بك، حيث لا يعمل فقط بالطريقة التي يجب أن يعمل بها
أو بالطريقة التي يخبرك بها كيفية حل المشكلة، ثم style50
عندما تريد التأكد أن، هل تبدو التعليمات البرمجية الخاصة بي صحيحة من حيث الأسلوب،
وهل يمكن قراءتها قدر الإمكان؟
وبصراحة، ستعثر علينا في ساعات العمل وسنقوم
غالبًا بتشجيعك، مهلاً، قبل أن نجيب على هذا السؤال،
هل يمكنك من فضلك تشغيل style50 على التعليمات البرمجية الخاصة بك؟
هل يمكنك تنظيف التعليمات البرمجية الخاصة بك، لأنها تجعل حياتنا، أيضًا،
كالأشخاص الآخرين أسهل بكثير عندما نفهم ماذا
يحدث دون الاضطرار إلى الاكتشاف بصريًا أين تصطف الأقواس
والأقواس المتعرجة.
ولهذا يجب عليكم التمسك بهذه العادة، لأنها
ستوفر لكم الوقت من إضاعته في تحليل الأشياء بصريًا بأنفسكم.
حسنًا.
لذا لا يوجد فقط وحدات معالجة مركزية في أجهزة الكمبيوتر.
وحدات المعالجة المركزية هي العقول، وحدة المعالجة المركزية،
ولهذا نظل نؤكد على التعليمات التي تفهمها أجهزة الكمبيوتر.
وهناك أيضًا هذا، ما رأيناه المرة الماضية، أيضًا.
وهذا مثال على أي نوع من الأجهزة؟
الجمهور: رام.
ديفيد ج. مالان: رام، أو ذاكرة الوصول العشوائي.
هذا هو نوع الذاكرة الذي تحتويه أجهزة الكمبيوتر المحمولة وأجهزة سطح المكتب والخوادم
والذي يستخدم في أي وقت تقوم بتشغيل برنامج أو فتح ملف.
هناك نوع آخر من الذاكرة يسمى محركات الأقراص الثابتة أو محركات الأقراص ذات الحالة الصلبة،
والتي ربما تكون على دراية به كمستهلك،
وهذا هو المكان الذي يتم فيه تخزين ملفاتك بشكلٍ دائم.
يمكن أن تنتهي بطاريتك.
يمكنك سحب القابس من الكمبيوتر المحمول أو سطح المكتب،
وتكون أي ملفات محفوظة على محرك أقراص صلب ثابتة بصورةٍ دائمة.
إنهم يبقون هناك بسبب التقنية
المستخدمة لتنفيذ ذلك.
لكن ذاكرة الوصول العشوائي سريعة الزوال بصورةٍ أكبر.
يتم تشغيل ذاكرة الوصول العشوائي فقط عن طريق الكهرباء.
يتم استخدامها فقط عند تشغيل الطاقة أو عندما تكون البطارية مشحونة،
وهي المكان الذي تُخزن فيه ملفاتك وبرامجك بفعالية عندما
تقوم بالنقر المزدوج عليهم وفتحهم.
لذا عندما تقوم بالنقر المزدوج على شيء مثل برنامج Microsoft Word،
يتم نسخه من القرص الصلب ذي المدى الطويل إلى هذا النوع من الذاكرة،
لأن هذا النوع من الذاكرة، مع أنه أصغر من حيث السعة--
ليس لديك الكثير من وحدات البايت فيه--
لكنه أسرع بصورةٍ كبيرة جدًا.
بالمثل، عند فتح مستند، أو الانتقال إلى صفحة ويب،
محتوى الملف الذي تشاهده يُخزن في هذا النوع من الأجهزة،
لأنه على الرغم من أنك لا تملك الكثير من وحدات البايت فيه،
لكنه فقط أسرع بصورةٍ كبيرة جدًا.
وهذا سيكون موضوعيًا في علوم الكمبيوتر وفي الأجهزة.
أنت نوعًا ما لديك الكثير من الأشياء البطيئة والرخيصة،
مثل مساحة القرص الثابت، من الناحية النسبية، ولديك أقل قليلاً
من الأشياء الأكثر تكلفة ولكن أسرع مثل ذاكرة الوصول العشوائي.
ولديك وحدة معالجة مركزية واحدة فقط، عادةً، وهي الشيء السريع حقًا
والذي يمكنه القيام بمليارات الأشياء في الثانية.
ولكنها أيضا أكثر تكلفة.
ولذا يوجد أربعة رقائق مرئية على هذا الشيء، إذا صح التعبير.
ولن ندخل في التفاصيل حول كيفية عمل هذه الأشياء، ولكن دعونا فقط
نقوم بتكبير هذه الرقاقة السوداء هنا و نركز عليها
كممثله لبعض المقدار من الذاكرة.
ربما تكون واحد ميغا بايت، مليون بايت.
ربما حتى واحد جيجا بايت هذه الأيام، مليار بايت.
ولكن هذا يعني أن هذه الشريحة يمكن اعتبارها مجرد
مجموعة من وحدات البايت.
هذا ليس معيارًا.
لديك الكثير من وحدات البايت أكثر من هذه، ولكن دعوني
أقترح أن تفكروا فقط في كل واحد من هذه المربعات
هنا كممثل لبايت واحد.
لذا فالبايت الأول من الذاكرة الذي يمكنني الوصول إليه هو هنا.
التالي هو هنا، وهكذا.
وحقيقة أنهم يلتفون هو مجرد تصوير فني.
يمكنك التفكير بهذه الأشياء افتراضيًا فقط على أنها
تنتقل من اليسار إلى اليمين، وليس في أي نوع من الشبكات، ولكن ماديًا، يبدو الأمر كذلك.
لذلك عندما تقوم بإنشاء متغير بالفعل في برنامج مثل C،
فأنت تحتاج إلى char.
يميل char إلى أن يكون بايت واحد أو 8 وحدات من البت،
وهذا يعني أنه عندما يكون لديك متغير من نوع char في برنامج بلغة C،
يذهب حرفيًا، بصورة مادية إلى واحدة من هذه المربعات،
داخل ذاكرة الوصول العشوائي للكمبيوتر الخاص بك.
على سبيل المثال، قد يأخذ منا كل هذه المسافة في أعلى اليسار.
إذا كان لديك نوع أكبر من البيانات، مثلاً
لديك عدد صحيح، والذي يميل إلى أن يكون أربع وحدات بايت أو 32 بت،
قد تحتاج إلى أكثر من مربع، إذًا قد يمنحك الكمبيوتر إمكانية الوصول إلى
إلى أربعة مربعات بدلاً من ذلك.
ولديك 32 بت تغطي تلك المنطقة من الذاكرة.
لكن بصراحة، اخترت تلك المربعات بشكل تعسفي.
كان يمكن أن يكونوا في أي مكان في تلك الشريحة أو في أي من الشرائح الأخرى.
الأمر يعود للكمبيوتر ليتذكر مكانهم لك.
أنت لست بحاجة لتذكر ذلك، في حد ذاته.
لكن إذا فكرنا في هذه الشبكة، يتضح أن
هذا في الواقع قيّم جدًا أن لدينا أجزاء من الذاكرة--
وحدات من البايت، إذا صح التعبير--
متصلين على التوالي مع بعضهم البعض.
في واقع الأمر، هناك كلمة لهذه التقنية.
وهي الذاكرة المتجاورة--
متصلين على التوالي مع بعضهم البعض.
وبصفة عامة، في البرمجة، يُشار إلى هذا بمصفوفة.
قد تتذكرون من برنامج Scratch، إذا كنتم تستخدمون هذه الميزة،
إنها في الواقع لديها أشياء تسمى قوائم، والتي
هي عبارة بالضبط عن-- قوائم قيم، قوائم كلمات، قوائم سلاسل.
المصفوفة هي مجرد أجزاء متجاورة من الذاكرة، حتى
يمكنك تخزين شيء هنا، شيء هنا، شيء هنا،
شيء هنا، وهكذا.
لذا يتضح أن المصفوفة، هذا الشيء الأساسي البسيط الرائع
هو في الواقع قوي بشكل لا يصدق.
مجرد القدرة على تخزين أشياء في ذاكرة الكمبيوتر
متصلين على التوالي مع بعضهم البعض يتيح العديد من الاحتمالات، كلا التصميمين،
مثل كيف يمكنني كتابة التعليمات البرمجية، وأيضًا مدى السرعة التي يمكنني بها تشغيل التعليمات البرمجية.
لذلك اسمحوا لي بالمضي قدمًا وإعطاء مثال على ذلك.
اسمحوا لي بالمضي قدمًا وفتح، على سبيل المثال، ملف جديد في sandbox،
وسنطلق عليه score0.
لذلك اسمحوا لي بالمضي قدما وإغلاق هذا، وإنشاء ملف جديد يُسمى scores0.c.
وفي هذا الملف، دعونا نمضي قدمًا ونكتب برنامجًا بسيطًا نسبيًا.
اسمحوا لي بالمضي قدمًا، كالمعتاد، وإعطاء نفسي إمكانية وصول
إلى بعض الدوال المفيدة-- cs50.h وstdio.h.
وليس هناك حاجة لنسخ كل هذا في الأسفل حرفيًا، إذا كنت لا تحب ذلك.
كل شيءٍ بالفعل على الموقع الإلكتروني للدورة.
دعوني أبدأ برنامجي كالعادة مع int main void.
ثم اسمحوا لي بكتابة برنامج، كما يشير اسم هذا البرنامج،
مثل، أن يطلب من المستخدم ثلاث درجات على مجموعات المشكلة الأخيرة،
أو مسابقات، أيًا كان، ثم نوعًا ما يُنشيء مخططًا بسيطًا جدًا منهم،
مخطط شريطي مثلاً ليساعدني على تصور مدى جودة
أو رداءة أدائي في شيءٍ ما.
إذا كنت أرغب في الحصول على عدد صحيح، لا مفاجأة،
يمكننا استخدام دالة int، ويمكنني فقط
أن أطلب من المستخدم الحصول على أول درجة له.
ولكن ربما يجب أن أفعل شيئًا بهذه النتيجة،
وعلى الجانب الأيسر من هذا، ما الذي أضعه عادةً؟
نعم.
إذًا int--بالتأكيد، النتيجة 1 تساوي هذا، ثم الفاصلة المنقوطة.
قد لا يكون لديكم العديد من المناسبات لاستخدام ints فقط حتى الآن،
لكن get int موجود في مكتبة cs50.
هذا هو ما يسمى المُحث الذي يراه الشخص
واسمحوا لي في الواقع بإصلاح المسافة الخاصة بي، لأنني
أريد أن يرى الشخص المسافة بعد النقطتين.
لكن هذا مجرد تفصيل جمالي.
ثم عندما أعيد إلى هذه القيمة، قيمة إرجاعها--
تماما مثلما، في الأسبوع الماضي، سلمني آرون قطعة من الورق،
فـ get int أيضًا سلمني قطعة افتراضية من الورق وفيها رقم
والتي سأخزنها في متغير يُسمى Score 1.
والآن فقط لنكون واضحين، ما حدث فعليًا هو هذا.
في اللحظة التي تقوم فيها بإنشاء متغير من نوع int، وهو أربع وحدات بايت،
حرفيًا، هذا هو ما يفعله Clang أو، بشكل عام،
الكمبيوتر من أجلك.
يتم تخزين int الذي كتبه الإنسان حرفيًا
في أربع وحدات بايت متجاورة متصلة على التوالي، ربما هنا، ربما هنا،
لكن معًا.
هذا كل ما يحدث عندما في الواقع تستخدم لغة C.
لذلك اسمحوا لي بالعودة إلى التعليمات البرمجية الخاصة بي هنا، وأنا الآن
أريد أن-- ليس من المثير كتابة درجة واحدة.
لذا دعوني أمضي قُدمًا وأكتب واحدة أخرى.
إذًا int Score 2، get int، get int، وسأطلب من المستخدم score 2،
فاصلة منقوطة، ثم دعونا نحصل على واحدة أخرى Score 3، get int، ثم نسميها Score 3،
فاصلة منقوطة.
حسنًا، اسمحوا لي الآن بالمضي قدمًا والقيام بتوليد شريط،
مثل المخطط الشريطي لهذا.
سأستخدم ما سندعوه فن ASCII.
ASCII، بالطبع، هو مجرد نص، تذكروا--
نص بسيط جدًا في الكمبيوتر.
ويمكنني أن أقوم بتصميم مخطط شريطي بسيط جدًا فقط عن طريق طباعة
مجموعة من رموز الشباك مثلاً أفقيًا، لذلك سيمثل الشريط القصير
رقمًا صغيرًا، وسيمثل الشريط الطويل رقمًا كبيرًا.
لذا دعوني أمضي قدمًا وأقول للمستخدم، حسنًا، ها هو Score 1 الخاص بك.
سأمضي قدمًا، ثم، أقول، for int i get 0.
I أقل من Score 1, i++.
والآن إذا قمت بالتمرير لأسفل وأعطيت نفسي مساحة هنا،
دعوني أمضي قدمًا وأنفذ فقط طباعةٍ بسيطة.
امضِ قدمًا واطبع رمز شباك، ثم عندما تنتهي من هذا،
اطبع سطرًا جديدًا في نهاية التكرار الحلقي هذا.
دعونا فقط نتوقف لثانية هنا.
فقط للتلخيص، لقد سألت الأشخاص عن ثلاث نتائج.
أنا أفعل شيئًا ما مع واحد منهم فقط في الوقت الحالي، لذلك في الواقع،
فقط كفحص سريع، دعوني أحذف هؤلاء لكي لا أمضي قدمًا بنفسي.
دعوني أقوم make score 0.
سأعقد أصابعي.
حسنًا، لا أخطاء.
الآن اسمحوا لي بالمضي قدمًا وكتابة ./score0، وماذا كانت نتيجتك الأولى في pset
هذا العام من أصل 100؟
حسنًا، 100.
وعمل جيد.
إنه حقًا شريطٌ طويل، وإذا قمنا بعد هؤلاء،
نأمل، أن يكون هناك في الواقع 100 شريط.
وإذا قمنا بتشغيله مجددًا والقول، إيه، هذا لم يجرِ يصورةٍ جيدة.
حصلت على 50.
هذا نصف حجم الشريط.
لذلك يبدو أننا في طريقنا الصحيح لطريقة التشغيل.
والآن دعوني أمضي قدمًا وأحصل على الدرجات الأخرى.
حسنًا، حصلت عليهم هنا منذ لحظة.
لذا دعوني أمضي قدمًا وحسنًا فقط، أنسخ، وألصق، وأغير هذا إلى اثنين،
وأغير هذا إلى ثلاثة، وأغير هذا إلى ثلاثة، هذا إلى ثلاثة.
حسنًا، أعرف كيفية طباعة شريط بطريقة واضحة، لذا دعوني أمضي قدمًا
وأقوم بذلك، ومن ثم أقوم بذلك، ثم إصلاح المسافة البادئة.
لا أريد أن أقول Score 1 في كل مكان.
أريد أن Score 2, Score 2.
أعني أنك ربما كنت مُضللاً بطريقة خاطئة أن هذا
أمرًا سيئًا ومملاً، ولماذا؟
ما الذي أفعله بشكل سيئ الآن من حيث التصميم؟
الجمهور: نسخ التعليمات البرمجية ولصقها.
ديفيد ج. مالان: النسخ واللصق معظم الوقت أمر سيئ، أليس كذلك؟
يوجد تكرار هنا، لكن لا بأس.
دعونا نعطي الأولوية للتصحيح، في الوقت الحالي، على الأقل.
إذًا دعوني أمضي قدمًا وأنشيء Score 0.
حسنًا، لا أخطاء-- ./score0.
ثم النقر عليها.
دعوني أمضي قُدمًا وأشغل--
حسنًا، لقد حصلنا على 100 في المرة الأولى.
وحصلنا على 50 فى--
أوه، هذا خطأ.
ما الذي فعلته هناك؟
انظروا، هذا ما يحدث عندما تقومون بالنسخ واللصق.
إذًا دعونا نصلح هذا.
ينبغي أن يكون هذا Score 2، إذًا Control+C سينهي البرنامج.
سيقوم Make score 0 بإعادة إنشائه. ./0، Enter--
حسنًا، ها قد بدأنا.
100، 50.
دعونا نقسم التباعد--
75.
حسنًا، لذلك هذا مخطط شريطي بسيط مرسوم أفقيًا
لكل واحدة من النقاط الثلاث الخاصة بي، حيث أن هذا هو 100، وهذا 50، وهذا 75.
لكن هناك فرص للتحسين هنا.
إذًا أولاً، إنها تضلل بعض الناس
بالفعل حيث كنا حرفيًا ننسخ التعليمات البرمجية ونلصقها.
فأين هى الفرصة الوحيدة للتحسين هنا؟
ما الذي ينبغي عليّ فعله بدلاً من نسخ التعليمات البرمجية ولصقها مراراً وتكراراً؟
ما المقوم الذي يمكنكم وضعه؟
حسنًا، إذًا يمكننا استخدام التكرار الحلقي وفي الواقع فعل الشيء نفسه ثلاث مرات.
إذًا دعونا نجرب ذلك.
دعوني أمضي قُدمًا وأقوم بذلك.
إذًا دعوني أمضي قدمًا وأحذف النسخ واللصق الذي قمت به،
ودعوني أمضي قدمًا وأقول، حسنًا، for int i get zero, i less than 3, i++.
دعوني أنشيء قوسًا.
يمكنني تمييز عدة سطور والنقر فوق Tab،
وستتم إزاحتهم جمعيًا، وهو أمر مناسب.
هل يمكنني القيام بذلك الآن، مثلاً؟
قولها بصوتٍ أعلى قليلاً.
الجمهور: إذا كنت [INAUDIBLE] إلى محددة [INAUDIBLE]..
ديفيد ج. مالان: نعم، أنا قلق قليلاً.
كما تلاحظون هنا، إننا نستخدم في السطر 13 هنا المتغير نفسه، إذًا امم.
حدس جيد، لكني أشعر فى الواقع
أن هذا البرنامج، مغاير لسابقه فى الأسبوع الماضي، ونحن
الآن نجمع عدة أجزاء من البيانات.
التي يقسمها لنا التكرار الحلقي.
نعم.
الجمهور: يأخذ [INAUDIBLE] دالة [INAUDIBLE] تؤخذ فى--
كما لو يمكنك الحصول عليه [INAUDIBLE].
ديفيد ج. مالان: حسنًا.
الجمهور: مثل مُدخلٍ لِكم عدد النتائج التي أردت إدخالها.
ديفيد ج. مالان: حسنًا.
الجمهور: وإذًا، [INAUDIBLE].
ديفيد ج. مالان: نعم، يمكننا تنفيذ
دالة أخرى تقلل بعضًا من تلك الوظيفة.
أي أفكار أخرى؟
AUDIENCE: قم بتخزين نتائجك في مصفوفة.
ديفيد ج. مالان: حسنًا، يمكننا أيضًا تخزين نتائجنا فى مصفوفة.
إذًا دعونا نفعل هذا بترتيب، في الواقع.
إذًا التكرارت الحلقية رائعة عندما تريد أن تفعل شيئًا مرارًا
وتكرارًا، ولكن الغرض كله من دالة ما،
في جوهر الأمر، هو لتعيين أداء وظيفي مشترك.
وربما ما يزال هناك تكرار حلقي فى الحل،
لكن المشكلة الجوهرية الحقيقية مع ما كنت أفعله منذ لحظة
هي أنني كنت أقوم بنسخ ولصق الأداء الوظيفي--
لا يتعين علينا القيام بهذا، لأن في كل من C و سكراتش،
كان بوسعنا إنشاء الدالات الخاصة بنا.
إذًا دعونا نقوم بذلك.
دعوني ألغي تغييرات التكرار الحلقي هنا، فقط للعودة
إلى ما كنا عليه منذ لحظات.
دعوني أمضي قدمًا، وبدلاً من ذلك، إزالة هذا قليلا.
دعوني أمضي قدمًا وأُنشيء دالة جديدة
في الأسفل هنا سأسميها مثلاً، Chart، فقط
فقط لأنشىء مخططًا لنفسي.
وانها ستحصل على نتيجة لكونها مُدخل، ولكن يمكنني أن أسميه ما أريد.
إنها void كونها علامة رجوع، لأنني لا أريدها أن تسلمني شيئًا
مجددًا.
لن أحصل على سلسلة من المستخدم.
قمت فقط بطباعة حرف.
إنه ما يسمى التأثير الجانبي أو المخرج.
الآن سأمضي قدمًا وسأقوم بالتكرار الحلقي لديّ هنا for int i get 0.
I أقل من--
كم عدد علامات الشباك التي أريد طباعتها في حالة تمريري في نتيجة المستخدم؟
مثلاً، هل هذا 3 هنا؟
الجمهور: النتيجة.
ديفيد ج. مالان: النتيجة، إذًا لو تم
تسليمي رقمًا يتراوح من 0 إلى 100، وهذا ما أريد تكراره دومًا.
إذا كان هدفي هنا، في النهاية--
دعوني أنهي هذه المُعضِلة-- i++ هى [؟ 2 ؟] داخل هذا التكرار الحلقي
اطبع علامة شباك واحدة لكل نقطة فى إجمالي نتائج 1.
وفقط للحفاظ على الأشياء نظيفة، سأمضي قدمًا وأضع
سطرًا جديدًا في أقصي نهاية هذا.
لكنني أعتقد الآن، أنني قمت بتقليل كمية لا بأس بها من التكرار.
ليس جميعه، ولكني على الأقل الآن
منحت نفسي دالة تسمى Chart.
إذًا فى الأعلى هنا، يبدو أنه يمكنني نوعًا ما إزالة ذلك التكرار الحلقي، الذي
قمت بتقليله.
إنه متطابق تقريبًا، باستثناء أن اسم المتغير كان مُرّمزًا ضمنيًا.
وأعتقد أنه يمكنني الآن إنشاء مخطط مثل هذا،
ثم ربما يمكنني القيام بالنسخ واللصق قليلاً، لو كان ممكنًا، إذا
يمكنني البعد عن طريق القيام بذلك، ثم مثلاًُ 2، ثم مثلاً 3،
ثم لنقل 3، ثم لنقل 2.
إنه لا يزال يقوم بالنسخ واللصق، لكن بشكل أقل.
ويبدو أفضل.
إنه حرفيًا يناسب الموجود على الشاشة، لذا إنه تقدم-- ليس مثاليًا، لكنه تقدم.
تصميم أفضل، لكنه ليس مثاليًا.
إذًا هل سيتحول هذا برمجيًا؟
سأواجه أخطاء، لماذا؟
الجمهور: بشكل أساسي، إنه [INAUDIBLE] البرنامج[INAUDIBLE]..
ديفيد ج. مالان: حسنًا.
أجل.
الجمهور: نحن بحاجة إلى إعلان [INAUDIBLE]..
ديفيد ج. مالان: حسنًا، جيد.
اسمحوا لي أن أحث الخطأ الفعلي، فقط حتى نعرف المشكلة التي نقوم بحلها.
اسمحوا لي بالمضي قدمًا وأن أمضي قدمًا نوعًا ما ببراءة
وأقوم بتحويل Score 0 برمجيًا على أمل أن كل شيء على ما يرام، لكن بالطبع،
ليس بسبب خطأ شائع هنا.
لذا لاحظوا، التصريح الضمني لمخطط الدالة غير صالح في C99.
لذا مرة أخرى، التصريح الضمني للدالة
فقط قد يعني أن Clang لا يعرف ما الذي تتحدث عنه.
ويمكنك تشغيل help50، وربما على الأرجح
سيعطيك نصيحة مماثلة.
لكن مضمون هذا هو أن المخطط ليس دالة C.
إنه لا يأتي مع لغة C. أنا من كتبته.
لقد كتبته منذ قليل.
إذًا فإن الحل الذي لم نستخدمه الأسبوع الماضي
سيكون، حسنًا، إذا لم تعرفوا ما هو المخطط، فاسمحوا لي فقط
أن أذهب وأضعه حيث ستعرفونه.
والآن قم بتشغيل make score 0.
حسنًا، تم حل المشكلة.
إذًا هذا يصلحها، لكننا قد أصلحناها بطريقة مختلفة الأسبوع الماضي.
ولماذا قد نرغب في التمسك بنهج الأسبوع الماضي
وليس مجرد نسخ الدالة ولصقها ووضعها
في الأعلى بدلاً من الأسفل؟
الجمهور: [INAUDIBLE].
ديفيد ج. مالان: أجل، أنا أقصد أنه يمثل قلقًا طفيفًا نوعًا ما في هذه اللحظة،
لأن هذا برنامج قصير جدًا.
ولكني أقوم بدفع الجزء الرئيسي من برنامجي، حرفيًا يدعى Main،
أبعد وأبعد باتجاه الأسفل.
والمغزى من قراءة التعليمة البرمجية هو فهم ماذا تفعل.
لذا إذا قمت بفتح هذا الملف، وتعين علي التمرير، والتمرير، والتمرير، والتمرير، والتمرير
فقط للبحث عن الدالة الرئيسية، فإن هذا أسلوب سيء.
إنه لطيف نوعًا ما، وهو تقليد بشري جيد.
ضع التعليمة البرمجية الرئيسية، الدالة الرئيسية، مكافئ النقر على العلم الأخضر،
في الأعلى.
إذًا لغة C تقدم لنا حلاً هنا.
يجب عليك فقط أن تزوده بتلميح صغير.
اسمحوا لي بالمضي قدمًا وقص هذا من هنا، ووضعه ثانيةً في الأسفل هنا،
ومن ثم المضي قدمًا والنسخ واللصق فقط أو إعادة كتابة القيمة فقط--
عذرًا--القيمة لهذا السطر الأول، والتي تسمى بالنموذج الأولي.
أعطي Clang معلومات كافية بحيث يعرف الوسائط التي تأخذها الدالة
ونوع الإرجاع الخاص بها، وما هو اسمها، فاصلة منقوطة،
وهذا هو ما يسمى بالإعلان أو--
ومن ثم تنفيذها بالأقواس المتعرجة وكل المنطق أدناه.
لذا دعونا نمضي قدمًا ونشغل هذا.
وإذا مررت لأعلى هنا، سنرى-- عذرًا.
سنرى make score 0.
حسنًا، نحن الآن في طريقنا إلى، score 0.
Enter.
Score 1 هو 100، 50، 75، والآن يبدو أننا لدينا دالة جيدة.
ولكن لا يزال هناك فرصة، أجرؤ على القول، للتحسين.
وأعتقد أن المشكلة الأساسية هي أنني ما زلت
أقوم بنسخ ولصق الأشياء الصغيرة، لكن أعتقد
أن المشكلة الأساسية هي أنني لا يوجد لدي التعبيرات المنطقية لتخزين
قيم متعددة، إلا إذا كنت مسبقًا، كمبرمج،
أعطيتهم جميع الأسماء الفريدة، لأنه إذا استخدمت المتغير نفسه لكل شيء،
لن أتمكن من جمع الثلاث متغيرات في الأعلى،
ثم تتكرر على كل ثلاثة في الأسفل، إذا كان لدي متغير واحد فقط.
لذلك أحتاج إلى ثلاثة متغيرات، لكن هذا لا يُقاس بشكلٍ جيد.
ومن يعلم؟
إذا أردت أن آخذ خمس نتائج، أو 10 نتائج، أو نتائج أكثر،
فأنا حقًا أقوم بالنسخ واللصق بشكلٍ مفرط.
لذا يتضح، بالفعل، أن الإجابة هي مصفوفة.
لذا المصفوفة، في نهاية الأمر، هي مجرد
تأثير جانبي لتخزين الأشياء في الذاكرة متصلين على التوالي مع بعضهم البعض.
ولكن ما هو قوي حول حقيقة الذاكرة هذه هو التالي.
أستطيع المضي قدمًا وفي، لنقل، إصدار جديد وأكثر تحسينًا
من هذا البرنامج، والقيام بهذا.
دعوني أمضي قدمًا وأفتح هذا، والذي كتبته مسبقًا، ويُسمى scores2.c.
وفي scores2.c, لاحظوا أن لدينا التعليمات البرمجية التالية.
في الدالة الرئيسية، لدي ميزة جديدة ووحدة بت جديدة من الصيغ.
هذا السطر هنا الذي ظللته يقول، مرحبًا، Clang،
أعطني متغيرًا يُدعى Scores من نوع العدد الصحيح،
لكن من فضلك أعطني ثلاثةً منهم.
لذا فإن الصيغة الجديدة هي القوسان المربعان لديك،
وداخلهما أرقام المتغيرات التي تريدها من هذا النوع.
ولا يجب عليك أن تمنحهم أسماء فريدة من نوعها.
أنت تدعوهم حرفيًا بصورة جماعية، Scores،
وباللغة الإنجليزية، اخترت عمدًا صيغة الجمع للتعبير عن ذلك.
هذه مصفوفة قيم، وليست قيمة مفردة.
ما الذي يمكنني فعله بعد ذلك؟
حسنًا، ها هو التكرار الحلقي for loop for int i get zero i أقل من 3 i++،
والآن قمت بحل هذه المشكلة السابقة التي تم اقتراحها.
حسنًا، فقط ضعه في تكرارٍ حلقي.
أستطيع الآن، لأن المتغيرات الخاصة بي لا تُسمى Score 1, Score 2, Score 3،
والتي حولتها إلى تعليمات برمجية ثابت.
هم فقط يسمون Scores، والآن بما أنهم يُطلق عليهم Scores،
ولدي هذا الترقيم للأقواس المربعة، فلاحظوا ما يمكنني القيام به.
يمكنني الحصول على int, ويمكنني القول أن، اعطني score%i، وأدخل i زائد 1.
لم أكن أريد أن أقول "صفر"، لأن الأشخاص
لا يعدون من الصفر في العموم.
لذا هذا يعد من واحد، اثنين، ثلاثة، لكن الكمبيوتر يقوم بهذا.
لذا فإن Scores يعد متغيرًا.
قوس، i، إغلاق القوس يقول خزّن قيمة i-th هناك.
لذا i-th ليست لغة إنجليزية.
وهذا يعني الانتقال إلى القوس 0، والقوس 1، والقوس 2.
إذًا ما يعنيه هذا بشكلٍ فعال هو أن التكرار الأول للتكرار الحلقي، عندما
i يساوي صفرًا، هذا يبدو مشابهًا لهذا، بشكلٍ فعّال.
عندما يصبح i واحدًا في التكرار التالي، إذًا قم بهذا.
عندما يصبح i اثنين في التكرار النهائي، فهي تبدو مثل هذا.
عندما يصبح i ثلاثة، حسنًا، 3 ليس أقل من 3،
وبالتالي لا يتم تنفيذه مجددًا.
لذا باستخدام i داخل هذه الأقواس المربعة، هل أقوم بفهرسة المصفوفة؟
الفهرسة إلى مصفوفة تعني الانتقال إلى موقع معين،
الموقع المُسمى i-th، لكنك تبدأ العد من الصفر.
فقط لجعل هذا أكثر واقعية، ثم، إذا ذهبت للخلف
لهذه الصورة لذاكرة جهاز الكمبيوتر الخاص بك،
لذلك، هذا ربما، يكون القوس i، القوس 1--
القوس 0، القوس 1، القوس 2، القوس 3، القوس 4، القوس 50، أو أيًا كان.
يمكنك الآن، باستخدام الأقواس المربعة، الدخول إلى أيٍ من كتل الذاكرة هذه
لتخزين القيم لك.
أي أسئلة حول ما قمنا به للتو؟
حسنًا، ثم على الجانب الآخر، يمكننا القيام بالشيء نفسه بالضبط.
الآن عندما أطبع نتائجي، يمكنني التكرار بالمثل من 0 إلى 3،
ثم طباعة النتائج عن طريق التمرير إلى المخطط
القيمة نفسها، نتيجة i-th.
مجددًا، الصيغة الجديدة الوحيدة هنا هي اسم متغير، قوس مربع،
ثم رقم ، مثل 0، 1، 2، أو متغير مثل i،
ثم دالة المخطط الخاصة بي هنا هي نفسها بالضبط.
ليس لديها أدنى فكرة عن أن المصفوفة متضمَّنة، لأنني فقط
أمرر نتيجة واحدة في وقت واحد.
الآن يتضح أنه لا يزال هناك قرار تصميم سيئ واحد في هذا البرنامج.
لا يزال هناك بعض التكرار، شيءٌ أستمر في كتابته مرارًا
وتكرارًا.
هل تظهر أمامك أي قيمة كأنها مكررة؟
الجمهور: التكرار الحلقي.
ديفيد ج. مالان: التكرار الحلقي.
حسنًا، لقد حصلت على التكرار الحلقي في أماكن متعددة.
بالتأكيد.
وما هي القيمة الأخرى التي تبدو في أماكن متعددة؟
إنها دقيقة.
الرقم الإجمالي.
نعم، 3.
ثلاثة في أماكن متعددة.
إنه هنا.
إنه عندما أُعلن المصفوفة وأسأل نفسي عن ثلاث نتائج.
إنه هنا عندما أقوم بالتكرار.
إنه ليس هنا، لأن هذا تكرار مختلف.
هذا فقط لرموز الشباك.
حتى في، ويا للسخرية، كتبت 3 في ثلاثة أماكن.
إذًا ماذا يعني هذا؟
حسنًا، لنفترض أن العام المقبل ستأخذون المزيد من الاختبارات أو ما شابه،
وتحتاجون إلى المزيد من النتائج.
فتفتحون البرنامج الخاص بكم، وحسنًا، الآن لقد حصلت على خمس نتائج وخمس--
عذرًا، خطأ مطبعي بالفعل-- خمسة، مثل هذا النوع من النمط
حيث تكتب الشيء نفسه مرارًا وتكرارًا.
والآن يقع العبء علي، المبرمج،
لتذكر تغيير القيمة [? اللعينة ?] نفسها في أماكن متعددة--
تصميم سيء للغاية.
أنت ستنسى واحدة من تلك القيم.
سيصبح البرنامج الخاص بك أكثر تعقيدًا.
ستترك واحدًا كما هو 3 وتغيّر الآخرين إلى 5،
وستحدث الأخطاء المنطقية في النهاية.
إذًا كيف يمكننا حل هذا؟
الدالة ليست الحل هنا، لأنها ليست وظيفية.
إنها مجرد قيمة.
حسنًا ، يمكننا استخدام متغير، ولكن نوع معين من المتغيرات.
هذه الأرقام هنا-- 5، 5، 5 أو 3، 3، 3--
هي ما يشير إليه الإنسان عمومًا كأرقام سحرية.
هم أرقام، ولكنهم سحريين نوعًا ما،
لأنك فقط بشكلٍ تعسفي تقوم بتضمينهم في أماكن عشوائية.
لكن ستحدث اتفاقية أفضل، في كثير من الأحيان كمتغير عالمي، وهي القيام بهذا--
int، دعونا نطلق عليها "count"، يساوي 3.
لذا قم بإعلان متغير من النوع int على أنه عدد الأشياء
الذي تريدها، ثم اكتب اسم هذا المتغير في جميع أنحاء التعليمات البرمجية الخاصة بك
بحيث وفي وقت لاحق، إذا كنت ترغب في تغيير هذا البرنامج،
تغيره-- عذرًا-- في مكانٍ واحد، وتكون
قد انتهيت بعد إعادة تحويل البرنامج برمجيًا.
وفي الواقع، يجب علي فعل أفضل من ذلك قليلاً.
يتضح أنه إذا كنت تعلم أن لديك متغيرًا لن تقوم أبدًا
بتغييره، لأنه ليس من المفترض أن يتغير--
من المفترض أن يكون قيمة ثابتة--
لدى C أيضًا كلمة أساسية خاصة تُسمى const، حيث قبل نوع البيانات،
تقول، const int، ثم الاسم ثم القيمة، وهكذا،
سيتأكد المحول البرمجي، Clang، أنك، الإنسان،
لا تفسد وتحاول بطريق الخطأ تغيير العد في أي مكان آخر.
هناك شيء واحد آخر ملحوظ.
أنا أيضا قمت بتكبير جميع الحروف لسببٍ ما--
التقليد الإنساني.
في أي وقت تقوم بتكبير كل الأحرف في اسم متغير،
التقليد ينص على أن هذا يعني أنها عالمية.
هذا يعني أنه تم تعريفه بطريقة أعلى، ويمكنك استخدامه في أي مكان، لذلك،
لأنه خارج جميع الأقواس المتعرجة.
ولكن الهدف من ذلك هو التوضيح وتذكيرك أن هذا أمر مميز.
إنه ليس مجرد ما يُدعى بمتغير محلي داخل
دالة أو داخل التكرار الحلقي أو ما شابه ذلك.
أي أسئلة على هذا الجزء؟
أجل.
الجمهور: ما هو [INAUDIBLE]؟
لماذا لديك i زائد 1؟
ديفيد ج. مالان: أوه، لماذا لدي i زائد 1؟
اسمحوا لي بتشغيل هذا البرنامج بسرعة.
السؤال هو لماذا لدي i زائد 1 في هذا السطر هنا.
إذًا دعوني أمضي قدمًا وأقوم بتشغيل make scores 2--
عذرًا-- في الدليل الخاص بي.
Make scores 2 ./scores2, Enter.
أردت فقط من الأشخاص أن يروا Score 1 وScore 2 وScore 3.
لم أكن أريده أن يرى Score 0 ،Score 1 ،Score 2، لأنها تبدو فقط
نوعًا من السخافة للإنسان.
يحتاج الكمبيوتر إلى التفكير من حيث الأصفار.
الأشخاص والمستخدمين لا يفعلون، لذا هذا مجرد أمر جمالي.
أي أسئلة أخرى.
نعم.
الجمهور: [INAUDIBLE].
ديفيد ج. مالان: أوه، سؤال جيد حقًا.
وقد فكرت بهذا في الواقع في الليلة الماضية
عند محاولة صياغة هذا المثال.
لماذا لا أقوم فقط بدمج هذين الاثنين للتكرار الحلقي،
لأنهم يتكررون بوضوح عدد مماثل من المرات؟
هل كانت هذه يد أم مجرد تمطي؟
لا، تمطي.
إذًا هذا في الواقع متعمد.
إذا قمت بدمج هؤلاء، ما الذي قد يتغير منطقيًا في برنامجي؟
نعم.
الحضور: بعد كل [INAUDIBLE] المدخلات، قد [INAUDIBLE]..
ديفيد ج. مالان: نعم، إذًا، بعد كل مُدخل بشري لنتيجة،
كنت سأرى مخطط المستخدم، صف من رموز الشباك.
ثم سأطلب منهم قيمة أخرى.
سيشاهدون المخطط، قيمة أخرى، وسيشاهدون المخطط.
وهذا جيد، إذا كان هذا هو التصميم الذي تريده.
مقبول تمامًا.
صحيح تمامًا.
أردت أن يبدو برنامجي تقليديًا أكثر من ذلك بقليل مع كل الأشرطة
معًا، لذلك اضطررت بالفعل لتأجيل طباعة رموز الشباك.
ولهذا السبب لدي قليل من التكرار
عن طريق الحصول على مدخل المستخدم هنا ثم التكرار مجددًا
لطباعة مخرج المستخدم كمخطط، لذلك مجرد قرار تصميم.
سؤال جيد.
أي أسئلة أخرى؟
حسنًا ، ماذا يبدو هذا؟
في الواقع، أتعلم ماذا؟
ربما أستطيع فعل أفضل من ذلك قليلاً.
دعوني أفتح مثالاً واحدًا نهائيًا يتضمن النتائج وهذا الشيء
المُسمى مصفوفة.
في Scores 4 هنا، دعوني أمضي قدمًا وأفعل هذا.
الآن قمت بتغيير دالة المخطط لدي للقيام بالمزيد،
وقد تتذكر من الأسبوع 0 و1، كان لدينا دالة call،
واستمررنا في تحسينها لتفعل المزيد،
مثل وضع المزيد من المنطق.
لاحظوا هذا.
تأخذ دالة Chart الآن وسيطة ثانية، وهذا أمر مثير للاهتمام.
فهي تأخذ وسيطة واحدة، والتي تكون رقمًا،
ثم الوسيطة التالية والتي تكون مصفوفة من scores.
إذن فالقصة الطويلة باختصار، إذا أردت أن تمتلك دالة
تأخذ مصفوفة كمدخل، فلا حاجة لك بمعرفة
مدى حجم تلك المصفوفة سلفًا.
في الحقيقة، لا ينبغي عليك وضع رقم بين أقواس مربعة
في هذا السياق.
لكن الشيء الذي تحتاج لمعرفته، في مرحلة ما
هو كم عدد العناصر في المصفوفة.
إذا قمت بالبرمجة في Java، أو أخذت إلحاق متقدم في علوم الكمبيوتر، فسيمنحك Java فقط. طول،
إذا كنت تتذكر ميزة الكائنات هذه.
لا تمتلك لغة C هذا.
لا تحتوي المصفوفات على طول متأصل مرتبط بها.
يجب أن تخبر كل فرد يستخدم مصفوفتك عن مدى طولها.
لذا على الرغم من أنك لا تقوم بهذا هنا من ناحية الصيغ،
فأنت حرفيًا تقول فقط، أنا أتوقع وسيطة تسمى scores
وهي مصفوفة في الأقواس المربعة.
يجب عليك غالبًا دومًا تمرير متغير ثانٍ
يتم تسميته بما تريد،
لكنه عدد من الأشياء في هذه المصفوفة،
لأنه إذا كان هدف هذه الدالة هو فقط
تكرار أكثر لعدد النتائج التي تم تمريرها،
ثم التكرار أكثر لعدد النقاط في هذه النتيجة
من أجل طباعة علامات الشباك، فعليك أن تعرف هذا العدد.
لذا ما الذي تقوم به هذه الدالة، فقط للتوضيح؟
إنها تكرر أكثر عدد الإجمالي للنتائج من 0 إلى عدد،
وهو على الأرجح 3 أو 5 أو أيًا كان.
هذا التكرار الحلقي هنا، والذي يستخدم J، وهو فقط المتعارف عليه،
يكرر من 0 إلى درجة i-th أيًا كانت.
لذا هذا ما يعتبر مناسب.
الآن لقد قمت بالتمرير في المصفوفة، وما زلت أستطيع الحصول على قيم فردية
فقط باستخدام i، لأنني في تكرار i-th هنا.
لذا قد تتذكر هذا من ماريو، على سبيل المثال، أو أي مثال آخر
حيث يكون لديك تكرار حلقي متداخل--
من المتعارف عليه جدًا استخدام i في الخارج، وj في الداخل.
لكن مرة أخرى، فإن النقطة الوحيدة هنا هي أننا نستطيع، بالفعل، تمرير المصفوفات،
حتى كوسائط، والذي سنفهم سبب فائدته قريبًا.
أي أسئلة؟
حسنًا، إذًا كان هذا كثيرًا، لكن يمكننا أن نفعل أكثر بكثير باستخدام المصفوفات.
إنها تصبح رائعة أكثر وأكثر.
في الواقع، سنرى، خلال لحظات، كيف كانت المصفوفات بالفعل
معنا منذ الأسبوع الماضي.
إننا لم نلاحظها تمامًا تحت الغطاء، لكن دعونا نمضي قدمًا
ونأخذ استراحة، خمس دقائق.
سنعود ونتعمق في الأمر.
حسنًا.
أنا أعرف أن هذا كان مشوقًا قليلاً.
أين يمكن أيضًا أن تكون المصفوفات بالفعل؟
لكن، بالطبع، هذه هي الطريقة التي قد نصورها بها بشكل تصويري.
نحن أطلقنا عليها مصفوفة، ومن الواضح أنه في الأسبوع الماضي، عندما
قمنا بتقديم السلاسل، وهي تسلسلات من الحروف،
والتي كانت حرفيًا مصفوفة باسم آخر.
فالسلسلة هي مصفوفة من الحروف، والحروف، بالطبع، هي نوع بيانات آخر.
الآن، ما هي الآثار الفعلية لهذا،
كلاهما من حيث التمثيل، مثل طريقة تمثيل الكمبيوتر
للمعلومات، وبشكل أساسي، وبرمجي
ماذا يمكننا أن نفعل عندما نعرف أن جميع بياناتنا
متصلة عل التوالي أو قريبة جدًا لبعضها البعض؟
حسنًا، من الواضح أنه يمكننا تطبيق هذا المنطق بعدة طرق مختلفة.
اسمحوا لي بالمضي قدمًا وفتح، على سبيل المثال،
مثال هنا يسمى String 0.
لذا في التعليمة البرمجية الخاصة بنا لهذا اليوم، في مجلد Source 2 الخاص بنا،
اسمحوا لي بالمضي قدمًا وفتح String 0، وهذا المثال يبدو مثل هذا.
لاحظوا أننا أولاً، على السطر 9، نحصل على سلسلة من المستخدم.
فقط قل، مدخل، من فضلك.
فإننا نقوم بتخزين القيمة في string, s، ثم نقول، هنا يأتي المخرج.
ولاحظوا ما أقوم به في السطر التالي.
أنا أكرر أكثر i من 0 إلى strlen، أيًا كان هذا.
ثم في السطر 13 أقوم بطبع حرف واحد في كل مرة.
لكن لاحظوا الصيغة التي أستخدمها، والتي لم نستخدمها الأسبوع الماضي.
إذا كانت لديك سلسلة تسمى s، فيمكنك فهرستها إلى سلسلة
تمامًا كأنها مصفوفة، لكنها، بالفعل، غير ظاهرة.
إذًا s قوس i، حيث تبدأ i من الصفر فصاعدًا
إلى أي قيمة كانت هذه، فإنها طريقة للحصول على الحرف 0، ثم
الحرف 1،ثم الحرف 2، ثم الحرف 3،
وبالتالي فستبدو النتيجة النهائية مثل هذا.
اسمحوا لي بالمضي قدمًا، وكتابة make string--
عذرًا-- make string 0.
عذرًا.
ليس في هذا الدليل.
Make string 0، ./string0، Enter، وسأكتب فيه، قل، Zamyla،
والمخرج الآن هو Z-A-M-Y-L-A. إنها فوضوية قليلاً،
لأنني لم يكن لدي سطر جديد هنا، لذا اسمحوا لي بالفعل-- دعونا نزيل هذا،
لأن هذا أمر سيء لا داعي له.
لذا اسمحوا لي بالمضي قدمًا وطباعة سطر جديد.
اسمحوا لي بإعادة تجميعه باستخدام make string 0، نقطة--
عذرًا-- ./string0.
المدخل يجب أن يكون Zamyla، Enter، والآن Z-A-M-Y-L-A.
إذًا لماذا يحدث هذا؟
حسنًا، إذا قمت بالتمرير لأسفل في هذه التعليمة البرمجية، فيبدو أنني،
عبر سطر printf هنا، أحصل على حرف i-th من الاسم الموجود في s،
ثم أطبع حرفًا واحدًا في كل مرة لكل %c،
يتبعه سطر جديد.
لذا فقد تخمنوا، ماذا تفعل هذه الدالة هنا؟
Strlen-- مختصرة بشكل طفيف، لكن يمكنك، ربما، فهم ما تعنيه.
حسنًا، إنه في الواقع طول السلسلة.
لذا من الواضح أن هناك دالة تأتي
مع لغة C تسمى strlen، وأن البشر في السابق
وحاليًا يحبون الكتابة بعدد حروف أقل عندما يكون ذلك ممكنًا.
وبالتالي فإن strlen هي طول السلسلة، والطريقة التي تستخدمها هي
أنك فقط بحاجة إلى ملف رأس واحد آخر.
لذا يوجد هناك مكتبة أخرى تسمى مكتبة السلسلة
والتي تعطيك دوال ذات صلة بالسلسلة
وتتجاوز ما تقدمه مكتبة CS50.
وبالتالي إذا قمت بتضمين string.h، التي تمنحك الوصول
إلى دالة أخرى تسمى strlen، إذا قمت بإعطائها،
متغيرًا يتضمن سلسلة، فستعيد التمرير إليك
عدد الحروف كقيمة إرجاع إجمالي.
لذا لقد قمت بكتابة Z-A-M-Y-L-A، لذا يجب أن يرجع إلي هذا ستة،
وبالتالي طباعة ستة أحرف في اسم Zamyla.
أجل.
الجمهور:[INAUDIBLE].
ديفيد ج. مالان: اه.
الجمهور: [INAUDIBLE] مفيد للحصول على أرقام فردية [INAUDIBLE]..
ديفيد ج. مالان: سؤال جيدحقًا.
في مشكلة الائتمان لمجموعة المشكلة، هل كان هذا مفيدًا؟
نعم بالتأكيد.
لكن تذكر أن في الائتمان لـ pset، نحن نشجعك في الواقع
على أن تأخذ الرقم مثل رقم طويل، ليتسنى للقيمة المتكاملة، والتي
استلزمت بعض الحسابات.
لكن أجل، إذا كان لديك، بدلاً من ذلك، مشكلة تتعلق بأرقام بطاقة الائتمان
وحصلت على مدخل الإنسان كسلسلة طويلة من الأحرف
وليس كعدد حقيقي مثل عدد صحيح أو طويل،
إذًا، نعم، يمكنك بالفعل الحصول على تلك الحروف الفردية،
والتي ربما كانت ستجعل الأشياء أسهل لكنها متعمدة.
أجل.
الجمهور: [INAUDIBLE].
ديفيد ج. مالان: سؤال جيدحقًا.
إذا قمنا بتعريف السلسلة في CS50، فهل سنعرفها مرة أخرى في سلسلة؟
لا.
حتى السلسلة، بالرغم من أنها تدعى string.h،
فإنها لا تعرف شيء ما يدعى string.
إنها تحتوي على دوال ذات صلة بالسلسلة فقط.
المزيد من ذلك قريبًا.
أجل.
الجمهور: [INAUDIBLE] قيم فردية [INAUDIBLE]؟؟
ديفيد ج. مالان: اه، سؤال جيد حقًا.
هل يمكنك تعديل القيم الفردية؟
إجابة مختصرة، نعم.
يمكننا بالطبع تغيير القيم، وسنقوم بذلك قريبًا في سياق آخر.
أي أسئلة أخرى؟
حسنًا، إذًا من الواضح أن هذا صحيح، إذا كان هدفي هو
طباعة جميع الحروف في اسم Zamyla،
لكنه ليس التصميم الأفضل.
ولكن هذا التصميم دقيق قليلاً، لكنه، ثانيةً ما نعنيه بشأن التصميم.
وردًا على السؤال الذي طُرح خلال فترة الراحة،
هل توقعنا من الجميع الكتابة بأسلوب جيد وتصميم جيد الأسبوع الماضي؟
لا.
حتى اليوم، قدمنا فكرة الصواب
في كل من Scratch ولغة C الأسبوع الماضي، لكن الآن نحن
نقدم محاور جودة التعليمات البرمجية الأخرى
مثل التصميم، ومدى جودة التصميم، ومدى الجمالية
في سياق الأسلوب.
لذا التوقعات هنا من المفترض أن تتماشى مع تلك الخصائص،
لكن ليس في الماضي.
لذلك يوجد عدم كفاءة طفيفة هنا.
لذا في التكرار الأول في هذا التكرار الحلقي، أقوم أولاً بتهيئة i إلى 0،
ثم أتحقق مما إذا كانت i أقل من طول السلسلة، والتي نأمل،
أن يكون كذلك، إذا كان Zamyla، والذي هو أطول من 0.
سأطبع الحرف i-th.
سأقوم بزيادة i.
سأتحقق من هذا الشرط.
سأطبع الحرف i-th.
سأقوم بزيادة i.
سأتحقق من هذا الشرط وهكذا.
مررنا من خلال التكرار الحلقي الأسبوع الماضي، وكنتم قد استخدمتموه، ربما،
حتى الآن في المشاكل.
ما السؤال الذي أسأله بشكل متكرر ودون داعٍ؟
يجب أن أتحقق من الشرط مرارًا وتكرارًا،
لأن i تزيد.
لكن هناك سؤال آخر والذي لا أحتاج
إلى الاستمرار في سؤاله للحصول على الإجابة نفسها.
الجمهور: ما هو طول [? السلسلة? ?]
ديفيد ج. مالان: أجل، هناك دالة call هذه
في التكرار الحلقي الخاص بـ strlen، s، وهذا جيد.
هذا صحيح.
أنا أتحقق من طول السلسلة، لكن بمجرد كتابة Zamyla،
اسمها لا يتغير في الطول.
أقوم بزيادة i، لذا أتنقل في السلسلة، إذا صح التعبير.
لكن السلسلة نفسها، Z-A-M-Y-L-A، لا تتغير.
فلماذا أطلب من الكمبيوتر، مرارًا وتكرارًا، أن يعطيني strlen الخاص بـ s،
أن يعطيني strlen الخاص بـ s، أن يعطيني strlen الخاص بـ s.
لذا يمكنني بالفعل إصلاح هذا.
يمكنني تحسين التصميم، لأن هذا يجب أن يأخذ بعض الوقت.
ربما إنه سريع، لكنه لا يزال كمية غير صفرية من الوقت.
لذا هل تعرف ما الذي يمكنني فعله؟
يمكنني القيام بشيء مثل هذا-- int n get string length of s.
والآن أفعل هذا فقط.
هذا من شأنه أن يكون تصميم أفضل، لأن الآن أنا فقط أسأل السؤال مرة واحدة
من الدالة.
أنا أتذكر أو أقوم بالتخزين المؤقت، إذا صح التعبير، للإجابة، ثم
أستخدم فقط متغيرًا.
ومقارنة المتغيرات تصبح أسرع
من مقارنة متغير مقابل دالة، والتي يجب أن تُسمى،
والتي تصبح قيمة معادة، والتي يمكنك مقارنتها بعد ذلك.
ولكن بصراحة، إنه لا يجب أن يكون بهذا الإطناب.
يمكن بالفعل أن نكون منمقين أكثر بشأن هذا.
إذا كنت تستخدم التكرار الحلقي، ميزة سرية في التكرارات الحلقية
هي أنه يمكنك الحصول على فواصل بعد إعلان المتغيرات.
ويمكنك بالفعل القيام بهذا وفعل هذا بصورةٍ أكثر أناقة، إذا صح التعبير،
أو بصورةٍ مربكة أكثر، اعتمادًا على وجهة نظرك.
لكن هذا الآن يفعل الشيء نفسه لكنه يعلن n داخل التكرار الحلقي،
تمامًا كما أحدد i، وإنه أكثر إحكامًا بقليل.
إنه سطر واحد أقل من التعليمات البرمجية.
أية أسئلة أخرى؟
الجمهور: [INAUDIBLE].
ديفيد ج. مالان: سؤال جيد.
بالطريقة التي قمت بها لا يمكن إعادة استخدام هذا خارج الأقواس المتعرجة.
يوجد نطاق i وn في هذا السياق فقط الآن.
الطريقة الأخرى، نعم.
كان يمكن أن أستخدمها في مكانٍ آخر.
الجمهور: ماذا لو كنت [INAUDIBLE] من تكرار حلقي آخر، ولديك أيضًا [INAUDIBLE]؟؟
ديفيد ج. مالان: بالتأكيد.
الجمهور: استخدام حروف أبجدية مختلفة،
يمكنك استخدام n وليس [INAUDIBLE]..
ديفيد ج. مالان: صحيح.
إذا كنت أرغب في استخدام طول s مجددًا، بالتأكيد.
يمكنني تحديد المتغير، كما فعلت سابقًا، خارج التكرار الحلقي،
حتى يمكنني إعادة استخدامه.
هذا جيد تمامًا.
نعم.
وحتى i-- توجد i فقط داخل هذا التكرار الحلقي، لذا إذا كان لدي تكرار حلقي آخر،
يمكنني إعادة استخدام i، وهي i مختلفة، لأن هذه المتغيرات فقط
توجد داخل التكرار الحلقي الذي تم تحديدهم فيه.
إذًا من الواضح أن هذه السلاسل لا يوجد بداخلها أي شيء
بخلاف حرف بعد حرف بعد حرف.
وفي الواقع، دعوني أمضي قدمًا هنا وأرسم
صورة لما يحدث بالفعل تحت غطاء الكمبيوتر
هنا.
لذا عندما أكتب اسم Zamyla، فأنا، بالطبع،
أقوم بشيء مثل Z-A-M-Y-L-A. لكن أين يذهب هذا بالفعل؟
حسنًا، نحن نعرف الآن أن بداخل الكمبيوتر ذاكرة الوصول العشوائي أو الذاكرة،
ويمكنك تخيلها كشبكة.
وبصراحة، يمكنني التفكير في هذه الشاشة بأكملها
كما يجري في مختلف الاتجاهات، كشبكة من الذاكرة.
لذا على سبيل المثال، ربما يمكننا تقسيمها إلى صفوف وأعمدة مثل هكذا، ليس
بالضرورة على نطاق واسع، ويوجد العديد من الصفوف والأعمدة.
إذًا على الشاشة هنا، أنا فقط أُقسم الأشياء
إلى وحدات بايت فردية من الذاكرة التي رأيناها منذ لحظة.
وهكذا، في الواقع، تحت غطاء الكمبيوتر يوجد تخطيط الذاكرة.
اكتشف المحول البرمجي بطريقةٍ ما أو اكتشف البرنامج بطريقةٍ ما
أين يضع z وأين يضع a وأين يضع m وأين يضع y وأين يضع l وأين يضع a،
لكن الأساس هو أنهم جميعًا متجاورون، على التوالي مع بعضهم البعض.
ولكن تكمن المشكلة إذا كنت أكتب كلمات أخرى في برنامجي أو نتائجي
في برنامجي أو أي بيانات في برنامجي،
سوف ينتهي الأمر في مكان آخر في ذاكرة الكمبيوتر.
إذًا كيف تعرف أين تبدأ Zamyla وأين
تنتهي، إذا جاز التعبير، في الذاكرة؟
حسنًا، المتغير، المدعو s، موجود هنا بشكل أساسي.
هناك تذكر ما في الكمبيوتر للمكان الذي يبدأ s منه.
لكن ليست هناك طريقة واضحة لمعرفة أين تنتهي Zamyla،
إلا إذا أخبرنا الكمبيوتر بأنفسنا.
إذًا وبدون علم منا، في أي وقت يقوم الكمبيوتر بتخزين سلسلة مثل
Z-A-M-Y-L-A، يتضح أنه لا يستخدم واحد، اثنين، ثلاثة، أربعة، خمسة
ستة حروف.
في الواقع إنه يستخدم سبعة سرًا.
إنه في الواقع يضع حرفًا خاصًا
لجميع الأصفار في وحدات البايت الأخيرة جدًا.
كل وحدة بايت تساوي ثمان وحدات بت، لذا فإنها تضع سرًا ثمان أصفار هنا،
أو يمكننا بالفعل رسم هذا بطريقة متعارف عليها أكثر كـ /0.
وهذا ما يسمى بالحرف الفارغ، ويعني تمامًا جميع الأصفار.
لذا فإن طول السلسلة، Zamyla، هو ستة،
لكن كم عدد وحدات البت التي تأخذها على ما يبدو، فقط للتوضيح؟
إذًا في الواقع إنها تأخذ سبعة.
وهذا نوع من تفاصيل التنفيذ السرية
الذي لانهتم حقًا بأمره، لكن في النهاية، سنفعل ذلك،
لأن إذا أردنا تنفيذ دالة معينة،
فسنكون بحاجة إلى معرفة ما الذي يحدث في الواقع.
لذا فعلى سبيل المثال، اسمحوا لي بالمضي قدمًا والقيام بذلك.
اسمحوا لي بالمضي قدمًا وإنشاء برنامج يسمى strlen نفسه.
إذًا هذه ليست دالة لكنه برنامج يسمى strlen.c.
اسمحوا لي بالمضي قدمًا وتضمين مكتبة CS50 في الجزء العلوي.
اسمحوا لي بالمضي قدمًا وتضمين stdio.h.
اسمحوا لي بالمضي قدمًا وكتابة main void، كل هذا متماثل كما هو الحال دائمًا.
اسمحوا لي بالمضي قدمًا وحث المستخدم، لنقل، لاسمه أو اسمها،
مثل ذلك.
ثم أتعلمون ماذا؟
اسمحوا لي بالفعل، هذه المرة، عدم طباعة أسمائهم فقط،
لأننا قمنا بهذه الوسيطة.
دعونا فقط نعد عدد الأحرف في اسمه أو اسمها.
إذًا كيف يمكننا فعل ذلك؟
حسنًا، يمكننا فقط القيام بهذا-- int n get strlen من s، ثم نقول،
printf "The length of your name is %i."
ومن ثم يمكننا إدخال n، لأن هذا هو
الرقم الذي قمنا بتخزين الطول فيه.
لكن لاستخدام strlen، يجب أن أضمن أي ملف رأس؟
String.h، وهي سلسلة جديدة، لذا string.h.
والآن إذا طبعت هذا بشكل صحيح، make strlen، make strlen، جيد.
./strlen-- دعونا نجربها--
Zamyla.
Enter.
حسنًا، طول الاسم هو ستة.
لكن ماذا يفعل strlen؟
حسنًا، strlen هو فقط تجريد لنا، قام شخص آخر بكتابته،
وهو متعارف عليه بشكل رائع، لكن تعلمون، لا حاجة لنا به أبدًا.
يمكنني القيام بهذا بنفسي.
إذا فهمت ما الذي يقوم به الكمبيوتر،
فيمكنني تنفيذ هذه الوظيفة نفسها بنفسي كما يلي.
يمكنني الإعلان عن متغير يسمى n وأهيئه إلى 0،
ثم أتعلمون ماذا؟
سأمضي قدمًا وأفعل هذا.
في حين أن s قوس n لا يساوي جميع الأصفار،
لكنك لا تكتب جميع الأصفار مثل هذا.
أنت تفعل ذلك حرفيًا--
أن /0 والتي أشرت إليها سابقًا في علامات الاقتباس المفردة.
وهذا يعني تمامًا جميع الأصفار في وحدات البايت.
والآن يمكنني المضي قدمًا وكتابة n++.
إذا كنت على دراية بما يعنيه هذا، تذكروا،
أن هذا هو مجرد n يساوي n زائد 1،لكن إنه موجز قليلاً لقول،
n++.
ثم يمكنني طباعة اسم n الخاص بك--
اسم-- طول اسمك هو %i، داخل في n.
إذًا لماذا يعمل هذا؟
إنه يبدو غريب قليلاً، لكن هذا فقط
يدل على فهم ما يحدث
أسفل الغطاء المشهور.
إذا تمت تهيئة n لصفر، ونظرت إلى s قوس n،
حسنًا، فهذا يشبه النظر إلى s قوس 0.
وإذا كانت السلسلة، s، هي Zamyla، فما هو s قوس 0؟
Z. وهي بعد ذلك لا تساوي /0.
إنها تساوي z، بالتأكيد.
إذًا نحن نقوم بزيادة n.
إذًا الآن n تساوي 1.
الآن n تساوي 1.
إذًا ما هو s قوس 1 في اسم Zamyla؟
A وهكذا، ونحصل على Z-A-M-Y-L-A، ثم جميع الأصفار،
التي تسمى بالحرف الفارغ، أو /0.
هذا، بالطبع، يساوي /0، لذا يتوقف التكرار الحلقي،
تاركًا العدد الإجمالي أو قيمة n كما كانت عليه،
والذي كان 6.
إذًا هذا هو الأمر.
مثل جميع ما هو غير ظاهر، كل ما لدينا
هو ذاكرة موضوعة مثل هذا، من الأعلى للأسفل، اليسار لليمين
ومع ذلك كل وظيفتها التي تم استخدامها لمدة أسبوع من الآن
فصاعدًا يتلخص في بعض البدائيات البسيطة نسبيًا،
وإذا فهمت هذه البدائيات، فيمكنك
القيام بأي شيء تريده باستخدام الكمبيوتر بكل من الطريقة الحسابية
وفيما يتعلق بالتعليمات البرمجية، وأيضًا فيما يتعلق بالذاكرة.
يمكننا بالفعل رؤية، في الواقع، بعض الأشياء التي نظرنا إليها في الإسبوعين الماضيين
كما يلي.
اسمحوا لي بالمضي قدمًا وفتح مثال يسمى ASCII 0.
تذكروا أن ASCII يقوم بالربط بين الأحرف والأرقام في الكمبيوتر.
ولاحظوا ما الذي سيفعله هذا البرنامج.
Make-- دعوني أفتح هذا المجلد.
Make ascii0، ./ascii0، Enter.
يجب أن تكون السلسلة، دعونا نقول، Zamyla، Enter.
حسنًا، اتضح أنك إذا كنت تبحث عن
رمز ASCII لاسم Zamyla، سيكون z هو 90، والحرف الصغير a هو 97، وm هو 109،
وهكذا.
توجد تلك الأحرف وفي الواقع، يمكننا
لعب اللعبة نفسها التي قمنا بها الأسبوع الماضي.
إذا قمت بذلك مجددًا على "hi،" فيوجد 72 الخاص بك، ويوجد 73 الخاص بك.
من أين يأتي هذا؟
حسنًا، الآن أعرف كيفية معالجة السلاسل الفردية،
لاحظوا ما الذي يمكنني فعله.
يمكنني الحصول على سلسلة من المستخدم، تمامًا كما يمكننا دومًا.
يمكنني التكرار على طول تلك السلسلة، وإن كان بشكل غير فعال
باستخدام strlen هنا.
ثم لاحظوا هذه الميزة الجديدة اليوم.
يمكنني الآن تحويل نوع بيانات واحد إلى آخر، لأن char،
حرف هو فقط ثماني وحدات بت، ولكنه يقدم في سياق الأحرف.
كما أن وحدات البت هي فقط ثماني وحدات بت يمكنك معاملتها كعدد صحيح، رقم.
إنها حساسة للسياق تمامًا.
إذا قمت باستخدام برنامج Photoshop، فستكون رسمًا.
إذا قمت باستخدام برنامج نصي، فستكون رسالة وهكذا.
لذا يمكنك ترميز--
تغيير السياق.
لذا لاحظوا هنا، s قوس i هي، بالطبع، حرف i-th من اسم Zamyla
لذا Z أو A أو M أو أيًا كان.
ولكن يمكنني تحويل حرف i إلى عدد صحيح بالقيام بما يسمى الصب.
يمكن حرفيًا، في ما بين الأقواس، تحديد نوع البيانات
التي ترغب في تحويل نوع بيانات واحد إليها، ثم
تخزينه في نوع البيانات هذا بالضبط.
لذا s قوس i-- حوله إلى رقم.
ثم خزنه في متغير رقم حقيقي، حتى يمكنني طباعة قيمته.
إذًا لغة c-- تعرض لي هذا الحرف.
تعرض لي الحرف كما هو متصل بالحرف، ومن ثم الحرف--
عفوًا، الحرف والرقم الذي قمت للتو بتحويله إليه.
ولا يتوجب عليك فعليًا أن تكون صريحًا.
هذا ما يسمى بالصب الصريح.
فنيًا، يمكننا القيام بهذا بشكل ضمني، أيضًا.
ويعرف جهاز الكمبيوتر أن الأرقام هي أحرف،
والأحرف هي رقم.
لا يتوجب عليك أن تدقق كثيرًا وتقوم
بالصب الصريح في الأقواس.
يمكنك القيام به فقط باستخدام أنواع البيانات، وبصراحة في هذه النقطة،
أنا لا أحتاج إلى المتغير.
يمكنني التخلص منه، وهنا في الأسفل، يمكنني حرفيًا
طباعة الشيء نفسه مرتين، ولكن أخبر printf
أن يقوم بطباعة الأول في سياق حرف
والثاني في سياق عدد صحيح، فقط بالتعامل مع وحدات البت نفسها بالضبط
بشكل مختلف.
هذا هو الصب الضمني.
ويظهر فقط ما قمنا به في أسبوع 0
عندما زعمنا أن الأحرف هي أرقام،
والأرقام يمكن أن تكون ألوانًا، والألوان يمكن أن تكون صورًا، وهكذا.
هل هذا سؤال؟
الجمهور: هل كانت ستكون مفيدة بالنسبة للائتمان.
ديفيد ج. مالان: أيضًا، نعم.
إن الأمر كله يعتمد على الائتمان.
نعم.
حقًا.
أي أسئلة أخرى؟
لا.
حسنًا، إذًا ما الذي يمكننا القيام به في الواقع بهذا التقدير؟
ميزة بسيطة جدًا نعتبرها جميعًا أمرًا مسلمًا به،
إذا كنا نستخدمها بعد هذه الأيام.
يمكن لـ Google Docs، وMicrosoft Word، وما يماثلهما
كتابة كلمات بأحرف كبيرة تلقائيًا لك هذه الأيام.
أعني أن هاتفك يمكنه القيام بذلك الآن.
إنها فقط عبارة عن نوع من التصحيح التلقائي لرسائلك.
حسنًا، كيف يعمل هذا فعليًا؟
حسنًا، بمجرد أن تعرف أن السلسلة عبارة عن مجموعة من الأحرف فقط
متصلة على التوالي مع بعضها البعض، وتعرف أن هذه الأحرف لديها أرقام
تمثلها، ومثل الحرف الكبير A هو 65، والحرف الصغير A هو 97، بشكل واضح،
وهكذا، يمكننا الحصول على هذه الأنماط.
إذا مضيت قدمًا وفتحت المثال الآخر هذا
هنا المسمى بـ Capitalize 0، لاحظوا ما الذي سيقوم به هذا البرنامج
لي أولاً بتشغيله.
Make capitalize 0 ./capitalize0.
دعوني أمضي قدمًا وأكتب اسم Zamyla فقط كما فعلت من قبل، ولكن الآن
بجعل جميع الأحرف كبيرة.
لذا هذا زائد قليلاً.
آمل أن هاتفك لا يكتب كل حرف بالأحرف الكبيرة،
ولكن يمكنك تخيله يكتب الحرف الأول فقط، إذا رغبت في ذلك.
لذا كيف يتم هذا؟
حسنًا، دعوني أمضي قدمًا وأفتح هذا المثال هنا.
وهذا ما قمنا به--
هنا، أحصل على سلسلة من المستخدم، تمامًا كما نفعل دائمًا.
ثم فقط أقول، after، لتنسيق المخرج بشكل لطيف نوعًا ما.
هنا، أقوم بتكرار حلقي بكفاءة جيدة من i يعادل 0 إلى ما يصل
إلى طول السلسلة.
والآن لاحظوا تطبيق المنطق الأنيق هذا.
إنه مشفر قليلاً، للوهلة الأولى.
ولكن عفوًا.
والآن لقد اختفى.
وما الذي أقوم به بالضبط باستخدام سطور التعليمات البرمجية هذه؟
حسنًا، بكل عملية تكرار لهذا التكرار الحلقي، سأطرح السؤال،
هل الحرف i من s، لذا الحرف الحالي،
أكبر من أو يعادل الحرف الصغير A، وأقل من
أو يعادل الحرف الصغير Z؟
وبعبارة أخرى، كيف يمكنك قول ذلك بتعبير عامي أكثر باللغة الإنجليزية؟
هل هو حرف صغير، حرفيًا.
ولكن هذه هي الطريقة الأكثر برمجية للتعبير، هل هو حرف صغير؟
حسنًا، إذا كان كذلك، فلتمضي قدمًا وتقوم بذلك.
الآن هذا غريب قليلاً، ولكن اطبع حرفًا، على وجه التحديد،
الحرف i، ولكن اطرح من ذلك الحرف الصغير حرفًا أيًا كان
الاختلاف بين الحرف الصغير A والحرف الكبير A. الآن من أين أتى ذلك؟
إذًا يتضح أن--
حسنًا، الحرف الكبير A هو 65.
الحرف الصغير A هو 97.
لذا الفرق بين هذين الحرفين هو 32.
وهذا صحيح لـ B، لذا الحرف الكبير B هو 66، والحرف الصغير B هو 98.
وما زال 32، ويتكرر للأحرف الأبجدية بأكملها.
لذا يمكنني فقط القيام بهذا.
إذا علمت أن الأحرف الصغيرة لديها أرقام كبيرة، مثل 97، 98،
وأعرف أن الأرقام الصغيرة لديها أحرف صغيرة، مثل 65، 66،
يمكنني فقط حرفيًا طرح 32 من الأحرف الصغيرة الخاصة بي.
كما أشرتم، إنه حرف صغير.
اطرح 32، ويعطينا هذا أي نتيجة؟
الإصدار المكتوب بأحرف كبيرة.
إنها تقوم بتكبير الأشياء من أجلنا.
ولكن بصراحة، إن هذا يبدو نوعًا من الاختراق، مثل، حسنًا، نعم،
يمكنني القيام بعملية حسابية بشكل صحيح، ولكن أتعرفون؟
إنها ممارسة أفضل، بشكل عام، للطرح بهذه الطريقة.
لا تدخلوا في تعقيدات حساب عدد الأحرف التي تفصلهم
عن بعضها البعض.
الحساب أمر سهل وبسيط على جهاز الكمبيوتر.
فلتدعه يقوم بالعملية الحسابية لأجلك من خلال طرح قيمة الحرف الكبير A،
أيًا كانت من قيمة الحرف الصغير A. أو يمكننا فقط كتابة 32.
وإلا أمضي قدمًا وقم فقط بطباعة الحرف الذي لم يتغير.
لذا في هذه الحالة، تم تكبير الأحرف A-M-Y-L-A في اسم Zamyla،
وكل شيء آخر، وتم ترك الحرف Z بمفرده،
فقط من خلال فهم ما الذي يجري باستخدام الكيفية التي يتم تقديم جهاز الكمبيوتر بها.
ولكن بصراحة، لا أريد أن أستمر في كتابة تعليمة برمجية كهذه.
مثل، لن أحصل على هذا أبدًا.
أنا جديد في عالم البرمجة، من المحتمل.
لن أحصل أبدًا على هذا النوع من التسلسل لجميع الرموز المشفرة
معًا، وهذا جيد، لأنه يمكننا تنفيذ هذا البرنامج نفسه
بشكل أكثر سهولة قليلاً، بفضل الدوال
وعمليات التجريد التي كتبها الآخرون من أجلنا.
لذا في هذا البرنامج، اتضح أنه يمكنني تبسيط
الأسئلة التي سأطرحها من خلال حرفيًا طلب دالة تقول، أقل من.
وتوجد دالة أخرى تسمى، is upper،
وتوجد مجموعة أخرى والتي تسمى حرفيًا،
بشيء آخر أو غير ذلك.
لذا is lower تأخذ وسيطة مثل الحرف i من s،
ولا ترجع شيئًا-- صحيح أو خاطئ فقط.
كيف يتم تنفيذ ذلك؟
حسنًا، وبصراحة، إذا نظرنا في التعليمة البرمجية التي كتبها شخص آخر منذ عقود
لـ is upper، فالاحتمالات هي-- أو is lower--
الاحتمالات هي أنه كتب أو أنها كتبت تعليمة برمجية تشبه هذه كثيرًا.
ولكننا لسنا بحاجة إلى القلق من هذا المستوى من التفاصيل.
يمكننا استخدام دالته أو دالتها فقط، ولكن كيف يمكننا القيام بذلك؟
اتضح أن هذه الدالة-- ويمكنك معرفة هذا فقط
عن طريق إخبارك أو البحث عنه في Google أو قراءة مرجع--
موجودة في مكتبة باسم ctype.h.
وتحتاج إلى ملف الرأس المسمى ctype.h لكي تستخدمه.
وسنقوم دائمًا تقريبًا بتوجيهك إلى مراجع ووثائق
لتوضيح ذلك لك.
To upper هي ميزة أخرى، أليس كذلك؟
هذه الحسابات-- مثل، يا إلهي.
أريد فقط كتابة حرف كبير.
أنا لا أريد أن أستمر في التفكير حقًا حول إلى أي مدى الفرق بين الأحرف الكبيرة
والأحرف الصغيرة.
اتضح أن في مكتبة من النوع C، توجد
دالة أخرى تسمى toupper والتي تقوم حرفيًا بالشيء نفسه بالضبط
في البرنامج السابق الذي كتبناه.
ولذا هذا، أيضًا، جيد.
ولكن أتدرون ماذا؟
يبدو هذا أكثر إطنابًا قليلاً.
سيكون من الجيد إذا تمكنت حقًا من ربط هذا البرنامج.
لذا كيف تعمل toupper هذه؟
حسنًا، يتضح أن البعض منكم أصبح على دراية بمرجع CS50
على الإنترنت، تطبيقنا القائم على الويب والذي لدينا
لمساعدتكم في التنقل بين الوظائف المتاحة في C.
يتضح أن جميع البيانات لذلك التطبيق
تأتي من برنامج سطر أوامر قديم يأتي في Linux
ويأتي في أداة تحديد الوصول التي تسمى Man لدليل.
وفي أي وقت تكتب فيه "man" في محث الأوامر، ومن ثم اسم
دالة أنت مهتم بها، إذا وجدت،
ستخبرك شيئًا بسيطًا حيال ذلك.
لذا إذا انتقلت إلى toupper ،man toupper سأحصل على وثائق مشفرة قليلاً
هنا.
ولكن لاحظوا أن toupper وبعض الدوال الأخرى
تحول حرف صغير أو حرف كبير.
هذا هو الملخص.
لاحظوا أنه في الملخص الموجز، صفحة man، إذا جاز التعبير،
تخبرني أي ملف رأس يتوجب عليّ تضمينه.
لاحظوا أنه أسفل الملخص الموجز، تخبرني أيضًا
بأي توقيع أو نموذج أولي للدالة.
وبعبارة أخرى، الوثائق في Man، دليل المبرمجين من Linux،
موجزة للغاية.
لذا فهي لن تحتفظ بيدك في تنسيق الأبيض والأسود هذا.
إنها فقط ستقوم بتحويلك، حسنًا، بشكل ضمني،
إلى الأفضل بوضع هذا في أعلى ملفك.
وبالمناسبة، هذه هي كيفية استخدامك للدالة.
إنها تأخذ وسيطة تسمى C، وتعيد قيمة من النوع int.
لماذا هذا int؟
دعونا لا نلقي بالاً لهذا.
إنها تعيد حرفًا لأغراضنا اليوم.
وإذا انتقلنا إلى الأسفل، حسنًا، وصف.
آه، أنا حقًا لا أريد قراءة كل هذا، ولكن حسنًا، ها نحن ذا.
إذا كان c حرفًا صغيرًا، فتعيد toupper مكافئًا كبيرًا له،
إذا وجد تمثيل حرف كبير في الإعدادات المحلية الحالية.
فهذا يعني فقط إذا كان ترقيمًا، أنه لن يقوم بأي شيء.
وإلا فسيعيد C، وهذا نوع من التفاصيل الرئيسية.
إذا قمت بتمرير الحرف الصغير a إليه، فسيقدم لي الحرف الكبير A،
ولكن إذا قمت بتمرير الحرف الكبير A، فما الذي سيقدمه لي؟
الجمهور: الحرف الكبير A.
ديفيد ج. مالان: أيضًا، الحرف الكبير A. تعيد الحرف الأصلي، c.
هذا هو التفصيل الوحيد الذي أهتم به.
في حالة الشك، اقرأ الدليل.
وقد يكون مشفرًا قليلاً، وهذا
هو السبب وراء أخذ مرجع CS50 وثائق مشفرة إلى حد ما
ومحاولته تبسيطها في مصطلحات ملائمة أكثر للإنسان.
ولكن في نهاية اليوم، هذه هي الإجابات الموثوقة.
وإذا كنت لا أعرف أنا أو أحد العاملين، فنحن حرفيًا
نسحب صفحة Man أو مرجع CS50 للإجابة على هذه الأنواع من الأسئلة.
الآن ما هو الأثر؟
لا أحتاج أيًا من هذه.
يمكنني حرفيًا التخلص من الشرط وأسمح فقط
لـ toupper القيام بكل العمل الشاق، والآن برنامجي
أصبح مضغوطًا أكثر مما كانت عليه الإصدارات السابقة
لأنني قرأت الوثائق.
أنا اعرف ما الذي تقوم به الدالة، ويمكنني السماح لـ toupper بتكبير شيء
أو تمريره فقط بدون تغيير.
يمكننا التصميم بشكل أفضل، لأننا كتبنا بعض سطور التعليمات البرمجية
الواضحة تمامًا، ولذا يمكننا الآن ربط الأشياء.
أي أسئلة حول هذا النهج المعين؟
حسنًا.
لذا نحصل على مستوى منخفض جدًا.
الآن دعونا نجعل هذه الأشياء مفيدة أكثر، لأنه وبشكل واضح، قام أشخاص آخرون
بحل بعض المشكلات هذه لأجلنا،
من خلال وجود هذه الدوال والمكتبة من النوع C ومكتبة السلسلة.
ما الذي يوجد هناك أكثر؟
حسنًا، تذكروا ذلك كل مرة نقوم فيها بتشغيل Clang، أو حتى نقوم بتشغيل make،
نكتب كلمات متعددة في محث الأوامر.
أنت تكتب make hello أو make Mario، كلمة ثانية،
أو تكتب clang-o، hello، hello.c،
العديد من الكلمات في المحث.
حسنًا، يتضح أن طوال هذا الوقت، أنت تستخدم، حقًا،
وسيطات سطر الأوامر.
ولكن في C، يمكنك كتابة برامج تقبل أيضًا كلمات وأرقام عندما
يشغّل المستخدم البرنامج.
فكر مجددًا، بعد كل هذا.
عندما قمت بتشغيل Mario، فأنت قمت بـ ./mario، Enter.
لم يمكنك كتابة أي كلمات أكثر في المحث.
عندما قمت بالائتمان، فأنت قمت بـ ./credit، Enter.
لا توجد كلمات أخرى في المحث.
لقد استخدمت get string أو get more input، ولكن ليس
في سطر الأوامر.
ويتضح أنه يمكننا، ببساطة نسبيًا، في C،
ولكن هذا مشفر قليلاً للوهلة الأولى.
دعوني أمضي قدمًا--
دعوني أمضي قدمًا، هنا، وأسحب هذا التوقيع هنا، والذي يشبه هذا.
هذه هي الدالة التي قمنا باستخدامها جميعًا حتى الآن لكتابة دالة رئيسية.
وحتى الآن، لقد قلنا void.
ولا يأخذ Main أي مخرج، وحقًا إنها فقط تقوم بالتشغيل.
ولكن يتضح أنه إذا قمت بتغيير برامجك الموجودة أو برامجك المستقبلية،
ليس بقول void، ولكن بقول int argc، string argv،
إنه مشفر قليلاً للوهلة الأولى.
ولكن ما هو الرمز الذي يمكن التعرف عليه الآن؟
نعم، توجد أقواس هنا.
لذا يتضح أن كل مرة تكتب فيها برنامجًا،
إذا لم تقل void فقط، فأنت تمكّن هذه الميزة في الواقع
من خلال كتابة int argc، string argv.
يمكنك إخبار Clang، أتعرفون ماذا؟
أريد هذا البرنامج أن يقبل كلمة واحدة أو أكثر أو رقمًا واحدًا أو أكثر بعد اسم
البرنامج، إذًا يمكنني القيام بـ ./hellodavid، أو ./hellozamyla.
لا أحتاج إلى انتظار البرنامج ليتم تشغيله لاستخدام سلسلة.
ومثلما هو الحال في المثال السابق، حيث كان يمكنك رسم مصفوفة،
يتم تحديد main بأخذ مصفوفة، تسمى argv لأسباب تاريخية--
وسيطة vector.
Vector يعني مصفوفة.
تعني وسيطة vector، قوس، قوس مغلق فقط هذا هو--
يحتوي هذا على كلمة واحدة أو أكثر، كل منها سلسلة.
Argc هو عدد الوسيطات، لذا هذا هو المتغير
حيث يصل main إلى ذلك ليخبره عن عدد الوسيطات،
عدد السلاسل الموجود بالفعل في argv.
لذا كيف يمكننا استخدام هذا بطريقة مفيدة؟
حسنًا، دعوني أمضي قدمًا وأفتح أداة تحديد الوصول.
ودعوني أمضي قدمًا وأقوم بإنشاء ملف جديد باسم، لنقل، argv0، argv0.c--
مجددًا، وسيطة vector، فقط قائمة أو مصفوفة من الوسيطات.
ودعوني أمضي قدمًا، وكما هو معتاد، include cs50.h، include stdio.h،
ومن ثم int main ليس void، ولكن int argc، string argv--
argv-- فتح قوس، قوس مغلق.
وحتى إذا لم يظهر بشكل عادي في البداية، فستصبح هكذا في النهاية.
سأقوم بفعل ذلك.
إذا كان عدد الوسيطات التي تم تمريرها يساوي 2،
ثم أقوم بالمضي قدمًا وأفعل هذا-- printf، مرحبًا %s، فاصلة،
وهنا من قبل، قمت بكتابة اسم متغير.
ويمكنني الآن الوصول إلى متغير.
أمضي قدمًا وأكتب argv قوس 1.
Else، إذا لم يقم المستخدم بكتابة، على ما يبدو كلمتين،
دعوني أمضي قدمًا وفقط بشكل افتراضي، أقول، hello world، كما نفعل دائمًا.
الآن لماذا-- ما الذي يقوم به هذا، وكيف يقوم بذلك؟
حسنًا، فلنشغله بسرعة.
لذا make-- أوه.
Make argv0, ./argv0, Enter, Hello World.
ولكن إذا كتبت Hello--
أو نقطة-- سيكون اسم البرنامج بشكل أفضل
إذا أطلقنا عليه Hello، ولكن Zamyla، Enter.
Hello Zamyla.
إذا قمت بتغييره إلى ديفيد، الآن يمكنني الوصول إلى ديفيد.
إذا كان لدي ديفيد مالان، لا.
إنه لا يدعم ذلك.
إذًا ما الذي يحدث؟
إذا قمت بتغيير main في أي برنامج للكتابة لتأخذ
هاتين الوسيطتين، argc وargv من النوع string int
ومن ثم مصفوفة السلاسل، تخبرك argc عدد الكلمات
المكتوبة في المحث.
لذا إذا كتب شخص كلمتين، أفترض أن
الكلمة الأولى هي اسم البرنامج، نقطة خط مائل argv0،
والكلمة الثانية من المفترض أن تكون اسمي، إذا كان يقدم أو كانت تقدم في الواقع
اسمه أو اسمها في المحث.
ولذا طبعت argv قوس 1.
ليس 0 لأن هذا هو اسم البرنامج، ولكن argv قوس 1.
Else، في الأسفل هنا، إذا لم يقدم الشخص فقط Zamyla، أو ديفيد فقط،
أو كلمة واحدة فقط بشكل عام أكثر، فأنا أطبع الافتراضي فقط، "Hello world."
لكن الأنيق حول هذا الآن هو لاحظوا أن argv هي مصفوفة السلاسل.
ما هي سلسلة؟
إنها مصفوفة من الأحرف.
ولذا دعونا ندخل قطعة واحدة أخرى من الصيغة التي تصبح أقوى نوعًا ما
هنا.
دعوني أمضي قدمًا وأفعل هذا.
دعوني أمضي قدمًا، وفي ملف جديد هنا، argv 1.c.
دعوني أمضي قدمًا وألصق هذا.
أغلق هذا.
دعوني أمضي قدمًا وأفعل هذا.
وبدلاً من القيام بهذا التدقيق المنطقي، دعوني أقوم بهذا، لـ--
دعونا نقول for int, i get 0.
i أقل من argc--
i++.
دعونا نمضي قدمًا، واحد في كل سطر، ونطبع كل كلمة
كتبها شخص فقط، فقط لتأكيد
أن هذا هو ما يحدث حقًا.
لذا argv قوس 0، حفظ.
Make argv 1، enter.
والآن دعوني أمضي قدمًا وأشغل هذا البرنامج--
نقطة خط مائل، argv 1، ديفيد مالان.
حسنًا، ترون جميع الكلمات الثلاث.
إذا قمنا بتغييرها إلى Zamyla، سنرى هاتين الكلمتين فقط.
إذا قمنا بتغييرها إلى Zamyla Chan، سنرى الكلمات الثلاث هذه.
لذا من الواضح أننا لدينا إمكانية الوصول إلى جميع الكلمات في المصفوفة،
ولكن دعونا نأخذ هذه الخطوة الإضافية.
وبدلاً من طباعة كل كلمة فقط في سلسلة، دعونا نمضي قدمًا ونفعل ذلك.
For intj get 0.
n يعادل طول السلسلة من الوسيطة الحالية، مثل هذا--
j أقل من n، j++--
أوه، أوه، أوه-- j++.
الآن دعوني أمضي قدمًا ولا أطبع السلسلة بأكملها، ولكن دعوني أقوم-- أوه،
أوه-- دعوني أمضي قدمًا وأطبع هذا--
ليست سلسلة، ولكن حرف، n قوس i قوس j، مثل هذا.
حسنًا.
إذًا ما الذي يحدث؟
واحد، هذا تكرار حلقي خارجي، ودعونا نعلق عليه، التكرار على السلاسل في argv.
هذا تكرار حلقي داخلي، تكرار على chars في argv قوس i.
لذا التكرار الحلقي الخارجي يتكرر على جميع السلاسل في argv.
والتكرار الداخلي، باستخدام متغير مختلف، يبدأ من 0،
يتكرر على جميع الأحرف في وسيطة i،
والتي هي سلسلة في حد ذاتها.
لذا يمكننا تسميتها بطول السلسلة.
ومن ثم نقوم بهذا حتى n، وهي طول تلك السلسلة.
ومن ثم نطبع كل حرف.
لذا فقط ليكون الأمر واضحًا-- عندما أقوم بتشغيل argv1 وأصححه، للوهلة الأولى،
لماذا يعلن بشكل ضمني دالة المكتبة sterling، ما هو الحل دائمًا
عندما تقوم بهذا الخطأ؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: أجل.
إذًا لقد نسيت هذا، include string.h وhelp50 قد
يساعد في هذا أيضًا.
لنعيد التحويل البرمجي باستخدام make argv1.
حسنًا.
عندما أقوم بتشغيل argv1، من، Zamyla Chan، ما الذي سأقوله؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: أجل.
هل ذلك هو الحدس الصحيح؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: سأنتقل لرؤية Zamyla Chan، لكن--
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: حرف واحد على كل سطر، بما في ذلك اسم البرنامج.
لذا في الحقيقة، دعوني أمرر هذا لأعلى حتى يصبح أكبر قليلاً.
Enter.
حسنًا، إن البرنامج غبي قليلاً، ولكنه يؤكد أن استخدام المصفوفات
هل لدي إمكانية الوصول ليس فقط إلى الكلمات، ولكن يمكنني نوعًا ما
الحصول على البعد الثاني.
ومن خلال كل كلمة، يمكنني الحصول على كل حرف بداخلها.
ونحن نقوم بذلك، مجددًا، فقط باستخدام ليس فقط أقواسًا مربعة مفردة،
ولكن اثنين.
ومجددًا، قم بتفصيل هذا إلى المبادئ الأساسية.
ما هو هذا القوس الأول؟
هذه هي وسيطة i، سلسلة i في المصفوفة.
ومن ثم إذا أخذنا هذا مجددًا، باستخدام قوس j،
والذي يعطيك الحرف j داخل هذا.
الآن، مَن يهتم بأي من هذا النوع من الوظائف؟
حسنًا، دعوني أقوم بالتمرير مجددًا وأقترح تطبيقًا واحدًا هنا.
لذا تذكروا أن علم الكمبيوتر هو فقط عبارة عن حل مشكلة حقًا.
ولكن لنفترض أن المشكلة التي تريد حلها
هي في الواقع عبارة عن تمرير رسالة سرية في الصف الدراسي
أو إرسال سر إلى شخص ما أيًا كان السبب.
حسنًا، يسمَى المدخل إلى تلك المشكلة
بشكل عام بالاختبار البسيط، رسالة تريد إرسالها إلى ذلك الشخص الآخر.
أنك تريد أن يظهر النص المشفر منه بشكل مثالي،
والتي تكون مشفرة ومشوشة، ومعلومات مشفرة إلى حد ما
وهكذا أي شخص في الغرفة، المعلم مثلاً، لا يمكنه انتزاع دفتر الملاحظات
وقراءة ما ترسله إلى فتى أحلامك أو الشخص الذى تحبه الموجود فى الغرفة،
أو في أي سياق آخر أيضًا.
لكن المشكلة تكمن فى إن كانت الرسالة التي تريد إرسالها،
هى مرحبًا!، إلى صديقنا القديم مع علامة تعجب،
يمكنك تشفيرها في سياقات محددة مثل 72، أو 73،أو 33.
ويمكنني القول أن معظم الفصول الدراسية في الحرم الجامعي إذا كتبت على قطعة من الورق 72،
73، 33، ومررتها خلال الغرفة، ومهما اعترضها الأستاذ الجامعي،
فلن يفهم ما تقوله على أى حال.
لكن هذا ليس نظامًا جيدًا.
هذا ليس نظام تشفير.
لماذا؟
لأنه ليس آمنًا.
[INAUDIBLE]
[INTERPOSING VOICES]
ديفيد ج. مالان: أجل.
أي شخص يستطيع الوصول إلى هذا، أليس كذلك، طالما
كما كنتم تحضرون الأسبوع الأول مثلاً أو صفر من CS50، أو أن
لديكم معرفة عامة بـ Ascii.
مثل هذا مجرد شفرة ما.
أعني أن Ascii هو نظام يقوم بتعيين الأحرف إلى أرقام.
وأي شخص آخر يعرف تلك الشفرة فمن الواضح
أنه يعرف ما هي رسالتك، لأنه ليس سرًا فريدًا من نوعه
لك والمتلقي.
إذًا ربما هذه ليست أفضل فكرة.
حسنًا، يمكنك أن تكون أكثر تطورًا قليلاً.
وترجع هذه-- فى الواقع إلى كونها، صورة
من الحرب العالمية الأولى لرسالة أُرسلت من ألمانيا إلى المكسيك
تم تشفريها بطريقة مشابهة جدًا.
ولم تكن تستخدم Ascii.
والأرقام ،التي يمكنك استخلاصها من الصورة،
هي في الواقع أكبر من ذلك بكثير.
ولكن في هذا النظام، في السياق العسكري، كان هناك كتاب شفرات.
مشابهة جدًا في جوهرها للـ Ascii، حيث لديك
عمود من الأرقام وعمود من الأحرف التي تتوافق معها،
كتاب الشفرات الذي بشكل عام يحتوي على أرقام مثلاً، ثم ربما
حروف أو كلمات كاملة حتى تتوافق معها،
وأحيانًا الآلاف منهم، يكون حرفيًا كتابًا كبيرًا جدًا عن الشفرات.
وطالما فقط، في هذا السياق أن الألمان والمتلقين،
المكسيكيين، توّصلوا إلى الكتاب نفسه،
يمكنهم التعمية وفك التعمية، أو بالأحرى تشفير وفك تشفير المعلومات.
بالطبع، في هذا السياق المحدد للغاية--
يمكنك قراءة المزيد حول هذا في النصوص التاريخية--
تم اعتراض هذا.
هذه الرسالة، على ما يبدو ليست خطرًا، رغم أنها بالتأكيد
تبدو مثيرة للشكوك مع كل هذه الأرقام،
إذًا، هى خطر، قام البريطانيون، في هذه الحالة بالفعل، باعتراضها.
وبفضل العديد من المجهودات وتحليل الشفرات،
تم كسر نمط التعليمات البرمجية لحديقة بلتشلي، وإن كانوا حينها،
قادرين على اكتشاف ما تمثله الأرقام من كلمات
وفك تشفير الرسالة في الواقع.
في واقع الأمر، إليكم صورة لبعض الكلمات
التي تم ترجمتها من لغة إلى أخرى.
ولكن المزيد حول هذا على الإنترنت أو المراجع النصية.
اتضح أن هذه القصيدة أيضًا كان بها تعليمات برمجية مماثلة، أليس كذلك؟
إذًا بمناسبة وجودكم فى بوسطن هنا، قد تتذكرون هذا.
"انصتوا يا أطفالي، وسأقص عليكم قصيدة "رحلة منتصف الليل لبول ريفير".
في 18 أبريل لعام '75، رجل بالكاد
يحيا الآن ويتذكر هذا اليوم والسنة المشهورين.
فقال لصديقه، إذا كانت الجيش البريطاني يسير براً أو بحراً
من المدينة مساء الليلة، فعلق مصباحًا
عاليًا فى قنطرة جرس برج الكنيسة الشمالية كإشارة ضوئية،
واحدًا إذا كان عبر البر، واثنين إذا كان عبر البحر.
وسأكون على الشاطئ الآخر مستعدًا للمضي ودق
ناقوس الخطر فى كل قرية ومزرعة لأهل "ميدلسكس"
ليتأهبوا ويستعدوا."
إذًا اتضح أن بعض هذا ليس صحيحًا البتة في الواقع،
ولكن شفرة واحد إذا كانوا عبر البر واثنين عبر البحر كانت
مثالاً لشفرة المرة واحدة نوعًا ما.
لأنه إذا كان الثوار في الثورة الأمريكية
قرّروا سرًا نوعًا ما بين أنفسهم حرفيًا - سنضع
مصباحًا واحدًا على رأس الكنيسة إذا جاء البريطانيون برًا.
وسنستخدم بدلاً من ذلك اثنين إذا كان البريطانيون قادمين عن طريق البحر.
مثل هذا يعد شفرة ما.
ويمكنكم كتابتها فى كتاب ما، إلا إذا كان لديكم كتاب الشفرة.
ولكن بالطبع، بمجرد أن يكتشف شخص ما هذا النمط،
فسيكون تم اختراقه.
وهكذا فإن كتب الشفرة لا تميل إلى تكون الآليات الأقوى
لتشفير المعلومات.
بدلاً من ذلك، من الأفضل استخدام شيء خوارزمي أكثر.
ومن الرائع، في علم الحاسوب وجود هذا الصندوق الأسود
لكي-- نظل نقول إنه، موطن الخوارزميات.
وبشكل عام، لديّ التشفير مشكلة مع المدخلات والمخرجات،
لكننا نحتاج فقط إلى مُدخل واحد إضافي.
المُدخل هو ما يسمّى عمومًا المفتاح، أو السر.
والسر قد يكون مجرد رقم.
فعلى سبيل المثال، إذا أردت أن يكون سرّي رقم 1،
لأننا سنبقي على المثال فى شكل مبسط، ولكن حقًا يمكن أن يكون أي رقم.
وبالفعل، رأينا فى الصورة منذ لحظات،
استخدام الألمان لأكبر من هذا، وإن كان ذلك في سياق الشفرات.
افترضنا أنكم تريدون الآن إرسال رسالة أكثر خصوصية إلى شخص ما
عبر الغرفة في الفصل هى، أنا أحبك.
كيف تقوم بتشفير ذلك بطريقة ما لا تستخدام مجرد Ascii
ولا تستخدم مجرد بعض كتب التشفير البسيطة؟
حسنًا، دعوني أفترض الآن أننا فهمنا كيف يتم تمثيل السلاسل،
صحيح-- نحن حقًا على وشك أن نسفه ونقلل من قيمة الحب--
إذًا حتى الآن قد عرفتم كيفية تمثيل السلاسل بشكل حسابي،
حسنًا، دعونا فقط نبدأ بتمثيل جملة "أنا أحبك" في Ascii.
إذًا I تكون 73.
L تكون 76.
O-V-E Y-O-U. هذا هو Ascii.
لا ينبغي إرسالها بهذه الطريقة، لأن أي شخص
يعرف Ascii سيمكنه معرفة ما تقوله.
ولكن ماذا لو قمت بتشفير هذه الرسالة، وقمت بتطبيق خوارزمية عليها؟
وفى أبسط الأحوال، يمكن أن تكون الخوارزمية
رياضيات- عملية حسابية بسيطة، كما رأينا.
أتدرون، دعوني فقط أستخدم المفتاح السري لديّ رقم 1.
ودعوني أتأكد أن فتى أحلامي يعرف أنني أستخدم القيمة السرية لرقم 1.
إذًا هو أو هي أيضًا يدرك تلك القيمة.
وقبل أن أبعث رسالتي، سأقوم بإضافة رقم 1 إلى كل حرف.
إذًا، 73 يصبح 74.
76 يصبح 77.
80 و87 و70 و90 و80 و86.
الآن يمكن إرسال هذا بشكل واضح.
ولكن لاحقًا، يمكنني فى الواقع إرساله كرسالة نصية.
إذًا دعونا نرجعه إلى Ascii.
74 أصبح الآن j. و77 أصبح الآن M. و80 أصبح الآن P. وربما يمكنك أن ترى النمط.
هذه الرسالة كانت، أحبك.
والآن، أعتقد أن جميع الأحرف خطأ بمقدار 1، على ما أظن.
I أصبح J. وL أصبح M. وO أصبح P، وهكذا.
إذًا الادعاء سيكون، مشفرًا، سأقوم
بإرسال تلك الرسالة عبر الغرفة.
والآن لن يتمكن أي شخص لديه كتاب الشفرات من فكها.
لا يمكنني سرقة الكتاب وفك شفراتها،
لأن المفتاح الآن هو فقط في عقلي، إذا جاز التعبير.
إنه فقط الرقم 1 الذي هو أو هي وأنا
تعين علينا الاتفاق عليه مسبقًا أننا سنستخدمه
لإرسال رسائلنا السرية.
لذا إذا التقط شخص ما هذه الرسالة، المعلم في الفصل أو أي شخص،
كيف يمكنهم محاولة فكها أو حل رموز تلك الشفرة؟
هل هناك أي أساليب متاحة لهم؟
يمكنني القول أنه يمكننا نوعًا ما الكشف عما بداخل مذكرة الحب تلك.
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: ماذا؟
طريقة التخمين والتحقق.
حسنًا، يمكننا تجربة كل--
ما يزال هناك بعض التباعد نوعًا ما.
إذًا تدركون حقًا، أنه يمكننا القيام بتحليل شفرتها نوعًا ما،
تحليل التكرار.
مثل، أنه لا يمكنني التفكير في الكثير من الكلمات باللغة الإنجليزية
التي تحتوي على حرف واحد فيها.
إذًا ما الذي تمثله J على الأرجح؟
[INTERPOSING VOICES]
ديفيد ج. مالان: I، ربما.
ربما A، ولكن ربما I. وليس هناك الكثير من الخيارات الأخرى.
لذلك تجسسنا على جزء واحد الرسالة بالفعل.
أرى القواسم المشتركة.
هناك اثنان من ماذا هنا؟
اثنان P. ولا أعرف بالضرورة أنها تمثل O، ولكن
أعلم أنه الحرف نفسه.
لذلك إذا واصلت تلك العملية المدروسة أو هذا الاختبار والخطأ،
واكتشفت، أوه، ماذا لو كان هذا هو حرف O؟
وذاك O. ثم لحظة من فضلكم.
إنهم ينتقلون من واحد إلى آخر.
ربما يعطي هذا، أنا أحبك.
مثل لو كنت بالفعل تستطيع، مع بعض الاحتمالات،
فك تشفير رسالة ما من خلال تحليلها بهذه الطريقة نوعًا ما.
إنها على الأقل أكثر أمانًا من كتاب الشفرات،
لأنك لن تتعرض للاختراق إذا كان الكتاب نفسه مسروقًا.
ويمكنك تغيير المفتاح فى كل مرة، طالما اتفقت
أنت والمتلقي على شيء ما بالفعل.
لكن على الأقل وضعنا الآن هذه الآلية في الحسبان.
إذًا مجرد فهمك لما يمكنك القيام به مع السلاسل،
هل يمكنك في الواقع الآن القيام حقًا بأشياء مثيرة للاهتمام في المجال المحدد
لهم؟
في الواقع، سابقًا، القيصر، سابقًا في الأوقات العسكرية حقًا
استخدم تشفير مثل هذا تمامًا.
وبصراحة، عندما تكون الأول في استخدام هذه التشفيرات،
فهي في الواقع آمنة نوعًا ما، حتى لو كانت بسيطة نسبيًا.
لكن آملاً، عدم استخدام مفتاح 1، فقط، ربما 2، أو 13، أو 25،
أو شيءٍ أكبر.
لكن هذا مثال عن الشفرة البديلة،
أو الشفرات الدائرة حيث كل شيء نوعًا ما يدور--
A تصبح B ،B تصبح C. أو يمكنك نوعًا ما
تدويرها بصورة أكبر من ذلك.
حسنًا، دعونا نلقي نظرة على مثال أخير هنا
لميزةٍ واحدةٍ أخرى بدائية ونهائية
اليوم، قبل أن نرجع للوراء إلى مستوى أعلى ونجمع كل شيءٍ معًا.
يتضح أن طباعة رسائل الخطأ
ليست الطريقة الوحيدة للإشارة إلى أن شيئًا ما قد حدث بشكلٍ خاطئ.
هناك كلمة رئيسية جديدة، استخدام جديد لكلمة رئيسية قديمة في هذا المثال،
وهو في الواقع تقليد للإشارة إلى الأخطاء.
إذًا هذا مثال يُسمى exit.c.
ويبدو أنه يريد الإنسان أن يفعل ماذا، إذا استنتجنا من التعليمات البرمجية؟
الجمهور: خروج، [INAUDIBLE].
ديفيد ج. مالان: نعم.
كررها؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان، حسنًا، إنه يريد-- حسنًا ماذا
تريد أن يفعل الإنسان ضمنيًا، استنادًا إلى printf هنا؟
كيف يمكنني تشغيل هذا البرنامج؟
أجل؟
الجمهور: [INAUDIBLE] فقط قم بتطبيق [INAUDIBLE]..
ديفيد ج. مالان: نعم.
لذا لأي سبب من الأسباب، هذا البرنامج ضمنيًا
يريد مني أن أكتب بالضبط كلمتين في المُحث.
لأنه إذا لم أفعل ذلك، فسيصرخ في وجهي، أنه يفتقد وسيطة سطر الأوامر.
ثم سيرجع 1، أيًا كان ذلك.
وبخلاف ذلك، سوف يقول، أهلاً، كذا وكذا.
إذًا إذا قمت بالفعل بتشغيل هذا البرنامج--
فاسمحوا لي بالعودة هنا وكتابة make exit--
عذرًا، في دليلي، make exit.
حسنًا، نقطة خط مائل exit، enter، أنا أفتقد وسيطة سطر الأوامر.
حسنًا، اسمحوا لي بوضع اسم Zamyla.
أوه، Hello Zamyla.
اسمحوا لي بوضع Zamyla Chan.
لا، أنا أفتقد وسيطة سطر الأوامر.
يريد فقط وسيطة واحدة، حتى في هذه الحالة هنا.
أنا أرى بصريًا رسالة الخطأ، لكن من الواضح أن
الكمبيوتر يعطي إشارة لي بما يسمى تعليمات الإنهاء البرمجية.
إذن فالقصة الطويلة باختصار، أننا شاهدنا أمثلة بالفعل الأسبوع الماضي عن الطريقة
التي يمكنك بها الحصول على دالة لإرجاع قيمة.
ورأينا كيف [؟إيرين؟] جاء على خشبة المسرح،
وأعادت لي قصاصة ورق مع سلسلة عليها.
لكن من الواضح أن main هو خاص قليلاً.
إذا قامت main بإرجاع قيمة مثل 1 أو 0، فيمكنك بالفعل رؤية ذلك،
وإن كان بطريقة غير واضحة نوعًا ما.
إذا قمت بتشغيل exit، وقمت بتشغيلها بشكل صحيح باستخدام Zamyla كاسم،
إذا قمت بعد ذلك بكتابة echo، علامة الدولار، علامة استفهام، لجميع الأشياء،
enter، سأرى بعد ذلك بالفعل ما الذي عادت به main، وهي في هذه الحالة 0.
الآن، اسمحوا لي بالمحاولة وأكون غير متعاون.
إذا قمت بالفعل بتشغيل نقطة خط مائل exit، بدون كلمة،
سأرى، أنا أفتقد وسيطة سطر الأوامر.
لكن إذا قمت بالأمر المشفر نفسه، echo، علامة الدولار، علامة استفهام،
سأرى أن main خرجت بـ 1.
الآن، لماذا هذا مفيد؟
حسنًا، عندما بدأنا نكتب برامج أكثر تعقيدًا،
سيكون من المتعارف عليه الخروج من main بإرجاع
قيمة غير صفرية، إذا حدث خطأ ما.
ينتج 0 ليعني أن كل شيء سار بشكل جيد.
وفي الواقع، في كل البرامج لدينا
تمت كتابة هذا حتى الآن، إذا لم تذكر إرجاع أي شيء،
فسترجع main تلقائيًا لك 0.
ولقد كان ذلك طوال هذا الوقت.
إنها مجرد ميزة، لذا فلا تزعج نفسك بكتابتها.
ولكن اللطيف في ذلك، أو ما هو حقيقي بشأن ذلك،
هو إذا كان على جهاز الكمبيوتر الشخصي أو Mac لديك، إذا واجهت أي رسالة خطأ مزعجة
تقول، خطأ سلبي 29، حدث خطأ في النظام، أو شيء ما توقف،
لكنك غالبًا ما ترى أرقام على الشاشة، ربما.
مثل خطأ التعليمات البرمجية هذه والتي تميل إلى الارتباط بهذه الأنواع من القيم.
لذا إذا كان الإنسان يكتب برنامجًا وحدث خطأ ما
وحدث خطأ، فإنها كما هو متوقع تقوم بإرجاع قيمة مثل هذه.
ويحق للكمبيوتر الوصول إليه.
وأن هذا ليس بهذه الفائدة للشخص الذي يقوم بتشغيل البرنامج.
لكن عندما تصبح برامجك أكثر تعقيدًا، سنرى
أن هذا بالفعل مفيد كطريقة لإعطاء إشارة
أنه حدث خطأ ما بالفعل.
آه.
حسنًا، إنها صيغ كثيرة مغلفة في سياق محبب.
أية أسئلة قبل تناول مجال واحد نهائي؟
لا؟
حسنًا.
إذًا من الواضح أنه يمكننا الإجابة على سؤال "من يهتم" بطريقة أخرى
أيضًا.
من الواضح أن-- اسمحوا لي بالمضي قدمًا وفتح مثال لمصفوفتنا مرة أخرى هنا--
يمكن استخدام هذه المصفوفات بالفعل الآن لحل المشاكل بطريقة أكثر خوارزمية.
وهنا تصبح الحياة أكثر إثارة.
لأننا مررنا بشكلٍ لا يصدق بتعقيدات اليوم.
وكلما تقدمنّا في الصف، نحن
لن نمضي الكثير من الوقت في الصيغ،
وعلامات الدولار، وعلامات الاستفهام، والأقواس المربعة، وما شابه ذلك.
هذا ليس جزءًا مثيرًا للاهتمام.
الجزء المثير للاهتمام هو عندما نحصل الآن على هذه الكتل البنائية
الأساسية، مثل مصفوفة، والتي بمكننا من خلالها حل مشاكل.
لذا يتضح أن المصفوفة، أنت تعلم، يمكنك
نوعًا ما التفكير فيها كسلسلة من الخزائن،
سلسلة من الخزانات التي قد تبدو مثل هذا، وبداخلها يوجد
قيم-- سلاسل، أو أرقام، أو حروف، أو غيرهم.
لكن الخزانات هي استعارة ملائمة لأن جهاز الكمبيوتر، على عكس الأشخاص،
يمكنه فقط أن يرى ويفعل شيئًا واحدًا في المرة الواحدة.
يمكنه فتح خزانة واحدة والنظر داخلها، لكن لا يمكنه نوعًا ما
الرجوع خطوة للوراء، كما يمكننا نحن ذلك، والنظر داخل جميع الخزانات،
حتى إذا كانت جميع الأبواب مفتوحة.
لذا يجب أن يكون هناك إجراء متعمد أكثر من ذلك.
لذا ما هي الآثار الفعلية؟
حسنًا، طوال هذا الوقت--
كان لدينا مثال دليل الهاتف في الأسبوع الأول،
وكفاءة تلك الخوارزمية، من العثور على مايك سميث في دليل الهاتف هذا،
جميعنا يفترض ما هي ميزة دليل الهاتف هذا؟
الجمهور: إنه مرتب ترتيبًا أبجديًا.
ديفيد ج. مالان: إنه تم ترتيبه ترتيبًا أبجديًا.
وكان هذا إضافةً كبيرة، لأنني بعد ذلك استطعت الانتقال إلى المنتصف،
واستطعت الانتقل إلى منتصف المنتصف، وهكذا.
وكان هذا ممكنًا خوارزميًا.
على هواتفنا، إذا سحبت جهات الاتصال الخاصة بك،
فستحصل على قائمة من الأسماء الأولى، أو أسماء العائلة، كلها مرتبة ترتيبًا أبجديًا.
هذا لأن، خمن ما هو هيكل البيانات أو التخطيط
الذي ربما يستخدمه هاتفك لتخزين جهات الاتصال الخاصة بك؟
إنها مصفوفة نوعًا ما، أليس كذلك؟
إنها مجرد قائمة.
وقد يتم عرضها عموديًا بدلاً من أفقيًا،
كما رسمتها اليوم.
لكنها مجرد قيم متصلة على التوالي مع بعضهم البعض
والتي يتم تخزينها بالفعل.
لكن كيف أصبحت في ذلك الترتيب المخزن بالفعل؟
وكيف يمكنك بالفعل العثور على قيم؟
حسنًا، دعونا ننظر في ما هي هذا المشكلة بالفعل
للكمبيوتر، على النحو التالي.
دعوني أمضي قدمًا هنا.
هل يمانع أحد المتطوعين فى المجيء إلى هنا؟
يمكنني إهداؤه كرة ضغط.
حسنًا ، شخصًا ما من الخلف؟
حسنًا ، تعال إلى هنا.
تعال.
ما اسمك؟
إريك: إريك.
ديفيد ج. مالان: آرون.
حسنًا.
إذًا سيأتي آرون.
و--
إريك: إريك.
ديفيد ج. مالان: معذرةً؟
أوه، إريك.
تشرفت بمقابلتك.
حسنًا.
تعال هنا.
لذا إريك، الآن وبشكلٍ طبيعي، أود أن أطلب منك العثور على رقم 23.
ولكن هذا يبدو سهلاً قليلاً، يمكنك المضي قدمًا والعثور لنا
على رقم 50 خلف هذه الأبواب، أو حقًا هذه الخزانات الصفراء؟
8؟
كلا.
42؟
كلا.
حسنًا.
جيد جدًا.
هذه ثلاثة، ثلاثة من سبعة.
كيف حصلت عليها بهذه السرعة؟
إريك: قمت بالتخمين.
ديفيد ج. مالان: حسنًا، إذًا لقد خمّن.
هل هذه أفضل خوارزمية كان يمكن أن يستخدمها إريك هنا؟
إريك: ربما لا.
ديفيد ج. مالان: حسنًا، لا أعرف.
نعم؟
لا؟
الجمهور: نعم.
ديفيد ج. مالان: لماذا؟
لماذا نعم؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: ليس لديه معلومات أخرى.
لذا نعم، هذا كان أفضل ما يمكنك القيام به.
ولكن اسمحوا لي أن أقدم لكم القليل من المعلومات.
يمكنك البقاء هنا.
واسمحوا لي بالمضي قدمًا وإعادة تحميل الشاشة هنا.
ودعوني أمضي قدمًا وأسحب مجموعة مختلفة من الأبواب.
والآن لنفترض أن ذلك يشبه إلى حدٍ كبير دليل الهاتف، والكثير من الهواتف
يتم ترتيبها، والآن هذه الأبواب تم ترتيبها.
اعثر لنا على الرقم 50.
حسنًا.
جيد جدًا.
ماذا فعلتَ هذه المرة؟
الجمهور: حسنًا، [INAUDIBLE].
كان 50 هو 116.
لذلك أنا فقط--
ديفيد ج. مالان: حسنًا.
إذًا قفزتَ إلى الوسط في البداية، ثم إلى النصف الأيمن.
ثم من الناحية الفنية-- إذًا نحن بعيدون بمقدار 1 من الناحية الفنية، أليس كذلك؟
لأن البحث الثنائي مثلاً كان سينتقل إلى منتصف الـ--
لا بأس، عمل جيد جدًا يا إريك.
هنا، دعني أقدم لك كرة ضغط كمكافأة.
حسنًا شكرًا لك.
عمل جيد جدًا.
إذًا بهذه المعلومات الإضافية، كما تعلمون،
تمكّن إيرك من الأداء بشكل أفضل لأن المعلومات كانت مُرتبة على الشاشة.
لكن كانت لديه رؤية واحدة فقط لخزانة في كل مرة،
لأنه فقط من خلال الكشف عما بالداخل سيستطيع أن يراه بالفعل.
إذًا هذا يبدو أنه يقترح أنك بمجرد
حصولك على هذه المعلومات الإضافية في مثال إريك، في مثال هاتفك،
في مثال دليل الهاتف، فإنك تتيح الاحتمالات للمزيد، والمزيد من
الخوارزميات الفعّالة.
ولكن للوصول إلى هذا، كنا نؤجل هذا طوال الوقت في الصف الدراسي
كيف يمكنك في الواقع فرز هذه العناصر.
وإذا كنتم لا تمانعون-- بهذه الطريقة، نأمل أن ننتهي على
ملاحظة أكثر حيوية هنا لأنني أعرف أننا أصابنا الملل لبرهة--
هلا حصلنا على ثمانية متطوعين؟
حسنًا، 1، 2، 3، 4-- ماذا عن 5، 6، 7، 8، تعالوا هنا.
أوه، معذرة.
هل تغاضيت تمامًا عن الصف الأمامي؟
حسنًا.
لا بأس، المرة القادمة.
المرة القادمة.
تعالوا إلى هنا.
أوه، وكولتون، هل تمانع في مقابلتهم هنا بدلاً من هناك؟
حسنًا.
تعالوا.
ما اسمك؟
[? كامي: ?] [? كامي. ?]
ديفيد ج. مالان: [؟ كامي؟ ؟] ديفيد.
هناك بالضبط.
ما اسمك؟
مات: مات.
ديفيد ج. مالان: مات؟
ديفيد.
[؟ جوهي:؟] [؟ جوهي. ؟]
ديفيد ج. مالان: [؟ جوهي؟ ؟] ديفيد.
ماكس: ماكس.
ديفيد ج. مالان: ماكس، سعدت بلقائك.
جيمس: جيمس.
ديفيد ج. مالان: جيمس، سعدت بلقائك.
هنا، سأحضر المزيد من الكراسي.
ما اسمك؟
،بيتن: بيتن.
ديفيد ج. مالان: بيتن؟
ديفيد.
واثنين آخرين.
في الواقع هل يمكنكما المجيء إلي هنا؟
ما اسمك.
أندريا: أندريا.
ديفيد ج. مالان: أندريا، سعدت بلقائك.
واسمك؟
[؟ بيكو:؟] [؟ بيكو. ؟]
ديفيد ج. مالان: [؟ بيكو،؟] ديفيد.
سعدت بلقائك.
حسنًا، لدى كولتون قميصًا لكل واحد منكم، وهو على طراز جامعة هارفارد.
وكل واحد من هذه القمصان، التي على وشك أن تروها، عليها رقم ما.
وهذا الرقم هو--
حسنًا، امضوا قدمًا وارتدوهم، إذا لا تمانعون.
حسنًا، شكرًا جزيلاً لكم.
إذًا أعتقد أننا قد رتبنا الأشخاص لدينا مثل الخزائن إلى حد كبير في مصفوفة.
فمثلاً لدينا مجموعة أشخاص، متصلين على التوالي مع بعضهم البعض.
لكن هذا في الواقع نعمة ونقمة،
لأن لدينا فقط ثمانية مقاعد.
إذًا لا يوجد في الحقيقة متسعًا هنا، لذلك سنقتصر على هذه المساحة فقط هنا.
وأرى أن لدينا 4، 8، 5، 2، 3، 1، 6، 7.
هذا رائع.
كأنهم غير مُرتبين.
وحسب التعريف، هذا عشوائي جدًا.
إذًا هذا رائع.
إذًا دعونا نبدأ هكذا.
رتبوا أنفسكم من 1 إلى 8، رجاءً.
حسنًا.
حسنًا، أي خوارزمية كانت تلك؟
[LAUGHTER]
الجمهور: انظروا حولكم، وتبينوا الأمر.
ديفيد ج. مالان: انظروا حولكم، وتبينوا الأمر.
حسنًا، إذًا--
مات: الإبداع البشري.
ديفيد ج. مالان: الإبداع البشري؟
أحسنت للغاية.
إذًا هل يمكننا-- حسناً، معرفة ما الذي كان يدور
في عقولكم؟
مات: العثور على كرسي والجلوس.
ديفيد ج. مالان: العثور على الكرسي--
العثور على الكرسي المناسب.
إذًا الذهاب إلى موقع.
جيد.
إذًا مثل موقع الفهرس، أليس كذلك؟
المصفوفات لديها مؤشرات،إذا جاز التعبير--
0، 1، 2، على النسق نفسه حتى 7.
وعلى الرغم من أن القمصان الخاصة بنا مرقمة من 1 إلى 8،
يمكنك التفكير من حيث 0 إلى 7.
إذًا كان هذا جيدًا.
أي شخص آخر؟
أفكار أخرى؟
[؟ كامي:؟] أعني، هذا شيء كنا نفكر فيه بشكل ضمني،
ولم يخبرنا أحد أن الترتيب من اليمين إلى اليسار.
كان يمكننا الترتيب من اليسار إلى اليمين.
ديفيد ج. مالان: حسنًا.
قطعًا.
كان يمكنكم الانتقال من اليمين إلى اليسار، بدلاً من اليسار إلى اليمين.
ولكننا على الأقل وافقنا جميعًا على هذا الاتفاق
أيضًا، إذًا كان ذلك في عقولكم.
حسنًا.
جيد جدًا.
إذًا حصلنا على هذا الترتيب.
امضوا قدمًا وأعيدوا ترتيب أنفسكم عشوائيًا، إذا سمحتم.
أي خوارزمية كانت تلك؟
مجرد خلط عشوائي؟
حسنًا، هذا جيد.
إذًا يبدو عشوائيًا جدًا.
سيفي بالغرض.
دعونا نرى الآن إذا كان بإمكاننا تقليل عملية الترتيب
إلى شيء حسابي أكثر من ذلك بقليل حتى، أولاً، يمكننا أن نتأكد
أننا على صواب وليست مجرد صدفة أن كل شخص تبين أمره
ولم يُستثنى أحد، وثانيًا،
البدأ في التفكير في مدى كفاءتها، أليس كذلك؟
لأنه إذا كنا نظفر بكفاءة كبيرة لدليل الهاتف،
لجهات الاتصال لدينا، لـ [؟ خطأ؟] التالي،
كان يتعين علينا حقًا أن نسأل طوال الوقت،
بالتأكيد، يمكنكم توفير الوقت بواسطة البحث الثنائي وخوارزمية فرق تسد،
ولكن كم تستغرق لتصل إلى نقطة معينة
حيث يمكنك استخدام البحث الثنائي وخوارزمية فرق تسد؟
لأن الترتيب، إذا كان فائق الثمن وباهظًا للغاية ويستغرق وقتًا طويلاً
ربما يكون سلبيًا تمامًا.
ويمكنكم كذلك البحث في القائمة بأكملها،
بدلاً من ترتيب أي شيء.
حسنًا.
إذًا دعونا نرى هنا.
6 و5، لا أحب هذا.
لماذا؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: من المفترض أن يأتي 6 بعد 5.
وهكذا، هل يمكننا إصلاح هذا، من فضلكم؟
حسنًا.
ثم دعونا نرى.
حسنًا، 6 و1-- آه، لا يعجبني هذا حقًا.
نعم، هل يمكننا إصلاح هذا؟
جيد جدًا.
6 و3، حسنًا، لقد حصلنا على نتيجة غير متكافئة هنا.
إذًا 6 و3، هل يمكننا إصلاح هذا؟
و6-- نعم، حسنًا.
أوه، حسنًا، 6 و7-- جيد.
حسنًا، هذا جيد جدًا.
7 و8، جيد.
8 و4، آسف.
هل يمكننا التبديل هنا؟
حسنًا.
ثم 8 و2؟
هل يمكننا التبديل هنا؟
حسنًا.
دعوني أطرح عليكم سؤالاً بلاغيًا إلى حد ما.
حسنًا، هل انتهيت؟
حسنًا، لا.
من الواضح أنه لا، لكني عالجت بعض المشاكل، أليس كذلك؟
أصلحت بعض التبديلات، والأرقام غير المرتبة.
وفي الحقيقة، أنا-- ذكرني باسمك مجددًا؟
[? كامي: ?] [? كامي. ?]
ديفيد ج. مالان: [؟ كامي،؟] تزحزحت نوعًا ما إلى اليمين هنا، إذا جاز التعبير.
كما لو كنتِ بعيدة نوعًا ما، والآن أنتِ هنا.
ومثل الأرقام الأصغر، نوعًا ما-- نعم 1.
كأنه، يا إلهي، كأنه شق طريقه في هذا الاتجاه.
إذًا الأمور تسير، بشكل منطقي.
وهذا شيء جيد.
أتعلمون ماذا؟
دعوني أحاول إصلاح بعض المشاكل المتبقية.
إذًا 1 و5-- جيد.
أوه 3 و5، هل يمكنكما التبديل؟
5 و6، حسنًا.
6 و7؟
7 و4، هل يمكنكما التبديل؟
حسنًا.
7 و2، هل يمكنكما التبديل؟
والآن، لا يتعين عليّ التحدث مع [؟ كامي؟] مجددًا،
لأننا نعرف أنها في المكان الصحيح.
لذا أنا في الواقع لا يتعين عليّ القيام بالكثير
من العمل هذه المرة، وهذا جيد نوعًا ما.
لكن، هل انتهيت؟
لا، من الواضح لا.
لكن ما هو النمط الآن؟
ما هو الطراز الأساسي؟
إذا قارنت فقط بين زوج من الأشخاص والأرقام،
يمكنني تحسين الموقف نوعًا ما في كل مرة
من خلال تبديلهم فقط، تبدليهم.
وفي كل مرة الآن--
أنا آسف، [؟ بيكو ؟] في مكان رقم 7.
لا يتعين عليّ التحدث معه أكثر من ذلك، لأنه شق الآن
طريقه للوصول إلى القمة.
إذًا رغم أنني أفعل الشيء نفسه مرارًا وتكرارًا،
وأقوم بالتكرار الحلقي مرارًا وتكرارًا فهذا ليس دائمًا أفضل شيء،
طالما كنت تكرر لمرات أقل وأقل، فستتوقف في النهاية،
على ما يبدو.
لأن 6 ستذهب في النهاية إلى المكان المناسب، ثم 5،
ثم 4، وهكذا.
لذلك إذا استطعنا فقط إنهاء هذه الخوارزمية.
جيد.
ليس جيدًا.
حسنًا، 6 و2، ليس جيدًا.
هل يمكنكما التبديل؟
حسنًا، ذكّرني باسمك مجددًا؟
بيتن: بيتن.
ديفيد ج. مالان: بيتن الآن في المكان الصحيح.
لديّ عمل أقل الآن أمامي.
لذا إذا استطعت فقط مواصلة هذه العملية--
1 و3، و3 و5، و4 و5، حسنًا، ثم 2 و5.
ثم، ذكرني باسمك مجددًا؟
مات: مات.
ديفيد ج. مالان: مات الآن في المكان الصحيح.
صار لديّ عمل أقل.
كدنا نصل.
1 و3، و3 و4، و4 و2، هل يمكنكما التبديل.
حسنًا، كدنا ننتهي.
و1 و3، و3 و2، هل يمكنكما التبديل.
جيد.
إذًا هذا مثير للاهتمام.
يبدو أني-- أنتم تعرفون، في المقام الأول،
قارنت نوعًا ما بين سبعة أزواج من الأشخاص.
ثم في المرة التالية، قارنت كم زوجًا من الأشخاص
كحد أقصى؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: 6 فقط، أليس كذلك؟
لأننا كنا قادرين على ترك [? كامي ?].
ثم تمكنا من ترك [? بيكو ?]، ثم بيتن.
وبالتالي فإن عدد المقارنات التي أجريتها أصبح أقل وأقل.
لذا يبدو هذا جيدًا للغاية.
ولكن أتعرف ماذا؟
قبل أن نحلل هذا، هل يمكنكم ترتيب أنفسكم بشكل عشوائي مجددًا؟
تعد أي خوارزمية بشرية جيدة.
دعونا نحاول اتباع نهج واحد آخر، لأن هذا يبدو غير واضح، أليس كذلك؟
كنت أصلح الأمور، ولكن كان يتعين عليّ إصلاحها مرارًا وتكرارًا.
دعوني أحاول تقليل حجم المشكلة
هذه المرة من خلال فقط اختيار الشخص صاحب الرقم الأصغر.
حسنًا، إذًا ما هو اسمك مجددًا؟
[؟ جوهي:؟] [؟ جوهي. ؟]
ديفيد ج. مالان: [؟ جوهي،؟] رقم 2-- هذا رقم صغير جدًا،
إذًا سأتذكر ذلك في نوع المتغير العقلي.
4؟
لا، هذا رقم كبير جدًا.
كبير جدًا.
حسنًا، ذكّرني باسمك مجددًا؟
جيمس: جيمس.
ديفيد ج. مالان: جيمس.
جيمس هو رقم 1.
هذا جيد جدًا.
دعني أتابع التحقق.
حسنًا، جيمس، في المتغيّر العقلي لديّ هو أصغر عدد.
أعلم أنني أريده في البداية.
لذا إذا كنت لا تمانع في المجيء معي.
وأنا آسف، ليس لك مكان بعد الآن.
إذا يمكنك فقط-- أوه، أتدرون؟
هل يمكنكم جميعًا فقط التنحي جانبًا؟
حسنًا، امم، لا أعرف إن كنت أحب ذلك.
هذا كثير من العمل، أليس كذلك؟
نقل كل هذه القيم، دعونا لا نفعل ذلك.
رقم 2، هل تمانعين الذهاب حيث--
حيث--
جيمس: أنا جيمس.
ديفيد ج. مالان: كان جيمس؟
حسنًا، لقد نجحت في جعل المشكلة أسوأ قليلاً نوعًا ما بهذه الطريقة،
الآن، رقم 2 أصبح بعيدًا جدًا عن الهدف.
لكن كان من الممكن أن يحالفني الحظ، وربما كانت هي رقم 7 أو 8.
لذا دعوني أزعم هذا، في المتوسط، مجرد استبعاد الشخص
سيجعل الأمور متساوية نوعًا ما.
لكن جيمس الآن في المكان الصحيح.
تم.
الآن لدي مشكلة مقدارها 7 أشخاص.
إذًا دعوني أختار الشخص التالي صاحب الرقم الأصغر.
4 هو الرقم الأصغر التالي، وليس 8، ولا 5، ولا 7-- أوه، 2.
ليس 3، ولا 6.
حسنًا، إذًا عدتِ إلى اللعبة.
حسنًا، تعالي مجددًا.
وهل يمكننا استبعاد رقم 4؟
وفي تلك الخوارزمية، إذا جاز التعبير، أنا فقط
اخترت بشكل تفسيري أصغر شخص.
أنا لا أقارن الجميع تمامًا بالطريقة نفسها وأبادل بينهم زوجيًا،
أنا أقوم بالمزيد من المبادلات المجهرية.
إذًا سأذهب الآن للعثور على الرقم الأصغر التالي، وهو رقم 3.
إذا تفضلت بالظهور هنا؟
[؟ كامي، ؟] يتعين علينا، للأسف، استبعادك،
لكن هذا يصب في صالحنا.
دعوني أبحث عن الرقم الأصغر التالي، وهو رقم 4.
حسنًا، لقد عدتِ.
تعالي.
بدلي مع رقم 5.
حسنًا، أبحث الآن عن رقم 5.
مهلاً، رقم 5، ها أنت ذا.
حسنًا.
إذًا تعال هنا.
حسنًا، أبحث عن رقم 6.
أوه، 6، بدلوا أماكنكم قليلاً.
حسنًا.
والآن أبحث عن رقم 7.
أوه، 7، إذا أمكنك الذهاب إلى هنا.
لكن لاحظوا، أنا لا أعود للخلف.
وهذا هو المهم.
خطواتي تصبح أقصر وأقصر.
خطواتي المتبقية تصبح أقصر وأقصر.
والآن قمنا بالفعل بترتيب كل هؤلاء الأشخاص.
إذًا طريقتان مختلفتان اختلافًا جوهريًا، لكن كلتيهما مُقارن بطبيعته،
لأنني أقارن هذه الأحرف مرارًا،
وتكرارًا، وأبدلهم إذا كانوا غير مرتبين.
أو في مستوى أعلى، أو أمر عبرهم وأبدلهم مرارًا،
وتكرارًا.
ولكن كم عدد الخطوات التي آخذها كل مرة؟
على الرغم أنني أفعل القليل والقليل ولم أعد للخلف مرة أخرى،
في المرة الأولى، كنت أقوم بمقارنات مثل n ناقص 1.
ثم عدت إلى هنا.
وفي الخوارزمية الأولى، توقفت عن المضي قدر الإمكان نوعًا ما.
في الخوارزمية الثانية، أنا فقط لم أعد للخلف قدر الإمكان نوعًا ما.
إذًا كانت مجرد طريقة مختلفة نوعًا ما للتفكير في المشكلة.
ولكن بعد ذلك ماذا فعلت؟
سبع مقارنات مثلاً؟
ثم ستة، ثم خمسة، ثم أربعة، ثم ثلاثة، ثم اثنتين، ثم واحدة.
إنها تصبح أصغر، ولكن كم عدد المقارنات في المجمل؟
لقد حصلت مثلاً على n أشخاص n هو رقم.
الجمهور: [INAUDIBLE]
دايفيد ج. مالان: ليس بدرجة السوء نفسها كالمتغيرات.
سنكون هنا طوال اليوم.
لكنها كبيرة.
إنها كبيرة.
دعونا-- نقدم عاصفة من التصفيق، رجاءً، لمتطوعينا.
يمكنكم الاحتفاظ بالقمصان، إذا رغبتم، كتذكار.
[APPLAUSE]
شكرًا جزيلاً لكم.
دعوني أرى ما إذا كان بامكاننا تحديد ذلك-- شكرًا جزيلاً لكم--
ونرى كيف وصلنا في الواقع إلى هذه النقطة.
إذا مضيت قدمًا ولم أسحب خزائننا، وإنما إجاباتنا هنا،
دعوني أقول أن ما فعلناه فقط كان في الأساس خوارزميتين.
واحدة تُسمي "bubble".
وكنت أتعمد نوعًا ما إقحام الكلمة هناك.
"Bubble sort" هو فقط ترتيب مُقارن، زوج مقابل زوج،
لإصلاح الأخطاء الصغيرة.
لكننا بحاجة إلي القيام به مرارًا وتكرارًا.
حتى تشكل هذه الخطوات إضافة ما، ولكن يمكننا التعبير عنهم كتعليمات برمجية زائفة.
لذا في التعليمات البرمجية الزائفة-- يمكنك كتابة أي عدد من الطرق--
قد أفعل ما يلي فقط.
فقط أستمر في القيام بما يلي، حتى لا يكون هناك مبادلات متبقية--
من i من 0 إلى n -2، وn هو العدد الإجمالي للأشخاص.
n -2 تمثل قول اذهب من هذا الشخص إلي هذا الشخص،
لأنني أرغب فى مقارنته أو مقارنتها مع الشخص الذي بجانبه/بجانبها.
لذا لا أريد فعل هذا دون قصد.
هذا هو السبب أن n -2 في النهاية هنا.
ثم أريد أن أمضي قدمًا، إذا كانت العناصر i وi +1
غير مرتبة، فقم بتبديلهم.
ولهذا السبب كنت أطلب من الأشخاص المتطوعين تبديل أماكنهم.
وأستمر فقط فى متابعة ذلك، حتى لا يتبقى أحد للتبديل.
وبحسب التعريف، يكون قد تم ترتيب الجميع.
بينما، تحتوي الخوارزمية الثانية على الاسم التقليدي "selection sort".
"selection sort" هو حرفيًا حيث تقوم حقًا
بتحديد أصغر شخص، أو رقم يهمك، بشكل حدسي،
مرارًا وتكرارًا.
ويصبح الرقم أكبر، لكنك
تبدأ بتجاهل الناس الذين وضعتهم بالفعل في أماكنهم.
وبالتالي فإن المشكلة، بالمثل، تصبح أصغر وأصغر.
تمامًا مثل "bubble sort"، كانت تصبح مرتبة أكثر فأكثر.
قد تبدو التعليمات البرمجية الزائفة لـ "selection sort" هكذا.
For i from 0 to n -1، إذًا هذا 0 في مصفوفة.
وهذا هو n -1.
فقط استمروا في البحث عن أصغر عنصر بين هذين الكرسيين،
ثم أخرجوا هذا الشخص.
ثم فقط استبعدوا من هناك أيًا كان-- بدلوهم،
ولكن ليس بالضرورة جانبًا، فقط بعيد قدر ما هو ضروري.
وبهذه الطريقة، أدير ظهري إلي المزيد والمزيد من الناس
لأنهم أصبحوا في مكانهم.
إذًا هناك إطاران مختلفان للمشكلة،
ولكن اتضح أن كليهما في الواقع لديه عدد الخطوات نفسه، المعطاة أو المأخوذة.
اتضح بشدة أنهما عدد الخطوات نفسه،
رغم إنهما طريقتان مختلفتان للتفكير حول هذا الموضوع.
لأني إن فكرت في "bubble sort"، التكرار الأول، على سبيل المثال،
ما الذي فقط-- فعلاً، حسنًا، دعونا حتى نفكر في "selection sort".
في "selection sort"، كم عدد المقارنات التى تعين عليّ فعلها؟
حسنًا، بمجرد عثوري على عنصري الأصغر،
كان لزامًا عليّ مقارنته بالجميع.
إذًا هذه n -1 مقارنة في المرة الأولى.
إذًا n -1 على اللوحة.
ثم يمكنني تجاهلها، لأنها أصبحت ورائي الآن.
إذًا الآن كم عدد المقارنات المنتهية من n من الأشخاص لديّ؟
n -2، لأنني قد طرحت واحدة.
ثم مجددًا، n -3، ثم n -4، بنفس النسق إلي أن يتبقى شخص واحد.
لذا سأعبر عن هذا النوع بشكل عام، رياضيًا، هكذا.
إذًا n -1 زائد n -2 زائد أيًا كان زائد مقارنة واحدة أخيرة، أيًا كانت هذه.
واتضح أنه في الواقع إذا قرأت الجزء الخلفي من كتاب الرياضيات
أو كتب الفيزياء المدرسية الخاصة بك حيث لديهم تلك الأوراق المرجعية
بشأن ما تكون عليه تلك التكرارات، اتضح أن n -1 زائد n -2 زائد n -3
وما إلى ذلك يمكن التعبير عنهم بشكل أكثر إيجازًا
كحرفيًا فقط n ضرب n ن-1 مقسومًا على 2.
وإذا لم تتذكر ذلك، لا بأس.
أنا دومًا ما أراجع هذه الأمور أيضًا.
لكن هذا صحيح-- حقًا.
إذًا ما الذي يعادله هذا؟
حسناً، إنه مثل n تربيع ناقص n، إذا ما ضربته فقط.
ثم إذا قمت بقسمة الاثنين، يكون
n تربيع مقسومًا على 2 ناقص n على 2.
إذًا هذا هو العدد الإجمالي للخطوات.
ويمكنني بالفعل إدخال هذا فيه.
يمكننا إدخال 8، والقيام بالحسابات، والحصول على العدد الإجمالي للمقارنات
التي كانت حرفيًا تزعجني نوعًا ما.
إذًا هل هذا أمر كبير؟
امم، يبدو الأمر كما لو أنه مرتب بتربيع n.
وفي الحقيقة، عالم الكمبيوتر، عند تقييمه
فعالية خوارزمية ما، يميل إلى عدم الاهتمام كثيرًا
بالقيم الدقيقة.
كل ما سنهتم به هو المصطلح الأكبر.
ما هي القيمة التي تتوصل إليها في الصيغة
التي تهيمن على المصطلحات الأخرى، إذا جاز التعبير،
التي لها التأثير الأكبر، خاصةً أن n تصبح أكبر وأكبر؟
الآن، لماذا هذا؟
حسنًا، دعونا نوعًا ما نجري برهانًا على المثال، إذا صح التعبير.
إذا كان هذا هو التعبير، من الناحية الفنية، لكني
أزعم أن، آه، إنها قريبة بما يكفي لنقول
في ترتيب، رمز O الكبير لـ n تربيع، إذا جاز التعبير، دعونا نستخدم مثالاً.
إذا كان هناك مليون شخص على خشبة المسرح، وليس فقط ثمانية،
فستكون الحسابات تقريبًا مليونًا مربعًا
مقسومًا على خطوتين ناقص مليون مقسومًا على 2، الإجمالي.
إذًا فماذا سينتج هذا في الواقع؟
حسنًا، هذه 500 مليار ناقص 500,000.
وماذا سينتج هذا في الواقع؟
حسنًا، هذه 499 مليار، 999 مليون، 500,000.
هذا قريب للغاية من n تربيع مثلاً.
أعني، أن طرح 500,000 من 500 مليار شىء لا يُذكر.
لذلك أتعلم ماذا؟
أه، إنها في ترتيب n تربيع.
هذا ليس دقيقًا، لكنه في هذا الترتيب العام للمقدار،
إذا جاز التعبير.
وإذًا هذا الرمز، هذا حرف 0 كبير، هو حرفيًا رمز
مُستخدم في علوم الكمبيوتر وفي البرمجة
للوصف بإيجاز،
وباستخدام بعض الحدس والخوارزمية الجيدة، مدى سرعة أو بطء خوارزميتك.
واتضح أن هناك طرق مختلفة لتقييم الخوارزميات
مع صيغ مماثلة متنوعة فقط.
n تربيع تصادف أن تكون الوقت الذى استغرقه كلُ من bubble sort
وselection sort.
إذا قمت حرفيًا بعدّ كل الأعمال
التى قمنا بها على خشبة المسرح مع متطوعينا،
سيكون حوالي n تربيع، 8 تربيع، أو 64 خطوة، معطاة أو مأخوذة،
لجميع هؤلاء الأفراد.
وسيكون هذا خارج السياق بشكل ملحوظ.
هناك كمية لا بأس بها من خطأ التقريب هناك.
ولكن إذا كان لدينا مليون متطوع على خشبة المسرح،
إذًا سيصبح خطأ التقريب مهملاً جدًا.
لكننا رأينا بالفعل بعض من ترتيبات المقدار الأخرى،
إذا جاز التعبير، مسبقًا.
على سبيل المثال، عندما أحصينا شخصًا ما، أو بحثنا عن مايك سميث بقلب صفحة واحدة
في كل مرة، سمّينا هذا خوارزمية خطية.
وكان ذلك حرف O كبير لـ n.
إذًا، إنها في ترتيب خطوات n.
إنها 1000.
ربما تكون 999.
أيًا كان.
إنها في ترتيب خطوات n.
كان نهج [؟ twosies ؟] أسرع مرتين، تذكّروا-- صفحتين في كل مرة.
ولكن أتدرون ماذا؟
ما يزال هذا خطي، أليس كذلك؟
مثل صفحتين في آنّ واحد؟
دعوني أنتظر حتى العام القادم عندما تصبح وحدة المعالجة المركزية أسرع
بمرتين، لأن شركة Intel والشركات تستمر في تسريع أجهزة الكمبيوتر.
تكون الخوارزمية في الأساس هي نفسها.
وفي الواقع، إذا رجعتم بالذاكرة إلي الصورة التي رسمناها،
كانت أشكال تلك المنحنيات هي نفسها في الحقيقة.
الخوارزمية الأولى تلك، العثور على مايك بقلب صفحة واحدة فى كل مرة كانت هكذا.
الخوارزمية الثانية العثور عليه كانت هكذا.
فقط الخوارزمية الثالثة، فرق تسد، وتقسيم دليل الهاتف
كانت شكلاً مختلفاً اختلافًا جذريًا.
وعلى الرغم من أننا لم نستخدم هذه الصياغة الخيالية منذ بضعة أسابيع
مضت، تلك الخوارزميات الأولى، صفحة واحدة في كل مرة، صفحتان في كل مرة،
إنهم على ترتيب n.
من الناحية الفنية، نعم، n مقابل n مقسومًا على 2،
لكننا نهتم فقط بالعامل المسيطر، المتغير n.
يمكننا التخلص من كل شيء موجود في المقام،
ويمكننا التخلص من كل ما هو أصغر من المصطلح الأكبر، الذي
وفي هذه الحالة هو n.
وقد ألمحت إلى هذا قبل أسبوعين--
لوغاريتمي.
حسنًا، اتضح أن في أي وقت تقسم شيئًا مرارًا
وتكرارًا، فإنك تحصل على دالة نوع لوغاريتمي
قاعدة log 2 من الناحية الفنية.
ولكن على ترتيب قاعدة log فإن n شائع أيضًا.
الخوارزميات الرائعة هي هذه--
حرفيًا، خطوة واحدة، أو عدد خطوات ثابت من الناحية الفنية.
على سبيل المثال، ما هي الخوارزمية التي قد تكون وقتًا ثابتًا؟
افتحوا دليل الهاتف.
حسنًا، خطوة واحدة.
لا يهم فى الحقيقة كم عدد الصفحات هناك،
سأقوم فقط بفتح دفتر الهاتف.
ولا يختلف هذا بحسب عدد الصفحات.
قد تكون هذه خوارزمية الوقت الثابت، على سبيل المثال.
إذاً، هذا أقل ما يمكن أن تذهب إليه.
ثم هناك مكان ما وليكن فى المنتصف هنا
نتطلع إليه مع بعض الخوارزميات الأخرى.
إذًا فى الحقيقة، دعونا نرى فقط إذا-- لحظة--
دعونا فقط نرى ما إذا كنا بمقدورنا القيام بهذا بإيجاز أكثر.
دعونا نمضي قدمًا ونستخدم المصفوفات في طريقة واحدة نهائية فقط، باستخدام أنواع الدمج.
اتضح أن، باستخدام مصفوفة، يمكننا بالفعل
القيام بأمر كبير للغاية، طالما أننا نتيح لأنفسنا
زوجين من المصفوفات.
إذًا مرة أخرى، عندما نضيف sorting مع bubble sort وselection sort،
فإننا حصلنا على مجموعة واحدة فقط.
كان لدينا ثمانية مقاعد لأفرادنا الثمانية.
ولكن إذا سمحت بوجود 16 مقعدًا مثلاً أو أكثر،
وسمحت لهؤلاء الأشخاص بالتحرك أكثر قليلاً،
سيمكنني بالفعل القيام بما هو أفضل من ذلك باستخدام المصفوفات.
إذاً هذه بعض الأرقام العشوائية التي سنقوم بها بشكل مرئي دون استخدام أى أشخاص.
وهم في مصفوفة، متصلين على التوالي.
ولكن إذا أتحت لنفسي مصفوفة ثانية، سأكون
قادرًا على خلط هذه الأشياء وليس مقارنتهم فقط،
لأن هذه المقارنات وجميع خطواتي صوبهم
التي بدأت تستنفد الكثير من الوقت بالفعل.
إذًا ها هى مصفوفتي.
أتعلمون ماذا؟
تمامًا مثل دليل الهاتف-- مثال دليل الهاتف هذا الذى حصلنا عليه سابقًا
في الأسبوع الأول--
دعوني أعالج نصف المشكلة في وقت واحد ثم أجمع إجابتي نوعًا ما.
إذًا ها هى مصفوفة--
4، 2، 7، 5، 6، 8، 3، 1-- تم ترتيبها بشكل عشوائي.
دعوني أمضي قدمًا وأرتب نصفهم فقط،
تمامًا مثلما بحثت عن مايك في البداية في منتصف دليل الهاتف فقط.
إذًا 4، 2، 7، 5-- لم يتم ترتيبهم.
ولكن أتدرون ماذا؟
هذا يبدو وكأنه ما يزال مشكلة كبيرة للغاية.
دعوني أرتب النصف الأيسر من النصف الأيسر.
حسنًا، الآن أصبحت المشكلة أصغر.
أتعلمون؟
4 و2، ما يزالان غير مرتبين.
دعوني أقسم هذه القائمة الثنائية إلى مصفوفتين صغيرتين، كل واحدة من الحجم 1.
إذًا، ها هنا مصفوفة صغيرة بحجم 1، وأخرى بحجم
7، ولكنهم متصلين على التوالي، أيًا كان.
لكن هذه المصفوفة من الحجم 1، هل تم ترتيبها؟
الجمهور: لا.
ديفيد ج. مالان: معذرةً؟
الجمهور: لا.
ديفيد ج. مالان: لا؟
إذا كان لدى هذا المصفوفة عنصر واحد فقط وهذا العنصر هو 4--
الجمهور: لا يوجد سوى شيء واحد يمكنك القيام به.
ديفيد ج. مالان: نعم، إذًا تم ترتيبها، حسب التعريف.
حسنًا، إذًا تمت.
حققنا بعض التقدم.
الآن، دعوني أقم بتنشيط ذاكرتكم قليلاً.
دعوني أرتب النصف الأيمن من تلك المصفوفة.
إذًا الآن لديّ مصفوفة أخرى من الحجم 1.
هل يتم ترتيب هذه المصفوفة؟
نعم، بغباء نوعًا ما.
يبدو حقًا أنه لا يتعين علينا فعل أي شيء.
نحن فقط نقوم بمحض افتراضات.
بلى، تم ترتيب هذا.
لكن الآن، كان هذا هو النصف الأصلي.
وتم ترتيب هذا النصف.
تم ترتيب هذا النصف.
ماذا لو قمت الآن بدمج هذه الأنصاف المرتبة نوعًا ما؟
لديّ قائمتان بحجم 1--
4 و2.
والآن إذا كان لديّ مساحة تخزين إضافية، إذا كان لديّ مقاعد إضافية،
يمكنني القيام بهذا بشكل أفضل قليلاً.
ماذا إن مضيت قدمًا ودمجت هذين على النحو التالي؟
ستذهب 2 إلى هناك.
ستذهب 4 إلى هناك.
إذًا الآن لقد أخذت قائمتين مرتبتين وأنشئت واحدة أكبر، قائمة أكثر ترتيبًا
فقط عن طريق دمجهما معًا، واكتساب بعض المساحة الإضافية.
الآن، دعوني أقم بتنشيط ذاكراتكم.
كيف وصلت إلى 4 و2؟
حسنًا، لقد بدأت بالنصف الأيسر، ثم بالنصف الأيسر من النصف الأيسر.
دعوني أتولى النصف الأيمن من النصف الأيسر، إذا صح التعبير.
حسناً، دعوني أُقَسم هذا مجدداً.
7، قائمة بالحجم 1، هل تم ترتيبها؟
نعم، ببساطة.
5، هل تم ترتيبها؟
نعم.
7 و5، دعونا نمضي قُدمًا وندمجهما سويًا.
5، بالطبع ، ستذهب إلى هنا.
7، بالطبع، ستذهب إلى هنا.
حسنًا.
الآن، إلى أين وصلنا؟
نحن في الأصل رتبنا النصف الأيسر.
دعونا نرتب الأيمن-- أوه، الأيمن.
معذرةً.
الآن، لدينا النصف الأيسر.
وتم ترتيب النصف الأيمن من النصف الأيسر.
دعونا نمضي قُدمًا وندمج هؤلاء.
لدينا قائمتان الآن بحجم 2--
تم فرز كل من، 2 و4 و5 و7.
إذا قمت الآن بدمج 2 و4 و5 و7، أى عنصر ينبغي أن يأتي أولاً
في القائمة الكبيرة المطولة، بوضوح؟
2.
ثم 4، ثم 5، ثم 7.
لم يكن أمرًا شاقًا.
لكن حسنًا، نحن فقط نستخدم مساحة أكثر قليلاً في مصفوفتنا.
الآن ماذا بعد؟
الآن، دعونا نفعل النصف الأيمن.
مرة أخرى، بدأنا بتناول المشكلة كلها، والقيام بالنصف الأيسر،
والنصف الأيسر من النصف الأيسر، والنصف الأيسر للنصف الأيسر من النصف الأيسر.
والآن سنرجع بالزمن، إذا صح التعبير.
إذًا دعونا نقسم هذا إلى نصفين، ومايزال إلى الآن النصف الأيسر
فى نصفين.
6 تم ترتيبها.
8 تم ترتيبها.
الآن يتعين عليّ دمجهما--
6، 8.
الآن ماذا بعد؟
النصف الأيمن-- 3 و1.
حسنًا، تم ترتيب النصف الأيسر، تم ترتيب النصف الأيمن--
1 و3.
حسنًا، كيف يمكنني الآن دمج هؤلاء؟
6، 8، 1، 3، أي عنصر من الواضح يُفترض أن يأتي أولاً؟
1، ثم 3، ثم 6، ثم 8.
ثم أخيرًا، لديّ قائمتان بحجم أربعة.
دعوني أمنح نفسي مساحة صغيرة أكثر، ومصفوفة أخرى.
والآن دعوني أمضي قدمًا وأضع 1 و2 و3 و4 و5،
و6 و7 و8.
ما الذي حدث للتو؟
لأنه حدث في الواقع كثيرًا بشكل أسرع، رغم أننا كنا نقوم بذلك
كله لفظيًا.
حسنًا لاحظوا، كم عدد المرات التي قام بها كل رقم بتغيير أماكنه؟
حرفيًا ثلاث مرات، أليس كذلك؟
مثل واحد، اثنان، ثلاثة، صحيح؟
انتقلت من المصفوفة الأصلية، إلى المصفوفة الثانية، إلى المصفوفة الثالثة،
إلى المجموعة الرابعة، أيًا كان ما يسمّى.
ثم صارت في مكانها فى نهاية المطاف.
إذًا كان يتعين على كل رقم أن يتحرك واحدة، اثنتين، ثلاثة نقاط.
ثم كم عدد الأرقام هناك؟
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: حسنًا، لقد كانوا بالفعل في المجموعة الأصلية.
كم عدد المرات التي تعين عليهم الانتقال؟
فقط مرة، اثنتين، ثلاثة.
إذًا، كم عدد الأجمالي للأرقام هناك، فقط للتوضيح؟
هناك ثمانية.
إذًا 8 ضرب 3.
إذًا دعونا نعمم هذا.
إذا كان هناك أرقام n، وكل مرة قمنا بنقل
الأرقام التي فعلناها حوالي نصفهم، من النصف، ثم النصف، حسنًا،
كم مرة يمكنك قسمة 8 على 2؟
8 تذهب إلى 4.
4 تذهب إلى 2.
2 تذهب إلى 1.
ولهذا السبب وصلنا للمستوى الأدنى في عنصر واحد، قوائم الحجم 1.
إذًا اتضح أنه كلما قمت بتقسيم شيء إلى النصف، إلى النصف، إلى النصف،
ما هذه الدالة أو الصيغة؟
ليست "power"، هذا سيء.
هذا هو البعد الآخر.
الجمهور: [INAUDIBLE]
ديفيد ج. مالان: إنه لوغاريتم.
إذًا مرة أخرى، اللوغاريتم هو فقط وصف رياضي
لأية دالة تبقيك تقسم شيئاً ما مرارًا وتكرارًا.
إلى النصف، إلى النصف، إلى النصف، إلى الثلث، إلى الثلث، إلى الثلث، أيًا كان هو،
وتعني فقط التقسيم بالكميات النسبية نفسها،
مرارًا وتكرارًا.
ولذا إذا قمنا بتحريك الأرقام ثلاث مرات، أو بشكل عام سجل
مرات n، التي تعني مجدّدًا تقسيمك لأشياء n مرارًا،
وتكرارًا، يمكنك فقط تسميت هذا بسجل n.
ويوجد أرقام n، إذًا قامت أرقام n بنقل
سجل مرات n،الحساب الإجمالي هنا في السؤال
هو واحد من تلك القيم الأخرى فى ورقة الملاحظات لدينا، والتي
تبدو مثل هذا.
في ورقة الملاحظات لدينا، تذكّروا أنه كان لدينا صيغ تبدو مثل هذه،
ليس مجرد n تربيع وn،وlog n و1، لدينا هذا في المنتصف--
n ضرب log n.
إذًا مجدّدًا، إننا نمضي سريعًا نوعًا ما هنا.
ولكن مجدّدًا، كل رقم يتحرك في مواقع log n.
يوجد المجموع الإجمالي لأرقام n.
إذًا n ضرب log n يكون، حسب التعريف، n log n.
ولكن لماذا تم فرز هذا بهذه الطريقة؟
حسنًا log n، تذكّروا في الأسبوع الأول من مثال دليل الهاتف،
المنحنى الأخضر هو بالتأكيد أصغر من n. n كانت الخطوط المستقيمة،
كان log n هو المنحنى الأخضر.
إذًا في الواقع ينتمي هذا إلى كليهما لأن هذا هو n ضرب n.
هذا n.
هذا n ضرب شيء ما أصغر من n.
الآن ما هو الأثر الفعلي؟
حسنًا، إذا كان علينا تشغيل هذه الخوارزميات جنبًا إلى جنب
ومقارنتهم في الواقع بشيء مثل هذا--
دعوني أمضي قدمًا وأقارن هذه الخوارزميات باستخدام هذا العرض التوضيحي هنا--
إذا مضيت قدمًا، وضغطت على تشغيل، سنرى أن الأشرطة في هذا المخطط
هي أفقية في الواقع.
والأشرطة الصغيرة تمثل الأرقام الصغيرة،
الأشرطة الكبيرة تمثل الأرقام الطويلة.
ثم يقوم كل واحد منهما بتشغيل خوارزمية مختلفة-- selection
sort على اليسار، bubble sort فى المنتصف،
merge sort، كما سنسميها الآن، على اليمين.
وإليك كم يستغرق كل واحد منهم لترتيب هذه القيم.
ما تزال Bubble مستمرة.
ما تزال Selection مستمرة.
وهذا هو الاختلاف الملموس، وإن كان هناك عرض توضيحي صغير،
بين n تربيع وشيء مثل log n.
إذًا ماذا فعلنا هنا؟
نحن، حقًا للغاية مشغولين بتفاصيل ما يمكن أن تقوم به المصفوفة في الواقع
لنا وما هي العلاقات مع السلاسل، لأن كل ذلك
يقلل من اتصال الأشياء مع بعضها على التوالي.
ولكننا سنعود الآن نوعًا ما وسنتابع
باستمرار هذا المسار في المرة القادمة ليمكنني
التحدث على مستوى أعلى بكثير حول ما يجري في الواقع.
ويمكننا الآن التحدث فى هذا بتعمق، من خلال تطبيق
نوع آخر من أشكال الوسائط إلى هذه الأنواع نفسها من الأسئلة.
وسنستنتج أنه يستغرق حوالي 60 ثانية.
هذه الأشرطة عمودية، بدلاً من أن تكون أفقية.
وما سترونه هنا هو تصور
ترتيبات مختلفة لخوارزميات، من بينهم selection sort،
وbubble sort، وmerge sort،وكل ترتيبات البقية، كل منهم
لديه صوت مختلف له بسبب السرعة
والنمط الذي تعمل من خلاله بالفعل.
إذًا دعونا نلقي نظرة سريعة.
[VIDEO PLAYBACK]
[MUSIC PLAYING]
هذا هو bubble sort.
ويمكنكم رؤية أن العناصر الكبيرة تتزحزح بالفعل إلى الأعلى.
[؟
ويمكنكم سماع [؟ صوت توالي الدورات نوعًا ما،
أو الدورة التي تدور فيها.
وهناك عمل قليل للغاية للقيام به، حتى تقريبًا--
هذا هو selection sort الآن.
إذًا يبدأ بشكل عشوائي، لكننا نواصل اختيار الأفراد أصحاب العدد الأصغر
أو، في هذه الحالة، الشريط الأقصر.
وسترى هنا أن الأشرطة ترتبط بالتردد بشكل واضح.
إذاً هي تصبح أعلى وأعلى وأطول وأطول.
هذا هو merge sort الآن تذكّروا، الذي، يقسم الأشياء إلى أنصاف،
ثم أنصاف الأنصاف، ثم يدمج تلك الأنصاف.
إذًا قمنا بعمل الجزء الأيسر كله، وتقريبًا عمل الجزء الأيمن كله.
هذا الجزء ممتع جدًا.
[LAUGHS]
هذا شيء يسمّى [؟ nom ؟] sort, ويقوم بتحسين الأمور.
ليس مثاليًا تمامًا، ولكنه دائمًا ما يحقق تقدمًا للأمام،
ثم الرجوع للخلف على نحو مضاعف نوعًا ما ومحو الأشياء.
[END PLAYBACK]
آه.
كان هذا كثيرًا.
دعونا نتوقف هنا.
سأبقى هنا لبعض الوقت من أجل الأسئلة الفردية.
حسنًا أراكم المرة القادمة.
[APPLAUSE]