إسماعيل ابراهيم

مجموعة إجابات لأسئلة تتكرر كثيرا FAQ - مهم جدّاً.

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

نورد هنا سين و جيم , لأسئلة تتكرر, وقد تتكرر كثيرا, هذه الاجابات قمت بإعدادها انا وأخي محمد

muhammad ... دعوني أشكر اخي muhammad لأن جهوده كبيره في المنتدى لكنه يعمل كالجندي المجهول ترى فعائله ولا تراه ... فتحياتي لك وشكري أخي محمد...

ملاحظة:

بما أن هذا الموضوع سيكون مغلقا.. فإنك مدعو لطرح تسائلاتك , وآرائك في هذا الموضوع : ملحق FAQ - تعليقات وتسائلات

------------------------------------------------------------------------------------

كيف تجعل البرنامج يتوقّف منتظرا ضغطة على لوحة المفاتيح؟

كيف تحاكي الامر pause في دوس حيث ترى الجملة

: Press Any key to continue...

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

هناك - في الحقيقة - عدة طرق لفعل هذا... وكلّها تؤدي الغرض بدون مشاكل...

سنورد عدة أكواد هنا, اذا لم يعمل معك أحدها إسأل عن هذا في المنتديات..

الطريقة الاولى, وهي بلغة سي, وباستخدام الدالة القياسية getchar :

--------------------------------------------------------------------

#include <stdio.h> 



int main(void)

{

 int ch;

 printf ("Press [Enter] to continue");

 while ((ch = getchar()) != 'n' && ch != EOF);

 return(0);

}

---------------------------------------------------------------------

الكود الثاني خاص بلغة سي++:

--------------------------------------------------------------------

#include <iostream> 



int main(void)

{

 std::cout <<"Press [Enter] to continue" <<std::endl;

 std::cin.get();

 return(0);

}

------------------------------------------------------------------

وهناك طريق رديئة للقيام بهذا, وهي باستخدام دالة النظام pause ..

-----------------------------------------------------------------

#include <stdlib.h> 



int main(void)

{

 system ("pause");

 return(0);

}

-----------------------------------------------------------

طريقة أخرى:

----------------------------------------

#include <stdio.h> /* for printf() */ 

#include <conio.h> /* for getch()  */



int main(void)

{

  printf("Press a key to continue...");

  getch();

  return 0;

}

-----------------------------------------------------

الطريقة التالية خاصة بنظام يونيكس:

----------------------------------------------------

#include <stdio.h> 

#include <termios.h>

#include <unistd.h>



int mygetch(void)

{

 struct termios oldt,

                newt;

 int            ch;

 

 tcgetattr( STDIN_FILENO, &oldt );

 newt = oldt;

 newt.c_lflag &= ~( ICANON | ECHO );

 tcsetattr( STDIN_FILENO, TCSANOW, &newt );

 ch = getchar();

 tcsetattr( STDIN_FILENO, TCSANOW, &oldt );

 

 return ch;

}

------------------------------------------------------------------------------------

كيف تمسح الشاشة؟

ربما يبدو موضوع مسح الشاشة بسيطا... لكن الاجابة عن السؤال : كيف نمسح الشاشة؟ ليس بهذه البساطة...

المشكلة الرئيسية في الموضوع, أنه لا سي ولا سي++ تقدم لنا وسيلة موثوقة لمسح الشاشة.. وذلك لأن اللغة بُنيت لتكون لغة مستقلة عن بيئة التشغيل, بمعنى ان برامجها تعمل في اي بيئة..(دوس..يونكس..الخ), وأي تعامل من هذا النوع مع الشاشة سيؤثر على إستقلاليّة برنامجك عن بيئة التشغيل. هذا الامر يجب أن تنتبه اليه دائما وانت تبرمج.

الحل هو أن تقرأ وثائق المترجم الذي معك, لتجد لك أي دالة غير قياسية تقوم بالواجب:

الخيار الاول:

إذا كان مترجمك يدعم الدالة ()clrscr فاستعملها :

---------------------------------------

#include <conio.h> 



int main(void)

{

 clrscr();

 return(0);

}

---------------------------------------

إيجابيات الطريقة أعلاه: بسيطة,سريعة..

سلبياتها: فقط عدد من المترجمات تدعمها.

الخيار الثاني :

وهو استخدام الدالة ()putchsr لكي نضع عدد من الاسطر الفارغة.. مما يؤدي الى صعود كل شيء مكتوب على الشاشة الى الاعلى حتى يختفي :

------------------------------------

#include <stdio.h> 



int main(void)

{

 int i;

 

 for (i = 0; i < 25; i++)

   putchar ('n');

   

 return(0);

}

-------------------------------------------

الايجابيات: انها تعمل :)

السلبيات: ليس كل الشاشات تحتوي على نفس عدد الاسطر, أضف الى ذلك انها طريقة بطيئة

