khaled_prg

3 أسباب تجعلني أشك في لغة السي !

28 ردود في هذا الموضوع

السلام عليكم

يسرني أن أبدأ معكم هذا النقاش الذي يتمحور حول مقارنة الخدمات القياسية و الدوال الجاهزة التي تُوفرها السي مع بقية الخدمات القياسية (و أصر على كلمة "قياسية") الموجودة في معظم لغات البرمجة :) (خصوصاً الجافا)

1. شخصياً, أرى أن لغة السي القياسية غير مرنة في التعامل مع المصوفات الحرفية (النصوص) لأن الإعتماد على نوع بدائي مثل char سيكون مُرهقا جداً.

فمشاكل الترميز (دعم اليونيكود مثلا) و الفيض (الــ OverFlow) لا تزال مطروحة بشكل كبير في السي ..

في الجافا, توجد الفئة String التي تدعم ترميز الــ Unicode بالإضافة إلى حجمها الكبير جداً..

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

2. في الملفات مثلا, لا توجد طريقة قياسية في لغة السي لمعرفة سبب عدم فتح الملف !

في معيار C ISO, الحل الوحيد لاختبار وجود ملف هو محاولة فتحه:

FILE *fp = fopen("fichier.txt", "r");
if (fp == NULL) {
fputs("Le fichier n’existe pas,\n"
"ou vous n’avez pas les droits necessaires\n"
"ou il est inaccessible en ce moment\n"
, stderr);
} else {
/* ... operation sur le fichier */
fclose(fp);
}

مع أن هذه الطريقة ليست سليمة 100% لأنه إذا لم يتم فتح الملف فهذا لا يعني بالضرورة أن الملف غير موجود !, توجد عدة أسباب أخرى :

  • قد لا تملك الصلاحيات الضرورية لفتح الملف
  • قد لا يمكن الوصول إلى محتوى الملف في تلك اللحظة (ملف مُشفر مثلا)
  • قد لا يملك النظام مساحة الذاكرة الكافية لفتح الملف

في نظام DOS/Windows و أنظمة *Nix يمكننا فحص قيمة errno, هل هي مُساوية لـــ ENOENT (no such file or directory).

أما في الجافا فالأمر بسيط جداً, مجرد تحقق بسيط من القيمة المُعادة من طرف الدالة exists و ينتهي الأمر :

File f =  new File(msg);
if (f.exists()) System.out.print("found ");
else System.out.print("not found");

كذلك, عندما نُحاول معرفة حجم ملف معين في لغة السي القياسية سنجد أن الدالتان stat و fstat التابعتان للمعيار POSIX غير مُدرجتان في معيار ISO.

الحل القياسي الوحيد يكمن في استخدام الدالتين fseek و ftell :

int fsize(const char * fname, long * ptr) {
/* Cette fonction retourne 0 en cas de succes, une valeur differente dans le cas contraire. */
/* La taille du fichier, si elle a pu etre calculee, est retournee dans *ptr */
FILE * f;
int ret = 0;
f = fopen(fname, "rb");
if (f != NULL) {
fseek(f, 0, SEEK_END); /* aller a la fin du fichier */
*ptr = ftell(f); /* lire l'offset de la position courante par rapport au debut du fichier */
fclose(f);
} else
ret = 1;
return ret;
}

أما في الجافا فيمكننا استخدام الدالة length الموجودة في الفئة java.io.File هكذا :

long octets = new File("monFichier.txt").length();

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

int copier_fichier(char const * const source, char const * const destination) {
FILE* fSrc;
FILE* fDest;
char buffer[512];
int NbLus;
if ((fSrc = fopen(source, "rb")) == NULL) {
return 1;
}
if ((fDest = fopen(destination, "wb")) == NULL) {
fclose(fSrc);
return 2;
}
while ((NbLus = fread(buffer, 1, 512, fSrc)) != 0)
fwrite(buffer, 1, NbLus, fDest);
fclose(fDest);
fclose(fSrc);
return 0;
}

أما في الجافا فيمكننا إنشاء كائن من الفئة FileInputStream لقراءة الملف المُراد نسخه و كائن آخر من الفئة FileOutputStream لكتابة بيانات الملف الجديد ثم نُمرر الكائنين السابقين للدالة copy (الموجودة في الفئة IOUtils) حيث تقوم بنسخ محتويات الــ InputStream إلى الــ OutputStream, هكذا :

import org.apache.commons.io.IOUtils;
InputStream input = new FileInputStream("monFichierSource.txt");
OutputStream output = new FileOutputStream("monNouveauFichier.txt");
IOUtils.copy(input, output);

في لغة السي القياسية, إذا أردتَ مثلا أن تحذف سطراً في ملف معين فعليك كتابة الدالة بنفسك لأن السي القياسية لا تحتوي على دالة جاهزة لمثل هذا الأمر !

أما في الجافا, فيمكننا قراءة الملف ووضعه داخل Vector ثم نُمرر رقم السطر إلى الدالة removeElementAt و ينتهى الأمر :

public static void main(String args[]) throws IOException { 
Vector monVector = new Vector();
File f = new File("monFichier.txt");
BufferedReader B = new BufferedReader(new FileReader(f));
String ligne = B.readLine();
while (ligne != null){
monVector.addElement(ligne);
ligne = B.readLine();
}
monVector.removeElementAt(numeroLigne);
PrintWriter P = new PrintWriter (new FileWriter(f));
for (int i = 0; i < monVector.size(); i++){
P.println(monVector.get(i));
}
P.close();
}

