• 0
bahbah

[تمت الإجابة] أسئلة من الكود الأول في ++C

سؤال

بسم الله الرحمن الرحيم

اللهم صل على محمد وآل محمد

السلام عليكم ورحمة الله وبركاته

 

 

 

 

قررت تعلم لغتي السي والسي بلس بلس .. بسبب ما يحتويه القسم من نشاط كبير ..

 

 

فلدي بعض الغموض حول هذه اللغة .. لو أزلتُموه عني ..

 

 

 

هذه بعض الأسئلة ..

 في هذا الكود

#include<iostream>using namespace std;int main(){cout<<"Hello World!";return 0;}

 

1- لماذا نستعمل جملة "using namespace std;" في السي بلس بلس لإستخدام مكتبة iostream ؟

 

2- لماذا وضعنا كلمة std في الجملة السابقة

 

3- لماذا لا نستطيع تعريف الدالة main على أساس void في السي بلس بلس بينما السي يمكننا ذلك ؟؟ وما معنى void ؟؟

 

4- في السي بلس بلس يمكننا تعريف المتغير داخل حلقة التكرار , بينما في السي لا يمكننا لماذا ؟؟

 

5- لماذا لا توجد مكتبة iostream في السي ، ونستعمل بديلاً عنها stdio.h ..

 

6- لماذا بعض الملفات نضع الإمتداد وبعضها لا ؟؟

 

تقبلوا تحياتي  ^_^

 

تم تعديل بواسطه مصطفى 36a2
إضافة الأسئلة و الكود
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

11 إجابة على هذا السؤال .

  • 0
1- لماذا نستعمل جملة "using namespace std;" في السي بلس بلس لإستخدام مكتبة iostream ؟

 

 

كما تعلم, السي++ احتوت على جزء من لغة السي (الأم) ، وللأسف كانت هناك مشكلتان بعدما بدأ المقياس الأول للغة سي++.

 

  1. المشكلة الأولى: أسماء المكتبات القياسية في لغة السي ++ بالإضافة إلى التي توفرها بعض المترجمات تكون بصيغ غير موحدة, مثلا بعضها ينتهي بـ .h وبعضها ينتهي بـ .hpp 
  2. المشكلة الثانية: عندما نقوم بكتابه تطبيق كبير يُشارك فيه أكثر من مبرمج, يجب أن نراعي أسماء المتغيرات المُستخدمة, فمثلا لو قام أحد المبرمجين بكتابة اسم متغير في ملف a.h وقمت أنت باستخدام نفس الاسم في الملف b.h , عندما تقوم بترجمة التطبيق (بجميع ملفاته) ستجد خطأ في مرحلة الـ linking و السبب يعود إلى استخدمك لأكثر من متغير بنفس الإسم و هذا ما يسبب مشكلة التصادم أو ما يعرف بالـ Coillision.

كان يحتوي المقياس القديم للسي++ على تلك العيوب إلى أن جاء المقياس الجديد (وهو ليس بجديد فهو منذ عام 1997, أي حوالي 16 سنه من الآن) ، المقياس الجديد حل المشكلة الأولى بأن يتم حذف جميع الإمتدادات من المكتبات القياسية وجعلها من غير امتداد, أما مكتبات السي القياسية الموجودة في السي++ فأيضا نحذف امتدادها مع بإضافة حرف c قبل اسم المكتبة للدلالة على أنها قادمة من لغة السي.

 

مثال على المقياس القديم :

#include<iostream.h>#include<stdio.h>#include<stdlib.h>

في المقياس الجديد أصبحت بهذا الشكل :

#include<iostream>#include<cstdio>#include<cstdlib>

وهكذا تم حل مشكلة عدم وجود امتداد محدد للمكتبات القياسية.

بالنسبة للمشكلة الثانية فقد قام مطوروا اللغة بإيجاد مفهوم جديد يسمى بـ  Name Space , أي مساحة الأسماء حيث  تم تعريف جميع المتغيرات والكلاسات المُستخدمة, وفي حال كان هناك أكثر من namespace مثلا : مساحة لـ A و أخرى لـ B وكل منهم احتوى على متغير بنفس الإسم. الآن لن نجد مشكلة لأن كل واحد من هذه المتغيرات معرف في "مساحة" خاصة به و بهذا نكون قد أنهينا مشكله الـ Coillision.

المقياس الجديد أضاف شيء جميل وهو أن جميع مكتبات السي++ القياسية ستكون داخل  namespace تسمى std وذلك اختصارا لـ Standard لذلك إذا أردنا أستخدام مكتبات السي++ القياسية فيجب أن نحدد هذه المساحة باستخدام using. مثال على استخدام المكتبة iostream :

#include<iostream>using namespace std;