الطريقة الثالثة:

استخدام مكتبة خاصة بوضع النص مثل المكتبة curses.h ... :

-------------------------------------------------------

#include <curses.h> 



void clrscr(void)

{

   static int init;



   if (init == 0)

   {

       initscr();

       init = 1;

   }



   clear();

   refresh();

}

--------------------------------------------

ايجابيات: برنامجك قابل للنقل(يعمل على أي بيئة).. ويشترط أت تكون عندك هذه المكتبة,

السلبيات: عليك في المقام الاول الحصول على هذه المكتبة..(curses)

-------------------------------------------------------

الطريقة الرابعة (لا يتوفر كود)... وهي :

الكتابة بطريقة مباشرة الى ذاكرة الشاشة , ومسح كل البتات (bits) ...

الايجابيات : الطريقة تعمل!

السلبيات : بعض نظم التشغيل لا تسمح لك بالوصول المباشر الى العتاد لذا لا تتوقع ان تكون هذه الطريقة قابلة للنقل بين عدة بيئات ...

-----------------------------

الطريقة الخامسة:

استعمل أمر النظام cls ..

-----------------

include <stdlib.h> 



int main(void)

{

 system ("cls"); /* Or system ("clear"); for Unix */

 return(0);

}

-----------------------------------

طريقة لا تلجأ اليها الاّ مضطرّا :)

************************************************

مسح شاشة Console في نظام ويندوز:

- ما عليك الا نسخ هذه الدالة... واستدعائها متى تشاء:

#include <windows.h> 



void clrscr(void)

{

   COORD                       coordScreen = { 0, 0 };

   DWORD                       cCharsWritten;

   CONSOLE_SCREEN_BUFFER_INFO  csbi;

   DWORD                       dwConSize;

   HANDLE                      hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

   GetConsoleScreenBufferInfo(hConsole, &csbi);

   dwConSize = csbi.dwSize.X * csbi.dwSize.Y;

   FillConsoleOutputCharacter(hConsole, TEXT(' '),

                              dwConSize, coordScreen, &cCharsWritten);

   GetConsoleScreenBufferInfo(hConsole, &csbi);

   FillConsoleOutputAttribute(hConsole, csbi.wAttributes,

                              dwConSize, coordScreen, &cCharsWritten);

   SetConsoleCursorPosition(hConsole, coordScreen);

}

-------------------------------------

طريقة أخيرة: هناك طريقة لمسح الشاشة : إجلب فرشاة وصابون.. و......... :) بلاش:).

*/*/*/*/*//*/*/*//*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/

طريقة توليد ارقام عشوائية:----------------------

للحصول على ارقام عشوائية , يمكنك استخدام الدالة ()rand وهو معرفة في stdlib.h (أو cstdlib.h في سي++) سترجع لك الدالة عدد بين 0 الى RAND_MAX وهو رقم معرف في stdlib.h الذي قد يصل الى 32767 .

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

#include <stdlib.h>

int rand(void);

void srand(unsigned int seed);

الرقم الذي تمرره كمعامل parameter الى الدالة ()srand يستحثّ مولد الارقام, اذا قمت بتمرير نفس الرقم دائما, فستحصل على نفس المجموعة من الارقام العشوائة, وللحصول على مجموعات مختلفة كل مرة, عليك ان تمرر رقم مختلف كل مرة.. أكثر الطرق شيوعا لتمرير عدد مختلف كل مرة هو استدعاء الدالة ()time وتمرير نتيجتها الى دالة srand ...

-------------------------------------------------

/*

* This code is written in C, but it could just as easily be done in C++.

* The rand() and srand() functions are available in both languages.

*/



#include <stdio.h>  

#include <stdlib.h>  

#include <time.h>  



int main(void)

{

 int i;

 

 srand(time(NULL));

 

 i = rand();

 

 printf ("Your random number is %dn", i);  



 printf ("This compiler can generate random numbers from 0 to %dn", RAND_MAX);



 return(0);

}

---------------------------------------------------------

نسخة ال سي++ من نفس البرنامج اعلاه :

#include <iostream>   

#include <ctime>  



int main(void)

{

 int i;    

 

 srand(time(NULL));    

 i = rand();  

 std::cout <<"Your random number is " <<i <<std::endl;  

 std::cout <<"This compiler can generate random numbers from 0 to "

           <<RAND_MAX <<std::endl;

 

 return(0);

}

--------------------------------------------------------------------

للحصول على ارقام في مجال محدد, عليك القيام بعمليات رياضياتيّة (نسبة الى الرياضيات, وليس رياضية نسبة الى رياضة)..

العملية الرياضية هي أن تحصل أولا على ارقام عشوائية من صفر بطول المجال المرغوب فيه( المجال هنا هو الفرق بين الرقم الاصغر والرقم الاكبر ), كيف نفعل هذا ... لنفرض أننا نريد ارقام عشوائية بين 10 و 18