3. لغة السي و حتى السي++, لا تمتلك أي منهما مكتبة GUI قياسية و بالتالي إذا أردتَ برمجة الواجهات ستحتاج إلى مغادرة المطار القياسي لــ C/C++ مُتوجها إلى الــ MFC, GTK, QT, VCL أو الــ wxWidgets.

أما في الجافا فتجد مكتوباً في أعلى غرفة الــ GUI : مرحبا بك في عالم الــ Swing/AWT !

هذه الأسباب الثلاثة و غيرها جعلت من لغة السي (أو على الأقل حسب وجهة نظري) تبدو و كأنها فقيرة من ناحية الدوال الضرورية التي تُقدمها و التي من شأنها أن تختصر عمل المبرمج.

ما رأيكم ؟

تم تعديل بواسطه khaled_prg
5

شارك هذا الرد


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

... لا.

أختصر الرد في القول:: لغة السي ليست للبرامج التي تستهدف المستخدم النهائي البريء.smile.gif

حينما تدرس البرمجة "العميقة" ستمقت لغة اسمها جافا.

تم تعديل بواسطه A.S Hack
4

شارك هذا الرد


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

حبنما تدرس البرمجة "العميقة" ستمقت لغة اسمها جافا.

إن كنت تقصد برمجة الهاردوير (Programming Hardware Devices) فالأسمبلي و السي هما الأفضل ! :happy:

لكن ألا ترى أن السي "ضعيفة" جداً أمام الجافا في الأمور البسيطة التي ذكرتُها آنفاً ؟ :)

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

شارك هذا الرد


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

إن كنت تقصد برمجة الهاردوير (Programming Hardware Devices) فالأسمبلي و السي هما الأفضل ! :happy:

لكن ألا ترى أن السي "ضعيفة" جداً أمام الجافا في الأمور البسيطة التي ذكرتُها آنفاً ؟ :)

من غير العدل استخدام لفظة "ضعيفة"، بل الـC ليست موجهة لتلك الأمور "البسيطة" كما سميتها، فهي للأمور "الصعبة" smile.gif.

ألا ترى معي أني مخطيء أو غير منصف لو قلت أن الجافا "ضعيفة" في كتابة برامج "بسيطة" تستهدف real time systems . بل الجافا غير موجهة لذلك. هل لي أن أقول أن الجافا ضعيفة في التعامل مع Embedded systems مقارنة بالـC؟ لا لكنها غير موجهة لذلك.

بل سأذهب أبعد من ذلك وأقول صدق أو لا تصدق لغة الـC تستطيع انتاج برامج لا تعمل على نظام تشغيل! اذا الجافا ضعيفة أيضا في ذلك wacko.gif لانها لا تستطيع ذلك.

حتى لا يحتار البعض، البرامج الموجهة لـMicrocontrollers تعمل بلا نظام تشغيل laugh.gif.

تم تعديل بواسطه A.S Hack
2

شارك هذا الرد


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

من غير العدل استخدام لفظة "ضعيفة"، بل الـC ليست موجهة لتلك الأمور "البسيطة" كما سميتها، فهي للأمور "الصعبة" :)

صحيح :)

لكن أيضا من غير العدل استخدام لفظ "ستمقت لغة اسمها الجافا" عشان متزعلش الجافاويين :happy:

عموما, أرى أن التعامل مع "النصوص" و "الأعداد الضخمة" و "الملفات" و "الواجهات الرسومية" ليس بهذه البساطة التي نتوقعها, لأنك قد تحتاج إليه في أي وقت و حتى في برمجة بعض الأمور المتقدمة.

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

شارك هذا الرد


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

النقاط التي ذكرتها صحيحة ، لكن الخطأ في العنوان ، أنت تقارن لغة C مع Java ، كل لغة لها أهداف مختلفة و حتى نمط برمجي مختلف كما ذكر @A.S Hack ، لو قارنت Cpp مع Java لكانت المقارنة ممكنة ( مع بعض التحفظ ) . عموماً مقال منظم و مفيد بالمجمل ، مع أني أتمنى أن يخرج المبرمج من حصر نفسه في لغات معينة ، الآن أصبحنا نستخدم ٤ لغات برمجية في تطبيق واحد ، الأمر واسع ولا يحتاج لمزيد تفكير ، شكراً .

2

شارك هذا الرد


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

موضوع جميل و لكن لا أتفق معاك تماماً smile.gif

ما رأيك لو أعطيتك C# مثلاً و قولت لك برمج لي نافذة مكتوب عليها "مرحباً بكم" و لكن لم أوفر لك framework فهل ستستطيع أن تصممها؟

هنا ستحاول أن تكتب كود كثير جداً و تعتمد على API حتى تظهر النافذة و هو كما الحال مع الجافا فأنت تقول أنها مدعمه بأدوات تساعد على فتح و حفظ الملفات و لكن أليست هذه مكتبه مضافة للغه فأحذفها و قل لي هل تستطيع أن تفتح الملف؟

أخي العزيز

لغة C أو C++ هي لغات قياسية و إستخدام المكتبات معاها ليس فيه ضرر فهل ما يضرك هو أنك تعد الجافا فتجد معها ما تريده من مكتبات و لكن مع C أو C++ تتعب في إختيار مكتبه تتعامل معها أو تتعب في إعدادها مثلاً؟ smile.gif

أسف هذا ما فهمته من الموضوع و هو أنك تريد تجريد C و C++ ثم مقارنتها مع لغات أخرى مسلحة بكل مكتباتها بل يزيد على ذلك أنها مقارنه بين لغات ناتج كل واحده منهم يعمل بإسلوب مختلف عن الأخر.

2

شارك هذا الرد


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

أشكرك على الرد أستاذي الشمري :)

