صفحه 1:
اشاره گرها
صفحه 2:
در درس مباني کامپیوتر با اشاره گرها آشنا شدیم و نحوه استفاده و کاربرد
آنها رابررسي کردیم.در این قسمت ابتدا يادوري از مباحث گذشته آورده
میشوده.سپس به ذکر مباحث پیشرفته تري از اشاره گرها مي پردازيم.
صفحه 3:
اشاره گرها :
۰ اشاره گرها در »++ کاربردهای فراوانی دارند.زیرادارای قابلیتهای
بسیاری هستند که تعدادی از آنها عبارتند از:
* بهبود کارائی بسیاری از توابع
* دسترسی آسان به عناصر آرایه ها
* تسهیل انجام کاربارشته هاو آرایه ها
* انتقال آرایه هاورشته ها به توابع
* ارسال آرگومان ها ازطریق فراخوانی با ارجاع
© تخصیص حافظه پویا
؟ ایجاد ساختمان داده هاثی نظیرلیستهای پیوندی
صفحه 4:
اآدرس هاواشاره گرها:
* اشاره گر چیست؟
؟ اشاره گر یک متغیر است که آدرس یک متفیر دیگر را در خود نگه
میدارد.
* حافظه کامپیوتر مجموعه ای از چندین بایت است.
* هر بایت دارای یک شماره ردیف است.
۴ شماره ردیف هر بایت از حافظه را آدرس آن محل از حافظه گویند.
* آدرس اولین بایتی از حافظه که به متغیر اختصاص می یابد.آدرس آن
متغیر می نامیم. به شکل زیر توجه کنید:
صفحه 5:
متفیرهای اشاره گر:
* تعريف متفیراشاره گردر ++ به صورت زیر عمل می کنیم:
:متغير * نوع *
© int *ptr;
۴ که در اینجا :: به معنی تعریف اشاره گر می باشد.
* دليل اين نوع تعريف نيز اين مى باشد كه كاميايلر نيازمند اين
است كه بداند اين اشاره كر به جه نوع متغيرى اشاره ميكند.
صفحه 6:
عملگرهای اشاره گر:
int a=5,b;
int *ptr;
ptr = &a;
b=*ptr;
؟ عملگر »6 آدرس عملوند خودرامشخص می کند.
* عملكر * محتویات جائی را مشخص می نماید که عملوندش به آن اشاره
می کند.
* به عملگر *# .عملكر دسترسی به اطلاعات یا عملگر غیرمستقیم میگویند.
در اکثر کتب برنامه نویسی به این عملگر, نام عملگر محتوا اطلاق شده
است زیرابیانگر محتوای یک متغیر است.
صفحه 7:
حال به مثال زیر توجه کنید:
int varl=11, var2=22;
int *ptr;
ptr=&var1;
cout<<"ptr point to “<<&varl<<"& ptr contents is”<<*ptr;
ptr=&var2;
cout<<"ptr point to “<<&var2<<"& ptr contents is”<<* ptr;
return 0;
خروجي این برنامه عبارت است از:
int main ()
{
ptr point to Ox8f4ffff2 & ptr contents is 11
ptr point to Ox8f4ffffO & ptr contents is 22
صفحه 8:
اشاره گر به ۷0[0:
ee
"5 معيولا آدرسی که در یک اشاره گر قرار میگیردباید همنوع با اشاره گر
؟ براي مثال نمی توان آدرس یک متغیر 1031] رادر یک اشاره گر از نوع
0 جایگزین کنید.
Lol ® یک نوع اشاره گر همه منظوره وجود دارد که می تواند به هرنوع
داده ای اشاره کند.
© اینگونه اشاره گرها دارای کاربرد ویژه و معینی نظیر انتقال اشاره گر به
تابعی هستند که بطور مستقل برروی انواع داده ای مختلف عمل میکند.
که به صورت زیر تعریف می شود:
:نام متغي ر* ١/010
صفحه 9:
int *intptr, a=3;
float *floatptr, b=4; ud gi oe
void *ptr; به مثال زیر توجه كنيد
HOK
/Error
3 Error
floatptr = &b; //OK
ptr = &a; //OK
ptr = &b; //OK
توضیح مثال:
برطبق تعریف بالا آدرس متفیر 8را نمیتوان در متفیر
۲ ذخيره كرد ونيز آدرس متغير (آرا هم نمی
توان در متغير 11781211 ذخيره كرد.اما آدرس هر دو متغير
هو را می توان در متغیر ۵۲ که از نوع 010لا است
ذخیره کرد.
صفحه 10:
اعمال روی اشاره گرها:
اعمالي که مي توان برروي اشاره گرها انجام داد عبارتند از؛
“عمل انتساب اشاره كرهابه يكديكر
*اعمال محاسباتي جمع وتفریق
“عمل مقايسه اشاره كرها
صفحه 11:
اعمال محاسباتی بر روی اشاره گرها:
* اعمال جمع و تفریق را می توان بر روی اشاره گرها انجام داد.
با افزایش یک واحدبه اشاره گر به اندازه طول نوع اشاره گر
به آن اضافه می شود.
* به عنوان مثال اگر 0 اشاره گری از نوع ]۲0[ باشد که محل
۰ حافظه اشاره می نماید 0++ موجب می شودکه 0 به
عدد صحیح بعدی اشاره کند. و ۵0 برابر ۱۰۰۴ شود.
صفحه 12:
مقایسه اشاره گرها:
اشاره گرها را نیز مي توان با عملگرهاي رابطه اي مقایسه کرد.
به عنوان مثال به دستورات زیر توجه کنید:
برليقايسه محتولیمحلشارم [02* << 01*
برليقایسه محليکه لشارم گر به لنجا لشارم ميکند 02 == PL
براي مثال دستور زیر معتبر است به شرطي که 0 و 0۷ هردو اشاره گر به
يك نوع داده (مثلا 101 ) باشند.
if (px<py)
printf ("px points to lower memory than
py") :
printf ("px points to upper memory than
= py")
صفحه 13:
انتقال اشاره گر به تابع:
* وقتى كه یک اشاره گر به یک تابع گذر داده میشود. در واقع
آدرس آن قلم از داده به تابع فرستاده میشود.
© هر گونه تغییراتی که در محتوای آدرس مورد نظر انجام گیرد.
هم در تابع فراخوانده شده و هم در برنامه یا تابع فراخواننده
تأثیر میگذارد .
؟ پارامتر متناظر تابعی که یک آدرس را به عنوان آر گومان
دریافت میکند . باید یک اشاره گر باشد .
صفحه 14:
پارامتر متناظر تابعی که یک آدرس را به عنوان آر گومان دریافت میکند . باید
یک اشارهگر باشد .
# include <stdio.h>
void add (int *) ;
void main ()
{
int count = 7;
printf("the original value of count is %d\n" , count) ;
add (& count) ;
printf ("the new value of count is %d\n" , count) ;
}
void add (int *countptr)
++ (*countptr) ; /* increments count in main */
1
خروجي:
حي the original value of count is
7
the new value of count is 8
صفحه 15:
مثال: برنامه زیر. تفاوت بین آرگومانهای معمولی که بوسیله مقدارعبور
داده می شوند و آر گومانهای اشاره گر را که بوسیله مرجع عبور داده می
اشوند روشن مسی سزد
;void funcl (int u, int v)
; void func2 (int *pu, int *pv )
() void main
21 با ۱ :
: ۱۱۲ ۷ 23
; printf (“\n Before calling funcl :u=%d v=%d",u,v)
;funcl(u, v )
; printf (“\n After calling funcl :u=%d v=%d",u,v)
; printf (“\n Before calling func2 :u=%d v=%d",u,v)
; func2(&u , &v )
; printf (“\n After calling func2 :u=%d v=%d",u,v)
;Qgetch
{
صفحه 16:
void funcl (int u, int v)
}
;u=0
:۷ ۶0
; printf (“\n Within funcl :u=%d v=%d",u,v)
; return
{
void func2 (int *pu, int *pv )
}
; pu = 0*
: pv = 0*
; printf (“\n Within func2 :*pu=%d *مان 900 " , لام* , نام* (
: ۵
Before calling funcl :
Within funcl : ۱ x
After calling funcl : خروجي:
86۲0۲6 و۵11۱ 2
2عصدم صاحا]آلالا :
After calling func2 :
صفحه 17:
اشارهگر و آرایه: ۱
* بین اشاره گرها و آرایهها رابطه نزدیکی وجود دارد . نام یک آرایه
در واقع اشاره گری به اولین عنصر آرایه است.
char str[18], *p;
p = str;
* اكر بخواهيم به ينجمين عنصر در 5:1 دسترسى داشته باشيم »
مى توانيم اين كار را به دو روش زير انجام دهيم :
[5]4 يا *(4ج+م)
1
کاراکتر مخصوص ۷(
تج
صفحه 18:
x{i] = 11
x[i] = 12
x{i] = 13
xli] = 14
x{i] = 15
Ve = (K+),
۱۱ + (
۱۲- +
We xt,
للم دعر
1o=(x+i),
x{i] = 72&
x[i] = 74&
x{i] = 76&
x[i] = 78&
x[i] = 7a&
x[i] = 7c&
x+i= 72
xt+i = 74
x+i = 76
x+i = 78
xt+i = 7a
x+i = 7c
صفحه 19:
مدیریت حافظه : عملگر های ۲6۷۷ و delete
++ روش ديكرىبرلىب دست آوردنقسمتهايىاز حافظه با
لستفاده از عملگر ۱6۷۷ فرلهمساخته. لینعملگر از سيستم عامل
حافظه لیب ا طولمشخصرمیگیردو بکلشارده گر که به نقطه
شروع آنلشارد میکند را بر ميكردلند
Student *pSt;
1) pSt = new Student;
حافظه به لنداززه ی کهلنشجو لخذ میشود ||
2) pSt = new Student[10];
حافظه برلین گهداریلطلاعات ۱ دلنشجو از سیستم گرفته میشود ||
صفحه 20:
* امثال
* تکه برنامه ای بنویسید که تعداد المانهای یک آرایه صحیح
را گرفته و با توجه به مقدار وارد شده یک آرايه از نوع
صحیح ایجاد نماید
int *x,n
cin>>n
x = new int [n];
صفحه 21:
عملگر 06۱616 :
اگر در برنامه خود با استفاده از عملگر MEW ۰ مقدار زيادي حافظه
بگیریم آنگاه تمام حافظه موجود در اختیار برنامه خواهد بود . براي
برگرداندن حافظه گرفته شده توسط دستور delete Js 5) new
استفاده مي كنيم .
البته با خاتمه اجراي برنامه » حافظه گرفته شده توسط دستور NeW 42
صورت اتوماتيك به سیستم بر میگردد و احتياجي به دستور 06۱646 نیست .
صفحه 22:
اشاره گر هایی به اشیا :
اشیا مي توانند به انواع داده اي ساده و آرایه ها اشاره کنند . تعریف کلاس زیر
را در نظر بگیرید :
به عنوان مثال دستور زیر براي ایجاد يك کلاس استفاده میشود .
Distance dist;
مي توان اشاره گري به صورت زیر تعریف کرد که به انواع داده اي از نوع اين
: کلاس اشاره کند
Distance *ptr;
صفحه 23:
مبتوان از عملگر هاي ۱6۷۷ و 06666 نیز استفاده کرد.
Distance *ptr = new Distance;
Distance ۱۵۷ آدرس بسك شيجدید که در حافظه لیجاد میشود را
برمیگردلند و لینآدرسدر متغیر 00۲ نگهداريميشود.
دسترسي به اعضا :
براي دسترسي به اعضاي يك شي داده وقتي اشاره گري به آن نسبت داده ایم باید
از علامت خاصي به شکل زیر استفاده کنیم :
ptr->get()
: البته از این روش نیز میتوان استفاده کرد
*(ptr).get()
صفحه 24:
|تمرین
*؟ یک کلاس برای نگهداری اطلاعات دانشجو تعریف نمایید.
* توابع مناسب برای مقداردهی به متغیرهای عضو کلاس و نمایش
اطلاعات كلاس را تعريف نماييد
* یک اشاره گر از نوع ]51010611 تعریف نمایید
* فضای لازم برای نگهداری اطلاعات یک دانشجو را از سیستم بگیرید
* با استفاده از توابع عضو کلاس پس از مقدار دهی به شی دانشجو
اطلاعات وارد شده را نمایش دهید.
؟ حافظه اخذ شده را به سیستم بر گردانید
© حال مجدداً با استفاده از همان اشاره گر فضا برای نگهداری اطلاعات ۳
دانشجو را اخذ نمایید و پس از گرفتن اطلاعات دانشجویان, آنرا نمایش
داده و حافظه را به سیستم بر گردانید.
صفحه 25:
۴ در صورتی که تخصیص حافظه بصورت آرایه ای باشد باید
آزادسازی حافظه به شکل زیر انجام گیرد:
۳0| »
ptr = new int[n]; ®
9
صفحه 26:
ليست پیوندی 5۴| ۱۳۷
۴ تعریف : مجموعه ای از گره ها که هر گره حداقل شامل یک فیلد داده ویک
فیلد اشاره گر است.
*؟ اشاره گر هر گره از نوع خود گره است.
* هر گره به وسیله ی اشاره گر خود به گره بعدی اشاره می کند.
صفحه 27:
- عمليات ليست پیوندی
- ايجاد ليست
- درج كره در ليست
- حذف گره از لیست
- جستجو در لیست
- مرتب سازى ليست
- معكوس كردن ليست
وا
2
Feb 25 Mer. 15
A linked list
صفحه 28:
پیاده سازی با اشاره گر
۴ تعریف یک نود
* لازم است اين مسئله مشخص شود كه
فيلدهاى ما جه نوع داده اى هستند.(به
عنوان مثال مى توان یک کاراکتر)
class CNode
3 {
private:
char data;
CNode *link;
public:
CNode(char d , CNode* I=NULL);
1
صفحه 29:
class CLinkList
4
private:
CNode *first,*last;
public:
CLinkList();
CLinkList(const CLinkList &!);
void InsertFirst(char new_char);
void InsertAfter(CNode *pNode , char new_char);
void InsertBefore(CNode *pNode , char new_char);
void InsertLast(char new_char);
void Deleteltem(CNode *pNode);
char GetltemData(int Itemindex);
void Display()const;
CNode* Find(char ch);
void DestroyList();
~CLinkList();
صفحه 30:
CNode *t = new CNode(new_char, first);
first = t;
if(tlast)
last = first;
درج كره در ابتداى ليست
للها
8 688 :- ب
vo — 888 06
صفحه 31:
اضافه كردن به ابتداى ليست
newN سوه
A
first B 0 D E|0
صفحه 32:
اضافه کردن به ابتدای لیست-ادامه
newhode —,
first B 9 * و E|0
newNode > link = first;
صفحه 33:
اضافه کردن به ابتدای لیست-ادامه
۱۳9
0 8 اه ط ا« 0 first B
first = newNode;
صفحه 34:
اضافه کردن به ابتدای لیست-دامه
—"
first B c +) D 80
صفحه 35:
نمایش لیست پیوندی (پیمایش)
void CLinkList ::Display()
{
if( !first ) return; //no node
Node *temp = first;
while(temp) //traverse list
cout << temp data;
temp = temp link; //next node
صفحه 36:
اضافه کردن عنصر جدید
* البته برای کاربردهای مختلف اضافه کردن فرق می کند.
& ما در اینجا اضافه کردن عنصر جدید بعد از یک عنصر مشخص را نشان
می دهیم.
۴ مراحل کار:
۱) نصب عنصر جدید
۲) تنظیم اشاره گرهای مربوط به عنصر جدید
صفحه 37:
curNode.
newNode—~
first
صفحه 38:
اضافه کردن عنصر جدید-دامه
curNode.
A B ظ يم | 0
١
newNod 5
first
newNode > link = curNode > link ;
صفحه 39:
اضافه کردن عنصر جدید-ادامه
curNode.
A B (= ظ | 0
newNode—4 ¢
first
curNode > link = newNode ;
صفحه 40:
اضافه کردن عنصر جدیددامه
first
صفحه 41:
اضافه کردن عنصر جدیدادامه
void CLinkList::InsertAfter(CNode *pNode , char new_char)
{
CNode*newNode = new CNode(new_char);
newNode-link = curNodelink ; — //assign newNode
curNode—link = newNode ; //assign curNode
}
صفحه 42:
* مراحل کار:
۱) تنظیم اشاره گرها
۲) حذف کردن گره (آزاد کردن حافظه)
صفحه 43:
حذف عنصر از ابتدای لیست پیوندی
curNode
*|oB 0 oD اكه 0
first
صفحه 44:
ink;
حذف عنصر از لیست پیوندی-ادامه
curNode
5
9 0
هه
first = first >
first
صفحه 45:
حذف عنصر از ابتدای لیست پیوندی-دامه
delete cur;
first
صفحه 46:
حذف عنصر از لیست پیوندی-ادامه
(6
oD OE} 0 0 و
Node *temp = first;
temp
first
صفحه 47:
حذف عنصر از لیست پیوندی-ادامه
(6
و
temp
while( temp > link != cur)
temp = temp > link;
first
صفحه 48:
حذف عنصر از لیست پیوندی-ادامه
(6
0 اظه هه c و اه ۹
temp
while( temp > link != cur)
temp = temp > link;
صفحه 49:
حذف عنصر از لیست پیوندی-ادامه
(6
- إن => 0 oD
۳
temp
temp > link = cur > link;
first
صفحه 50:
حذف عنصر از لیست پیوندی-ادامه
temp
delete cur;
اده
first
صفحه 51:
حذف عنصر از لیست پیوندی-ادامه
if( cur == first )
{
first = first > link;
delete cur;
return;
1
Node *temp = first;
while( temp link != cur)
temp = temp > link;
temp link = cur link;
delete cur;
void CLinkList::Deleteltem(CNode *cur)
1
صفحه 52:
2 تمرین
؟ کلاس لیست پیوندی که 0۲0101006 آن در اسلایدهای قبل
آورده شده است را پیاده سازی نمایید.
* برای نمایش لیست پیوندی در صورتی که در محیط )91لا5 ۷ برنامه نویسی میکنید
در تابع ۵15012۷ یک اشاره گر از نوع CLIStBOX گرفته شود و درون لیست
نمایش اطلاعات صورت پذیرد. دیالوگهای مناسب جهت اضافه و حذف را طراحی
نموده و پیامهای مناسب نیز نمایش داده شود.
صفحه 53:
ليست هاى حلقوى
* به وسيله ى اتصال آخرين كره به اولين كره مى توان ليست حلقوى را
توليد كرد.
* دراين كونه ليست ها به راحتى مى توان از آخر ليست به اول ليست
يرش كرد.
صفحه 54:
نمونه ای از لیست حلقوی
first
صفحه 55:
ليست هاى ييوندى دوكانه ( دو طرفه )
* مشكل اساسى ليست هاى يك طرفه عدم دسترسى به كره قبلى
* ليست هاى دوكانه با اضافه كردن يك اشاره كر به كرهى قبلى اين مشكل را
حل كرده است.
1
i
A doubly linked list
صفحه 56:
انواع لیست های پیوندی دو گانه
لیست دوطرفه ی ساده
لیست دوطرفه ی حلقوی
first امس
first مب
صفحه 57:
اضافه کردن عنصر به لیست دوطرفه ساده
newEle
first A B D E
صفحه 58:
اضافه كردن عنصر به ليست دوطرفه ساده-ادامه
newEle > next = cur > next;
صفحه 59:
اضافه كردن عنصر به ليست دوطرفه ساده-ادامه
newEle
cur > next = newEle;
صفحه 60:
اضافه كردن عنصر به لیست دوطرفه ساده-ادامه
cur > next = newEle;
صفحه 61:
اضافه كردن عنصر به لیست دوطرفه ساده-ادامه
newEle
cur 5
(newEle > next) > pre = newEle;
صفحه 62:
اضافه كردن عنصر به ليست دوطرفه ساده-ادامه
cur newEle
۱
A B 8 D E
صفحه 63:
؟ اگر بخواهیم عنصر ۱6۷۷۱6 را به ابتدای لیست اضافه کنیم؟
* اگر بخواهیم عنصر ۱6۷۷۶۱6 را به انتهای لیست اضافه کنیم؟
* اكر ليست خالى باشد؟
صفحه 64:
حذف از لیست دوطر فه ساده
cur
صفحه 65:
حذف از لیست دوطرفه ساده -ادامه
cur
A B Cc D 3
1
(cur > next ) > pre = cur > pre;
صفحه 66:
حذف از لیست دوطرفه ساده-ادامه
cur
(cur > pre ) > next = cur > next;
صفحه 67:
pre
(cur > pre ) > next = cur > next;
حذف از لیست دوطرفه ساده -ادامه
۱۵|
pre
| |
1
next
pre
next}—
صفحه 68:
حذف از لیست دوطرفه ساده -ادامه
next 1
next +.
عنم لم pre |
next
first
صفحه 69:
* اگر بخواهیم عنصر ابتدای لیست را حذف کنیم؟
* اگر بخواهیم عنصر ابتدای لیست را حذف کنیم؟
۴ اگر لیست خالی باشد؟
صفحه 70:
* اپراتورهای زیر را در کلاس ا5أام) تعریف نمایید
* +: این عملگر مشابه افزودن به انتهای لیست عمل ميكند
* عملگر -: این عملگر بدنبال یک کارکتر در لیست میگردد و در صورت
وجود این عنصر در لیست آنرا حذف میکند
© عمگر عملگر یک لیست را در لیست دیگر کپی میکند
* عملگر --: این عملگر دو لیست را با هم مقایسه نموده و در صورتی که
با هم برابر باشند مقدار ](] و در غیر اینصورت مقدار FALSE
برمیگرداند
* عملكر [] كه يك انديس كرفته و مقدار موجود در گره با اندیس وارد
شده را برميكرداند. ()101 00۵6۲۵۲۵۲][)1۳1 10۱2۲
صفحه 71:
: اشاره گر ۲۳5
* توابع عضو هر شى به یک اشاره گر جادوبی به نام 015
دسترسی دارند که به خود شی اشاره میکند.
؟ معنای وجود این متغیر در کلاس یعنی هر شی آدرس خود در
خافظه را میداند و يا تعبیر دیگر اينکه هر شی خودش را
ميبيند و خودش را میشناسد.
صفحه 72:
class where
it
private:
char charArr[10];
public:
void reveal()
{
cout<< “\nMy object’s address is:"<<this;
i ; ۱ ا
void main()
1 ا وت يي ا
where w1,w2; توص ا
WL. reveal);
WA. reved();
vant <<“ul Odes & “<<8&uAl;
فص > Oddress :سم >>" ص
صفحه 73:
اکاربر دهای اشاره گر this
* يكى از پر کاربردترین کاربردها زمانی است که میخواهیم
خروجی یک تابع عضو خود شی و یا ادرس خود شی باشد.
؟ کاربرد دیگر زمانی است که میخواهیم خود شی را بعنوان
آرگومان یک تابع ارسال نماییم
* فرض كنيد تابعى داريم كه یک شی را گرفته و اطلاعات آنرا
نمایش دهد. ما میخواهیم همین تابع نمایش دادن بصورت یک
تابع عضو کلاس نیز باشد. sly استفاده از تابع موجود میتوانیم
از اشاره گر 05 استفاده نماییم.