طول المجال هنا هو 8 , للحصول على ارقام عشوائية من 0 الى 8 ماذا نفعل؟ نحصل على اي رقم عشوائي, ثم نجد الباقي من قسمتهب 8 +1 (%) نحن نعرف أن باقي القسمة في هذه الحالة لن يتخطّ 8 ... الان حصلنا على رقم بين 0 و 8 , لكي نحله الى رقم نت 10-8 نجمع له الرقم 10 ...فاذا حصلنا على:

---------------

0 - سيتحول الى 10

1 - سيتحول الى 11

.

.

7- سيتحول الى 17

8- سيتحول الى 18

----------------

هذا الكود :

---------------------------------------------------------------

#include <stdio.h> 

#include <stdlib.h>



int GetRand(int min, int max);



int main(void)

{

 int i, r;

 

 for (i = 0; i < 20; i++)

 {

   r = GetRand(10, 12);

   printf ("Your number is %dn", r);

 }

 

 return(0);

}



int GetRand(int min, int max)

{

 static int Init = 0;

 int rc;

 

 if (Init == 0)

 {

   /*

    *  As Init is static, it will remember it's value between

    *  function calls.  We only want srand() run once, so this

    *  is a simple way to ensure that happens.

    */

   srand(time(NULL));

   Init = 1;

 }



 /*

  * Formula:  

  *    rand() % N   <- To get a number between 0 - N-1

  *    Then add the result to min, giving you

  *    a random number between min - max.

  */  

 rc = (rand() % (max - min + 1) + min);

 

 return (rc);

}

-------------------------------------------------------------------

التغييرات اللازمة ليصبح الكود أعلاه مناسبا ل سي++:

-----------------------------------------------

#include <iostream> 

#include <ctime>



int main(void)

{

 int i, r;



 for (i = 0; i < 20; i++)

 {

   r = GetRand(10, 12);

   std::cout <<"Your number is " <<r <<std::endl;

 }



 return(0);

}

-----------------------------------------------------

كيف تشغل برنامج من داخل برنامجك

هناك الكثير من الطرق لتشغيل برنامج من داخل برنامجك ، هنا سنعرض بعض الطرق لعمل ذلك مع ذكر محاسن ومساوئ كل طريقة وعليك اختيار ما يناسبك منها حسب نوع البرنامج وال compiler المستخدم في الترجمة .

1- الدالة system

نموذج التابع

int system(const char* s);

هذه الدالة تقوم بتنفيذ او تشغيل الأمر الذي بين القوسين واذا كان برنامج ستقوم بتشغيله وتعيد الدالة القيمة صفر اذا نجحت بتنفيذ الأمر وتعيد أي قيمة غير الصفر اذا لم تنجح بالتنفيذ ، ولكن لا ينصح باستخدام هذه الدالة لعدة أسباب :

- لاتستطيع ايقاف البرنامج الفرعي عن طريق البرنامج الذي قام بتشغيله .

- لأسباب أمنية مختلفة ، منها استهلاك موارد النظام وتركها مفتوحة .

- يعتبر بطئ نسبيا اذا ما قورن بسرعة النظام .

وتعتبر هذه الدالة محدودة الإستخدام وينصح باستخدامها فقط في البرامج التي تعمل في بيئة الدوس ، وهنا مثال على استخدامها :

#include <stdlib.h>



int main()

{

 char strCmd[] = "cmd.exe";

 system(strCmd);

 return 0;

}

2- الدالة spawn

هذه الدالة تعطيك خيارات أكثر من سابقتها ، وعملها القيام بتنفيذ برنامج او أمر من اوامر النظام لكن مع تحكم أكبر ، وهنا مجموعة من التوابع يطلق عليها عائلة spawn :

#include <process.h>

#include <stdio.h>

int spawnl(int mode, char *path, char *arg0, arg1, ..., argn, NULL);

int spawnle(int mode, char *path, char *arg0, arg1, ..., argn, NULL, char *envp[]);

int spawnlp(int mode, char *path, char *arg0, arg1, ..., argn, NULL);

int spawnlpe(int mode, char *path, char *arg0, arg1, ..., argn, NULL, char *envp[]);

int spawnv(int mode, char *path, char *argv[]);

int spawnve(int mode, char *path, char *argv[], char *envp[]);

int spawnvp(int mode, char *path, char *argv[]);

int spawnvpe(int mode, char *path, char *argv[], char *envp[]);

لنأخذ مثلا هنا الدالة spawnv ونشرح البارامترات التي تأخذها

- mode توضح حالة البرنامج الأب (الذي قام بالتشغيل)والبرنامج الإبن بعد تنفيذ البرنامج وتأخذ احدى القيم التالية :

