PowerPoint Tutorial

Download Report

Transcript PowerPoint Tutorial

‫درس برنامه نویسی پیشرفته‬
‫‪C++ Programming‬‬
‫دانشگاه فناوری های نوین‬
‫مدرس‪ :‬زینب باقرآبادی‬
‫‪1394-1393‬‬
C++ ‫ و‬C ‫تاریخچه‬
BCPL, 1967, Martin Richards
Writing Operating Systems software and compiler
B, 1969, Ken Thomson
-based on BCPL
C, 1972, Dennis Ritchie
-based on BCPL and B
C++, early 1980s, Bjarne Stroustrup
- Object Oriented Programming
2
‫مراجع‬
P. Deitel, H. Deitel, C++: how to program
J. Soulie, C++ Language tutorial, available at:
http://www.cplusplus.com/doc/tutorial
[email protected]
3
‫نمره دهی‬
‫تمرین‬
‫‪ 2‬نمره‬
‫پروژه‬
‫‪ 4‬نمره‬
‫کوییز و فعالیت کالس ی‬
‫میان ترم‬
‫پایان ترم‬
‫‪ 3‬نمره‬
‫‪ 5‬نمره (هفته دوم اردیبهشت)‬
‫‪ 8‬نمره‬
‫‪4‬‬
‫رئوس مطالب‬
‫مروری بر برنامه نویس ی به زبان ‪C‬‬
‫… ‪Loops, structs, arrays, basic data types,‬‬
‫نگاهی دقیق به ‪C++‬‬
‫کالس ها‪ ،‬وراثت‪ ،‬اشاره گرها‪ ،‬رشته ها‪... ،‬‬
‫‪5‬‬
Simple C Program
Examples:
//Simplest Program
int main ()
{
return 0;
}
//int is return data type
//main is entrance function
int main ()
{
statement1;
statement2; /*
//...
Objective: print on Screen
*/
return 0;
#include <stdio.h>//preprocessor statements
}
int main ()
{
printf(“welcome to c!!”);
return 0;//indicate that program ended successfully
}
6
Example
#include<stdio.h>
#define pi 3.14 //pl constant(preprocessor)
using namespace std;
int main()
{
/*variable definiton*/
float Radius;
float area=0;
/*get radious of circle from user*/
printf("Enter Radius: \n");
scanf("%f", &Radius );
/*calculate area of circle*/
area=pi*Radius*Radius;
printf("Area=%f",area);
printf("\n Pause");
return 0;
}
7
‫تعریف متغیر‬
‫ تعریف متغیر می تواند به سه طریق زیر انجام‬،‫قبل استفاده از یک متغیر باید آنرا تعریف کنید‬
:‫شود‬
 Data_Type identifier;

int width;

float area;

char separator;
 Data_Type identifier= Initial_Value;

int width=10;

float area=255;

char separator=‘,’;
 Data_Type identifier1, identifier2,…, identifier;

int width, length;

float radios, area=0;
8
‫انواع داده‬
‫‪ Minimal set of basic data types‬‬
‫‪- Primitive data types‬‬
‫)‪ int(4‬‬
‫‪ float‬‬
‫‪ double‬‬
‫)‪ char(1‬‬
‫‪ void‬‬
‫‪ ‬سایز و رنج انواع داده ای ممکن است در کامپایلرها و انواع مختلف پردازنده ها متفاوت‬
‫باشد‪.‬‬
‫‪9‬‬
‫انواع داده(کارکتر)‬
‫•‬
‫•‬
‫•‬
‫•‬
‫‌گیرند‪:‬‬
‫نوع داده‌اي ‪ char‬براي ذخیره سازي كاراكترها بكار مي‌رود كه در دسته‌بندي‌هاي زير قرار مي ‌‬
‫‪ ‬حروف بزرگ و كوچك‪ A-Z :‬و ‪a-z‬‬
‫‪ ‬ارقام دهدهي‪0-9 :‬‬
‫هموارهرهازاز‬
‫اكتر‪،‬‬
‫كا‬
‫يك‬
‫نمايش‬
‫اي‬
‫ر‬
‫ب‬
‫براي نمايش يك كارراكتر‪ ،‬هموا‬
‫‪ ‬جاي خالي يا ‪blank‬‬
‫‌شود‪.‬‬
‫ي‬
‫م‬
‫استفاده‬
‫يكاني‬
‫كوتيشن‬
‫كوتيشن يكاني استفاده مي‌شود‪.‬‬
‫‪ ‬كاراكترهاي مخصوص‪* ( $ % ^ ! :‬‬
‫‪‘\n’,‬‬
‫‪‘A’,‬‬
‫’‪‘5‬‬
‫’‪‘\n’, ‘A’, ‘5‬‬
‫‪ ‬كاراكترهاي كنترلي‪\n, \t :‬‬
‫متغیر رزرو‌ مي‌نمايد‪.‬‬
‫‌‬
‫اين نوع داده‌‌اي به طور‌ پيش‌فرض ‪ 8‬بيت ‌از فضاي حافظه را براي‬
‫محدوده‌ي قابل نمايش براي داده‌ي نوع ‪ char‬از ‪ -127‬تا ‪ 127‬خواهد بود‪.‬‬
‫دو ز ‌ير مجموعه‌اي ‪ signed‬و ‪ unsigned‬مي‌باشد‪.‬‬
‫نیز داراي ‌‬
‫نوع داده‌اي ‪‌ char‬‬
‫‪10‬‬
‫انواع داده(کارکتر)‬
‫هر‬
‫دیگر را با تخصیص عددی (کد) به ‌‬
‫کار می‌کنند ‌و کاراکترهاي ‌‬
‫• کامپیوترها فقط با کدها (اعداد) ‌‬
‫در خود ذخیره می‌کنند ‌و یا ‌بر روی آن پردازش انجام می دهند‪.‬‬
‫یک ‌از آنها ‌‬
‫متمايز نسبت می‬
‫‌‬
‫ی ‪ ASCII‬به حروف‪ ،‬ارقام‪ ،‬عالئم ‌و کاراکترهای مختلف يک عدد‬
‫• کد گذار ‌‬
‫دهد‪.‬‬
‫‪11‬‬
‫داده های اعشاری‬
‫بكار‬
‫• نوع داده‌اي ‪ float‬براي ذخیره سازي‌ اعداد اعشاري‌ مانند ‪ 12345/43 ،12/5‬و ‪‌ 45/6‬‬
‫مي‌رود‪.‬‬
‫متغیر رزرو‌ مي‌نمايد ‌و داراي‬
‫‌‬
‫• اين نوع داده‌‌اي به طور‌ پيش‌فرض ‪ 32‬بيت ‌از فضاي حافظه را براي‬
‫اعشار دقت مي‌باشد‪.‬‬
‫‌‬
‫‪ 7‬رقم‬
‫گتر از ‪‌ float‬از نوع ‪ double‬با ‪ 64‬بيت فضاي براي دقتي‬
‫• براي ذخیره‌ي اعداد اعشاري‌ بزر ‌‬
‫اعشار استفاده مي‌شود‪.‬‬
‫‌‬
‫معادل ‪ 15‬رقم‬
‫‪12‬‬
Data Types qualifiers
 Modify the behavior of data type to wich
they are applied:
13




Size qualifier
short: multiple by 0.5
long: multiple by 2
short can be applied to: int
long can be applied to: int and double



Sign qualifier
signed: + and –
unsigned: +
they can be apply to: int and char
Data Types qualifiers
14
‫داده های نوع ‪bool‬‬
‫• نوع ‪ bool‬يک نوع صحيح است که متغیرهاي اين نوع فقط ميتوانند مقدار ‪ true‬يا‬
‫‪ false‬داشته باشند‪.‬‬
‫• گرچه درون برنامه مجبوريم ‌از عبارات ‪ true‬يا ‪ false‬براي مقداردهي به اين نوع‬
‫كامپيوتر ذخیره‬
‫‌‬
‫در اصل به صورت ‪ 0‬و ‪ 1‬درون‬
‫مقادير ‌‬
‫‌‬
‫متغیر استفاده کنيم‪ ،‬اما اين‬
‫‌‬
‫مي‌شوند‪.‬‬
‫‪0‬‬
‫;‪bool flag=false‬‬
‫‪flag‬‬
‫متغیر نوع‬
‫‌‬
‫• چنانچه بخواهيد به جاي مقادير ‪ true‬و ‪ false‬با استفاده ‌از اعداد‬
‫مقدار غیر ‪ 0‬براي نوع ‪ bool‬معادل‬
‫‌‬
‫هر‬
‫‪ bool‬را مقداردهي نماييد بايد توجه كنيد ‌‬
‫مقدار ‪true‬خواهد بود‪.‬‬
‫‪0‬‬
‫;‪bool a=0‬‬
‫;‪bool b=6‬‬
‫‪1‬‬
‫;‪bool c=-34‬‬
‫‪15‬‬
‫ثابت ها‬
.‫تغییر نمی باشد‬
‌ ‫متغیر که توسط هیچ بخش دیگری‌ ‌از کد قابل‬
‌
‫• روش ی برای تعریف یک‬
- # define : without memory consume
- const : with memory consume
•
-
16
#define
#define
#define
#define
#define
identifier constant_value
pi 3.14
EROR “Disk error”
ONE 1
TWO ONE+ONE
‫ثابت ها‬
• const [Data_type] identifier =
constant_value;
- const p = 3; //const int p=3;
- const p;
p = 3.14; //compiler error
- const p = 3.14;//p=3 because default is int
- const float p = 3.14;
17
‫عملگرها‬
• Arithmetic Operators
- unary Operators
Operators that require only one Operand
- binary Operators
Operators that require two Operands
• Assignment Operators
• Equality and relational Operators
• Logical Operators
• Bitwise Operators
• Conditional Operator
• sizeof
18
‫عملگرهای ریاض ی‬
• Unary Operators
19
Operation
Operator
Expression
Explanation
Positive
+
A=+3;
Negative
-
B=-4;
Increment
++
i++;
i=i+1;
Decrement
--
j--;
j=j-1;
‫عملگرهای ریاض ی‬
• Binary Operators
20
Operation
Operator
Expression
Addition
+
a=b+2;
Substraction
-
a=b-4;
Multiplication
*
a=b*3;
Division
/
a=b/5;
Modulus(integer)
%
a=b%c;
‫تقسیم‬
• the division of variables of type integer will always produce
a variable of type integer as the result
• Example
int a=7, b;
float z;
b=3
b = a/2;
z = a/2.0;
printf(“b=%d , z=%f \n”, b, z);
21
, z=3.50000
Assignment operators
• lvalue=rvalue;
• Example
int i;
float f;
i = 2; //*&i=2;
2 = i; //error: invalid value assignment
f = 5.6;
i = f; //i=5;
i = -5.9; //i=-5;
22
Assignment operators
• c=9;
23
Operator
Expression
Equivalent
statement
Results
+=
c+=7;
c=c+7;
c=16;
-=
c-=8;
c=c-8;
c=1;
*=
c*=10;
c=c*10;
c=90;
/=
c/=5;
c=c/5;
c=1;
%=
c%=5;
c=c%5;
c=4;
&=
c&=2;
c=c&2;
c=0;
^=
c^=2;
c=c^2;
c=11;
|=
c|=2;
c=c|2;
c=11;
<<=
c<<=2;
c=c<<2;
c=36;
>>=
c>>=2;
c=c>>2;
c=2;
Equality and Relational Operators
‫عملگرهای مقایسه ای‬
• Equality Operators
Operator
Example
Meaning
==
x==y
x is equal to y
!=
x!=y
x is not equal to y
• Relational Operators
24
Operator
Example
Meaning
>
x>y
x is greater than y
<
x<y
x is less than y
>=
x>=y
x is greater than or equal to y
<=
x<=y
x is less than or equal to y
Logical Operators
Operator
Description
Example
&&
Called Logical
AND operator.
(A && B) is false.
||
Called Logical OR (A || B) is true.
Operator.
!
Called Logical
NOT Operator.
-if ( a==2 && b==3 )
-if ( c=3 || d=4 )
-if ( ! (r<90))
25
!(A && B) is true.
Bitwise Operators
p
q
p&q
p|q
p^q
0
0
0
0
0
0
1
0
1
1
1
1
1
1
0
1
0
0
1
1
B=13 ‫ و‬A=60 ‫• مثال‬
A = 0011 1100
B = 0000 1101
----------------A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
26 ~A = 1100 0011
Bitwise Operators
Operator
Description
Example
&
Binary AND
(A & B),0000 1100
|
Binary OR
(A | B),0011 1101
^
Binary XOR
(A ^ B),0011 0001
~
Binary Ones
Complement
(~A ),1100 0011(-61)
<<
Binary Left Shift
A << 2 ,1111 0000
>>
Binary Right Shift
A >> 2,0000 1111
B=13 ‫ و‬A=60 ‫• مثال‬
27
‫عملگرهای شرطی‬
if (condition)
Expresion1;
else
Expresion2;
• Condition ? Expresion1 : Expresion2;
28
sizeof
• returns the number of bytes
• returns an unsigned integer result
• sizeof variable-identifier;
• sizeof (variable-identifier);
• sizeof (Data_Type);
29
‫‪Operator precedence‬‬
‫جدول روبرو اولویت عملگرها را‬
‫پایین نشان می دهد‬
‫‪1‬‬
‫)(‬
‫از‪~ ++ --‬‬
‫باال ! به‬
‫‪2‬‬
‫‪sizeof‬‬
‫‪3‬‬
‫‪* / %‬‬
‫‪4‬‬
‫ ‪+‬‬‫‪5‬‬
‫>> <<‬
‫> > =< <‬
‫‪6‬‬
‫=‬
‫‪7‬‬
‫=! ==‬
‫‪8‬‬
‫&‬
‫‪9‬‬
‫^‬
‫‪10‬‬
‫|‬
‫‪11‬‬
‫&&‬
‫‪12‬‬
‫||‬
‫‪13‬‬
‫?‬
‫ =‪= +‬‬‫‪14‬‬
‫=‪= *= /‬‬
‫=‪%‬‬
‫‪15‬‬
‫‪,‬‬
‫‪30‬‬
‫ساختارهای کنترلی‬
• Sequence
• Decision Selection Statement
- if
- if… else
- switch
• Repetition
while
- do… while
- for
31
‫ساختارهای تصمیم‬
if(condition)
{
// statement(s) will execute if the Boolean expression is true
}
32
‫ساختارهای تصمیم‬
‫مثال ‪ :‬يك بلوك دستورالعمل درون يك دستور ‪if‬‬
‫اين برنامه دو عدد صحيح را گرفته و به ترتيب بزرگتري‪ ،‬آنها را چاپ ميكند‪:‬‬
‫)(‪int main‬‬
‫;‪{ int x, y‬‬
‫;" ‪cout << "Enter two integers:‬‬
‫;‪cin >> x >> y‬‬
‫;‪if (x > y) { int temp = x‬‬
‫;‪x = y‬‬
‫;‪y = temp‬‬
‫‪} //swap x and y‬‬
‫;‪cout << x << " <= " << y << endl‬‬
‫}‬
‫‪33‬‬
‫ساختارهای تصمیم‬
if(condition)
{// statement(s) will execute if the Boolean expression is true}
else
{ // statement(s) will execute if the boolean expression is false }
34
‫ساختارهای تصمیم‬
‫مثال يک آزمون قابليت تقسيم‬
int main()
{
int n, d;
cout << " Enter two positive integers: ";
cin >> n >> d;
if (n%d)
cout << n << " is not divisible by " << d << endl;
else
cout << n << " is divisible by " << d << endl;
}
35
‫ساختارهای تصمیم‬
‫‪36‬‬
‫ساختارهای تصمیم‬
switch(expression)
{
case constant-expression1 :
statement(s)1;
break; //optional
case constant-expression2 :
statement(s)2;
break; //optional
// you can have any number of case statements.
default : //Optional
statement(s);
}
37
‫حلقه های تکرار‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫حلقه ‪while‬‬
‫خاتمه دادن به یک حلقه‬
‫حلقه ‪do … while‬‬
‫حلقه ‪for‬‬
‫دستور ‪break‬‬
‫دستور ‪continue‬‬
‫دستور ‪goto‬‬
‫‪38‬‬
while ‫حلقه ی‬
39
while ‫حلقه ی‬
while ‫ محاسبۀ حاصل جمع اعداد صحيح متوالي با حلقۀ‬:‫مثال‬
:‫ محاسبه ميكند‬n ‫ را براي عدد ورودي‬1 + 2 + 3 + … + n ‫اين برنامه مقدار‬
int main()
{ int n, i=1;
cout << "Enter a positive integer: ";
cin >> n;
long sum=0;
while (i <= n)
sum += i++;
cout << "The sum of the first " << n << " integers is "
<< sum;
}
40
‫خاتمه دادن به یک حلقه‬
.‫نیز ميتوان استفاده کرد‬
‌ ‫ براي پايان دادن به حلقه‌ها‬break ‌‫از دستور‬
41
int main()
{ int n, i=1;
cout << "Enter a positive integer: ";
cin >> n;
long sum=0;
while (true)
{ if (i > n) break;
sum += i++;
}
cout << "The sum of the first " << n << " integers is " <<
sum;
}
‫خاتمه دادن به یک حلقه‬
while ‫ محاسبۀ حاصل جمع اعداد صحيح متوالي با حلقۀ‬:‫مثال‬
:‫ محاسبه ميكند‬n ‫ را براي عدد ورودي‬1 + 2 + 3 + … + n ‫اين برنامه مقدار‬
int main()
{ int n, i=1;
cout << "Enter a positive integer: ";
cin >> n;
long sum=0;
while (i <= n)
sum += i++;
cout << "The sum of the first " << n << " integers is "
<< sum;
}
42
‫خاتمه دادن به یک حلقه‬
‫ همۀ اعداد فيبوناچي را تا يك محدودۀ مشخص که از ورودي دريافت‬،‫ برنامۀ زير‬:‫• مثال‬
:‫ محاسبه و چاپ ميكند‬،‫ميشود‬
int main()
{ long bound;
cout << "Enter a positive integer: ";
cin >> bound;
cout << "Fibonacci numbers < " << bound << ":\n f0, f1";
long f0=0, f1=1;
while (true)
{ long f2 = f0 + f1;
if (f2 > bound) break;
cout << ", " << f2;
f0 = f1;
f1 = f2;}
}
43
‫خاتمه دادن به یک حلقه‬
‫ هرچند که اين تابع بالفاصله‬.‫ي براي خاتمه دادن به يك حلقه‌ است‬
‌ ‫ روش ديگر‬exit(0) ‫تابع‬
:‫اجراي کل برنامه را پايان مي‌دهد‬
int main()
{ long bound;
cout << "Enter a positive integer: ";
cin >> bound;
cout << "Fibonacci numbers < " << bound << ":\n0, 1";
long f0=0, f1=1;
while (true)
{ long f2 = f0 + f1;
if (f2 > bound) exit(0);
cout << ", " << f2;
f0 = f1;
f1 = f2; }
}
44
‫حلقه ی ‪do…while‬‬
‫ساختار ‪ do..while‬روش ديگري براي ساختن حلقه است‪ .‬نحو آن به صورت زير است‪:‬‬
‫;)‪do statement while (condition‬‬
‫به جاي ‪ condition‬يك شرط قرار ميگیرد و به جاي ‪ statement‬دستور يا بلوکي قرار‬
‫ميگیرد که قرار است تکرار شود‪.‬‬
‫‪45‬‬
do…while ‫حلقه ی‬
do..while ‫• محاسبۀ حاصل جمع اعداد صحيح متوالي با حلقۀ‬
int main()
{ int n, i=0;
cout << "Enter a positive integer: ";
cin >> n;
long sum=0;
do
sum += i++;
while (i <= n);
cout << "The sum of the first " << n << " integers is " << sum;
}
46
do…while ‫حلقه ی‬
:‫ چاپ ميکند‬،‫• برنامۀ زير همۀ اعداد فاكتوريال را که از عدد داده شده کوچکترند‬
int main()
{ long bound;
cout << "Enter a positive integer: ";
cin >> bound;
cout << "Factorial numbers < " << bound << ":\n1";
long f=1, i=1;
do
{ cout << ", " << f;
f *= ++i;
}
while (f < bound);
}
47
‫حلقه ی ‪for‬‬
‫نحو دستورالعمل ‪ for‬به صورت زير است‪:‬‬
‫;‪for (initialization; condition; update) statement‬‬
‫سه قسمت داخل پرانتز‪ ،‬حلقه را کنترل ميکنند‪.‬‬
‫مثال‪ :‬استفاده از حلقۀ ‪ for‬براي محاسبۀ مجموع اعداد صحيح متوالي‬
‫‪48‬‬
for ‫حلقه ی‬
‫ براي محاسبۀ مجموع اعداد صحيح متوالي‬for ‫ استفاده از حلقۀ‬:‫مثال‬
int main()
{ int n;
cout << "Enter a positive integer: ";
cin >> n;
long sum=0;
for (int i=1; i <= n; i++)
sum += i;
cout << "The sum of the first " << n << " integers is " << sum;
}
49
‫حلقه ی ‪for‬‬
‫• مثال‪ :‬يك حلقۀ ‪ for‬نزو لي‪ ،‬برنامۀ زير ده عدد صحيح مثبت را به ترتيب نزو لي چاپ‬
‫ميكند‪:‬‬
‫)(‪int main‬‬
‫)‪{ for (int i=10; i > 0; i--‬‬
‫;‪cout << " " << i‬‬
‫}‬
‫• مثال ‪ ،‬بيشتر از يك متغیر كنترل در حلقۀ ‪ ،forT‬حلقۀ ‪ for‬در برنامۀ زير دو متغیر كنترل‬
‫دارد‪:‬‬
‫)(‪int main‬‬
‫)‪{ for (int m=95, n=11; m%n > 0; m -= 3, n++‬‬
‫;‪cout << m << "%" << n << " = " << m%n << endl‬‬
‫}‬
‫‪50‬‬
continue ‫دستور‬
.‫ ادامۀ چرخۀ فعلي را لغو کرده و اجراي دور بعدي حلقه را آغاز ميکند‬،‫اين دستور‬
continue ‫ و‬break ‫ استفاده از دستورهاي‬،‫مثال‬
:‫ را شرح ميدهد‬continue ‫ و‬break ‫ دستورهاي‬،‫اين برنامۀ كوچك‬
int main()
{ int n = 1;
char c;
for( ; ;n++ )
{ cout << "\nLoop no: " << n << endl;
cout << "Continue? <y|n> ";
cin >> c;
if (c = = 'y') continue;
break;
}
cout << "\nTotal of loops: " << n;
51 }
‫دستور ‪goto‬‬
‫• دستور‪ goto‬نوع ديگري از دستورهاي پرش است‪ .‬مقصد اين پرش توسط يك برچسب‬
‫معین ميشود‪.‬‬
‫• برچسب شناسهاي است كه جلوي آن عالمت كولن( ‪ ) :‬ميآيد و جلوي يك دستور ديگر‬
‫قرار ميگیرد‪.‬‬
‫• يک مزيت دستو ‌ر ‪ goto‬اين است که با استفاده ‌از آن مي‌توان ‌از همۀ حلقه‌هاي تودرت ‌و‬
‫در برنامه پرش نمود‪.‬‬
‫خارج شد ‌و به مکان دلخواهي ‌‬
‫‪52‬‬
goto ‫دستور‬
‫ براي خارج شدن از حلقههاي تودرتو‬goto ‫ استفاده از دستور‬،‫• مثال‬
int main()
{ const int N=5;
for (int i=0; i<N; i++)
{ for (int j=0; j<N; j++)
{ for (int k=0; k<N; k++)
if (i+j+k>N) goto esc;
else cout << i+j+k << " ";
cout << "* ";
}
esc: cout << "." << endl;
}
}
53
‫توابع‬
‫‪54‬‬
‫توابع‬
‫با استفاده از توابع می توان برنامه های ساخت یافته نوشت‪ ،‬وظایف این برنامه ها توسط‬
‫بخش های مستقلی که تشکیل دهنده ی برنامه اند انجام می شود‪.‬‬
‫• نوشتن ساده تر‬
‫• ایجاد همکاری بین افراد‬
‫• اشکال زدایی ساده تر‬
‫• صرفه جویی در زمان‬
‫‪55‬‬
‫توابع‬
‫هر تابع دارای سه جنبه است‪:‬‬
‫• جنبه تعریف‬
‫• جنبه فراخوانی‬
‫• جنبه اعالن‬
‫‪56‬‬
‫توابع کتابخانه ای ‪ C++‬استاندارد‬
‫ساير‬
‫• «كتابخانۀ ‪ C++‬استاندارد» مجموعه‌اي است که شامل توابع‌ ‌از پيش تعريف شده ‌و ‌‬
‫عناصر ‌از طريق «سرفايل‌ها» قابل دستيابي‌اند‪.‬‬
‫‌‬
‫عناصر برنامه است‪ .‬اين توابع ‌و‬
‫‌‬
‫• قب ‌ال برخي ‌از آن‌ها را استفاده كرده‌ايم‪ :‬تابع ()‪ sqrt‬که در <‪ >cmath‬تعريف شده است و‪...‬‬
‫‪.‬‬
‫• مثال‪ :‬برنامۀ سادۀ زير‪ ،‬تابع از پيش تعريف شدۀ جذر را به کار ميگیرد‪:‬‬
‫>‪#include <cmath‬‬
‫‪// defines the sqrt() function‬‬
‫‪#include <iostream> // defines the cout object‬‬
‫;‪using namespace std‬‬
‫)(‪int main‬‬
‫‪{ //tests the sqrt() function:‬‬
‫)‪for (int x=0; x < 6; x++‬‬
‫;‪cout << "\t" << x << "\t" << sqrt(x) << endl‬‬
‫}‬
‫‪57‬‬
‫توابع کتابخانه ای ‪ C++‬استاندارد‬
‫احضار تابع» گفته مي‌شود‪ .‬بنابراين وقتي كد )‪ sqrt(x‬اجرا شود‪ ،‬تابع‬
‫‌‬
‫اين کار «فراخواني تابع» يا «‬
‫در‬
‫امتر واقعي» فراخواني ناميده مي‌شود‪‌ .‬‬
‫)(‪ sqrt‬فراخواني مي‌گردد‪ .‬عبارت ‪ x‬درون پرانتز «آرگومان» يا «پار ‌‬
‫چنین حالتي مي‌گوييم كه ‪ x‬توسط «مقدار» به تابع فرستاده مي‌شود‪ .‬لذا وقتي ‪ x=3‬است‪ ،‬با اجراي کد‬
‫نیز حاصل‬
‫)‪ sqrt(x‬تابع )(‪ sqrt‬فراخواني شده ‌و مقدار ‪ 3‬به آن فرستاده مي‌شود‪ .‬تابع مذکور‌ ‌‬
‫‪ 1.73205‬را به عنوان پاسخ برمي‌گرداند…‬
‫فرخواني اين توابع به شكل زير است‪:‬‬
‫;)‪functionName (argument‬‬
‫•‬
‫آرگومان توابع مي تواند يكي از انواع زير باشد‬
‫– ثابت‬
‫;) ‪sqrt( 4‬‬
‫– متغیر‬
‫;) ‪sqrt( x‬‬
‫– عبارت‬
‫; ) ) ‪sqrt( sqrt( x‬‬
‫;) ‪sqrt( 3 - 6x‬‬
‫‪58‬‬
‫توابع کتابخانه ای ‪ C++‬استاندارد‬
‫بيشتر توابع معروف رياض ي كه در ماشینحسابها هم وجود دارد در سرفايل >‪ <cmath‬تعريف شده است‪.‬‬
‫بعض ي از اين توابع در جدول زير نشان داده شده‪:‬‬
‫‪59‬‬
‫توابع ساخت کاربر‬
‫• مثال‪ :‬تابع )(‪ ، cube‬يك مثال ساده از توابع ساخت كاربر‪:‬‬
‫)‪int cube(int x‬‬
‫‪{ // returns cube of x:‬‬
‫;‪return x*x*x‬‬
‫}‬
‫‪60‬‬
‫توابع ساخت کاربر‬
‫يك تابع ساخت كاربر دو قسمت دارد‪:‬‬
‫‪-1‬عنوان‬
‫‪ -2‬بدنه‪.‬‬
‫عنوان يك تابع به صورت زير است‪:‬‬
‫(فهرست‌ پارامترها) نام نوع بازگشتي‬
‫مثال‪:‬‬
‫)‪int cube(int x‬‬
‫{‬
‫…‬
‫بدنه تابع‬
‫}‬
‫‪61‬‬
‫برنامه ی آزمون‬
‫نياز را ايجاد کرديد‪ ،‬فورا بايد آن تابع را با يک برنامۀ ساده امتحان کنيد‪.‬‬
‫وقتي يک تابع مورد ‌‬
‫چنین برنامه‌اي برنامۀ آزمون ناميده مي‌شود‪.‬‬
‫کار آن است‪.‬‬
‫تنها هدف اين برنامه‪ ،‬امتحان کردن تابع ‌و بررس ي صحت ‌‬
‫• برنامۀ آزمون‌ يک برنامۀ موقتي است که بايد «سريع ‌و کثيف» باشد؛‬
‫يعني‪:‬‬
‫در آن تمام ظرافت‌هاي برنامه‌نويس ي – مثل پيغام‌هاي خروجي‪ ،‬برچسب‌ها ‌و‬
‫• الزم نيست ‌‬
‫راهنماهاي خوانا – را لحاظ کنيد‪.‬‬
‫‪62‬‬
‫برنامه ی آزمون‬
‫ و برنامۀ آزمون آن‬cube() ‫ کد زير شامل تابع‬،cube() ‫ يك برنامۀ آزمون براي تابع‬،‫مثال‬
:‫است‬
int cube(int x)
{ // returns cube of x:
return x*x*x;
}
int main()
{ // tests the cube() function:
int n=1;
while (n != 0)
{ cin >> n;
cout << "\tcube(" << n << ") = " << cube(n) << endl; }}
63
‫برنامه ی آزمون‬
‫هر عدد صحيحي که خوانده مي‌شود‪ ،‬با استفاده ‌از کد )‪ cube(n‬به تابع )(‪cube‬‬
‫• ‌‬
‫مقدار بازگشتي ‌از تابع‪ ،‬جايگزين عبارت )‪ cube(n‬گشته ‌و با استفاده از‬
‫‌‬
‫فرستاده مي‌شود‪.‬‬
‫در خروجي چاپ می شود‪.‬‬
‫‪‌ cout‬‬
‫)(‪cube‬‬
‫‪x 5‬‬
‫‪int‬‬
‫)(‪main‬‬
‫‪5‬‬
‫‪5‬‬
‫‪125‬‬
‫‪64‬‬
‫برنامه ی آزمون‬
‫ اين تابع از دو مقدار فرستاده‬.‫ تابع زير دو پارامتر دارد‬،max() ‫ يك برنامۀ آزمون براي تابع‬،‫مثال‬
:‫ مقدار بزرگتر را برميگرداند‬،‫شده به آن‬
int max(int x, int y)
{ // returns larger of the two given integers:
int z;
z = (x > y) ? x : y ;
return z;
}
int main()
{ int m, n;
do
{ cin >> m >> n;
cout << "\tmax(" << m << "," << n << ") = " << max(m,n) << endl; }
65 while (m != 0);}
‫اعالن و تعاریف توابع‬
‫به د ‌و روش ميتوان توابع را تعريف نمود‪:‬‬
‫‪-1‬توابع قبل ‌از تابع )(‪ main‬به طور‌ كامل با بدنه مربوطه آورده شوند‪.‬‬
‫بيشتر رواج دارد اين گونه است که ابتدا تابع اعالن شود‪ ،‬سپس متن برنامۀ‬
‫‌‬
‫ي که‬
‫‪-2‬راه ديگر ‌‬
‫اصلي)(‪ main‬بيايد‪ ،‬پس از آن تعريف کامل تابع قر ‌ار بگیرد‪.‬‬
‫• اعالن تابع با تعريف تابع تفاوت دارد‪.‬‬
‫در انتهاي آن قر ‌ار دارد‪.‬‬
‫• اعالن تابع‪ ،‬فقط عنوان تابع است که يک سميکولن ‌‬
‫• تعريف تابع‪ ،‬متن کامل تابع است که هم شامل عنوان است ‌و هم شامل بدنه‬
‫‪66‬‬
‫اعالن و تعاریف توابع‬
‫ با اعالن‌ جدا ‌از تعريف آن‬max()‫ تابع‬،‫• مثال‬
int max(int,int);
int main()
{
int m, n;
do
{
cin >> m >> n;
cout << "\tmax(" << m << "," << n << ") = "
<< max(m,n) << endl;
while (m != 0);}
int max(int x, int y)
{if (x < y) return y;
else return x;}
67
}
‫آرگومان و پارامتر‬
‫امتر يک تابع نام برده مي‌شوند‪(.‬هنگام تعریف‬
‫در فهرست پار ‌‬
‫• پارامترها متغیرهايي هستند که ‌‬
‫تابع)‬
‫در طول‌ اجراي تابع وجود‬
‫• پارامترها متغیرهاي محلي براي تابع محسوب مي‌شوند؛ يعني فقط ‌‬
‫دارند‪.‬‬
‫• آرگومانها متغیرهايي هستند که ‌از برنامۀ اصلي به تابع فرستاده مي‌شوند‪( .‬هنگام فراخوانی‬
‫تابع)‬
‫‪68‬‬
‫متغیرهای محلی‪ ،‬توابع محلی‬
‫متغیر محلي‪ ،‬متغیري است که در داخل يک بلوک اعالن گردد‪ .‬اين گونه متغیرها فقط در‬
‫‌‬
‫•‬
‫داخل همان بلوکي که اعالن ميشوند قابل دستيابي هستند‪.‬‬
‫• چون بدنۀ تابع‪ ،‬خودش يک بلوک است پس متغیرهاي اعالن شده در يک تابع متغیرهاي‬
‫محلي براي آن تابع هستند‪.‬‬
‫• اين متغیرها فقط تا وقتي که تابع در حال کار است وجود دارند‪.‬‬
‫• پارامترهاي تابع نیز متغیرهاي محلي محسوب ميشوند‪.‬‬
‫‪69‬‬
‫توابع‬
‫• مثال‪ ،‬تابع فاكتوريل‪ ،‬فاكتوريل عدد صحيح ‪ n‬برابر است با‪:‬‬
‫)‪n! = n(n-1)(n-2)..(3)(2)(1‬‬
‫تابع زير‪ ،‬فاکتوريل عدد ‪ n‬را محاسبه ميکند‪:‬‬
‫)‪long fact(int n‬‬
‫)‪{ //returns n! = n*(n-1)*(n-2)*...*(2)*(1‬‬
‫;‪if (n < 0) return 0‬‬
‫;‪int f = 1‬‬
‫)‪while (n > 1‬‬
‫;‪f *= n--‬‬
‫;‪return f‬‬
‫}‬
‫‪70‬‬
‫تابع ‪void‬‬
‫• الزم نيست يك تابع حتما مقداري را برگرداند‪ .‬در ‪ C++‬براي مشخص کردن چنین توابعي‬
‫از کلمۀ کليدي ‪ void‬به عنوان نوع بازگشتي تابع استفاده ميکنند‬
‫• يک تابع ‪ void‬تابعي است که هيچ مقدار بازگشتي ندارد‪.‬‬
‫• از آنجا كه يك تابع ‪ void‬مقداري را برنميگرداند‪ ،‬نيازي به دستور ‪ return‬نيست ولي‬
‫اگر قرار باشد اين دستور را در تابع ‪ void‬قرار دهيم‪ ،‬بايد آن را به شکل تنها استفاده‬
‫کنيم بدون اين که بعد از کلمۀ ‪ return‬هيچ چیز ديگري بيايد‪:‬‬
‫;‪return‬‬
‫• در اين حالت دستور ‪ return‬فقط تابع را خاتمه ميدهد‪.‬‬
‫‪72‬‬
‫توابع بولی‬
‫در برنامه‪ ،‬شرطي بررس ي شود‪.‬‬
‫در بسياري‌ ‌از اوقات الزم است ‌‬
‫• ‌‬
‫بهتر است که يک تابع اين بررس ي‬
‫نياز داشته باشد‪‌ ،‬‬
‫اگر بررس ي اين شرط به دستورات زيادي ‌‬
‫• ‌‬
‫بسيار مفيد است‪.‬‬
‫‌‬
‫کار مخصوصا هنگامي که ‌از حلقه‌ها استفاده مي‌شود‬
‫را انجام دهد‪ .‬اين ‌‬
‫• توابع بولي فقط دو مقدار را برميگردانند‪ true :‬يا ‪. false‬‬
‫• اسم توابع بولي را معموال به شکل سوالي انتخاب مي‌کنند زيرا توابع بولي هميشه به يک سوال‬
‫مفروض پاسخ بلي يا خیر مي‌دهند‪.‬‬
‫•‬
‫‪73‬‬
‫ کد زير يك تابع بولي است كه‬،‫ تابعي كه اول بودن اعداد را بررس ي ميكند‬،‫مثال‬
:‫ اول است يا خیر‬،‫تشخيص ميدهد آيا عدد صحيح ارسال شده به آن‬
bool isPrime(int n)
{
// returns true if n is prime, false otherwise:
float sqrtn = sqrt(n);
if (n < 2) return false;
// 0 and 1 are not primes
if (n < 4) return true;
// 2 and 3 are the first primes
if (n%2 == 0) return false; // 2 is the only even prime
for (int d=3; d <= sqrtn; d += 2)
if (n%d == 0) return false; // n has a nontrivial divisor
return true;
}
74
// n has no nontrivial divisors
‫توابع ورودی و خروجی )‪(Input/Output‬‬
‫برنامه‬
‫گیر مي‌پردازد ‌و خيلي به هدف اصلي ‌‬
‫• بخش‌هايي ‌از برنامه که به جزييات دست ‌و پا ‌‬
‫در چنین شرايطي سودمندي توابع محسوس‌ت ‌ر‬
‫مربوط نيست را مي‌توان به توابع سپرد‪‌ .‬‬
‫مي‌شود‪.‬‬
‫• فرض کنيد نرم‌افزاري‌ براي سيستم آموزش ي دانشگاه طراحي کرده‌ايد که سوابق تحصيلي‬
‫دانشجو به عنوان يکي ‌از‬
‫‌‬
‫در اين نرم‌افز ‌ار الزم است که سن‬
‫دانشجويان را نگه مي‌دارد‪‌ .‬‬
‫اگر وظيفۀ دريافت سن را به عهدۀ يک تابع بگذاريد‪،‬‬
‫اطالعات پروندۀ دانشج ‌و وارد شود‪‌ .‬‬
‫در اين تابع‬
‫مي‌توانيد جزيياتي ‌از قبيل کنتر ‌ل ورودي معتبر‪ ،‬يافتن سن ‌از روي تاريخ تولد و ‪‌ ...‬را ‌‬
‫مسیر برنامۀ اصلي منحرف شويد‪.‬‬
‫پياده‌سازي‌ کنيد بدون‌ اين که ‌از ‌‬
‫‪75‬‬
‫• مثال‪ ،‬تابعي براي دریافت سن كاربر‪ ،‬تابع سادۀ‬
‫زیر‪ ،‬سن کاربر را درخواست ميکند و مقدار‬
‫دریافت شده را به برنامۀ اصلي ميفرستد‪ .‬این‬
‫تابع تقریبا هوشمند است و هر عدد صحیح ورودي‬
‫غیر منطقي را رد ميکند و به طور مکرر درخواست‬
‫ورودي معتبر ميکند تا این که یک عدد صحیح در‬
‫محدودۀ ‪ 7‬تا ‪ 120‬دریافت دارد‪:‬‬
‫)(‪int age‬‬
‫‪{ // prompts the user to input his/her age and returns that value:‬‬
‫;‪int n‬‬
‫)‪while (true‬‬
‫;" ‪{ cout << "How old are you:‬‬
‫;‪cin >> n‬‬
‫‪if (n < 0) cout << "\a\tYour age could not‬‬
‫;"‪be negative.‬‬
‫‪else if (n > 120) cout << "\a\tYou could not‬‬
‫;"‪be over 120.‬‬
‫;‪else return n‬‬
‫;"‪cout << "\n\tTry again.\n‬‬
‫}‬
‫} ‪76‬‬
‫یك برنامۀ آزمون و خروجي حاصل از آن در ادامه‬
:‫آمده است‬
int age();
int main()
{ // tests the age() function:
int a = age();
cout << "\nYou are " << a << " years old.\n";
}
How old are you? 125
You could not be over 120
Try again.
How old are you? -3
Your age could not be negative
Try again.
How old are you? 99
You are 99 years old
77
‫تا این لحظه تمام پارامترهایي كه در توابع‬
‫دیدیم به طریق مقدار ارسال شدهاند‪ .‬یعني ابتدا‬
‫مقدار متغیري که در فراخواني تابع ذکر شده‬
‫برآورد ميشود و سپس این مقدار به پارامترهاي‬
‫محلي تابع فرستاده ميشود‪.‬‬
‫مثال در فراخواني )‪ cube(x‬ابتدا مقدار ‪ x‬برآورد‬
‫شده و سپس این مقدار به متغیر محلي ‪ n‬در تابع‬
‫فرستاده ميشود و پس از آن تابع کار خویش را‬
‫آغاز ميکند‪ .‬در طي اجراي تابع ممکن است مقدار ‪n‬‬
‫تغییر کند اما چون ‪ n‬محلي است هیچ تغییري روي‬
‫مقدار ‪ x‬نميگذارد‪.‬‬
‫پس خود ‪ x‬به تابع نميرود بلکه مقدار آن درون‬
‫تابع کپي ميشود‪.‬‬
‫تغییر دادن این مقدار کپي شده درون تابع هیچ‬
‫تاثیري بر ‪ x‬اصلي ندارد‪ .‬به این ترتیب تابع‬
‫ميتواند مقدار ‪ x‬را بخواند اما نميتواند مقدار‬
‫‪ x‬را تغییر دهد‪.‬‬
‫به همین دلیل به ‪ x‬یک پارامتر «فقط‬
‫خواندني» ‪78‬‬
‫ارسال به طریق ارجاع(آدرس)‬
‫• ارسال به طريق مقدار باعث ميشود که متغیرهاي برنامۀ اصلي از تغيیرات ناخواسته در‬
‫توابع مصون بمانند‪.‬‬
‫• اما گاهي اوقات عمدا ميخواهيم اين اتفاق رخ دهد‪ .‬يعني ميخواهيم که تابع بتواند‬
‫محتويات متغیر فرستاده شده به آن را دستکاري کند‪ .‬در اين حالت از ارسال به طريق‬
‫ارجاع استفاده ميکنيم‪.‬‬
‫• براي اين که مشخص کنيم يک پارامتر به طريق ارجاع ارسال ميشود‪ ،‬عالمت & را به‬
‫نوع پارامتر در فهرست پارامترهاي تابع اضافه ميکنيم‪ .‬اين باعث ميشود که تابع به جاي‬
‫اين که يک کپي محلي از آن آرگومان ايجاد کند‪ ،‬خود آرگومان محلي را به کار بگیرد‪.‬‬
‫• به اين ترتيب تابع هم ميتواند مقدار آرگومان فرستاده شده را بخواند و هم ميتواند‬
‫مقدار آن را تغيیر دهد‪ .‬در اين حالت آن پارامتر يک پارامتر «خواندني‪-‬نوشتني» خواهد بود‪.‬‬
‫‪79‬‬
‫ارسال به طریق ارجاع(آدرس)‬
‫• هر تغيیري که روي پارامتر خواندني‪-‬نوشتني در تابع صورت گیرد به طور مستقيم روي‬
‫متغیر برنامۀ اصلي اعمال ميشود‪ .‬به مثال زير نگاه کنيد‪.‬‬
‫• تابع ‪ swap‬که در مرتب کردن داده ها کاربرد زیادی دارد‪.‬‬
‫)‪void swap(float& x, float& y‬‬
‫‪{ // exchanges the values of x and y:‬‬
‫هدف اين تابع جابجا کردن دو عنصري است‬
‫که به آن فرستاده ميشوند‪ .‬براي اين منظور‬
‫پارامترهاي ‪ x‬و ‪ y‬به صورت پارامترهاي ارجاع‬
‫تعريف شدهاند‪:‬‬
‫‪float& x, float& y‬‬
‫;‪float temp = x‬‬
‫;‪x = y‬‬
‫;‪y = temp‬‬
‫}‬
‫‪80‬‬
y ‫ و‬x ‫• عملگر ارجاع & موجب ميشود كه به جاي‬
‫ برنامۀ آزمون‬.‫آرگومانهاي ارسالي قرار بگیرند‬
:‫و اجراي آزمایشي آن در زیر آمده است‬
void swap(float&, float&);
// exchanges the values of x and y:
int main()
{ // tests the swap() function:
float a = 55.5, b = 88.8;
cout << "a = " << a << ", b = " << b << endl;
swap(a,b);
cout << "a = " << a << ", b = " << b << endl;
}
81
a = 55.5, b = 88.8
a = 88.8, b = 55.5
‫ ارسال به طریق مقدار و ارسال به طریق‬:‫مثال‬
‫ارجاع‬
void f(int,int&);
int main()
{ int a = 22, b = 44;
cout << "a = " << a << ", b = " << b << endl;
f(a,b);
cout << "a = " << a << ", b = " << b << endl;
f(2*a-3,b);
cout << "a = " << a << ", b = " << b << endl;}
void f(int x , int& y)
{ x = 88;
a = 22, b = 44
y = 99;}
a = 22, b = 99
a = 22, b = 99
82
‫ارسال از طریق ارجاع‬
‫ارسال از طریق مقدار‬
‫;‪int& x‬‬
‫;‪int x‬‬
‫پارامتر ‪ x‬یک ارجاع است‬
‫پارامتر ‪ x‬یک متغیر محلي است‬
‫‪ x‬مترادف با آرگومان است‬
‫‪ x‬یک کپي از آرگومان است‬
‫ميتواند محتویات آرگومان را‬
‫تغییر دهد‬
‫تغییر محتویات آرگومان ممکن‬
‫نیست‬
‫آرگومان ارسال شده از طریق‬
‫ارجاع فقط باید یک متغیر باشد‬
‫آرگومان ارسال شده از طریق‬
‫مقدار ميتواند یک ثابت‪ ،‬یک‬
‫متغیر یا یک عبارت باشد‬
‫آرگومان خواندني‪-‬نوشتني است‬
‫آرگومان فقط خواندني است‬
‫‪83‬‬
‫مثال‪ :‬بازگشت بیش از یک متغیر‪ ،‬تابع زیر از‬
‫طریق دو پارامتر ارجاع‪ ،‬دو مقدار را‬
‫بازميگرداند‪ area :‬و ‪( circumference‬محیط و‬
‫مساحت) براي دایرهاي که شعاع آن عدد مفروض ‪r‬‬
‫است‪:‬‬
‫)‪void ComputeCircle(double& area, double& circumference, double r‬‬
‫‪{ // returns the area and circumference of a circle with radius r:‬‬
‫;‪const double PI = 3.141592653589793‬‬
‫;‪area = PI*r*r‬‬
‫;‪circumference = 2*PI*r‬‬
‫}‬
‫• برنامۀ آزمون تابع فوق و یک اجراي آزمایشي آن‬
‫در اسالید بعد نشان داده شده است‪.‬‬
‫‪84‬‬
void ComputerCircle(double&, double&, double);
// returns the area and circumference of a circle with radius r;
int main()
{ // tests the ComputeCircle() function:
double r, a, c;
cout << "Enter radius: ";
cin >> r;
ComputeCircle(a, c, r);
cout << "area = " << a << ", circumference = "
<< c << endl;}
85
‫ارسال به طریق ارجاع ثابت‬
‫ارسال پارامترها به طریق ارجاع دو خاصیت مهم‬
‫دارد‪:‬‬
‫‪ ‬اول این که تابع ميتواند روي آرگومان واقعي‬
‫تغییراتي بدهد‬
‫‪ ‬دوم این که از اشغال بيمورد حافظه جلوگیري‬
‫دیگري نیز براي ارسال آرگومان وجود دارد‪:‬‬
‫روش‬
‫ميشود‪.‬‬
‫‪ ‬ارسال از طریق ارجاع ثابت‪ .‬این روش مانند‬
‫ارسال از طریق ارجاع است با این فرق که تابع‬
‫نميتواند محتویات پارامتر ارجاع را دستکاري‬
‫نماید و فقط اجازۀ خواندن آن را دارد‪.‬‬
‫‪ ‬براي این که پارامتري را از نوع ارجاع ثابت‬
‫اعالن کنیم باید عبارت ‪ const‬را به ابتداي اعالن‬
‫آن اضافه نماییم‪.‬‬
‫‪86‬‬
‫مثال‪ :‬ارسال از طریق ارجاع ثابت‪ ،‬در تابع زیر‬
‫سه طریقه ارسال پارامتر به کار رفته است‪:‬‬
‫)‪void f(int x, int& y, const int& z‬‬
‫;‪{ x += z‬‬
‫;‪y += z‬‬
‫" = ‪cout << "x = " << x << ", y = " << y << ", z‬‬
‫;‪<< z << endl‬‬
‫}‬
‫‪87‬‬
‫ برنامه ی آزمون و یک اجرای آزمایشی از‬:‫مثال‬
‫مثال قبل‬
a = 22, b = 33, c = 44
x = 66, y = 77, z = 44
a = 22, b = 77, c = 44
x = 85, y = 121, z = 44
a = 22, b = 121, c = 44
void f(int, int&, const int&);
int main()
{ // tests the f() function:
int a = 22, b = 33, c = 44;
cout << "a = " << a << ", b = " << b << ", c = "
<< c << endl;
f(a,b,c);
cout << "a = " << a << ", b = " << b << ", c = "
<< c << endl;
f(2*a-3,b,c);
cout << "a = " << a << ", b = " << b << ", c = "
<< c << endl;
}
88
‫چندشکلی توابع‬
‫‪ ‬در ‪ C++‬ميتوانیم چند تابع داشته باشیم که‬
‫همگي یک نام دارند‪ .‬در این حالت ميگوییم که‬
‫تابع مذکور‪ ،‬چندشکلي دارد‪ .‬شرط این کار آن‬
‫است که فهرست پارامترهاي این توابع با‬
‫تعداد‬
‫یعني‬
‫باشد‪.‬‬
‫داشته‬
‫تفاوت‬
‫یکدیگر‬
‫پارامترها متفاوت باشد یا دست کم یکي از‬
‫پارامترهاي متناظر هم نوع نباشند‪.‬‬
‫مثال‪ :‬چندشکلي تابع )(‪ ،max‬در مثال های قبلی‬
‫تابع ‪ max‬را تعریف کرده ایم‪ ،‬حاال توابع دیگري‬
‫با همان نام ولي شکلي متفاوت تعریف ميکنیم و‬
‫همه را در یک برنامه به کار ميگیریم‪:‬‬
‫;)‪int max(int, int‬‬
‫;)‪int max(int, int, int‬‬
‫;)‪89 int max(double, double‬‬
int max(int x, int y)
{ // returns the maximum of the two given integers:
return (x > y ? x : y);
}
int max(int x, int y, int z)
{ // returns the maximum of the three given integers:
int m = (x > y ? x : y); // m = max(x , y)
return ( z > m ? z : m);
}
int max(double x, double y)
{ // return the maximum of the two given doubles:
return (x>y ? x : y);
}
90
‫تابع ‪main‬‬
‫برنامههایي که تا کنون نوشتیم همه داراي تابعي‬
‫به نام )(‪ main‬هستند‪.‬‬
‫منطق ‪ C++‬این طور است که هر برنامه باید داراي‬
‫تابعي به نام )(‪ main‬باشد‪.‬‬
‫در حقیقت هر برنامه کامل‪ ،‬از یک تابع )(‪ main‬به‬
‫همراه توابع دیگر تشکیل شده است که هر یک از‬
‫این توابع به شکل مستقیم یا غیر مستقیم از درون‬
‫تابع )(‪ main‬فراخواني ميشوند‪.‬‬
‫خود برنامه با فراخواني تابع )(‪ main‬شروع ميشود‪.‬‬
‫چون این تابع یک نوع بازگشتي ‪ int‬دارد‪ ،‬منطقي‬
‫است که بلوک تابع )(‪ main‬شامل دستور ;‪return 0‬‬
‫باشد هرچند که در برخي از کامپایلرهاي ‪ C++‬این‬
‫خط اجباري نیست و ميتوان آن را ذکر نکرد‪.‬‬
‫مقدار صحیحي که با دستور ‪ return‬به سیستم عامل‬
‫‪91‬‬
‫آرایه ها‬
‫‪92‬‬
‫آرایه ها‬
‫• یک آرایه‪ ،‬یك زنجیره از متغیرهایي است كه همه‬
‫از یك نوع هستند‪.‬‬
‫• به این متغیرها «اعضاي آرایه» ميگویند‪.‬‬
‫• هر عضو آرایه با یک شماره مشخص ميشود که به‬
‫این شماره «ایندکس» یا «زیرنویس» ميگویند‬
‫• عناصر یک آرایه در خانههاي پشت سر هم در حافظه‬
‫ذخیره ميشوند‪ .‬به این ترتیب آرایه را ميتوان‬
‫بخشي از حافظه تصور کرد که این بخش خود به‬
‫قسمتهاي مساوي تقسیم شده و هر قسمت به یک عنصر‬
‫تعلق دارد‪.‬‬
‫‪93‬‬
‫آرایه ها‬
‫شکل مقابل آرايۀ ‪ a‬که پنج عنصر دارد را نشان‬
‫ميدهد‪.‬‬
‫عنصر ]‪ a[0‬حاوي مقدار ‪ 17.5‬و عنصر ]‪ a[1‬حاوي ‪19.0‬‬
‫و عنصر ]‪ a[4‬حاوي مقدار ‪ 18.0‬است‪.‬‬
‫‪17.50‬‬
‫‪0‬‬
‫‪19.00‬‬
‫‪1‬‬
‫‪16.75‬‬
‫‪2‬‬
‫‪15.00‬‬
‫‪3‬‬
‫‪18.00‬‬
‫‪4‬‬
‫‪94‬‬
‫آرایه ها‬
‫; ]‪int x[5‬‬
‫‪x‬‬
‫‪4‬‬
‫پنجمین عنصر ]‪x[4‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫اولین عنصر ]‪x[0‬‬
‫‪95‬‬
‫آرایه ها‬
‫مثال‪ :‬دستيابي مستقيم به عناصر آرايه‪ ،‬برنامۀ سادۀ زير يک آرايۀ سه عنصري را تعريف‬
‫ميکند و سپس مقاديري را در آن قرار داده و سرانجام اين مقادير را چاپ ميکند‪:‬‬
‫‪a[0] = 11‬‬
‫‪a[1] = 33‬‬
‫‪a[2] = 55‬‬
‫)(‪int main‬‬
‫;]‪{ int a[3‬‬
‫;‪a[2] = 55‬‬
‫;‪a[0] = 11‬‬
‫;‪a[1] = 33‬‬
‫;‪cout << "a[0] = " << a[0] << endl‬‬
‫;‪cout << "a[1] = " << a[1] << andl‬‬
‫;‪cout << "a[2] = " << a[2] << endl‬‬
‫}‬
‫‪96‬‬
‫آرایه ها‬
‫•‬
‫نحو کلي براي اعالن آرايه به شکل زير است‪:‬‬
‫;]‪type array_name[array_size‬‬
‫عبارت ‪ type‬نوع عناصر آرايه را مشخص ميکند‪ array_name .‬نام آرايه است ‪.‬‬
‫‪ array_size‬تعداد عناصر آرايه را نشان ميدهد‪ .‬اين مقدار بايد يک عدد ثابت صحيح باشد و‬
‫حتما بايد داخل کروشه ][ قرار بگیرد‪.‬‬
‫• میزان حافظه ی آرایه=طول نوع عناصر آرایه * طول آرایه‬
‫‪97‬‬
‫مقدار دهی آرایه ها‬
‫• در ‪ C++‬مي‌توانيم يک آرايه را با استفاده ‌از فهرست مقداردهي‪ ،‬اعالن ‌و مقدارگذاري‌ کنيم‪:‬‬
‫;}‪float a[] = {22.2,44.4,66.6‬‬
‫عناصر آرايه قر ‌ار‬
‫‌‬
‫مقادير داخل فهرست به همان ترتيبي که چيده شده‌اند درون‬
‫‌‬
‫• به اين ترتيب‬
‫در فهرست خواهد بود‪.‬‬
‫عناصر موجود ‌‬
‫‌‬
‫ابر با تعداد‬
‫نیز بر ‌‬
‫مي‌گیرند‪ .‬اندازه آرايه ‌‬
‫• پس همین خط مختصر‪ ،‬آرايهاي از نوع ‪ float‬و با نام ‪ a‬و با تعداد سه عنصر اعالن کرده‬
‫و هر سه عنصر را با مقدارهاي درون فهرست‪ ،‬مقداردهي ميکند‪.‬‬
‫;}‪float a[5] = {22.2,44.4,66.6‬‬
‫اگر تعداد مقادير اوليه كمتر از تعداد عضوهاي آرايه باشد عضوهاي باقيمانده بطور اتوماتيك‪ ،‬مقدار اوليه صفر مي‌گیرند‪.‬‬
‫‌‬
‫‪98‬‬
‫مقدار دهی آرایه ها‬
float a[] = {22.2,44.4,66.6};
22.2
44.4
66.6
float a[5] = {22.2,44.4,66.6};
22.2
44.4
66.6
0.0
0.0
22.2
44.4
66.6
-
-
float a[5];
a[0]=22.2;
a[1]=44.4;
a[2]=66.6;
99
‫مقدار دهی آرایه ها‬
‫مقدار آنها را به‬
‫‌‬
‫عملگر جايگزيني مقداردهي کرد اما نميتوان‬
‫‌‬
‫آرايهها را ميتوان با استفاده ‌از‬
‫يکديگر تخصيص داد‪:‬‬
‫‌‬
‫;} ‪float a[7] = { 22.2, 44.4, 66.6‬‬
‫;} ‪float b[7] = { 33.3, 55.5, 77.7‬‬
‫!‪b = a; // ERROR: arrays cannot be assigned‬‬
‫ديگر استفاده كنيم‪:‬‬
‫همچنین نميتوانيم يك آرايه را به طو ‌ر مستقيم براي مقداردهي به آرايۀ ‌‬
‫;} ‪float a[7] = { 22.2, 44.4, 66.6‬‬
‫‪float b[7] = a; // ERROR: arrays cannot be used as‬‬
‫!‪initializers‬‬
‫‪100‬‬
‫ایندکس بیرون از حدود آرایه ها‬
‫بيشتر‬
‫‌‬
‫در بعض ي ‌از زبان‌هاي برنامه‌نويس ي‪ ،‬ايندکس آرايه نمي‌تواند ‌از محدودۀ تعريف شده براي آن‬
‫‌‬
‫عنصر تعريف شده باشد ‌و آنگاه ]‪a[7‬‬
‫‌‬
‫اگر آرايۀ ‪ a‬با تعداد پنج‬
‫در پاسکال ‌‬
‫باشد‪ .‬براي مثال ‌‬
‫کار مي‌افتد‪ .‬اين سيستم حفاظتي در ‪ C++‬وجود ندارد‪ .‬مثال بعدي‬
‫دستيابي شود‪ ،‬برنامه ‌از ‌‬
‫عناصر تعريف شده براي آن‬
‫‌‬
‫بيشتر ‌از‬
‫‌‬
‫نشان مي‌دهد که ايندکس يک آرايه هنگام دستيابي مي‌تواند‬
‫باز هم بدون‌ اين که خطايي گرفته شود‪ ،‬برنامه ادامه يابد‪.‬‬
‫باشد ‌و ‌‬
‫‪101‬‬
‫ایندکس بیرون از حدود آرایه ها‬
‫مثال‪ :‬تجاوز ايندکس آرايه از محدودۀ تعريف شده براي آن‬
‫برنامۀ ز ‌ير يک خطاي زمان اجرا دارد؛ به بخش ي ‌از حافظه دستيابي مي‌کند که ‌از محدودۀ آرايه‬
‫بیرون است‪:‬‬
‫)(‪in main‬‬
‫;‪{ const int SIZE=4‬‬
‫‪a[0] = 33.3‬‬
‫‪a[1] = 44.4‬‬
‫;} ‪float a[SIZE} = { 33.3, 44.4, 55.5, 66.6‬‬
‫‪a[2] = 55.5‬‬
‫!‪for (int i=0; i<7; i++) //ERROR: index is out of bounds‬‬
‫‪a[3] = 66.6‬‬
‫‪a[4] = 5.60519e-45‬‬
‫‪a[5] = 6.01888e-39‬‬
‫;‪cout << "\ta[" << i << "] = " << a[i] << endl‬‬
‫}‬
‫‪a[6] = 6.01889e-39‬‬
‫‪102‬‬
‫مثال‪ :‬اثر همسايگي‪ ،‬برنامۀ ز ‌ير ‌از ايندکس خارج ‌از محدوده استفاده مي‌کند ‌و اين باعث مي‌شود که‬
‫تغيیر کند‪:‬‬
‫متغیر به طو ‌ر ناخواسته ‌‬
‫‌‬
‫مقدار يک‬
‫‌‬
‫)(‪int main‬‬
‫;‪{ const int SIZE=4‬‬
‫;} ‪float a[] = { 22.2, 44.4, 66.6‬‬
‫;‪float x=11.1‬‬
‫;‪cout << "x = " << x << endl‬‬
‫!‪a[3] = 88.8; // index is out of bounds‬‬
‫;‪cout << "x = " << x << endl‬‬
‫}‬
‫‪x = 88.8‬‬
‫‪103‬‬
‫متغیر ‪ x‬بعد از آرايۀ ‪ a‬اعالن‌ شده‪ ،‬پس يک سلول‌ چهاربايتي بالفاصله بعد ‌از دوازده بايت آرايه به آن‬
‫تخصيص مي‌يابد‪ .‬بنابراين وقتي برنامه تالش مي‌کند مقدار ‪ 88.8‬را در ]‪ a[3‬قر ‌ار دهد (که جز ‌و‬
‫مقدار به شکل ناخواسته در ‪ x‬قر ‌ار مي‌گیرد‪ .‬شکل مقابل نشان مي‌دهد چطور‌ اين‬
‫‌‬
‫آرايه نيست) اين‬
‫در حافظه رخ مي‌دهد‪.‬‬
‫اتفاق ‌‬
‫• اين خطا يکي ‌از وحشت‌ناک‌ترين خطاهاي زمان اجراست‬
‫زيرا ممکن است اص ‌ال نتوانيم منبع خطا را کشف کنيم‪.‬‬
‫ديگري‌‬
‫حتي ممکن است به اين روش داده‌هاي برنامه‌هاي ‌‬
‫در حال کارند را خراب کنيم ‌و اين باعث ايجاد اختالل‬
‫که ‌‬
‫اثر همسايگي»‬
‫در کل سيستم شود‪ .‬به اين خطا « ‌‬
‫‌‬
‫مي‌گويند‪ .‬اين وظيفۀ برنامه‌نويس است که تضمین کند‬
‫ايندکس آرايه هيچ‌گاه ‌از محدودۀ آن خارج نشود‪.‬‬
‫‪22.2‬‬
‫‪44.4‬‬
‫‪66.6‬‬
‫‪88.8‬‬
‫‪a‬‬
‫‪22.2‬‬
‫‪44.4‬‬
‫‪66.6‬‬
‫‪0‬‬
‫‪1‬‬
‫‪2‬‬
‫‪88.8‬‬
‫‪x‬‬
‫‪104‬‬
‫ارسال آرایه ها به توابع‬
‫كامپايلر مي‌گويد‪:‬‬
‫‌‬
‫چیز را به‬
‫كد ;][‪ float a‬كه آرايه ‪ a‬را اعالن مي‌كند د ‌و ‌‬
‫‪ -1‬اين که نام آرايه ‪ a‬است‬
‫عناصر آرايه ‌از نوع ‪ float‬هستند‪.‬‬
‫‌‬
‫‪-2‬‬
‫کامپايلر گفته شود‬
‫‌‬
‫عناصر آرايه به‬
‫‌‬
‫سمبل ‪ a‬نشاني حافظۀ آرايه را ذخیره مي‌کند‪ .‬الزم نيست تعداد‬
‫عناصر را بازيابي نمود‪ .‬به همین طريق مي‌توان يک آرايه ‌را به‬
‫‌‬
‫زيرا ‌از روي نشاني موجود در ‪ a‬مي‌توان‬
‫امتر به تابع فرستاده مي‌شود‪.‬‬
‫تابع ارسال کرد‪ .‬يعني فقط نوع آرايه ‌و نشاني حافظۀ آن به عنوان پار ‌‬
‫‪105‬‬
‫ارسال آرایه ها به توابع‬
‫ ارسال آرايه به تابعي كه مجموع عناصر آرايه را برميگرداند‬،‫مثال‬
int sum(int[],int);
int main()
{ int a[] = { 11, 33, 55, 77 };
int size = sizeof(a)/sizeof(int);
cout << "sum(a,size) = " << sum(a,size) << endl;}
int sum(int a[], int n)
{ int sum=0;
for (int i=0; i<n; i++)
sum += a[i];
return sum;
}
106
‫ارسال آرايه به تابع شبيه ارسال متغیر به‬
.‫طريق ارجاع است‬
‫ استفاده مي‌شود تا مقاديري‬read() ‫ در اين برنامه از تابع‬،‫ توابع ورودي و خروجي براي يک آرايه‬،‫مثال‬
:‫ مقادير داخل آرايه چاپ مي‌شوند‬print() ‫ سپس با استفاده از تابع‬.‫به داخل آرايه وارد شود‬
void read(int[],int&);
Enter integers. Terminate with 0:
void print(int[],int);
a[0]: 11
int main()
{ const int MAXSIZE=100;
a[1]: 22
a[2]: 33
a[3]: 44
int a[MAXSIZE]={0}, size;
a[4]: 0
read(a,size);
The array has 4 elements: 11 22 33 44
cout << "The array has " << size << " elements: ";
print(a,size);
}
107
void read(int a[], int& n)
{ cout << "Enter integers. Terminate with 0:\n";
n = 0;
do
{ cout << "a[" << n << "]: ";
cin >> a[n];
} while (a[n++] !=0 && n < MAXSIZE);
--n; // don't count the 0
}
void print(int a[], int n)
{ for (int i=0; i<n; i++)
cout << a[i] << " ";
}
108
‫در ‪ C++‬توابع قادر نيستند تعداد عناصر آرايۀ ارسالي را تشخيص دهند‪ .‬بنابراين به منظور‬
‫ارسال آرايهها به تابع از سه مشخصه استفاده ميشود‪:‬‬
‫‪ – 1‬آدرس اولین خانۀ آرايه‬
‫عناصر آرايه‬
‫‌‬
‫‪ – 2‬تعداد‬
‫عناصر آرايه‬
‫‌‬
‫‪ – 3‬نوع‬
‫عنصر مي‌تواند به تک تک اعضاي آرايه دستيابي کند‪.‬‬
‫‌‬
‫تابع با استفاده ‌از اين سه‬
‫‪109‬‬
‫مرتب سازی آرایه ها‪-‬مرتب سازی حبابی‬
‫• «مرتب‌سازي‌ حبابي» يکي ‌از ساده‌ترين الگوريتم‌هاي مرتب‌سازي‌ است‪.‬‬
‫• در اين روش‪ ،‬آرايه چندين مرتبه پويش ميشود و در هر مرتبه بزرگترين عنصر موجود به‬
‫سمت باال هدايت ميشود و سپس محدودۀ مرتبسازي براي مرتبۀ بعدي يکي کاسته ميشود‪.‬‬
‫• در پايان همۀ پويشها‪ ،‬آرايه مرتب شده است ‪.‬‬
‫‪110‬‬
‫مرتب سازی آرایه ها‪-‬مرتب سازی حبابی‬
‫ديگر به اين شکل است‬
‫عناصر ‌‬
‫‌‬
‫عنصر ‌و انتقال آن به باالي‬
‫‌‬
‫طريقۀ يافتن بزرگ‌ترين‬
‫‪ .1‬اولین عنصر آرايه با عنصر دوم مقايسه ميشود‪.‬‬
‫‪ .2‬اگر عنصر اول بزرگتر بود‪ ،‬جاي اين دو با هم عوض ميشود‪.‬‬
‫‪ .3‬سپس عنصر دوم با عنصر سوم مقايسه ميشود‪.‬‬
‫‪ .4‬اگر عنصر دوم بزرگتر بود‪ ،‬جاي اين دو با هم عوض ميشود‬
‫و به همین ترتيب مقايسه و جابجايي زوجهاي همسايه ادامه مييابد تا وقتي به انتهاي آرايه‬
‫رسيديم‪ ،‬بزرگترين عضو آرايه در خانۀ انتهايي قرار خواهد گرفت‪.‬‬
‫در اين حالت محدودۀ جستج ‌و يکي کاسته مي‌شود‬
‫‌‬
‫‌تر بعدي به مکان باالي محدوده‬
‫ي يکي يکي مقايسه مي‌شوند تا عدد بزرگ ‌‬
‫‌و دوباره زوج‌هاي کنار ‌‬
‫عنصر اول‌ محد ‌ود‬
‫‌‬
‫جستجو به‬
‫‌‬
‫منتقل شود‪ .‬اين پويش ادامه مي‌يابد تا اين که وقتي محدوده‬
‫شد‪ ،‬آرايه مرتب شده است‪.‬‬
‫‪111‬‬
‫مثال مرتبسازي‪ ،‬برنامۀ ز ‌ير تابعي را آزمايش مي‌کند که اين تابع با استفاده ‌از مرتب‌سازي‌ حبابي يک‬
‫آرايه را مرتب مي‌نمايد‪:‬‬
‫;)‪void print(float[],int‬‬
‫;)‪void sort(float[],int‬‬
‫)(‪int main‬‬
‫{‬
‫;}‪float a[]={55.5,22.2,99.9,66.6,44.4,88.8,33.3, 77.7‬‬
‫;)‪print(a,8‬‬
‫;)‪sort(a,8‬‬
‫;)‪print(a,8‬‬
‫}‬
‫‪55.5, 22.2, 99.9, 66.6, 44.4, 88.8, 33.3, 77.7‬‬
‫‪22.2, 33.3, 44.4, 55.5, 66.6, 77.7, 88.8, 99.9‬‬
‫‪112‬‬
‫)‪void sort(float a[], int n‬‬
‫‪{ // bubble sort:‬‬
‫)‪for (int i=1; i<n; i++‬‬
‫)‪for (int j=0; j<n-i; j++‬‬
‫;)]‪if (a[j] > a[j+1]) swap (a[j],a[j+1‬‬
‫تابع )(‪‌ sort‬از د ‌و حلقۀ تودرت ‌و استفاده مي‌كند‪.‬‬
‫}‬
‫اگر آن‌ها خارج ‌از‬
‫‪ -1‬حلقه ‪ for‬داخلي زوج‌هاي همسايه را با هم مقايسه مي‌كند ‌و ‌‬
‫ترتيب باشند‪ ،‬جاي آن د ‌و را با هم عوض مي‌کند‪.‬‬
‫در محدودۀ فعلي به‬
‫عنصر موجود ‌‬
‫‌‬
‫وقتي ‪ for‬داخلي به پايان رسيد‪ ،‬بزرگ‌ترين‬
‫انتهاي آن هدايت شده است‪.‬‬
‫‪-2‬سپس حلقۀ ‪ for‬بیروني محدودۀ جستج ‌و را يکي کم مي‌کند ‌و دوباره ‪ for‬داخلي‬
‫عنصر بعدي به سمت باالي آرايه هدايت شود‪.‬‬
‫‌‬
‫را راه مي‌اندازد تا بزرگ‌ترين‬
‫‪113‬‬
‫جستجو در آرایه ها‪-‬جستجوی خطی‬
‫کار مي‌روند‪.‬‬
‫بيشتر براي پردازش يک زنجیره ‌از داده‌ها به ‌‬
‫‌‬
‫آرايه‌ها‬
‫مقدار خاص درون يک آرايه موجود است يا خیر‪.‬‬
‫‌‬
‫اغلب الزم است که بررس ي شود آيا يک‬
‫عناصر آرايه ‌را جستج ‌و‬
‫‌‬
‫عنصر آرايه شروع کنيم ‌و يکي يکي همۀ‬
‫‌‬
‫ساده‌ترين راه اين است که ‌از اولین‬
‫عنصر قر ‌ار گرفته‪ .‬به اين روش «جستجوي‌ خطي»‬
‫‌‬
‫در کدام‬
‫نظر ‌‬
‫مقدار مورد ‌‬
‫‌‬
‫نماييم تا بفهميم که‬
‫مي‌گويند‪.‬‬
‫‪114‬‬
‫جستجوی خطی‬-‫جستجو در آرایه ها‬
‫ي خطي‬
‌ ‫در اين تابع ‌از روش جستجو‬
‌ ‫ برنامۀ ز ‌ير تابعي را آزمايش مي‌کند که‬،‫مثال جستجوي خطي‬
:‫مقدار خاص استفاده شده‬
‌
‫براي يافتن يک‬
int index(int,int[],int);
int main()
{ int a[] = { 22, 44, 66, 88, 44, 66, 55};
cout << "index(44,a,7) = " << index(44,a,7) << endl;
cout << "index(50,a,7) = " << index(50,a,7) << endl;
}
int index(int x, int a[], int n)
{ for (int i=0; i<n; i++)
if (a[i] == x) return i;
return n; // x not found
}
115
index(44,a,7) = 1
index(40,a,7) = 7
‫جستجو در آرایه ها‪-‬جستجوی دودویی‬
‫نياز است‪.‬‬
‫در روش جستجوي دودويي به يک آرايۀ مرتب ‌‬
‫‌‬
‫‪ ‬هنگام جستج ‌و آرايه ‌از وسط به د ‌و بخش بااليي ‌و پاييني تقسيم مي‌شود‪.‬‬
‫عنصر بخش پاييني مقايسه مي‌شود‪.‬‬
‫‌‬
‫مقدار مورد جستج ‌و با آخرين‬
‫‪‌ ‬‬
‫در بخش پاييني وجود ندارد ‌و بايد‬
‫جستجو ‌‬
‫‌‬
‫جستجو بود‪ ،‬مورد‬
‫‌‬
‫مقدار‬
‫‌‬
‫‌تر ‌از‬
‫عنصر کوچک ‌‬
‫‌‬
‫اگر اين‬
‫‪‌ ‬‬
‫در بخش بااليي به دنبال آن گشت‪.‬‬
‫‌‬
‫دوباره بخش بااليي به دو بخش تقسيم مي‌گردد و گام‌هاي باال تکرار مي‌شود‪.‬‬
‫عنصر محدود مي‌شود که يا آن عنصر با مورد جستجو برابر‬
‫‌‬
‫سرانجام محدودۀ جستجو به يک‬
‫است و عنصر مذکور يافت شده و يا اين که آن عنصر با مورد جستجو برابر نيست و لذا مورد‬
‫جستجو در آرايه وجود ندارد‪.‬‬
‫‌تر به جواب مي‌رسيم‪.‬‬
‫اين روش پيچيده‌تر از روش جستجوي خطي است اما در عوض بسيار سريع ‌‬
‫‪116‬‬
‫مثال جستجوي دودويي‪ ،‬برنامۀ آزمون‌ ز ‌ير با برنامۀ آزمون‌ مثال جستجوی‌ خطی يکي است اما تابعي‬
‫مقدار درون آرايه استفاده مي‌کند‪:‬‬
‫‌‬
‫در ز ‌ير آمده ‌از روش جستجوي‌ دودويي براي يافتن‬
‫که ‌‬
‫;)‪int index(int, int[],int‬‬
‫)(‪int main‬‬
‫;} ‪{ int a[] = { 22, 33, 44, 55, 66, 77, 88‬‬
‫;‪cout << "index(44,a,7) = " << index(44,a,7) << endl‬‬
‫;‪cout << "index(60,a,7) = " << index(60,a,7) << endl‬‬
‫}‬
‫‪117‬‬
int index(int x, int a[], int n)
{ // binary search:
int lo=0, hi=n-1, i;
while (lo <= hi)
{ i = (lo + hi)/2;
// the average of lo and hi
if (a[i] == x) return i;
if (a[i] < x) lo = i+1; // continue search in a[i+1..hi]
else hi = i-1;
// continue search in a[0..i-1]
}
return n;
}
index(44,a,7) = 2
index(60,a,7) = 7
118
// x was not found in a[0..n-1]
‫جستجو در آرایه ها‪-‬جستجوی دودویی‬
‫در آرايۀ ‪n‬‬
‫‌تر مي‌شود‪‌ .‬‬
‫بار که حلقه تکر ‌ار مي‌شود‪ ،‬محدودۀ جستجو ‪ %50‬کوچک ‌‬
‫هر ‌‬
‫در تابع فوق‌ ‌‬
‫‌‬
‫نياز دارد تا به پاسخ برسد‪.‬‬
‫حداکثر به ‪ log2n+1‬مقايسه ‌‬
‫‌‬
‫عنصري‪ ،‬روش جستجوي‌ دودويي‬
‫نياز است‪.‬‬
‫در روش جستجوي‌ خطي به ‪ n‬مقايسه ‌‬
‫حال آن که ‌‬
‫‪119‬‬
‫جستجو در آرایه ها‬
‫تفاوتهاي جستجوي دودويي و خطي‬
‫‌تر ‌از جستجوي‌ خطي است‪.‬‬
‫جستجوي‌ دودويي سريع ‌‬
‫مقادير يکساني باشند‪ ،‬آنگاه جستجوي‌‬
‫‌‬
‫عنصر داراي‬
‫‌‬
‫اگر چند‬
‫در اين است که ‌‬
‫دومین تفاوت ‌‬
‫ي دودويي نمي‌توان گفت‬
‫در مورد جستجو ‌‬
‫خطي هميشه کوچک‌ترين ايندکس را برمي‌گرداند ولي ‌‬
‫که کدام ايندکس بازگردانده مي‌شود‪.‬‬
‫در اين است که جستجوي‌ دودويي فقط روي آرايه‌هاي مرتب کارايي دارد ‌و اگ ‌ر‬
‫سومین فرق‌ ‌‬
‫ي خطي هميشه پاسخ‬
‫ي دودويي پاسخ غلط مي‌دهد ولي جستجو ‌‬
‫آرايه‌اي مرتب نباشد‪ ،‬جستجو ‌‬
‫صحيح خواهد داد‪.‬‬
‫‪120‬‬
‫آرایه ها ی چند بعدی‬
‫همۀ آرايه‌هايي كه تاکنون‌ تعريف کرديم‪ ،‬يک بعدي هستند‪ ،‬خطي هستند‪ ،‬رشته‌اي هستند‪.‬‬
‫هر خانه ‌از آن آرايه‪ ،‬خود يک آرايه باشد‪.‬‬
‫مي‌توانيم آرايه‌اي تعريف کنيم که ‌از نوع آرايه باشد‪ ،‬يعني ‌‬
‫به اين قبيل آرايه‌ها‪ ،‬آرايههاي چندبعدي مي‌گوييم‪.‬‬
‫يک آرايۀ دو بعدي آرايه‌اي است که هر خانه از آن‪ ،‬خود يک آرايۀ يک بعدي باشد‪.‬‬
‫برای مثال در کامپیوتر برای نمایش ماتریس ها از آرایه ها دو بعدی استفاده می شود‪.‬‬
‫يک آرايۀ سه بعدي آرايه‌اي است که هر خانه از آن يک آرايۀ دو بعدي باشد‪.‬‬
‫‪121‬‬
‫آرایه ها ی چند بعدی‬
‫عنصر ‌از نوع ‪ int‬تعريف مي‌کند‪ .‬اين يک آرايۀ يک بعدي‬
‫‌‬
‫• دستور‌ ;]‪ int a[5‬آرايه‌اي با پنج‬
‫است‪.‬‬
‫هر عنصر‪ ،‬خود يک آرايۀ پنج‬
‫عنصر تعريف مي‌کند که ‌‬
‫‌‬
‫• دستو ‌ر ;]‪ int a[3][5‬آرايه‌اي با سه‬
‫عضو دارد‪.‬‬
‫‌‬
‫در مجموع پانزده‬
‫عنصري‌ ‌از نوع ‪ int‬است‪ .‬اين يک آرايۀ د ‌و بعدي است که ‌‬
‫هر عنصر‪ ،‬سه آرايه است‬
‫عنصر تعريف مي‌کند که ‌‬
‫‌‬
‫• دستور‌ ;]‪ int a[2][3][5‬آرايه‌اي با د ‌و‬
‫عضو‬
‫‌‬
‫در مجموع س ي‬
‫هر آرايه پنج عض ‌و ‌از نوع ‪ int‬دارد‪ .‬اين يک آرايۀ سه بعدي است که ‌‬
‫که ‌‬
‫دارد‪.‬‬
‫آرايههاي چند بعدي مثل آرايههاي يک بعدي به توابع فرستاده ميشوند با اين تفاوت که هنگام‬
‫اعالن و تعريف تابع مربوطه‪ ،‬بايد تعداد عناصر بعد دوم تا بعد آخر حتما ذکر شود‪.‬‬
‫‪122‬‬
‫آرایه ها ی چند بعدی‬
‫ماتريسها بوسيله آرايههاي دوبعدي در كامپيوترنمايش داده ميشوند‪.‬‬
‫;]‪int a[3][4‬‬
‫]‪a[2][3‬‬
‫ستون ‪3‬‬
‫ستون ‪2‬‬
‫ستون ‪1‬‬
‫ستون ‪0‬‬
‫]‪a[0][3‬‬
‫]‪a[0][2‬‬
‫]‪a[0][1‬‬
‫]‪a[0][0‬‬
‫سطر ‪0‬‬
‫]‪a[1][3‬‬
‫]‪a[1][2‬‬
‫]‪a[1][1‬‬
‫]‪a[1][0‬‬
‫سطر ‪1‬‬
‫]‪a[2][3‬‬
‫]‪a[2][2‬‬
‫]‪a[2][1‬‬
‫]‪a[2][0‬‬
‫سطر ‪2‬‬
‫]‪a[2][2‬‬
‫]‪a[2][1‬‬
‫]‪a[2][0‬‬
‫]‪a[1][3‬‬
‫]‪a[1][2‬‬
‫]‪a[1][1‬‬
‫]‪a[1][0‬‬
‫]‪a[0][3‬‬
‫]‪a[0][2‬‬
‫]‪a[0][1‬‬
‫]‪a[0][0‬‬
‫‪123‬‬
‫آرایه ها ی چند بعدی‬
‫تخصیص مقادیر اولیه به عناصر آرایه ‪:‬‬
‫; } }‪int a[3][4]={ {1,2,3,4}, {5,6,7,8}, {9,10,11,12‬‬
‫; } ‪int a[3][4]={ 1,2,3,4, 5,6,7,8, 9,10,11,12‬‬
‫; } ‪int a[][4]={ 1,2,3,4, 5,6,7,8, 9,10,11,12‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫‪4‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫‪8‬‬
‫‪7‬‬
‫‪6‬‬
‫‪5‬‬
‫‪1‬‬
‫‪12‬‬
‫‪11‬‬
‫‪10‬‬
‫‪9‬‬
‫‪2‬‬
‫‪124‬‬
‫آرایه ها ی چند بعدی‬
‫; } }‪int a[3][4]= { {1}, {2,3} , {4,5,6‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪1‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫‪6‬‬
‫‪5‬‬
‫‪4‬‬
‫‪2‬‬
‫‪125‬‬
‫آرایه ها ی چند بعدی‬
‫; } ‪int a[3][4]= {1, 2, 3, 4,5‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫‪4‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪5‬‬
‫‪1‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪2‬‬
‫‪126‬‬
‫آرایه ها ی چند بعدی‬
‫در يك آراية دوانديس ي‪ ،‬هر سطر‪ ،‬در حقيقت آرايهاي يك انديس ي است‪ .‬در‬
‫اعالن آرايههاي دوانديس ي ذكر تعداد ستونها الزامي است‪.‬‬
‫;}‪int a[ ][4]={1,2,3,4,5‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫‪4‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪5‬‬
‫‪1‬‬
‫‪127‬‬
‫رشته ها‬
‫• در ‪ c++‬رشته نوع جدیدی نمی باشد بلکه به صورت آرایه ای ‌از کارکترها تعریف می شود‬
‫کارکتر خاص ی به نام ‪ NULL‬استفاده می شود که با ’‪‘\0‬‬
‫• در ‪ c++‬برای تعیین انتهای رشته ‌از ‌‬
‫مشخص می شود‪.‬‬
‫کارکتر رشته ’‪ ‘\0‬می باشد‪.‬‬
‫‌‬
‫• بنابراین آخرین‬
‫;]‪• Char S[10‬‬
‫است‪،‬حداکثر از ‪ 9‬خانه می توان استفاده کرد‪ ،‬آخرین خانه ی بعد‬
‫‌‬
‫در با ‌ال رشته ای ‪ S‬تعریف شده‬
‫‌‬
‫‌از رشته‪ ،‬مقدار ‪ NULL‬یا ’‪ ‘\0‬دارد‪.‬‬
‫طول رشته ها را باید یک واحد بیشتر از آنچه نیاز دارید تعریف کنید‪.‬‬
‫‪128‬‬
‫مقدار اولیه دادن به رشته ها‬
• char S[]= “computer”;
• char St[12]=“algorithm”;
• char Str[]={‘p’, ‘q’, ‘t’, ‘\0’};
129
‫ورودی خروجی رشته ها‬
‫• ‌از همان امکاناتی که برای ورودی خروجی داده ها مورد استفاده قر ‌ار می گرفت می توان برای‬
‫نیز استفاده کرد‪:‬‬
‫ورودی خروجی رشته ها ‌‬
‫;]‪char f[20‬‬
‫;‪cin >> f‬‬
‫;‪cout <<“f is :” <<f‬‬
‫‪130‬‬
‫ورودی خروجی رشته ها‬
‫;)طول رشته ‪ ,‬نام رشته(‪cin.get‬‬
‫;)’جداکننده‘ ‪ ,‬طول رشته ‪ ,‬نام رشته(‪cin.get‬‬
‫تابع ‪ get‬عضو ش یء ‪ cin‬می باش‪.‬‬
‫•تفاوت ‪ cin‬و ‪:get‬‬
‫مگر اینکه برنامه نویس با استفاده‬
‫•در ‪ get‬فقط کلید ‪ Enter‬انتهای رشته را مشخص می کند‪‌ ،‬‬
‫در این تابع رشته می تواند‬
‫کارکتر دیگری‌ را برای این منظور‌ مشخص کرده باشد‪‌ .‬‬
‫‌‬
‫‌از دستور‌ دوم‬
‫نیز باشد‪.‬‬
‫حاوی‌ فاصله ‌و تب ‌‬
‫نیز به عنوان کارکترهای جدا کننده محسوب می شوند‪.‬‬
‫در دستور‌ ‪ cin‬فاصله ‌و تب ‌‬
‫• ‌‬
‫نکته‪ :‬ارسال رشته ها به توابع مانند ارسال آرایه ها به توابع می باشد‪.‬‬
‫‪131‬‬
‫توابع کار با رشته ها‬
‫تابع‬
strcpy(s1, s2);
Copies string s2 into string s1.
strcat(s1, s2);
Concatenates string s2 onto the end of string s1.
strlen(s1);
Returns the length of string s1.
strcmp(s1, s2);
Returns 0 if s1 and s2 are the same; less than 0 if
s1<s2; greater than 0 if s1>s2.
Returns a pointer to the first occurrence of character
ch in string s1.
strchr(s1, ch);
strstr(s1, s2);
132
‫هدف‬
Returns a pointer to the first occurrence of string s2
in string s1.
‫اشاره گرها‬
‫‪133‬‬
‫اشاره گرها‬
‫نظر گرفت‪ .‬براي مثال رايانه‌اي با ‪256‬‬
‫در ‌‬
‫• حافظۀ رايانه را مي‌توان به صورت يک آرايۀ بزرگ ‌‬
‫هر‬
‫ي آرايه‌اي به اندازۀ ‪ 268،435،456‬خانه است که اندازۀ ‌‬
‫در حقيقت حاو ‌‬
‫مگابايت ‪‌ RAM‬‬
‫خانه يک بايت است‪.‬‬
‫هر بايت‪ ،‬آدرس‬
‫صفر تا ‪ 268،435،455‬هستند‪ .‬به ايندکس ‌‬
‫‌‬
‫• اين خانه‌ها داراي ايندکس‬
‫حافظۀ آن مي‌گويند‪.‬‬
‫• آدرس‌هاي حافظه را با اعداد شانزده‌دهي نشان مي‌دهند‪ .‬پس رايانۀ مذکور‌ داراي محدوده‬
‫آدرس ‪ 0x00000000‬تا ‪ 0x0fffffff‬مي‌باشد‪.‬‬
‫متغیر نسبت داده مي‌شود‪« :‬نوع‬
‫هر وقت که متغیري‌ را اعالن مي‌کنيم‪ ،‬سه ويژگي اساس ي به آن ‌‬
‫• ‌‬
‫متغیر» و «نام متغیر» و «آدرس حافظه» آن‪.‬‬
‫‪134‬‬
‫اشاره گرها‬
‫در آن قر ‌ار مي‌گیرد‬
‫• اعالن ;‪ ،int n‬نوع ‪‌ int‬و نام ‪‌ n‬و آدرس چند خانه ‌از حافظه که مقدار ‪‌ n‬‬
‫يکديگر مرتبط مي‌سازد‪ .‬فرض کنيد آدرس اين متغیر ‪ x0050cdc00‬است‪ .‬بنابراين‬
‫‌‬
‫را به‬
‫مي‌توانيم ‪ n‬را مانند شکل مقابل مجسم کنيم‪:‬‬
‫‪n‬‬
‫‪0x0050cdc0‬‬
‫‪int‬‬
‫‪135‬‬
‫اشاره گرها‬
‫متغیر فوق‌ به شکل ;‪ int n=32‬مقداردهي اوليه شود‪ ،‬آنگاه بلوک حافظه به شکل ز ‌ير‬
‫اگر ‌‬
‫‌‬
‫متغیر منظو ‌ر شده ذخیره مي‌شود‪.‬‬
‫چهار بايتي که براي آن ‌‬
‫در ‌‬
‫خواهد بود‪ .‬مقدار ‪‌ 32‬‬
‫‪0x0050cdb8‬‬
‫‪0x0050cdb9‬‬
‫‪0x0050cdc0‬‬
‫‪n‬‬
‫‪32‬‬
‫‪int‬‬
‫‪0x0050cdc0‬‬
‫‪32‬‬
‫‪0x0050cdc1‬‬
‫‪0x0050cdc2‬‬
‫‪0x0050cdc3‬‬
‫‪0x0050cdc4‬‬
‫‪0x0050cdc5‬‬
‫‪136‬‬
‫عملگر ارجاع &‬
‫متغیر مي‌توان از عملگر ارجاع & استفاده نمود‪ .‬به اين‬
‫‌‬
‫در ‪ C++‬براي بدست آوردن آدرس يک‬
‫نیز مي‌گويند‪ .‬عبارت ‪ &n‬آدرس متغیر ‪ n‬را به دست مي‌دهد‪.‬‬
‫علمگر آدرس» ‌‬
‫‌‬
‫عملگر «‬
‫)(‪int main‬‬
‫;‪{ int n=44‬‬
‫;‪cout << " n = " << n << endl‬‬
‫;‪cout << "&n = " << &n << endl‬‬
‫}‬
‫‪n = 44‬‬
‫‪&n = 0x00c9fdc3‬‬
‫‪137‬‬
‫اشاره گرها‬
‫در‬
‫در متغیري‌ ‌از نوع ‪ int‬نگهداري‌ کنيم ‌و اعداد اعشاري‌ را ‌‬
‫مي‌دانيم که اعداد صحيح را بايد ‌‬
‫متغیرهايي ‌از نوع ‪.float‬‬
‫در‬
‫در متغیرهايي ‌از نوع ‪ char‬نگهداريم ‌و مقدارهاي منطقي را ‌‬
‫به همین ترتيب کاراکترها را بايد ‌‬
‫متغیرهايي ‌از نوع ‪.bool‬‬
‫اما آدرس حافظه را در چه نوع متغیري بايد قرار دهيم؟‬
‫متغیري که يک آدرس در آن ذخیره مي‌شود اشارهگر ناميده مي‌شود‪.‬‬
‫‪138‬‬
‫اشاره گرها‬
:‫نح ‌و کلی اعالن اشاره گرها‬
type* pointername;
‫ و يک اشارهگر از‬n ‫ به نام‬int ‫ برنامۀ زير يک متغیر از نوع‬،‫ به کارگیري اشارهگرها‬،‫• مثال‬
:‫ را اعالن ميکند‬pn ‫ به نام‬int* ‫نوع‬
int main()
{ int n=44;
cout << "n = " << n << ", &n = " << &n << endl;
int* pn=&n; // pn holds the address of n
cout << " pn = " << pn << endl; n = 44, &n = 0x0064fddc
cout << "&pn = " << &pn << endl;}
pn = 0x0064fddc
139
&pn = 0x0064fde0
‫متغیر ‪ n‬با مقدار ‪ 44‬مقداردهي‌ شده ‌و آدرس‬
‫آن ‪ 0x0064fddc‬مي‌باشد‪ .‬اشاره‌گر ‪pn‬‬
‫با مقدار ‪ &n‬يعني آدرس ‪ n‬مقداردهي شده‪.‬‬
‫ابر با‬
‫مقدار درون ‪ pn‬بر ‌‬
‫‌‬
‫پس‬
‫‪ 0x0064fddc‬است‌ (خط دوم خروجي‬
‫اين موضوع را تاييد مي‌کند) ‪.‬‬
‫‪n‬‬
‫‪44‬‬
‫‪0x0064fddc‬‬
‫‪int‬‬
‫‪pn‬‬
‫وقتي مي‌گوييم «‪ pn‬به ‪n‬‬
‫متغیر مستقل است ‌و آدرس‬
‫‌‬
‫اما ‪ pn‬يک‬
‫دستس ‪ n‬قرار دارد‪.‬‬
‫مستقلي دارد‪ &pn .‬آدرسدرو‪pn‬ن را‪pn‬به آدر‬
‫*‪int‬‬
‫مي‌دهد‪ .‬خط سوم خروجي ثابت مي‌کند که‬
‫تصوير‬
‫‌‬
‫متغیر ‪ pn‬مستقل ‌از متغیر ‪ n‬است‪.‬‬
‫در‬
‫بهتر اين موضوع کمک مي‌کند‪‌ .‬‬
‫ز ‌ير به درک ‌‬
‫تصوير ويژگي‌هاي مهم ‪ n‬و ‪ pn‬نشان داده‬
‫‌‬
‫اين‬
‫‌گر به ‪ n‬است و ‪ n‬مقدار‬
‫شده‪ pn .‬يک اشاره ‌‬
‫‪ 44‬دارد‪.‬‬
‫‪0x0064fde0 0x0064fddc‬‬
‫اشاره مي‌کند» يعني‬
‫‪44‬‬
‫‪int‬‬
‫‪n‬‬
‫‪pn‬‬
‫*‪int‬‬
‫‪140‬‬
‫اشاره گرها‬
‫فرض کنيد ‪ n‬داراي مقدار ‪ 22‬باشد و ‪ pn‬اشاره‌گري‌ به ‪ n‬باشد‪ .‬با اين حساب بايد بتوان ‌از طريق ‪pn‬‬
‫‌گر به آن اشاره دارد را به دست آورد‪.‬‬
‫به مقدار ‪ 22‬رسيد‪ .‬با استفاده از * مي‌توان مقداري‌ که اشاره ‌‬
‫به اين کار مقداريابي اشارهگر مي‌گوييم‪.‬‬
‫‪141‬‬
‫اشاره گرها‬
‫ فقط يک خط کد‬.‫ اين‌ برنامه‌ همان‌ برنامۀ‌ مثال قبل است‬،‫ مقداريابي يك اشارهگر‬،‫• مثال‬
:‫بيشتر دارد‬
‌
int main()
{ int n=44;
cout << "n = " << n << ", &n = " << &n << endl;
int* pn=&n;
// pn holds the address of n
cout << "
pn = " << pn << endl;
cout << "&pn = " << &pn << endl;
cout << "*pn = " << *pn << endl;
}
142
n = 44, &n = 0x0064fdcc
pn = 0x0064fdcc
&pn = 0x0064fdd0
*pn = 44
‫اعمال روی اشاره گرها‬
‫‪ .1‬عمل انتساب اشاره گرها به یکدیگر‬
‫‪ .2‬اعمال محاسباتی جمع ‌و تفریق‬
‫‪ .3‬عمل مقایسه اشاره گرها‬
‫• انتساب‬
‫;‪int *p1, *p2, x, y‬‬
‫;‪X=50, y=100‬‬
‫;‪P1=&x‬‬
‫;‪p2=&y‬‬
‫;‪*p1=*p2‬‬
‫;‪p1=p2‬‬
‫‪143‬‬
‫اعمال روی اشاره گرها‬
‫• اعمال محاسباتی جمع ‌و تفریق‬
‫‪p‬‬
‫‪p+1‬‬
‫‪p+2‬‬
‫‪p+3‬‬
‫‪1000‬‬
‫;‪char *ch‬‬
‫‪ch‬‬
‫;‪int *p‬‬
‫‪1001‬‬
‫‪ch+1‬‬
‫‪1002‬‬
‫‪ch+2‬‬
‫‪1003‬‬
‫‪ch+3‬‬
‫‪1004‬‬
‫‪ch+4‬‬
‫‪1005‬‬
‫‪ch+5‬‬
‫‪1006‬‬
‫‪ch+6‬‬
‫‪1007‬‬
‫‪ch+7‬‬
‫‪144‬‬
‫اعمال روی اشاره گرها‬
‫• عمل مقایسه اشاره گرها‬
‫;‪int *p1, *p2, x, y‬‬
‫;‪X=50, y=100‬‬
‫;‪p1=&x‬‬
‫;‪p2=&y‬‬
‫)‪if(p1==p2‬‬
‫…‬
‫‪else‬‬
‫…‬
‫‪145‬‬
‫اشاره گرها‬
‫اين‌ مثال‌ نشان‌ مي‌دهد كه‌ چگونه‌ مي‌توان ‌از‬،‫ پيمايش آرايه با استفاده ‌از اشاره‌گر‬،‫• مثال‬
:‫‌گر براي پيمايش يک آرايه استفاده نمود‬
‌ ‫اشاره‬
int main()
{ const int SIZE = 3;
short a[SIZE] = {22, 33, 44};
cout << "a = " << a << endl;
cout << "sizeof(short) = " << sizeof(short) << endl;
short* end = a + SIZE; // converts SIZE to offset 6
short sum = 0;
for (short* p = a; p < end; p++)
{ sum += *p;
a = 0x3fffd1a
cout << "\t p = " << p;
sizeof(short) = 2
cout << "\t *p = " << *p;
p = 0x3fffd1a
cout << "\t sum = " << sum << endl;
p = 0x3fffd1c
}
cout << "end = " << end << endl;
p = 0x3fffd1e
}
end = 0x3fffd20
146
*p = 22
sum = 22
*p = 33
sum = 55
*p = 44
sum = 99
‫اشاره گرها‬
‫وقتي يك اشارهگر شبيه اين اعالن شود‪:‬‬
‫‪// p is a pointer to a float‬‬
‫;‪float* p‬‬
‫يک فضاي چهاربايتي به ‪ p‬تخصيص داده مي‌شود (معموال )‪ sizeof(float‬چهار بايت است)‪ .‬حاال ‪p‬‬
‫ايجاد شده است اما به هيچ جايي اشاره نمي‌کند زيرا هنوز آدرس ي درون آن قرار نگرفته‪ .‬به چنین‬
‫اشاره‌گري اشارهگر سرگردان مي‌گويند‪ .‬اگر سعي کنيم يک اشاره‌گر سرگردان را مقداريابي يا ا ‌رجاع کنيم‬
‫با خطا مواجه مي‌شويم‪.‬‬
‫‪147‬‬
‫اشاره گرها‬
‫مثال دستور‪:‬‬
‫‪*p = 3.14159; // ERROR: no storage has been allocated for *P‬‬
‫خطاست‪ .‬زيرا ‪ p‬به هيچ آدرس ي اشاره نميکند و سيستم عامل نميداند که مقدار‬
‫‪ 3.14159‬را کجا ذخیره کند‪ .‬براي رفع اين مشکل ميتوان اشارهگرها را هنگام اعالن‪،‬‬
‫مقداردهي کرد‪:‬‬
‫‪// x cintains the value 0‬‬
‫;‪float x = 0‬‬
‫‪float* p = &x // now p points to x‬‬
‫‪*p = 3.14159; // O.K. assigns this value to address that p points to‬‬
‫‪148‬‬
‫اشاره گرها‪-‬تخصیص حافظه پویا‬
‫راه حل ديگر اين است که يک آدرس اختصاص ي ايجاد شود و درون ‪ p‬قرار بگیرد‪ .‬بدين ترتيب‬
‫‪ p‬از سرگرداني خارج ميشود‪ .‬اين کار با استفاده از عملگر ‪ new‬صورت ميپذيرد‪:‬‬
‫;‪float* p‬‬
‫‪p = new float; // allocates storage for 1 float‬‬
‫*‪*p = 3.14159; // O.K. assigns this value to that storage‬‬
‫دقت کنيد که عملگر ‪ new‬فقط خود ‪ p‬را مقداردهي ميکند نه آدرس ي که ‪ p‬به آن اشاره‬
‫ميکند‪ .‬ميتوانيم سه خط فوق را با هم ترکيب کرده و به شکل يک دستور بنويسيم‪:‬‬
‫;)‪float* p = new float(3.141459‬‬
‫‪149‬‬
‫اشاره گرها‬
‫تاکنون دانستيم که به دو طريق ميتوان يک متغیر را ايجاد و مقداردهي کرد‪ .‬روش اول‪:‬‬
‫‪// allocates named memory‬‬
‫;‪float x = 3.14159‬‬
‫و روش دوم‪:‬‬
‫‪float* p = new float(3.14159); // allocates unnamed memory‬‬
‫در حالت اول‪ ،‬حافظۀ مورد نياز براي ‪ x‬هنگام کامپايل تخصيص مييابد‪ .‬در حالت دوم‬
‫حافظۀ مورد نياز در زمان اجرا و به يک ش يء بينام تخصيص مييابد که با استفاده از ‪*p‬‬
‫قابل دستيابي است‪.‬‬
‫‪150‬‬
‫حذف حافظه ی پویا‬-‫اشاره گرها‬
delete ‫ با استفاده از عملگر‬: ‫آزاد سازی حافظه ی اشغال شده‬
delete ‫;نام اشاره گر‬
float* p = new float(3.14159);
delete p;
// deallocates q
*p = 2.71828; // ERROR: p has been deallocated
151
‫اشاره گرها‪-‬حذف حافظه ی پویا‬
‫اگر متغیري را صريحا اعالن کردهايد و سپس اشارهگري به آن نسبت دادهايد‪ ،‬از عملگر‬
‫‪ delete‬استفاده نکنيد‪ .‬اين کار باعث اشتباه غیر عمدي زير ميشود‪:‬‬
‫‪float x =3.14159; // x contains the value 3.14159‬‬
‫‪float* p = &x; // p contains the address of x‬‬
‫‪delete p; // WARNING: this will make x free‬‬
‫کد باال باعث ميشود که حافظۀ تخصيصيافته براي ‪ x‬آزاد شود‪ .‬اين اشتباه را به سختي‬
‫ميتوان تشخيص داد و اشکالزدايي کرد‪.‬‬
‫‪152‬‬
‫آرایه های پویا‬
‫در زمان‌ كامپايل‪ ،‬ايجاد ‌و تخصيص‌ داده‌ مي‌شود‪:‬‬
‫‌گر ثابت است كه‌ ‌‬
‫در حقيقت يك اشاره ‌‬
‫نام آرايه ‌‬
‫‪float a[20]; //a is a const pointer to a block of 20 floats‬‬
‫‪// so is p‬‬
‫;]‪float* const p = new float[20‬‬
‫هم ‪‌ a‬و هم ‪ p‬اشاره‌گرهاي ثابتي هستند که به بلوکي حاوي‌ ‪ 20‬متغیر ‪ float‬اشاره دارند‪ .‬به اعالن‬
‫در زمان کامپايل‬
‫نياز براي ‪‌ a‬‬
‫‪ a‬بسته‌بندي ايستا مي‌گويند زيرا اين کد باعث مي‌شود که حافظۀ مورد ‌‬
‫هر حال حافظۀ مربوطه تخصيص خواهد يافت حتي‬
‫تخصيص داده شود‪ .‬وقي برنامه اجرا شود‪ ،‬به ‌‬
‫اگر ‌از آن هيچ استفاده‌اي نشود‪.‬‬
‫‌‬
‫در‬
‫نياز آن فقط ‌‬
‫مي‌توانيم با استفاده ‌از اشاره‌گر‪ ،‬آرايۀ فوق‌ را طوري تعريف کنيم که حافظه مورد ‌‬
‫زمان اجرا تخصيص يابد‪:‬‬
‫;]‪float* p = new float[20‬‬
‫اختيار گذاشته ‌و اشاره‌گر ‪ p‬را به خانۀ اول‌‬
‫‌‬
‫در‬
‫دستور‌ باال‪ 20 ،‬خانۀ خالي حافظه ‌از نوع ‪ float‬را ‌‬
‫آن نسبت مي‌دهد‪ .‬به اين آرايه‪« ،‬آرايۀ پويا» مي‌گويند‪ .‬به اين طرز‌ ايجاد اشيا بسته‌بندي پويا يا‬
‫«بسته‌بندي زمان جرا» مي‌گويند‪.‬‬
‫‪153‬‬
‫آرایه های پویا‬
‫براي آزاد کردن آرايۀ پوياي ‪ p‬براکت‌ها ][ قبل ‌از نام ‪ p‬بايد حتما قيد شوند زيرا ‪ p‬به يک آرايه‬
‫اشاره دارد‪.‬‬
‫;‪delete [] p‬‬
‫‪154‬‬
‫اشاره گر ثابت‬
‫ اشاره‌گرهاي ثابت ‌و اشاره‌گرهايي به ثابت‌ها‬،‫مثال‬
،pc ‫ اشاره به يک ثابت‬،cp ‫‌گر ثابت‬
‌ ‫ اشاره‬،p ‫ اشاره‌گر‬.‫‌گر اعالن شده‬
‌ ‫چهار اشاره‬
‌ ‫در اين کد‬
‌
: cpc ‫‌گر ثابت به يک ثابت‬
‌ ‫اشاره‬
int n = 44;
// an int
int* p = &n;
// a pointer to an int
++(*p);
// OK: increments int *p
++p;
int* const cp = &n;
++(*cp);
++cp;
const int k = 88;
const int * pc = &k;
++(*pc);
++pc;
// OK: increments pointer p
// a const pointer to an int
// OK: increments int *cp
// illegal: pointer cp is const
// a const int
// a pointer to a const int
// illegal: int *pc is const
// OK: increments pointer pc
const int* const cpc = &k; // a const pointer to a const int
++(*cpc);
155 ++cpc;
// illegal: int *pc is const
// illegal: pointer cpc is const
‫آرایه ای از اشاره گرها‬
‫‌گر باشند‪ .‬مث ‌ال دستور‌‪:‬‬
‫مي‌توانيم آرايه‌اي تعريف کنيم که اعضاي آن ‌از نوع اشاره ‌‬
‫;]‪float* p[4‬‬
‫عناصر اين‬
‫‌‬
‫عنصر ‌از نوع *‪( float‬يعني اشاره‌گري‌ به ‪ )float‬اعالن مي‌کند‪.‬‬
‫‌‬
‫چهار‬
‫آرايۀ ‪ p‬را با ‌‬
‫آرايه را مثل اشاره‌گر‌هاي معمولي مي‌توان مقداردهي کرد‪:‬‬
‫;)‪p[0] = new float(3.14159‬‬
‫;)‪p[1] = new float(1.19‬‬
‫‪p‬‬
‫‪3.14159‬‬
‫‪double‬‬
‫‪1.19‬‬
‫‪double‬‬
‫‪0‬‬
‫‪1‬‬
‫‪2‬‬
‫‪3‬‬
‫‪156‬‬
‫تمرین‬
‫ی حبابی را با استفاده ‌از آرایه ای ‌از اشاره گرها انجام دهید‪ ،‬اشاره گ ‌ر‬
‫مرتب ساز ‌‬
‫عناصر جابجا شوند‪ ،‬اشاره‬
‫‌‬
‫عناصر را داریم‪ ،‬سپس به جای آنکه خود‬
‫‌‬
‫های به‬
‫گرهای آنها جابجا می شوند‪.‬‬
‫‪157‬‬
‫اشاره گری به اشاره گر دیگر‬
char c = 't';
char* pc = &c;
char** ppc = &pc;
char*** pppc = &ppc;
***pppc = 'w'; // changes value of c to 'w'
pppc
ppc
pc
c
158
'\t'
‫اشاره گر به توابع‬
‫حقيقت اين است که نام يک تابع مثل نام يک آرايه‪ ،‬يک اشارهگر ثابت است‪.‬‬
‫نام تابع‪ ،‬آدرس ي از حافظه را نشان ميدهد که کدهاي درون تابع در آن قسمت‬
‫جاي گرفتهاند‪ .‬پس بنابر قسمت قبل اگر اشارهگري به تابع اعالن کنيم‪ ،‬در اصل‬
‫اشارهگري به اشارهگر ديگر تعريف کردهايم‪ .‬اما اين تعريف‪ ،‬نحو متفاوتي دارد‪:‬‬
‫‪// declares function f‬‬
‫;)‪int f(int‬‬
‫‪int (*pf)(int); // declares function pointer pf‬‬
‫‪// assigns address of f to pf‬‬
‫;‪pf = f‬‬
‫;)‪f(4‬‬
‫;)‪pf(4‬‬
‫‪159‬‬
‫اشاره گر به توابع‬
int f(int);
// declares function f
int (*pf)(int); // declares function pointer pf
pf = f;
// assigns address of f to pf
pf
f
160
int f(int n)
{
...
}
#include <iostream>
using namespace std;
void print(int x)
{
cout << x << endl;
}
void print_twice(int x)
{
cout << x << ' ' << x << endl;
}
int main()
{
void (*func_ptr)(int);
func_ptr = print;
func_ptr(10);
func_ptr = print_twice;
func_ptr(20);
}
161
‫ توابعی که یک مقدار صحیح را یک بار و‬:‫مثال‬
‫دوبار در خروجی چاپ می کنند با استفاده از‬
:‫اشاره گر اجرا می شوند‬
‫ و عدد‬pf ‫ اشارهگر تابع‬:‫ در اين مثال دو پارامتر دارد‬sum() ‫ تابع‬،‫مثال تابع مرکب جمع‬
: n ‫صحيح‬
int sum(int (*)(int), int);
int square(int);
int cube(int);
int main()
{ cout << sum(square,4) << endl; // 1 + 4 + 9 + 16
cout << sum(cube,4) << endl; //1 + 8 + 27 + 64
}
int sum(int (*pf)(int k), int n)
{ // returns the sum f(0) + f(1) + f(2) + ... + f(n-1):
int s = 0;
for (int i = 1; i <= n; i++) s += (*pf)(i);
int square(int k) { return k*k; }
int cube(int k)
162
{ return k*k*k; }
30
100
return s;}
‫اشاره گرها‬
‫‪:NULL‬‬
‫• اشاره گری است که به هیچ کجا از حافظه ی مجاز اشاره نمی کند‪،‬‬
‫• هنگام اعالن اشاره گر بهتر است ابتدا مقدار ‪ NULL‬به آن بدهیم تا مقدار زباله ی آن‬
‫پاک شود‬
‫• جهت کنترل هر چه بهتر برنامه استفاده می شود‬
‫>‪#include <stdlib.h> // or <stdio.h‬‬
‫;‪int *q=NULL‬‬
‫;‪int *p‬‬
‫;‪q=NULL; // q=0‬‬
‫… )‪if(q!=0‬‬
‫… )‪if (p‬‬
‫‪163‬‬
‫اشاره گرهای عام‬
void *
void *p;
int i;
char c;
p=&i;
p=&c;
putchar(* (char *)p);
164
:‫اشاره گر به هر نوعی‬
‫عملیات محاسباتی اشاره گرها‬
‫• به اشاره گر می توان مقداری صحیح را اضافه کرد یا مقداری صحیح از آن‬
‫کاست؛‬
‫• متغیرهایی که از نوع اشاره گر می باشند فقط می توانند از یکدیگر کم شوند؛‬
‫;‪int a,b‬‬
‫;‪int *p=&a, *q=&b‬‬
‫‪p=p+q; //ERROR‬‬
‫‪p=p*q; //ERROR‬‬
‫‪p=p/q; //ERROR‬‬
‫!‪p=p-q; //OK‬‬
‫!‪p=p+3; //OK‬‬
‫‪p+=1.6; //ERROR‬‬
‫‪p%=q; //ERROR‬‬
‫‪165‬‬
‫عملیات محاسباتی اشاره گرها‬
int a[10], *p, *q, i;
p=&a[2];
q=&a[5];
i=q-p; /* i is 3 */
i=p-q; /* i is -3 */
a[2]=a[5]=0;
i=*p-*q; /* i=a[2]-a[5] */
if (p<q) …;
if (p==q) …;
if (p!=q) …;
166
‫اشاره گرها و آرایه ها‬
‫• نام آرایه‪ :‬اشاره گری به اولین عنصر آرایه‬
‫;]‪int a[n‬‬
‫;]‪a=&a[0‬‬
‫;)‪a[i]=*(a+i‬‬
‫;‪&a[i]=a+i‬‬
‫;‪int a[10], *p‬‬
‫;]‪p=&a[2‬‬
‫;‪p[0]=10‬‬
‫;‪p[1]=10‬‬
‫;)]‪printf(“%d” , p[3‬‬
‫‪p‬‬
‫]‪p[7‬‬
‫]‪[9‬‬
‫]‪p[5] p[6‬‬
‫]‪p[3] p[4‬‬
‫]‪[7‬‬
‫]‪[5‬‬
‫]‪[8‬‬
‫]‪[6‬‬
‫]‪p[2‬‬
‫]‪[4‬‬
‫]‪p[0] p[1‬‬
‫]‪[3‬‬
‫]‪[2‬‬
‫]‪[1‬‬
‫]‪[0‬‬
‫‪a‬‬
‫‪167‬‬
‫اشاره گرها و آرایه ها‬
‫ اشاره گری به اولین عنصر آرایه‬:‫• نام آرایه‬
int a[n];
a=&a[0];
a[i]=*(a+i);
&a[i]=a+i;
int i;
int array[10];
for(i=0;i<10;i++)
{
array[i]= …;
}
168
0
1
2
3
[0]
[1]
[2]
[3]
a
a+1
a+2
a+3
int *p;
int array[10];
for(p=array;p<&array[10];p++)
{
*p= …;
}
‫اشاره گرها و آرایه ها‬
‫• نام آرایه‪ :‬مانند یک اشاره گر ثابت می باشد که به اولین عنصر آرایه اشاره می‬
‫کند؛‬
‫;‪int a[10], *p, *q‬‬
‫;‪int * const a‬‬
‫‪/* p=&a[0]; */‬‬
‫‪/*q=&a[0]+3; */‬‬
‫‪/* ERROR!!! */‬‬
‫;‪p=a‬‬
‫;‪q=a+3‬‬
‫;‪a++‬‬
‫‪169‬‬
‫مثال‬
int a[10], i;
int *p=a; //int *p=&a[0];
for(i=0;i<10;i++)
scanf(“%d”, a+i); //scanf(“%d”, &a[i]);
for(i=9; i>=0; i--)
printf(“%d”, *(p+i));
//printf(“%d”, a[i]);
//printf(“%d”, p[i]);
170
for(p=a;p<&a[10]; p++)
printf(“%d”, *p);
‫مثال‬
int a[10], *p, *q;
p=&a[2];
q=p+3;
p=q-1;
p++;
q--;
*p=123;
*q=*p;
q=p;
printf(“%d”, *q);
171
‫اشاره گرها و رشته ها‬
‫• رشته ها آرایه ای از کارکترها می باشند‪،‬‬
‫• ارتباطی که برای آرایه ها و اشاره گرها وجود دارد برای رشته ها نیز صادق‬
‫است‪.‬‬
‫;”!‪• char str1[15]=“Hello, world‬‬
‫‪\0‬‬
‫!‬
‫‪d‬‬
‫‪r‬‬
‫‪l‬‬
‫‪w‬‬
‫‪o‬‬
‫‪o‬‬
‫‪,‬‬
‫‪l‬‬
‫‪l‬‬
‫‪e‬‬
‫‪H‬‬
‫;”!‪• char str2[]=“Hello, world‬‬
‫‪\0‬‬
‫!‬
‫‪d‬‬
‫‪l‬‬
‫‪r‬‬
‫‪o‬‬
‫‪w‬‬
‫‪,‬‬
‫‪o‬‬
‫‪l‬‬
‫‪l‬‬
‫‪e‬‬
‫‪H‬‬
‫;”!‪• char *str3=“Hello, world‬‬
‫‪172‬‬
‫اشاره گرها و رشته ها‬
:‫مثال‬
void copy1(char * const s1, const char* const s2)
{
int i;
for(i=0; (s1[i]=s2[i])!=‘\0’;i++);
}
void copy2(char* s1, const char* s2)
{
for(;(*s1=*s2)!=‘\0’;s1++,s2++);
}
173
‫اشاره گرها و رشته ها‬
‫ آرایه ای از اشاره گرها به رشته ها‬:‫مثال‬
char *suit[4]={“Heart”, “Diamond”, “Club”, “Spade”};
suit[0]
H
e
a
r
t
suit[1]
D
i
a
m
o
suit[2]
C
l
u
b
\0
suit[3]
174
S
p
a
d
\0
n
e
\0
d
\0
‫کالس ها و ش ی گرایی‬
‫‪175‬‬