لكن حتى لو قارننا السي++ بالجافا فستظل النقاط السابقة موجودة ما عدا الفئة string !

السي++ القياسية لا تحتوي على BigInteger : (

لا يمكننا التأكد من عدم وجود ملف بطريقة قياسية, طبعا يمكننا فعل الأمر باستخدام الدالة exists الموجودة في المكتبة boost::filesystem لكن ليس هذا ما أقصده :)

الحل الأفضل (أو على الأقل الحل الذي يستخدمه أغلب مبرمجي السي++) هو استدعاء الدالة fail التي تُعيد true إذا كان الملف "موجود و قابل للقراءة"و false في الحالة المعاكسة, لكن هذا أيضا لا يضع الاصبع على الجرح ..

في السي++ القياسية أيضا, لا توجد دالة جاهزة يمكنها معرفة حجم الملف (دون فتحه), الطريقة الوحيدة هي فتح الملف و الإنتقال إلى آخر سطر فيه ثم حساب حجم البيانات الموجودة بين الموقعين, هكذا :

long GetFileSize( std::ifstream & Fichier )
{
long pos = Fichier.tellg();
Fichier.seekg( 0 , std::ios_base::end );
long size = Fichier.tellg() ;
Fichier.seekg( pos, std::ios_base::beg ) ;
return size ;
}

و بنفس الطريقة أيضا نقوم بنسخ الملفات إذ لا توجد دوال جاهزة لمثل هذه الأمور.

و هلم جرا ..

أخيراً و ليس آخراً, السي++ القياسية لا تحتوي على مكتبة واجهات رسومية ..

تقريباً, نفس نقاط الضعف باستثناء وجود الفئة string.

أسف هذا ما فهمته من الموضوع و هو أنك تريد تجريد C و C++ ثم مقارنتها مع لغات أخرى مسلحة بكل مكتباتها

أضف كلمة "قياسية" إلى عبارة "مكتباتها" :)

لو كانت توجد حلول قياسية للأمور التي ذكرتها فسيكون الأمر جميلاً جداً :)

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

شارك هذا الرد


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

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

على ما اعتقد ان كل شخص منا قد سأل نفسه هذا السؤال في وقت من الاوقات

برايي انه لكل لغه غرضها فلو كانت السي او السي بلس بلس كافيه و وافيه لما ظهرت جافا او سي شارب.

مثل ما اشار الاخوه أنفا ان لغة السي تناسب اجهزة الميكروكنترولر مع اني اعتب عليهم انهم لم يذكروا ان لغة جافا وسي شارب ايضا تستطيع ذلك Javalin, Netduino وغيره

لغة سي واسمبلي هي الاساس عندما تريد كتابة نظام تشغيل مثلا. كما انه يجب عليك ان لاتنسى ان اللغات الــ Managed لها ايضا مشاكلها التي لا تتضح إلا بعد ان يكبر البرنامج بشكل كبير جدا وهنا تظهر اكسبشنز لا تدري لما تظهر او من اي جاءت ، كما تبدأ بملاحظة تدهور في الاداء ، لا اتكلم عن برنامج المائتين سطر ولكن لقد عشت فعلا مشاكل البرامج الكبيرة التي تكتب باللغات الــ Managed بعض المكتبات التي انا رايت انها سبب مشاكل هي Monotouch, Devexpress.

ولكن دعنا نرى الامر من وجهة نظر اخرى: الى اين تسير عملية تطور لغات البرمجة؟ هل تسير نحو مشابهة لغة الانسان؟ او قرأة افكارة بحيث تولد برامج من افكار الانسان؟

الاجابة تختلف من شخص لاخر، برايي فإن مسالة مشابهة لغة البرمجة للغة الانسان كانت توجه قديم والتوجه الفعلي الملوحظ حاليا هو نحو تقليل عدد الاكواد التي يكتبها المبرمج cut the fluff وذلك عن طريق سبل تسريع كثيره منها مثلا الــ Lambda Expressions في سي شارب او بعض الــ Design Patterns التي اصبحت تظهر مدمجه في اللغات بحيث يتجنب المبرمج تطبيقها بشكل يدوي منها مثلا الــ Iterator كما تحتوي لغات مثل روبي على انماط كثيره بداخلها على ما اعتقد. المسألة هنا عبارة عن Revolutionize how we code اي كيف تعبر عن نفسك باقل عدد من الاسطر.

ولكن كل شيئ بحسابه ، اغلب البرامج ذات القيمه على حسب علمي ومعرفتي مكتوبه باسلوب Native وخاصه بلغة سي بلس بلس لانها توفر اداء افضل ولاسباب اخرى. ولكن يجب ان نضع ببالنا ان هناك قيود تفرض علينا اختيار اللغة ، فأنا مثلا اذا اوكل الي مشروع يتطلب عمل N-tier application using (PL, BLL,DAL) واستخدام Dependency Container وغيره سأجد اني لا استطيع اختيار لغة السي بلس بلس لانه لا توجد مثل هذه الاشياء في لغة سي بلس بلس او تحتاج اضافتها الى استخدام مكتبات Third party والقيام بربط يدوي وتغيير اعدادات الــ Compiler, Linker (في الحقيقه لم اجرب مثل هذه المشاريع على السي بلس بلس من قبل) ، هذه نقطه تستحق الوقوف عندها عن التطوير اما بالنسبة لمسألة الواجهات الرسوميه فاذا كان البرنامج موجه لويندوز فقط مثلا فأنا ارى ان استخدام سي او سي بلس بلس افضل حتى ولو عنى الامر كتابة كود مطول في الاخير ليس عليك ان تكتب كل سطر بنفسك هناك مايسمى بالنسخ و اللصق كما توجد ادوات كثيره توفرها بيئة التطوير مثل فيجوال ستوديو منها على السبيل الذكر الــ intellisense كما توجد انماط معروفه لاستخدام مثل هذه الاكواد التي يتبسط استخدامها مع الوقت وليس هناك داعي للوقوف امام حاجز رهبة الكود المشبك الذي يحتوي على عدد كبير من الاسطر لرسم نافذه.