هكذا نكون قد وصلنا للمكتبة iostream ولجميع ما بها عن طريق الــ namespace.

 

2- لماذا وضعنا كلمة std في الجملة السابقة

 

في العبارة السابقة استخدمنا مساحة الأسماء الخاصة بالمكتبة الرئيسية للغة السي++ و التي تدعى Standard Library و التي تندرج تحت مجال الأسماء std  كمـا أن مجالات الأسماء من الأشياء التي توجد في السي++ و لا توجد في السي.

عندما نريد إنشاء مساحة أسماء جديدة فهذا يعني أننا سنجمع مجموعة من المتغـيرات و الثوابت و الدوال و الكائنات في مجال واحد و الذي هو مساحة الأسماء ,انظر الـكود الآتي:

namespace test {  char ch;  long n,m;  float x,y;}

في هذا المثال قمنا بالإعلان عن مساحة أسماء تحت اسم test و تحتوي على مجموعة من المتغيرات, إذا أردنا الوصول إلى هذه المتغيرات نستخدم معامل تحديد المدى ::, مثال :

test::ch;

طيب الآن لو أردنا استخدام أحد المتغيرات (الموجودة داخل مساحة الأسماء) في جميع أجزاء البرنامج .. ماذا نفعل !؟

يتم ذلك باستخدام الكلمة المحجوزة using مع اسم مساحة الأسماء إضافة إلى معامل المدى وصولا إلى المتغير الذي نريد التعامل معه, هكذا:

using test::ch;

و تأتي فائدة الكلمة using في استمرار استخدام هذا المتغير طوال تنفيذ البرنامج بحيث تغنينا عن تكرار العبارة test::ch كلما أردنا تنفيذ البرنامج.

الآن سنرجع إلى مساحة الأسماء std و التي يوجد بها جميع الدوال والكائنات الموجودة داخل المكتبة الرئيسية للغة السي++ فنحن عندما نكتب السطر

using namespace std

فهذا معناه أننا نأمر الكومبايلر باستخدام جميع الدوال و الكائنات (إذا اقتضت الضرورة) الموجودة داخل مساحة الأسماء std و بما أن المكتبة iostream تقع ضمن هذه المساحة فيجب علينا استخدام العبارة السابقة لتضمين جميع الكائنات و الدوال الموجودة داخلها.

 

 

3- لماذا لا نستطيع تعريف الدالة main على أساس void في السي بلس بلس بينما السي يمكننا ذلك ؟؟ وما معنى void ؟؟

 

هذا يُحدده المعيار, فمثلا إعادة void مسموحة في المعيار C89 حسب ما أعتقد.

void تعني لا شيء أي أن الدالة لا تُعيد أي قيمة.

 

 

4- في السي بلس بلس يمكننا تعريف المتغير داخل حلقة التكرار , بينما في السي لا يمكننا لماذا ؟؟

 

هذا أيضا, يتعلق يالمعيار الذي يدعمه المترجم. المعيار C89 لا يسمح بتعريف المتغيرات داخل الحلقة for على عكس C99.

 

 

5- لماذا لا توجد مكتبة iostream في السي ، ونستعمل بديلاً عنها stdio.h ..

 

iostream خاصة بالسي++, تُقابلها stdio.h في السي.

بالنسبة لـ "لماذا لا توجد" فهذا سؤال محير :D لأنه ليس كل مكتبات السي++ توجد في السي و العكس صحيح :)

 

 

6- لماذا بعض الملفات نضع الإمتداد وبعضها لا ؟؟

 

على عكس السي, لا يوجد امتداد لـ header files في السي++.

تم تعديل بواسطه Snack3r
3

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

c و c++ يتشاركان الكثير من الأشياء إلا أنهما لغتين مختلفين وكل واحدة تطور لوحدها، تعامل معهما على هذا الأساس.

 

الـnamespace وجدت لمنع التضارب الذي قد يحصل عندما توجد هناك دالتين أم متغيرين لهما نفس الإسم، في c عندما يريد شخص بناء مكتبة كبيرة كواجهة برمجية أو غيرها، غالباً تجد أنه يستخدم أسماء دوال أو أنواع بيانات طويلة لكي يقلل من حودث هذه المشكلة مثل:

void library_window_create(void);     ^^^^^^^void library_window_close(void);     ^^^^^^^void library_button_set_text(void);     ^^^^^^^...

مايقوم به مبرمج c هنا هو namespacing بوضعه السابقة library_. في c++ أضيف دعم الـnamespacing، يمكن أن يكتب المبرمج الآن:

namespace library {void window_create();void window_close();void button_set_text();}

ويستخدم تلك الدوال هكذا:

library::window_create();-------------------------------------using namespace library;window_create();-------------------------------------using library::window_create;window_create();