P_WAIT توقف تنفيذ البرنامج الأب لغاية الإنتهاء من تنفيذ البرنامج الإبن

P_NOWAIT الإستمرار بتنفيذ المعالجة الأب مع المعالجة الإبن

P_NOWAITO نفس سابقه ولكن هنا لا تستطيع اجبار المعالجة الأب على الإنتظار باستخدام التابع wait()

P_OVERLAY استبدال مكان المعالجة الأب بمكان المعالجة الإبن في الذاكرة ثم تنفيذ البرنامج

- path اسم البرنامج المراد تشغيله

- argv مؤشر لمصفوفة سلسلة حرفية .

وهنا مثال على استخدامها

#include <stdio.h> 

#include <process.h>



int main()

{

 char *my_args[4];

 my_args[0] = "child.exe";

 my_args[1] = "arg1";

 my_args[2] = "arg2";

 my_args[3] = NULL;

 spawnv( P_WAIT, "child.exe", my_args);

 return 0;

}

الدوال السابقة الذكر تستطيع استخدامها في التطبيقات التي تعمل في بيئة الدوس والويندوز أيضا ولكن يفضل عدم استخدامها في التطبيقات التي تعمل في بيئة ويندوز واستخدامها فقط في بيئة الدوس .

هنا مجموعة من الدوال التي تعمل في تطبيقات الويندوز فقط .

3- الدالة WinExec

هذه الذالة بقيت تستخدم لضمان استمرارية التوافق مع تطبيقات الويندوز 16 بت ويفضل عدم استخدامها في تطبيقات ويندوز 32 بت ، وتأتي هذه الدالة على الصيغة

WinExec(LPCSTR lpCmdLine,UINT uCmdShow);

وتأخذ بارامترين الأول اسم البرنامج المراد تشغيله والثاني لتحديد وضع البرنامج عند تشغيله (مخفي ، عادي ، مصغر ، ...)

مثال على استخدامها :

#include <windows.h>



int main()

{

 WinExec("prog.exe",SW_SHOW);

 return 0;

}

4-الدالة CreateProcess

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

صيغة الدالة

BOOL CreateProcess(

 LPCTSTR lpApplicationName,// مؤشر الى اسم المعالجة المطلوب تنفيذها

 LPTSTR lpCommandLine,  // مؤشر الى سطر الأوامر argv , argc في اللغة القياسية

 LPSECURITY_ATTRIBUTES lpProcessAttributes,  // محددات الأمان (مؤشر الى الستركت SECURITY_ATTRIBUTE)

 LPSECURITY_ATTRIBUTES lpThreadAttributes,   // نفس سابقه ولكن

بالنسبة للمعالجات الفرعية

 BOOL bInheritHandles,  // لتحديد اذا كانت المعالجة الفرعية سترث الهاندل تيبل للمعالجة الرئيسية

 DWORD dwCreationFlags, // تحديد حالة البرنامج عند تشغيله وتأخذ عدة قيم نستطيع الإستعاضة عنها بالقيمة صفر

 LPVOID lpEnvironment,  // مؤشر الى ال environement variable (PEB)

 LPCTSTR lpCurrentDirectory,   // اسم المجلد الذي يحتوي على البرنامج المطلوب تنفيذه

 LPSTARTUPINFO lpStartupInfo,  // مؤشر الى ال STARTUPINFO

 LPPROCESS_INFORMATION lpProcessInformation  //مؤشر الىPROCESS_INFORMATION                

);

هذه الدالة مع كثرة البارامترات التي تحتويها تبقى سهلة الإستعمال لأنك تستطيع أن تضع في مكان أغلب البارامترات القيمة NULL الا في بعض الحالات التي لسنا بصدد ذكرها في هذه المرحلة ولنأخذ الآن مثال على استخدامها ثم نعود للشرح

#include <windows.h>



int main()

{

PROCESS_INFORMATION pi;

STARTUPINFO si= { sizeof(si) };

TCHAR szCmdLine[] = TEXT("CALC");

   CreateProcess(NULL,szCmdLine,NULL,NULL,false,0,

  NULL,NULL,&si,π);

   return 0;

}

أولا يجب عليك تعريف غرض من الستركت PROCESS_INFORMATION و STARTUPINFO وتحديد حجمه لكي تضع مشير لهذه الأغراض مكان البارامتر الأخير وقبل الأخير ، وهنا تلاحظ أن أغلب البارامترات اخذت القيمة NULL لأنك لاتحتاج الى وضع قيم أخرى فمثلا ال SECURITY_ATTRIBUTES تأخذ قيمتها الإفتراضية عند وضع NULL مكانها ولتضمن عمل برنامجك في بيئة الويندوز 98 والسبب أن الويندوز 98 لا يحتوي على هذه الضوابط الأمنية ، أما بالنسبة لباقي البارامترات فستعرف السبب من وراء اعطاءها القيمة NULL بعدما نوضح لماذا وضعنا اسم البرنامج المطلوب تنفيذه في مكان ال CommandLine وليس مكان ال ApplicationName ، والسبب في ذلك :