وفي الاخير يجب ان نتذكر ان سي بلس بلس 11 اصبحت توفر الــ Lambda Expressions كما انك تستطيع ان تربطها مع بايثون كما انها توفر افضل Performance per dollar كما ذكر هيرب سوتر.

تحياتي.

1

شارك هذا الرد


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

السلام عليكم..

من ناحية السهولة والبساطة وما إلى ذلك، لغة Ruby تصبح أفضل لغة برمجة معروفة على الإطلاق - بحسب رأيي! لكن هذا بالتأكيد ليس حقيقًا بالضرورة، فهل يمكن استعمال Ruby في برمجة نظام تشغيل مثلًا؟! أقصد نظام تشغيل ذو مواصفات قياسية، وليس بسيطًا جدًا..


["1.html", "2.html", "2.html"].each do |x|
puts File.exists? x
end

تم تعديل بواسطه sitesmaker
-1

شارك هذا الرد


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

@mental-driller

كلامك جميل و عميق أيضاً, شكرا لك :)

@SM

للأسف, لا أعرف الكثير عن Ruby. كل ما أعرفه هو أنها لغة برمجية كائنية التوجه, حرة, ديناميكية, مفسرة, متعددة الوظائف بالإضافة إلى أنها تشبه Smalltalk في العديد من الأمور.

لكن قل لي :

هل هي مُوجهة للويب أكثر من تطبيقات الــ Desktop ؟

هل تدعم Ruby "المؤشرات" بشكل مباشر كما في السي و السي++ ؟

هل تحتوي على مكتبات GUI قياسية ؟

كخلاصة لما سبق و أن ذكرتُه, أقول :

عندما يشرع أحدنا في تعلم السي و يقوم مثلا بتنصيب IDE خفيف مثل Code::Blocks و يبدأ بتعلم أساسيات السي في بيئة الــ Console, سيحتاج إلى كتابة الكثير من التراكيب و الدوال الضرورية التي سيحتاج إليها في عمله, لأن فسلفة السي تعتمد على مقولة "اعمل كل شيء بنفسك فلا يوجد شيء جاهز !". بعد أن ينتهي صاحبنا من تعلم أساسيات السي و يصبح يفكر في الإنتقال إلى برمجة الواجهات الرسومية سيضطر إلى الإنتقال إلى بيئة جديدة لا علاقة لها بالمكتبات القياسية التي كان يعمل عليها ..

أما في الجافا فأرى أن الأمر بسيط جداً, لأنه إذا قام صاحبنا بتحميل IDE قوي و ليكن NetBeans فسيجد كل ما يحتاج إليه متوفراً و قياسي أيضا و بالتالي لن يحتاج إلى التنقل هنا أو هناك لكي يحصل على خدمة جديدة.

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

تحياتي.

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

شارك هذا الرد


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

لأن فسلفة السي تعتمد على مقولة "اعمل كل شيء بنفسك فلا يوجد شيء جاهز !".

هذه ليست فلسفة السي، بل فلسفة من يستخدم السي لكتابة برامج الـend users. أي أنها فلسفة من يوجه هذه اللغة لغير ما أوجدت له.

مبرمجو السي لن يضطروا لقول ذلك أصلا، ولكن من ينظر للسي وهو على وسادة قطنية مثل الجافا، سيقول ذلك، والأصل أنه غير مضطر لذلك، لأن المقارنة مغلوطة.

لك أن تقول أن فلسفة السي تقول للمبرمج: افعل كل ما تريد فعله! سأسمح لك أن تفعل "كل شيء" .. وكل شيء تتضمن "الأخطاء".

تم تعديل بواسطه Adban
2

شارك هذا الرد


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

من ينظر للسي وهو على وسادة قطنية مثل الجافا

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

لك أن تقول أن فلسفة السي تقول للمبرمج: افعل كل ما تريد فعله! سأسمح لك أن تفعل "كل شيء"

"سأسمح لك أن تفعل كل شيء" لا تتعارض أبداً مع "سأقدم لك الأشياء التي تستعملها بشكل يومي من أجل اختصار الوقت" !!

0

شارك هذا الرد


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

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

المشكلة في كلامك يكمن في قولك "التي يستخدمها المبرمج بشكل شبه يومي"...

الأمر نسبي، فلا يعدل من يحصر "المبرمج" و "استخدام المبرمج" في برامج سطح المكتب أو الويب الموجهة للمستخدم end user.. ثم يأتي ليقارن لغات البرمجة ....لذا "الدوال التي يستخدمها المبرمج بشكل شبه يومي" جملة هلامية، فمن هو المبرمج وماذا يبرمج، ثم لك أن تبحث عن ماهي الدوال الشبه يومية التي يستخدمها، ثم لك أن تقول ماهي اللغة المُثلى "الموجهة" لظروفه. ثم بعدها ليس لك الحق أن "تُقوي" لغة على أخرى بسبب الظرف "المحدد" الذي تتكلم عنه.

مبرمجو السي يرون أن السي وفرت لهم كل ما يحتاجونه بشكل "جاهز"، وفرت لهم المؤشرات، وفرت لهم دوال ادارة الذاكرة، وفرت لهم مرونة للتحكم في موارد الجهاز.. الخ، هذا كله "جاهز" لهم.

أرأيت لماذا أعارضك في الفلسفة المغلوطة التي ذكرتها للغة مثل ال السي.؟؟

ثم مسألة أخرى: حينما تقول "برمجة صواريخ" ... :sleep:

هل أفهم منها أنك تقول أن لغة مثل C يُحصر استعمالها في ما هو بعيد عن الاستخدام؟؟

تم تعديل بواسطه Adban
2

شارك هذا الرد


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

لمشكلة في كلامك يكمن في قولك "التي يستخدمها المبرمج بشكل شبه يومي"... الأمر نسبي

"النسبية" موجودة في كل شيء يا عزيزي !

و إذا قمتُ بالرد عليك في هذه النقطة, سيتحول الموضوع في النهاية إلى "كلام فلسفي" لا دخل للبرمجة فيه ..

لكنني أؤكد لك أنه لا يختلف اثنان على أن الدوال التي ذكرتُها في بداية الموضوع تُعتبر من الدوال "الكثيرة الإستخدام" و يجب أن تتوفر في أي لغة برمجة مهما كان هدفها.

وفرت لهم دوال ادارة الذاكرة

السي لا توفر مكتبة خاصة بالــ Memory allocation functions, أيضا الدوال "القياسية" الموجودة قليلة جدا :

malloc, calloc, realloc, free, memcpy, memmove, memchr, memcmp, memset

و إذا احتاج المبرمج إلى التعامل مع بعض الأمور المتقدمة في إدارة الذاكرة فسيحتاج إلى كتابتها بنفسه .. عُدنا للمربع الأول !!

ثم مسألة أخرى: حينما تقول "برمجة صواريخ" ... :sleep:

هل أفهم منها أنك تقول أن لغة مثل C يُحصر استعمالها في ما هو بعيد عن الاستخدام؟؟

لا تعليق ..!

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

شارك هذا الرد


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

"النسبية" موجودة في كل شيء يا عزيزي !

و إذا قمتُ بالرد عليك في هذه النقطة, سيتحول الموضوع في النهاية إلى "كلام فلسفي" لا دخل للبرمجة فيه ..

لكنني أؤكد لك أنه لا يختلف اثنان على أن الدوال التي ذكرتُها في بداية الموضوع تُعتبر من الدوال "الكثيرة الإستخدام" و يجب أن تتوفر في أي لغة برمجة مهما كان هدفها.

السي لا توفر مكتبة خاصة بالــ Memory allocation functions, أيضا الدوال "القياسية" الموجودة قليلة جدا :

malloc, calloc, realloc, free, memcpy, memmove, memchr, memcmp, memset

و إذا احتاج المبرمج إلى التعامل مع بعض الأمور المتقدمة في إدارة الذاكرة فسيحتاج إلى كتابتها بنفسه .. عُدنا للمربع الأول !!

لا تعليق ..!

ما الحكمة من زيادة عدد الدوال ما دمت أستطيع فعل أي شيء بها.

هذه الدوال القليلة وفرت كل المرونة لمبرمجي السي لانتاج مكوّن مثل Sun JVM الخاص ببرامج ولغة جافا. تم عجن garbage collector للجافا بأيدي رجال السي.. فصنعوا لغة "لانتاج برامج المستخدم النهائي".

ثم يأتي بعدها أحدهم ويقول "أشك" في لغة السي. !

0

شارك هذا الرد


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

ما الحكمة من زيادة عدد الدوال ما دمت أستطيع فعل أي شيء بها ؟

تستطيع أن تفعل بها أي شيء ؟ .. جميل جداً ! :)

طيب, هل يمكنك كتابة دالة (بالسي القياسية) تستقبل وسيط واحد عبارة عن مؤشر من نوع void و تُعيد سلسلة محارف تحوي اسم النوع الذي يُشير إليه المؤشر ؟؟

هذه الدوال القليلة وفرت كل المرونة لمبرمجي السي لانتاج مكوّن مثل Sun JVM الخاص ببرامج ولغة جافا. تم عجن garbage collector للجافا بأيدي رجال السي.. فصنعوا لغة "لانتاج برامج المستخدم النهائي".

ثم يأتي بعدها أحدهم ويقول "أشك" في لغة السي. !

المبرمجون الذين كتبوا الــ GC لم يقولوا أنهم "عجنوه" و لم يقولوا أيضا أنهم "صنعوا لغة .." ..

ثم يأتي بعدها أحدهم ويقول "تم عجن الــ GC" في لغة الجافا !!

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

شارك هذا الرد


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

تستطيع أن تفعل بها أي شيء ؟ .. جميل جداً ! :)

طيب, هل يمكنك كتابة دالة (بالسي القياسية) تستقبل وسيط واحد عبارة عن مؤشر من نوع void و تُعيد سلسلة محارف تحوي اسم النوع الذي يُشير إليه المؤشر ؟؟

لماذا تشدد في أمر قد يسره الله وتجبرني على امرار وسيط واحد!

لماذا تجبرني على عدم استخدام ميزة "إمكانية تعدد الوسائط"التي يمكن امرارها في دالة مكتوبة بلغة السي! أليست هذه ميزة قياسية في اللغة؟

ثم أنت تواصل بهذا سلسلة مغالطاتك! فسؤالك لا يختلف عن سائل يسأل فيقول:

كيف أستطيع أن أحجز ذاكرة وأحررها دون استخدام دوال التحرير في لغة السي القياسية!

يعني أنت الآن وصلت لمرحلة تقول لي فيها: لديك عينان ولكن لا تنظر بهما! واعجبي!

كل ما رأيته من ردودك الآن - وما سأراه - يدخل في باب "العناد"، وأكاد أجزم أنك فهمت مقصد من ردوا عليك.

المبرمجون الذين كتبوا الــ GC لم يقولوا أنهم "عجنوه" و لم يقولوا أيضا أنهم "صنعوا لغة .." ..

ثم يأتي بعدها أحدهم ويقول "تم عجن الــ GC" في لغة الجافا !!

هذه لا تعدو "حديث نفس".

1

شارك هذا الرد


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

للفائدة :) :

الحل القياسي يكون باستخدام الــ Generic function حيث يتم تمرير وسيطين إلى الدالة. الوسيط الأول هو مؤشر void و الثاني يُمثل حجم أو نوع المتغير, هكذا :

typedef enum {
TYPES_char,
TYPES_short,
TYPES_int,
TYPES_long,
TYPES_float,
TYPES_double
} TypePtr;

void MyFunction(void * Ptr, TypePtr Type);

نفس الشيء إذا أردنا المرور على عناصر مصفوفة مجهولة النوع, قد تكون مصفوفة من int أو float أو حتى مصفوفة تراكيب, الحل سيكون باستخدام generic function حيث سنقوم بتمرير عدد عناصر المصفوفة و حجم كل عنصر بالإضافة إلى مؤشر void هكذا :

void parcours( void * data , size_t nb_elt , size_t size )
{
size_t i;
for( i = 0 ; i < nb_elt ; ++i )
{
printf("%p\n", data + (i * size) );
}
}

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

شارك هذا الرد


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

  1. http://stackoverflow.com/questions/230062/whats-the-best-way-to-check-if-a-file-exists-in-c-cross-platform لمعرفة وجود الملف او لا
  2. معرفة حجم الملف في الجافا يتم عن طريق Native Methods
  3. مكتبة org.apache.commons.io.IOUtils ليست مكتبة قياسية بلغة الجافا بل مكتبة خارجية
  4. قرأة الملفات في الجافا تستخدم بالتعاون مع Native Methods ايضا

4

شارك هذا الرد


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

الدالة _access ليست قياسية و كذلك _waccess :)

أيضا بقية الحلول سبق و أن ذكرتها و هي غير قياسية (stat, fstat, erno).

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

شارك هذا الرد


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

أخي العزيز khaled_prg

هل يمكنك أن تعطيني الطريقة القياسية في الجافا التي تعطيني إمكانية إنشاء ملف على قسم من الهارد ديسك تم تهيئتة بـ NTFS على سبيل المثال؟

لا داعي للسؤال السابق فهو صعب فهل يمكنك أن تعطيني الطريقة القياسية في الجافا التي تعطيني الحجم فقط لملف مخزن في قسم من الهارد تم تهيئته بـ EXT4 على سبيل المثال؟

إذا ذكرت لي أي مكتبة مصاحبه للجافا و قولت أنها قياسية بحجه أنها تأتي مع لغة الجافا فإذاً لم تفهم مقصدي من الأسئلة السابقة smile.gif

الأخ .S.T.A.L.K.E.R و هو مشرف قسم الجافا يقول لك مثلاً لمعرفة حجم الملف في الجافا يتم عن طريق Native Methods وأنت تتجاهل كلامة و تركز على النقطة الأولى فقط

ما الهدف من الموضوع؟

بدأت أمل من الموضوع sad.gif

0

شارك هذا الرد


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

مرحباً بك أخي الكريم :)

أوكي, نكتفي بهذا القدر من النقاش.

أظن أن الآراء كانت متقاربة إلى حد ما, ما أردت لفت الإنتباه إليه هو وفرة المكتبات التي تأتي جاهزة مع معظم لغات البرمجة (الجافا على سبيل المثال) بينما نجد أن السي دائما ما تكون النسخة القياسية منها منفردة عن بقية المكتبات الأخرى مع العلم أنه يُمكننا كتابة كل ما نريده باستخدام المكتبات القياسية فقط, لكن الأمر قد يكون مُعقداً لدى البعض و "حماسياً" لدى البعض الآخر :cool:

سأطرح بعد قليل موضوعا جديداً يحمل في طياته أسئلة من نوع آخر .. تقودنا إلى نقاش جديد ..

.. أرجو أن يكون مُفيداً, ودياً و مختلفاً :happy:

تحياتي.

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

شارك هذا الرد


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

السلام عليكم

معلومه حقيقاً لا أعلمها ولكنها ربما توضح بعض الأمور

- سنه صدور أخر نسخة قياسية من لغة الـ C

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

1

شارك هذا الرد


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

توفر سي دوال قياسية لتعامل مع اليونيكود مدرجة في الملف wchar.h وبالنسبة للأخطاء فهناك errno.h وهي قياسية أيضاً :

#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <wchar.h>

void open_or_throw_error(char *filename);

int main(int argc, char **argv)
{
open_or_throw_error("blabla_notexist.txt");
fprintf(stderr, "Error while opening 'blabla_notexist.txt': %s\n", strerror(errno));
assert(errno == ENOENT);

wchar_t *say_hi = L"Hello wide char world!";

wprintf(L"%s (%d bytes in size)\n", say_hi, wcslen(say_hi) * sizeof(wchar_t));

return 0;
}

void open_or_throw_error(char *filename)
{
FILE *fh = NULL;

if( (fh = fopen(filename, "r")) == NULL )
perror("Error");
else
fclose(fh);
}

إذا كان هناك خطأ فيُمكن معرفة السبب بقراءة قيمة errno.

بعض أخطاء الملفات , الباقي موجود في الملف errno.h :

