المؤشرات والعبارات النصية في ++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 متغير مؤثر , ومن ثم فهو قابل للتغير . ولهذا السبب يمكن تطبيق عملية التزايد عليه , بينما لا يمكن علي الأول ويبين لك ذلك أن أسلوب المؤثرات أكثر مرونة من أسلوب المصفوفات . ويبين الشكل كلا الأسلوبين .
شكل أسلوب المصفوفات وأسلوب المؤشرات للعبارة النصية
العبارات النصية كمعاملات
إليك مثالا يبين عبارة نصية ترحل كمعامل لدالة فرعية تقوم بإظهارها .
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 ) , ويتزايد المؤشران معا خطوة بخطوة . تقف الدالة عند الوصول للمحرف الصفري في العبارة المنسوخ منها فنضيفه نحن في الدالة المنسوخ إليها . ويبين الشكل هذه العملية .
شكل نسخ عبارة نصية
الدوال المكتبية للعبارات النصية
إن دوال العبارات النصية المكتبية التي استخدمناها من قبل تحمل تعاريف تستخدم أسلوب المؤشرات , فلو نظرت لتعريف الدالة 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 . والأن تذكر أن المصفوفة تمثل دائما بعنوان وحيد هو عنوان أول حرف بها ويخزن في المصفوفة المذكورة عناوين حروف العبارة النصية , كما هو موضح في الشكل .
شكل مصفوفة مؤشرات لعبارة نصية
تعليقات
إرسال تعليق