عند وضع اسم البرنامج في خانة ال CommandLine فليس فإن الدالة تفترض تلقائيا أن هذا ملف تنفيذي وتلحق له exe ومن دون تحديد مسار البرنامج path فان الدالة تبحث عنه في هذه الأماكن

- في المجلد الذي تنفذ منه برنامجك .

-في مجلد الويندوز ومجلد النظام Windows , System

-في جميع المسارات المعرفة في ال environment varieble

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

5- الدالة ShellExecute

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

HINSTANCE ShellExecute(

   HWND hwnd,  الهاندل للنافذة الأب ويكفي هنا تمرير القيمة NULL

   LPCTSTR lpOperation,  تأخذ احدى هذه القيم حسب المطلوب open explore print

   LPCTSTR lpFile,  البرنامج المطلوب تشغيله

   LPCTSTR lpParameters,  ضع هنا NULL

   LPCTSTR lpDirectory,  المجلد المحتوي على البرنامج

   INT nShowCmd  حالة البرنامج عند تشغيله

);

مثال على استخدامها

#include <windows.h>



int main()

{

ShellExecute(NULL,"open","CALC",

 NULL,NULL,SW_SHOW);

   return 0;

}

جرب أن تضع مكان اسم البرنامج اسم موقع على النت مثلا

ShellExecute(NULL,"open","http://www.arabteam2000.com/vb",

NULL,NULL,SW_SHOW);

وهكذا تستطيع فتح اي ملف حتى لو كان ملف تكست او استعراض ملفات القرص الصلب

ShellExecute(NULL,"explore","C:",

 NULL,NULL,SW_SHOW);

/*/*/*/*/*/////////*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*

كيف تجعل لبرنامجك بارامتر

عند استخدامك لبرنامج من ال Run او من ال command قد يكون من المفيد لو

أضفت له بارامتر او أكثر لتستطيع التعامل معه مثلا

copy source.txt target.txt [/ALIGN]

dir /p[/ALIGN]

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

int main (int argc, char *argv[])

argc هي عبارة عن عداد لمعرفة كم قيمة ألحقت بالبرنامج كبارامترات وهذه القيم تخزن في المصفوفة argv ، ويجب أن تعرف أنه في حالة الحاق اي قيمة بالبرنامج كبارامتر فان القيمة فان قيمة argc ستزداد أي تصبح أكبر من صفر وبالتالي فإن argv[0] ستأخذ قيمة وهي اسم البرنامج الحالي المنفذ من خلال argv[argc - 1] ، وتصبح argv[1] عبارة عن البارامتر الأول للبرنامج وهكذا ... الى أن تأخذ الخانة الأخيرة في المصفوفة argv[argc] القيمة NULL دلالة على انتهاء المصفوفة .قد تبدو العملية صعبة ولكن مع قليل من الممارسة ستصبح بغاية السهولة ، واليك هنا بعض الأمثلة :



#include <string.h>



int main(int argc, char *argv[])

{

 /*

  * Look for -a or -d in command line

  */

 int i;

 

 for (i = 1; i < argc; i++)

 {

   if (argv[i][0] == '-')

     if (argv[i][1] == 'a')

       puts ("Found -a");

     else if (argv[i][1] == 'd')

       puts ("Found -d");

     else printf ("Unknown switch %sn", argv[i]);

   else if (strcmp(argv[i], "name") == 0)

     puts ("Found name");

 }

 

 return(0);

}
#include <stdio.h> 

يفحص هذا البرنامج البارامترات المدخلة ويقوم بطباعتها (اذا كانت مساوية للخانات التي عرفها مثلا -a -d name فانه يعطيك رسالة بأنها موجودة ) وتستطيع ان تستبدل التعليمة التي تقوم بالطباعة لأي تعليمة تريدها ، ويكفي فهمك لهذا البرنامج لفهم هذا الموضوع كامل

اليك المزيد من الأمثلة



int main(int argc, char *argv[])

{

 if (argc > 0)

 printf ("Program name is >%s<n", argv[0]);    

 return 0;  

}
#include <stdio.h> 



int main(int argc, char *argv[])

{

   int i;

   for (i = 1; i < argc; i++)

   puts(argv[i]);

   return 0;

}
#include <stdio.h> 



int main(int argc, char *argv[])

{

while (--argc)

printf ("%s ", *++argv);

return 0;

}
#include <stdio.h> 

شغل هذه البرامج من ال command لكي تستطيع الحاقها ببعض البارامترات

*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*

كيف تضع مؤقت في برنامجك ؟