EPERM   -> عملية مرفوضة
ENOFILE -> الملف أو المجلد غير موجود
EBADF -> إسم غير صالح
ENOMEM -> لاتوجد مساحة كافية
EACCES -> الوصول مرفوض
EEXIST -> الملف موجود أصلاً
ENOTDIR -> ملف وليس مجلد
EISDIR -> مجلد وليس ملف
EROFS -> للقراءة فقط
....

معيار posix قياسي وأشمل وموجة لبرمجة النظم. أغلب الأنظمة من بينها ويندوز تطبق أغلب معايير POSIX 1.0 والذي يضم سي ودوال التعامل مع الملفات.

الإختلاف بين سي وجافا أن الأولى موجة لبرمجة النُظم والثانية موجة لبرمجة التطبيقات ولاوجود لها في مجال النظم, يُمكن إستخدامها عن طريق JNI ويتم بالسي لكن لن يُصبح البرنامج محمول بل يلزم إعادة تصريفة لك نظام.

عندما يقال برمجة النُظم فلا يُعنى برمجة نظام تشغيل بإستخدام سي, فالأنظمة التي كتبت بها لاتتعدى أصابع اليد الواحدة, بل المقصود النوع الأخر من من البرمجة (أنواع البرامج : 1- التطبيقات 2- برامج النظم) "وتعني البرمجة لنظام التشغيل بإستخدام دواله وواجهته البرمجية".

أي لُغة لايُمكن لها الوصول للملفات بنفسها. فهذا شيء مسؤول عنه نظام التشغيل والنواة. فحتى سي وجافا تستخدم واجهة النظام البرمجية وتغلفها, إنظر للجزء الخاص بالقراءة والكتابة على ويندوز في openjdk, وبالتحديد الملف io_util_md.c.

موضوع الواجهات فليس سهلاً أن تجعل واجهة رسومية قياسية لإختلاف العتاد, فهذا أندرويد وبلاكبيري يستخدمان جافا ولكن لاتعمل فيهما مكوناتها الرسومية.

رغم هذا فهناك العديد من المكتبات الرسومية وأغبها كتبت بالسي ولايُوجد شيء يمنع من تحميلها.

الفئة string في C++ تعمل تماماً كهذا البرنامج :

/* @file: test.c
*/
#include <stdio.h>
#include "stringtype.h"

int main(int argc, char **argv)
{
StringType *hello = string_new("Hello"); /* string *hello = new string("Hello"); */

printf("%s\n", string_get_string(hello)); /* printf("%s\n", hello->c_str()); */

string_join(hello, " C"); /* *hello += " C"; */
printf("%s\n", string_get_string(hello)); /* printf("%s\n", hello->c_str()); */

string_join(hello, " World!"); /* *hello += " World!" */
printf("%s\n", string_get_string(hello)); /* printf("%s\n", hello->c_str()); */

string_destroy(hello); /* delete hello; */
return 0;
}

/* @file: stringtype.h
*/
#ifndef __STRINGTYPE_H__
#define __STRINGTYPE_H__

typedef struct _StringType StringType;

#ifdef __cplusplus
extern "C" {
#endif

StringType *string_new(char *str);
char *string_get_string(StringType *string);
int string_join(StringType *string, char *str);
void string_destroy(StringType *string);

#ifdef __cplusplus
};
#endif

#endif /* __STRINGTYPE_H__ */

/* @file: stringtype_private.h
*/
#ifndef __STRINGTYPE_PRIVATE_H__
#define __STRINGTYPE_PRIVATE_H__

typedef struct _StringType {
size_t lenght;
int alloc;
char *buff;
} StringType;

#endif /* __STRINGTYPE_PRIVATE_H__ */

/* @file: stringtype_private.c
*/
#include <string.h>
#include <stdlib.h>

#include "stringtype.h"
#include "stringtype_private.h"

StringType *string_new(char *str)
{
StringType *string = NULL;

if( (string = (StringType *) malloc(sizeof(StringType))) == NULL )
return NULL;

string->lenght = strlen(str);
string->alloc = 1;

if( (string->buff = (char *) malloc(sizeof(char) * (string->lenght + 1))) == NULL )
return NULL;

strncpy(string->buff, str, string->lenght);

return string;
}

char *string_get_string(StringType *string)
{
return string->buff;
}

int string_join(StringType *string, char *newpart)
{
char *temp = NULL;
size_t len = strlen(newpart);

if( (temp = (char *) malloc(sizeof(char) * (string->lenght + len + 1))) == NULL )
return -1;

strncpy(temp, string->buff, string->lenght);
strncat(temp, newpart, len);

free(string->buff);
string->buff = temp;
string->lenght += len;

return 0;
}

void string_destroy(StringType *string)
{
if( string->alloc )
free(string->buff);
free(string);
}

لتصريفه :

gcc test.c stringtype_private.c

الا أن إعادة تعريف المعاملات في C++ تخفي عنك الكثير من تلك الوظائف.

....السي لا توفر مكتبة خاصة بالــ Memory allocation functions, أيضا الدوال "القياسية" الموجودة قليلة جدا :

malloc, calloc, realloc, free, memcpy, memmove, memchr, memcmp, memset

و إذا احتاج المبرمج إلى التعامل مع بعض الأمور المتقدمة في إدارة الذاكرة فسيحتاج إلى كتابتها بنفسه .. عُدنا للمربع الأول !!

سي توفر دوال قياسية لتخصيص الذاكرة, وهي المشار إليها بالأحمر. وبالمناسبة لايُمكن للمبرمج كتابة دالة للتعامل مباشرة مع الذاكرة, لأن هذا الشيء مثل الملفات مسؤولية نظام التشغيل.

تستطيع أن تفعل بها أي شيء ؟ .. جميل جداً ! :)طيب, هل يمكنك كتابة دالة (بالسي القياسية) تستقبل وسيط واحد عبارة عن مؤشر من نوع void و تُعيد سلسلة محارف تحوي اسم النوع الذي يُشير إليه المؤشر ؟؟

السي تتعامل مباشرة مع الذاكرة ولاتوجد هناك أي طريقة لمعرفة نوع البيانات من النظر فالذاكرة, في أي لغة. فلو قرأت أربع بايتات من الذاكرة وظهر لك :

+------+------+------+------+
| 0x68 | 0x67 | 0x66 | 0x65 |
+------+------+------+------+

فلا تستطيع الجزم هل هذه الرقم 1701209960 أم ABCD, فكلاهما يظهران بنفس الشكل. يقوم مبرمجين سي بإنشاء نوع من بنية وإضافة وسم tag بنوع هذه البيانات, مثال :

/* @file: test.c
*/
#include <stdio.h>
#include "types.h"

int main(int argc, char **argv)
{
Types *one = types_string_new("Types test");
Types *two = types_char_new('B');
Types *three = types_int_new(12345);
Types *four = types_float_new(12.234);

printf("one = %s\n", types_get_type_string(one));
printf("two = %s\n", types_get_type_string(two));
printf("three = %s\n", types_get_type_string(three));
printf("four = %s\n", types_get_type_string(four));

types_destroy(one);
types_destroy(two);
types_destroy(three);
types_destroy(four);

return 0;
}

/* @file: types.h
*/
#ifndef __TYPES_H__
#define __TYPES_H__

typedef enum _TypesDataTypes {
TYPES_STRING = 0,
TYPES_CHAR,
TYPES_INT,
TYPES_FLOAT
/* @TODO: more types ... */
} TypesDataTypes;

typedef struct _Types Types;

#ifdef __cplusplus
extern "C" {
#endif

Types *types_string_new(char *type_string);
Types *types_char_new(char type_char);
Types *types_int_new(int type_int);
Types *types_float_new(float type_float);

TypesDataTypes types_get_type(Types* type);
const char *types_get_type_string(Types* type);
void types_destroy(Types* type);

#ifdef __cplusplus
};
#endif

#endif /* __TYPES_H__ */

/* @file: types_private.h
*/
#ifndef __TYPES_PRIVATE_H__
#define __TYPES_PRIVATE_H__

#include "types.h"

const char *_types_names_string[] = {
"string",
"char",
"int",
"float"
};

typedef struct _Types {
TypesDataTypes tag;
int alloc;
union {
char *type_string;
char type_char;
int type_int;
float type_float;
} buff;
} Types;

#endif /* __TYPES_PRIVATE_H__ */

/* @file: types_private.c
*/
#include <string.h>
#include <stdlib.h>

#include "types.h"
#include "types_private.h"

static Types *_types_new(void);

static Types *_types_new(void)
{
Types *type = NULL;

if( (type = (Types*) malloc(sizeof(Types))) == NULL)
return NULL;

memset(type, 0, sizeof(Types));

return type;
}

Types *types_string_new(char *type_string)
{
Types *type = NULL;

if( (type = _types_new()) == NULL )
return NULL;

type->buff.type_string =
(char *) malloc(sizeof(char) * (strlen(type_string) + 1));
if( type->buff.type_string == NULL ) {
free(type);
return NULL;
}

type->tag = TYPES_STRING;
type->alloc = 1;

strncpy(type->buff.type_string, type_string, strlen(type_string));

return type;
}

Types *types_char_new(char type_char)
{
Types *type = NULL;

if( (type = _types_new()) == NULL )
return NULL;

type->tag = TYPES_CHAR;
type->alloc = 0;

type->buff.type_char = type_char;

return type;
}

Types *types_int_new(int type_int)
{
Types *type = NULL;

if( (type = _types_new()) == NULL )
return NULL;

type->tag = TYPES_INT;
type->alloc = 0;

type->buff.type_int = type_int;

return type;
}

Types *types_float_new(float type_float)
{
Types *type = NULL;

if( (type = _types_new()) == NULL )
return NULL;

type->tag = TYPES_FLOAT;
type->alloc = 0;

type->buff.type_float = type_float;

return type;
}

TypesDataTypes types_get_type(Types* type)
{
return type->tag;
}

const char *types_get_type_string(Types* type)
{
return _types_names_string[type->tag];
}

void types_destroy(Types* type)
{
if( type->alloc )
free(type->buff.type_string);
free(type);
}

لتصريفه :

gcc test.c types_private.c

جافا أحد أكثر اللغات وفرة بالمكتبات الخارجية, ولم تظهر تلك المكتبات الا لأنه مستحيل بناء لغة لكل شيء. وأيضاً إعادت كتابة كل شيء من الصفر إذا توفرت مكتبات جاهزة ومناسبة, مضيعة للوقت والمجهود.

من يواجه نفس تلك المشاكل مع سي, فهناك مكتبة GLib , التحميل, مكتبة كانت جزء من GTK ثم إنفصلت عنها في مكتبة مستقلة ويمكن إستخدامها دون الحاجة لـGTK. تعمل على العديد من الأنظمة, من بينها ويندوز.

وتوفر وظائف متنوعة للتعامل مع النصوص والملفات والعمليات والذاكرة والوقت وتراكيب البيانات ومعالجة النصوص وغيرها من الوظائف التي يحتاجها مطورين التطبيقات, تشبه boots في C++.

3

شارك هذا الرد


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

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

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