الـnamespace المسماة std ليست خاصة فقط بـiostream، بل بكل دوال وقوالب ومحتويات مكتبة c++ القياسية، مثل string و vector وغيرها.

 

كتابة using namespace std ليست جيدة، كثير من دوال المكتبة القياسية تستخدم أسماء شائعة وقد تقع في نفس المشكلة التي وقع بها السائل هنا (مشكلة في المكدسات).

 

 

3- لماذا لا نستطيع تعريف الدالة main على أساس void في السي بلس بلس بينما السي يمكننا ذلك ؟؟ وما معنى void ؟؟

 

معيايير c و c++ تشترط أن تعيد الدالة الرئيسية int، بعض مصرفات c تسمح بأن لا تعيد الدالة الرئسية شيء (void)، رغم أنه خطأ، حتى لو فعلت التحذيرات (في gcc استخدم -Wall) ستجد تحذير بخصوص هذا الشيء الا أن بناء البرنامج يكتمل. أما أغلب مصرفات c++ تعتبره خطأ صريح وتفرض عليك أن تعيد الدالة int.

 

في c++ و c99، إذا كتبت int main دون أن تكتب return فضمنياً كأنك كتبت return 0:

int main() {}

 

4- في السي بلس بلس يمكننا تعريف المتغير داخل حلقة التكرار , بينما في السي لا يمكننا لماذا ؟؟

 

حتى في c إذا كنت تستخدم مصرف يدعم معيايير سنة 99 يمكنك أن تعرف متغير داخل حلقة التكرار، إذا كنت تستخدم gcc مرر الخيار -std=c99، مصرف vc++ لايدعم c99، فقط c89.

 

 

5- لماذا لا توجد مكتبة iostream في السي ، ونستعمل بديلاً عنها stdio.h ..

 

iostream مكتبة خاصة بـc++، الفرق بين دوال الإدخال والإخراج الخاصة بـc و c++ أن دوال عائلة iostream  مثل cout و cin يمكنها التعامل مع الكائنات على عكس printf و scanf وغيرها. مثلاً لايمكنك طباعة كائن string باستخدام printf لأنها لاتستطيع التعامل مع الكائن بل فقط مع الأنواع البسيطة char * و int و غيرها، مثلاً:

#include <iostream>#include <stdio.h>#include <string>int main(int argc, char **argv) {  std::string str = "ABCD"; // هذا ليس نوع بيانات، بل "كائن" للتعامل مع النصوص  std::cout << str << "\n"; // يعمل   //printf("%s\n", str); // لن يعمل  printf("%s\n", str.c_str()); // لجعله يعمل مع دوال سي  return 0;}

بالنسبة للإمتداد، يمكنك استخدام أي إمتداد ولاتوجد مشكلة، لست متأكد لماذا الملفات الرئسية بـc++ بدون امتداد، قد لايكون هناك سبب معين.

تم تعديل بواسطه Mr.B
2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

كان يحتوي المقياس القديم للسي++ على تلك العيوب إلى أن جاء المقياس الجديد (وهو ليس بجديد فهو منذ عام 1997, أي حوالي 16 سنه من الآن) ، المقياس الجديد حل المشكلة الأولى بأن يتم حذف جميع الإمتدادات من المكتبات القياسية وجعلها من غير امتداد, أما مكتبات السي القياسية الموجودة في السي++ فأيضا نحذف امتدادها مع بإضافة حرف c قبل اسم المكتبة للدلالة على أنها قادمة من لغة السي.

 

 

بالمناسبة c++ لم تصبح قياسية الا في سنة 1998 وكان أول إصدار قياسي، جميع الملفات الرأسية التي بالإمتداد *.h ليست قياسية وتدعما بعض المصرفات القديمة قبل أن ترسم أما المصرفات الجديدة لاتدعمها.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بالمناسبة c++ لم تصبح قياسية الا في سنة 1998

 

صحيح, أطلق أول إصدار من سي++ في سنة 1998 باسم ISO/CEI 14882:1998.

 

 

جميع الملفات الرأسية التي بالإمتداد *.h ليست قياسية

 

نعم بطبيعة الحال لكن أنا كنت أقصد جميع الملفات الرأسية القياسية الموجودة في السي. مثلا الملف conio.h لم يتحول إلى cconio لأنه غير قياسي و لم يتم ذكره في كتاب the c programming language.

تم تعديل بواسطه Snack3r
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

  1. المشكلة الأولى: أسماء المكتبات القياسية في لغة السي ++ بالإضافة إلى التي توفرها بعض المترجمات تكون بصيغ غير موحدة, مثلا بعضها ينتهي بـ .h وبعضها ينتهي بـ .hpp 

كان يحتوي المقياس القديم للسي++ على تلك العيوب إلى أن جاء المقياس الجديد (وهو ليس بجديد فهو منذ عام 1997, أي حوالي 16 سنه من الآن) ، المقياس الجديد حل المشكلة الأولى بأن يتم حذف جميع الإمتدادات من المكتبات القياسية وجعلها من غير امتداد, أما مكتبات السي القياسية الموجودة في السي++ فأيضا نحذف امتدادها مع بإضافة حرف c قبل اسم المكتبة للدلالة على أنها قادمة من لغة السي.

بالنسبة للإمتداد، يمكنك استخدام أي إمتداد ولاتوجد مشكلة، لست متأكد لماذا الملفات الرئسية بـc++ بدون امتداد، قد لايكون هناك سبب معين.

 

مكتبات لغة cpp الإفتراضية لا تحتوى على امتداد للتفرقة بينها و بين مكتبات لغة c الإفتراضية حيث يمكن استخدام مكتبات لغة c داخل cpp بطريقتين:

1- عن طريق إستخدام إسم الملف بسابقة c و بدون إمتداد.

2- عن طريق استخدام إسم الملف كما فى لغة c.

 

الفرق بين الطريقتين يكمن فى طبيعة المحتوى حيث مع الإصدارات الحديثة من مكتبات لغة cpp قد يتم تغيير محتويات مكتبات لغة c - و التى تبدأ بـ c و بدون إمتداد - او قد يتم إسقاط دعم لغة c من مكتبات اللغه الحديثه و حينها لا تصبح مشكلة بين مكتبات لغة c و مكتبات لغة cpp.

 

كما نعلم ان لغة c تحتوى على مكتبة نصوص بالإسم string.h، فلك ان تتخيل ماذا سيحدث لمترجم cpp عندما تصبح مكتبة نصوص اللغة لها نفس الإسم و نفس الإمتداد و كيف سيستطيع التفرقة بينهم فى حال و قف دعم استخدام مكتبات لغة c.

 

بالنسبة للإمتدادين hh و hpp فهم موجهين لمكتبات مبرمج cpp و إستخدامهم للتفرقة بين مكتبات مبرمج cpp و مكتبات مبرمج c.

 

 

و الله ولي التوفيق

تم تعديل بواسطه C++er
2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

from libstdc++-api.20130701.pdf

 

5.123.1 Detailed Description
This is a Standard C++ Library file. You should #include this file in your programs, rather than any of the .h
implementation files.
This is the C++ version of the Standard C Library header stdio.h, and its contents are (mostly) the same as that
header, but are all contained in the namespace std (except for names which are defined as macros in C).

تم تعديل بواسطه مصطفى 36a2
LDR
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

أشكر الأخ Snack3r على مشاركته القيمة ..

 

وأشكر كلاً من C++er و Mr.B على إضافاتهم المتميزة

 

تقبلوا تحياتي  :blush:

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

iostream خاصة بالسي++, تُقابلها stdio.h في السي.

بالنسبة لـ "لماذا لا توجد" فهذا سؤال محير :Dلأنه ليس كل مكتبات السي++ توجد في السي و العكس صحيح  :)

 

 

 

 

 

 

 

 

هههههه ، حقيقةً علمت بهذا الأمر عندما تصفحت المنتدى ووجدت بعض الأكواد ، فأصبحت أميز الكود المكتوب بأي لغة عندما أرى هذه المكتبة :D

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بالنسبة للأخ Mr.B لدي سؤال على ما طرحته ..

 

كيف أسعتمل ما قلته ..

 

 

حتى في c إذا كنت تستخدم مصرف يدعم معيايير سنة 99 يمكنك أن تعرف متغير داخل حلقة التكرار، إذا كنت تستخدم gcc مرر الخيار -std=c99، مصرف vc++ لايدعم c99، فقط c89.

 

أنا أعمل على code::Block وأظهر لي هذه الملاحظة وإستعمل GNU GCC Compiler ..

 

تحياتي  ^_^

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

أنا أعمل على code::Block وأظهر لي هذه الملاحظة وإستعمل GNU GCC Compiler ..

 

إذا كنت تستخدم الـ compiler من الـ console فاكتب gcc -std=c99 code.c

و إذا كنت تستخدم الـ IDE في الترجمة فغير الإعدادات كالتالي :

settings -> compiler -> compiler settings -> other options -> -std=c99

1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

إذا كنت تستخدم الـ compiler من الـ console فاكتب gcc -std=c99 code.c

و إذا كنت تستخدم الـ IDE في الترجمة فغير الإعدادات كالتالي :

settings -> compiler -> compiler settings -> other options -> -std=c99

 

شكراً على الإجابة السريعة

 

تحياتي  ^_^

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .