اذهب إلى المحتوى

سامح أشرف

الأعضاء
  • المساهمات

    2934
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    56

كل منشورات العضو سامح أشرف

  1. يمكنك أن تقوم بعمل عنصر جديد من خلال التابع new_tag ثم تقوم بإضافة العنصر العناصر الأبناء إليه، كالتالي: from bs4 import BeautifulSoup soup = BeautifulSoup('<p> sometexthere </p>', features='lxml') # إنشاء العناصر div_element = soup.new_tag('div', **{"class":"container"}) # يمكنك أن تضيف خصائص أيضًا من هنا i_element = soup.new_tag('i') # إحاطة النص بالعنصر i soup.p.string.wrap(i_element) # إضافة كل العناصر إلى العنصر div الذي قمنا بإنشائه body_children = list(soup.body.children) for child in body_children: div_element.append(child) # إزالة كل العناصر من جسم الصفحة soup.body.clear() # إضافة العنصر div الذي يحتوي على كل العناصر إلى جسم الصفحة soup.body.append(div_element) print(soup.prettify()) """ <html> <body> <div class="container"> <p> <i> sometexthere </i> </p> </div> </body> </html> """
  2. يمكنك أن تقوم بهذا الأمر من خلال الدالة std::transform، على النحو التالي: #include <algorithm> #include <string> #include <iostream> int main() { std::string str = "HELLO, WORLD"; std::transform(data.begin(), data.end(), data.begin(), [](unsigned char c) { return std::tolower(c); }); std::cout << str; // hello, world } بهذا الشكل سوف يتم تغير محتوى المتغير str إلى أحرف صغيرة. ويمكنك أيضًا أن تستخدم التابع to_lower من مكتبة boost بشكل أسهل، كالتالي: #include <boost/algorithm/string.hpp> #include <iostream> std::string str = "HELLO, WORLD"; boost::algorithm::to_lower(str); std::cout << str; // hello, wolrd
  3. يمكنك أن تقوم بعمل دالة left-trim ، كالتالي: const char* wihte_spaces = " \t\n\r\f\v"; // إزالة المسافات الزائدة من بداية النص std::string& ltrim(std::string& str, const char* ws = wihte_spaces) { str.erase(0, str.find_first_not_of(ws)); return str; } تقوم الدالة السابقة بإستقبال النص كمدخل لها وتعيد نفس النص بعد إزالة المسافات الزائدة من بدايته، لاحظ كيف تم إستخدام الثابت wihte_spaces والذي يحتوي على كل أشكال المسافات، وفي الدالة نفسها نقوم بحذف كل هذه المسافات من البداية (index 0) ويمكن إستخدام نفس الطريقة لعمل دالة rtrim: std::string& rtrim(std::string& str, const char* ws = wihte_spaces) { str.erase(str.find_last_not_of(ws) + 1); return str; } تقوم هذه الدالة بحذف المسافات من نهاية النص، لاحظ كيفية إستخدام التابع find_last_not_of وإضافة 1 إلى القيمة المرجعة. الآن يمكنك أن تقوم ببساطة عمل دالة تسمى trim تقوم بتنفيذ الدالتين السابقتين، على النحو التالي: // ستقوم هذه الدالة بحذف المسافات من بداية ونهاية النص المدخل إليها std::string& trim(std::string& str, const char* ws = wihte_spaces) { return ltrim(rtrim(str, ws), ws); } ستقوم هذه الدالة بإستدعاء كلٍ من ltrim و rtrim ثم إرجاع النص بعد إزالة المسافات من بدايته ونهايته. الآن يمكنك إستخدام الدالة الأخيرة كالتالي: std::string s = " Hello world "; std::cout << trim(s); // Output: "Hello world"
  4. إذا كانت الأرباح يتم توزيعها بناءً على نسبة الإستثمار في المشروع فقط فيمكن حساب نسبة كل فرد من الأرباح كالتالي: إجمالي رأس المال في سؤالك هو 15000 + 10000 + 4000 = 29000 على سبيل المثال، نسبة الشخص الذي دفع 15 ألف تساوي 51.72% من صافي الأرباح كالتالي: (15000/29000)*100 = 51.72% // نسبة الشخص الأول (10000/29000)*100 = 34.48% // نسبة الشخضص الثاني (4000/29000)*100 = 13.79% // نسبة الشخص الثالث هذا بفرض أن المساهمة في المشروع تكون برأس المال فقط.
  5. يمكن القيام بذلك من خلال جلب كل العناصر التي تحتوي على الخاصية class فقط، ثم المرور على هذه العناصر وإستخراج الأصناف منها، بعد ذلك نقومك بإزالة كل الأصناف المكررة من خلال إستخدام set كالتالي: from bs4 import BeautifulSoup import requests URL = "https://en.wikipedia.org/wiki/2019_Ballon_d%27Or" response = requests.get(URL).content soup = BeautifulSoup(response, features='lxml') # إستخراج العناصر التي لديها الخاصية class classes = [tag.get('class') for tag in soup.find_all(class_=True)] # تستطيح القائمة (جعلها تحتوي على عناصر نصية فقط) classes = sum(classes, []) # السطر السابق يمكن عملة كالتالي أيضًا # classes = [item for sublist in classes for item in sublist] # إزالة كل الأصناف المكرر من خلال إستخدام set class_set = set(classes) print(class_set) """ {'printfooter', 'wb-langlinks-edit', ..... 'tocsection-2', 'mw-selflink', 'mw-portlet-interaction'} """
  6. تحويل برنامج بسيط مكون من 5 أسطر مثل هذا سوف يأخذ بعض المجهود الإضافي لإنشاء واجهة رسومية GUI له، حيث يجب أن يتم إستعمال أحد المكتبات الخاصة بالواجهات الرسومية مثل Tkinter (موجودة مسبقًا في Python لذلك لا تحتاج تثبيت أي شيء إضافي)، لذلك يمكن إما جعل البرنامج يتلقى مُدخل من المستخدم من سطر الأوامر مباشرة: # Distance Traveled speed=int(input("Enter Speed: ")) # The distance in 5 hours print("The distance the car will travel in 5 hours is", speed*5, "miles") print("The distance the car will travel in 8 hours is", speed*8, "miles") print("The distance the car will travel in 12 hours is", speed*12, "miles") أو يمكن عمل واجهة كاملة من خلال مكتبة Tkinter وستكون الخطوات كالتالي: في البداية نقوم بعمل نافذة فارغة: import tkinter as tk from tkinter import * class App(tk.Frame): def __init__(self, master): super().__init__(master) root = tk.Tk() # تغير عنوان النافذة root.title("Calculate Distance") myapp = App(root) myapp.mainloop() بعد ذلك نقوم بإضافة صندوق للإدخال ونص "Enter Speed" وزر لحساب المسافة: class App(tk.Frame): def __init__(self, master): super().__init__(master) # إضافة حاشية إلى النافذة self.pack(padx=20, pady=20) # كتابة نص بسيط self.label = tk.Label(self, text="Enter Speed:") self.label.pack(fill=BOTH, expand=True) # عمل صندوق لإدخال قيمة السرعة self.entrythingy = tk.Entry(self, width=50) self.entrythingy.pack(fill=BOTH, expand=True) # عمل نص لعرض النتيجة في النهاية self.result_label = tk.Label(self, text="") self.result_label.pack(fill=BOTH, expand=True) # عرض ثلاث أزرار لحساب المسافة self.calc_btn_5 = tk.Button( text="Time: 5", command=lambda:self.calcDistance(time=5)) # التابع calcDistance سنقوم بعملة في الخطوة التالية self.calc_btn_5.pack(side=LEFT, expand=True) self.calc_btn_8 = tk.Button( text="Time: 8", command=lambda:self.calcDistance(time=8)) # التابع calcDistance سنقوم بعملة في الخطوة التالية self.calc_btn_8.pack(side=LEFT, expand=True) self.calc_btn_12 = tk.Button( text="Time: 12", command=lambda:self.calcDistance(time=12)) # التابع calcDistance سنقوم بعملة في الخطوة التالية self.calc_btn_12.pack(side=LEFT, expand=True) الآن نقوم بعمل التابع calcDistance لحساب المسافة وإظهار النتيجة في النافذة: class App(tk.Frame): def __init__(self, master): super().__init__(master) # ... def calcDistance(self, time=1): # جلب القيمة من صندوق الإدخال speed = self.entrythingy.get() if not speed: return # تحويل المدخل إلى رقم speed = int(speed) # تجهيز النتيجة النهائية result = f"The distance the car will travel in { time } hours is { speed * time } miles" # عرض النتيحة في النافذة self.result_label.config(text=result) سيكون شكل البرنامج في النهاية كالتالي: هنا الكود بالكامل: import tkinter as tk from tkinter import * class App(tk.Frame): def __init__(self, master): super().__init__(master) # إضافة حاشية إلى النافذة self.pack(padx=20, pady=20) # كتابة نص بسيط self.label = tk.Label(self, text="Enter Speed:") self.label.pack(fill=BOTH, expand=True) # عمل صندوق لإدخال قيمة السرعة self.entrythingy = tk.Entry(self, width=50) self.entrythingy.pack(fill=BOTH, expand=True) # عمل نص لعرض النتيجة في النهاية self.result_label = tk.Label(self, text="") self.result_label.pack(fill=BOTH, expand=True) # عرض ثلاث أزرار لحساب المسافة self.calc_btn_5 = tk.Button( text="Time: 5", command=lambda:self.calcDistance(time=5)) self.calc_btn_5.pack(side=LEFT, expand=True) self.calc_btn_8 = tk.Button( text="Time: 8", command=lambda:self.calcDistance(time=8)) self.calc_btn_8.pack(side=LEFT, expand=True) self.calc_btn_12 = tk.Button( text="Time: 12", command=lambda:self.calcDistance(time=12)) self.calc_btn_12.pack(side=LEFT, expand=True) def calcDistance(self, time=1): # جلب القيمة من صندوق الإدخال speed = self.entrythingy.get() if not speed: return # تحويل المدخل إلى رقم speed = int(speed) # تجهيز النتيجة النهائية result = f"The distance the car will travel in { time } hours is { speed * time } miles" # عرض النتيحة في النافذة self.result_label.config(text=result) root = tk.Tk() # تغير عنوان النافذة root.title("Calculate Distance") myapp = App(root) myapp.mainloop()
  7. لا تحتاج إلى أي مكتبات للقيام بهذا الأمر حيث يقوم المصرِّف تلقائيًا بتمرير عدد هذه القيم المدخلة arguments إلى البرنامج وقيمها أيضًا إلى الدالة main، لذلك تحتاج إلى أستقبال هذه القيم في شكل معاملات parameters int main(int argc, char** argv) { std::cout << "The total arguments is " << argc << std::endl; std::cout << "The file name is " << argv[0] << std::endl; std::cout << "The first argument is " << argv[1] << std::endl; return 0; } عند تشغيل البرنامج السابق وتمرير كلمة Hsoub إليه فستجد أن البرنامج يقوم بطباعة التالي: C:\> main.exe Hsoub The total arguments is 2 The file name is main.exe The first argument is Hsoub المعامل الأول الذي يتم تمريره إلى الدالة main هو عدد صحيح عبارة عن عدد المدخلات، بينما المعامل الثاني فيعبر عن كل القيم الممرة وتكون أول قيمة هي اسم البرنامج نفسه. ملاحظة: المعامل الأول يكون دائمًا اسم البرنامج نفسه في سطر الأوامر (main.exe)، لذلك فإن سنجد أن عدد المدخلات في المثال السابق هو 2 وليس 1 يمكن أيضًا إستخدام الكود التالي وستحصل على نفس النتيجة: int main(int argc, char** argv) { // ... } ملاحظة في حالة تمرير أكثر من معامل سيتم الفصل بينهم من خلال المسافة: C:\> main.exe Hello World The total arguments is 3 The file name is main.exe The first argument is Hello في المثال السابق يتم تمرير كلمة Hello كمعامل ثاني وكلمة World كمعامل ثالث، ولكي يتم تتمرير الكلمتين كمعامل واحد فقط يجب أن يتم وضعهم داخل علامة تنصيص، على النحو التالي: C:\> main.exe "Hello World" The total arguments is 3 The file name is main.exe The first argument is Hello World
  8. تحتوي لغة ++C على أربع طرق أساسية لتهيئة المتغيرات، وهي كالتالي: الطريقة الأولى: تعريف المتغير بدون تهيئة قيمة أولية للمتغير int a; نستخدم هذه الطريقة عندما نريد تخزين قيمة في وقت لاحق، كما في الكوطد التالي: int age; std::cin >> age; // نخزن العمر بعد أن يقوم المستخدم بإدخال الرقم أو في حالة أردنا إستخدام متغير عام داخل أحد المجالات المحلية، وقد ذكرت هذا الأمر هنا: الطريقة الثانية: هي تهيئة النسخ copy initialization، وهي الطريقة العادية المتبعة في أغلب لغات البرمجة: int width = 5; تسمى هذه الطريقة بهذا الاسم، لأنها تقوم بنسخ القيمة الموجودة على اليمين إلى المتغير الموجود على اليسار.، ويفضل إتباع هذه الطريقة في الحالات العادية، ولكن هناك حالات أكثر تعقيدًا لن يمكننا أن نستخدم فيها هذه الطريقة. الطريقة الثالثة: هي التهيئة المباشرة Direct initialization int width( 5 ); الطريقة السابقة هي نفسها المستخدمه في طريقة تهئية النسخ، ولكن بالنسبة الحالات الأكثر تعقيدًا ، تميل التهيئة المباشرة إلى أن تكون أكثر كفاءة من تهيئة النسخ. الطريقة الرابعة والأخيرة: هي التهيئة باستخدام الأقواس Brace initialization (وتسمى أيضًا بـ uniform initialization أو list initialization) يمكن إستخدام هذه الطريقة بثلاث أشكال: int width { 5 }; // يفضل إتباع هذه الطريقة int height = { 6 }; // نفس الطريقة السابقة int depth {}; // تسمى بـ value initialization هناك بعض الحالات التي لا يمكن فيها إستخدام تهئية النسخ أو التهيئة المباشرة، فعلى سبيل المثال في الكود التالي سوف يحدث خطأ: int width { 4.5 }; // Error في الكود السابق نحاول تخزين القيمة 4.5 (وهي قيمة من نوع double) في المتغير width ولكن نوع المتغير هو رقم صحيح int وبالتالي يظهر خطأ بسبب إختلاف الأنواع، لن يظهر هذا الخطأ إن كانت القيمة صحيح (4.0 أو 4). بينما إن تم إستخدام طريقة تهيئة النسخ أو التهيئة المباشرة سوف يتم تجاهل القيمة العشرية بالكامل وسكون الرقم هو 4 فقط، مما قد يؤدي إلى أخطأ وقت التشغيل يصعب إكتشافها وإصلاحها. لذلك يفضل التهيئة باستخدام الأقواس كلما أمكن ذلك.
  9. القيمة المرجعة من الدالة main تشير إلى حالة البرنامج أثناء خروجه، وتعني القيمة 0 أن البرنامج قد إنتهى بشكل سليم وبدون مشاكل، بينما أي قيمة أخرى تعني أن هناك مشكلة قد حدثت ولكن لا يوجد قيم متفق عليها تشير إلى حالة واحدة من المشاكل بين أنظمة التشغيل، ومع ذلك توفر الحزمة iostream القيمتين EXIT_SUCCESS و EXIT_FAILURE والتي يمكن إستخدامها للتعبر عن حالة البرنامج أثناء خروجه وستعمل هذه القيم بدون مشكلة بغض النظر عن نظام التشغيل المستخدم: #include <iostream> int main() { return EXIT_SUCCESS; } أيضًا إن لم يتم إرجاع أي قيمة من الدالة main فسوف يتم إرجاع القيمة 0 بشكل إفتراضي بدون تدخل من المبرمج. أما بالنسبة إلى نوع الدالة فيجب أن يكون النوع int في ++C وذلك حسب معاير اللغة نفسها، وبالرغم من أن النوع void يمكن أن يستخدم ولن تظهر أي أخطاء فلا يجب أن يتم إستخدام هذا النوع كنوع للدالة main . أما بالنسبة للتأثير على أداء البرنامج فلا يوجد فرق بين أي طريقة من الطريق السابقة من ناحية الأداء، حيث يتم تنفيذ الدالة main مرة واحدة في الغالب ويتم إغلاقها بمجرد إنتهاء البرنامج.
  10. تحتوي الأكاديمية في الوقت الحالي على 6 دورات كاملة يتم تطويرها بإستمرار وإضافة المزيد من المحتوى والتحديثات إليها، وهي كالتالي: دورة علوم الحاسوب دورة تطوير واجهات المستخدم دورة تطوير التطبيقات باستخدام لغة JavaScript دورة تطوير تطبيقات الويب باستخدام لغة PHP دورة تطوير تطبيقات الجوال باستخدام تقنيات الويب دورة تطوير تطبيقات الويب باستخدام لغة Ruby يمكنك الإطلاع على كل دورة بالتفصيل من خلال الصفحة الرئيسية للأكاديمية من هنا تعمل الأكاديمية الآن على إنشاء دورة متخصصة بلغة بايثون وستُنشر في الأشهر القادمة القليلة عندما تكون جاهزة، وفي الوقت الحالي يمكنك الإطلاع على المقالات المنشورة في الأكاديمية عن لغة Python وبعض المكتبات الخاصة بها من هنا
  11. كل دورات حسوب ليس دورات متخصصة في لغة برمجة أو تقنية معينة، بل تهتم بالمجال بشكل عام، فعلى سبيل المثال ستجد أن هناك دورة لتطوير واجهات المستخدم يتم فيها شرح أساسيات HTML و CSS و JavaScript و jQuery و Bootstrap وغيرها الكثير من التقنيات والمكتبات والحزم، وبالتالي يمكن للطالب أن يقوم أي واجهة مستخدم بعد الإنتهاء من الدورة بشكل كامل وإتمام كل المشاريع التي تحتويها. أو كمثال آخر هو دورة تطوير الواجهات الخلفية بإستخدام لغة PHP، سنجد أن الدورة تركز على شرح أساسيات التعامل مع الواجهات الخلفية وإتمام المشاريع العملية التي يحتاجها سوق العمل، بالطبع بعد شرح كل أساسيات لغة PHP من البداية، ويقوم الطالب بعمل العديد من المشاريع بإستعمال أشهر إطارات العمل Laravel، وكنتيجة لهذا الأمر سيكون لدى الطالب إماكانية عمل كل مشاريع الواجهات الخلفية Backend بإستخدام لغة PHP لذلك لا تحتوي الأكاديمية على دورة مخصصة تشرح فيها لغة Python وحدها، ولكن تحتوي الأكاديمية على دورة علوم الحاسوب على شرح لكل أساسيات لغة Python ومفاهيم البرمجة الكائنية Object-oriented programming، وكيفية تنفيذ أشهر الخوارزميات بإستخدام هذه اللغة، بالإضافة لشرح هياكل البيانات Data Structure بإستخدام Python أيضًا، وكذلك أنماط التصميم Design Patterns الإنشائية والهيكلية والسلوكية، وكل هذا يكون بعد تعليم الطالب الأساسيات البرمجية وكيفية التعامل مع أنظمة التشغيل وفهمه لأنظمة قواعد البيانات المختلفة. يمكنك معرفة المزيد عن هذه الدورة من خلال الصفحة الخاصة بها من هنا (دورة علوم الحاسوب)
  12. جمل case عبارة عن وسوم حالة case label وهذا يعني أن المصرِّف سوف يفهم هذا الجزء على أنه قفز jump (إنتقال مباشر) إلى وسم حالة case label الذي يساوي القيمة val مباشرة، وسبب المشكلة هنا متعلق بالأقواس المعقوفة Curly Brackets، حيث أن الأقواس الخاصة بجملة Switch نفسها تحدد المجال scope بأنه كل شيء داخل جملة Switch، وهذا يعني أن عملية الإنتقال ستتجاهل تعريف متغير x في داخل أي وسم حالة case label لكي لا يحدث خطأ redefined variable، حيث يتم إعتبار أن كل الحالات cases تتبع نفس مجال switch مما يؤدي إلى إعادة تعريف المتغير أكثر من مرة (حسب الحالات cases). لحل هذه المشكلة يمكن ببساطة إضافة أقواس لكل حالة case، على النحو التالي: int main() { int val = 1; switch (val) { case 1: { std::cout << "done"; int x = 123; break; } case 2: { int x = 456; break; } } return 0; } أو يمكن أيضًا تعريف المتغير نفسه خارج جملة Switch وتغير قيمته في كل حالة case: int main() { int val = 1; int x; switch (val) { case 1: std::cout << "done"; x= 123; break; case 2: x = 456; break; } std::cout << x; // 123 return 0; } يفضل أن تستعمل كلا الطريقتين السابقتين (إستعمال الأقواس وتعريف المتغير خارج switch)، ليكون الكود في النهاية على هذا الشكل: int main() { int val = 1; int x; switch (val) { case 1: { std::cout << "done"; x = 123; break; } case 2: { x = 456; break; } } std::cout << x; // 123 return 0; } يوجد حل آخر أقل شيوعًا وهو تعريف المتغير داخل جملة Switch نفسها، ولكن هذا الأمر سوف يؤدي إلى أن يكون المتغير تابع إلى مجال scope جملة switch وبالتالي لا يمكنك أن تستعمل هذا المتغير خارج Switch: int main() { int val = 1; switch (val) { int x; // تعريف المتغير داخل switch نفسها case 1: { std::cout << "done"; x = 123; break; } case 2: { x = 456; break; } } std::cout << x; // Error: 'x': undeclared identifier return 0; } يمكنك أن تستعمل الكود السابق في حالة أردت أن تستعمل المتغير x داخل Switch فقط، وليس خارجها. يمكنك أن تقرأ أكثر حول وسوم الحالة case labels من خلال هذه المقالة: أو من خلال هذه المقالة التي تشرح جملة Switch بالتفصيل:
  13. كلامهما عبارة عن مصرِّف من مجموعة مصرفات جنو GNU Compliers Collection أو إختصارًا GCC (بأحرف كبيرة)، وهو عبارة عن كل اللغات المختلفة التي يدعما مصرف جنو GNU Compiler. التسمية سُمي المصرِّف gcc كإختصار لـ GNU: C Compiler ، بينما تم تسميه المصرِّف ++g إختصار لـ GNU C++ Compiler الإختلافات توجد مجموعة من الإختلافات الرئيسية بينهما: المصرِّف gcc سوف يقوم بتصريف الملفات c.* و cpp.* بناءً على اللغة المستخدمة، أي أن الملفات التي تنتهي بالصيغة c. سوف يتم ترجمتها على أساس لغة C ونفس الأمر بالنسبة للملفات التي لها الصيغة cpp.* سيتم تصريفها على أساس لغة ++C، على الجانب الآخر لن يقوم المصرف ++C بهذا الأمر وسيقوم بالتعامل مع كلا الصيغتين على أنهما ملفات ++C بشكل إفتراضي. عند إستخدام المصرِّف ++g لربط ملفات الكائنات Object files سوف يقوم تلقائيًا بربط المكتبات القياسية المستخدمة std C++ libraries، بينما المصرِّف gcc يحتاج إلى إستخدام المعامل التالي: gcc -xc++ -lstdc++ -shared-libgcc المصرِّف gcc سوف يستخدم شيفرات جامعة (macros) أقل عند تصريف ملفات c.* عند إستخدام المصرف gcc لتصريف ملفات ++C أو عند إستخدام المصرِّف ++g (لتصريف الملفات c.* أو cpp.*) فسيتم إستخدام بعض الـ Macros الإضافية، كالتالي: #define __GXX_WEAK__ 1 #define __cplusplus 1 #define __DEPRECATED 1 #define __GNUG__ 4 #define __EXCEPTIONS 1 #define __private_extern__ extern كخلاصة لما سبق، يمكن إستخدام كلا المصرفين لتصريف ملفات ++C بدون مشكلة، ويفضل أن تستخدم ++g عند التعامل معه ++C بشكل عام، لأنه يسهل على المبرمج عملية ربط ملفات الكائنات Object Files.
  14. هذه العادة البرمجية جاءت من لغة C ، حيث أنه في لغة C الدالة التي لديها قوسين فارغين كالدالة التالية: int func(); تقبل أي عدد من المدخلات من أي نوع، حيث لا يقوم المصرف بالتحقق في هذه الحالة من عدد المدخلات إلى الدالة، ولجعل الدالة لا تقبل أي مدخلات على الإطلاق يجب أن تكتب النوع void كمعامل لهذه الدالة، ويؤدي إستخدام الدالة بأقواس فارغة إلى سلوك غير معروف undefined behavior, لذلك يجب أن يتم تمرير معامل واحد على الأقل، وفي الوقت الحالي يفضل أن يتم إستخدام طريقة ... لعمل دالة تقبل أي عدد من المدخلات: int func(int args, ...); أما في لغة ++C فإن الأقواس الفارغة ( ) تعني أن الدالة لا تقبل أي مدخلات، ومع ذلك فإن void كمعامل للدالة في لغة ++C يُعد صحيحًا أيضًا. وبناءً على ما سبق فلا يوجد فرق في للأداء بين الطريقتين.
  15. في BeautifulSoup يمكن إستخدام التابع find أو find_all للبحث عن عنصر معين من خلال تمرير دالة كمعامل لهذا التابع، كالتالي: import requests from bs4 import BeautifulSoup def check_content(tag): return tag.name=="h2" and "دورة" in tag.get_text() user_input_url = 'https://academy.hsoub.com/store/c1-%D8%AF%D9%88%D8%B1%D8%A7%D8%AA-%D8%AA%D8%B9%D9%84%D9%8A%D9%85%D9%8A%D8%A9/' website_content = requests.get(user_input_url.strip()).text soup = BeautifulSoup(website_content, features='lxml') print(soup.find_all(check_content)) # سيتم طباعة قائمة من العناصر التي تحتوي على كلمة 'دورة' في داخلها لاحظ أن الدالة check_content يجب أن تقوم بإرجاع قيمة منطقية Boolean الفرق بين find و find_all هو أن التابع find سقوم بإرجاع أول عنصر يجده، بينما التابع find_all سوف يقوم بإرجاع كل العناصر التي تنطبق عليها الشروط. أيضًا يمكن إستعمال الأنماط التعبيرية regular expression للبحث عن النصوص بطريقة متقدمة أكثر، كالتالي: import requests from bs4 import BeautifulSoup import re user_input_url = 'https://academy.hsoub.com/store/c1-%D8%AF%D9%88%D8%B1%D8%A7%D8%AA-%D8%AA%D8%B9%D9%84%D9%8A%D9%85%D9%8A%D8%A9/' website_content = requests.get(user_input_url.strip()).text soup = BeautifulSoup(website_content, features='lxml') h2_elements = soup.find_all('h2') # تحديد كل عناصر h2 # سنتحقق من محتوى كل عنصر من عناصر h2 التي تم تحديدها for element in h2_elements: if element.find_all(text=re.compile("دورة")): # إن كان محتوى العنصر يحتوي على الكلمة دورة print(element)
  16. في الواقع هذا ليس معامل واحد بل معاملين معًا، الأول هو معامل الإنقاص -- والثاني هو معامل المقارنة < ، وبذلك يتم مقارنة قيمة x مع الصفر ثم يتم إنقاص واحد من هذه القيمة، ليكون الكود أوضح يمكنك أن تستخدم الأقواس، كالتالي: #include <iostream> int main() { int x = 11; while ((x--) > 0) { std::cout << x << std::endl; } return 0; } لاحظ يبدو الكود أكثر وضوحًا الآن، كما يمكن إستعمال نفس الطريقة في حلقة for: for(int x = 11; x --> 0;) { std::cout << x << std::endl; }
  17. السبب ليس تأثير هذه الطريقة في إستخدام المجال std على أداء البرنامج، في الواقع هذا الكود لن يؤثر على أداء البرنامج بل على طريقة تصريفه compiling حيث قد تظهر العديد من الأخطاء في حالة وجود دوال مشابة للموجودة في المجال std، فعلى سبيل المثال إن كان لدينا الكود التالي: using namespace foo; // يحتوي على الدالة xyz using namespace bar; // يحتوي ايضًا على الدالة xyz الكود السابق سوف يؤدي إلى خطأ أثناء عملية التصريف بسبب تعريف الدالة xyz مسبقًا، وبالتالي لا تستفيد من فضاءات الأسماء namespaces حيث أن سبب إستخدامها هو حل هذه المشكلة من الأساس. يمكنك الإطلاع على هذه المقالة لمزيد من المعلومات حول فضاءات الأسماء namespaces: ملاحظة يمكنك أن تستعمل اللكود التالي في حالة أردت إستخدام cout بدون كتابة اسم المجال std: #include <iostream> // إستخدام cout فقط using std::cout; int main() { cout << "hello, wolrd\n"; return 0; } بهذه الطريقة يمكنك إستعمال كل الدوال من المكتبة القياسية iostream وفي نفس الوقت تستطيع إستعمال cout بشكل مباشر.
  18. يظهر هذا الخطأ بسبب تعريف الدالة getSquareSides أكثر من مرة (مرة لكل تضمين include) وبالتالي لا يستطيع المترجم التفريق بين الدوال التي لها نفس التوقيع signature (نوع الرجوع return type + اسم الدالة + المعاملات التي تقبلها الدالة)، وهنا ما يقوم به المصرف compiler بشكل مفصل: أولًا يقوم المصرف بتضمين الملف square.h في الملف main.cpp، وبالتالي يتم نسخ الدالة getSquareSides إلى الملف main.cpp لأول مرة بعد ذلك يتم تضمين الملف geometry.h في الملف main.cpp، والذي بدورة يقوم بتضمين الملف square.h مرة أخرى، وبهذا يتم نسخ محتوى الملف square.h إلى داخل geometry.h ثم نسخ محتوى الملف geometry.h (بما في ذلك الدالة getSquareSides) إلى الملف main.cpp وسيكون شكل الكود في النهاية (بالنسبة للمصرف compiler)، كالتالي: int getSquareSides() // من الملف square.h { return 4; } int getSquareSides() // من الملف geometry.h (عبر square.h) { return 4; } int main() { return 0; } كل ملف على حدى لا يحتوي على أخطاء ولكن إستدعاء هذه الملفات بشكل هرمي ومتوازي معًا يسبب خطأ تعريف نفس الدالة لأكثر من مرة. لحل هذه المشكلة يجب إستخدام Header guards أو ما يسمى بواقيات معالج مسبق (Preprocessor Guards)، كالتالي: الملف square.h: #ifndef SQUARE_H #define SQUARE_H // لن يتم تضمين الدالة التالية إلا مرة واحدة فقط int getSquareSides() { return 4; } #endif الملف geometry.h: #ifndef GEOMETRY_H #define GEOMETRY_H #include "square.h" #endif ويبقى الملف main.cpp كما هو بدون تغير، وبالتالي سيكون شكل الملف main.cpp بعد عملية preprocessing على الشكل التالي: // تضمين الملف square.h من داخل main.cpp #ifndef SQUARE_H #define SQUARE_H int getSquareSides() { return 4; } #endif // SQUARE_H // تضمين الملف geometry.h من داخل main.cpp #ifndef GEOMETRY_H #define GEOMETRY_H #ifndef SQUARE_H // تضمين الملف square.h من داخل geometry.cpp , SQUARE_H معرفة بالفعل في الأعلى #define SQUARE_H // لذلك لن يتم تضمين هذا المحتوى مرة أخرى في عملية التصريف compiling int getSquareSides() { return 4; } #endif // SQUARE_H #endif // GEOMETRY_H int main() { // ... return 0; } يمكنك أن تقرأ أكثر حول الـ Header guards من خلال هذه المقالة هنا، حيث يتم شرح كيفية تضمين ملفات الترويسة Headers بطيرقة صحيحة:
  19. يمكنك إستخراج كل الروابط في صفحة ما وتقسيم هذه الروابط إلى روابط داخلية internal links (روابط لصفحات أخرى أو أماكن مختلفة في نفس الصفحة) وروابط خارجية external links (روابط تؤدي إلى مواقع آخرى)، على النحو التالي: # لعمل الطلبات import requests # لإستخرج الروابط من مستند HTML from bs4 import BeautifulSoup # لإستخرج نطاق الموقع domain من الروابط import urllib.parse if __name__ == '__main__': user_input_url = "https://github.com" domain = urllib.parse.urlparse(user_input_url).netloc # فحص إتصال الإنترنت try: website_content = requests.get(user_input_url.strip()).text except: check_internet = requests.get('https://google.com').status_code if check_internet != requests.codes.ok: raise ConnectionError("ERROR: Check internet connection.") _soup = BeautifulSoup(website_content, features='lxml') internal_url_links = [] external_url_links = [] for link in _soup.find_all('a', href=True): if link.get('href'): url_domain = urllib.parse.urlparse(link.get('href')).netloc # Absolute links if domain == url_domain: internal_url_links.append(link.get('href')) # Relative links # كل الروابط النسبية تبدأ بأحد الرموز التالية elif link.get('href')[0] in ['/', '#', '?']: internal_url_links.append(urllib.parse.urljoin(user_input_url, link.get('href'))) # external url # إذا كان طول الرابط أقل من 3 أحرف فهو رابط غير صالح elif domain != url_domain and len(link.get('href')) > 3: external_url_links.append(link.get('href')) print(internal_url_links, '\n') print(external_url_links, '\n')
  20. بداية من ++C11 يمكنك أن تستخدم الدالة to_string لتحويل الأرقام بشكل عام إلى نصوص، كالتالي: #include <string> int main() { int x = 23; std::string s = std::to_string(x); return 0; } الكود السابق مشابهة لـ atoi و itoa في لغة C ولكن من خلال std:to_string يمكنك أيضًا أن تستعمل stringstream بدون مشكلة: int main() { int x = 10; std::stringstream ss; ss << x; std::string str = ss.str(); return 0; } ولكن الطريقة الأولى أسهل في الكتابة وأوضح في القراءة.
  21. يمكنك تحويل وحدة القياس إلى px بدلًا من pt من خلال قائمة edit ثم Preference ثم Unit & Rulers وقم بتغير قيمة Type، كما في الصورة: وستجد أن حجم الخط وإرتفاع السطر قد قد ظهرت قيمها بالبيكسل: يمكن تحويل بعض القيم في الصورة السابقة إلى CSS كالتالي بسهولة: font-family: "Myriad Arabic"; font-size: 50px; line-height: 48px; font-weight: normal; /* تساوي Regular */
  22. تحتوي دورة إنشاء تطبيقات الويب بلغة PHP على مشروع واحد فقط يتم عمله بلغة PHP بدون إطار عمل والهدف منه هو تعلم أساسيات اللغة نفسها من متغيرات ودوال وحلقات وأصناف .. إلخ، وذلك لتأهيل الطالب للعمل على مشاريع أخرى بإستخدام Laravel أو WordPress، وذلك لأن سوق العمل يتطلب إستخدام إطار عمل معروف أكثر من إنشاء كل مشروع من الصفر بإستخدام PHP فقط، أيضًا توفر إطارات العمل الكثير من الوقت والمجهود على المبرمجين، حيث تأتي بالكثير من الأدوات والملفات المعدة مسبقًا والتي يمكن إستخدامها بشكل مباشر. وبالتالي يجب على الطالب أن يتدرب أكثر على إستخدام إطار عمل مشهور وواسع الإنتشار مثل Laravel بالتأكيد بعد تعلم أساسيات البرمجة بإستخدام PHP. أيضًا يفضل أن يستخدم المبرمج إطار عمل جاهز حتى ولو كان متقنًا للغة البرمجة التي يستعملها، لأن إطارات العمل مفتوحة المصدر يعمل عليها العشرات من المبرمجين المحترفين لتطويرها وكذلك لإضافة مميزات جديدة فيها وحمايتها من الثغرات وبالتالي لن يتمكن مبرمج واحد من عمل ما يقوم به عشرات المبرمجين المحترفين ومئات المبرجين الآخرين الذين يقوم بعمل العديد من الحزم والمكتبات لإطار العمل هذا. في حالة أردت أن تتدرب أكثر على لغة PHP فيمكنك أن تحاول تقليد أي موقع تراه من الصفر بإستخدام PHP وحدها أو حتى محاولة إنشاء مشاريع Laravel الموجودة في الدورة بدون إطار عمل.
  23. يكمن الفرق بين الطريقتين في مكان الملفات التي يبحث عنها الـ preprocessor: #include <filename> عند إستخدام الكود السابق يقوم الـ Preprocessor بالبحث عن الملفات حسب ترتيب إستدعائها في المجلدات المعدة مسبقًا في بيئة التطوير IDE أو في المصرف Compiler، وينم إستخدام هذه الطريقة في العادة لإستدعاء ملفات الترويسة Header الخاصة بالمكتبات القياسية Standard Libraries. في حين أن أستخدام الكود التالي: #include "filename" يقوم الـ Preprocessor بالبحث عن الملفات بداية من المجلد الحالي (مجلد التنفيذ CWD) عن الملفات حسب المسار المستخدم في جملة include، وتستخدم هذه الطريقة في العادة لإستدعاء ملفات الترويسة Header التى قام بكتابتها أو إضافتها المبرمج نفسه، وهي ليست جزء من مكتبات اللغة القياسية. يمكنك الإطلاع على هذه المقالة: ولمزيد من الشرح عن المعالجة الأولية Preprocessor أطلع على هذه المقالة:
  24. يمكنك تجربة الكود هنا، حيث يبدو انه يعمل بدون مشكلة بالنسبة للصور التي لها طول وعرض أقل من 200 بيكسيل يمكنك التأكد من طول وعرض الصورة من خلال الضغط عليها بالزر الأيمن للفأرة وإختيار properties ثم التبويبت details وستجد عرض وطول الصورة
  25. يمكنك أن تستعمل promise لعمل دالة تقوم بالتحقق أولًا من طول وعرض الصورة عبر الكائن Image، كالتالي: const imageDimensions = (file) => new Promise((resolve, reject) => { const img = new Image(); img.onload = () => { const { naturalWidth: width, naturalHeight: height } = img; resolve({ width, height }); }; img.onerror = () => { reject("There was some problem with the image."); $(".img-validate").val(""); }; img.src = URL.createObjectURL(file); }); ثم نقوم بإستعمال هذه الدالة على الشكل التالي: $(document).ready(function () { $(".img-validate").change(function () { var allowedTypes = ["image/jpeg", "image/gif", "image/png"]; var file = this.files[0]; imageDimensions(file).then((sizes) => { var height = sizes.height; var width = sizes.width; var MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB var fileSize = this.files[0].size; // التحقق من الملف من خلال صيغته if ( !file.name.endsWith(".jpg") && !file.name.endsWith(".jpeg") && !file.name.endsWith(".png") && !file.name.endsWith(".gif") ) { alert("Restricted File Type, Please Select only image files"); $(".img-validate").val(""); return false; } // التحقق من ابعاد الصورة else if (height > 200 || width > 200) { alert("Dimention is too Large "); $(".img-validate").val(""); return false; } // التحقق من حجم الملف else if (fileSize > MAX_FILE_SIZE) { alert("الحد الاقصى للصورة 5 ميجابايت"); $(".img-validate").val(""); } else { this.setCustomValidity(""); } }); }); }); أو يمكنك أن تقوم بوضع كل الكود في داخل الحدث onload كالتالي: $(document).ready(function () { $(".img-validate").change(function () { var allowedTypes = ["image/jpeg", "image/gif", "image/png"]; var file = this.files[0]; const img = new Image(); img.onload = () => { const { naturalWidth: width, naturalHeight: height } = img; var MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB var fileSize = this.files[0].size; alert(file.name) // التحقق من الملف من خلال صيغته if ( !file.name.endsWith(".jpg") && !file.name.endsWith(".jpeg") && !file.name.endsWith(".png") && !file.name.endsWith(".gif") ) { alert("Restricted File Type, Please Select only image files"); $(".img-validate").val(""); return false; } // التحقق من ابعاد الصورة else if (height > 200 || width > 200) { alert("Dimention is too Large "); $(".img-validate").val(""); return false; } // التحقق من حجم الملف else if (fileSize > MAX_FILE_SIZE) { alert("الحد الاقصى للصورة 5 ميجابايت"); $(".img-validate").val(""); } else { this.setCustomValidity(""); alert('done') } }; img.onerror = () => { alert("Restricted File Type, Please Select only image files"); $(".img-validate").val(""); }; img.src = URL.createObjectURL(file); }); }); مع العلم أن في حالة إستخدام أي طريقة من هذه الطرق لن تحتاج إلى التأكد من أن الملف عبارة عن صورة، لأن الكائن Image سوف يقوم بتشعيل الحدث onerror في حالة فشله لتحميل الصورة وهذا ما يحدث عند تحميل أي نوع آخر من الملفاـ، ولكن مازال يمكنك التحقق من صيفة الملف بدون مشكلة.
×
×
  • أضف...