من أفضل الطرق لحساب وقت تنفيذ البرنامج من ناحية السرعة والدقة هو استخدام طريقة تدعى profiler وتعتمد على حساب مدة بقاء البرنامج بالذاكرة ولكنها تعمل على انواع معالجات معينة وايضا مترجمات معينة لذلك سنبحث عن البديل ، توفر لنا المكتبة time.h و مكتبة ctime بعضا من الدوال المفيدة في هذا المجال والتي نستطيع الإكتفاء بها ، وهنا سنكتفي بوضع مثال يعطي فكرة عن استخدام هذه الدوال



#include <time.h>



int main ( void )

{

 clock_t start, end;



 /* Start the timer */

 start = clock();



 printf ( "Please wait a few moments and hit returnn" );

 getchar();



 /* End the timer */

 end = clock();



 /* Print out the difference */

 printf ( "The interval was: %f secondsn",

   (double)( end - start ) / (double)CLOCKS_PER_SEC );



 return 0;

}
#include <stdio.h> 

تم تعديل بواسطه طارق إبراهيم
0

شارك هذا الرد


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

كيف تجعل برنامجك في حالة سبات ؟

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

لعمل ذلك تستطيع استخدام الدالة sleep وتمرير مدة ايقاف البرنامج للدالة مقدرا بالثواني ولكن باستخدام هذه الدالة يصبح برنامجك غير قابل للنقل لمنصات تشغيل أخرى لأن الدالة sleep ليست قياسية وتأتي معرفة في الملف dos.h وفي ملف windows.h بالنسبة للدالة Sleep المستخدمة في الويندوز .

يوجد طريقة أخرى لإدخال برنامجك في حالة سبات بدون استخدام الدالة sleep وهذه للحفاظ على محمولية البرنامج وابقاؤه قابل للنقل ومبدأها أن تدخل البرنامج في حلقة تكرارية لمدة معينة من الوقت انت تحددها بأن تأخذ الوقت الحالي للجهاز وتضيف عليه المدة الزمنية التي ترغب بها وتخزنه في متغير وتدخل البرنامج في حلقة الى ان يتساوى الوقت الحالي للجهاز مع الوقت المخزن في المتغير

#include <time.h> void sleep_seconds ( long seconds ) {  clock_t limit, now = clock();  limit = now + seconds * CLOCKS_PER_SEC;  while ( limit > now )    now = clock();}void sleep_ticks ( long ticks ) {  clock_t limit, now = clock();  limit = now + ticks;  while ( limit > now )    now = clock();}void wait(long milliseconds){  long timeout = clock() + milliseconds;  while( clock() < timeout ) continue;}
هذه الطريقة لا ينصح بها لأنها تأخذ من وقت ال CPU وتبقيه في حالة معالجة للبرنامج ، وما الك الا sleep .

/*/*/*/*//*/*/*/*/*/*/*/*//*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*

كيف تقوم بتلوين النص ؟

اذا كنت تكتب برنامج ليعمل في بيئة الدوس او كان المترجم الذي تستعمله يدعم الأمر textcolor فستصبح عملية تلوين النص سهلة وكل ما عليك فعله هو استدعاء الدالة textcolor واللون المطلوب استخدامه وهنا مثال على استخدامها وتحته جدول بالألوان الممكن استخدامها مع ثوابتها العددية والرمزية

#include <stdio.h> #include <conio.h> int main ( void ){  textcolor ( MAGENTA );  cprintf ( "This is a testn" );  return 0;}
وهنا جدول الألوان

0 BLACK

1 BLUE

2 GREEN

3 CYAN

4 RED

5 MAGENTA

6 BROWN

7 LIGHTGRAY

8 DARKGRAY

9 LIGHTBLUE

10 LIGHTGREEN

11 LIGHTCYAN

12 LIGHTRED

13 LIGHTMAGENTA

14 YELLOW

15 WHITE

أما اذا كان برنامجك سيعمل بالويندوز أي في وضع الكونسول فلا يوجد لك خيار غير استخدام توابع ال API للقيام بذلك

#include <stdio.h> #include <windows.h> int main ( void ){  HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );  WORD wOldColorAttrs;  CONSOLE_SCREEN_BUFFER_INFO csbiInfo;     /*   * First save the current color information   */  GetConsoleScreenBufferInfo(h, &csbiInfo);  wOldColorAttrs = csbiInfo.wAttributes;     /*   * Set the new color information   */  SetConsoleTextAttribute ( h, FOREGROUND_RED | FOREGROUND_INTENSITY );    printf ( "This is a testn" );  /*   * Restore the original colors   */  SetConsoleTextAttribute ( h, wOldColorAttrs);  return 0;}

كيف تنقل مؤشر الكتابة في وضع الكونسول ؟

