المؤشرات والعبارات النصية في ++C

المؤشرات والعبارات النصية

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

المؤشرات لثوابت العبارات النصية

إليك برنامج نعرف فيه عبارتين نصيتين , الأولي بأسلوب المصفوفات : char str1[] والثانية بأسلوب المؤشرات char* str2 .

twostr.cpp


 


// twostr.cpp


// strings defined using array and pointer notation


#include <iostream.h>


#include <conio.h>


 


void main()


   {


   char str1[] = "Defined as an array";


   char* str2 = "Defined as a pointer";


 


   cout << endl << str1;    // display both strings


   cout << endl << str2;


 


// str1++;                  // can't do this; str1 is a constant


   str2++;                  // this is OK, str2 is a pointer


 


   cout << endl << str2;    // now str2 starts "efined..."


   getche();


   }




في كثير من المواقف يكون الأسلوبان متكافئين , إلا أن هناك فرق خفي , هو أن str1 هو عنوان أي ثابت مؤشر (مؤشر ذو قيمة ثابتة) بينما str2 متغير مؤثر , ومن ثم فهو قابل للتغير . ولهذا السبب يمكن تطبيق عملية التزايد عليه , بينما لا يمكن علي الأول ويبين لك ذلك أن أسلوب المؤثرات أكثر مرونة من أسلوب المصفوفات . ويبين الشكل كلا الأسلوبين .



Object-Oriented Programming in C   _Page_0479_Image_0001



شكل أسلوب المصفوفات وأسلوب المؤشرات للعبارة النصية



العبارات النصية كمعاملات



إليك مثالا يبين عبارة نصية ترحل كمعامل لدالة فرعية تقوم بإظهارها .






ptrstr.cpp


 


// ptrstr.cpp


// displays a string with pointer notation


#include <iostream.h>


#include <conio.h>


 


void main()


   {


   void dispstr(char*);     // prototype


 


   char str[] = "Idle people have the least leisure.";


 


   dispstr(str);            // display the string


   getche();


   }


 


void dispstr(char* ps)


   {


   cout << endl;            // start on new line


   while( *ps )             // until null character,


      cout << *ps++;        // print characters


   }




يمثل str عنوان المصفوفة , فهو ثابت مؤشر وهو يرحل للدالة الفرعية ولكنه يرحل كقيمة , ومن ثم فإن نسخة منه تكون لدي الدالة الفرعية مستخدمة كمتغير مؤشر ps في هذه الحالة , ولذلك تقبل التزايد فتظهر محارف العبارة محرفا بعد الأخر , إلي أن نصل إلي المحرف الصفري وقيمته 0 وهي تعني عدم التحقق false , فتنتهي الدوارة .



نسخ مصفوفة بواسطة المؤشرات



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






copystr.cpp


 


// copystr.cpp


// copies one string to another with pointers


#include <iostream.h>


#include <conio.h>


 


void main()


   {


   void copystr(char*, char*);  // prototype


 


   char* str1 = "Self-conquest is the greatest victory.";


   char str2[80];               // empty string


 


   copystr(str2, str1);         // copy str1 to str2


   cout << endl << str2;        // display str2


   getche();


   }


 


void copystr(char* dest, char* src)


   {


   while( *src )                // until null character,


      *dest++ = *src++;         // copy chars from src to dest


   *dest = '\0';                // terminate dest


   }




تستدعي الدالة الأصلية الدالة الفرعية لتنسخ محتويات المصفوفة الأولي في الثانية وأمر النسخ في الدالة الفرعية هو :



*dest++ = *src++;



وترجمته (محتوي كل عنوان في src يخزن في كل عنوان مقابل في dest ) , ويتزايد المؤشران معا خطوة بخطوة . تقف الدالة عند الوصول للمحرف الصفري في العبارة المنسوخ منها فنضيفه نحن في الدالة المنسوخ إليها . ويبين الشكل هذه العملية .



Object-Oriented Programming in C   _Page_0481_Image_0001



شكل نسخ عبارة نصية



الدوال المكتبية للعبارات النصية



إن دوال العبارات النصية المكتبية التي استخدمناها من قبل تحمل تعاريف تستخدم أسلوب المؤشرات , فلو نظرت لتعريف الدالة strcpy() التي استخدمناها في الفصل الثامن لنسخ المصفوفات ستجد أنها معرفة كالتالي :



Char* strcpy(char* dest, const char* src);



وهي تعيد مؤشرا هو عنوان المصفوفة dest . وتقوم بالوظيفة التي تقوم بها دالتنا التي صنعناها محليا . أما عن الموصف const في تعريف الدالة فيعني أن الدالة لا تغير من محتويات scr .



مصفوفات المؤشرات لعبارات نصية



كما يوجد مصفوفات من نوع الأعداد الصحيحة و الكسرية , فلدينا أيضا مصفوفات عناصرها من نوع المؤشرات . ومن الاستخدامات العادية لذلك مصفوفات مؤشرات لعبارة نصية .



في الفصل الثامن بينا في البرنامج straray.cpp مصفوفة عبارة نصية , هي أن كل العبارات لها نفس الطول , مما يترتب عليه فقد في المساحات للعبارات الأقصر .



أنظر كيف يحل أسلوب المؤشرات هذه المشكلة سوف نعدل البرنامج لننشئ مصفوفة مؤشرات لمصفوفة بدلا من مصفوفة عبارة نصية .






ptrtostr.cpp


 


// ptrtostr.cpp


// an array of pointers to strings


#include <iostream.h>


#include <conio.h>


 


const int DAYS = 7;             // number of pointers in array


 


void main()


   {                            // array of pointers to char


   char* arrptrs[DAYS] = { "Sunday", "Monday", "Tuesday",


               "Wednesday", "Thursday",


               "Friday", "Saturday"  };


 


   for(int j=0; j<DAYS; j++)    // display every string


      cout << arrptrs[j] << endl;


   getche();


   }




حينما تخزن عبارات نصية دون أن تكون عناصر مصفوفة , تخزنها السي++ متجاورة توفيرا للذاكرة , إلا أن وجودها في مصفوفة يجعل من الممكن استخدام المؤشرات للتعامل معها . والعبارة ذاتها مصفوفة محارف , بمعني أن مصفوفة المؤشرات لعبارة نصية هي مصفوفة مؤشرات لمحارف . هذا هو معني التعريف المعطي للمصفوفة arrptr . والأن تذكر أن المصفوفة تمثل دائما بعنوان وحيد هو عنوان أول حرف بها ويخزن في المصفوفة المذكورة عناوين حروف العبارة النصية , كما هو موضح في الشكل .



Object-Oriented Programming in C   _Page_0484_Image_0001



شكل مصفوفة مؤشرات لعبارة نصية

التسميات: