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