اذا كنت تبرمج في وضع الدوس فما عليك سوى استدعاء التابع gotoxy(x,y) وتمرير الإحداثي السيني والصادي لنقل مؤشر الكتابة اليه ، في وضع الكونسول لا يعمل هذا التابع ، اذن عليك القيام بتعريف تابع يقوم بنفس العملية باستخدام توابع ال API وكل ما عليك فعله هو تعريف غرض من المبني COORD لحفظ إحداثيات المؤشر السيني والصادي والحصول على مقبض المؤشر ثم نقل المؤشر للمكان الجديد باستخدام SetConsoleCursorPosition

#include <windows.h> void gotoxy(int x, int y){  COORD coord;  coord.X = x;  coord.Y = y;  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);}
*/*/*/*/*/*/*/*/*/*//*/*/*/*/*/*/*/*/**/*//*/*/*/*/*/*/*

كيف تحصل على القيم المدخلة من المستخدم من غير ان يضغط على المفتاح Enter ؟

لا يوجد دالة قياسية في لغة سي ، سي++ تقوم بهذه العملية ، ولكن اذا كان المترجم الذي تستخدمه يملك المكتبة الغير قياسية conio.h والمعرفه بداخلها الدالة getch() فإنك تستطيع انشاء روتين بسيط يقوم بهذه العملية ، انظر الى هذا المثال

#include <stdio.h> #include <conio.h> int main(){  int ch;  puts ("Press any key, q to quit");      while ((ch = getch()) != EOF && ch != 'q')    printf ("%cn", ch);  return 0;}
هنا تأخذ القيمة من المستخدم وتخزن في المتغير ch من نوع char أي أنك تستطيع فورا معالجة المدخلات من غير أن يضغط المستخدم على المفتاح Enter ، هنا تعاملنا مع خانة واحدة char وكل حرف تدخله يحل مكان سابقة ، قد تحتاج في برامج أخرى لأخذ قيمة طويلة (سلسلة حرفية )من المستخدم بنفس هذه الطريقة عندها عليك تعريف مصفوفة من النوع char والتعامل معها خانة خانة بواسطة الدالة getch() أنظر الى هذا المثال الذي يأخذ كلمة سر من المستخدم ويطبعها على شكل نجوم

#include  

#include

#include

int main()

{

 int ch;

 char pword[bUFSIZ];

 int i = 0;

 

 puts ("Enter your password");

 

 while ((ch = getch()) != EOF

         && ch != 'n'

         && ch != 'r'

         && i < sizeof(pword) - 1)

 {

   if (isalnum(ch))

   {

     putchar('*');

     pword[i++] = ch;

   }

 }

 pword[i] = '

0

شارك هذا الرد


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

التعامل مع الملفات في لغة سي .

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

سنضع مثال يوضح كيف تتم عملية القراءة من ملف والكتابة في آخر ولكن قبل ذلك يجب عليك ان تعرف أنه اذا أردت اجراء اي عملية على الملف من قراءة او كتابة فيجب عليك فتحه أولا وذلك بتعريف مشير للغرض FILE ثم استدعاء الدالة fopen عليه

FILE *fp = fopen ( file, mode );

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

مثال يقوم بنسخ ملف الى ملف آخر بفتح الأول والقراءة منه حرف حرف ووضعه في الملف الآخر

#include <stdio.h> 

#include <stdlib.h>



static FILE *open_file ( char *file, char *mode )

{

 FILE *fp = fopen ( file, mode );



 if ( fp == NULL ) {

   perror ( "Unable to open file" );

   exit ( EXIT_FAILURE );

 }



 return fp;

}



int main ( int argc, char *argv[] )

{

 int ch;

 FILE *in;

 FILE *out;



 if ( argc != 3 ) {

   fprintf ( stderr, "Usage: %s <readfile1> <writefile2>n", argv[0] );

   exit ( EXIT_FAILURE );

 }



 in = open_file ( argv[1], "r" );

 out = open_file ( argv[2], "w" );



 while ( ( ch = fgetc ( in ) ) != EOF )

   fputc ( ch, out );



 fclose ( in );

 fclose ( out );



 return EXIT_SUCCESS;

}

لنرجع للدالة fopen هذه الدالة تأخذ بارامترين الأول مشير الى سلسلة نصية تحتوي على اسم الملف المراد فتحه والبارامتر الثاني يأخذ احدى هذه القيم الثابتة

"r"  فتح الملف للقراءة  

"w"   فتح الملف للكتابة ، المحتويات الأصلية للملف سوف تمسح

"a"   فتح للكتابة في نهاية الملف ، المحتويات الأصلية تبقى كما هي

"r+" فتح الملف للقراءة والكتابة في نفس الوقت

"w+" فتح الملف للقراءة والكتابة مع مسح المحتويات الأصلية

"a+" فتح للقراءة والكتابة في نهاية الملف

هذا بالنسبة للملفات التسلسية ، اما بالنسبة للملفات الثنائية فيجب عليك الحاق الحرف b نسبة الى binary لهذه الثوابت مثلا "r" تصبح "rb"

أخيرا أضع هنا قائمة بالتوابع التي تستخدم مع الملفات في لغة سي

FILE *fopen ( const char *filename, const char *mode );

int  fclose ( FILE *stream );

int  fprintf( FILE *stream, const char *format, ... );

int  fscanf ( FILE *stream, const char *format, ... );

int  fgetc  ( FILE *stream );

char *fgets ( char *s, int n, FILE *stream );

int  fputc  ( int c, FILE *stream );

int  fputs  ( const char *s, FILE *stream );

int  getc   ( FILE *stream );

int  putc   ( int c, FILE *stream );

int  ungetc ( int c, FILE *stream );

size_t fread  ( void *ptr, size_t size, size_t nmemb, FILE *stream );

size_t fwrite ( const void *ptr, size_t size, size_t nmemb, FILE *stream );

0

شارك هذا الرد


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

التعامل مع الملفات في لغة سي ++ .

تتعامل لغة سي ++ مع الملفات على أساس أنها مجاري تسلسلية من البايتات تنتهي بعلامة نهاية الملف eof ، التعامل مع الملفات في السي ++ لا يختلف عنه في سي من حيث المبدأ : فتح الملف ، قراءة ، اغلاق .. الخ ، يبقى الإختلاف شكليا فقط فهنا توفر لنا مكتبة fstream جميع التوابع للتعامل مع الملفات ، لنلق نظرة على البرنامج الذي وضعناه في الدرس السابق والذي يقوم بعملية نسخ ملف لأخر ولكن مكتوب بالسي ++ ثم نعود للحديث عن fstream

#include <iostream> 

#include <fstream>

#include <cstdlib>



int main ( int argc, char *argv[] )

{

 if ( argc != 3 ) {

   std::cerr<<"Usage: %s <readfile1> <writefile2>n";

   exit ( EXIT_FAILURE );

 }



 std::ifstream in ( argv[1] );



 if ( !in.is_open() ) {

   std::cerr<<"Error opening input filen";

   exit ( EXIT_FAILURE );

 }



 std::ofstream out ( argv[2] );



 if ( !out.is_open() ) {

   std::cerr<<"Error opening output filen";

   exit ( EXIT_FAILURE );

 }



 char ch;

 while ( in.get ( ch ) )

   out.put ( ch );



 return 0;

}

هل يذكرك اسم المكتبة fstream باسم المكتبة iostream ، هذه المكتبة هي فعلا مشتقة من مكتبة iostream أي أن جميع تعريفات صفوف مجاري الدخل والخرج تستطيع استخدامها هنا ، مثلا الغرض cin مجرى الدخل القياسي يتيح لك أخذ معلومات من المستخدم بواسطة لوحة المفاتيح ، كذلك الغرض cout مجرى الخرج القياسي يتيح لك عرض معلومات على الشاشة ، نفس الشيء مع الملفات انت عندما تنشئ ملف يتم انشاء غرض ومجرى متصل مع هذا الملف ، تأمل المثال التالي :

#include <iostream>

#include <fstream>

using namespace std;



int main()

{

ofstream file("file.txt",ios::out);

char name[10];

cout<<"what's your name? n";

cin>>name;

file<<"your name :"<<name<<endl;

return 0;

}

في هذا المثال وجهنا مجرى الخرج الى الغرض file .

بقي أن نقول انه لإنشاء ملف للقراءة يكفي تعريف غرض من ifstream وتمرير اسم الملف ، واذا كان للكتابة فيه فنكتفي بإنشاء غرض من ofstream مع تمرير اسم الملف الذي نود انشاؤه ، مع انه بالإمكان ان تمرر للغرض بارامتر ثاني لتوضح ما الغرض من انشاء الملف بالضبط (قراءة ، كتابة ، كتابة بآخر الملف ، ... الخ )ويأخذ احدى هذه الثوابت

ios::app    // للكتابة في آخر الملف

ios::ate    // للكتابة في أخر الملف او في أماكن عشوائية ضمن الملف ، يستعمل في حالة كان الملف ثنائي

ios::binary // اذا كان الملف ثنائي

ios::in     // للقراءة فقط

ios::out    // للكتابة مع مسح المحتويات الأصلية للملف

ios::trunc  // لإفراغ محتويات الملف

وتستطيع طبعا استخدام أكثر من ثابت في نفس الوقت بوضع العلامة | بينهم

fstream in ( filename, ios::in | ios::binary );

وبعد الإنتهاء من العمل على الملف عليك اغلاقه باستخدام الدالة close

file.close();

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

# include <conio.h>

تم تعديل بواسطه طارق إبراهيم
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

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

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