C
C
»ﺑﺮﻧﺎﻣﻪﺳﺎﺯﻱ ﭘﻴﺸﺮﻓﺘﻪ«
‐ ﺯﺑﺎﻥ Cﺑﺮﺍﻱ ﺍﺟﺮﺍﻱ ﺑﺴﻴﺎﺭﻱ ﺍﺯ ﺩﺳﺘﻮﺭﺍﺗﺶ ﺍﺯ ﺗﻮﺍﺑﻊ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ ﻭ ﺑﻴﺸﺘﺮ
ﺧﺼﻮﺻﻴﺎﺕ ﻭﺍﺑﺴﺘﻪ ﺑﻪ ﺳﺨﺖﺍﻓﺰﺍﺭ ﺭﺍ ﺑﻪ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﻭﺍﮔﺬﺍﺭ ﻣﻲﻧﻤﺎﻳﺪ .ﻧﺘﻴﺠﻪ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ
ﻧﺮﻡﺍﻓﺰﺍﺭ ﺗﻮﻟﻴﺪ ﺷﺪﻩ ﺑﺎ ﺍﻳﻦ ﺯﺑﺎﻥ ﺑﻪ ﺳﺨﺖﺍﻓﺰﺍﺭ ﺧﺎﺹ ﺑﺴﺘﮕﻲ ﻧﺪﺍﺭﺩ ﻭ ﺑﺎ ﺍﻧﺪﮎ ﺗﻐﻴﻴﺮﺍﺗﻲ
ﻣﻲﺗﻮﺍﻧﻴﻢ ﻧﺮﻡﺍﻓﺰﺍﺭ ﻣﻮﺭﺩ ﻧﻈﺮ ﺭﺍ ﺭﻭﻱ ﻣﺎﺷﻴﻨﻲ ﻣﺘﻔﺎﻭﺕ ﺍﺟﺮﺍ ﮐﻨﻴﻢ .ﻳﻌﻨﻲ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﺑﺎ C
ﻧﻮﺷﺘﻪ ﻣﻲﺷﻮﻧﺪ »ﻗﺎﺑﻠﻴﺖ ﺍﻧﺘﻘﺎﻝ« ﺩﺍﺭﻧﺪ ﻭ ﻣﺴﺘﻘﻞ ﺍﺯ ﻣﺎﺷﻴﻦ ﻫﺴﺘﻨﺪ .ﻋﻼﻭﻩ ﺑﺮ ﺍﻳﻦ C ،ﺍﺟﺎﺯﻩ
ﻣﻲﺩﻫﺪ ﺗﺎ ﮐﺎﺭﺑﺮ ﺗﻮﺍﺑﻊ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ ﺧﺎﺹ ﺧﻮﺩﺵ ﺭﺍ ﺍﻳﺠﺎﺩ ﮐﻨﺪ ﻭ ﺍﺯ ﺁﻥﻫﺎ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺶ
ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﺪ .ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﮐﺎﺭﺑﺮ ﻣﻲﺗﻮﺍﻧﺪ ﺍﻣﮑﺎﻧﺎﺕ Cﺭﺍ ﮔﺴﺘﺮﺵ ﺩﻫﺪ.
‐ ﺑﺮﻧﺎﻡۀ ﻣﻘﺼﺪﻱ ﮐﻪ ﺗﻮﺳﻂ ﮐﺎﻣﭙﺎﻳﻠﺮﻫﺎﻱ Cﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ ﺑﺴﻴﺎﺭ ﻓﺸﺮﺩﻩﺗﺮ ﻭ ﮐﻢﺣﺠﻢﺗﺮ
ﺍﺯ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻣﺸﺎﺑﻪ ﺩﺭ ﺳﺎﻳﺮ ﺯﺑﺎﻥﻫﺎ ﺍﺳﺖ.
C++ﮐﻪ ﺍﺯ ﻧﺴﻞ Cﺍﺳﺖ ،ﺗﻤﺎﻡ ﻭﻳﮋﮔﻲﻫﺎﻱ ﺟﺬﺍﺏ ﺑﺎﻻ ﺭﺍ ﺑﻪ ﺍﺭﺙ ﺑﺮﺩﻩ ﺍﺳﺖ .ﺍﻳﻦ
ﻓﺮﺯﻧﺪ ﺍﻣﺎ ﺑﺮﺗﺮﻱ ﻓﻨﻲ ﺩﻳﮕﺮﻱ ﻫﻢ ﺩﺍﺭﺩ C++ :ﺍﮐﻨﻮﻥ »ﺷﻲﮔﺮﺍ« ﺍﺳﺖ .ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﺍﻳﻦ ﺧﺎﺻﻴﺖ ،ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺷﻲﮔﺮﺍ ﺗﻮﻟﻴﺪ ﻧﻤﻮﺩ .ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺷﻲﮔﺮﺍ ﻣﻨﻈﻢ ﻭ ﺳﺎﺧﺖﻳﺎﻓﺘﻪﺍﻧﺪ،
ﻗﺎﺑﻞ ﺭﻭﺯﺁﻣﺪ ﮐﺮﺩﻥﺍﻧﺪ ،ﺑﻪ ﺳﻬﻮﻟﺖ ﺗﻐﻴﻴﺮ ﻭ ﺑﻬﺒﻮﺩ ﻣﻲﻳﺎﺑﻨﺪ ﻭ ﻗﺎﺑﻠﻴﺖ ﺍﻃﻤﻴﻨﺎﻥ ﻭ ﭘﺎﻳﺪﺍﺭﻱ
ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﻧﺪ.
ﻭ ﺳﺮﺍﻧﺠﺎﻡ ﺁﺧﺮﻳﻦ ﺩﻟﻴﻞ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ C++ﻭﺭﻭﺩ ﺑﻪ ﺩﻧﻴﺎﻱ ) C#ﺑﺨﻮﺍﻧﻴﺪ ﺳﻲ ﺷﺎﺭﭖ(
ﺍﺳﺖ C# .ﮐﻪ ﺍﺧﻴﺮﺍ ﻋﺮﺿﻪ ﺷﺪﻩ ،ﺯﺑﺎﻧﻲ ﺍﺳﺖ ﮐﺎﻣﻼ ﺷﻲﮔﺮﺍ .ﺍﻳﻦ ﺯﺑﺎﻥ ﺩﺭ ﺷﻲﮔﺮﺍﻳﻲ
ﭘﻴﺸﺮﻓﺖﻫﺎﻱ ﺯﻳﺎﺩﻱ ﺩﺍﺭﺩ ﻭ ﻫﻤﻴﻦ ﻣﻮﺿﻮﻉ ﺳﺒﺐ ﭘﻴﭽﻴﺪﮔﻲ ﺑﻴﺸﺘﺮ ﺁﻥ ﺷﺪﻩ ﺍﺳﺖ .ﻭﻟﻲ
ﺑﺮﺍﻱ ﻋﺒﻮﺭ ﺍﺯ ﺍﻳﻦ ﭘﻴﭽﻴﺪﮔﻲ ﻳﮏ ﻣﻴﺎﻥﺑﺮ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﻭ ﺁﻥ C++ﺍﺳﺖ .ﻧﺤﻮ C#ﺑﺴﻴﺎﺭ
ﺷﺒﻴﻪ C++ﺍﺳﺖ .ﺍﮔﺮ C++ﺭﺍ ﺑﻠﺪ ﺑﺎﺷﻴﻢ C#ﺁﻥﻗﺪﺭﻫﺎ ﻫﻢ ﭘﻴﭽﻴﺪﻩ ﻧﻴﺴﺖ .ﮐﻠﻴﺪ ﻭﺭﻭﺩ ﺑﻪ
ﺩﻧﻴﺎﻱ C#ﻣﻴﺎﻥ ﮐﺪﻫﺎﻱ C++ﻧﻬﻔﺘﻪ ﺍﺳﺖ.
1 – 2ﺗﺎﺭﻳﺨﭻۀ C++
ﺩﺭ ﺩﻫﻪ 1970ﺩﺭ ﺁﺯﻣﺎﻳﺸﮕﺎﻩﻫﺎﻱ ﺑﻞ ﺯﺑﺎﻧﻲ ﺑﻪ ﻧﺎﻡ Cﺍﻳﺠﺎﺩ ﺷﺪ .ﺍﻧﺤﺼﺎﺭ ﺍﻳﻦ ﺯﺑﺎﻥ
ﺩﺭ ﺍﺧﺘﻴﺎﺭ ﺷﺮﮐﺖ ﺑﻞ ﺑﻮﺩ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﺩﺭ ﺳﺎﻝ 1978ﺗﻮﺳﻂ Kernighanﻭ Richie
ﺷﺮﺡ ﮐﺎﻣﻠﻲ ﺍﺯ ﺍﻳﻦ ﺯﺑﺎﻥ ﻣﻨﺘﺸﺮ ﺷﺪ ﻭ ﺑﻪ ﺳﺮﻋﺖ ﻧﻈﺮ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺣﺮﻓﻪﺍﻱ ﺭﺍ ﺟﻠﺐ
ﻧﻤﻮﺩ .ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺑﺤﺚ ﺷﻲﮔﺮﺍﻳﻲ ﻭ ﻣﺰﺍﻳﺎﻱ ﺁﻥ ﺩﺭ ﺟﻬﺎﻥ ﻧﺮﻡﺍﻓﺰﺍﺭ ﺭﻭﻧﻖ ﻳﺎﻓﺖ ،ﺯﺑﺎﻥ C
3 ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ C++ ﻓﺼﻞ اول /
ﮐﻪ ﻗﺎﺑﻠﻴﺖ ﺷﻲﮔﺮﺍﻳﻲ ﻧﺪﺍﺷﺖ ﻧﺎﻗﺺ ﺑﻪ ﻧﻈﺮ ﻣﻲﺭﺳﻴﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﺩﺭ ﺍﻭﺍﻳﻞ ﺩﻩۀ 1980
ﺩﻭﺑﺎﺭﻩ ﺷﺮﮐﺖ ﺑﻞ ﺩﺳﺖ ﺑﻪ ﮐﺎﺭ ﺷﺪ ﻭ Bjarne Stroustrupﺯﺑﺎﻥ C++ﺭﺍ
ﻃﺮﺍﺣﻲ ﻧﻤﻮﺩ C++ .ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﺩﻭ ﺯﺑﺎﻥ Cﻭ Simulaﺑﻮﺩ ﻭ ﻗﺎﺑﻠﻴﺖﻫﺎﻱ ﺷﻲﮔﺮﺍﻳﻲ ﻧﻴﺰ
ﺩﺍﺷﺖ .ﺍﺯ ﺁﻥ ﺯﻣﺎﻥ ﺑﻪ ﺑﻌﺪ ﺷﺮﮐﺖﻫﺎﻱ ﺯﻳﺎﺩﻱ ﮐﺎﻣﭙﺎﻳﻠﺮﻫﺎﻳﻲ ﺑﺮﺍﻱ C++ﻃﺮﺍﺣﻲ ﮐﺮﺩﻧﺪ.
ﺍﻳﻦ ﺍﻣﺮ ﺳﺒﺐ ﺷﺪ ﺗﻔﺎﻭﺕﻫﺎﻳﻲ ﺑﻴﻦ ﻧﺴﺨﻪﻫﺎﻱ ﻣﺨﺘﻠﻒ ﺍﻳﻦ ﺯﺑﺎﻥ ﺑﻪ ﻭﺟﻮﺩ ﺑﻴﺎﻳﺪ ﻭ ﺍﺯ
ﻗﺎﺑﻠﻴﺖ ﺳﺎﺯﮔﺎﺭﻱ ﻭ ﺍﻧﺘﻘﺎﻝ ﺁﻥ ﮐﺎﺳﺘﻪ ﺷﻮﺩ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺩﺭ ﺳﺎﻝ 1998ﺯﺑﺎﻥ C++
ﺗﻮﺳﻂ ﻣﻮﺳﺲۀ ﺍﺳﺘﺎﻧﺪﺍﺭﺩﻫﺎﻱ ﻣﻠﻲ ﺁﻣﺮﻳﮑﺎ ) (ANSIﺑﻪ ﺷﮑﻞ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻭ ﻳﮏﭘﺎﺭﭼﻪ
ﺩﺭﺁﻣﺪ .ﮐﺎﻣﭙﺎﻳﻠﺮﻫﺎﻱ ﮐﻨﻮﻧﻲ ﺑﻪ ﺍﻳﻦ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﭘﺎﻳﺒﻨﺪﻧﺪ .ﮐﺘﺎﺏ ﺣﺎﺿﺮ ﻧﻴﺰ ﺑﺮ ﻣﺒﻨﺎﻱ ﻫﻤﻴﻦ
ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻧﮕﺎﺭﺵ ﻳﺎﻓﺘﻪ ﺍﺳﺖ.
1 – 3ﺁﻣﺎﺩﻩﺳﺎﺯﻱ ﻣﻘﺪﻣﺎﺕ
ﻳﮏ »ﺑﺮﻧﺎﻣﻪ «1ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎﻱ ﻣﺘﻮﺍﻟﻲ ﺍﺳﺖ ﮐﻪ ﻣﻲﺗﻮﺍﻧﺪ ﺗﻮﺳﻂ ﻳﮏ ﺭﺍﻳﺎﻧﻪ ﺍﺟﺮﺍ
ﺷﻮﺩ .ﺑﺮﺍﻱ ﻧﻮﺷﺘﻦ ﻭ ﺍﺟﺮﺍﻱ ﻫﺮ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻳﮏ »ﻭﻳﺮﺍﻳﺶﮔﺮ ﻣﺘﻦ «2ﻭ ﻳﮏ »ﮐﺎﻣﭙﺎﻳﻠﺮ«3
ﺍﺣﺘﻴﺎﺝ ﺩﺍﺭﻳﻢ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻭﻳﺮﺍﻳﺶﮔﺮ ﻣﺘﻦ ﻣﻲﺗﻮﺍﻧﻴﻢ ﮐﺪ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﻭﻳﺮﺍﻳﺶ ﮐﻨﻴﻢ.
ﺳﭙﺲ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺍﻳﻦ ﮐﺪ ﺭﺍ ﺑﻪ ﺯﺑﺎﻥ ﻣﺎﺷﻴﻦ ﺗﺮﺟﻤﻪ ﻣﻲﮐﻨﺪ .ﮔﺮﭼﻪ ﻭﻳﺮﺍﻳﺶﮔﺮ ﻭ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺭﺍ
ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺩﻟﺨﻮﺍﻩ ﺍﻧﺘﺨﺎﺏ ﻧﻤﻮﺩ ﺍﻣﺎ ﺍﻣﺮﻭﺯﻩ ﺑﻴﺸﺘﺮ ﺗﻮﻟﻴﺪﮐﻨﻨﺪﮔﺎﻥ ﮐﺎﻣﭙﺎﻳﻠﺮ» ،ﻣﺤﻴﻂ ﻣﺠﺘﻤﻊ
ﺗﻮﻟﻴﺪ «(IDE)4ﺭﺍ ﺗﻮﺻﻴﻪ ﻣﻲﮐﻨﻨﺪ .ﻣﺤﻴﻂ ﻣﺠﺘﻤﻊ ﺗﻮﻟﻴﺪ ﻳﮏ ﺑﺴﺘﻪ ﻧﺮﻡﺍﻓﺰﺍﺭﻱ ﺍﺳﺖ ﮐﻪ
ﺗﻤﺎﻡ ﺍﺑﺰﺍﺭﻫﺎﻱ ﻻﺯﻡ ﺑﺮﺍﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺭﺍ ﻳﮏﺟﺎ ﺩﺍﺭﺩ :ﻳﮏ ﻭﻳﺮﺍﻳﺶﮔﺮ ﻣﺘﻦ ﻭﻳﮋﻩ ﮐﻪ
ﺍﻣﮑﺎﻧﺎﺕ ﺧﺎﺻﻲ ﺩﺍﺭﺩ ،ﻳﮏ ﮐﺎﻣﭙﺎﻳﻠﺮ ،ﺍﺑﺰﺍﺭ ﺧﻄﺎﻳﺎﺑﻲ ﻭ ﮐﻨﺘﺮﻝ ﺍﺟﺮﺍ ،ﻧﻤﺎﻳﺶﮔﺮ ﮐﺪ ﻣﺎﺷﻴﻦ،
ﺍﺑﺰﺍﺭ ﺗﻮﻟﻴﺪ ﺧﻮﺩﮐﺎﺭ ﺑﺮﺍﻱ ﺍﻳﺠﺎﺩ ﺍﻣﮑﺎﻧﺎﺕ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ،ﭘﻴﻮﻧﺪﺩﻫﻨﺪﻩﻫﺎﻱ 5ﺧﻮﺩﮐﺎﺭ،
ﺭﺍﻫﻨﻤﺎﻱ ﺳﺮﻳﻊ ﻭ ﻫﻮﺷﻤﻨﺪ ﻭ . ...ﺑﻴﺸﺘﺮ ﺍﻳﻦ ﺍﺑﺰﺍﺭﻫﺎ ﺑﺮﺍﻱ ﺳﻬﻮﻟﺖ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ،
ﺗﻮﺍﻧﺎﻳﻲﻫﺎﻱ ﻭﻳﮋﻩﺍﻱ ﺩﺍﺭﻧﺪ .ﻭﻳﺮﺍﻳﺶﮔﺮﻫﺎﻱ ﻣﺘﻦ ﮐﻪ ﺩﺭ ﻣﺤﻴﻂﻫﺎﻱ IDEﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ
ﻗﺎﺑﻠﻴﺖﻫﺎﻱ ﺑﺼﺮﻱ ﺑﻪ ﮐﺪ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺩﻫﻨﺪ ﺗﺎ ﮐﺪ ﺧﻮﺍﻧﺎﺗﺮ ﺷﻮﺩ ﻭ ﻧﻮﺷﺘﻦ ﻭ ﺩﻧﺒﺎﻝ ﮐﺮﺩﻥ
ﺑﺮﻧﺎﻣﻪ ﺁﺳﺎﻥﺗﺮ ﺑﺎﺷﺪ .ﺑﻪ ﻋﻨﻮﺍﻥ ﻣﺜﺎﻝ ،ﺩﺳﺘﻮﺭﺍﺕ ﺭﺍ ﺑﺎ ﺭﻧﮓ ﺧﺎﺻﻲ ﻣﺘﻤﺎﻳﺰ ﻣﻲﺳﺎﺯﻧﺪ،
ﻣﺘﻐﻴﺮﻫﺎ ﺭﺍ ﺑﺎ ﺭﻧﮓ ﺩﻳﮕﺮﻱ ﻣﺸﺨﺺ ﻣﻲﮐﻨﻨﺪ ،ﺗﻮﺿﻴﺤﺎﺕ ﺍﺿﺎﻓﻲ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺎﻳﻞ ﻧﺸﺎﻥ
ﻣﻲﺩﻫﻨﺪ ﻭ ﺣﺘﻲ ﺑﺎ ﻧﻮﺷﺘﻪﻫﺎﻱ ﺧﺎﺻﻲ ﺷﻤﺎ ﺭﺍ ﺭﺍﻫﻨﻤﺎﻳﻲ ﻣﻲﮐﻨﻨﺪ ﮐﻪ ﮐﺠﺎﻱ ﺑﺮﻧﺎﻣﻪ ﭼﻪ
ﭼﻴﺰﻫﺎﻳﻲ ﺑﻨﻮﻳﺴﻴﺪ .ﺗﻤﺎﻡ ﺍﻳﻦ ﺍﻣﮑﺎﻧﺎﺕ ﺳﺒﺐ ﺷﺪﻩ ﺗﺎ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺟﺬﺍﺏﺗﺮ ﺍﺯ ﮔﺬﺷﺘﻪ
ﺑﺎﺷﺪ ﻭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺑﻪ ﻋﻮﺽ ﺍﻳﻦ ﮐﻪ ﻧﮕﺮﺍﻥ ﺳﺮﮔﺮﺩﺍﻧﻲ ﺩﺭ ﮐﺪ ﺑﺮﻧﺎﻣﻪ ﻳﺎ ﺭﻓﻊ ﺧﻄﺎ ﺑﺎﺷﺪ،
ﺗﻤﺮﮐﺰ ﺧﻮﻳﺶ ﺭﺍ ﺑﺮ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ ﻭ ﻗﺎﺑﻠﻴﺖﻫﺎﻱ ﺁﻥ ﺍﺳﺘﻮﺍﺭ ﮐﻨﺪ.
C++ ﺑﺴﺖۀ Visual C++ﻣﺤﺼﻮﻝ ﺷﺮﮐﺖ ﻣﻴﮑﺮﻭﺳﺎﻓﺖ ﻭ ﺑﺴﺖۀ
Builderﻣﺤﺼﻮﻝ ﺷﺮﮐﺖ ﺑﻮﺭﻟﻨﺪ ﻧﻤﻮﻧﻪﻫﺎﻱ ﺟﺎﻟﺒﻲ ﺍﺯ ﻣﺤﻴﻂ ﻣﺠﺘﻤﻊ ﺗﻮﻟﻴﺪ ﺑﺮﺍﻱ ﺯﺑﺎﻥ
C++ﺑﻪ ﺷﻤﺎﺭ ﻣﻲﺭﻭﻧﺪ .ﺍﻟﺒﺘﻪ ﻫﺮ ﺩﻭﻱ ﺍﻳﻦﻫﺎ ﻣﺨﺼﻮﺹ ﺳﻴﺴﺘﻢﻋﺎﻣﻞ ﻭﻳﻨﺪﻭﺯ ﻫﺴﺘﻨﺪ .ﺍﮔﺮ
ﻣﻲﺧﻮﺍﻫﻴﺪ ﺭﻭﻱ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﺩﻳﮕﺮﻱ ﻣﺜﻞ Unixﻳﺎ Linuxﺑﺮﻧﺎﻣﻪ ﺑﻨﻮﻳﺴﻴﺪ ﺑﺎﻳﺪ
ﮐﺎﻣﭙﺎﻳﻠﺮﻱ ﮐﻪ ﻣﺨﺼﻮﺹ ﺍﻳﻦ ﺳﻴﺴﺘﻢﻋﺎﻣﻞﻫﺎ ﺍﺳﺖ ﭘﻴﺪﺍ ﮐﻨﻴﺪ.
ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺑﺎ C++ﺭﺍ ﺷﺮﻭﻉ ﮐﻨﻴﻢ ﻳﮏ ﻣﺤﻴﻂ ﻣﺠﺘﻤﻊ ﺗﻮﻟﻴﺪ ﺭﻭﻱ
ﺭﺍﻳﺎﻧﻪﺗﺎﻥ ﻧﺼﺐ ﮐﻨﻴﺪ ﺗﺎ ﺑﺘﻮﺍﻧﻴﺪ ﻣﺜﺎﻝﻫﺎﻱ ﮐﺘﺎﺏ ﺭﺍ ﺧﻮﺩﺗﺎﻥ ﻧﻮﺷﺘﻪ ﻭ ﺍﻣﺘﺤﺎﻥ ﮐﻨﻴﺪ .ﺍﻳﻦ ﮐﺎﺭ
ﻫﻢ ﮐﻤﮏ ﻣﻲﮐﻨﺪ ﺗﺎ C++ﺭﺍ ﺑﻬﺘﺮ ﻳﺎﺩ ﺑﮕﻴﺮﻳﺪ ﻭ ﻫﻢ ﻣﻬﺎﺭﺕﻫﺎﻱ ﺣﺮﻓﻪﺍﻱﺗﺎﻥ ﺭﺍ ﺩﺭ ﮐﺎﺭ ﺑﺎ
ﻣﺤﻴﻂﻫﺎﻱ ﻣﺠﺘﻤﻊ ﺗﻮﻟﻴﺪ ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ.
ﺣﺎﻻ ﺷﻤﺎ ﺭﺍﻳﺎﻧﻪﺍﻱ ﺩﺍﺭﻳﺪ ﮐﻪ ﺑﻪ ﻳﮏ ﮐﺎﻣﭙﺎﻳﻠﺮ C++ﻣﺠﻬﺰ ﺍﺳﺖ .ﺩﺭ ﺍﺩﺍﻡۀ ﻓﺼﻞ،
ﻣﺜﺎﻝﻫﺎﻱ ﺳﺎﺩﻩﺍﻱ ﺍﺯ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ C++ﺭﺍ ﺫﮐﺮ ﻣﻲﮐﻨﻴﻢ ﻭ ﻧﮑﺎﺗﻲ ﺭﺍ ﺩﺭ ﻗﺎﻟﺐ ﺍﻳﻦ ﻣﺜﺎﻝﻫﺎ ﺑﻴﺎﻥ
ﺧﻮﺍﻫﻴﻢ ﮐﺮﺩ .ﺍﮔﺮ ﺍﺯ ﻗﺒﻞ ﺑﺎ Cﻳﺎ C++ﺁﺷﻨﺎﻳﻲ ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﻣﻤﮑﻦ ﺍﺳﺖ ﺍﻳﻦ ﻣﺜﺎﻝﻫﺎ ﻣﺒﻬﻢ
ﺑﻪ ﻧﻈﺮ ﺑﺮﺳﻨﺪ ﻭ ﺑﺮﺧﻲ ﺍﺯ ﻧﮑﺎﺕ ﺭﺍ ﺧﻮﺏ ﺩﺭﮎ ﻧﮑﻨﻴﺪ ،ﺍﻣﺎ ﺍﺻﻼ ﺟﺎﻱ ﻧﮕﺮﺍﻧﻲ ﻧﻴﺴﺖ ﺯﻳﺮﺍ
ﺍﻳﻦ ﻓﺼﻞ ﻳﮏ ﻣﺮﻭﺭ ﮐﻠﻲ ﺭﺍﺟﻊ ﺑﻪ C++ﺍﺳﺖ ﻭ ﺗﻤﺎﻡ ﺍﻳﻦ ﻧﮑﺎﺕ ﺩﺭ ﻓﺼﻞﻫﺎﻱ ﺑﻌﺪﻱ ﺑﻪ
ﺷﮑﻞ ﮐﺎﻣﻞ ﺷﺮﺡ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ .ﺍﻳﻦ ﻓﺼﻞ ﺑﻪ ﺷﻤﺎ ﮐﻤﮏ ﻣﻲﮐﻨﺪ ﺗﺎ ﻧﮑﺎﺕ ﺍﻭﻟﻴﻪ ﻭ
ﺿﺮﻭﺭﻱ C++ﺭﺍ ﻳﺎﺩ ﺑﮕﻴﺮﻳﺪ ﻭ ﻫﻤﭽﻨﻴﻦ ﻣﻄﻠﻊ ﺷﻮﻳﺪ ﮐﻪ ﺩﺭ ﻓﺼﻮﻝ ﺑﻌﺪﻱ ﺑﺎﻳﺪ ﻣﻨﺘﻈﺮ ﭼﻪ
ﻣﻄﺎﻟﺒﻲ ﺑﺎﺷﻴﺪ.
C++ﻧﺴﺒﺖ ﺑﻪ ﺣﺮﻭﻑ »ﺣﺴﺎﺱ ﺑﻪ ﺣﺎﻟﺖ «1ﺍﺳﺖ .ﻳﻌﻨﻲ Aﻭ aﺭﺍ ﻳﮑﻲ ﻧﻤﻲﺩﺍﻧﺪ.
ﭘﺲ ﺩﺭ ﻋﺒﺎﺭﺕﻫﺎﻱ MYﻭ Myﻭ mYﻭ myﻫﻴﭻ ﻳﮏ ﺑﺎ ﺩﻳﮕﺮﻱ ﺑﺮﺍﺑﺮ ﻧﻴﺴﺖ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ
ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺩﭼﺎﺭ ﺍﻳﻦ ﺍﺷﺘﺒﺎﻩ ﻧﺸﻮﻳﺪ ،ﺍﺯ ﻗﺎﻧﻮﻥ ﺯﻳﺮ ﭘﻴﺮﻭﻱ ﮐﻨﻴﺪ» :ﻫﻤﻪ ﭼﻴﺰ ﺭﺍ ﺑﺎ ﺣﺮﻭﻑ
ﮐﻮﭼﮏ ﺑﻨﻮﻳﺴﻴﺪ ،ﻣﮕﺮ ﺍﻳﻦﮐﻪ ﺑﺮﺍﻱ ﺑﺰﺭﮒ ﻧﻮﺷﺘﻦ ﺑﺮﺧﻲ ﺍﺯ ﺣﺮﻭﻑ ﺩﻟﻴﻞ ﻗﺎﻧﻊﮐﻨﻨﺪﻩﺍﻱ
ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ«.
ﺍﻭﻟﻴﻦ ﺑﺮﻧﺎﻣﻪﺍﻱ ﮐﻪ ﻣﻲﻧﻮﻳﺴﻴﻢ ﺑﻪ ﻣﺤﺾ ﺗﻮﻟﺪ ،ﺑﻪ ﺷﻤﺎ ﺳﻼﻡ ﻣﻲﮐﻨﺪ ﻭ ﻋﺒﺎﺭﺕ
"! "Hello, my programmerﺭﺍ ﻧﻤﺎﻳﺶ ﻣﻲﺩﻫﺪ:
>#include <iostream
)(int main
; "{ std::cout << "Hello, my programmer!\n
;return 0
}
– 3ﻧﺎﻡ ﻳﮏ »ﻓﺎﻳﻞ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ« ﮐﻪ ﻣﻴﺎﻥ ﺩﻭ ﻋﻼﻣﺖ >< ﻣﺤﺼﻮﺭ ﺷﺪﻩ ﺍﺳﺖ .ﺑﻪ
ﻓﺎﻳﻞ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ »ﺳﺮﻓﺎﻳﻞ «3ﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ .ﻓﺎﻳﻞ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ ﮐﻪ ﺩﺭ ﺍﻳﻦﺟﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ
iostreamﻧﺎﻡ ﺩﺍﺭﺩ.
ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺍﺟﺰﺍﻱ ﻓﻮﻕ ،ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﻩ ﺧﻄﻲ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺍﻃﻼﻉ
ﻣﻲﺩﻫﺪ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﻣﻮﺟﻮﺩﻳﺘﻲ ﺍﺳﺖ ﮐﻪ ﺗﻌﺮﻳﻒ ﺁﻥ ﺭﺍ ﺑﺎﻳﺪ ﺩﺭ ﻓﺎﻳﻞ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ ﻣﺬﮐﻮﺭ
ﺟﺴﺘﺠﻮ ﮐﻨﺪ .ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﻮﺟﻮﺩﻳﺖ std::coutﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﮐﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺭﺍﺟﻊ
ﺑﻪ ﺁﻥ ﭼﻴﺰﻱ ﻧﻤﻲﺩﺍﻧﺪ ،ﭘﺲ ﺑﻪ ﻓﺎﻳﻞ iostreamﻣﺮﺍﺟﻌﻪ ﻣﻲﮐﻨﺪ ،ﺗﻌﺮﻳﻒ ﺁﻥ ﺭﺍ
ﺭﻭﻱ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﮐﺎﺭﺍﮐﺘﺮ \nﻧﻴﺰ ﺩﺭ ﺭﺷﺘﻪ ﻓﻮﻕ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﻭﻟﻲ ﺑﻪ
ﺟﺎﻱ ﺁﻥ ﭼﻴﺰﻱ ﭼﺎﭖ ﻧﻤﻲﺷﻮﺩ ،ﺑﻠﮑﻪ ﭼﺎﭖ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﻣﮑﺎﻥﻧﻤﺎ ﺑﻪ ﺧﻂ
ﺑﻌﺪﻱ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﭘﺮﺵ ﮐﻨﺪ .ﺑﻪ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮ ،ﮐﺎﺭﺍﮐﺘﺮ »ﺧﻂ ﺟﺪﻳﺪ« ﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ.
ﻧﻤﻮﻧﻪﻫﺎﻱ ﺩﻳﮕﺮﻱ ﺍﺯ ﺍﻳﻦ ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﺑﺎﺯ ﻫﻢ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ.
ﺩﺳﺘﻮﺭ ﺧﻂ ﺳﻮﻡ ﺑﺎ ﻋﻼﻣﺖ ﺳﻤﻴﮑﻮﻟﻦ ; ﭘﺎﻳﺎﻥ ﻳﺎﻓﺘﻪ ﺍﺳﺖ .ﺍﻳﻦ ﺩﻭﻣﻴﻦ ﻗﺎﻧﻮﻥ ﻣﻬﻢ
ﻭ ﺳﺎﺩﻩ C++ﺍﺳﺖ» :ﺣﺘﻤﺎ ﺑﺎﻳﺪ ﺩﺭ ﭘﺎﻳﺎﻥ ﻫﺮ ﺩﺳﺘﻮﺭ ،ﻋﻼﻣﺖ ﺳﻤﻴﮑﻮﻟﻦ ; ﻗﺮﺍﺭ ﺩﻫﻴﺪ« .ﺍﻳﻦ
ﻋﻼﻣﺖ ﺑﻪ ﻣﻌﻨﺎﻱ ﭘﺎﻳﺎﻥ ﺁﻥ ﺩﺳﺘﻮﺭ ﺍﺳﺖ .ﺍﮔﺮ ﺳﻤﻴﮑﻮﻟﻦ ﭘﺎﻳﺎﻥ ﻳﮏ ﺩﺳﺘﻮﺭ ﺭﺍ ﻓﺮﺍﻣﻮﺵ
ﮐﻨﻴﺪ ،ﮐﺎﻣﭙﺎﻳﻠﺮ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺷﻤﺎ ﺧﻄﺎ ﻣﻲﮔﻴﺮﺩ ﻭ ﺍﺻﻼ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺍﺟﺮﺍ ﻧﻤﻲﮐﻨﺪ.
ﺧﻂ ﭼﻬﺎﺭﻡ )ﺩﻭﻣﻴﻦ ﺩﺳﺘﻮﺭ ﺑﺮﻧﺎﻣﻪ( ﻳﻌﻨﻲ
;return 0
ﻣﻘﺪﺍﺭ 0ﺭﺍ ﺑﻪ ﺳﻴﺴﺘﻢﻋﺎﻣﻞ ﺑﺎﺯ ﻣﻲﮔﺮﺩﺍﻧﺪ ﻭ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﭘﺎﻳﺎﻥ ﻣﻲﺩﻫﺪ .ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺍﻳﻦ ﺩﺳﺘﻮﺭ
ﻧﻴﺰ ﻋﻼﻣﺖ ﺳﻤﻴﮑﻮﻟﻦ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ .ﺍﻳﻦ ﺧﻂ ﺩﺭ C++ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ،ﺍﺧﺘﻴﺎﺭﻱ ﺍﺳﺖ ﺍﻣﺎ
ﺍﮔﺮ ﺍﺯ ﮐﺎﻣﭙﺎﻳﻠﺮﻱ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﺪ ﮐﻪ ﺣﺘﻤﺎ ﺍﻳﻦ ﺧﻂ ﺭﺍ ﺍﻧﺘﻈﺎﺭ ﺩﺍﺭﺩ )ﻣﺜﻞ Visual C++
ﻳﺎ (C++ Builderﺑﺎﻳﺪ ﺩﺳﺘﻮﺭ ; return 0ﺭﺍ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺑﺪﻥۀ ﺑﺮﻧﺎﻣﻪ ﻗﺮﺍﺭ ﺩﻫﻴﺪ.
ﮐﺎﻣﭙﺎﻳﻠﺮﻫﺎﻱ ﻣﺬﮐﻮﺭ ،ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺭﺍ ﺑﻪ ﻣﻌﻨﺎﻱ ﭘﺎﻳﺎﻥ ﺗﺎﺑﻊ )( mainﺗﻠﻘﻲ ﻣﻲﮐﻨﻨﺪ.
ﺑﻪ ﻓﺎﺻﻠﻪﮔﺬﺍﺭﻱﻫﺎ ﺩﺭ ﻣﺜﺎﻝ 1‐1ﺩﻗﺖ ﮐﻨﻴﺪ .ﮐﺎﻣﭙﺎﻳﻠﺮ ﺍﻳﻦ ﻓﺎﺻﻠﻪﻫﺎﻱ ﺍﺿﺎﻓﻲ ﺭﺍ
ﻧﺎﺩﻳﺪﻩ ﻣﻲﮔﻴﺮﺩ ﻣﮕﺮ ﺟﺎﻳﻲ ﮐﻪ ﻻﺯﻡ ﺑﺎﺷﺪ ﺷﻨﺎﺳﻪﻫﺎ ﺍﺯ ﻫﻢ ﺟﺪﺍ ﺷﻮﻧﺪ .ﻳﻌﻨﻲ ﮐﺎﻣﭙﺎﻳﻠﺮ ،ﺑﺮﻧﺎﻡۀ
ﻓﻮﻕ ﺭﺍ ﺍﻳﻦﭼﻨﻴﻦ ﻣﻲﺑﻴﻨﺪ:
>#include<iostream
};Int main(){std::cout<<"Hello, my programmer!\n";return 0
ﻣﺎ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﺴﺘﻴﻢ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺑﻪ ﻫﻤﻴﻦ ﺷﮑﻞ ﺑﻨﻮﻳﺴﻴﻢ ﺍﻣﺎ ﺩﺭﮎ ﺑﺮﻧﺎﻣﻪﺍﻱ ﮐﻪ ﺑﺪﻭﻥ ﻓﺎﺻﻠﻪ
ﻧﻮﺷﺘﻪ ﻣﻲﺷﻮﺩ ﺑﺴﻴﺎﺭ ﻣﺸﮑﻞ ﺍﺳﺖ .ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻓﺎﺻﻠﻪﻫﺎﻱ ﻣﻨﺎﺳﺐ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﺧﻮﺍﻧﺪﻥ
ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺘﺎﻥ ﺭﺍﺣﺖﺗﺮ ﺑﺎﺷﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 8
ﺑﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﻣﻲﮔﻮﻳﺪ ﮐﻪ ﻋﺒﺎﺭﺕ std::ﺭﺍ ﺩﺭ ﺳﺮﺍﺳﺮ ﺑﺮﻧﺎﻣﻪ ﺩﺭ ﻧﻈﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺗﺎ
ﻣﺠﺒﻮﺭ ﻧﺒﺎﺷﻴﻢ ﺑﺮﺍﻱ ﺩﺳﺘﻮﺭﺍﺗﻲ ﻣﺜﻞ coutﺍﻳﻦ ﭘﻴﺸﻮﻧﺪ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ .ﺑﻪ ﺍﻳﻦ ﻃﺮﻳﻖ
ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺮﺍﻱ ﺩﺳﺘﻮﺭ ﺧﺮﻭﺟﻲ ﺑﻪ ﺟﺎﻱ std::coutﺍﺯ ﻋﺒﺎﺭﺕ coutﺗﻨﻬﺎ ﺍﺳﺘﻔﺎﺩﻩ
ﻧﻤﺎﻳﻴﻢ )ﮐﻪ ﺩﺭ ﺧﻂ ﭘﻨﺠﻢ ﻫﻤﻴﻦ ﮐﺎﺭ ﺭﺍ ﮐﺮﺩﻩﺍﻳﻢ( .ﺩﺭ ﻧﻬﺎﻳﺖ ﻳﮏ ﺧﻂ ﺑﻪ ﺑﺮﻧﺎﻣﻪ ﺍﺿﺎﻓﻪ
ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﺩﺭ ﻋﻮﺽ ﻣﺠﺒﻮﺭ ﻧﻴﺴﺘﻴﻢ ﻗﺒﻞ ﺍﺯ ﻫﺮ coutﻋﺒﺎﺭﺕ std::ﺭﺍ ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ.
ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺧﻮﺍﻧﺪﻥ ﻭ ﻧﻮﺷﺘﻦ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻃﻮﻻﻧﻲ ﺁﺳﺎﻥﺗﺮ ﻣﻲﺷﻮﺩ.
Stdﻳﮏ »ﻓﻀﺎﻱ ﻧﺎﻡ «1ﺍﺳﺖ .ﻓﻀﺎﻱ ﻧﺎﻡ ﻣﺤﺪﻭﺩﻩﺍﻱ ﺍﺳﺖ ﮐﻪ ﭼﻨﺪ ﻣﻮﺟﻮﺩﻳﺖ ﺩﺭ
ﺁﻥ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ .ﻣﺜﻼ ﻣﻮﺟﻮﺩﻳﺖ coutﺩﺭ ﻓﻀﺎﻱ ﻧﺎﻡ stdﺩﺭ ﺳﺮﻓﺎﻳﻞ
iostreamﺗﻌﺮﻳﻒ ﺷﺪﻩ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻓﻀﺎﻱ ﻧﺎﻡ ﻣﻲﺗﻮﺍﻧﻴﻢ ﭼﻨﺪ ﻣﻮﺟﻮﺩﻳﺖ ﺭﺍ ﺑﺎ ﻳﮏ
ﻧﺎﻡ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ ،ﻣﺸﺮﻭﻁ ﺑﺮ ﺍﻳﻦ ﮐﻪ ﻓﻀﺎﻱ ﻧﺎﻡ ﻫﺮ ﮐﺪﺍﻡ ﺭﺍ ﺫﮐﺮ ﮐﻨﻴﻢ .ﺑﺮﺍﻱ
ﺁﺷﻨﺎﻳﻲ ﺑﻴﺸﺘﺮ ﺑﺎ ﻓﻀﺎﻱ ﻧﺎﻡ ﺑﻪ ﻣﺮﺍﺟﻊ C++ﻣﺮﺍﺟﻌﻪ ﮐﻨﻴﺪ.
ﻫﻢۀ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺍﻳﻦ ﮐﺘﺎﺏ ﺑﺎ ﺩﻭ ﺧﻂ
>#include <iostream
;using namespace std
ﺷﺮﻭﻉ ﻣﻲﺷﻮﻧﺪ .ﻫﺮ ﭼﻨﺪ ﺑﺮﺍﻱ ﺍﺧﺘﺼﺎﺭ ﺍﺯ ﺍﻳﻦ ﺑﻪ ﺑﻌﺪ ﺍﻳﻦ ﺩﻭ ﺧﻂ ﺭﺍ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺫﮐﺮ
1 – Namespace
9 ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ C++ ﻓﺼﻞ اول /
ﻧﺨﻮﺍﻫﻴﻢ ﮐﺮﺩ ﺍﻣﺎ ﻓﺮﺍﻣﻮﺵ ﻧﮑﻨﻴﺪ ﮐﻪ ﺑﺮﺍﻱ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺣﺘﻤﺎ ﺩﻭ ﺧﻂ ﺑﺎﻻ ﺭﺍ ﺑﻪ ﺍﺑﺘﺪﺍﻱ
ﺑﺮﻧﺎﻣﻪﺗﺎﻥ ﺍﺿﺎﻓﻪ ﮐﻨﻴﺪ.
ﺑﻪ ﺧﻂ ﭼﻬﺎﺭﻡ ﺑﺮﻧﺎﻣﻪ ﺗﻮﺟﻪ ﮐﻨﻴﺪ:
// prints "Hello, my programmer!" :
ﺍﻳﻦ ﺧﻂ ،ﻳﮏ »ﺗﻮﺿﻴﺢ «1ﺍﺳﺖ .ﺗﻮﺿﻴﺢ ،ﻣﺘﻨﻲ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻣﻨﻈﻮﺭ ﺭﺍﻫﻨﻤﺎﻳﻲ ﻭ ﺩﺭﮎ ﺑﻬﺘﺮ
ﺑﻪ ﺑﺮﻧﺎﻣﻪ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ ﻭ ﺗﺎﺛﻴﺮﻱ ﺩﺭ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﻧﺪﺍﺭﺩ .ﮐﺎﻣﭙﺎﻳﻠﺮ ﺗﻮﺿﻴﺤﺎﺕ ﺑﺮﻧﺎﻣﻪ ﺭﺍ
ﻗﺒﻞ ﺍﺯ ﺍﺟﺮﺍ ﺣﺬﻑ ﻣﻲﮐﻨﺪ .ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺿﻴﺢ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ﺳﺎﻳﺮ ﺍﻓﺮﺍﺩ ﮐﺪ ﺑﺮﻧﺎﻡۀ ﺷﻤﺎ
ﺭﺍ ﺭﺍﺣﺖﺗﺮ ﺩﺭﮎ ﮐﻨﻨﺪ .ﻣﺎ ﻫﻢ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺍﻳﻦ ﮐﺘﺎﺏ ﺑﺮﺍﻱ ﺭﺍﻫﻨﻤﺎﻳﻲ ﺷﻤﺎ ﺗﻮﺿﻴﺤﺎﺗﻲ
ﺍﺿﺎﻓﻪ ﮐﺮﺩﻩﺍﻳﻢ .ﺑﻪ ﺩﻭ ﺻﻮﺭﺕ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ C++ﺗﻮﺿﻴﺤﺎﺕ ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ:
– 1ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﻭ ﻋﻼﻣﺖ ﺍﺳﻠﺶ : //ﻫﺮ ﻣﺘﻨﻲ ﮐﻪ ﺑﻌﺪ ﺍﺯ ﺩﻭ ﻋﻼﻣﺖ ﺍﺳﻠﺶ
ﺑﻴﺎﻳﺪ ﺗﺎ ﭘﺎﻳﺎﻥ ﻫﻤﺎﻥ ﺳﻄﺮ ﻳﮏ ﺗﻮﺿﻴﺢ ﺗﻠﻘﻲ ﻣﻲﺷﻮﺩ.
– 2ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺣﺎﻟﺖ : Cﻫﺮ ﻣﺘﻨﻲ ﮐﻪ ﺑﺎ ﻋﻼﻣﺖ * /ﺷﺮﻭﻉ ﺷﻮﺩ ﻭ ﺑﺎ ﻋﻼﻣﺖ
*/ﭘﺎﻳﺎﻥ ﻳﺎﺑﺪ ﻳﮏ ﺗﻮﺿﻴﺢ ﺗﻠﻘﻲ ﻣﻲﺷﻮﺩ .ﺗﻮﺿﻴﺢ ﺣﺎﻟﺖ Cﺩﺭ ﺯﺑﺎﻥ Cﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻓﺘﻪ ﮐﻪ
ﺑﺮﺍﻱ ﺣﻔﻆ ﺳﺎﺯﮔﺎﺭﻱ ﺩﺭ C++ﻫﻢ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ.
ﭘﺲ ﺗﻮﺿﻴﺢ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ ﺑﻪ ﺍﻳﻦ ﺷﮑﻞ ﻫﻢ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻨﻮﻳﺴﻴﻢ:
/* prints "Hello, my programmer!" */
ﺑﻪ ﻓﺮﻕ ﺑﻴﻦ ﺍﻳﻦ ﺩﻭ ﺗﻮﺿﻴﺢ ﺗﻮﺟﻪ ﮐﻨﻴﺪ :ﺩﺭ ﺣﺎﻟﺖ ﺍﻭﻝ ،ﻣﺘﻨﻲ ﮐﻪ ﺑﻌﺪ ﺍﺯ //ﺗﺎ ﺁﺧﺮ
ﺳﻄﺮ ﺁﻣﺪﻩ ﺗﻮﺿﻴﺢ ﺗﻠﻘﻲ ﻣﻲﺷﻮﺩ ﻭ ﺑﺎ ﺷﺮﻭﻉ ﺧﻂ ﺑﻌﺪﻱ ،ﺗﻮﺿﻴﺢ ﻧﻴﺰ ﺧﻮﺩ ﺑﻪ ﺧﻮﺩ ﺑﻪ ﭘﺎﻳﺎﻥ
ﻣﻲﺭﺳﺪ ﻭﻟﻲ ﺩﺭ ﺣﺎﻟﺖ Cﺗﻮﺿﻴﺢ ﺑﺎ ﻋﻼﻣﺖ * /ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ﻭ ﻫﻤﭽﻨﺎﻥ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ
ﺗﺎ ﺑﻪ ﻋﻼﻣﺖ */ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ .ﻳﻌﻨﻲ ﺗﻮﺿﻴﺢ ﺣﺎﻟﺖ Cﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪ ﺧﻂ ﺍﺩﺍﻣﻪ ﺩﺍﺷﺘﻪ
ﺑﺎﺷﺪ ﻭﻟﻲ ﺗﻮﺿﻴﺢ ﺑﺎ //ﻓﻘﻂ ﻳﮏ ﺧﻂ ﺍﺳﺖ ﻭ ﺑﺮﺍﻱ ﺍﺩﺍﻡۀ ﺗﻮﺿﻴﺢ ﺩﺭ ﺧﻂ ﺑﻌﺪﻱ ﺑﺎﻳﺪ
ﺩﻭﺑﺎﺭﻩ ﺩﺭ ﺍﺑﺘﺪﺍﻱ ﺧﻂ ﻋﻼﻣﺖ //ﺭﺍ ﻗﺮﺍﺭ ﺩﺍﺩ.
1 – Comment
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 10
1 – 5ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ
ﻋﻼﻣﺖ << ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ ﺩﺭ C++ﻧﺎﻡ ﺩﺍﺭﺩ )ﺑﻪ ﺁﻥ ﻋﻤﻠﮕﺮ ﺩﺭﺝ ﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ(.
ﻳﮏ »ﻋﻤﻠﮕﺮ «1ﭼﻴﺰﻱ ﺍﺳﺖ ﮐﻪ ﻋﻤﻠﻴﺎﺗﻲ ﺭﺍ ﺭﻭﻱ ﻳﮏ ﻳﺎ ﭼﻨﺪ ﺷﻲ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ .ﻋﻤﻠﮕﺮ
ﺧﺮﻭﺟﻲ ،ﻣﻘﺎﺩﻳﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﺳﻤﺖ ﺭﺍﺳﺘﺶ ﺭﺍ ﺑﻪ ﺧﺮﻭﺟﻲ ﺳﻤﺖ ﭼﭙﺶ ﻣﻲﻓﺮﺳﺘﺪ.
ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺩﺳﺘﻮﺭ
; cout << 66
ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ << ﭼﻬﺎﺭ ﺑﺎﺭ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﻭ ﭼﻬﺎﺭ ﻋﻨﺼﺮ ﺭﺍ ﺑﻪ
coutﻓﺮﺳﺘﺎﺩﻩ ﺗﺎ ﺭﻭﻱ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﭼﺎﭖ ﺷﻮﻧﺪ .ﺳﻪ ﺗﺎﻱ ﺍﻭﻟﻲ ﻳﻌﻨﻲ ""Hello, m
ﻭ " "y prograﻭ "! "mmerﺳﻪ ﺭﺷﺘﻪﺍﻧﺪ ﮐﻪ ﺑﻪ ﻳﮑﺪﻳﮕﺮ ﭘﻴﻮﻧﺪ ﻣﻲﺧﻮﺭﻧﺪ ﺗﺎ ﻋﺒﺎﺭﺕ
"! "Hello, my programmerﺩﺭ ﺧﺮﻭﺟﻲ ﺗﺸﮑﻴﻞ ﺷﻮﺩ .ﻋﺒﺎﺭﺕ ﭼﻬﺎﺭﻡ ﻳﻌﻨﻲ
endlﻫﻤﺎﻥ ﮐﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ ' '\nﺭﺍ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ .ﻳﻌﻨﻲ ﻣﮑﺎﻥﻧﻤﺎ ﺭﺍ ﺑﻪ ﺧﻂ ﺑﻌﺪﻱ ﺭﻭﻱ
ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﻣﻨﺘﻘﻞ ﻣﻲﮐﻨﺪ.
1 – Operator
11 ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ C++ ﻓﺼﻞ اول /
1 – 6ﻟﻴﺘﺮﺍﻝﻫﺎ ﻭ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ
ﻳﮏ »ﻟﻴﺘﺮﺍﻝ «1ﺭﺷﺘﻪﺍﻱ ﺍﺯ ﺣﺮﻭﻑ ،ﺍﺭﻗﺎﻡ ﻳﺎ ﻋﻼﻳﻢ ﭼﺎﭘﻲ ﺍﺳﺖ ﮐﻪ ﻣﻴﺎﻥ ﺩﻭ ﻋﻼﻣﺖ
ﻧﻘﻞ ﻗﻮﻝ " " ﻣﺤﺼﻮﺭ ﺷﺪﻩ ﺑﺎﺷﺪ .ﺩﺭ ﻣﺜﺎﻝ 1‐ 3ﺳﻪ ﻋﻨﺼﺮ " "Hello, mﻭ "y
" prograﻭ "! "mmerﻟﻴﺘﺮﺍﻝ ﻫﺴﺘﻨﺪ .ﻟﻴﺘﺮﺍﻝ ﻣﻲﺗﻮﺍﻧﺪ ﺗﻬﻲ ﺑﺎﺷﺪ "" :ﻭ ﻳﺎ ﻣﻲﺗﻮﺍﻧﺪ
ﻓﻘﻂ ﻳﮏ ﻓﺎﺻﻞۀ ﺧﺎﻟﻲ ﺑﺎﺷﺪ " " ﻭ ﻳﺎ ﻓﻘﻂ ﻳﮏ ﺣﺮﻑ ﺑﺎﺷﺪ."W" :
ﻳﮏ »ﮐﺎﺭﺍﮐﺘﺮ «2ﻳﮏ ﺣﺮﻑ ،ﺭﻗﻢ ﻳﺎ ﻋﻼﻣﺖ ﻗﺎﺑﻞ ﭼﺎﭖ ﺍﺳﺖ ﮐﻪ ﻣﻴﺎﻥ ﺩﻭ ﻧﺸﺎﻥۀ
' ' ﻣﺤﺼﻮﺭ ﺷﺪﻩ ﺑﺎﺷﺪ .ﭘﺲ ' 'wﻭ '!' ﻭ ' '1ﻫﺮ ﮐﺪﺍﻡ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺳﺖ .ﻫﺮ
ﮐﺎﺭﺍﮐﺘﺮ ﻳﮏ ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ ﻣﻲﮐﻨﺪ .ﺭﺍﻳﺎﻧﻪﻫﺎ 128ﮐﺎﺭﺍﮐﺘﺮ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺭﺍ
ﻣﻲﺷﻨﺎﺳﻨﺪ؛ ﺣﺮﻭﻑ ﺍﻟﻔﺒﺎﻱ ﺍﻧﮕﻠﻴﺴﻲ ﮐﻮﭼﮏ ﻭ ﺑﺰﺭﮒ ﻭ ﺍﻋﺪﺍﺩ ﺻﻔﺮ ﺗﺎ 9ﻭ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ
ﮐﻨﺘﺮﻟﻲ ﻭ ﻭﻳﺮﺍﻳﺸﻲ .ﺭﺍﻳﺎﻧﻪﻫﺎ ﺑﻪ ﻫﺮ ﮐﺎﺭﺍﮐﺘﺮ ﻳﮏ ﻋﺪﺩ ﻳﮏ ﺑﺎﻳﺘﻲ ﺗﺨﺼﻴﺺ ﻣﻲﺩﻫﻨﺪ ﺗﺎ ﺑﻪ
ﻭﺳﻴﻞۀ ﺁﻥ ﻋﺪﺩ ،ﮐﺎﺭﺍﮐﺘﺮ ﻣﻮﺭﺩ ﻧﻈﺮ ﺭﺍ ﺷﻨﺎﺳﺎﻳﻲ ﻳﺎ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﻨﺪ .ﺍﻳﻦ 128ﮐﺎﺭﺍﮐﺘﺮ ﻭ
ﺍﻋﺪﺍﺩ ﺗﺨﺼﻴﺼﻲ ﻫﺮ ﻳﮏ ﺩﺭ ﺟﺪﻭﻟﻲ ﺑﻪ ﻧﺎﻡ ﺟﺪﻭﻝ ) ASCIIﺑﺨﻮﺍﻧﻴﺪ ﺍﹶﺳﮑﻲ( ﻗﺮﺍﺭ
ﻣﻲﮔﻴﺮﻧﺪ .ﺍﻳﻦ ﺟﺪﻭﻝ ﺩﺭ ﺿﻤﻴﻢۀ ﮐﺘﺎﺏ ﺁﻣﺪﻩ ﺍﺳﺖ .ﺑﺎ ﺩﻗﺖ ﺩﺭ ﺍﻳﻦ ﺟﺪﻭﻝ ﻣﻲﺑﻴﻨﻴﻢ ﮐﻪ
ﺑﻌﻀﻲ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺩﻭ ﻋﻀﻮﻱ ﻫﺴﺘﻨﺪ ،ﻣﺜﻞ ﮐﺎﺭﺍﮐﺘﺮ ' '\nﮐﻪ ﻗﺒﻼ ﺩﻳﺪﻳﻢ .ﮔﺮﭼﻪ ﺍﻳﻦ
ﮐﺎﺭﺍﮐﺘﺮ ﺍﺯ ﺩﻭ ﻋﻀﻮ nﻭ \ ﺗﺸﮑﻴﻞ ﺷﺪﻩ ﺍﻣﺎ ﺭﺍﻳﺎﻧﻪ ﺁﻥ ﺩﻭ ﺑﺎ ﻫﻢ ﺭﺍ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻓﺮﺽ
ﻣﻲﮐﻨﺪ .ﺑﻴﺸﺘﺮ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻳﻲ ﮐﻪ ﺩﻭ ﻋﻀﻮﻱ ﻫﺴﺘﻨﺪ ﺑﺮﺍﻱ ﮐﻨﺘﺮﻝ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ﻣﺜﻞ ﮐﺎﺭﺍﮐﺘﺮ
' '\nﮐﻪ ﻣﮑﺎﻥﻧﻤﺎ ﺭﺍ ﺑﻪ ﺧﻂ ﺟﺪﻳﺪ ﻣﻲﺑﺮﺩ .ﺭﺍﺟﻊ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺩﺭ ﻓﺼﻞ ﺑﻌﺪﻱ ﺷﺮﺡ
ﺑﻴﺸﺘﺮﻱ ﺧﻮﺍﻫﻴﺪ ﺩﻳﺪ.
ﺑﻪ ﺗﻔﺎﻭﺕ ﺳﻪ ﻣﻮﺟﻮﺩﻳﺖ »ﻋﺪﺩ« ﻭ »ﮐﺎﺭﺍﮐﺘﺮ« ﻭ »ﻟﻴﺘﺮﺍﻝ ﺭﺷﺘﻪﺍﻱ« ﺩﻗﺖ ﮐﻨﻴﺪ 6 :ﻳﮏ
ﻋﺪﺩ ﺍﺳﺖ '6' ،ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺳﺖ ﻭ " "6ﻳﮏ ﻟﻴﺘﺮﺍﻝ ﺭﺷﺘﻪﺍﻱ ﺍﺳﺖ.
ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﻣﺎﻧﻨﺪ ﻟﻴﺘﺮﺍﻝﻫﺎﻱ ﺭﺷﺘﻪﺍﻱ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﺧﺮﻭﺟﻲ ﻧﻤﺎﻳﺶ ﺩﺍﺩ .ﺑﻪ ﻣﺜﺎﻝ
ﺑﻌﺪﻱ ﺗﻮﺟﻪ ﻧﻤﺎﻳﻴﺪ.
)(int main
{ // prints "Hello, my programmer!":
;'cout << "Hello, " << 'm' << "y programmer" << '!' << '\n
;return 0
}
ﻣﺜﺎﻝ ﺑﺎﻻ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻟﻴﺘﺮﺍﻝ ﺭﺷﺘﻪﺍﻱ ﭘﻴﻮﻧﺪ ﺩﺍﺩ ﻭ
ﺧﺮﻭﺟﻲ ﺗﺮﮐﻴﺒﻲ ﺩﺭﺳﺖ ﮐﺮﺩ.
ﻭﻗﺘﻲ ﻣﺜﺎﻝ ﺑﺎﻻ ﺭﺍ ﺍﺟﺮﺍ ﮐﻨﻴﻢ ،ﺧﺮﻭﺟﻲ ﺑﻪ ﺷﮑﻞ Today is Feb 5 2005
ﺭﻭﻱ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﭼﺎﭖ ﻣﻲﮔﺮﺩﺩ .ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﻳﮏ »ﮐﺎﺭﺍﮐﺘﺮ ﺟﺎﻱ ﺧﺎﻟﻲ« ' ' ﺑﻴﻦ 5
ﻭ 2005ﮔﻨﺠﺎﻧﺪﻩﺍﻳﻢ ﺗﺎ ﺍﻳﻦ ﺩﻭ ﻋﺪﺩ ﺑﺎ ﻓﺎﺻﻠﻪ ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﭼﺎﭖ ﺷﻮﻧﺪ ﻭ ﺑﻪ ﻫﻢ ﭘﻴﻮﻧﺪ
ﻧﺨﻮﺭﻧﺪ.
1 – Variable
13 ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ C++ ﻓﺼﻞ اول /
ﺩﺭ ﺁﻥ ﺁﺩﺭﺱ ﭼﻪ ﻧﻮﻉ ﺩﺍﺩﻩﺍﻱ ﻣﻲﺗﻮﺍﻧﺪ ﺫﺧﻴﺮﻩ ﺷﻮﺩ ﻭ ﭼﻪ ﺍﻋﻤﺎﻟﻲ ﺭﻭﻱ ﺁﻥ ﻣﻲﺗﻮﺍﻥ ﺍﻧﺠﺎﻡ
ﺩﺍﺩ .ﻣﻘﺪﺍﺭ ﻧﻴﺰ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ ﮐﻪ ﺩﺭ ﺁﻥ ﻣﺤﻞ ﺍﺯ ﺣﺎﻓﻈﻪ ﭼﻪ ﻣﻘﺪﺍﺭﻱ ﺫﺧﻴﺮﻩ ﺷﺪﻩ ﺍﺳﺖ.
ﺩﺭ C++ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺑﺘﻮﺍﻧﻴﻢ ﺍﺯ ﻣﺘﻐﻴﺮﻱ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ ،ﺑﺎﻳﺪ ﺁﻥ ﺭﺍ ﺍﻋﻼﻥ 1ﻧﻤﺎﻳﻴﻢ.
ﻧﺤﻮ ﺍﻋﻼﻥ ﻳﮏ ﻣﺘﻐﻴﺮ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
type name initializer
ﻋﺒﺎﺭﺕ typeﻧﻮﻉ ﻣﺘﻐﻴﺮ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ .ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﺑﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺍﻃﻼﻉ ﻣﻲﺩﻫﺪ
ﮐﻪ ﺍﻳﻦ ﻣﺘﻐﻴﺮ ﭼﻪ ﻣﻘﺎﺩﻳﺮﻱ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﻭ ﭼﻪ ﺍﻋﻤﺎﻟﻲ ﻣﻲﺗﻮﺍﻥ ﺭﻭﻱ ﺁﻥ ﺍﻧﺠﺎﻡ ﺩﺍﺩ.
ﻣﺜﻼ ﻧﻮﻉ intﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ﻧﻮﻉ char
ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ .ﺍﻧﻮﺍﻉ ﺍﺻﻠﻲ ﺩﺭ C++ﺭﺍ ﺩﺭ ﻓﺼﻞ
ﺑﻌﺪﻱ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﻴﻢ.
ﻋﺒﺎﺭﺕ nameﻧﺎﻡ ﻣﺘﻐﻴﺮ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﺍﻳﻦ ﻧﺎﻡ ﺣﺪﺍﮐﺜﺮ ﻣﻲﺗﻮﺍﻧﺪ 31ﮐﺎﺭﺍﮐﺘﺮ
ﺑﺎﺷﺪ ،ﻧﺒﺎﻳﺪ ﺑﺎ ﻋﺪﺩ ﺷﺮﻭﻉ ﺷﻮﺩ ،ﻋﻼﻳﻢ ﺭﻳﺎﺿﻲ ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﺪ ﻭ ﻫﻤﭽﻨﻴﻦ »ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ« ﻧﻴﺰ
ﻧﺒﺎﺷﺪ» .ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ« ﮐﻠﻤﻪﺍﻱ ﺍﺳﺖ ﮐﻪ ﺩﺭ C++ﺑﺮﺍﻱ ﮐﺎﺭﻫﺎﻱ ﺧﺎﺻﻲ ﻣﻨﻈﻮﺭ ﺷﺪﻩ ﺍﺳﺖ.
63 C++ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ ﺩﺍﺭﺩ ﮐﻪ ﺩﺭ ﺿﻤﻴﻤﻪ ﺁﻣﺪﻩ ﺍﺳﺖ .ﺑﻬﺘﺮ ﺍﺳﺖ ﻧﺎﻡ ﻳﮏ ﻣﺘﻐﻴﺮ ﺑﺎ ﻳﮏ
ﺣﺮﻑ ﺷﺮﻭﻉ ﺷﻮﺩ.
ﻋﺒﺎﺭﺕ initializerﻋﺒﺎﺭﺕ »ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ« ﻧﺎﻡ ﺩﺍﺭﺩ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ
ﻋﺒﺎﺭﺕ ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻴﻪﺍﻱ ﺩﺭ ﻣﺘﻐﻴﺮ ﻣﻮﺭﺩ ﻧﻈﺮ ﻗﺮﺍﺭ ﺩﺍﺩ.
ﺩﺳﺘﻮﺭ ﺯﻳﺮ ﺗﻌﺮﻳﻒ ﻳﮏ ﻣﺘﻐﻴﺮ ﺻﺤﻴﺢ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ:
;int n = 50
ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ nﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﻭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻴﻪ 50ﺭﺍ ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ
ﻣﻲﺩﻫﺪ .ﺍﻳﻦ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ intﺍﺳﺖ ،ﻳﻌﻨﻲ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﮐﻨﺪ.
ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺩﺭ ﻳﮏ ﻣﺘﻐﻴﺮ ﻗﺮﺍﺭ ﺩﻫﻴﻢ ،ﺍﺯ ﻋﻤﻠﮕﺮ ﺍﻧﺘﺴﺎﺏ » = « ﺍﺳﺘﻔﺎﺩﻩ
ﻣﻲﮐﻨﻴﻢ .ﻣﺜﻼ ﺩﺳﺘﻮﺭ ; n=50ﻣﻘﺪﺍﺭ 50ﺭﺍ ﺩﺭ ﻣﺘﻐﻴﺮ nﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ.
1 – Declaration
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 14
ﺑﻪ ﻃﻮﺭ ﻏﻴﺮ ﻣﺴﺘﻘﻴﻢ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺑﻪ ﻳﮏ ﻣﺘﻐﻴﺮ ﺗﺨﺼﻴﺺ ﺩﻫﻴﻢ .ﺑﺮﺍﻱ
ﻣﺜﺎﻝ ﺍﮔﺮ ﻣﺘﻐﻴﺮ mﻣﻘﺪﺍﺭ 45ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﺩﺳﺘﻮﺭ ; n=mﺳﺒﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ﻣﻘﺪﺍﺭ n
ﺑﺮﺍﺑﺮ ﺑﺎ ﻣﻘﺪﺍﺭ mﺷﻮﺩ؛ ﻳﻌﻨﻲ ﻣﻘﺪﺍﺭ nﺑﺮﺍﺑﺮ ﺑﺎ 45ﺷﻮﺩ.
ﻫﻤﭽﻨﻴﻦ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻳﮏ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﻪ ﻃﻮﺭ ﻫﻢﺯﻣﺎﻥ ﺩﺭ ﭼﻨﺪ ﻣﺘﻐﻴﺮ ﺍﺯ ﻳﮏ ﻧﻮﻉ ﻗﺮﺍﺭ
ﺩﻫﻴﻢ .ﺩﺳﺘﻮﺭ ; n=m=k=45ﻣﻘﺪﺍﺭ 45ﺭﺍ ﺍﺑﺘﺪﺍ ﺩﺭ kﻭ ﺳﭙﺲ ﺩﺭ mﻭ ﺳﺮﺍﻧﺠﺎﻡ ﺩﺭ n
ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ .ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﻫﺮ ﺳﻪ ﻣﺘﻐﻴﺮ ﻓﻮﻕ ﻣﻘﺪﺍﺭ 45ﺧﻮﺍﻫﻨﺪ ﺩﺍﺷﺖ.
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺘﻐﻴﺮ mﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ intﻭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ 45ﺗﻌﺮﻳﻒ ﺷﺪﻩ .ﺳﭙﺲ ﻣﺘﻐﻴﺮ
nﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ intﻭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ 55ﺗﻌﺮﻳﻒ ﮔﺸﺘﻪ ﺍﺳﺖ .ﺳﺮﺍﻧﺠﺎﻡ ﻣﻘﺎﺩﻳﺮ ﺍﻳﻦ ﺩﻭ
ﻣﺘﻐﻴﺮ ﺑﺎ ﺩﺳﺘﻮﺭ coutﺭﻭﻱ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﺷﺪﻩ ﺍﺳﺖ.
ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﺘﻐﻴﺮﻫﺎ ﺭﺍ ﻫﻨﮕﺎﻡ ﺗﻌﺮﻳﻒ ،ﺑﺪﻭﻥ ﻣﻘﺪﺍﺭ ﺭﻫﺎ ﮐﻨﻴﻢ ﻭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺭﺍ ﺑﻪ ﺩﺭﻭﻥ
ﺑﺮﻧﺎﻣﻪ ﻣﻮﮐﻮﻝ ﻧﻤﺎﻳﻴﻢ .ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ:
ﺩﺭ ﺧﻂ ﺳﻮﻡ ﻭ ﭼﻬﺎﺭﻡ ،ﻣﺘﻐﻴﺮﻫﺎﻱ mﻭ nﺗﻌﺮﻳﻒ ﺷﺪﻩﺍﻧﺪ ﺍﻣﺎ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩﺍﻧﺪ .ﺩﺭ ﺧﻂ
ﭘﻨﺠﻢ ﻣﻘﺪﺍﺭ 45ﺩﺭ ﻣﺘﻐﻴﺮ mﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ .ﺩﺭ ﺧﻂ ﺷﺸﻢ ﻧﻴﺰ ﻣﻘﺪﺍﺭ m+10ﻳﻌﻨﻲ
45+10ﮐﻪ ﺑﺮﺍﺑﺮ ﺑﺎ 50ﺍﺳﺖ ﺩﺭ nﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ .ﭘﺲ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺩﻭ ﻣﺘﻐﻴﺮ
ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﺪﻧﺪ ،ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺩﺳﺘﻮﺭ coutﺁﻥﻫﺎ ﺭﺍ ﭼﺎﭖ ﮐﻨﻴﻢ.
ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﻣﻲﺗﻮﺍﻧﺴﺘﻴﻢ ﻣﺘﻐﻴﺮﻫﺎﻱ mﻭ nﺭﺍ ﺭﻭﻱ ﻳﮏ ﺧﻂ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ:
;int m,n
ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﻫﺮ ﺩﻭ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ intﺗﻌﺮﻳﻒ ﻣﻲﺷﻮﻧﺪ ﻭ ﻫﻴﭻ ﮐﺪﺍﻡ ﻣﻘﺪﺍﺭﺩﻫﻲ
ﻧﻤﻲﺷﻮﻧﺪ .ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ mﻭ nﺑﺎ ﻳﮏ ﻋﻼﻣﺖ ﮐﺎﻣﺎ ,ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﺟﺪﺍ ﺷﺪﻩﺍﻧﺪ .ﻟﺬﺍ
ﻣﻲﺗﻮﺍﻧﻴﻢ ﭼﻨﺪ ﻣﺘﻐﻴﺮ ﺭﺍ ﺭﻭﻱ ﻳﮏ ﺳﻄﺮ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﺑﻪ ﺷﺮﻃﻲ ﮐﻪ ﻫﻤﻪ ﺍﺯ ﻳﮏ ﻧﻮﻉ ﺑﺎﺷﻨﺪ.
1 – Initializing
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 16
;return 0
}
x = ?? and y = 45
ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﻣﺘﻐﻴﺮ xﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﻣﺎ ﺩﺭ ﺳﺮﺍﺳﺮ ﺑﺮﻧﺎﻣﻪ ﻫﻴﭻ ﻣﻘﺪﺍﺭﻱ ﺩﺭ ﺁﻥ
ﮔﺬﺍﺷﺘﻪ ﻧﺸﺪﻩ ﺍﺳﺖ .ﺍﮔﺮ ﺳﻌﻲ ﮐﻨﻴﻢ ﭼﻨﻴﻦ ﻣﺘﻐﻴﺮﻱ ﺭﺍ ﭼﺎﭖ ﮐﻨﻴﻢ ﺑﺎ ﻧﺘﺎﻳﺞ ﻏﻴﺮﻣﻨﺘﻈﺮﻩﺍﻱ
ﻣﻮﺍﺟﻪ ﺧﻮﺍﻫﻴﻢ ﺷﺪ .ﮐﺎﻣﭙﺎﻳﻠﺮﻱ ﮐﻪ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ ﺍﺟﺮﺍ ﮐﺮﺩﻩ ،ﻣﻘﺪﺍﺭ xﺭﺍ ?? ﭼﺎﭖ ﻧﻤﻮﺩﻩ
ﺍﺳﺖ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﻲ ﮐﻪ ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ xﺷﻨﺎﺧﺘﻪ ﺷﺪﻩ ﻧﻴﺴﺖ .ﻳﮏ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺩﻳﮕﺮ ﻣﻤﮑﻦ ﺍﺳﺖ
ﺧﺮﻭﺟﻲ ﺯﻳﺮ ﺭﺍ ﺑﺪﻫﺪ:
x = 7091260 and y = 45
ﺑﺎ ﻭﺟﻮﺩ ﺍﻳﻦ ﮐﻪ ﺑﻪ xﻫﻴﭻ ﻣﻘﺪﺍﺭﻱ ﺗﺨﺼﻴﺺ ﻧﺪﺍﺩﻩﺍﻳﻢ ،ﺩﺭ ﺧﺮﻭﺟﻲ ﻣﻘﺪﺍﺭ
7091260ﭼﺎﭖ ﺷﺪﻩ ﺍﺳﺖ .ﺑﻪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ »ﺯﺑﺎﻟﻪ «1ﻣﻲﮔﻮﻳﻨﺪ )ﻳﻌﻨﻲ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﻗﺒﻼ ﺩﺭ
ﺁﻥ ﻗﺴﻤﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺑﻮﺩﻩ ﻭ ﺳﭙﺲ ﺑﺪﻭﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺭﻫﺎ ﺷﺪﻩ ﺍﺳﺖ(.
ﺩﺭﺩﺳﺮ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ ﻭﻗﺘﻲ ﺑﺰﺭﮒﺗﺮ ﻣﻲﺷﻮﺩ ﮐﻪ ﺳﻌﻲ ﮐﻨﻴﻢ ﻣﺘﻐﻴﺮ
ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ ﺭﺍ ﺩﺭ ﻳﮏ ﻣﺤﺎﺳﺒﻪ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ .ﻣﺜﻼ ﺍﮔﺮ xﺭﺍ ﮐﻪ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ ﺩﺭ
ﻋﺒﺎﺭﺕ ; y = x + 5ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ ،ﺣﺎﺻﻞ yﻏﻴﺮ ﻗﺎﺑﻞ ﭘﻴﺶﺑﻴﻨﻲ ﺧﻮﺍﻫﺪ ﺑﻮﺩ .ﺑﺮﺍﻱ
ﺍﺟﺘﻨﺎﺏ ﺍﺯ ﭼﻨﻴﻦ ﻣﺸﮑﻼﺗﻲ ﻋﺎﻗﻼﻧﻪ ﺍﺳﺖ ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎ ﺭﺍ ﻫﻤﻴﺸﻪ ﻫﻨﮕﺎﻡ ﺗﻌﺮﻳﻒ ،ﻣﻘﺪﺍﺭﺩﻫﻲ
ﮐﻨﻴﻢ.
1 – 9ﺛﺎﺑﺖﻫﺎ
ﺩﺭ ﺑﻌﻀﻲ ﺍﺯ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺍﺯ ﻣﺘﻐﻴﺮﻱ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﻓﻘﻂ ﻳﮏ ﺑﺎﺭ ﻻﺯﻡ ﺍﺳﺖ ﺁﻥ ﺭﺍ
ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﻨﻴﻢ ﻭ ﺳﭙﺲ ﻣﻘﺪﺍﺭ ﺁﻥ ﻣﺘﻐﻴﺮ ﺩﺭ ﺳﺮﺍﺳﺮ ﺑﺮﻧﺎﻣﻪ ﺑﺪﻭﻥ ﺗﻐﻴﻴﺮ ﺑﺎﻗﻲ ﻣﻲﻣﺎﻧﺪ .ﻣﺜﻼ
ﺩﺭ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﻣﺤﺎﺳﺒﺎﺕ ﺭﻳﺎﺿﻲ ،ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ PIﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﻴﻢ ﻭ ﺁﻥ ﺭﺍ ﺑﺎ 3.14
ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﮐﻨﻴﻢ ﻭ ﻣﻲﺧﻮﺍﻫﻴﻢ ﮐﻪ ﻣﻘﺪﺍﺭ ﺍﻳﻦ ﻣﺘﻐﻴﺮ ﺩﺭ ﺳﺮﺍﺳﺮ ﺑﺮﻧﺎﻣﻪ ﺛﺎﺑﺖ ﺑﻤﺎﻧﺪ .ﺩﺭ
ﭼﻨﻴﻦ ﺣﺎﻻﺗﻲ ﺍﺯ »ﺛﺎﺑﺖﻫﺎ «2ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ .ﻳﮏ ﺛﺎﺑﺖ ،ﻳﮏ ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﺍﺳﺖ ﮐﻪ ﻓﻘﻂ ﻳﮏ
ﺑﺎﺭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﺗﻐﻴﻴﺮ ﺩﺍﺩﻥ ﻣﻘﺪﺍﺭ ﺁﻥ ﺩﺭ ﺍﺩﺍﻡۀ ﺑﺮﻧﺎﻣﻪ ﻣﻤﮑﻦ ﻧﻴﺴﺖ.
ﺗﻌﺮﻳﻒ ﺛﺎﺑﺖﻫﺎ ﻣﺎﻧﻨﺪ ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮﻫﺎﺳﺖ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ const
ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﺗﻌﺮﻳﻒ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ .ﭘﺲ ﺩﺳﺘﻮﺭ; int k=3ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ kﻭ ﺑﺎ ﻣﻘﺪﺍﺭ
ﺍﻭﻟﻲۀ 3ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﺩﺭ ﺍﺩﺍﻡۀ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭ ﺁﻥ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﺍﺩ ﻭﻟﻲ ﺩﺳﺘﻮﺭ
;const int k=3
ﺛﺎﺑﺘﻲ ﺑﻪ ﻧﺎﻡ kﻭ ﺑﺎ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ 3ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺩﺭ ﺍﺩﺍﻡۀ
ﺑﺮﻧﺎﻣﻪ ﺗﻐﻴﻴﺮ ﺩﺍﺩ.
ﺛﺎﺑﺖﻫﺎ ﺭﺍ ﺑﺎﻳﺪ ﻫﻨﮕﺎﻡ ﺗﻌﺮﻳﻒ ،ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﻧﻤﻮﺩ .ﻳﮏ ﺛﺎﺑﺖ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺯ ﻧﻮﻉ
ﮐﺎﺭﺍﮐﺘﺮﻱ ،ﺻﺤﻴﺢ ،ﺍﻋﺸﺎﺭﻱ ﻭ ...ﺑﺎﺷﺪ .ﻣﺜﺎﻝ ﺯﻳﺮ ﭼﻨﺪ ﻧﻮﻉ ﺛﺎﺑﺖ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻧﺎﻡ ﺛﺎﺑﺖﻫﺎ ﺭﺍ ﺑﺎ ﺣﺮﻭﻑ ﺍﻧﮕﻠﻴﺴﻲ ﺑﺰﺭﮒ ﻧﻮﺷﺘﻪﺍﻳﻢ .ﻣﻌﻤﻮﻻ ﺩﺭ
ﺑﺮﻧﺎﻣﻪﻫﺎ ﺑﺮﺍﻱ ﻧﺸﺎﻥ ﺩﺍﺩﻥ ﺛﺎﺑﺖﻫﺎ ﺍﺯ ﺣﺮﻭﻑ ﺑﺰﺭﮒ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻨﺪ .ﻫﺮ ﭼﻨﺪ ﺍﻳﻦ ﮐﺎﺭ
ﺍﺟﺒﺎﺭﻱ ﻧﻴﺴﺖ ،ﺍﻣﺎ ﺑﺎ ﺭﻋﺎﻳﺖ ﺍﻳﻦ ﻗﺮﺍﺭﺩﺍﺩ ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺛﺎﺑﺖﻫﺎ ﺭﺍ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎ ﺗﻤﻴﺰ
ﺩﻫﻴﻢ.
1 – 10ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ
ﺩﺭ ﺑﻴﺸﺘﺮ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺍﺯ ﮐﺎﺭﺑﺮ ﺧﻮﺍﺳﺘﻪ ﻣﻲﺷﻮﺩ ﺗﺎ ﻣﻘﺎﺩﻳﺮﻱ ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﺪ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ
ﺑﺘﻮﺍﻧﻴﻢ ﻫﻨﮕﺎﻡ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﻣﻘﺎﺩﻳﺮﻱ ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﻴﻢ ﺍﺯ ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ >> ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 18
ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ ﻣﺎﻧﻨﺪ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ ﺍﺳﺖ ﻭ ﺑﻪ ﻫﻤﺎﻥ ﺳﺎﺩﮔﻲ ﮐﺎﺭ ﻣﻲﮐﻨﺪ .ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﺩﺳﺘﻮﺭ ﻭﺭﻭﺩﻱ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
;cin >> variable
ﺩﺭ ﺍﻳﻦ ﺷﮑﻞ ،ﻋﺪﺩﻱ ﮐﻪ ﮐﺎﺭﺑﺮ ﻭﺍﺭﺩ ﮐﺮﺩﻩ ﺑﺎ ﺣﺮﻭﻑ ﺳﻴﺎﻩﺗﺮ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ .ﺑﺎﺯ ﻫﻢ
ﺑﻪ ﮐﺪ ﺑﺮﻧﺎﻣﻪ ﻧﮕﺎﻩ ﮐﻨﻴﺪ .ﺩﺭ ﺧﻂ ﭼﻬﺎﺭﻡ ﮐﺪ ﻳﻌﻨﻲ:
;" cout << "Enter a number:
19 ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ C++ ﻓﺼﻞ اول /
ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮ ' '\nﻳﺎ endlﺍﺳﺘﻔﺎﺩﻩ ﻧﮑﺮﺩﻩﺍﻳﻢ ﺗﺎ ﻣﮑﺎﻥﻧﻤﺎ ﺩﺭ ﻫﻤﺎﻥ ﺧﻂ ﺑﺎﻗﻲ ﺑﻤﺎﻧﺪ
ﻭ ﻭﺭﻭﺩﻱ ﺩﺭ ﺟﻠﻮﻱ ﻫﻤﺎﻥ ﺧﻂ ﻭﺍﺭﺩ ﺷﻮﺩ.
ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ ﻧﻴﺰ ﻣﺎﻧﻨﺪ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ ﺑﻪ ﺷﮑﻞ ﺟﺮﻳﺎﻧﻲ ﺭﻓﺘﺎﺭ ﻣﻲﮐﻨﺪ .ﻳﻌﻨﻲ
ﻫﻤﺎﻥ ﻃﻮﺭ ﮐﻪ ﺩﺭ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ ﻣﻲﺗﻮﺍﻧﺴﺘﻴﻢ ﭼﻨﺪ ﻋﺒﺎﺭﺕ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﭼﻨﺪ ﻋﻤﻠﮕﺮ
<< ﺑﻪ ﺻﻮﺭﺕ ﭘﺸﺖ ﺳﺮ ﻫﻢ ﭼﺎﭖ ﮐﻨﻴﻢ ،ﺩﺭ ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﭼﻨﺪ ﻋﻤﻠﮕﺮ >> ﭼﻨﺪ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ﭘﺸﺖ ﺳﺮ ﻫﻢ ﺩﺭﻳﺎﻓﺖ ﮐﻨﻴﻢ .ﻣﺜﻼ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﺩﺳﺘﻮﺭ:
;cin >> x >> y >> z
ﺳﻪ ﻣﻘﺪﺍﺭ xﻭ yﻭ zﺑﻪ ﺗﺮﺗﻴﺐ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﻣﻲﺷﻮﻧﺪ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭ ﺑﺎﻳﺪ ﺑﻴﻦ ﻫﺮ
ﻭﺭﻭﺩﻱ ﻳﮏ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ) (spaceﺑﮕﺬﺍﺭﻳﺪ ﻭ ﭘﺲ ﺍﺯ ﺗﺎﻳﭗ ﮐﺮﺩﻥ ﻫﻢۀ ﻭﺭﻭﺩﻱﻫﺎ ،ﮐﻠﻴﺪ
enterﺭﺍ ﺑﻔﺸﺎﺭﻳﺪ .ﺁﺧﺮﻳﻦ ﻣﺜﺎﻝ ﻓﺼﻞ ،ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ ﺑﻬﺘﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
ﺍﻋﺪﺍﺩﻱ ﮐﻪ ﮐﺎﺭﺑﺮ ﺩﺭ ﺍﻳﻦ ﺍﺟﺮﺍ ﻭﺍﺭﺩ ﻧﻤﻮﺩﻩ ﺑﻪ ﺻﻮﺭﺕ ﺳﻴﺎﻩﺗﺮ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 20
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﻣﻮﺍﺭﺩ ﺯﻳﺮ ﺩﺭ ﻣﻮﺭﺩ C++ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟
ﺏ ( ﺷﻲﮔﺮﺍﺳﺖ ﺍﻟﻒ ( ﺍﺯ ﻧﺴﻞ ﺯﺑﺎﻥ Cﺍﺳﺖ
ﺩ ( ﺳﻄﺢ ﭘﺎﻳﻴﻦ ﺍﺳﺖ ﺝ ( ﻫﻤﻪ ﻣﻨﻈﻮﺭﻩ ﺍﺳﺖ
– 2ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﺯﺑﺎﻥﻫﺎﻱ ﺯﻳﺮ ﺩﺭ ﺗﻮﻟﻴﺪ C++ﻧﻘﺶ ﺩﺍﺷﺘﻪ ﺍﺳﺖ؟
ﺏ ( Java ﺍﻟﻒ ( Basic
ﺩ ( Pascal ﺝ ( Simula
– 3ﻣﺤﻴﻂ ﻣﺠﺘﻤﻊ ﺗﻮﻟﻴﺪ ) (IDEﺷﺎﻣﻞ ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﺍﻣﮑﺎﻧﺎﺕ ﺯﻳﺮ ﺍﺳﺖ؟
ﺏ ( ﮐﺎﻣﭙﺎﻳﻠﺮ ﺍﻟﻒ ( ﻭﻳﺮﺍﻳﺶﮔﺮ ﻣﺘﻦ
ﺩ ( ﻫﻢۀ ﻣﻮﺍﺭﺩ ﺝ ( ﺍﺑﺰﺍﺭﺧﻄﺎﻳﺎﺑﻲ
– 4ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺯﻳﺮ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ ﺩﺭ C++ﺍﺳﺖ؟
ﺩ ( // ﺝ ( >> ﺏ(# ﺍﻟﻒ ( <<
– 5ﺍﺯ ﻣﻮﺍﺭﺩ ﺯﻳﺮ ﮐﺪﺍﻡ ﺩﺭ ﻣﻮﺭﺩ ﻋﺒﺎﺭﺕ " "10ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺏ ( " "10ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺳﺖ ﺍﻟﻒ ( " "10ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺳﺖ
ﺩ ( " "10ﻳﮏ ﻋﺪﺩ ﺩﻭﺩﻭﻳﻲ ﺍﺳﺖ ﺝ ( " "10ﻳﮏ ﻟﻴﺘﺮﺍﻝ ﺍﺳﺖ
– 6ﺩﺭ ﻣﻮﺭﺩ ﻋﺒﺎﺭﺕ ; int k = 8ﮐﺪﺍﻡ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟
ﺍﻟﻒ ( ﻣﺘﻐﻴﺮ kﺑﺎ ﻣﻘﺪﺍﺭ 8ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺷﺪﻩ ﺍﺳﺖ
ﺏ ( ﻣﺘﻐﻴﺮ kﺍﺯ ﻧﻮﻉ intﺍﺳﺖ
ﺝ ( ﻣﺘﻐﻴﺮ kﺩﺭ ﺁﺩﺭﺱ 8ﺍﺯ ﺣﺎﻓﻈﻪ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺍﺳﺖ
ﺩ ( ﺩﺭ ﺁﺩﺭﺱ kﻣﻘﺪﺍﺭ 8ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺍﺳﺖ
– 7ﻋﻤﻠﮕﺮ ﺍﻧﺘﺴﺎﺏ ﺩﺭ C++ﭼﻴﺴﺖ؟
ﺩ ( =! ﺝ(# ﺏ ( == ﺍﻟﻒ ( =
;const int x=7 – 8ﺩﺭ ﮐﺪ ﻣﻘﺎﺑﻞ ﭼﻪ ﺭﻭﻱ ﻣﻲﺩﻫﺪ؟ ;x+=9
ﺍﻟﻒ ( ﻣﻘﺪﺍﺭ 9ﺩﺭ xﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ
ﺏ ( ﻣﻘﺪﺍﺭ 7+9ﻳﻌﻨﻲ 16ﺩﺭ xﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ ﭼﺮﺍ ﺑﻪ C++ﻳﮏ ﺯﺑﺎﻥ ﺳﻄﺢ ﻣﺘﻮﺳﻂ ﻣﻲﮔﻮﻳﻨﺪ؟
‐2ﻳﮏ ﺗﻮﺿﻴﺢ ﺣﺎﻟﺖ Cﺑﺎ ﻳﮏ ﺗﻮﺿﻴﺢ ﺣﺎﻟﺖ C++ﭼﻪ ﺗﻔﺎﻭﺕﻫﺎﻳﻲ ﺩﺍﺭﺩ؟
‐3ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﺴﺖ؟
>#include <iostream
)(int main
{ //prints "Hello, World!" :
"cout << "Hello, World!\n
;return 0
}
‐9ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺳﻦ ﮐﺎﺭﺑﺮ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﮐﺮﺩﻩ ﻭ ﺳﭙﺲ ﺁﻥ ﻣﻘﺪﺍﺭ ﺭﺍ ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ
ﻣﻲﮐﻨﺪ ﺍﻣﺎ ﺧﻄﻮﻁ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻫﻢ ﺭﻳﺨﺘﻪ ﺍﺳﺖ .ﺁﻥ ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﺩﺭﺳﺖ ﻣﺮﺗﺐ ﮐﻨﻴﺪ:
)(int main
{ // testing:
;cout << "Your age is: " << age << " years." << endl
;cin >> age
;" cout << "Enter your age:
;int age
;return 0
}
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﮐﻪ ﻫﻢۀ ﺣﺮﻭﻑ ﺍﻟﻔﺒﺎﻱ ﺍﻧﮕﻠﻴﺴﻲ ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﭼﺎﭖ ﮐﻨﺪ ﺑﻪ ﻃﻮﺭﻱ
ﮐﻪ ﮐﻨﺎﺭ ﻫﺮ ﺣﺮﻑ ﺑﺰﺭﮒ ،ﻣﺸﺎﺑﻪ ﮐﻮﭼﮏ ﺁﻥ ﻫﻢ ﻭﺟﻮﺩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ.
‐2ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺑﻪ ﻭﺳﻴﻞۀ ﺳﺘﺎﺭﻩﻫﺎ ،ﺣﺮﻑ Bﺭﺍ ﺩﺭ ﻳﻚ ﺑﻠﻮﻙ 6×7ﻣﺎﻧﻨﺪ ﺯﻳﺮ ﭼﺎﭖ ﻛﻨﺪ.
*****
* *
* *
*****
* *
* *
*****
‐3ﺑﺮﻧﺎﻣﻪﺍﻱ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﺍﻭﻟﻴﻦ ﺣﺮﻑ ﻧﺎﻡ ﻓﺎﻣﻴﻞ ﺷﻤﺎ ﺭﺍ ﺑﻪ ﻭﺳﻴﻞۀ ﺳﺘﺎﺭﻩﻫﺎ ﺩﺭ
ﻳﻚ ﺑﻠﻮﻙ 7×7ﭼﺎﭖ ﻛﻨﺪ.
‐4ﺑﺮﻧﺎﻣﻪﺍﻱ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﻧﺸﺎﻥ ﺩﻫﺪ ﭼﻪ ﺍﺗﻔﺎﻗﻲ ﻣﻲﺍﻓﺘﺪ ﺍﮔﺮ ﻫﺮ ﻳﻚ ﺍﺯ ﺩﻩ
ﺳﻮﻳﭻ ﺧﺮﻭﺟﻲ ﺯﻳﺮ ﭼﺎﭖ ﺷﻮﺩ:
?\ \a , \b , \n , \r , \t , \v , \' , \" , \\ ,
1 – Binary
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 26
ﺩﺍﺩﻩﻫﺎ ﺑﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﻭﺍﮔﺬﺍﺭ ﺷﺪﻩ ﺍﺳﺖ ﻭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺑﺎ ﺧﻴﺎﻝ ﺭﺍﺣﺖ ﻣﻲﺗﻮﺍﻧﺪ ﺍﻧﻮﺍﻉ ﻭﺍﻗﻌﻲ
ﺭﺍ ﮐﻪ ﺁﻥ ﺯﺑﺎﻥ ﺩﺭ ﺍﺧﺘﻴﺎﺭ ﻣﻲﮔﺬﺍﺭﺩ ﺑﻪ ﮐﺎﺭ ﺑﺮﺩ .ﻭﻗﺘﻲ ﺑﺮﻧﺎﻣﻪ ﮐﺎﻣﭙﺎﻳﻞ ﺷﺪ ،ﺍﻳﻦ ﺩﺍﺩﻩﻫﺎ ﺧﻮﺩ
ﺑﻪ ﺧﻮﺩ ﺑﻪ ﺍﻋﺪﺍﺩ ﺩﻭﺩﻭﻳﻲ ﺗﺒﺪﻳﻞ ﻣﻲﺷﻮﻧﺪ.
ﺩﺭ C++ﺩﻭ ﻧﻮﻉ ﺍﺻﻠﻲ ﺩﺍﺩﻩ ﻭﺟﻮﺩ ﺩﺍﺭﺩ» :ﻧﻮﻉ ﺻﺤﻴﺢ «1ﻭ »ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ.«2
ﻫﻢۀ ﺍﻧﻮﺍﻉ ﺩﻳﮕﺮ ﺍﺯ ﺭﻭﻱ ﺍﻳﻦ ﺩﻭ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﻧﺪ )ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ(.
ﺑﺴﺘﮕﻲ ﺯﻳﺎﺩﻱ، ﺍﻳﻦ ﻣﻴﺰﺍﻥ ﺣﺎﻓﻆۀ ﻣﻮﺭﺩ ﺍﺳﺘﻔﺎﺩﻩ ﻭ ﻣﺤﺪﻭﺩۀ ﻣﻘﺎﺩﻳﺮ.ﻣﻲﺗﻮﺍﻧﻨﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ
ﻧﻮﻉ، ﻳﻌﻨﻲ ﻣﻤﮑﻦ ﺍﺳﺖ ﺭﻭﻱ ﻳﮏ ﺭﺍﻳﺎﻧﻪ.ﺑﻪ ﺳﺨﺖﺍﻓﺰﺍﺭ ﻭ ﻫﻤﭽﻨﻴﻦ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﺩﺍﺭﺩ
اﻧﻮاع اﺻﻠﯽ ﺩﻭ ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ ﮐﻨﺪ ﺩﺭint
اﻧﻮاع ﺻﺤﻴﺢ
ﻧﻮع ﻋﺪدی ﺻﺤﻴﺢ ﺣﺎﻟﻲ ﮐﻪ ﺭﻭﻱ ﺭﺍﻳﺎﻧﻪﺍﻱ ﺍﺯ ﻧﻮﻉ ﺩﻳﮕﺮ ﻧﻮﻉ
short
int
ﺑﻪ ﭼﻬﺎﺭ ﺑﺎﻳﺖ ﺣﺎﻓﻈﻪ ﻧﻴﺎﺯ ﺩﺍﺷﺘﻪint
long
unsigned short
<limits> ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺳﺮﻓﺎﻳﻞ.ﺑﺎﺷﺪ
unsigned int
unsigned long
ﻣﻲﺗﻮﺍﻥ ﻣﺸﺨﺺ ﻧﻤﻮﺩ ﮐﻪ ﻫﺮ ﻧﻮﻉ ﻋﺪﺩ
.ﺻﺤﻴﺢ ﺭﻭﻱ ﺭﺍﻳﺎﻧﻪﺗﺎﻥ ﭼﻪ ﻣﺤﺪﻭﺩﻩﺍﻱ ﺩﺍﺭﺩ
ﺑﺎ ﺩﻗﺖ ﺩﺭ ﺍﻳﻦ ﺟﺪﻭﻝ ﻣﺸﺨﺺ ﻣﻲﺷﻮﺩ ﮐﻪ ﺩﺭ ﺭﺍﻳﺎﻥۀ ﻣﺬﮐﻮﺭ ،ﻧﻮﻉ longﻣﺎﻧﻨﺪ
ﻧﻮﻉ intﺍﺳﺖ ﻭ ﻧﻮﻉ unsigned longﻧﻴﺰ ﻣﺎﻧﻨﺪ unsigned intﺍﺳﺖ.
ﮔﺮﭼﻪ ﻣﻤﮑﻦ ﺍﺳﺖ ﺍﻳﻦ ﺍﻧﻮﺍﻉ ﺭﻭﻱ ﺭﺍﻳﺎﻧﻪﺍﻱ ﺍﺯ ﻧﻮﻉ ﺩﻳﮕﺮ ﻣﺘﻔﺎﻭﺕ ﺑﺎﺷﺪ.
ﻭﻗﺘﻲ ﺑﺮﻧﺎﻣﻪﺍﻱ ﻣﻲﻧﻮﻳﺴﻴﺪ ،ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﻣﻨﺎﺳﺐ ﺍﺳﺘﻔﺎﺩﻩ
ﮐﻨﻴﺪ ﺗﺎ ﻫﻢ ﺑﺮﻧﺎﻣﻪ ﺩﭼﺎﺭ ﺧﻄﺎ ﻧﺸﻮﺩ ﻭ ﻫﻢ ﺣﺎﻓﻆۀ ﺳﻴﺴﺘﻢ ﺭﺍ ﻫﺪﺭ ﻧﺪﻫﻴﺪ.
ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺟﻤﻊ ) ، (+ﺗﻔﺮﻳﻖ ) ، (-ﺿﺮﺏ )*( ،ﺗﻘﺴﻴﻢ ) (/ﻭ ﺑﺎﻗﻴﻤﺎﻧﺪﻩ ) (%ﺍﺳﺘﻔﺎﺩﻩ
ﻣﻲﮐﻨﺪ.
ﻧﺘﻴﺞۀ ﺗﻘﺴﻴﻢ m/nﺟﺎﻟﺐ ﺗﻮﺟﻪ ﺍﺳﺖ .ﺣﺎﺻﻞ ﺍﻳﻦ ﺗﻘﺴﻴﻢ ﺑﺮﺍﺑﺮ ﺑﺎ 2ﺍﺳﺖ ﻧﻪ 2.7ﺗﻮﺟﻪ
ﺑﻪ ﺍﻳﻦ ﻣﻄﻠﺐ ﺑﺴﻴﺎﺭ ﻣﻬﻢ ﺍﺳﺖ .ﺍﻳﻦ ﺍﻣﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺣﺎﺻﻞ ﺗﻘﺴﻴﻢ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ
ﺑﺮ ﻋﺪﺩ ﺻﺤﻴﺢ ﺩﻳﮕﺮ ،ﻫﻤﻮﺍﺭﻩ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺳﺖ ﻧﻪ ﻋﺪﺩ ﺍﻋﺸﺎﺭﻱ .ﻫﻤﭽﻨﻴﻦ ﺑﻪ
ﺣﺎﺻﻞ m%nﻧﻴﺰ ﺩﻗﺖ ﮐﻨﻴﺪ .ﻋﻤﻠﮕﺮ %ﺑﺎﻗﻴﻤﺎﻧﺪۀ ﺗﻘﺴﻴﻢ ﺭﺍ ﺑﻪ ﺩﺳﺖ ﻣﻲﺩﻫﺪ .ﻳﻌﻨﻲ ﺣﺎﺻﻞ
ﻋﺒﺎﺭﺕ 54%20ﺑﺮﺍﺑﺮ ﺑﺎ 14ﺍﺳﺖ ﮐﻪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ،ﺑﺎﻗﻴﻤﺎﻧﺪۀ ﺗﻘﺴﻴﻢ 54ﺑﺮ 20ﺍﺳﺖ.
ﺭﺍ ﻳﮏ ﻭﺍﺣﺪ ﮐﺎﻫﺶ ﻣﻲﺩﻫﺪ .ﺍﻣﺎ ﻫﺮ ﮐﺪﺍﻡ ﺍﺯ ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﺩﻭ ﺷﮑﻞ ﻣﺘﻔﺎﻭﺕ ﺩﺍﺭﻧﺪ:
ﺷﮑﻞ »ﭘﻴﺸﻮﻧﺪﻱ« ﻭ ﺷﮑﻞ »ﭘﺴﻮﻧﺪﻱ«.
ﺩﺭ ﺷﮑﻞ ﭘﻴﺸﻮﻧﺪﻱ ،ﻋﻤﻠﮕﺮ ﻗﺒﻞ ﺍﺯ ﻧﺎﻡ ﻣﺘﻐﻴﺮ ﻣﻲﺁﻳﺪ ﻣﺜﻞ ++mﻳﺎ . --nﺩﺭ ﺷﮑﻞ
ﭘﺴﻮﻧﺪﻱ ،ﻋﻤﻠﮕﺮ ﺑﻌﺪ ﺍﺯ ﻧﺎﻡ ﻣﺘﻐﻴﺮ ﻣﻲﺁﻳﺪ ﻣﺜﻞ m++ﻳﺎ . n--ﺗﻔﺎﻭﺕ ﺷﮑﻞ ﭘﻴﺸﻮﻧﺪﻱ ﺑﺎ
ﺷﮑﻞ ﭘﺴﻮﻧﺪﻱ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﺷﮑﻞ ﭘﻴﺸﻮﻧﺪﻱ ﺍﺑﺘﺪﺍ ﻣﺘﻐﻴﺮ ،ﻣﺘﻨﺎﺳﺐ ﺑﺎ ﻋﻤﻠﮕﺮ،
ﺍﻓﺰﺍﻳﺶ ﻳﺎ ﮐﺎﻫﺶ ﻣﻲﻳﺎﺑﺪ ﻭ ﭘﺲ ﺍﺯ ﺁﻥ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺒﺎﺕ ﺩﻳﮕﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ
ﻭﻟﻲ ﺩﺭ ﺷﮑﻞ ﭘﺴﻮﻧﺪﻱ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺕ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ ﻭ ﭘﺲ ﺍﺯ ﺁﻥ ﻣﻘﺪﺍﺭ
ﻣﺘﻐﻴﺮ ﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﺍﻳﺶ ﻳﺎ ﮐﺎﻫﺶ ﻣﻲﻳﺎﺑﺪ .ﺑﺮﺍﻱ ﺩﺭﮎ ﺑﻬﺘﺮ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ
ﺗﻮﺟﻪ ﮐﻨﻴﺪ.
ﺍﺯ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ .ﭘﺲ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ mﺑﻪ 76ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ ﻭ
ﺳﭙﺲ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﻪ nﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻭﻗﺘﻲ ﺩﺭ ﺧﻂ ﺷﺸﻢ ﻣﻘﺪﺍﺭ ﺍﻳﻦ ﺩﻭ ﻣﺘﻐﻴﺮ
ﭼﺎﭖ ﻣﻲﺷﻮﺩ m = 76 ،ﻭ n = 76ﺧﻮﺍﻫﺪ ﺑﻮﺩ.
31 ﻓﺼﻞ دوم /اﻧﻮاع اﺻﻠﯽ
;int n=22
;cout << " n = " << n << endl
n += 9; // adds 9 to n
;cout << "After n += 9, n = " << n << endl
n -= 5; //substracts 5 from n
;cout << "After n -= 5, n = " << n << endl
n *= 2; //multiplies n by 2
;cout << "After n *= 2, n = " << n << endl
n /= 3; //divides n by 3
;cout << "After n /= 3, n = " << n << endl
n %= 7; //reduces n to the remainder from dividing by 4
;cout << "After n %= 7, n = " << n << endl
;return 0
}
n = 22
After n =+ 9, n = 31
After n =- 5, n = 26
After n =* 2, n = 52
After n =/ 3, n = 17
After n =% 7, n = 3
ﺍﮐﻨﻮﻥ ﺑﺮﺍﻱ ﻣﺸﺨﺺ ﻧﻤﻮﺩﻥ ﻣﺤﻞ ﺍﻋﺸﺎﺭ ﺩﺭ ﻋﺪﺩ ،ﺗﻤﺎﻡ ﺭﻗﻢﻫﺎ ﺭﺍ ﺑﻪ ﺳﻤﺖ ﺭﺍﺳﺖ ﻣﻤﻴﺰ
ﻣﻨﺘﻘﻞ ﻣﻲﮐﻨﻴﻢ .ﺍﻟﺒﺘﻪ ﺑﺎ ﻫﺮ ﺟﺎﺑﺠﺎﻳﻲ ﻣﻤﻴﺰ ،ﻋﺪﺩ ﺣﺎﺻﻞ ﺑﺎﻳﺪ ﺩﺭ ﺗﻮﺍﻧﻲ ﺍﺯ 2ﺿﺮﺏ ﺷﻮﺩ:
123.45 = 0.11110110111001 × 27
ﮐﻪ ﻣﺎﻧﺘﻴﺲ ﻭ ﻧﻤﺎ ﺭﺍ ﺫﺧﻴﺮﻩ ﮐﻨﻴﻢ .ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺑﺨﻮﺍﻫﻴﻢ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺫﺧﻴﺮﻩ ﺷﺪﻩ ﺭﺍ ﺑﺎﺯﻳﺎﺑﻲ
ﮐﻨﻴﻢ ،ﺳﻴﺴﺘﻢﻋﺎﻣﻞ ﻧﻤﺎ ﻭ ﻣﺎﻧﺘﻴﺲ ﺭﺍ ﺩﺭ ﻣﺴﻴﺮﻱ ﻋﮑﺲ ﻣﺴﻴﺮ ﺑﺎﻻ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﺩ ﺗﺎ ﻋﺪﺩ
123.45ﺭﺍ ﺍﺯ ﺭﻭﻱ ﺁﻥ ﺩﻭﺑﺎﺭﻩ ﺑﺴﺎﺯﺩ .ﺩﺭ ﻣﻮﺭﺩ ﻋﺪﺩﻱ ﻣﺜﻞ ﻋﺪﺩ ﻣﺬﮐﻮﺭ ﻣﻤﮑﻦ ﺍﺳﺖ
ﺍﻳﻦ ﺭﻭﺵ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ،ﻃﻮﻻﻧﻲ ﻭ ﺑﻲﻣﻮﺭﺩ ﺑﻪ ﻧﻈﺮ ﺑﺮﺳﺪ .ﺍﻣﺎ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺷﺎﻣﻞ
ﺍﻋﺪﺍﺩ ﺧﻴﻠﻲ ﮐﻮﭼﮏ ﻣﺜﻞ 0.000000001ﻳﺎ ﺍﻋﺪﺍﺩ ﺧﻴﻠﻲ ﺑﺰﺭﮒ ﻣﺜﻞ
100000000.00000002ﻫﺴﺘﻨﺪ ﮐﻪ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻭ ﺍﻧﺠﺎﻡ ﻣﺤﺎﺳﺒﺎﺕ ﺭﻳﺎﺿﻲ ﺭﻭﻱ
ﺁﻥﻫﺎ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺎﻧﺘﻴﺲ ﻭ ﻧﻤﺎ ﺑﺴﻴﺎﺭ ﺁﺳﺎﻥﺗﺮ ﺍﺳﺖ.
ﺩﺭ C++ﺳﻪ ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﻭﺟﻮﺩ ﺩﺍﺭﺩ :ﻧﻮﻉ floatﻭ ﻧﻮﻉ doubleﻭ ﻧﻮﻉ
. long double
ﻣﻌﻤﻮﻻ ﻧﻮﻉ floatﺍﺯ ﭼﻬﺎﺭ ﺑﺎﻳﺖ ﺑﺮﺍﻱ ﻧﮕﻬﺪﺍﺭﻱ ﻋﺪﺩ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ ،ﻧﻮﻉ
doubleﺍﺯ ﻫﺸﺖ ﺑﺎﻳﺖ ﻭ ﻧﻮﻉ long doubleﺍﺯ ﻫﺸﺖ ﻳﺎ ﺩﻩ ﻳﺎ ﺩﻭﺍﺯﺩﻩ ﻳﺎ ﺷﺎﻧﺰﺩﻩ
ﺑﺎﻳﺖ .ﺩﺭ ﻳﮏ 32 floatﺑﻴﺘﻲ )ﭼﻬﺎﺭ ﺑﺎﻳﺘﻲ( ﺍﺯ 23ﺑﻴﺖ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻣﺎﻧﺘﻴﺲ
ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ 8ﺑﻴﺖ ﻧﻴﺰ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻧﻤﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ ﻭ ﻳﮏ ﺑﻴﺖ ﻧﻴﺰ
ﻋﻼﻣﺖ ﻋﺪﺩ ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﮐﻨﺪ.
ﺩﺭ ﻳﮏ 64 doubleﺑﻴﺘﻲ )ﻫﺸﺖ ﺑﺎﻳﺘﻲ( ﺍﺯ 52ﺑﻴﺖ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻣﺎﻧﺘﻴﺲ
ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ 11ﺑﻴﺖ ﺑﺮﺍﻱ ﻧﮕﻬﺪﺍﺭﻱ ﻧﻤﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ ﻭ ﻳﮏ ﺑﻴﺖ ﻧﻴﺰ ﻋﻼﻣﺖ
ﻋﺪﺩ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
ﺑﻪ ﭘﺎﺳﺦﻫﺎﻱ ﺑﺎﻻ ﺩﻗﺖ ﮐﻨﻴﺪ :ﺑﺮ ﺧﻼﻑ ﺗﻘﺴﻴﻢ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ،ﺗﻘﺴﻴﻢ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺑﻪ
54.0 / 20.0 = 2.7 ﺻﻮﺭﺕ ﺑﺮﻳﺪﻩﺷﺪﻩ ﻧﻴﺴﺖ:
ﺗﻔﺎﻭﺕ ﻧﻮﻉ floatﺑﺎ ﻧﻮﻉ doubleﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻧﻮﻉ doubleﺩﻭ ﺑﺮﺍﺑﺮ
floatﺍﺯ ﺣﺎﻓﻈﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ .ﭘﺲ ﻧﻮﻉ doubleﺩﻗﺘﻲ ﺑﺴﻴﺎﺭ ﺑﻴﺸﺘﺮ ﺍﺯ float
ﺩﺍﺭﺩ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﻣﺤﺎﺳﺒﺎﺕ doubleﻭﻗﺖﮔﻴﺮﺗﺮ ﺍﺯ ﻣﺤﺎﺳﺒﺎﺕ floatﺍﺳﺖ.
ﺑﻨﺎﺑﺮﺍﻳﻦ ﺍﮔﺮ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺘﺎﻥ ﺑﻪ ﻣﺤﺎﺳﺒﺎﺕ ﻭ ﭘﺎﺳﺦﻫﺎﻱ ﺑﺴﻴﺎﺭ ﺩﻗﻴﻖ ﻧﻴﺎﺯ ﺩﺍﺭﻳﺪ ،ﺍﺯ ﻧﻮﻉ
doubleﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﺪ .ﻭﻟﻲ ﺍﮔﺮ ﺳﺮﻋﺖ ﺍﺟﺮﺍ ﺑﺮﺍﻳﺘﺎﻥ ﺍﻫﻤﻴﺖ ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﺩ ،ﻧﻮﻉ
floatﺭﺍ ﺑﻪ ﮐﺎﺭ ﺑﮕﻴﺮﻳﺪ.
35 ﻓﺼﻞ دوم /اﻧﻮاع اﺻﻠﯽ
ﺩﺭ C++ﺑﺮﺍﻱ ﻧﺸﺎﻥ ﺩﺍﺩﻥ ﺣﺎﻟﺖ ﻋﻠﻤﻲ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺍﺯ ﺣﺮﻑ ﺍﻧﮕﻠﻴﺴﻲ eﻳﺎ
Eﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ:
-1.23×10-10 = -1.23e-10
1.23×1011 = 1.23e11
ﻫﻨﮕﺎﻡ ﻭﺍﺭﺩ ﮐﺮﺩﻥ ﻣﻘﺎﺩﻳﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ،ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﺷﮑﻞ ﺳﺎﺩﻩ ﻳﺎ ﺷﮑﻞ ﻋﻠﻤﻲ
ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ .ﻫﻨﮕﺎﻡ ﭼﺎﭖ ﻣﻘﺎﺩﻳﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ،ﻣﻌﻤﻮﻻ ﻣﻘﺎﺩﻳﺮ ﺑﻴﻦ 0.1ﺗﺎ 999.999ﺑﻪ
ﺷﮑﻞ ﺳﺎﺩﻩ ﭼﺎﭖ ﻣﻲﺷﻮﻧﺪ ﻭ ﺳﺎﻳﺮ ﻣﻘﺎﺩﻳﺮ ﺑﻪ ﺷﮑﻞ ﻋﻠﻤﻲ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ.
ﺗﺎ ﺍﻳﻦﺟﺎ ﺍﻧﻮﺍﻉ ﻋﺪﺩﻱ ﺭﺍ ﺩﺭ C++ﺩﻳﺪﻳﻢ .ﺍﻳﻦ ﺍﻧﻮﺍﻉ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺒﺎﺕ ﺍﺳﺘﻔﺎﺩﻩ
ﻣﻲﺷﻮﻧﺪ ﻭ ﺗﻘﺮﻳﺒﺎ ﺩﺭ ﻫﺮ ﺑﺮﻧﺎﻣﻪﺍﻱ ﮐﻪ ﻣﻲﻧﻮﻳﺴﻴﺪ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ .ﺍﻣﺎ C++ﺍﻧﻮﺍﻉ ﺩﻳﮕﺮﻱ
ﻧﻴﺰ ﺩﺍﺭﺩ ﮐﻪ ﮐﺎﺭﺑﺮﺩﻫﺎﻱ ﺩﻳﮕﺮﻱ ﺩﺍﺭﻧﺪ .ﻧﻮﻉ ﺑﻮﻟﻴﻦ ﮐﻪ ﺑﺮﺍﻱ ﻋﻤﻠﻴﺎﺕ ﻣﻨﻄﻘﻲ ﺍﺳﺘﻔﺎﺩﻩ
ﻣﻲﺷﻮﺩ ﻭ ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻱ ﮐﻪ ﺑﺮﺍﻱ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺗﺪﺍﺭﮎ ﺩﻳﺪﻩ ﺷﺪﻩ ﺍﺳﺖ ﻭ ﻧﻮﻉ
ﺷﻤﺎﺭﺷﻲ ﮐﻪ ﺑﻴﺸﺘﺮ ﺑﺮﺍﻱ ﻣﺠﻤﻮﻋﻪﻫﺎﻳﻲ ﮐﻪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ.
ﺍﻳﻦ ﺍﻧﻮﺍﻉ ﺟﺪﻳﺪ ﮔﺮﭼﻪ ﮐﺎﺭﺑﺮﺩﺷﺎﻥ ﺑﺎ ﺍﻋﺪﺍﺩ ﺗﻔﺎﻭﺕ ﺩﺍﺭﺩ ﺍﻣﺎ ﺩﺭ ﺣﻘﻴﻘﺖ ﺑﻪ ﺷﮑﻞ ﺍﻋﺪﺍﺩ
ﺻﺤﻴﺢ ﺩﺭ ﺭﺍﻳﺎﻧﻪ ﺫﺧﻴﺮﻩ ﻭ ﺷﻨﺎﺳﺎﻳﻲ ﻣﻲﺷﻮﻧﺪ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﻳﻦ ﻧﻮﻉﻫﺎ ﺭﺍ ﻧﻴﺰ
ﺯﻳﺮﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﺍﻧﻮﺍﻉ ﺻﺤﻴﺢ ﺩﺭ C++ﻣﻲﺷﻤﺎﺭﻧﺪ .ﺩﺭ ﺍﺩﺍﻡۀ ﺍﻳﻦ ﻓﺼﻞ ﺑﻪ ﺑﺮﺭﺳﻲ ﺍﻳﻦ
ﺍﻧﻮﺍﻉ ﻣﻲﭘﺮﺩﺍﺯﻳﻢ.
ﻧﻮﻉ boolﻳﮏ ﻧﻮﻉ ﺻﺤﻴﺢ ﺍﺳﺖ ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﻳﻦ ﻧﻮﻉ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻣﻘﺪﺍﺭ
trueﻳﺎ falseﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ true .ﺑﻪ ﻣﻌﻨﻲ ﺩﺭﺳﺖ ﻭ falseﺑﻪ ﻣﻌﻨﻲ ﻧﺎﺩﺭﺳﺖ
ﺍﺳﺖ .ﮔﺮﭼﻪ ﺩﺭﻭﻥ ﺑﺮﻧﺎﻣﻪ ﻣﺠﺒﻮﺭﻳﻢ ﺍﺯ ﻋﺒﺎﺭﺍﺕ trueﻳﺎ falseﺑﺮﺍﻱ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﻪ ﺍﻳﻦ
ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ ،ﺍﻣﺎ ﺍﻳﻦ ﻣﻘﺎﺩﻳﺮ ﺩﺭ ﺍﺻﻞ ﺑﻪ ﺻﻮﺭﺕ 1ﻭ 0ﺩﺭﻭﻥ ﺭﺍﻳﺎﻧﻪ ﺫﺧﻴﺮﻩ
ﻣﻲﺷﻮﻧﺪ 1 :ﺑﺮﺍﻱ trueﻭ 0ﺑﺮﺍﻱ .falseﻣﺜﺎﻝ ﺯﻳﺮ ﺍﻳﻦ ﻣﻄﻠﺐ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
1 – Boolean
37 ﻓﺼﻞ دوم /اﻧﻮاع اﺻﻠﯽ
ﺩﺭ ﺧﻂ ﺳﻮﻡ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ falgﺍﺯ ﻧﻮﻉ boolﺗﻌﺮﻳﻒ ﺷﺪﻩ ﻭ ﺑﺎ
ﻣﻘﺪﺍﺭ falseﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺷﺪﻩ ﺍﺳﺖ .ﺩﺭ ﺧﻂ ﺑﻌﺪﻱ ﻣﻘﺪﺍﺭ ﺍﻳﻦ ﻣﺘﻐﻴﺮ ﺩﺭ ﺧﺮﻭﺟﻲ
ﭼﺎﭖ ﺷﺪﻩ ﻭ ﺩﺭ ﺧﻂ ﭘﻨﺠﻢ ﻣﻘﺪﺍﺭ ﺁﻥ ﺑﻪ trueﺗﻐﻴﻴﺮ ﻳﺎﻓﺘﻪ ﺍﺳﺖ ﻭ ﺩﻭﺑﺎﺭﻩ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ
ﭼﺎﭖ ﺷﺪﻩ ﺍﺳﺖ .ﮔﺮﭼﻪ ﺑﻪ ﻣﺘﻐﻴﺮ flagﻣﻘﺪﺍﺭ falseﻭ trueﺩﺍﺩﻩﺍﻳﻢ ﺍﻣﺎ ﺩﺭ
ﺧﺮﻭﺟﻲ ﺑﻪ ﺟﺎﻱ ﺁﻥﻫﺎ ﻣﻘﺎﺩﻳﺮ 0ﻭ 1ﭼﺎﭖ ﺷﺪﻩ ﺍﺳﺖ.
ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻳﮏ ﺣﺮﻑ ،ﺭﻗﻢ ﻳﺎ ﻧﺸﺎﻧﻪ ﺍﺳﺖ ﮐﻪ ﻳﮏ ﺷﻤﺎﺭۀ ﻣﻨﺤﺼﺮ ﺑﻪ ﻓﺮﺩ ﺩﺍﺭﺩ .ﺑﻪ
ﻋﺒﺎﺭﺕ ﻋﺎﻣﻴﺎﻧﻪ ،ﻫﺮ ﮐﻠﻴﺪﻱ ﮐﻪ ﺭﻭﻱ ﺻﻔﺤﻪﮐﻠﻴﺪ ﺧﻮﺩ ﻣﻲﺑﻴﻨﻴﺪ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﻧﺸﺎﻥ
ﻣﻲﺩﻫﺪ )ﺍﻟﺒﺘﻪ ﺑﻪ ﻏﻴﺮ ﺍﺯ ﮐﻠﻴﺪﻫﺎﻱ ﻣﺎﻟﺘﻲﻣﺪﻳﺎ ﻳﺎ ﮐﻠﻴﺪﻫﺎﻱ ﺍﻳﻨﺘﺮﻧﺘﻲ ﮐﻪ ﺍﺧﻴﺮﺍ ﺩﺭ
ﺻﻔﺤﻪﮐﻠﻴﺪﻫﺎ ﻣﺮﺳﻮﻡ ﺷﺪﻩﺍﻧﺪ( .ﻣﺜﻼ ﻫﺮ ﻳﮏ ﺍﺯ ﺣﺮﻭﻑ ' 'Aﺗﺎ ' 'Zﻭ ' 'aﺗﺎ ' 'zﻭ
ﻫﺮ ﻳﮏ ﺍﺯ ﺍﻋﺪﺍﺩ ' '0ﺗﺎ ' '9ﻭ ﻳﺎ ﻧﺸﺎﻧﻪﻫﺎﻱ '~' ﺗﺎ ' '+ﺭﻭﻱ ﺻﻔﺤﻪﮐﻠﻴﺪ ﺭﺍ ﻳﮏ
ﮐﺎﺭﺍﮐﺘﺮ ﻣﻲﻧﺎﻣﻨﺪ .ﺭﺍﻳﺎﻧﻪﻫﺎ ﺑﺮﺍﻱ ﺷﻨﺎﺳﺎﻳﻲ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺍﺯ ﺟﺪﻭﻝ ﺍﺳﮑﻲ ﺍﺳﺘﻔﺎﺩﻩ
ﻣﻲﮐﻨﻨﺪ .ﺑﺎ ﺩﻗﺖ ﺩﺭ ﺍﻳﻦ ﺟﺪﻭﻝ ﺧﻮﺍﻫﻴﺪ ﺩﻳﺪ ﮐﻪ ﻫﺮ ﮐﺎﺭﺍﮐﺘﺮ ﻳﮏ ﺷﻤﺎﺭۀ ﻣﻨﺤﺼﺮ ﺑﻪ ﻓﺮﺩ
ﺩﺍﺭﺩ .ﻣﺜﻼ ﮐﺎﺭﺍﮐﺘﺮ ' 'Aﮐﺪ 65ﺩﺍﺭﺩ .ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺩﺭ ﺭﺍﻳﺎﻧﻪ ﺑﻪ ﺷﮑﻞ ﻋﺪﺩﻱﺷﺎﻥ ﺫﺧﻴﺮﻩ
ﻣﻲﺷﻮﻧﺪ ﺍﻣﺎ ﺑﻪ ﺷﮑﻞ ﮐﺎﺭﺍﮐﺘﺮﻱﺷﺎﻥ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ .ﻣﺜﻼ ﮐﺎﺭﺍﮐﺘﺮ ' 'Aﺑﻪ ﺷﮑﻞ ﻋﺪﺩ
65ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﺍﮔﺮ ﺳﻌﻲ ﮐﻨﻴﻢ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮ ' 'Aﺩﺭ ﺁﻥ ﺫﺧﻴﺮﻩ ﺷﺪﻩ ﺭﺍ
ﭼﺎﭖ ﮐﻨﻴﻢ ،ﺷﮑﻞ Aﺭﺍ ﺩﺭ ﺧﺮﻭﺟﻲ ﻣﻲ ﺑﻴﻨﻴﻢ ﻧﻪ ﻋﺪﺩ 65ﺭﺍ.
ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺯ ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ charﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ .ﻳﮏ
ﮐﺎﺭﺍﮐﺘﺮ ﺑﺎﻳﺪ ﺩﺭﻭﻥ ﺩﻭ ﻋﻼﻣﺖ ﺁﭘﺴﺘﺮﻭﻑ )'( ﻣﺤﺼﻮﺭ ﺷﺪﻩ ﺑﺎﺷﺪ .ﭘﺲ ' 'Aﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ
ﺍﺳﺖ؛ ﻫﻤﭽﻨﻴﻦ ' '8ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺳﺖ ﺍﻣﺎ 8ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻧﻴﺴﺖ ﺑﻠﮑﻪ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ
ﺍﺳﺖ.
ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﺤﻮۀ ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ﻣﺘﻐﻴﺮﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
cout << "c ;= " << c << ", int(c) = " << int(c) << endl
;'c ='t
cout << "c ;= " << c << ", int(c) = " << int(c) << endl
;'c ='\t // the tab character
cout << "c ;= " << c << ", int(c) = " << int(c) << endl
;'!'= c
cout << "c ;= " << c << ", int(c) = " << int(c) << endl
;return 0
}
c = A, int(c) = 65
c = t, int(c) = 116
c = , int(c) = 9
c = !, int(c) = 33
ﺩﺭ ﺧﻂ ﺳﻮﻡ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ cﺍﺯ ﻧﻮﻉ charﺗﻌﺮﻳﻒ ﺷﺪﻩ ﻭ ﺑﺎ ﻣﻘﺪﺍﺭ ''A
ﻣﻘﺪﺍﺭﮔﺬﺍﺭﻱ ﺍﻭﻟﻴﻪ ﺷﺪﻩ ﺍﺳﺖ .ﺳﭙﺲ ﺩﺭ ﺧﻂ ﺑﻌﺪﻱ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ cﭼﺎﭖ ﺷﺪﻩ ﮐﻪ ﺩﺭ
ﺧﺮﻭﺟﻲ ﻫﻤﺎﻥ Aﺩﻳﺪﻩ ﻣﻲﺷﻮﺩ ﻧﻪ ﻣﻘﺪﺍﺭ ﻋﺪﺩﻱ ﺁﻥ .ﺩﺭ ﺍﺩﺍﻡۀ ﺧﻂ ﭼﻬﺎﺭﻡ ،ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﺩﺳﺘﻮﺭ ) int(cﻣﻘﺪﺍﺭ ﻋﺪﺩﻱ cﻳﻌﻨﻲ 65ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﺧﻮﺍﻫﺪ ﺷﺪ .ﺩﺭ ﺧﻄﻮﻁ
ﺑﻌﺪﻱ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺩﻳﮕﺮﻱ ﺑﻪ cﺍﺧﺘﺼﺎﺹ ﻳﺎﻓﺘﻪ ﻭ ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﻣﻘﺪﺍﺭ cﻭ ﻣﻌﺎﺩﻝ
ﻋﺪﺩﻱ ﺁﻥ ﭼﺎﭖ ﺷﺪﻩ ﺍﺳﺖ.
;'c = '\t ﺑﻪ ﺧﻂ ﻫﻔﺘﻢ ﺑﺮﻧﺎﻣﻪ ﻧﮕﺎﻩ ﮐﻨﻴﺪ:
ﮐﺎﺭﺍﮐﺘﺮ ' '\tﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺧﺎﺹ ﺍﺳﺖ .ﺍﮔﺮ ﺳﻌﻲ ﮐﻨﻴﻢ ﮐﺎﺭﺍﮐﺘﺮ ' '\tﺭﺍ ﺭﻭﻱ
ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﻧﺸﺎﻥ ﺩﻫﻴﻢ ،ﻫﻔﺖ ﺟﺎﻱ ﺧﺎﻟﻲ ﺭﻭﻱ ﺻﻔﺤﻪ ﺩﻳﺪﻩ ﻣﻲﺷﻮﺩ)ﺑﻪ ﺧﺮﻭﺟﻲ ﺩﻗﺖ
ﮐﻨﻴﺪ( .ﻏﻴﺮ ﺍﺯ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮ ،ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺧﺎﺹ ﺩﻳﮕﺮﻱ ﻧﻴﺰ ﻫﺴﺘﻨﺪ ﮐﻪ ﮐﺎﺭﻫﺎﻳﻲ ﻣﺸﺎﺑﻪ ﺍﻳﻦ
ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﻨﺪ .ﻣﺜﻞ ﮐﺎﺭﺍﮐﺘﺮ ' '\nﮐﻪ ﺩﺭ ﻓﺼﻞ ﻗﺒﻞ ﺩﻳﺪﻳﻢ ﻭ ﻣﮑﺎﻥﻧﻤﺎ ﺭﺍ ﺑﻪ ﺳﻄﺮ ﺑﻌﺪﻱ
ﻣﻨﺘﻘﻞ ﻣﻲﮐﻨﺪ .ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺑﺮﺍﻱ ﺷﮑﻞﺩﻫﻲ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﻭ ﮐﻨﺘﺮﻝ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ.
ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺧﺎﺹ ﺩﺭ ﺟﺪﻭﻝ ﺍﺳﮑﻲ ﺑﻴﻦ ﺷﻤﺎﺭﻩﻫﺎﻱ 0ﺗﺎ 32ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪﺍﻧﺪ .ﺳﻌﻲ ﮐﻨﻴﺪ
ﻣﺜﻞ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﺎﻳﺸﻲ ﺑﻨﻮﻳﺴﻴﺪ ﻭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﻣﻘﺎﺩﻳﺮ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺧﺎﺹ
ﺭﺍ ﭼﺎﭖ ﮐﻨﻴﺪ ﺗﺎ ﺑﺒﻴﻨﻴﺪ ﭼﻪ ﺍﺗﻔﺎﻗﻲ ﻣﻲﺍﻓﺘﺪ .ﻻﺑﻪﻻﻱ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺑﻌﺪﻱ ﺍﺯ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ
ﺧﺎﺹ ﺍﺳﺘﻔﺎﺩﻩ ﺧﻮﺍﻫﻴﻢ ﮐﺮﺩ ﺗﺎ ﺑﺎ ﺁﻥﻫﺎ ﺑﻬﺘﺮ ﺁﺷﻨﺎ ﺷﻮﻳﺪ.
39 ﻓﺼﻞ دوم /اﻧﻮاع اﺻﻠﯽ
ﻋﻼﻭﻩ ﺑﺮ ﺍﻧﻮﺍﻋﻲ ﮐﻪ ﺗﺎ ﮐﻨﻮﻥ ﺑﺮﺭﺳﻲ ﮐﺮﺩﻳﻢ ،ﻣﻲ ﺗﻮﺍﻥ ﺩﺭ C++ﺍﻧﻮﺍﻉ ﺟﺪﻳﺪﻱ ﮐﻪ
ﮐﺎﺭﺑﺮ ﻧﻴﺎﺯ ﺩﺍﺭﺩ ﻧﻴﺰ ﺍﻳﺠﺎﺩ ﻧﻤﻮﺩ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭ ﺭﺍﻩﻫﺎﻱ ﻣﺨﺘﻠﻔﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﮐﻪ ﺑﻬﺘﺮﻳﻦ ﻭ
ﻗﻮﻱﺗﺮﻳﻦ ﺭﺍﻩ ،ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﮐﻼﺱﻫﺎ ﺍﺳﺖ)ﻓﺼﻞ ﺩﻩ( ،ﺍﻣﺎ ﺭﺍﻩ ﺳﺎﺩﻩﺗﺮﻱ ﻧﻴﺰ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﻭ ﺁﻥ
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ enumﺍﺳﺖ.
ﻳﮏ ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ﻳﮏ ﻧﻮﻉ ﺻﺤﻴﺢ ﺍﺳﺖ ﮐﻪ ﺗﻮﺳﻂ ﮐﺎﺭﺑﺮ ﻣﺸﺨﺺ ﻣﻲﺷﻮﺩ .ﻧﺤﻮ
ﺗﻌﺮﻳﻒ ﻳﮏ ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
}enum typename{enumerator-list
ﮐﻪ enumﮐﻠﻤﻪﺍﻱ ﮐﻠﻴﺪﻱ ﺍﺳﺖ typename ،ﻧﺎﻡ ﻧﻮﻉ ﺟﺪﻳﺪ ﺍﺳﺖ ﮐﻪ ﮐﺎﺭﺑﺮ ﻣﺸﺨﺺ
ﻣﻲﮐﻨﺪ ﻭ enumerator-listﻣﺠﻤﻮﻋﻪ ﻣﻘﺎﺩﻳﺮﻱ ﺍﺳﺖ ﮐﻪ ﺍﻳﻦ ﻧﻮﻉ ﺟﺪﻳﺪ ﻣﻲﺗﻮﺍﻧﺪ
ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺑﻪ ﻋﻨﻮﺍﻥ ﻣﺜﺎﻝ ﺑﻪ ﺗﻌﺮﻳﻒ ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ:
}enum Day{SAT,SUN,MON,TUE,WED,THU,FRI
ﺣﺎﻻ Dayﻳﮏ ﻧﻮﻉ ﺟﺪﻳﺪ ﺍﺳﺖ ﻭ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﮐﻪ ﺍﺯ ﺍﻳﻦ ﻧﻮﻉ ﺗﻌﺮﻳﻒ ﻣﻲﺷﻮﻧﺪ ﻣﻲﺗﻮﺍﻧﻨﺪ
ﻳﮑﻲ ﺍﺯ ﻣﻘﺎﺩﻳﺮ SATﻭ SUNﻭ MONﻭ TUEﻭ WEDﻭ THUﻭ FRIﺭﺍ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ:
;Day day1,day2
;day1 = MON
;day2 = THU
ﻭﻗﺘﻲ ﻧﻮﻉ ﺟﺪﻳﺪ Dayﻭ ﻣﺤﺪﻭﺩۀ ﻣﻘﺎﺩﻳﺮﺵ ﺭﺍ ﺗﻌﻴﻴﻦ ﮐﺮﺩﻳﻢ ،ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ
ﺍﺯ ﺍﻳﻦ ﻧﻮﻉ ﺟﺪﻳﺪ ﺑﺴﺎﺯﻳﻢ .ﺩﺭ ﮐﺪ ﺑﺎﻻ ﻣﺘﻐﻴﺮﻫﺎﻱ day1ﻭ day2ﺍﺯ ﻧﻮﻉ Dayﺗﻌﺮﻳﻒ
ﺷﺪﻩﺍﻧﺪ .ﺁﻧﮕﺎﻩ day1ﺑﺎ ﻣﻘﺪﺍﺭ MONﻭ day2ﺑﺎ ﻣﻘﺪﺍﺭ THUﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﺪﻩ ﺍﺳﺖ.
ﻣﻘﺎﺩﻳﺮ SATﻭ SUNﻭ ...ﻫﺮ ﭼﻨﺪ ﮐﻪ ﺑﻪ ﻫﻤﻴﻦ ﺷﮑﻞ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ﺍﻣﺎ ﺩﺭ
ﺭﺍﻳﺎﻧﻪ ﺑﻪ ﺷﮑﻞ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ 0ﻭ 1ﻭ 2ﻭ ...ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﻧﺪ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﺳﺖ ﮐﻪ
ﺑﻪ ﻫﺮ ﻳﮏ ﺍﺯ ﻣﻘﺎﺩﻳﺮ SATﻭ SUNﻭ ...ﻳﮏ ﺷﻤﺎﺭﺷﮕﺮ 1ﻣﻲﮔﻮﻳﻨﺪ .ﻭﻗﺘﻲ ﻓﻬﺮﺳﺖ
ﺷﻤﺎﺭﺷﮕﺮﻫﺎﻱ ﻳﮏ ﻧﻮﻉ ﺗﻌﺮﻳﻒ ﺷﺪ ،ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﻣﻘﺎﺩﻳﺮ 0ﻭ 1ﻭ 2ﻭ ...ﺑﻪ ﺗﺮﺗﻴﺐ
1 – Enumerator
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 40
ﺑﻪ ﺁﻥﻫﺎ ﺍﺧﺘﺼﺎﺹ ﻣﻲﻳﺎﺑﺪ .ﻫﺮﭼﻨﺪ ﮐﻪ ﻣﻲﺗﻮﺍﻥ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺭﺍ ﺷﮑﺴﺖ ﻭ ﻣﻘﺎﺩﻳﺮ ﺻﺤﻴﺢ
ﺩﻟﺨﻮﺍﻫﻲ ﺭﺍ ﺑﻪ ﺷﻤﺎﺭﺷﮕﺮﻫﺎ ﻧﺴﺒﺖ ﺩﺍﺩ:
}enum Day{SAT=1,SUN=2,MON=4,TUE=8,WED=16,THU=32,FRI=64
ﺍﮔﺮ ﻓﻘﻂ ﺑﻌﻀﻲ ﺍﺯ ﺷﻤﺎﺭﺷﮕﺮﻫﺎ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﻮﻧﺪ ،ﺁﻧﮕﺎﻩ ﺳﺎﻳﺮ ﺷﻤﺎﺭﺷﮕﺮﻫﺎ ﮐﻪ
ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩﺍﻧﺪ ﻣﻘﺎﺩﻳﺮ ﻣﺘﻮﺍﻟﻲ ﺑﻌﺪﻱ ﺭﺍ ﺧﻮﺍﻫﻨﺪ ﮔﺮﻓﺖ:
}enum Day{SAT=1,SUN,MON,TUE,WED,THU,FRI
ﺩﺳﺘﻮﺭ ﺑﺎﻻ ﻣﻘﺎﺩﻳﺮ 1ﺗﺎ 7ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﺑﻪ ﺭﻭﺯﻫﺎﻱ ﻫﻔﺘﻪ ﺗﺨﺼﻴﺺ ﺧﻮﺍﻫﺪ ﺩﺍﺩ.
ﻫﻤﭽﻨﻴﻦ ﺩﻭ ﻳﺎ ﭼﻨﺪ ﺷﻤﺎﺭﺷﮕﺮ ﺩﺭ ﻳﮏ ﻓﻬﺮﺳﺖ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻣﻘﺎﺩﻳﺮ ﻳﮑﺴﺎﻧﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ:
}enum Answer{NO=0,FALSE=0,YES=1,TRUE=1,OK=1
ﺩﺭ ﮐﺪ ﺑﺎﻻ ﺩﻭ ﺷﻤﺎﺭﺷﮕﺮ NOﻭ FALSEﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﻳﮑﺴﺎﻥ 0ﻭ ﺷﻤﺎﺭﺷﮕﺮﻫﺎﻱ YES
ﻭ TRUEﻭ OKﻧﻴﺰ ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﻳﮑﺴﺎﻥ 1ﻫﺴﺘﻨﺪ .ﭘﺲ ﮐﺪ ﺯﻳﺮ ﻣﻌﺘﺒﺮ ﺍﺳﺖ ﻭ ﺑﻪ ﺩﺭﺳﺘﻲ
ﮐﺎﺭ ﻣﻲﮐﻨﺪ:
;Answer answer
;cin >> answer
;"if (answer==TRUE) cout << "you said OK.
ﺑﻪ ﺍﻭﻟﻴﻦ ﺧﻂ ﮐﺪ ﻓﻮﻕ ﻧﮕﺎﻩ ﮐﻨﻴﺪ .ﺍﻳﻦ ﺧﻂ ﻣﻤﮑﻦ ﺍﺳﺖ ﮐﻤﻲ ﻋﺠﻴﺐ ﺑﻪ ﻧﻈﺮ ﺑﺮﺳﺪ:
;Answer answer
ﺍﻳﻦ ﺧﻂ ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ answerﺍﺯ ﻧﻮﻉ Answerﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ .ﺍﻭﻟﻴﻦ ﻗﺎﻧﻮﻥ ﺩﺭ
ﺑﺮﻧﺎﻣﻪﻫﺎﻱ C++ﺭﺍ ﺑﻪ ﺧﺎﻃﺮ ﺑﻴﺎﻭﺭﻳﺪ C++» :ﺑﻴﻦ ﺣﺮﻭﻑ ﮐﻮﭼﮏ ﻭ ﺑﺰﺭﮒ ﺗﻔﺎﻭﺕ ﻗﺎﻳﻞ
ﺍﺳﺖ« .ﭘﺲ Answerﺑﺎ answerﻣﺘﻔﺎﻭﺕ ﺍﺳﺖ Answer .ﺭﺍ ﺩﺭ ﺧﻂﻫﺎﻱ ﻗﺒﻠﻲ ﻳﮏ
ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ﺗﻌﺮﻳﻒ ﮐﺮﺩﻳﻢ ﻭ answerﺭﺍ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﺍﺯ ﻧﻮﻉ Answerﺍﺳﺖ .ﻳﻌﻨﻲ
answerﻣﺘﻐﻴﺮﻱ ﺍﺳﺖ ﮐﻪ ﻣﻲﺗﻮﺍﻧﺪ ﻳﮑﻲ ﺍﺯ ﻣﻘﺎﺩﻳﺮ YESﻳﺎ TRUEﻳﺎ OKﻳﺎ FALSEﻳﺎ
NOﺭﺍ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﻧﺤﻮۀ ﺍﻧﺘﺨﺎﺏ ﻧﺎﻡﻫﺎ ﺁﺯﺍﺩ ﺍﺳﺖ ﺍﻣﺎ ﺑﻴﺸﺘﺮ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺍﺯ ﺗﻮﺍﻓﻖ ﺯﻳﺮ ﺩﺭ
ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺸﺎﻥ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻨﺪ:
41 ﻓﺼﻞ دوم /اﻧﻮاع اﺻﻠﯽ
ﺯﻳﺮﺍ A+ﻭ A-ﻭ B+ﻭ B-ﻭ C+ﻭ C-ﻧﺎﻡﻫﺎﻱ ﻏﻴﺮﻣﻌﺘﺒﺮﻱ ﻫﺴﺘﻨﺪ ﭼﻮﻥ ﺩﺭ ﻧﺎﻡ ﺁﻥﻫﺎ ﺍﺯ
ﻧﺸﺎﻧﻪﻫﺎﻱ ﺭﻳﺎﺿﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ.
ﻋﻼﻭﻩ ﺑﺮ ﺍﻳﻦ ﺷﻤﺎﺭﺷﮕﺮﻫﺎﻱ ﻫﻢﻧﺎﻡ ﻧﺒﺎﻳﺪ ﺩﺭ ﻣﺤﺪﻭﺩﻩﻫﺎﻱ ﻣﺸﺘﺮﮎ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﻧﺪ.
ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺗﻌﺮﻳﻒﻫﺎﻱ ﺯﻳﺮ ﺭﺍ ﺩﺭ ﻧﻈﺮ ﺑﮕﻴﺮﻳﺪ:
}enum Score{A,B,C,D
}enum Group{AB,B,BC
ﺩﻭ ﺗﻌﺮﻳﻒ ﺑﺎﻻ ﻏﻴﺮﻣﺠﺎﺯ ﺍﺳﺖ ﺯﻳﺮﺍ ﺷﻤﺎﺭﺷﮕﺮ Bﺩﺭ ﻫﺮ ﺩﻭ ﺗﻌﺮﻳﻒ Scoreﻭ Group
ﺁﻣﺪﻩ ﺍﺳﺖ.
ﺁﺧﺮ ﺍﻳﻦ ﮐﻪ ﻧﺎﻡ ﺷﻤﺎﺭﺷﮕﺮﻫﺎ ﻧﺒﺎﻳﺪ ﺑﻪ ﻋﻨﻮﺍﻥ ﻧﺎﻡ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺩﻳﮕﺮ ﺩﺭ ﺟﺎﻫﺎﻱ ﺩﻳﮕﺮ
ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ .ﻣﺜﻼ:
}enum Score{A,B,C,D
;float B
;char c
ﺩﺭ ﺗﻌﺮﻳﻒﻫﺎﻱ ﺑﺎﻻ Bﻭ Cﺭﺍ ﻧﺒﺎﻳﺪ ﺑﻪ ﻋﻨﻮﺍﻥ ﻧﺎﻡ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺩﻳﮕﺮ ﺑﻪ ﮐﺎﺭ ﺑﺮﺩ ﺯﻳﺮﺍ ﺍﻳﻦ ﻧﺎﻡﻫﺎ
ﺩﺭ ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ Scoreﺑﻪ ﮐﺎﺭ ﺭﻓﺘﻪ ﺍﺳﺖ .ﭘﺲ ﺍﮔﺮ ﺍﻳﻦ ﺳﻪ ﺗﻌﺮﻳﻒ ﺩﺭ ﻳﮏ ﻣﺤﺪﻭﺩﻩ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 42
ﺑﺎﺷﻨﺪ ،ﺩﻭ ﺗﻌﺮﻳﻒ ﺁﺧﺮﻱ ﻏﻴﺮﻣﺠﺎﺯ ﺧﻮﺍﻫﺪ ﺑﻮﺩ .ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﺑﺮﺍﻱ ﺗﻮﻟﻴﺪ ﮐﺪ »ﺧﻮﺩ
ﻣﺴﺘﻨﺪ« ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ،ﻳﻌﻨﻲ ﮐﺪﻱ ﮐﻪ ﺑﻪ ﺭﺍﺣﺘﻲ ﺩﺭﮎ ﺷﻮﺩ ﻭ ﻧﻴﺎﺯ ﺑﻪ ﺗﻮﺿﻴﺤﺎﺕ ﺍﺿﺎﻓﻲ
ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﻣﺜﻼ ﺗﻌﺎﺭﻳﻒ ﺯﻳﺮ ﺧﻮﺩﻣﺴﺘﻨﺪ ﻫﺴﺘﻨﺪ ﺯﻳﺮﺍ ﺑﻪ ﺭﺍﺣﺘﻲ ﻧﺎﻡ ﻭ ﻧﻮﻉ ﮐﺎﺭﺑﺮﺩ ﻭ
ﻣﺤﺪﻭﺩۀ ﻣﻘﺎﺩﻳﺮﺷﺎﻥ ﺩﺭﮎ ﻣﻲﺷﻮﺩ:
enum }Color{RED,GREEN,BLUE,BLACK,ORANGE
enum }Time{SECOND,MINUTE,HOUR
enum }Date{DAY,MONTH,YEAR
enum }Language{C,DELPHI,JAVA,PERL
enum }Gender{MALE,FEMALE
ﺍﻣﺎ ﺍﮔﺮ ﻋﮑﺲ ﺍﻳﻦ ﻋﻤﻞ ﻣﻮﺭﺩ ﻧﻈﺮ ﺑﺎﺷﺪ ،ﻳﻌﻨﻲ ﺍﮔﺮ ﺑﺨﻮﺍﻫﻴﻢ ﻳﮏ ﻣﺘﻐﻴﺮ ﺻﺤﻴﺢ ﺭﺍ ﺑﺎ
ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺟﻤﻊ ﺑﺒﻨﺪﻳﻢ ﻭ ﺑﺨﻮﺍﻫﻴﻢ ﮐﻪ ﺣﺎﺻﻞ ﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﺎﺷﺪ ﻧﻪ ﻣﻤﻴﺰ
ﺷﻨﺎﻭﺭ ،ﭼﻪ ﺑﺎﻳﺪ ﺑﮑﻨﻴﻢ؟ ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ ﺍﺯ ﻋﻤﻠﮕﺮ ﺗﺒﺪﻳﻞ ﻧﻮﻉ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ .ﺍﻳﻦ ﺗﺒﺪﻳﻞ
ﺧﻮﺩﮐﺎﺭ ﻧﻴﺴﺖ ﺑﻠﮑﻪ ﮐﺎﻣﻼ ﺑﺎﻳﺪ ﺩﺳﺘﻲ ﺍﻧﺠﺎﻡ ﺷﻮﺩ ﻭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ،ﺧﻮﺩ ﺑﺎﻳﺪ ﻣﺮﺍﻗﺐ ﺍﻳﻦ
ﻋﻤﻞ ﺑﺎﺷﺪ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺭﺍ ﺑﻪ ﻧﻮﻉ ﺻﺤﻴﺢ ﺗﺒﺪﻳﻞ
ﮐﻨﻴﻢ ﺍﺯ ﻋﺒﺎﺭﺕ )( intﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ.
ﻣﺜﺎﻝﻫﺎﻱ ﺯﻳﺮ ﺗﺒﺪﻳﻞ ﻧﻮﻉ ﻭ ﮔﺴﺘﺮﺵ ﻧﻮﻉ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ.
ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺘﻐﻴﺮ vﺍﺯ ﻧﻮﻉ doubleﻭ ﺑﺎ ﻣﻘﺪﺍﺭ 1234.987ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ.
ﻫﻤﭽﻨﻴﻦ ﻣﺘﻐﻴﺮ nﺍﺯ ﻧﻮﻉ intﺗﻌﺮﻳﻒ ﮔﺸﺘﻪ ﺍﺳﺖ .ﺩﺭ ﺧﻂ ﭘﻨﺠﻢ ﺍﺯ ﮐﺪ ﺑﺎﻻ ﺍﺯ ﺗﺒﺪﻳﻞ ﻧﻮﻉ
ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ:
;)n = int(v
ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺩﺳﺘﻮﺭ ،ﻣﻘﺪﺍﺭ vﺍﺑﺘﺪﺍ ﺑﻪ ﻧﻮﻉ intﺗﺒﺪﻳﻞ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﺍﻳﻦ
ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ nﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺧﺮﻭﺟﻲ ﺑﺮﻧﺎﻣﻪ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻭﻗﺘﻲ ﺍﺯ ﻋﻤﻠﮕﺮ )(int
ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ ،ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ »ﺑﺮﻳﺪﻩ« ﻣﻲﺷﻮﺩ ،ﮔﺮﺩ ﻧﻤﻲﺷﻮﺩ .ﻳﻌﻨﻲ ﻗﺴﻤﺖ ﺍﻋﺸﺎﺭﻱ
ﻋﺪﺩ ﺑﻪ ﻃﻮﺭ ﮐﺎﻣﻞ ﺣﺬﻑ ﻣﻲﺷﻮﺩ ﻭ ﻓﻘﻂ ﻗﺴﻤﺖ ﺻﺤﻴﺢ ﺁﻥ ﺑﺎﻗﻲ ﻣﻲﻣﺎﻧﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻭﻗﺘﻲ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 44
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ nﺍﺯ ﻣﻘﺪﺍﺭ ﺻﺤﻴﺢ 22ﺑﻪ ﻣﻘﺪﺍﺭ ﺍﻋﺸﺎﺭﻱ 22.0ﮔﺴﺘﺮﺵ
ﻣﻲﻳﺎﺑﺪ ﻭ ﺳﭙﺲ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﺎ ﻣﻘﺪﺍﺭ ﻗﺒﻠﻲ pﺟﻤﻊ ﻣﻲﺷﻮﺩ .ﺣﺎﺻﻞ ﻳﮏ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ
ﺍﺳﺖ.
;double y=x ;cout << " double y = " << y << endl
;return 0
}
char c = A
short k = 65
int m = 65
long n = 65
float x = 65
double y = 65
ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﺍﺑﺘﺪﺍ ﻣﺘﻐﻴﺮ cﺍﺯ ﻧﻮﻉ charﺗﻌﺮﻳﻒ ﺷﺪﻩ ﻭ ﮐﺎﺭﺍﮐﺘﺮ ' 'Aﺩﺭ ﺁﻥ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ
ﺍﺳﺖ .ﺳﭙﺲ ﻣﻘﺪﺍﺭ cﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ kﮐﻪ ﺍﺯ ﻧﻮﻉ shortﺍﺳﺖ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ .ﭼﻮﻥ ﻧﻮﻉ k
ﺑﺎﻻﺗﺮ ﺍﺯ ﻧﻮﻉ cﺍﺳﺖ ،ﭘﺲ ﻣﻘﺪﺍﺭ cﺑﻪ ﻧﻮﻉ shortﮔﺴﺘﺮﺵ ﻣﻲﻳﺎﺑﺪ ﻭ ﻣﻘﺪﺍﺭ 65ﮐﻪ
ﻣﻌﺎﺩﻝ ﻋﺪﺩﻱ ﮐﺎﺭﺍﮐﺘﺮ ' 'Aﺍﺳﺖ ﺩﺭﻭﻥ kﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ.
ﺩﺭ ﺧﻂ ﺑﻌﺪﻱ ،ﻣﻘﺪﺍﺭ kﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ mﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ m .ﺍﺯ ﻧﻮﻉ intﺍﺳﺖ ﮐﻪ ﻧﻮﻉ
ﺑﺎﻻﺗﺮﻱ ﺍﺯ shortﻣﻲﺑﺎﺷﺪ .ﭘﺲ ﻣﻘﺪﺍﺭ kﺑﻪ intﮔﺴﺘﺮﺵ ﻣﻲﻳﺎﺑﺪ ﻭ ﺍﻳﻦ ﻣﻘﺪﺍﺭ
ﮔﺴﺘﺮﺵﻳﺎﻓﺘﻪ ﺩﺭﻭﻥ mﻧﻬﺎﺩﻩ ﻣﻲﺷﻮﺩ.
ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﺩﺭ ﺧﻄﻮﻁ ﺑﻌﺪﻱ ﻣﻘﺪﺍﺭ mﺑﻪ ﻧﻮﻉ longﮔﺴﺘﺮﺵ ﻳﺎﻓﺘﻪ ﻭ ﺩﺭﻭﻥ
nﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﻣﻘﺪﺍﺭ nﻧﻴﺰ ﺑﻪ ﻧﻮﻉ floatﮔﺴﺘﺮﺵ ﻳﺎﻓﺘﻪ ﻭ ﺩﺭﻭﻥ xﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ.
ﻣﻘﺪﺍﺭ xﻧﻴﺰ ﺑﻪ ﻧﻮﻉ doubleﮔﺴﺘﺮﺵ ﻣﻲﻳﺎﺑﺪ ﻭ ﺩﺭﻭﻥ yﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ
ﻣﻘﺪﺍﺭ xﻭ yﺩﺭ ﺧﺮﻭﺟﻲ ﺑﻪ ﺟﺎﻱ ﺁﻥ ﮐﻪ 65.0ﺑﺎﺷﺪ ﺑﻪ ﺷﮑﻞ 65ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ .ﺍﻳﻦ
ﻣﻘﺪﺍﺭ ،ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﻧﻴﺴﺖ ﺍﻣﺎ ﭼﻮﻥ ﻗﺴﻤﺖ ﺍﻋﺸﺎﺭﻱ ﺁﻥ ﺻﻔﺮ ﺍﺳﺖ ،ﺍﻋﺸﺎﺭ ﺣﺬﻑ
ﺷﺪﻩ ﻭ 65ﺗﻨﻬﺎ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ.
ﺗﻮﺳﻂ ﮐﺎﻣﭙﺎﻳﻠﺮ ﮐﺸﻒ ﻣﻲﺷﻮﻧﺪ »ﺧﻄﺎﻱ ﺯﻣﺎﻥ ﮐﺎﻣﭙﺎﻳﻞ« ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﻧﺪ ﻭ ﺑﻪ ﺭﺍﺣﺘﻲ
ﻣﻲﺗﻮﺍﻥ ﺁﻥﻫﺎ ﺭﺍ ﺭﻓﻊ ﻧﻤﻮﺩ .ﺍﻣﺎ ﺧﻄﺎﻫﺎﻱ ﺩﻳﮕﺮﻱ ﻧﻴﺰ ﻭﺟﻮﺩ ﺩﺍﺭﻧﺪ ﮐﻪ ﮐﺸﻒ ﺁﻥﻫﺎ ﺑﻪ
ﺭﺍﺣﺘﻲ ﻣﻤﮑﻦ ﻧﻴﺴﺖ ﻭ ﮐﺎﻣﭙﺎﻳﻠﺮ ﻧﻴﺰ ﭼﻴﺰﻱ ﺭﺍﺟﻊ ﺑﻪ ﺁﻥ ﻧﻤﻲﺩﺍﻧﺪ .ﺑﻪ ﺍﻳﻦ ﺧﻄﺎﻫﺎ »ﺧﻄﺎﻱ
ﺯﻣﺎﻥ ﺍﺟﺮﺍ« ﻣﻲﮔﻮﻳﻨﺪ .ﺑﺮﺧﻲ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺳﺒﺐ ﻣﻲﺷﻮﻧﺪ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻃﻮﺭ
ﮐﺎﻣﻞ ﻣﺘﻮﻗﻒ ﺷﻮﺩ ﻭ ﺍﺯ ﮐﺎﺭ ﺑﻴﻔﺘﺪ .ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ ﻣﺘﻮﺟﻪ ﻣﻲﺷﻮﻳﻢ ﮐﻪ ﺧﻄﺎﻳﻲ ﺭﺥ ﺩﺍﺩﻩ
ﺍﺳﺖ ﻭ ﺩﺭ ﺻﺪﺩ ﮐﺸﻒ ﻭ ﺭﻓﻊ ﺁﻥ ﺑﺮﻣﻲﺁﻳﻴﻢ .ﺑﺮﺧﻲ ﺩﻳﮕﺮ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ،ﺑﺮﻧﺎﻣﻪ
ﺭﺍ ﺍﺯ ﮐﺎﺭ ﻧﻤﻲﺍﻧﺪﺍﺯﻧﺪ ﺑﻠﮑﻪ ﺑﺮﻧﺎﻣﻪ ﻫﻤﭽﻨﺎﻥ ﮐﺎﺭ ﻣﻲﮐﻨﺪ ﺍﻣﺎ ﭘﺎﺳﺦﻫﺎﻱ ﻋﺠﻴﺐ ﻭ ﻧﺎﺩﺭﺳﺖ
ﻣﻲﺩﻫﺪ .ﺍﻳﻦ ﺑﺪﺗﺮﻳﻦ ﻧﻮﻉ ﺧﻄﺎﺳﺖ ﺯﻳﺮﺍ ﺩﺭ ﺣﺎﻻﺕ ﺧﺎﺻﻲ ﺭﺥ ﻣﻲﺩﻫﺪ ﻭ ﮔﺎﻫﻲ ﺳﺒﺐ
ﮔﻴﺞ ﺷﺪﻥ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﻣﻲﮔﺮﺩﺩ .ﺩﺭ ﺑﺨﺶﻫﺎﻱ ﺑﻌﺪﻱ ﺑﺮﺧﻲ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺭﺍﻳﺞ ﺯﻣﺎﻥ ﺍﺟﺮﺍ
ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻴﻢ ﺗﺎ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺘﺎﻥ ﺍﺯ ﺁﻥﻫﺎ ﭘﺮﻫﻴﺰ ﮐﻨﻴﺪ؛ ﺩﺳﺖ ﮐﻢ ﺍﮔﺮ ﺑﺎ ﭘﺎﺳﺦﻫﺎﻱ
ﻏﻴﺮﻣﻨﺘﻈﺮﻩ ﻭ ﻏﻠﻂ ﻣﻮﺍﺟﻪ ﺷﺪﻳﺪ ،ﻣﺤﻞ ﺭﺥ ﺩﺍﺩﻥ ﺧﻄﺎ ﺭﺍ ﺭﺍﺣﺖﺗﺮ ﭘﻴﺪﺍ ﮐﻨﻴﺪ.
2 – 14ﺳﺮﺭﻳﺰﻱ 1ﻋﺪﺩﻱ
ﻧﻮﻉ ﺻﺤﻴﺢ longﻳﺎ ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ doubleﻣﺤﺪﻭﺩۀ ﻭﺳﻴﻌﻲ ﺍﺯ ﺍﻋﺪﺍﺩ ﺭﺍ
ﻣﻲﺗﻮﺍﻧﻨﺪ ﻧﮕﻬﺪﺍﺭﻱ ﮐﻨﻨﺪ .ﺑﻪ ﺑﻴﺎﻥ ﺳﺎﺩﻩﺗﺮ ،ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﺍﺯ ﻧﻮﻉ longﻳﺎ doubleﺑﺎﺷﺪ،
ﮔﻨﺠﺎﻳﺶ ﺯﻳﺎﺩﻱ ﺩﺍﺭﺩ .ﺍﻣﺎ ﺣﺎﻓﻆۀ ﺭﺍﻳﺎﻧﻪﻫﺎ ﻣﺘﻨﺎﻫﻲ ﺍﺳﺖ .ﻳﻌﻨﻲ ﻫﺮ ﻗﺪﺭ ﻫﻢ ﮐﻪ ﻳﮏ ﻣﺘﻐﻴﺮ
ﮔﻨﺠﺎﻳﺶ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ،ﺑﺎﻻﺧﺮﻩ ﻣﻘﺪﺍﺭﻱ ﻫﺴﺖ ﮐﻪ ﺍﺯ ﮔﻨﺠﺎﻳﺶ ﺁﻥ ﻣﺘﻐﻴﺮ ﺑﻴﺸﺘﺮ ﺑﺎﺷﺪ .ﺍﮔﺮ
ﺳﻌﻲ ﮐﻨﻴﻢ ﺩﺭ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻘﺪﺍﺭﻱ ﻗﺮﺍﺭ ﺩﻫﻴﻢ ﮐﻪ ﺍﺯ ﮔﻨﺠﺎﻳﺶ ﺁﻥ ﻣﺘﻐﻴﺮ ﻓﺮﺍﺗﺮ ﺑﺎﺷﺪ ،ﻣﺘﻐﻴﺮ
»ﺳﺮﺭﻳﺰ« ﻣﻲﺷﻮﺩ .ﻣﺜﻞ ﻳﮏ ﻟﻴﻮﺍﻥ ﺁﺏ ﮐﻪ ﺍﮔﺮ ﺑﻴﺶ ﺍﺯ ﮔﻨﺠﺎﻳﺶ ﺁﻥ ﺩﺭ ﻟﻴﻮﺍﻥ ﺁﺏ ﺑﺮﻳﺰﻳﻢ،
ﺳﺮﺭﻳﺰ ﻣﻲﺷﻮﺩ .ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ ﻣﻲﮔﻮﻳﻴﻢ ﮐﻪ ﺧﻄﺎﻱ ﺳﺮﺭﻳﺰﻱ ﺭﺥ ﺩﺍﺩﻩ ﺍﺳﺖ.
1 – Overflow
47 اﻧﻮاع اﺻﻠﯽ/ ﻓﺼﻞ دوم
ﻧﻤﻲﺗﻮﺍﻧﺪ ﺑﻴﺸﺘﺮ،ﺍﻳﻦ ﻣﺜﺎﻝ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﺭﺍﻳﺎﻧﻪﺍﻱ ﻛﻪ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺍﺟﺮﺍ ﻛﺮﺩﻩ ﺍﺳﺖ
. ﺑﻪ ﻃﻮﺭ ﺻﺤﻴﺢ ﺿﺮﺏ ﻛﻨﺪ1000 ﺭﺍ ﺑﺎ1,000,000,000ﺍﺯ
x = 1e+24
x = inf
ﻣﺜﺎﻝ ﺑﺎﻻ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻳﻦ ﺭﺍﻳﺎﻧﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ xﺭﺍ ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ 1000ﺑﻴﺶ ﺍﺯ ﺳﻪ ﺑﺎﺭ
ﻣﺠﺬﻭﺭ ﮐﻨﺪ .ﺁﺧﺮﻳﻦ ﺧﺮﻭﺟﻲ ﻳﻌﻨﻲ infﻧﻤﺎﺩﻱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻣﻌﻨﺎﻱ ﺑﻲﻧﻬﺎﻳﺖ ﻣﻲﺑﺎﺷﺪ
)ﺍﻳﻦ ﻧﻤﺎﺩ ﻣﺨﻔﻒ infinityﺑﻪ ﻣﻌﻨﺎﻱ ﺑﻲﺍﻧﺘﻬﺎ ﺍﺳﺖ(.
ﺑﻪ ﺗﻔﺎﻭﺕ ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩ ﺻﺤﻴﺢ ﻭ ﺳﺮﺭﻳﺰﻱ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺗﻮﺟﻪ ﮐﻨﻴﺪ .ﻭﻗﺘﻲ ﻳﮏ
ﻋﺪﺩ ﺻﺤﻴﺢ ﺳﺮﺭﻳﺰ ﺷﻮﺩ ،ﻋﺪﺩ ﺳﺮﺭﻳﺰ ﺷﺪﻩ ﺑﻪ ﻳﮏ ﻣﻘﺪﺍﺭ ﻣﻨﻔﻲ »ﮔﺮﺩﺍﻧﻴﺪﻩ« ﻣﻲﺷﻮﺩ ﺍﻣﺎ
ﻭﻗﺘﻲ ﻳﮏ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺳﺮﺭﻳﺰ ﺷﻮﺩ ،ﻧﻤﺎﺩ infﺑﻪ ﻣﻌﻨﺎﻱ ﺑﻲﻧﻬﺎﻳﺖ ﺭﺍ ﺑﻪ ﺩﺳﺖ
ﻣﻲﺩﻫﺪ ،ﻧﺸﺎﻧﻪﺍﻱ ﻣﺨﺘﺼﺮ ﻭ ﻣﻔﻴﺪ.
1
2 – 15ﺧﻄﺎﻱ ﮔﺮﺩ ﮐﺮﺩﻥ
ﺧﻄﺎﻱ ﮔﺮﺩ ﻛﺮﺩﻥ ﻧﻮﻉ ﺩﻳﮕﺮﻱ ﺍﺯ ﺧﻄﺎﺳﺖ ﻛﻪ ﺍﻏﻠﺐ ﻭﻗﺘﻲ ﺭﺍﻳﺎﻧﻪﻫﺎ ﺭﻭﻱ ﺍﻋﺪﺍﺩ
ﺣﻘﻴﻘﻲ ﻣﺤﺎﺳﺒﻪ ﻣﻲﻛﻨﻨﺪ ،ﺭﺥ ﻣﻲﺩﻫﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﻋﺪﺩ 1/3ﻣﻤﻜﻦ ﺍﺳﺖ ﺑﻪ ﺻﻮﺭﺕ
ﻧﻴﺴﺖ .ﺑﻪ ﺍﻳﻦ ﺍﺧﺘﻼﻑ ،ﺧﻄﺎﻱ ﮔﺮﺩ 0.333333ﺫﺧﻴﺮﻩ ﺷﻮﺩ ﻛﻪ ﺩﻗﻴﻘﺎ ﻣﻌﺎﺩﻝ 1/3
ﻛﺮﺩﻥ ﻣﻲﮔﻮﻳﻨﺪ .ﺍﻳﻦ ﺧﻄﺎ ﺍﺯ ﺁﻥﺟﺎ ﻧﺎﺷﻲ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻋﺪﺍﺩﻱ ﻣﺜﻞ 1/3ﻣﻘﺪﺍﺭ ﺩﻗﻴﻖ
ﻧﺪﺍﺭﻧﺪ ﻭ ﺭﺍﻳﺎﻧﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺭﺍ ﭘﻴﺪﺍ ﮐﻨﺪ ،ﭘﺲ ﻧﺰﺩﻳﮏﺗﺮﻳﻦ ﻋﺪﺩ ﻗﺎﺑﻞ ﻣﺤﺎﺳﺒﻪ ﺭﺍ
ﺑﻪ ﺟﺎﻱ ﭼﻨﻴﻦ ﺍﻋﺪﺍﺩﻱ ﻣﻨﻈﻮﺭ ﻣﻲﮐﻨﺪ .ﺩﺭ ﺑﻌﻀﻲ ﺣﺎﻻﺕ ،ﺍﻳﻦ ﺧﻄﺎﻫﺎ ﻣﻲﺗﻮﺍﻧﺪ ﻣﺸﻜﻼﺕ
ﺣﺎﺩﻱ ﺭﺍ ﺍﻳﺠﺎﺩ ﻛﻨﺪ.
1 – Round-off
49 ﻓﺼﻞ دوم /اﻧﻮاع اﺻﻠﯽ
;cout << "z = " << z << endl // z = 3(1/3) - 1
;"if (z == 0) cout << "z == 0.\n
;"else cout << "z does not equal 0.\n //z != 0
;return 0
}
x = 333.333
y = 0.333333
z = -5.68434e-14
z does not equal 0.
ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺍﻳﻦ ﺷﮑﻞ ﺍﺳﺖ ﮐﻪ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ xﺑﺮﺍﺑﺮ ﺑﺎ 1000/3ﻳﻌﻨﻲ 333 1ﺍﺳﺖ.
3
ﺳﭙﺲ ﻗﺴﻤﺖ ﺻﺤﻴﺢ xﻳﻌﻨﻲ 333ﺍﺯ ﺁﻥ ﮐﺴﺮ ﻣﻲﺷﻮﺩ ﻭ ﺣﺎﺻﻞ ﮐﻪ ﺑﺮﺍﺑﺮ ﺑﺎ 1/3ﺍﺳﺖ
ﺩﺭ yﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺣﺎﻻ yﺩﺭ 3ﺿﺮﺏ ﻣﻲﺷﻮﺩ ﺗﺎ ﺣﺎﺻﻞ ﺑﺮﺍﺑﺮ ﺑﺎ 1ﺷﻮﺩ .ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺍﺯ
1ﮐﻢ ﻣﻲﺷﻮﺩ ﻭ ﺣﺎﺻﻞ ﺩﺭ zﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺍﻧﺘﻈﺎﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ zﺻﻔﺮ ﺑﺎﺷﺪ ﺍﻣﺎ ﭘﺎﺳﺦ
ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻣﺎ ﻣﻲﮔﻮﻳﺪ ﮐﻪ zﺻﻔﺮ ﻧﻴﺴﺖ!
ﺍﺷﮑﺎﻝ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺩﺭ ﮐﺠﺎﺳﺖ؟ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ ﮐﻪ ﺩﺭﺳﺖ ﺍﺳﺖ ،ﭘﺲ ﺟﺎﻳﻲ ﺩﺭ
ﺍﺳﺖ .ﺭﺍﻳﺎﻧﻪ ﻣﻘﺪﺍﺭ 1/3ﺭﺍ ﺑﺮﺍﺑﺮ ﺑﺎ ﻣﺤﺎﺳﺒﺎﺕ ﺑﺎﻳﺪ ﻏﻠﻂ ﺑﺎﺷﺪ .ﻣﺸﮑﻞ ﺩﺭ ﻣﻘﺪﺍﺭ y
0.333333ﻣﺤﺎﺳﺒﻪ ﻧﻤﻮﺩﻩ ﺍﺳﺖ ،ﺣﺎﻝ ﺁﻥ ﮐﻪ ﻣﻲﺩﺍﻧﻴﻢ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺩﻗﻴﻘﺎ ﺑﺮﺍﺑﺮ ﺑﺎ 1/3
ﻧﻴﺴﺖ .ﺍﻳﻦ ﺧﻄﺎ ﺍﺯ ﺁﻥ ﺟﺎ ﻧﺎﺷﻲ ﻣﻲﺷﻮﺩ ﮐﻪ ﺭﺍﻳﺎﻧﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ﺩﻗﻴﻖ 1/3ﺭﺍ ﭘﻴﺪﺍ ﮐﻨﺪ
ﭼﻮﻥ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﻪ ﺗﻌﺪﺍﺩ ﻧﺎﻣﺘﻨﺎﻫﻲ ﺍﻋﺸﺎﺭ 3ﺩﺍﺭﺩ ،ﭘﺲ ﺭﺍﻳﺎﻧﻪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺭﺍ ﮔﺮﺩ ﻣﻲﮐﻨﺪ ﻭ
ﻣﻘﺪﺍﺭ »ﻧﺴﺒﺘﺎ ﺩﺭﺳﺖ« 0.333333ﺭﺍ ﻣﻲﺩﻫﺪ .ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺕ ﺑﻌﺪﻱ ﺍﺳﺘﻔﺎﺩﻩ
ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﭼﻮﻥ ﺩﻗﻴﻖ ﻧﻴﺴﺖ ،ﭘﺎﺳﺦﻫﺎﻱ ﺑﻌﺪﻱ ﻧﻴﺰ ﺑﻪ ﺗﻨﺎﺳﺐ ﺑﺮ ﻣﻴﺰﺍﻥ ﺧﻄﺎ ﻣﻲﺍﻓﺰﺍﻳﺪ.
ﻧﺘﻴﺠﻪ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻣﻘﺪﺍﺭ zﺻﻔﺮ ﻧﻤﻲﺷﻮﺩ ،ﻫﺮﭼﻨﺪ ﮐﻪ ﺑﺴﻴﺎﺭ ﻧﺰﺩﻳﮏ ﺑﻪ ﺻﻔﺮ ﺑﺎﺷﺪ.
ﻣﺜﺎﻝ ﺑﺎﻻ ﻧﮑﺖۀ ﻣﻬﻤﻲ ﺭﺍ ﺩﺭ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ:
»ﻫﻴﭻﮔﺎﻩ ﺍﺯ ﻣﺘﻐﻴﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺑﺮﺍﻱ ﻣﻘﺎﻳﺴﻪ ﺑﺮﺍﺑﺮﻱ ﺍﺳﺘﻔﺎﺩﻩ ﻧﮑﻨﻴﺪ« ﺯﻳﺮﺍ ﺩﺭ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﻤﻴﺰ
ﺷﻨﺎﻭﺭ ﺧﻄﺎﻱ ﮔﺮﺩ ﮐﺮﺩﻥ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ﭘﺎﺳﺦ ﺑﺎ ﺁﻥ ﭼﻪ ﻣﻮﺭﺩ ﻧﻈﺮ ﺷﻤﺎﺳﺖ ﻣﺘﻔﺎﻭﺕ
ﺑﺎﺷﺪ .ﺩﺭ ﺣﺎﻟﺖ ﺑﺎﻻ ﮔﺮ ﭼﻪ ﻣﻘﺪﺍﺭ zﺑﺴﻴﺎﺭ ﻧﺰﺩﻳﮏ ﺻﻔﺮ ﺍﺳﺖ ،ﺍﻣﺎ ﺭﺍﻳﺎﻧﻪ ﻫﻤﻴﻦ ﻣﻘﺪﺍﺭ
ﮐﻮﭼﮏ ﺭﺍ ﺻﻔﺮ ﻧﻤﻲﺩﺍﻧﺪ .ﭘﺲ ﻣﻘﺎﻳﺲۀ ﺑﺮﺍﺑﺮﻱ ﺷﮑﺴﺖ ﻣﻲﺧﻮﺭﺩ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 50
ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺿﺮﺍﻳﺐ aﻭ bﻭ cﺭﺍ ﺑﺮﺍﻱ ﻣﻌﺎﺩﻝۀ ax 2 + bx + c = 0ﻣﻲﮔﻴﺮﺩ ﻭ ﺳﭙﺲ
ﺳﻌﻲ ﻣﻲﮐﻨﺪ ﺭﻳﺸﻪﻫﺎﻱ x1ﻭ x2ﺭﺍ ﭘﻴﺪﺍ ﮐﻨﺪ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭ ﺳﻪ ﻣﺘﻐﻴﺮ aﻭ bﻭ cﺍﺯ ﻧﻮﻉ
floatﺗﻌﺮﻳﻒ ﺷﺪﻩﺍﻧﺪ ﺗﺎ ﺑﺘﻮﺍﻧﻨﺪ ﻣﻘﺎﺩﻳﺮ ﺍﻋﺸﺎﺭﻱ ﺭﺍ ﻫﻢ ﺍﺯ ﻭﺭﻭﺩﻱ ﺑﮕﻴﺮﻧﺪ .ﺧﻂ ﻫﺸﺘﻢ
ﺗﺎ ﺳﻴﺰﺩﻫﻢ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﻘﺎﺩﻳﺮ aﻭ bﻭ cﺭﺍ ﺩﺭﻳﺎﻓﺖ ﻣﻲﮐﻨﻨﺪ )ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮ
ﺧﺎﺹ ' '\tﺩﺭ ﭘﻴﻐﺎﻡﻫﺎﻱ ﺧﺮﻭﺟﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺗﺎ ﻗﺒﻞ ﺍﺯ ﻫﺮ ﻭﺭﻭﺩﻱ ،ﻫﻔﺖ ﺟﺎﻱ
ﺧﺎﻟﻲ ﻗﺮﺍﺭ ﺑﮕﻴﺮﺩ .ﻭﻟﻲ ﺧﻮﺩ ﺣﺮﻑ tﭼﺎﭖ ﻧﻤﻲﺷﻮﺩ( .ﭘﺲ ﺍﺯ ﺩﺭﻳﺎﻓﺖ ﺿﺮﺍﻳﺐ ،ﻳﮏ ﺑﺎﺭ
ﺩﻳﮕﺮ ﺷﮑﻞ ﮐﻠﻲ ﻣﻌﺎﺩﻟﻪﺍﻱ ﮐﻪ ﻣﻮﺭﺩ ﻧﻈﺮ ﮐﺎﺭﺑﺮ ﺑﻮﺩﻩ ﺍﺳﺖ ﭼﺎﭖ ﻣﻲﺷﻮﺩ.
ﺗﺸﮑﻴﻞ ﺷﺪﻩ ﺍﺳﺖ .ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ b 2 − 4ac ﺩﺭ ﺧﻂ ﻳﺎﺯﺩﻫﻢ ،ﺭﺍﺑﻂۀ ﺩﻟﺘﺎ ﻳﻌﻨﻲ
ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮﻱ ﮐﻪ dﻧﺎﻡ ﺩﺍﺭﺩ ﻭ ﺍﺯ ﻧﻮﻉ floatﺍﺳﺖ ،ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ .ﺩﺭ ﺧﻂ ﺑﻌﺪﻱ ﻣﻘﺪﺍﺭ
ﺟﺬﺭ ﺩﻟﺘﺎ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ )( sqrtﻣﺤﺎﺳﺒﻪ ﺷﺪﻩ ﺍﺳﺖ .ﺗﺎﺑﻊ )( sqrtﺟﺬﺭ ﻋﺪﺩﻱ
ﮐﻪ ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰﻫﺎﻳﺶ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﺭﺍ ﺑﻪ ﺩﺳﺖ ﻣﻲﺩﻫﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﺭ ﺳﺮﻓﺎﻳﻞ ><cmath
ﺗﻌﺮﻳﻒ ﺷﺪﻩ .ﭘﺲ ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﺓ > #include<cmathﺑﻪ ﺍﺑﺘﺪﺍﻱ ﺑﺮﻧﺎﻣﻪ
ﺍﻓﺰﻭﺩﻩ ﺷﺪﻩ ﺍﺳﺖ .ﻣﻘﺪﺍﺭ ﺟﺬﺭ ﺩﻟﺘﺎ ﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮﻱ ﺑﻪ ﻧﺎﻡ sqrtdﻧﮕﻬﺪﺍﺭﻱ ﺷﺪﻩ ﺗﺎ
ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﺩﺭ ﺧﻄﻮﻁ ﺑﻌﺪﻱ ﻣﻘﺎﺩﻳﺮ x1ﻭ x2ﺑﻪ ﺩﺳﺖ ﺁﻳﺪ.
ﺩﺭ ﭼﻬﺎﺭ ﺧﻂ ﺁﺧﺮ ﺑﺮﻧﺎﻣﻪ ،ﻣﻘﺎﺩﻳﺮ x1ﻭ x2ﮐﻪ ﺑﺪﺳﺖ ﺁﻣﺪﻩ ﺍﺳﺖ ﺩﻭﺑﺎﺭﻩ ﺩﺭ
ﻣﻌﺎﺩﻟﻪ ﺟﺎﻱﮔﺬﺍﺭﻱ ﻣﻲﺷﻮﺩ ﺗﺎ ﺑﺮﺭﺳﻲ ﺷﻮﺩ ﮐﻪ ﺁﻳﺎ ﺟﻮﺍﺏ ﻣﻌﺎﺩﻟﻪ ﺻﻔﺮ ﻣﻲﺷﻮﺩ ﻳﺎ ﺧﻴﺮ .ﺑﻪ
ﺍﻳﻦ ﻭﺳﻴﻠﻪ ﺻﺤﺖ ﭘﺎﺳﺦﻫﺎﻱ x1ﻭ x2ﺗﺤﻘﻴﻖ ﻣﻲﺷﻮﺩ.
ﺧﺮﻭﺟﻲ ﺯﻳﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ،ﻣﻌﺎﺩﻝۀ 2 x 2 + 1x − 3 = 0ﺭﺍ ﺣﻞ ﮐﺮﺩﻩ ﺍﺳﺖ:
Enter the coeficients of a quadratic equation:
a: 2
b: 1
c: -3
The equation is: 2*x*x + 1*x + -3 = 0
The solutions are:
x1 = 1
x2 = -1.5
check:
a*x1*x1 + b*x1 + c = 0
a*x2*x2 + b*x2 + c = 0
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 52
ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﭘﺎﺳﺦﻫﺎﻱ x1=1ﻭ x2=-1.5ﺭﺍ ﭘﻴﺪﺍ ﮐﺮﺩﻩ ﺍﺳﺖ ﻭ ﺁﺯﻣﻮﻥ ﭘﺎﺳﺦ ﻧﻴﺰ
ﺟﻮﺍﺏ ﺻﻔﺮ ﺩﺍﺩﻩ ﺍﺳﺖ .ﺧﺮﻭﺟﻲ ﺩﻳﮕﺮﻱ ﺍﺯ ﺑﺮﻧﺎﻣﻪ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺗﻼﺵ ﮐﺮﺩﻩ
ﺭﺍ ﺣﻞ ﮐﻨﺪ ﻭﻟﻲ ﺷﮑﺴﺖ ﻣﻲﺧﻮﺭﺩ: 2 x 2 + 8.001x + 8.002 = 0 ﻣﻌﺎﺩﻟﻪ
Enter the coeficients of a quadratic equation:
a: 2
b: 8.001
c: 8.002
The equation is: 2*x*x + 8.001*x + 8.002 = 0
The solutions are:
x1 = -1.9995
x2 = -2.00098
check:
a*x1*x1 + b*x1 + c = 5.35749e-11
a*x2*x2 + b*x2 + c = -2.96609e-1
ﻣﻘﺪﺍﺭ x1ﮐﻪ ﺩﺭ ﺍﺟﺮﺍﻱ ﺑﺎﻻ ﺑﻪ ﺩﺳﺖ ﺁﻣﺪﻩ ،ﺩﺭ ﺁﺯﻣﻮﻥ ﺷﺮﮐﺖ ﮐﺮﺩﻩ ﻭ ﭘﺎﺳﺨﻲ ﺑﺴﻴﺎﺭ
ﻧﺰﺩﻳﮏ ﺑﻪ ﺻﻔﺮ ﺩﺍﺩﻩ ﺍﺳﺖ .ﺍﻣﺎ ﻣﻘﺪﺍﺭ x2ﺩﺭ ﺁﺯﻣﻮﻥ ﺷﮑﺴﺖ ﺧﻮﺭﺩﻩ ﺯﻳﺮﺍ ﺟﻮﺍﺏ ﻣﻌﺎﺩﻟﻪ
ﺑﻪ ﺍﺯﺍﻱ ﺁﻥ ﺻﻔﺮ ﻧﻴﺴﺖ .ﭼﻪ ﭼﻴﺰﻱ ﺑﺎﻋﺚ ﺷﺪﻩ ﺗﺎ ﻣﻌﺎﺩﻟﻪ ﭘﺎﺳﺦ ﻏﻠﻂ ﺑﺪﻫﺪ؟ ﺟﻮﺍﺏ ﺑﺎﺯ ﻫﻢ
ﺩﺭ ﺧﻄﺎﻱ ﮔﺮﺩ ﮐﺮﺩﻥ ﺍﺳﺖ x2 .ﻳﮏ ﭘﺎﺳﺦ ﮔﺮﺩﺷﺪﻩ ﺍﺳﺖ ﻧﻪ ﻳﮏ ﭘﺎﺳﺦ ﺩﻗﻴﻖ .ﺍﻳﻦ ﭘﺎﺳﺦ
ﮔﺮﺩﺷﺪﻩ ﺩﻭﺑﺎﺭﻩ ﺩﺭ ﻳﮏ ﻣﺤﺎﺳﺒﻪ ﺩﻳﮕﺮ ﺷﺮﮐﺖ ﻣﻲﮐﻨﺪ .ﭘﺎﺳﺦ ﺍﻳﻦ ﻣﺤﺎﺳﺒﻪ ﻫﻢ ﮔﺮﺩﺷﺪﻩ
ﺍﺳﺖ .ﭘﺲ ﺍﻧﺤﺮﺍﻑ ﺍﺯ ﺟﻮﺍﺏ ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ ﻭ ﻧﺘﻴﺠﻪﺍﻱ ﺩﻭﺭ ﺍﺯ ﺍﻧﺘﻈﺎﺭ ﺑﻪ ﺑﺎﺭ ﻣﻲﺁﻭﺭﺩ.
ﺩﺭ ﺍﻳﻦ ﺍﺟﺮﺍ ﺳﻌﻲ ﺷﺪﻩ ﺗﺎ ﻣﻌﺎﺩﻟﻪ 1x 2 + 2 x + 3 = 0ﺣﻞ ﺷﻮﺩ .ﺍﻳﻦ ﻣﻌﺎﺩﻟﻪ ﺟﻮﺍﺏ ﺣﻘﻴﻘﻲ
ﻧﺪﺍﺭﺩ ﺯﻳﺮﺍ ﺩﻟﺘﺎ ﻣﻨﻔﻲ ﺍﺳﺖ .ﻭﻗﺘﻲ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﺷﻮﺩ ،ﺗﺎﺑﻊ )( sqrtﺗﻼﺵ ﻣﻲﮐﻨﺪ ﺟﺬﺭ
ﻳﮏ ﻋﺪﺩ ﻣﻨﻔﻲ ﺭﺍ ﺑﮕﻴﺮﺩ ﻭﻟﻲ ﻣﻮﻓﻖ ﻧﻤﻲﺷﻮﺩ .ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﭘﺎﺳﺦ nanﺩﺍﺩﻩ
ﻣﻲﺷﻮﺩ) nanﻣﺨﻔﻒ ﻋﺒﺎﺭﺕ not a numberﺍﺳﺖ ﻳﻌﻨﻲ ﭘﺎﺳﺦ ﻋﺪﺩﻱ ﻧﻴﺴﺖ(.
ﺳﭙﺲ ﻫﺮ ﻣﺤﺎﺳﺐۀ ﺩﻳﮕﺮﻱ ﮐﻪ ﺍﺯ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﺪ ،ﻫﻤﻴﻦ ﭘﺎﺳﺦ nanﺭﺍ ﺧﻮﺍﻫﺪ
ﺩﺍﺷﺖ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺩﺭ ﻫﻢۀ ﺧﺮﻭﺟﻲﻫﺎ ﭘﺎﺳﺦ nanﺁﻣﺪﻩ ﺍﺳﺖ.
ﺳﺮﺍﻧﺠﺎﻡ ﺑﻪ ﺍﺟﺮﺍﻱ ﺯﻳﺮ ﺩﻗﺖ ﻧﻤﺎﻳﻴﺪ:
Enter the coeficients of a quadratic equation:
a: 0
b: 2
c: 5
The equation is: 0*x*x + 2*x + 5 = 0
The solutions are:
x1 = nan
x2 = -inf
check:
a*x1*x1 + b*x1 + c = nan
ﺩﺭ ﺍﻳﻦ ﺍﺟﺮﺍ ﮐﻮﺷﺶ ﺷﺪﻩ ﺗﺎ ﻣﻌﺎﺩﻝۀ 0 x 2 + 2 x + 5 = 0ﺣﻞ ﺷﻮﺩ .ﺍﻳﻦ ﻣﻌﺎﺩﻟﻪ ﺩﺍﺭﺍﻱ
ﺟﻮﺍﺏ x=2.5ﺍﺳﺖ ﺍﻣﺎ ﺑﺮﻧﺎﻣﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺍﻳﻦ ﺟﻮﺍﺏ ﺭﺍ ﺑﻴﺎﺑﺪ ﻭ ﺑﺎ ﭘﺎﺳﺦﻫﺎﻱ ﻋﺠﻴﺒﻲ
ﺭﻭﺑﺮﻭ ﻣﻲﺷﻮﻳﻢ .ﻋﻠﺖ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ aﺻﻔﺮ ﺍﺳﺖ ﻭ ﺩﺭ ﺣﻴﻦ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ،ﺳﻌﻲ ﻣﻲﺷﻮﺩ
ﻋﺪﺩﻱ ﺑﺮ ﺻﻔﺮ ﺗﻘﺴﻴﻢ ﺷﻮﺩ .ﻳﻌﻨﻲ ﺑﺮﻧﺎﻣﻪ ﻣﻌﺎﺩﻝۀ ﺯﻳﺮ ﺭﺍ ﺣﻞ ﻣﻲﮐﻨﺪ:
ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ ﺩﻭﺑﺎﺭﻩ ﭘﺎﺳﺦ nanﺑﺪﺳﺖ ﻣﻲﺁﻳﺪ .ﻫﻤﭽﻨﻴﻦ ﺑﺮﺍﻱ x2ﺩﺍﺭﻳﻢ:
ﺳﻪ ﻧﺸﺎﻥۀ nanﻭ infﻭ –infﺛﺎﺑﺖﻫﺎﻱ ﻋﺪﺩﻱ ﻫﺴﺘﻨﺪ .ﻳﻌﻨﻲ ﻣﻲﺗﻮﺍﻧﻴﺪ ﺍﻳﻦ
ﻣﻘﺎﺩﻳﺮ ﺭﺍ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺕ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﺪ ﺍﻣﺎ ﻧﺘﻴﺠﻪ ﻣﻌﻤﻮﻻ ﺑﻲﻓﺎﻳﺪﻩ ﺍﺳﺖ .ﻣﺜﻼ ﻣﻲﺗﻮﺍﻧﻴﺪ
ﻋﺪﺩﻱ ﺭﺍ ﺑﺎ infﺟﻤﻊ ﮐﻨﻴﺪ ﻳﺎ ﺍﺯ ﺁﻥ ﺗﻔﺮﻳﻖ ﻧﻤﺎﻳﻴﺪ ﺍﻣﺎ ﻧﺘﻴﺠﻪ ﺑﺎﺯ ﻫﻢ infﺧﻮﺍﻫﺪ ﺑﻮﺩ.
2 – 16ﺣﻮﺯۀ ﻣﺘﻐﻴﺮﻫﺎ
ﻣﺘﻐﻴﺮﻫﺎ ﺑﺨﺶ ﻣﻬﻤﻲ ﺍﺯ ﻫﺮ ﺑﺮﻧﺎﻣﻪ ﻫﺴﺘﻨﺪ .ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺑﺎ ﻧﻮﻉ ﻧﺎﻣﻨﺎﺳﺐ
ﺳﺒﺐ ﻫﺪﺭ ﺭﻓﺘﻦ ﺣﺎﻓﻈﻪ ﻭ ﮐﺎﻫﺶ ﺳﺮﻋﺖ ﻭ ﺍﻓﺰﺍﻳﺶ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ .ﺍﻧﺘﺨﺎﺏ
ﻧﺎﻡﻫﺎﻱ ﻧﺎﻣﻔﻬﻮﻡ ﻳﺎ ﻧﺎﻗﺺ ﺳﺒﺐ ﮐﺎﻫﺶ ﺧﻮﺍﻧﺎﻳﻲ ﺑﺮﻧﺎﻣﻪ ﻭ ﺍﻓﺰﺍﻳﺶ ﺧﻄﺎﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
1
ﻣﻲﺷﻮﺩ .ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎ ﺩﺭ ﺣﻮﺯۀ ﻧﺎﻣﻨﺎﺳﺐ ﻫﻢ ﺳﺒﺐ ﺑﺮﻭﺯ ﺧﻄﺎﻫﺎﻳﻲ ﻣﻲﺷﻮﺩ» .ﺣﻮﺯﻩ
ﻣﺘﻐﻴﺮ« ﻣﺤﺪﻭﺩﻩﺍﻱ ﺍﺳﺖ ﮐﻪ ﻳﮏ ﻣﺘﻐﻴﺮ ﺧﺎﺹ ﺍﺟﺎﺯﻩ ﺩﺍﺭﺩ ﺩﺭ ﺁﻥ ﻣﺤﺪﻭﺩﻩ ﺑﻪ ﮐﺎﺭ ﺭﻭﺩ ﻳﺎ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ.
ﺍﺻﻄﻼﺡ »ﺑﻠﻮﮎ «2ﺩﺭ C++ﻭﺍﮊﻩ ﻣﻨﺎﺳﺒﻲ ﺍﺳﺖ ﮐﻪ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻭﺳﻴﻞۀ ﺁﻥ ﺣﻮﺯۀ
ﻣﺘﻐﻴﺮ ﺭﺍ ﻣﺸﺨﺺ ﻧﻤﻮﺩ .ﻳﮏ ﺑﻠﻮﮎ ﺑﺮﻧﺎﻣﻪ ،ﻗﺴﻤﺘﻲ ﺍﺯ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺖ ﮐﻪ ﺩﺭﻭﻥ ﻳﮏ ﺟﻔﺖ
ﻋﻼﻣﺖ ﮐﺮﻭﺷﻪ } { ﻣﺤﺪﻭﺩ ﺷﺪﻩ ﺍﺳﺖ .ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﺗﺎﮐﻨﻮﻥ ﺩﻳﺪﻳﻢ ﺍﺯ ﺑﻠﻮﮎ
ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ .ﻫﻤﻴﺸﻪ ﺑﻌﺪ ﺍﺯ ﻋﺒﺎﺭﺕ )( int mainﻳﮏ ﮐﺮﻭﺷﻪ ﺑﺎﺯ { ﮔﺬﺍﺷﺘﻪﺍﻳﻢ
ﻭ ﺩﺭ ﭘﺎﻳﺎﻥ ﺑﺮﻧﺎﻣﻪ ﻳﮏ ﮐﺮﻭﺷﻪ ﺑﺴﺘﻪ } ﻗﺮﺍﺭ ﺩﺍﺩﻳﻢ .ﭘﺲ ﺗﻤﺎﻡ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﺗﺎ ﮐﻨﻮﻥ ﺫﮐﺮ
ﺷﺪ ،ﻳﮏ ﺑﻠﻮﮎ ﺩﺍﺷﺘﻪ .ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ ﻣﻲﺗﻮﺍﻥ ﮔﻔﺖ ﮐﻪ ﺣﻮﺯۀ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺯ ﻣﺤﻞ ﺍﻋﻼﻥ ﺁﻥ
ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ﻭ ﺗﺎ ﭘﺎﻳﺎﻥ ﻫﻤﺎﻥ ﺑﻠﻮﮎ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ .ﺧﺎﺭﺝ ﺍﺯ ﺁﻥ ﺑﻠﻮﮎ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﻣﺘﻐﻴﺮ
ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ .ﻫﻤﭽﻨﻴﻦ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﻣﺘﻐﻴﺮ ﺍﻋﻼﻥ ﺷﻮﺩ ﻧﻤﻲﺗﻮﺍﻥ ﺁﻥ ﺭﺍ ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﻮﺩ.
ﻣﺜﺎﻝ ﺯﻳﺮ ﺭﺍ ﺑﺮﺭﺳﻲ ﮐﻨﻴﺪ.
{
;x = 22 // OK: this is in the scope of x
;y = 33 // ERROR: this is not in the scope of y
;int y
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺩﻭ ﺑﻠﻮﮎ ﺗﻮﺩﺭﺗﻮ ﺩﺍﺭﺩ .ﺍﻭﻟﻴﻦ ﺑﻠﻮﮎ ﺑﻌﺪ ﺍﺯ ﻋﺒﺎﺭﺕ )( int mainﺷﺮﻭﻉ
ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﺧﻂ ﺁﺧﺮ ﺑﺮﻧﺎﻣﻪ ﺑﺴﺘﻪ ﻣﻲﺷﻮﺩ .ﺑﻠﻮﮎ ﺩﺍﺧﻠﻲ ﻧﻴﺰ ﺍﺯ ﺧﻂ ﭘﻨﺠﻢ ﺁﻏﺎﺯ ﻣﻲﺷﻮﺩ
ﻭ ﺩﺭ ﺧﻂ ﺩﻫﻢ ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ .ﻧﺤﻮۀ ﺗﻮﺭﻓﺘﮕﻲ ﺧﻄﻮﻁ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺩﺭﮎ ﻭ ﺗﺸﺨﻴﺺ ﺷﺮﻭﻉ ﻭ
ﭘﺎﻳﺎﻥ ﺑﻠﻮﮎﻫﺎ ﮐﻤﮏ ﻣﻲﮐﻨﺪ .ﺧﻂ ﭘﻨﺠﻢ ﺗﺎ ﺩﻫﻢ ﺗﻮﺭﻓﺘﮕﻲ ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﺩ ،ﻳﻌﻨﻲ ﺍﻳﻦ ﺧﻄﻮﻁ
ﺗﺸﮑﻴﻞ ﻳﮏ ﺑﻠﻮﮎ ﻣﻲﺩﻫﻨﺪ .ﻫﻤﭽﻨﻴﻦ ﺧﻂ ﺩﻫﻢ ﺑﻪ ﺑﻌﺪ ﺗﻮﺭﻓﺘﮕﻲ ﺑﻪ ﺍﻧﺪﺍﺯۀ ﺧﻂ ﺳﻮﻡ ﻭ
ﭼﻬﺎﺭﻡ ﺩﺍﺭﺩ ،ﻳﻌﻨﻲ ﻣﺠﻤﻮﻋﻪ ﺍﻳﻦ ﺧﻄﻮﻁ ﻫﻢ ﺩﺭ ﻳﮏ ﺣﻮﺯۀ ﻣﺸﺘﺮﮎ ﻗﺮﺍﺭ ﺩﺍﺭﻧﺪ.
ﺍﻭﻟﻴﻦ ﺧﻄﺎ ﺩﺭ ﺧﻂ ﺳﻮﻡ ﺭﺥ ﺩﺍﺩﻩ .ﻣﺘﻐﻴﺮ xﺩﺭ ﺧﻂ ﭼﻬﺎﺭﻡ ﺍﻋﻼﻥ ﺷﺪﻩ ﺍﺳﺖ .ﭘﺲ
ﺣﻮﺯۀ xﺍﺯ ﺧﻂ ﭼﻬﺎﺭﻡ ﺑﻪ ﺑﻌﺪ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ،ﺩﺭ ﺣﺎﻟﻲ ﮐﻪ ﺩﺭ ﺧﻂ ﺳﻮﻡ ﻣﺘﻐﻴﺮ x
ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﻭ ﺍﻳﻦ ﺧﺎﺭﺝ ﺍﺯ ﻣﺤﺪﻭﺩۀ xﺍﺳﺖ.
ﺩﻭﻣﻴﻦ ﺧﻄﺎ ﺩﺭ ﺧﻂ ﺷﺸﻢ ﺍﺗﻔﺎﻕ ﺍﻓﺘﺎﺩﻩ ﺍﺳﺖ .ﻣﺘﻐﻴﺮ yﺩﺭ ﺧﻂ ﻫﻔﺘﻢ ﺍﻋﻼﻥ ﺷﺪﻩ.
ﭘﺲ ﺣﻮﺯۀ yﺍﺯ ﺧﻂ ﻫﻔﺘﻢ ﺑﻪ ﺑﻌﺪ ﺍﺳﺖ ،ﺩﺭ ﺣﺎﻟﻲ ﮐﻪ ﺩﺭ ﺧﻂ ﺷﺸﻢ yﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﻭ
ﺍﻳﻦ ﺧﺎﺭﺝ ﺍﺯ ﻣﺤﺪﻭﺩۀ yﺍﺳﺖ.
ﺳﻮﻣﻴﻦ ﺧﻄﺎ ﮐﻪ ﺩﺭ ﺧﻂ ﺩﻭﺍﺯﺩﻫﻢ ﺭﻭﻱ ﺩﺍﺩﻩ ﻧﻴﺰ ﻣﺮﺑﻮﻁ ﺑﻪ yﺍﺳﺖ .ﮔﺮﭼﻪ yﺩﺭ
ﺧﻄﻮﻁ ﻗﺒﻠﻲ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﻣﺎ ﺍﻳﻦ ﺗﻌﺮﻳﻒ ﺩﺭ ﻳﮏ ﺑﻠﻮﮎ ﺩﺍﺧﻠﻲ ﺑﻮﺩﻩ ﺍﺳﺖ .ﺍﻳﻦ ﺑﻠﻮﮎ
ﺩﺍﺧﻠﻲ ﺩﺭ ﺧﻂ ﺩﻫﻢ ﺑﻪ ﭘﺎﻳﺎﻥ ﺭﺳﻴﺪﻩ ﺍﺳﺖ .ﭘﺲ ﺗﻤﺎﻡ ﺗﻌﺎﺭﻳﻔﻲ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﺑﻠﻮﮎ ﻭﺟﻮﺩ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 56
ﺩﺍﺷﺘﻪ ﻧﻴﺰ ﻓﻘﻂ ﺗﺎ ﺧﻂ ﺩﻫﻢ ﺍﻋﺘﺒﺎﺭ ﺩﺍﺭﺩ .ﻳﻌﻨﻲ ﺣﻮﺯۀ yﻓﻘﻂ ﺍﺯ ﺧﻂ ﻫﻔﺘﻢ ﺗﺎ ﺧﻂ ﺩﻫﻢ
ﺍﺳﺖ .ﻟﺬﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺩﺭ ﺧﻂ ﺩﻭﺍﺯﺩﻫﻢ ﮐﻪ ﺧﺎﺭﺝ ﺍﺯ ﻣﺤﺪﻭﺩﻩ yﺍﺳﺖ ،ﺁﻥ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺑﺮﺩ.
ﻣﺜﺎﻝ ﺑﺎﻻ ﻣﻄﻠﺐ ﻇﺮﻳﻔﻲ ﺭﺍ ﺑﻴﺎﻥ ﻣﻲﮐﻨﺪ :ﻣﻲﺗﻮﺍﻧﻴﻢ ﺩﺭ ﻳﮏ ﺑﺮﻧﺎﻣﻪ ،ﭼﻨﺪ ﻣﺘﻐﻴﺮ
ﻣﺘﻔﺎﻭﺕ ﺑﺎ ﻳﮏ ﻧﺎﻡ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ ﺑﻪ ﺷﺮﻃﻲ ﮐﻪ ﺩﺭ ﺣﻮﺯﻩﻫﺎﻱ ﻣﺸﺘﺮﮎ ﻧﺒﺎﺷﻨﺪ .ﺁﺧﺮﻳﻦ ﺑﺮﻧﺎﻡۀ
ﻓﺼﻞ ﺍﻭﻝ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ ﺑﻪ ﺧﻮﺑﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
)(int main
{ //illustrates the nested and parallel scopes:
;int x = 22
{ //begin scope of internal block
;int x = 33
;cout << "In block inside main() : x = " << x << endl
} //end scope of internal block
;cout << "In main() : x = " << x << endl
;cout << "In main() : ::x = " << ::x << endl
;return 0
} )(//end scope of main
In block inside main() : x = 33
In main() : x = 22
In main() : ::x = 11
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺳﻪ ﺷﻲﺀ ﻣﺘﻔﺎﻭﺕ ﺑﺎ ﻧﺎﻡ xﻭﺟﻮﺩ ﺩﺍﺭﺩ .ﺍﻭﻟﻴﻦ xﮐﻪ ﻣﻘﺪﺍﺭ 11ﺩﺍﺭﺩ ﻳﮏ
ﻣﺘﻐﻴﺮ ﺳﺮﺍﺳﺮﻱ ﺍﺳﺖ ﺯﻳﺮﺍ ﺩﺍﺧﻞ ﻫﻴﭻ ﺑﻠﻮﮐﻲ ﻗﺮﺍﺭ ﻧﺪﺍﺭﺩ .ﭘﺲ ﺣﻮﺯۀ ﺁﻥ ﺳﺮﺍﺳﺮ ﺑﺮﻧﺎﻣﻪ
)ﺣﺘﻲ ﺧﺎﺭﺝ ﺍﺯ ﺑﻠﻮﮎ )( ( mainﺍﺳﺖ .ﺩﻭﻣﻴﻦ xﺩﺭﻭﻥ ﺑﻠﻮﮎ )( mainﺑﺎ ﻣﻘﺪﺍﺭ 22
ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ .ﭘﺲ ﺣﻮﺯۀ ﺁﻥ ﺗﺎ ﭘﺎﻳﺎﻥ ﺑﻠﻮﮎ )( mainﺍﺳﺖ .ﺍﻳﻦ xﺣﻮﺯﻩ xﻗﺒﻠﻲ
ﺭﺍ ﮐﻮﺭ ﻣﻲﮐﻨﺪ .ﻳﻌﻨﻲ ﺩﺭﻭﻥ ﺑﻠﻮﮎ )( mainﻓﻘﻂ xﺩﻭﻡ ﺩﻳﺪﻩ ﻣﻲﺷﻮﺩ ﻭ xﺍﻭﻝ ﻣﺨﻔﻲ
ﻣﻲﺷﻮﺩ .ﭘﺲ ﺍﮔﺮ ﺩﺭﻭﻥ ﺍﻳﻦ ﺑﻠﻮﮎ ﺑﻪ xﺍﺭﺟﺎﻉ ﮐﻨﻴﻢ ﻓﻘﻂ xﺩﻭﻡ ﺭﺍ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ.
ﺳﻮﻣﻴﻦ xﺩﺭ ﻳﮏ ﺑﻠﻮﮎ ﺩﺍﺧﻠﻲ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ .ﺣﻮﺯﻩ ﺍﻳﻦ xﻓﻘﻂ ﺗﺎ ﭘﺎﻳﺎﻥ
ﻫﻤﺎﻥ ﺑﻠﻮﮎ ﺍﺳﺖ .ﺍﻳﻦ xﺣﻮﺯۀ ﻫﺮ ﺩﻭ xﻗﺒﻠﻲ ﺭﺍ ﮐﻮﺭ ﻣﻲﮐﻨﺪ .ﭘﺲ ﺍﮔﺮ ﺩﺭﻭﻥ ﺍﻳﻦ ﺑﻠﻮﮎ
57 ﻓﺼﻞ دوم /اﻧﻮاع اﺻﻠﯽ
xﺭﺍ ﻓﺮﺍﺧﻮﺍﻧﻲ ﮐﻨﻴﻢ ﻓﻘﻂ xﺳﻮﻡ ﺭﺍ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ .ﻭﻗﺘﻲ ﺍﺯ ﺍﻳﻦ ﺑﻠﻮﮎ ﺧﺎﺭﺝ ﺷﻮﻳﻢ x ،
ﻗﺒﻠﻲ ﺁﺯﺍﺩ ﻣﻲﺷﻮﺩ ﻭ ﺩﻭﺑﺎﺭﻩ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻣﻘﺪﺍﺭ ﺁﻥ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ .ﺍﮔﺮ ﺍﺯ ﺑﻠﻮﮎ )(main
ﻧﻴﺰ ﺧﺎﺭﺝ ﺷﻮﻳﻢ x ،ﺍﻭﻝ ﺁﺯﺍﺩ ﺧﻮﺍﻫﺪ ﺷﺪ .ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺍﺯ ﺍﻭﻝ ﺩﻧﺒﺎﻝ ﮐﻨﻴﺪ ﻭ ﺧﺮﻭﺟﻲ ﺭﺍ
ﺑﺮﺭﺳﻲ ﻧﻤﺎﻳﻴﺪ ﺗﺎ ﻣﺘﻮﺟﻪ ﺷﻮﻳﺪ ﮐﻪ ﮐﺪﺍﻡ xﻣﻌﺘﺒﺮ ﺑﻮﺩﻩ ﺍﺳﺖ .ﺩﺭ ﺧﻂ ﺩﻫﻢ ﺍﺯ ﻋﻤﻠﮕﺮ ::
ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ .ﺑﻪ ﺁﻥ ﻋﻤﻠﮕﺮ »ﺟﺪﺍﺳﺎﺯﻱ ﺣﻮﺯﻩ« ﻣﻲﮔﻮﻳﻨﺪ .ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺭﺍ ﺩﺭ ﻓﺼﻞﻫﺎﻱ
ﺑﻌﺪﻱ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﻴﻢ .ﺩﺭ ﺍﻳﻦﺟﺎ ﻓﻘﻂ ﻣﻲﮔﻮﻳﻴﻢ ﺑﺎ ﻋﻤﻠﮕﺮ ﺟﺪﺍﺳﺎﺯﻱ ﺣﻮﺯﻩ ﻣﻲﺗﻮﺍﻥ ﺑﻪ
ﻳﮏ ﺷﻲ ﮐﻪ ﺧﺎﺭﺝ ﺍﺯ ﺣﻮﺯۀ ﻓﻌﻠﻲ ﺍﺳﺖ ﺩﺳﺘﺮﺳﻲ ﭘﻴﺪﺍ ﮐﻨﻴﻢ .ﭘﺲ ::xﻳﻌﻨﻲ ﻣﺘﻐﻴﺮ xﮐﻪ
ﺩﺭ ﺣﻮﺯۀ ﺑﻴﺮﻭﻧﻲ ﺍﺳﺖ.
ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺗﻌﺮﻳﻒ ﭼﻨﺪ ﻣﺘﻐﻴﺮ ﺩﺭ ﻳﮏ ﺑﺮﻧﺎﻣﻪ ﺑﺎ ﻧﺎﻡ ﻳﮑﺴﺎﻥ ﺑﻪ ﺷﻴﻮۀ ﺑﺎﻻ ﻣﻤﮑﻦ ﻭ
ﻣﺠﺎﺯ ﺍﺳﺖ .ﺍﻣﺎ ﺳﻌﻲ ﮐﻨﻴﺪ ﺍﺯ ﺍﻳﻦ ﮐﺎﺭ ﺍﺟﺘﻨﺎﺏ ﮐﻨﻴﺪ ﺯﻳﺮﺍ ﺩﺭ ﻏﻴﺮ ﺍﻳﻦ ﺻﻮﺭﺕ ﻫﻤﻴﺸﻪ
ﻣﺠﺒﻮﺭﻳﺪ ﺑﻪ ﺧﺎﻃﺮ ﺑﺴﭙﺎﺭﻳﺪ ﮐﻪ ﺍﻻﻥ ﺩﺍﺧﻞ ﮐﺪﺍﻡ ﺣﻮﺯﻩ ﻫﺴﺘﻴﺪ ﻭ ﮐﺪﺍﻡ ﻣﺘﻐﻴﺮ ﻣﻮﺭﺩ ﻧﻈﺮ
ﺷﻤﺎﺳﺖ .ﺍﻳﻦ ﻃﻮﺭﻱ ﺭﺍﺣﺖﺗﺮﻳﺪ؟ ﺍﺧﺘﻴﺎﺭ ﺑﺎ ﺷﻤﺎﺳﺖ!
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 58
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﺍﺯ ﻣﻴﺎﻥ ﺍﻧﻮﺍﻉ ﺯﻳﺮ ،ﮐﺪﺍﻡ ﻳﮏ ﻧﻮﻉ ﺻﺤﻴﺢ ﺣﺴﺎﺏ ﻧﻤﻲﺷﻮﺩ؟
ﺩ ( bool ﺝ ( char ﺏ ( int ﺍﻟﻒ ( double
– 2ﺍﮔﺮ mﻭ nﻫﺮ ﺩﻭ ﺍﺯ ﻧﻮﻉ shortﺑﺎﺷﻨﺪ ﻭ m=6ﻭ n=4ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﺣﺎﺻﻞ m/n
ﺑﺮﺍﺑﺮ ﺍﺳﺖ ﺑﺎ:
ﺩ ( nan ﺝ(2 ﺏ ( 1.5 ﺍﻟﻒ ( 1
– 3ﺍﮔﺮ mﺍﺯ ﻧﻮﻉ doubleﻭ nﺍﺯ ﻧﻮﻉ intﺑﺎﺷﺪ ﻭ m=6.0ﻭ n=4ﺑﺎﺷﺪ ،ﺣﺎﺻﻞ
m/nﭼﻘﺪﺭ ﺍﺳﺖ؟
ﺩ ( nan ﺝ(2 ﺏ ( 1.5 ﺍﻟﻒ ( 1
– 4ﻣﺘﻐﻴﺮ mﺍﺯ ﻧﻮﻉ floatﻭ ﻣﺘﻐﻴﺮ nﺍﺯ ﻧﻮﻉ shortﺍﺳﺖ .ﺍﮔﺮ ﺑﺨﻮﺍﻫﻴﻢ ﺣﺎﺻﻞ
m*nﺭﺍ ﺩﺭ ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ kﻧﮕﻬﺪﺍﺭﻳﻢ ،ﺁﻧﮕﺎﻩ kﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ .................ﺑﺎﺷﺪ.
ﺏ ( long ﺍﻟﻒ ( short
ﺩ ( int ﺝ ( float
– 5ﺩﺭ ﻋﺒﺎﺭﺕ z += ++yﺍﮔﺮ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ yﺑﺮﺍﺑﺮ ﺑﺎ 5ﻭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ zﺑﺮﺍﺑﺮ ﺑﺎ 7
ﺑﺎﺷﺪ،ﺣﺎﺻﻞ zﭘﺲ ﺍﺯ ﺍﺟﺮﺍﻱ ﺁﻥ ﺩﺳﺘﻮﺭ ﻋﺒﺎﺭﺕ ﺍﺳﺖ ﺍﺯ:
ﺩ ( 13 ﺝ(5 ﺏ(6 ﺍﻟﻒ ( 12
– 6ﻋﺪﺩ 1.23e-1ﻣﻌﺎﺩﻝ ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﺍﻋﺪﺍﺩ ﺯﻳﺮ ﺍﺳﺖ؟
ﺩ ( -1.23 ﺝ ( 0.123 ﺏ ( -12.3 ﺍﻟﻒ ( 12.3
– 7ﺍﮔﺮ aﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ floatﺑﺎ ﻣﻘﺪﺍﺭ 5.63ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﺣﺎﺻﻞ ) int(aﺑﺮﺍﺑﺮ
ﺍﺳﺖ ﺑﺎ:
ﺩ ( 5.6 ﺝ ( 0.63 ﺏ(6 ﺍﻟﻒ ( 5
– 8ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺣﺎﺻﻞ m/nﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﺎﺷﺪ ﺑﺎﻳﺪ:
ﺏ ( nﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﺎﺷﺪ ﺍﻟﻒ ( mﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﺎﺷﺪ
ﺩ ( ﻫﻢ mﻭ ﻫﻢ nﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﺎﺷﺪ ﺝ ( ﻳﺎ mﻭ ﻳﺎ nﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﺎﺷﺪ
– 9ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﺍﺯ ﭼﻪ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ؟
ﺩ ( const ﺝ ( sqrt ﺏ ( enum ﺍﻟﻒ ( include
59 ﻓﺼﻞ دوم /اﻧﻮاع اﺻﻠﯽ
– 10ﺍﮔﺮ ﺑﺨﻮﺍﻫﻴﻢ ﮐﺎﺭﺍﮐﺘﺮ Mﺭﺍ ﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ chﮐﻪ ﺍﺯ ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺍﺳﺖ ﺑﮕﺬﺍﺭﻳﻢ ﺍﺯ
ﭼﻪ ﺩﺳﺘﻮﺭﻱ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ؟
ﺏ ( ;"ch = "M ﺍﻟﻒ ( ;ch = M
ﺩ ( ch M ﺝ ( ;'ch = 'M
– 11ﺧﻄﺎﻱ ﮔﺮﺩ ﮐﺮﺩﻥ ﻣﺮﺑﻮﻁ ﺑﻪ ﮐﺪﺍﻡ ﻧﻮﻉ ﺩﺭ C++ﺍﺳﺖ؟
ﺏ ( ﻧﻮﻉ ﺻﺤﻴﺢ ﺍﻟﻒ ( ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ
ﺩ ( ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ﺝ ( ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻱ
– 12ﺍﮔﺮ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ intﺳﺮﺭﻳﺰ ﺷﻮﺩ ،ﭼﻪ ﻣﻘﺪﺍﺭﻱ ﺩﺭ ﺁﻥ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ؟
ﺩ ( ﻋﺪﺩ ﺻﺤﻴﺢ ﻣﻨﻔﻲ ﺝ ( nan ﺏ ( inf ﺍﻟﻒ ( –inf
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 60
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﻗﺒﻞ ﺍﺯ ﺍﺟﺮﺍﻱ ﺩﺳﺘﻮﺭﺍﺕ ﺯﻳﺮ ،ﻣﻘﺪﺍﺭ mﺑﺮﺍﺑﺮ 5ﻭ ﻣﻘﺪﺍﺭ nﺑﺮﺍﺑﺮ 2ﺍﺳﺖ .ﺑﻌﺪ ﺍﺯ
ﺍﺟﺮﺍﻱ ﻫﺮ ﻳﻚ ﺍﺯ ﺩﺳﺘﻮﺭﺍﺕ ﺯﻳﺮ ﻣﻘﺪﺍﺭ ﺟﺪﻳﺪ mﻭ nﭼﻴﺴﺖ؟
;a. m *= n++
;b. m += --n
‐2ﻣﻘﺪﺍﺭ ﻫﺮ ﻳﻚ ﺍﺯ ﻋﺒﺎﺭﺍﺕ ﺯﻳﺮ ﺭﺍ ﭘﺲ ﺍﺯ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﺮﺁﻭﺭﺩ ﻛﻨﻴﺪ .ﺍﺑﺘﺪﺍ ﻓﺮﺽ ﻛﻨﻴﺪ ﻛﻪ
mﺑﺮﺍﺑﺮ 25ﻭ nﺑﺮﺍﺑﺮ 7ﺍﺳﺖ.
a. m - 8 - n
b. m = n = 3
c. m%n
d. m%n++
e. m%++n
‐‐f. ++m - n
‐4ﺑﺮﺍﻱ ﭘﻴﺪﺍ ﻛﺮﺩﻥ ﻛﺎﺭﺍﻛﺘﺮﻱ ﻛﻪ ﻛﺪ ﺍﺳﻜﻲ ﺁﻥ 100ﺍﺳﺖ ،ﭼﻪ ﻛﺪﻱ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﺪ ﺍﺟﺮﺍ
ﻛﻨﻴﺪ؟
‐5ﻣﻌﻨﺎﻱ »ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ« ﭼﻴﺴﺖ ﻭ ﭼﺮﺍ ﺑﻪ ﺍﻳﻦ ﻧﺎﻡ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ؟
‐6ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩﻱ ﭼﻴﺴﺖ؟
‐7ﻓﺮﻕ ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩ ﺻﺤﻴﺢ ﺑﺎ ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﭼﻴﺴﺖ؟
‐8ﺧﻄﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﭼﻴﺴﺖ؟ ﻣﺜﺎﻝﻫﺎﻳﻲ ﺑﺮﺍﻱ ﺩﻭ ﻧﻮﻉ ﻣﺘﻔﺎﻭﺕ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺑﻨﻮﻳﺴﻴﺪ.
‐9ﺧﻄﺎﻱ ﺯﻣﺎﻥ ﻛﺎﻣﭙﺎﻳﻞ ﭼﻴﺴﺖ؟ ﻣﺜﺎﻝﻫﺎﻳﻲ ﺑﺮﺍﻱ ﺩﻭ ﻧﻮﻉ ﻣﺘﻔﺎﻭﺕ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ
ﻛﺎﻣﭙﺎﻳﻞ ﺑﻨﻮﻳﺴﻴﺪ.
‐10ﻛﺪ ﺯﻳﺮ ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺍﺭﺩ؟
;}enum Semester {FALL, SPRING, SUMMER
;}enum Season {SPRING, SUMMER, FALL, WINTER
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﭼﻬﺎﺭ ﺩﺳﺘﻮﺭ ﻣﺘﻔﺎﻭﺕ C++ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ 1ﺭﺍ ﺍﺯ ﻣﺘﻐﻴﺮ ﻋﺪﺩ ﺻﺤﻴﺢ nﻛﻢ ﻛﻨﺪ.
‐2ﻳﻚ ﺑﻠﻮﻙ ﻛﺪ C++ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﻣﺸﺎﺑﻪ ﺟﻤﻞۀ ﺯﻳﺮ ﻋﻤﻞ ﻛﻨﺪ ﺑﺪﻭﻥ ﺍﻳﻦ ﻛﻪ ﺍﺯ ﻋﻤﻠﮕﺮ
++ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﺪ.
;n = 100 + m++
‐3ﻳﻚ ﺑﻠﻮﻙ ﻛﺪ C++ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﻣﺸﺎﺑﻪ ﺟﻤﻞۀ ﺯﻳﺮ ﻋﻤﻞ ﻛﻨﺪ ﺑﺪﻭﻥ ﺍﻳﻦ ﻛﻪ ﺍﺯ ﻋﻤﻠﮕﺮ
++ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﺪ.
;n = 100 + ++m
‐4ﻳﻚ ﺩﺳﺘﻮﺭ C++ﺗﻜﻲ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﻣﺠﻤﻮﻉ xﻭ yﺭﺍ ﺍﺯ zﻛﻢ ﻛﻨﺪ ﻭ ﺳﭙﺲ yﺭﺍ
ﺍﻓﺰﺍﻳﺶ ﺩﻫﺪ.
‐5ﻳﻚ ﺩﺳﺘﻮﺭ C++ﺗﻜﻲ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﻣﺘﻐﻴﺮ nﺭﺍ ﻛﺎﻫﺶ ﺑﺪﻫﺪ ﻭ ﺳﭙﺲ ﺁﻥ ﺭﺍ ﺑﻪ
totalﺍﺿﺎﻓﻪ ﻛﻨﺪ.
‐7ﺑﺮﻧﺎﻣﻪﺍﻱ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﻣﻮﺟﺐ ﺧﻄﺎﻱ ﭘﺎﺭﻳﺰﻱ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ shortﺷﻮﺩ.
‐8ﺑﺮﻧﺎﻣﻪﺍﻱ ﻣﺎﻧﻨﺪ ﻣﺜﺎﻝ 2 ‐ 8ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﺗﻨﻬﺎ ﻛﺪ ﺍﺳﻜﻲ ﺩﻩ ﺣﺮﻑ ﺻﺪﺍﺩﺍﺭ
ﺑﺰﺭﮒ ﻭ ﻛﻮﭼﻚ ﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ).ﺑﺮﺍﻱ ﺑﺮﺭﺳﻲ ﺧﺮﻭﺟﻲ ،ﺍﺯ ﺿﻤﻴﻢۀ »ﺍﻟﻒ« ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﺪ(
‐9ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 2‐15ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﺍﺯ ﻧﻮﻉ doubleﺑﻪ ﺟﺎﻱ float
ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﺪ .ﺳﭙﺲ ﻣﺸﺎﻫﺪﻩ ﻛﻨﻴﺪ ﻛﻪ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﭼﻄﻮﺭ ﺑﺎ ﻭﺭﻭﺩﻱﻫﺎﻳﻲ ﻛﻪ ﺧﻄﺎﻱ ﺯﻣﺎﻥ
ﺍﺟﺮﺍ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ ،ﺑﻬﺘﺮ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ.
‐10ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺍﻳﻨﭻ ﺭﺍ ﺑﻪ ﺳﺎﻧﺘﻴﻤﺘﺮ ﺗﺒﺪﻳﻞ ﻛﻨﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ ﻛﺎﺭﺑﺮ 16.9
ﺭﺍ ﺑﺮﺍﻱ ﻳﻚ ﻃﻮﻝ ﺑﺮ ﺣﺴﺐ ﺍﻳﻨﭻ ﻭﺍﺭﺩ ﻛﻨﺪ ،ﺧﺮﻭﺟﻲ 42.946 cmﭼﺎﭖ ﺷﻮﺩ).ﻳﻚ
ﺍﻳﻨﭻ ﺑﺮﺍﺑﺮ 2.54ﺳﺎﻧﺘﻴﻤﺘﺮ ﺍﺳﺖ(
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 62
ﻓﺼﻞ ﺳﻮﻡ
»ﺍﻧﺘﺨﺎﺏ«
ﻫﻢۀ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﺩﺭ ﺩﻭ ﻓﺼﻞ ﺍﻭﻝ ﺑﻴﺎﻥ ﺷﺪ ،ﺑﻪ ﺷﮑﻞ ﺗﺮﺗﻴﺒﻲ ﺍﺟﺮﺍ ﻣﻲﺷﻮﻧﺪ،
ﻳﻌﻨﻲ ﺩﺳﺘﻮﺭﺍﺕ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺗﺮﺗﻴﺐ ﺍﺯ ﺑﺎﻻ ﺑﻪ ﭘﺎﻳﻴﻦ ﻭ ﻫﺮ ﮐﺪﺍﻡ ﺩﻗﻴﻘﺎ ﻳﮏ ﺑﺎﺭ ﺍﺟﺮﺍ ﻣﻲﺷﻮﻧﺪ.
1
ﺟﻬﺖ ﺩﺭ ﺍﻳﻦ ﻓﺼﻞ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ ﭼﮕﻮﻧﻪ ﺍﺯ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎﻱ ﺍﻧﺘﺨﺎﺏ
ﺍﻧﻌﻄﺎﻑﭘﺬﻳﺮﻱ ﺑﻴﺸﺘﺮ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ .ﻫﻤﭽﻨﻴﻦ ﺩﺭ ﺍﻳﻦ ﻓﺼﻞ ﺍﻧﻮﺍﻉ ﺻﺤﻴﺢ ﻛﻪ ﺩﺭ
C++ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﺑﻴﺸﺘﺮ ﺑﺮﺭﺳﻲ ﻣﻲﮔﺮﺩﺩ.
3‐1ﺩﺳﺘﻮﺭ if
ﺩﺳﺘﻮﺭ ifﻣﻮﺟﺐ ﻣﻲﺷﻮﺩ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺷﮑﻞ ﺷﺮﻃﻲ ﺍﺟﺮﺍ ﺷﻮﺩ .ﻧﺤﻮ ﺁﻥ ﺑﻪ ﮔﻮﻥۀ ﺯﻳﺮ
ﺍﺳﺖ:
;If (condition) statement
1 – Selection
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 64
ﻣﻘﺪﺍﺭ 66%7ﺑﺮﺍﺑﺮ ﺑﺎ 3ﺑﺮﺁﻭﺭﺩ ﻣﻲﮔﺮﺩﺩ .ﭼﻮﻥ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ،ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﻏﻴﺮﺻﻔﺮ
ﺍﺳﺖ ،ﭘﺲ ﺷﺮﻁ ﺑﻪ ﻋﻨﻮﺍﻥ ﺩﺭﺳﺖ ﺗﻔﺴﻴﺮ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﻧﺘﻴﺠﻪ ﺩﺳﺘﻮﺭ coutﺍﺟﺮﺍ ﺷﺪﻩ ﻭ
ﭘﻴﻐﺎﻡ ﻋﺪﻡ ﻗﺎﺑﻠﻴﺖ ﺗﻘﺴﻴﻢ ﭼﺎﭖ ﻣﻲﺷﻮﺩ.
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ ﺩﻭﺑﺎﺭﻩ ﺍﺟﺮﺍ ﻣﻲﻧﻤﺎﻳﻴﻢ ﻭ ﺍﻳﻦ ﺩﻓﻌﻪ ﺍﻋﺪﺍﺩ 56ﻭ 7ﺭﺍ ﻭﺍﺭﺩ ﻣﻲﻛﻨﻴﻢ:
Enter two positive integers: 56 7
ﻣﻘﺪﺍﺭ 56%7ﺑﺮﺍﺑﺮ ﺑﺎ 0ﺑﺮﺁﻭﺭﺩ ﻣﻲﺷﻮﺩ ﻛﻪ ﺍﻳﻦ ﺑﻪ ﻣﻌﻨﻲ ﻧﺎﺩﺭﺳﺖ ﺗﻔﺴﻴﺮ ﻣﻲﮔﺮﺩﺩ ،ﭘﺲ
ﺩﺳﺘﻮﺭ coutﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﺷﺪﻩ ﻭ ﻫﻴﭻ ﭘﻴﻐﺎﻣﻲ ﺭﻭﻱ ﺻﻔﺤﻪ ﭼﺎﭖ ﻧﻤﻲﺷﻮﺩ.
ﺩﺭ C++ﻫﺮ ﻭﻗﺖ ﻳﻚ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﻚ ﺷﺮﻁ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ ،ﻣﻘﺪﺍﺭ 0
ﺑﻪ ﻣﻌﻨﻲ »ﻧﺎﺩﺭﺳﺖ« ﻭ ﻫﻢۀ ﻣﻘﺎﺩﻳﺮ ﺩﻳﮕﺮ ﺑﻪ ﻣﻌﻨﻲ »ﺩﺭﺳﺖ« ﺍﺳﺖ.
ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 3‐1ﻧﺎﻗﺺ ﺑﻪ ﻧﻈﺮ ﻣﻲﺁﻳﺪ ﺯﻳﺮﺍ ﺍﮔﺮ nﺑﺮ dﻗﺎﺑﻞ ﺗﻘﺴﻴﻢ ﺑﺎﺷﺪ ،ﺑﺮﻧﺎﻣﻪ
ﻫﻴﭻ ﻋﮑﺲﺍﻟﻌﻤﻠﻲ ﻧﺸﺎﻥ ﻧﻤﻲﺩﻫﺪ .ﺍﻳﻦ ﻧﻘﺺ ﺑﻪ ﮐﻤﮏ ﺩﺳﺘﻮﺭ if..elseﺭﻓﻊ ﻣﻲﺷﻮﺩ.
65 ﻓﺼﻞ ﺳﻮم /اﻧﺘﺨﺎب
3‐2ﺩﺳﺘﻮﺭ if..else
ﺣﺎﻻ ﻭﻗﺘﻲ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﻋﺪﺍﺩ 56ﻭ 7ﺭﺍ ﻭﺍﺭﺩ ﻛﻨﻴﻢ ،ﺑﺮﻧﺎﻣﻪ ﭘﺎﺳﺦ ﻣﻲﺩﻫﺪ ﮐﻪ 56
ﺑﺮ 7ﻗﺎﺑﻞ ﺗﻘﺴﻴﻢ ﺍﺳﺖ:
Enter two positive integers: 56 7
56 is divisible by 7
ﭼﻮﻥ ﺣﺎﺻﻞ 56%7ﺑﺮﺍﺑﺮ ﺑﺎ ﺻﻔﺮ ﺍﺳﺖ ،ﭘﺲ ﺍﻳﻦ ﻋﺒﺎﺭﺕ ﺑﻪ ﻋﻨﻮﺍﻥ ﻧﺎﺩﺭﺳﺖ ﺗﻔﺴﻴﺮ
ﻣﻲﮔﺮﺩﺩ .ﺩﺭ ﻧﺘﻴﺠﻪ ﺩﺳﺘﻮﺭ ﺑﻌﺪ ﺍﺯ ifﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﺷﺪﻩ ﻭ ﺩﺳﺘﻮﺭ ﺑﻌﺪ ﺍﺯ elseﺍﺟﺮﺍ
ﻣﻲﺷﻮﺩ .ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ if..elseﺑﻪ ﺗﻨﻬﺎﻳﻲ ﻳﻚ ﺩﺳﺘﻮﺭ ﺍﺳﺖ ،ﮔﺮ ﭼﻪ ﺑﻪ ﺩﻭ
ﺳﻤﻴﻜﻮﻟﻦ ﻧﻴﺎﺯ ﺩﺍﺭﺩ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 66
3‐4ﻋﻤﻠﮕﺮﻫﺎﻱ ﻣﻘﺎﻳﺴﻪﺍﻱ
ﺩﺭ C++ﺷﺶ ﻋﻤﻠﮕﺮ ﻣﻘﺎﻳﺴﻪﺍﻱ ﻭﺟﻮﺩ ﺩﺍﺭﺩ < :ﻭ > ﻭ =< ﻭ => ﻭ ==
ﻭ =! .ﻫﺮ ﻳﮏ ﺍﺯ ﺍﻳﻦ ﺷﺶ ﻋﻤﻠﮕﺮ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ:
x < y xﮐﻮﭼﮏﺗﺮ ﺍﺯ yﺍﺳﺖ //
x > y xﺑﺰﺭﮒﺗﺮ ﺍﺯ yﺍﺳﺖ //
xﮐﻮﭼﮏﺗﺮ ﻳﺎ ﻣﺴﺎﻭﻱ yﺍﺳﺖ x <= y //
xﺑﺰﺭﮒﺗﺮ ﻳﺎ ﻣﺴﺎﻭﻱ yﺍﺳﺖ x >= y //
xﻣﺴﺎﻭﻱ ﺑﺎ yﺍﺳﺖ x == y //
xﻣﺴﺎﻭﻱ ﺑﺎ yﻧﻴﺴﺖ x != y //
ﺍﻳﻦﻫﺎ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﺮﺍﻱ ﻣﻘﺎﻳﺲۀ ﻣﻘﺪﺍﺭ ﻋﺒﺎﺭﺍﺕ ﺑﺎ ﻫﺮ ﻧﻮﻉ ﺗﺮﺗﻴﺒﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﻧﺪ .ﻋﺒﺎﺭﺕ
ﺣﺎﺻﻞ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﻚ ﺷﺮﻁ ﺗﻔﺴﻴﺮ ﻣﻲﺷﻮﺩ .ﻣﻘﺪﺍﺭ ﺍﻳﻦ ﺷﺮﻁ ﺻﻔﺮ ﺍﺳﺖ ﺍﮔﺮ ﺷﺮﻁ
ﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﺪ ﻭ ﻏﻴﺮ ﺻﻔﺮ ﺍﺳﺖ ﺍﮔﺮ ﺷﺮﻁ ﺩﺭﺳﺖ ﺑﺎﺷﺪ .ﺑﺮﺍﻱ ﻧﻤﻮﻧﻪ ،ﻋﺒﺎﺭﺕ
7×8<6×9ﺑﺮﺍﺑﺮ ﺑﺎ ﺻﻔﺮ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ،ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﻲ ﻛﻪ ﺍﻳﻦ ﺷﺮﻁ ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ.
ﺩﻗﺖ ﮐﻨﻴﺪ ﻛﻪ ﺩﺭ C++ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺑﺎ ﻋﻤﻠﮕﺮ ﺑﺮﺍﺑﺮﻱ ﻓﺮﻕ ﺩﺍﺭﺩ .ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ
ﻳﮏ ﻣﺴﺎﻭﻱ ﺗﮑﻲ " = " ﺍﺳﺖ ﻭﻟﻲ ﻋﻤﻠﮕﺮ ﺑﺮﺍﺑﺮﻱ ،ﺩﻭ ﻣﺴﺎﻭﻱ " = = " ﺍﺳﺖ .ﻣﺜﻼ
67 ﻓﺼﻞ ﺳﻮم /اﻧﺘﺨﺎب
ﻇﺎﻫﺮﺍ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻡۀ ﻓﻮﻕ ﺑﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﺍﺳﺖ ﮐﻪ ﻋﺪﺩﻱ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﻣﻲﺷﻮﺩ ﻭ ﺍﮔﺮ
ﺍﻳﻦ ﻋﺪﺩ ﺑﺎ 22ﺑﺮﺍﺑﺮ ﺑﻮﺩ ،ﭘﻴﻐﺎﻡ ﺑﺮﺍﺑﺮﻱ ﭼﺎﭖ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﻏﻴﺮ ﺍﻳﻦ ﺻﻮﺭﺕ ﭘﻴﻐﺎﻡ ﻋﺪﻡ
ﺑﺮﺍﺑﺮﻱ ﭼﺎﭖ ﻣﻲﮔﺮﺩﺩ .ﻭﻟﻲ ﺍﺟﺮﺍﻱ ﺑﺎﻻ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺩﺭﺳﺖ ﮐﺎﺭ ﻧﻤﻲﮐﻨﺪ .ﻋﺪﺩ
77ﻭﺍﺭﺩ ﺷﺪﻩ ﻭﻟﻲ ﭘﻴﻐﺎﻡ n = 22ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﺷﺪﻩ ﺍﺳﺖ! ﺍﻳﺮﺍﺩ ﺩﺭ ﺧﻂ ﭘﻨﺠﻢ
ﺑﺮﻧﺎﻣﻪ ﺍﺳﺖ .ﻋﺒﺎﺭﺕ n = 22ﻣﻘﺪﺍﺭ 22ﺭﺍ ﺩﺭ nﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻭ ﻣﻘﺪﺍﺭ ﻗﺒﻠﻲ ﺁﻥ ﻛﻪ 77
ﺍﺳﺖ ﺭﺍ ﺗﻐﻴﻴﺮ ﻣﻲﺩﻫﺪ .ﺍﻣﺎ ﻋﺒﺎﺭﺕ n = 22ﺑﻪ ﻋﻨﻮﺍﻥ ﺷﺮﻁ ﺩﺳﺘﻮﺭ ifﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﭘﺲ
ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﺑﺎ ﻣﻘﺪﺍﺭ 22ﺑﺮﺁﻭﺭﺩ ﻣﻲﺷﻮﺩ .ﻟﺬﺍ ﺷﺮﻁ ) (n = 22ﺑﻪ
ﻋﻨﻮﺍﻥ »ﺩﺭﺳﺖ« ﺗﻔﺴﻴﺮ ﻣﻲﺷﻮﺩ ﺯﻳﺮﺍ ﻓﻘﻂ ﻣﻘﺪﺍﺭ 0ﺑﻪ ﻣﻌﻨﺎﻱ »ﻧﺎﺩﺭﺳﺖ« ﺍﺳﺖ .ﺑﻪ ﻫﻤﻴﻦ
ﺩﻟﻴﻞ ﺩﺳﺘﻮﺭ ﻗﺒﻞ ﺍﺯ elseﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ .ﺧﻂ ﭘﻨﺠﻢ ﺑﺎﻳﺪ ﺍﻳﻦﻃﻮﺭ ﻧﻮﺷﺘﻪ ﻣﻲﺷﺪ:
;if (n = = 22) cout << "n = 22" << endl // CORRECT
ﺧﻄﺎﻱ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ ،ﺧﻄﺎﻱ ﻣﻨﻄﻘﻲ 1ﻧﺎﻡ ﺩﺍﺭﺩ .ﺍﻳﻦ ﻧﻮﻉ ﺧﻄﺎ،
ﺑﺪﺗﺮﻳﻦ ﻧﻮﻉ ﺧﻄﺎﻫﺎﺳﺖ .ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﻛﺎﻣﭙﺎﻳﻞ )ﻣﺎﻧﻨﺪ ﺍﺯ ﻗﻠﻢ ﺍﻓﺘﺎﺩﻥ ﻳﻚ ﺳﻤﻴﻜﻮﻟﻦ( ﺑﻪ
ﻭﺳﻴﻞۀ ﻛﺎﻣﭙﺎﻳﻠﺮ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ .ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ )ﻣﺎﻧﻨﺪ ﺗﻘﺴﻴﻢ ﺑﺮ ﺻﻔﺮ( ﻧﻴﺰ ﺑﻪ ﻭﺳﻴﻞۀ
ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﺧﻄﺎﻱ ﻣﻨﻄﻘﻲ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﺎ ﺍﻳﻦ ﺍﺑﺰﺍﺭﻫﺎ ﻛﺸﻒ ﮐﺮﺩ.
ﺳﻪ ﺗﻮﺿﻴﺢ ﺫﻛﺮ ﺷﺪﻩ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ،ﻧﺤﻮۀ ﭘﻴﺸﺮﻓﺖ ﮐﺎﺭ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ :ﺍﺑﺘﺪﺍ minﺑﺮﺍﺑﺮ n1
ﻓﺮﺽ ﻣﻲﺷﻮﺩ ،ﻟﺬﺍ minﻛﻤﻴﻦۀ ﻣﺠﻤﻮﻉۀ } {n1ﻣﻲﺷﻮﺩ .ﭘﺲ ﺍﺯ ﺍﺟﺮﺍﻱ ﺍﻭﻟﻴﻦ ،ifﻣﻘﺪﺍﺭ
minﺑﺮﺍﺑﺮ ﺑﺎ n2ﻣﻲﺷﻮﺩ ﺍﮔﺮ n2ﺍﺯ ﻣﻘﺪﺍﺭ ﻓﻌﻠﻲ minﮐﻮﭼﮏﺗﺮ ﺑﺎﺷﺪ .ﭘﺲ minﺑﺮﺍﺑﺮ
ﻛﻤﻴﻦۀ ﻣﺠﻤﻮﻉۀ } {n1,n2ﻣﻲﺷﻮﺩ .ﺁﺧﺮﻳﻦ ﺩﺳﺘﻮﺭ ،ifﻣﻘﺪﺍﺭ minﺭﺍ ﺑﺮﺍﺑﺮ ﺑﺎ n3
ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﺍﮔﺮ n3ﺍﺯ ﻣﻘﺪﺍﺭ ﻓﻌﻠﻲ minﮐﻮﭼﮏﺗﺮ ﺑﺎﺷﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﺭ ﻧﻬﺎﻳﺖ ﻣﻘﺪﺍﺭ
minﺑﺮﺍﺑﺮ ﺑﺎ ﻛﻤﻴﻦۀ ﻣﺠﻤﻮﻉۀ } {n1, n2, n3ﺧﻮﺍﻫﺪ ﺷﺪ.
3‐5ﺑﻠﻮﻙﻫﺎﻱ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ
ﻳﻚ ﺑﻠﻮﻙ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﺯﻧﺠﻴﺮﻩﺍﻱ ﺍﺯ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎﺳﺖ ﻛﻪ ﺩﺭﻭﻥ ﺑﺮﺍﻛﺖ }{
ﻣﺤﺼﻮﺭ ﺷﺪﻩ ،ﻣﺎﻧﻨﺪ ﺍﻳﻦ:
{ ;int temp=x
;x = y
;y = temp
}
69 ﻓﺼﻞ ﺳﻮم /اﻧﺘﺨﺎب
ﺳﻪ ﺩﺳﺘﻮﺭ ﺩﺭﻭﻥ ﺑﻠﻮﻙ ،ﻣﻘﺎﺩﻳﺮ xﻭ yﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﺑﺰﺭﮒﺗﺮﻱ ﻣﺮﺗﺐ ﻣﻲﻛﻨﻨﺪ ﺑﺪﻳﻦ ﺷﮑﻞ
ﻛﻪ ﺍﮔﺮ ﺁﻥﻫﺎ ﺧﺎﺭﺝ ﺍﺯ ﺗﺮﺗﻴﺐ ﺑﺎﺷﻨﺪ ،ﺟﺎﻱ ﺁﻥ ﺩﻭ ﺭﺍ ﻋﻮﺽ ﻣﻲﻛﻨﻨﺪ .ﺑﺮﺍﻱ ﺍﻳﻦ ﺟﺎﺑﺠﺎﻳﻲ
ﺑﻪ ﺳﻪ ﮔﺎﻡ ﻣﺘﻮﺍﻟﻲ ﻭ ﻳﮏ ﻣﺤﻞ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻣﻮﻗﺘﻲ ﺍﺣﺘﻴﺎﺝ ﺩﺍﺭﻳﻢ ﻛﻪ ﺩﺭ ﺍﻳﻦﺟﺎ temp
ﻧﺎﻣﻴﺪﻩ ﺷﺪﻩ .ﺑﺮﻧﺎﻣﻪ ﻳﺎ ﺑﺎﻳﺪ ﻫﺮ ﺳﻪ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﺭﺍ ﺍﺟﺮﺍ ﻛﻨﺪ ﻭ ﻳﺎ ﻫﻴﭻ ﻳﻚ ﺭﺍ ﻧﺒﺎﻳﺪ ﺍﺟﺮﺍ
ﻛﻨﺪ .ﻭﻗﺘﻲ ﺍﻳﻦ ﺳﻪ ﺩﺳﺘﻮﺭ ﺭﺍ ﺩﺭﻭﻥ ﺑﻠﻮﮎ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻗﺮﺍﺭ ﺩﻫﻴﻢ ،ﻣﻨﻈﻮﺭ ﻓﻮﻕ ﺑﺮﺁﻭﺭﺩﻩ
ﻣﻲﺷﻮﺩ .ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﻣﺘﻐﻴﺮ tempﺩﺭﻭﻥ ﺑﻠﻮﻙ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ .ﺍﻳﻦ ﺳﺒﺐ ﻣﻲﺷﻮﺩ
ﻛﻪ ﻣﺘﻐﻴﺮ ﻣﺬﮐﻮﺭ ﺩﺭﻭﻥ ﺑﻠﻮﮎ ،ﻳﻚ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ 1ﺑﺎﺷﺪ .ﻳﻌﻨﻲ ﺍﻳﻦ ﻣﺘﻐﻴﺮ ﻓﻘﻂ ﻭﻗﺘﻲ ﺍﻳﺠﺎﺩ
ﻣﻲﺷﻮﺩ ﮐﻪ ﺑﻠﻮﮎ ﺍﺟﺮﺍ ﺷﻮﺩ .ﺍﮔﺮ ﺷﺮﻁ ﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﺪ )ﻳﻌﻨﻲ x<=yﺑﺎﺷﺪ( ﻣﺘﻐﻴﺮ temp
ﻫﺮﮔﺰ ﻣﻮﺟﻮﺩ ﻧﺨﻮﺍﻫﺪ ﺷﺪ .ﺍﻳﻦ ﻣﺜﺎﻝ ،ﺭﻭﺵ ﻣﻨﺎﺳﺒﻲ ﺑﺮﺍﻱ ﻣﺤﻠﻲ ﻛﺮﺩﻥ ﺍﺷﻴﺎ ﺭﺍ ﻧﺸﺎﻥ
ﻣﻲﺩﻫﺪ ،ﻃﻮﺭﻱ ﻛﻪ ﺍﺷﻴﺎ ﻭﻗﺘﻲ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﻧﺪ ﻛﻪ ﺑﻪ ﺁﻥﻫﺎ ﻧﻴﺎﺯ ﺍﺳﺖ .ﻫﻤﭽﻨﻴﻦ ﺗﻮﺟﻪ ﮐﻨﻴﺪ
ﻛﻪ ﻳﻚ ﺑﺮﻧﺎﻡۀ C++ﺧﻮﺩﺵ ﻳﻚ ﺑﻠﻮﻙ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﺍﺳﺖ ﻛﻪ ﺗﻮﺳﻂ ﺗﺎﺑﻊ
ﺍﺻﻠﻲ )( mainﺳﺎﺧﺘﻪ ﺷﺪﻩ ﺍﺳﺖ .ﻳﺎﺩﺁﻭﺭﻱ ﻣﻲﻛﻨﻴﻢ ﻛﻪ ﺣﻮﺯۀ ﻣﺘﻐﻴﺮ ،ﻗﺴﻤﺘﻲ ﺍﺯ ﻳﻚ
ﺑﺮﻧﺎﻣﻪ ﺍﺳﺖ ﻛﻪ ﻣﺘﻐﻴﺮ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺭ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ)ﺑﺨﺶ .(1‐5ﺍﻳﻦ ﺣﻮﺯﻩ ،ﺍﺯ ﻧﻘﻄﻪﺍﻱ
ﻛﻪ ﻣﺘﻐﻴﺮ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ ﺷﺮﻭﻉ ﺷﺪﻩ ﻭ ﺗﺎ ﭘﺎﻳﺎﻥ ﻫﻤﺎﻥ ﺑﻠﻮﻙ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ .ﭘﺲ ﻳﻚ ﺑﻠﻮﻙ
ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﻋﻨﻮﺍﻥ ﻣﺤﺪﻭﺩۀ ﺣﻮﺯۀ ﻣﺘﻐﻴﺮ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ .ﻳﮑﻲ ﺍﺯ ﻧﺘﺎﻳﺞ ﻣﻬﻢ ﺍﻳﻦ ﮐﺎﺭ ﺁﻥ ﺍﺳﺖ
ﮐﻪ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺘﻔﺎﻭﺗﻲ ﺑﺎ ﻳﮏ ﻧﺎﻡ ﺩﺭ ﻗﺴﻤﺖﻫﺎﻱ ﻣﺨﺘﻠﻒ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ.
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺳﻪ ﺑﻠﻮﻙ ﺩﺍﺧﻠﻲ ﺩﺍﺭﺩ .ﺍﻭﻟﻴﻦ ﺑﻠﻮﻙ ﻳﻚ nﺟﺪﻳﺪ ﺍﻋﻼﻥ ﻣﻲﻛﻨﺪ ﻛﻪ ﻓﻘﻂ ﺩﺭﻭﻥ
ﻫﻤﺎﻥ ﺑﻠﻮﻙ ،ﻣﻌﺘﺒﺮ ﻭ ﻣﻮﺟﻮﺩ ﺍﺳﺖ .ﺍﻳﻦ nﻣﺘﻐﻴﺮ nﺍﺻﻠﻲ ﺭﺍ ﭘﻨﻬﺎﻥ ﻣﻲﮐﻨﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻭﻗﺘﻲ
ﻣﻘﺪﺍﺭ 77ﺩﺭ ﺍﻳﻦ ﺑﻠﻮﮎ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﻣﻲﺷﻮﺩ ،ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ nﻣﺤﻠﻲ ﻗﺮﺍﺭ
ﻣﻲﮔﻴﺮﺩ ﻭ ﻣﻘﺪﺍﺭ nﺍﺻﻠﻲ ﺑﺪﻭﻥ ﺗﻐﻴﻴﺮ ﻣﻲﻣﺎﻧﺪ .ﺩﺭ ﺩﻭﻣﻴﻦ ﺑﻠﻮﻙ nﺟﺪﻳﺪﻱ ﺗﻌﺮﻳﻒ
71 ﻓﺼﻞ ﺳﻮم /اﻧﺘﺨﺎب
ﻧﻤﻲﺷﻮﺩ ،ﻟﺬﺍ ﺣﻮﺯۀ nﺍﺻﻠﻲ ﺍﻳﻦ ﺑﻠﻮﻙ ﺭﺍ ﻧﻴﺰ ﺷﺎﻣﻞ ﻣﻲﺷﻮﺩ .ﭘﺲ ﺩﺭ ﺳﻮﻣﻴﻦ ﺩﺳﺘﻮﺭ
ﺧﺮﻭﺟﻲ ،ﻣﻘﺪﺍﺭ nﺍﺻﻠﻲ ﻳﻌﻨﻲ 44ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﺑﻠﻮﮎ ﺳﻮﻡ ﺑﺮﻧﺎﻣﻪ ﻧﻴﺰ ﻣﺎﻧﻨﺪ ﺑﻠﻮﮎ ﺍﻭﻝ
ﻳﮏ nﺟﺪﻳﺪ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ nﺍﺻﻠﻲ ﺭﺍ ﭘﻨﻬﺎﻥ ﻣﻲﻧﻤﺎﻳﺪ ،ﺍﻣﺎ ﺍﻳﻦ nﺟﺪﻳﺪ ﻣﻘﺪﺍﺭﺩﻫﻲ
ﻧﻤﻲﺷﻮﺩ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﺭ ﭼﻬﺎﺭﻣﻴﻦ ﺧﺮﻭﺟﻲ ،ﻳﻚ ﻣﻘﺪﺍﺭ ﺯﺑﺎﻟﻪ ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﺩﺭ ﺧﻂ ﺍﻧﺘﻬﺎﻳﻲ
ﺑﺮﻧﺎﻣﻪ ،ﺗﻤﺎﻡ ﺑﻠﻮﮎﻫﺎﻱ ﻣﺤﻠﻲ ﺑﻪ ﭘﺎﻳﺎﻥ ﻣﻲﺭﺳﻨﺪ .ﺑﻪ ﻫﻤﻴﻦ ﺧﺎﻃﺮ ﻭﻗﺘﻲ ﺩﺭ ﺍﻳﻦ ﺧﻂ ﺩﺳﺘﻮﺭ
ﭼﺎﭖ ﺑﺮﺍﻱ nﺻﺎﺩﺭ ﻣﻲﺷﻮﺩ ،ﻣﻘﺪﺍﺭ nﺍﺻﻠﻲ ﻳﻌﻨﻲ 44ﭼﺎﭖ ﻣﻲﺷﻮﺩ.
3‐6ﺷﺮﻁﻫﺎﻱ ﻣﺮﻛﺐ
ﺷﺮﻁﻫﺎﻳﻲ ﻣﺎﻧﻨﺪ n%dﻭ x>=yﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﻪ ﺻﻮﺭﺕ ﻳﻚ ﺷﺮﻁ ﻣﺮﻛﺐ ﺑﺎ ﻫﻢ
ﺗﺮﻛﻴﺐ ﺷﻮﻧﺪ .ﺍﻳﻦ ﻛﺎﺭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯﻋﻤﻠﮕﺮﻫﺎﻱ ﻣﻨﻄﻘﻲ && ) (andﻭ || ) (orﻭ !
) (notﺻﻮﺭﺕ ﻣﻲﭘﺬﻳﺮﺩ .ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺗﻌﺮﻳﻒ ﻣﻲﺷﻮﻧﺪ:
p && qﺩﺭﺳﺖ ﺍﺳﺖ ﺍﮔﺮ ﻭ ﺗﻨﻬﺎ ﺍﮔﺮ ﻫﻢ pﻭ ﻫﻢ qﻫﺮ ﺩﻭ ﺩﺭﺳﺖ ﺑﺎﺷﻨﺪ
p || qﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ ﺍﮔﺮ ﻭ ﺗﻨﻬﺎ ﺍﮔﺮ ﻫﻢ pﻭ ﻫﻢ qﻫﺮ ﺩﻭ ﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﻨﺪ
!pﺩﺭﺳﺖ ﺍﺳﺖ ﺍﮔﺮ ﻭ ﺗﻨﻬﺎ ﺍﮔﺮ pﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﺪ
ﺑﺮﺍﻱ ﻣﺜﺎﻝ) (n%d || x>=yﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ ﺍﮔﺮ ﻭ ﺗﻨﻬﺎ ﺍﮔﺮ n%dﺑﺮﺍﺑﺮ ﺻﻔﺮ ﻭ x
ﻛﻮﭼﻚﺗﺮ ﺍﺯ yﺑﺎﺷﺪ.
ﺳﻪ ﻋﻤﻠﮕﺮ ﻣﻨﻄﻘﻲ ﺑﺎﻻ ﻣﻌﻤﻮﻻ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺟﺪﺍﻭﻝ ﺩﺭﺳﺘﻲ ﺑﻪ ﮔﻮﻥۀ ﺯﻳﺮ ﺑﻴﺎﻥ
ﻣﻲﺷﻮﻧﺪ:
ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻫﻤﺎﻥ ﻣﺴﺄﻝۀ ﻣﺜﺎﻝ 3‐5ﺭﺍ ﺣﻞ ﻣﻲﻛﻨﺪ ﻭﻟﻲ ﺍﻳﻦ ﮐﺎﺭ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﺷﺮﻁﻫﺎﻱ ﻣﺮﮐﺐ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ.
ﺑﺮﻧﺎﻣﻪﺍﻱ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ ﺁﻣﺪ ﻫﻴﭻ ﻣﺰﻳﺘﻲ ﺑﺮ ﻣﺜﺎﻝ 3‐5ﻧﺪﺍﺭﺩ ﻭ ﻓﻘﻂ ﻧﺤﻮۀ ﺍﺳﺘﻔﺎﺩﻩ
ﺍﺯ ﺷﺮﻁﻫﺎﻱ ﻣﺮﻛﺐ ﺭﺍ ﺑﻴﺎﻥ ﻣﻲﻛﻨﺪ .ﺩﺭ ﻣﺜﺎﻝ ﺯﻳﺮ ﻫﻢ ﺍﺯ ﺷﺮﻁ ﻣﺮﻛﺐ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ.
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺯ ﻛﺎﺭﺑﺮ ﭘﺎﺳﺨﻲ ﻣﻲﺧﻮﺍﻫﺪ ﻭ yﻭ nﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﺟﻮﺍﺏﻫﺎﻱ ﻣﻤﮑﻦ ﭘﻴﺸﻨﻬﺎﺩ
ﻣﻲﺩﻫﺪ .ﺍﻣﺎ ﻫﺮ ﻛﺎﺭﺍﻛﺘﺮ ﺩﻳﮕﺮﻱ ﺭﺍ ﻫﻢ ﻣﻲﭘﺬﻳﺮﺩ ﻭ ﺍﮔﺮ ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ ' 'yﻳﺎ ' 'Yﻧﺒﺎﺷﺪ،
ﻓﺮﺽ ﻣﻲﻛﻨﺪ ﻛﻪ ﭘﺎﺳﺦ ﻛﺎﺭﺑﺮ " "noﺍﺳﺖ.
3‐7ﺍﺭﺯﻳﺎﺑﻲ ﻣﻴﺎﻧﺒﺮﻱ
ﻋﻤﻠﮕﺮﻫﺎﻱ && ﻭ || ﺑﻪ ﺩﻭ ﻋﻤﻠﻮﻧﺪ ﻧﻴﺎﺯ ﺩﺍﺭﻧﺪ .ﻳﻌﻨﻲ ﺑﻪ ﺩﻭ ﻣﻘﺪﺍﺭ ﻧﻴﺎﺯ ﺩﺍﺭﻧﺪ ﺗﺎ
ﻣﻘﺎﻳﺴﻪ ﺭﺍ ﺭﻭﻱ ﺁﻥ ﺩﻭ ﺍﻧﺠﺎﻡ ﺩﻫﻨﺪ .ﺷﺮﻁﻫﺎﻱ ﻣﺮﻛﺐ ﻛﻪ ﺍﺯ && ﻭ || ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻛﻨﻨﺪ
ﻋﻤﻠﻮﻧﺪ ﺩﻭﻡ ﺭﺍ ﺑﺮﺭﺳﻲ ﻧﻤﻲﻛﻨﻨﺪ ﻣﮕﺮ ﺍﻳﻦ ﻛﻪ ﻻﺯﻡ ﺑﺎﺷﺪ .ﺟﺪﺍﻭﻝ ﺩﺭﺳﺘﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ
p&&qﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ ﺍﮔﺮ pﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﺪ .ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺩﻳﮕﺮ ﻧﻴﺎﺯﻱ ﻧﻴﺴﺖ ﮐﻪ q
ﺑﺮﺭﺳﻲ ﺷﻮﺩ .ﻫﻤﭽﻨﻴﻦ p||qﺩﺭﺳﺖ ﺍﺳﺖ ﺍﮔﺮ pﺩﺭﺳﺖ ﺑﺎﺷﺪ ﻭ ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﻫﻢ
ﻧﻴﺎﺯﻱ ﻧﻴﺴﺖ ﮐﻪ qﺑﺮﺭﺳﻲ ﺷﻮﺩ .ﺩﺭ ﻫﺮ ﺩﻭ ﺣﺎﻟﺖ ﮔﻔﺘﻪ ﺷﺪﻩ ،ﺑﺎ ﺍﺭﺯﻳﺎﺑﻲ ﻋﻤﻠﻮﻧﺪ ﺍﻭﻝ ﺑﻪ
ﺳﺮﻋﺖ ﻧﺘﻴﺠﻪ ﻣﻌﻠﻮﻡ ﻣﻲﺷﻮﺩ .ﺍﻳﻦ ﻛﺎﺭ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻴﺎﻧﺒﺮﻱ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ.
ﺩﺭ ﺍﺟﺮﺍﻱ ﺯﻳﺮ d ،ﻣﺜﺒﺖ ﻭ n%dﺻﻔﺮ ﺍﺳﺖ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﺷﺮﻁ ﻣﺮﻛﺐ ﺩﺭﺳﺖ ﺍﺳﺖ:
Enter two integers: 300 5
5 divides 300
ﺩﺭ ﺍﺟﺮﺍﻱ ﺑﻌﺪﻱ d ،ﻣﺜﺒﺖ ﺍﺳﺖ ﺍﻣﺎ n%dﺻﻔﺮ ﻧﻴﺴﺖ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﺷﺮﻁ ﻣﺮﻛﺐ
ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ:
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 74
ﺩﺭ ﺁﺧﺮﻳﻦ ﺍﺟﺮﺍ d ،ﺻﻔﺮ ﺍﺳﺖ .ﭘﺲ ﺑﻪ ﺳﺮﻋﺖ ﺑﺮﺁﻭﺭﺩ ﻣﻲﺷﻮﺩ ﮐﻪ ﺷﺮﻁ ﻣﺮﻛﺐ
ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ ﺑﺪﻭﻥ ﺍﻳﻦ ﻛﻪ ﻋﺒﺎﺭﺕ ﺩﻭﻡ ﻳﻌﻨﻲ n%d == 0ﺍﺭﺯﻳﺎﺑﻲ ﺷﻮﺩ:
Enter two integers: 300 0
0 does not divide 300
ﺍﺭﺯﻳﺎﺑﻲ ﻣﻴﺎﻧﺒﺮﻱ ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﺍﺯ ﺧﺮﺍﺑﻲ ﺑﺮﻧﺎﻣﻪ ﺟﻠﻮﮔﻴﺮﻱ ﻣﻲﻛﻨﺪ ﺯﻳﺮﺍ ﻭﻗﺘﻲ dﺻﻔﺮ
ﺍﺳﺖ ،ﺭﺍﻳﺎﻧﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ ﻋﺒﺎﺭﺕ n%dﺭﺍ ﻣﺤﺎﺳﺒﻪ ﮐﻨﺪ.
3‐8ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ
ﻳﻚ ﻋﺒﺎﺭﺕ ﻣﻨﻄﻘﻲ ﺷﺮﻃﻲ ﺍﺳﺖ ﻛﻪ ﻳﺎ ﺩﺭﺳﺖ ﺍﺳﺖ ﻳﺎ ﻧﺎﺩﺭﺳﺖ .ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻠﻲ
ﻋﺒﺎﺭﺍﺕ d>0ﻭ n%d == 0ﻭ ) (d>0 && n%d==0ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ ﻫﺴﺘﻨﺪ .ﻗﺒﻼ
ﺩﻳﺪﻳﻢ ﮐﻪ ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ ﺑﺎ ﻣﻘﺎﺩﻳﺮ ﺻﺤﻴﺢ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﻧﺪ .ﻣﻘﺪﺍﺭ ﺻﻔﺮ ﺑﻪ ﻣﻌﻨﺎﻱ
ﻧﺎﺩﺭﺳﺖ ﻭ ﻫﺮ ﻣﻘﺪﺍﺭ ﻏﻴﺮ ﺻﻔﺮ ﺑﻪ ﻣﻌﻨﺎﻱ ﺩﺭﺳﺖ ﺍﺳﺖ .ﺑﻪ ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ »ﻋﺒﺎﺭﺍﺕ ﺑﻮﻟﻲ«
ﻫﻢ ﻣﻲﮔﻮﻳﻨﺪ.
ﭼﻮﻥ ﻫﻢۀ ﻣﻘﺎﺩﻳﺮ ﺻﺤﻴﺢ ﻧﺎﺻﻔﺮ ﺑﻪ ﻣﻌﻨﺎﻱ ﺩﺭﺳﺖ ﺗﻔﺴﻴﺮ ﻣﻲﺷﻮﻧﺪ ،ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ
ﺍﻏﻠﺐ ﺗﻐﻴﻴﺮ ﻗﻴﺎﻓﻪ ﻣﻲﺩﻫﻨﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺩﺳﺘﻮﺭ
;"if (n) cout << "n is not zero
ﻭﻗﺘﻲ nﻏﻴﺮ ﺻﻔﺮ ﺍﺳﺖ ﻋﺒﺎﺭﺕ n is not zeroﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ ﺯﻳﺮﺍ ﻋﺒﺎﺭﺕ
ﻣﻨﻄﻘﻲ ) (nﻭﻗﺘﻲ ﻣﻘﺪﺍﺭ nﻏﻴﺮ ﺻﻔﺮ ﺍﺳﺖ ﺑﻪ ﻋﻨﻮﺍﻥ ﺩﺭﺳﺖ ﺗﻔﺴﻴﺮ ﻣﻲﮔﺮﺩﺩ .ﮐﺪ ﺯﻳﺮ ﺭﺍ
ﻧﮕﺎﻩ ﮐﻨﻴﺪ:
;"if (n%d) cout << "n is not a multiple of d
ﺩﺳﺘﻮﺭ ﺧﺮﻭﺟﻲ ﻓﻘﻂ ﻭﻗﺘﻲ ﻛﻪ n%dﻧﺎﺻﻔﺮ ﺍﺳﺖ ﺍﺟﺮﺍ ﻣﻲﮔﺮﺩﺩ ﻭ n%dﻭﻗﺘﻲ ﻧﺎﺻﻔﺮ
ﺍﺳﺖ ﮐﻪ nﺑﺮ dﺑﺨﺶﭘﺬﻳﺮ ﻧﺒﺎﺷﺪ .ﮔﺎﻫﻲ ﻣﻤﮑﻦ ﺍﺳﺖ ﻓﺮﺍﻣﻮﺵ ﮐﻨﻴﻢ ﮐﻪ ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ
ﻣﻘﺎﺩﻳﺮ ﺻﺤﻴﺢ ﺩﺍﺭﻧﺪ ﻭ ﺍﻳﻦ ﻓﺮﺍﻣﻮﺷﻲ ﺑﺎﻋﺚ ﺍﻳﺠﺎﺩ ﻧﺘﺎﻳﺞ ﻏﻴﺮ ﻣﻨﺘﻈﺮﻩ ﻭ ﻧﺎﻣﺘﻌﺎﺭﻑ ﺷﻮﺩ.
75 ﻓﺼﻞ ﺳﻮم /اﻧﺘﺨﺎب
ﻣﻨﺸﺄ ﺧﻄﺎ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﻳﻦ ﺍﺻﻞ ﺍﺳﺖ ﻛﻪ ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ ﻣﻘﺪﺍﺭﻫﺎﻱ ﻋﺪﺩﻱ ﺩﺍﺭﻧﺪ .ﭼﻮﻥ
ﻋﺒﺎﺭﺕ ) (n1>=n2>=n3ﺍﺯ ﭼﭗ ﺑﻪ ﺭﺍﺳﺖ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ،ﺑﻪ ﺍﺯﺍﻱ ﻭﺭﻭﺩﻱﻫﺎﻱ ﻓﻮﻕ
ﺍﻭﻟﻴﻦ ﺑﺨﺶ ﺍﺭﺯﻳﺎﺑﻲ ﻳﻌﻨﻲ n1>=n2ﺩﺭﺳﺖ ﺍﺳﺖ ﭼﻮﻥ 0>=0ﺍﻣﺎ »ﺩﺭﺳﺖ« ﺑﻪ ﺷﮑﻞ
ﻋﺪﺩ 1ﺩﺭ ﺣﺎﻓﻈﻪ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﺷﻮﺩ .ﺳﭙﺲ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﺎ ﻣﻘﺪﺍﺭ n3ﻛﻪ 1ﻣﻲﺑﺎﺷﺪ ﻣﻘﺎﻳﺴﻪ
ﻣﻲﺷﻮﺩ .ﻳﻌﻨﻲ ﻋﺒﺎﺭﺕ 1>=1ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻳﻦ ﻫﻢ ﺩﺭﺳﺖ ﺍﺳﺖ .ﻧﺘﻴﺠﻪ ﺍﻳﻦ ﺍﺳﺖ
ﮐﻪ ﮐﻞ ﻋﺒﺎﺭﺕ ﺑﻪ ﻋﻨﻮﺍﻥ ﺩﺭﺳﺖ ﺗﻔﺴﻴﺮ ﻣﻲﺷﻮﺩ ﮔﺮﭼﻪ ﺩﺭ ﺣﻘﻴﻘﺖ ﺍﻳﻦ ﻃﻮﺭ ﻧﻴﺴﺖ! ) 0
ﺑﻴﺸﻴﻦۀ 0ﻭ 1ﻧﻴﺴﺖ(
ﺍﻳﺮﺍﺩ ﮐﺎﺭ ﺍﻳﻦﺟﺎﺳﺖ ﻛﻪ ﺧﻂ ﺍﺷﺘﺒﺎﻩ ﺑﻪ ﻃﻮﺭ ﻧﺤﻮﻱ ﺻﺤﻴﺢ ﺍﺳﺖ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻧﻪ
ﻛﺎﻣﭙﺎﻳﻠﺮ ﻣﻲﺗﻮﺍﻧﺪ ﺧﻄﺎ ﺑﮕﻴﺮﺩ ﻭ ﻧﻪ ﺳﻴﺴﺘﻢﻋﺎﻣﻞ .ﺍﻳﻦ ﻧﻮﻉ ﺩﻳﮕﺮﻱ ﺍﺯ ﺧﻄﺎﻱ ﻣﻨﻄﻘﻲ ﺍﺳﺖ
ﻛﻪ ﺑﺎ ﺁﻥﭼﻪ ﺩﺭ ﻣﺜﺎﻝ 3‐4ﻣﻄﺮﺡ ﺷﺪ ﻗﺎﺑﻞ ﻣﻘﺎﻳﺴﻪ ﺍﺳﺖ .ﻧﺘﻴﺞۀ ﺍﻳﻦ ﻣﺜﺎﻝ ﺁﻥ ﺍﺳﺖ ﻛﻪ:
»ﻫﻤﻴﺸﻪ ﺑﻪ ﺧﺎﻃﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ ﻣﻘﺪﺍﺭ ﻋﺪﺩﻱ ﺩﺍﺭﻧﺪ ،ﺑﻨﺎﺑﺮﺍﻳﻦ ﺷﺮﻁﻫﺎﻱ
ﻣﺮﻛﺐ ﻣﻲﺗﻮﺍﻧﻨﺪ ﮔﻮﻝﺯﻧﻨﺪﻩ ﺑﺎﺷﻨﺪ«.
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ،ﺩﺳﺘﻮﺭ if..elseﺩﻭﻡ ﺩﺭﻭﻥ ﺩﺳﺘﻮﺭ if..elseﺍﻭﻝ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ
ﺍﺳﺖ .ﭘﺲ if..elseﺩﻭﻡ ﻭﻗﺘﻲ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ﻛﻪ dﺻﻔﺮ ﻧﺒﺎﺷﺪ .ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺩﺭ
ﺍﻳﻦﺟﺎ ﻣﺠﺒﻮﺭﻳﻢ ﺩﻭ ﺑﺎﺭ ﺍﺯ ﻋﺒﺎﺭﺕ does not divideﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﻢ .ﺍﻭﻟﻲ ﺩﺭ ﺍﻭﻟﻴﻦ
ﺩﺳﺘﻮﺭ if..elseﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﻭ ﺯﻣﺎﻧﻲ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ﻛﻪ dﺻﻔﺮ ﻧﺒﺎﺷﺪ ﻭ n%dﺻﻔﺮ
ﮔﺮﺩﺩ .ﺩﻭﻣﻲ ﻫﻢ ﻭﻗﺘﻲ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ﻛﻪ dﺻﻔﺮ ﺑﺎﺷﺪ.
ﻭﻗﺘﻲ ﺩﺳﺘﻮﺭ if..elseﺑﻪ ﺷﮑﻞ ﺗﻮ ﺩﺭ ﺗﻮ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ ،ﻛﺎﻣﭙﺎﻳﻠﺮ ﺍﺯ ﻗﺎﻧﻮﻥ ﺯﻳﺮ
ﺟﻬﺖ ﺗﺠﺰﻳﻪ ﺍﻳﻦ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻣﺮﻛﺐ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻛﻨﺪ:
» ﻫﺮ elseﺑﺎ ﺁﺧﺮﻳﻦ ifﺗﻨﻬﺎ ﺟﻔﺖ ﻣﻲﺷﻮﺩ«.
ﺑﺎ ﺑﻪﮐﺎﺭﮔﻴﺮﻱ ﺍﻳﻦ ﻗﺎﻧﻮﻥ ،ﻛﺎﻣﭙﺎﻳﻠﺮ ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻧﺪ ﻛﺪ ﭘﻴﭽﻴﺪۀ ﺯﻳﺮ ﺭﺍ ﺭﻣﺰ ﮔﺸﺎﻳﻲ ﻛﻨﺪ:
)if (a > 0) if (b > 0) ++a; else if (c > 0 //BAD CODING STYLE
if (a > 4) ++b; else ;if (b < 4) ++c; else –a //BAD CODING STYLE
;else if (c < 4) --b; else --c; else a = 0 //BAD CODING STYLE
ﺑﺮﺍﻱ ﺍﻳﻦ ﻛﻪ ﻛﺪ ﺑﺎﻻ ﺭﺍ ﺧﻮﺍﻧﺎﺗﺮ ﻭ ﻗﺎﺑﻞ ﻓﻬﻢ ﻛﻨﻴﻢ ،ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﻥ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺑﻨﻮﻳﺴﻴﻢ:
)if (a > 0
;if (b > 0) ++a
else
)if (c > 0
;if (a < 4) ++b
77 اﻧﺘﺨﺎب/ ﻓﺼﻞ ﺳﻮم
else
if (b < 4) ++c;
else –a;
else
if (c < 4) –b;
else –c;
else a = 0;
ﺩﺭ ﺍﺟﺮﺍﻱ ﺑﺎﻻ ،ﺍﻭﻟﻴﻦ ﺷﺮﻁ ) (n1<n2ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ ﻭ ﺳﻮﻣﻴﻦ ﺷﺮﻁ ) (n2<n3ﺩﺭﺳﺖ
ﺍﺳﺖ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﮔﺰﺍﺭﺵ ﻣﻲﺷﻮﺩ ﻛﻪ n2ﻛﻤﻴﻨﻪ ﺍﺳﺖ.
ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 3‐8ﻣﻮﺛﺮﺗﺮ ﺍﺳﺖ ﺯﻳﺮﺍ ﺩﺭ ﻫﺮ ﺍﺟﺮﺍﻱ ﺁﻥ ﻓﻘﻂ ﺩﻭ ﺷﺮﻁ
ﺳﺎﺩۀ ﺗﻮﺩﺭﺗﻮ ﺑﻪ ﺟﺎﻱ ﺳﻪ ﺷﺮﻁ ﻣﺮﻛﺐ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﻭﻟﻲ ﺑﻪ ﻧﻈﺮ ﻣﻲﺭﺳﺪ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ
ﺍﺭﺯﺵ ﻛﻢﺗﺮﻱ ﻧﺴﺒﺖ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 3‐8ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺯﻳﺮﺍ ﻣﻨﻄﻖ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﭘﻴﭽﻴﺪﻩﺗﺮ
ﺍﺳﺖ .ﺩﺭ ﻣﻘﺎﻳﺴﻪ ﺑﻴﻦ ﻛﺎﺭﺍﻳﻲ ﻭ ﺳﺎﺩﮔﻲ ،ﻣﻌﻤﻮﻻ ﺑﻬﺘﺮ ﺍﺳﺖ ﺳﺎﺩﮔﻲ ﺍﻧﺘﺨﺎﺏ ﮔﺮﺩﺩ.
{ ;cout >> "Is it less than 6? (y|n): "; cin >> answer
"if (answer = = 'y') cout << "Your number is 5.
;<< endl
;else cout << "Your number is 6." << endl
}
else // 7 <= n <= 8
;{ cout << "Is it less than 8? (y n): "; cin >> answer
"if (answer = = 'y') cout << "your number is 7.
;<< endl
;else cout << "Your number is 8." << endl
}
}
}
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺑﺎ ﺗﺠﺰﻱۀ ﻣﺴﺄﻟﻪ ﻗﺎﺩﺭ ﺍﺳﺖ ﺗﻨﻬﺎ ﺑﺎ ﺳﻪ ﭘﺮﺳﺶ ،ﻫﺮ ﻳﻚ ﺍﺯ ﻫﺸﺖ ﻋﺪﺩ ﺭﺍ
ﭘﻴﺪﺍ ﻛﻨﺪ .ﺩﺭ ﺍﺟﺮﺍﻱ ﺯﻳﺮ ،ﮐﺎﺭﺑﺮ ﻋﺪﺩ 6ﺭﺍ ﺩﺭ ﻧﻈﺮ ﺩﺍﺷﺘﻪ ﺍﺳﺖ:
Pick a number from 1 to 8.
Is it less than 5? (y|n) : n
Is it less than 7? (y|n) : y
Is it less than 6? (y|n) : n
Your number is 6.
ﺳﻌﻲ ﮐﻨﻴﺪ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ ﮐﺸﻒ ﮐﻨﻴﺪ .ﺑﻪ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺩﺭ ﻣﺜﺎﻝ 3‐14
ﺍﻟﮕﻮﺭﻳﺘﻢ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ 1ﻣﻲﮔﻮﻳﻨﺪ .ﺍﻳﻦ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺭﻭﻱ ﻣﺠﻤﻮﻋﻪﻫﺎﻱ ﻣﺮﺗﺐ ﺑﻪ ﮐﺎﺭ
ﻣﻲﺭﻭﺩ ﻭ ﺑﻪ ﺳﺮﻋﺖ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ ﺁﻳﺎ ﻳﮏ ﺩﺍﺩۀ ﻣﻔﺮﻭﺽ ﺩﺭ ﺍﻳﻦ ﻣﺠﻤﻮﻋﻪ ﻫﺴﺖ ﻳﺎ
ﺧﻴﺮ .ﺩﺭ ﻓﺼﻞﻫﺎﻱ ﺑﻌﺪﻱ ﺭﻭﺵﻫﺎﻱ ﺩﻳﮕﺮﻱ ﺍﺯ ﺟﺴﺘﺠﻮ ﺭﺍ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ.
ﺑﻴﺸﺘﺮ ﺍﺳﺘﻔﺎﺩﻩ،ﺍﻣﺎ ﻗﺎﻟﺐ ﻗﺒﻠﻲ ﺑﻪ ﻋﻠﺖ ﺍﻳﻦ ﻛﻪ ﺩﺭﮎ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺁﺳﺎﻥﺗﺮ ﻣﻲﮐﻨﺪ
. ﻫﻤﭽﻨﻴﻦ ﺑﻪ ﺗﻮﺭﻓﺘﮕﻲ ﻛﻤﺘﺮﻱ ﺍﺣﺘﻴﺎﺝ ﺩﺍﺭﺩ.ﻣﻲﺷﻮﺩ
81 اﻧﺘﺨﺎب/ ﻓﺼﻞ ﺳﻮم
switch ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ3‐11
Goodbye.
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺑﺘﺪﺍ scoreﺑﺮ 10ﺗﻘﺴﻴﻢ ﻣﻲﺷﻮﺩ ﺗﺎ ﻣﺤﺪﻭﺩۀ ﺍﻋﺪﺍﺩ ﺑﻴﻦ ﺻﻔﺮ ﺗﺎ 10
ﻣﺤﺪﻭﺩ ﺷﻮﺩ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﺭ ﺍﺟﺮﺍﻱ ﺁﺯﻣﺎﻳﺸﻲ ،ﻧﻤﺮۀ 83ﺑﻪ 8ﺗﺒﺪﻳﻞ ﻣﻲﺷﻮﺩ ،ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ
ﺑﻪ case 8ﺍﻧﺸﻌﺎﺏ ﻣﻲﮐﻨﺪ ﻭ ﺧﺮﻭﺟﻲ ﻣﺮﺑﻮﻃﻪ ﭼﺎﭖ ﻣﻲﮔﺮﺩﺩ .ﺳﭙﺲ ﺩﺳﺘﻮﺭ break
ﻣﻮﺟﺐ ﻣﻲﺷﻮﺩ ﻛﻪ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺩﺳﺘﻮﺭ switchﺧﺎﺭﺝ ﺷﺪﻩ ﻭ ﺑﻪ ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ﺑﻌﺪ
ﺍﺯ ﺑﻠﻮﻙ switchﺍﻧﺸﻌﺎﺏ ﻛﻨﺪ .ﺩﺭ ﺁﻥﺟﺎ ﻋﺒﺎﺭﺕ " "Goodbye.ﭼﺎﭖ ﻣﻲﺷﻮﺩ.
ﻻﺯﻡ ﺍﺳﺖ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﻫﺮ caseﺩﺳﺘﻮﺭ breakﻗﺮﺍﺭ ﺑﮕﻴﺮﺩ .ﺑﺪﻭﻥ ﺍﻳﻦ ﺩﺳﺘﻮﺭ،
ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﭘﺲ ﺍﺯ ﺍﻳﻦ ﻛﻪ caseﻣﺮﺑﻮﻃﻪ ﺭﺍ ﺍﺟﺮﺍ ﮐﺮﺩ ﺍﺯ ﺩﺳﺘﻮﺭ switchﺧﺎﺭﺝ
ﻧﻤﻲﺷﻮﺩ ،ﺑﻠﮑﻪ ﻫﻢۀ caseﻫﺎﻱ ﺯﻳﺮﻳﻦ ﺭﺍ ﻫﻢ ﺧﻂ ﺑﻪ ﺧﻂ ﻣﻲﭘﻴﻤﺎﻳﺪ ﻭ ﺩﺳﺘﻮﺭﺍﺕ ﻣﻘﺎﺑﻞ
ﺁﻥﻫﺎ ﺭﺍ ﺍﺟﺮﺍ ﻣﻲﮐﻨﺪ .ﺑﻪ ﺍﻳﻦ ﺍﺗﻔﺎﻕ ،ﺗﻞۀ ﺳﻘﻮﻁ 1ﻣﻲﮔﻮﻳﻨﺪ.
ﺩﺭ ﺍﺟﺮﺍﻱ ﻓﻮﻕ ﭘﺲ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺑﻪ case 8ﺍﻧﺸﻌﺎﺏ ﺷﺪ ﻭ ﻋﺒﺎﺭﺕ ﻣﻘﺎﺑﻞ ﺁﻥ ﭼﺎﭖ ﺷﺪ،
ﭼﻮﻥ ﺩﺳﺘﻮﺭ breakﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ ،ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺧﻂ ﺑﻌﺪﻱ ﻳﻌﻨﻲ case 7ﻣﻲﺭﻭﺩ
ﺭﺍ ﻧﻴﺰ ﭼﺎﭖ ﻣﻲﮐﻨﺪ ﻭ ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﻳﮑﻲ ﻳﮑﻲ ""Your grade is a C. ﻭ ﻋﺒﺎﺭﺕ
ﻫﻢۀ ﻋﺒﺎﺭﺕﻫﺎﻱ caseﺭﺍ ﺍﺟﺮﺍ ﻣﻲﻧﻤﺎﻳﺪ ﻭ ﺳﺮﺍﻧﺠﺎﻡ ﻋﺒﺎﺭﺕ defaultﺭﺍ ﻫﻢ ﺍﺟﺮﺍ
ﻧﻤﻮﺩﻩ ﻭ ﺁﻧﮕﺎﻩ ﺍﺯ ﺩﺳﺘﻮﺭ switchﺧﺎﺭﺝ ﻣﻲﺷﻮﺩ.
ﺩﺭ ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺍﺑﺘﺪﺍ ﺷﺮﻁ conditionﺑﺮﺭﺳﻲ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ ﺍﻳﻦ ﺷﺮﻁ ﺩﺭﺳﺖ ﺑﻮﺩ،
ﺣﺎﺻﻞ ﮐﻞ ﻋﺒﺎﺭﺕ ﺑﺮﺍﺑﺮ ﺑﺎ expression1ﻣﻲﺷﻮﺩ ﻭ ﺍﮔﺮ ﺷﺮﻁ ﻧﺎﺩﺭﺳﺖ ﺑﻮﺩ ،ﺣﺎﺻﻞ
ﮐﻞ ﻋﺒﺎﺭﺕ ﺑﺮﺍﺑﺮ ﺑﺎ expression2ﻣﻲﺷﻮﺩ .ﻣﺜﻼ ﺩﺭ ﺩﺳﺘﻮﺭ ﺍﻧﺘﺴﺎﺏ ﺯﻳﺮ:
;) min = ( x<y ? x : y
ﺍﮔﺮ x<yﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ xﺭﺍ ﺩﺭﻭﻥ minﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﻭ ﺍﮔﺮ x<yﻧﺒﺎﺷﺪ ﻣﻘﺪﺍﺭ yﺭﺍ ﺩﺭﻭﻥ
minﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ .ﻳﻌﻨﻲ ﺑﻪ ﻫﻤﻴﻦ ﺳﺎﺩﮔﻲ ﻭ ﺍﺧﺘﺼﺎﺭ ،ﻣﻘﺪﺍﺭ ﮐﻤﻴﻦۀ xﻭ yﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ
minﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﻳﮏ ﻋﻤﻠﮕﺮ ﺳﻪﮔﺎﻧﻪ ﺍﺳﺖ .ﻳﻌﻨﻲ ﺳﻪ ﻋﻤﻠﻮﻧﺪ ﺭﺍ
85 ﻓﺼﻞ ﺳﻮم /اﻧﺘﺨﺎب
ﺑﺮﺍﻱ ﺗﻬﻲۀ ﻳﮏ ﻣﻘﺪﺍﺭ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﺩ .ﺑﻬﺘﺮ ﺍﺳﺖ ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﻓﻘﻂ ﺩﺭ ﻣﻮﺍﻗﻊ
ﺿﺮﻭﺭﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ؛ ﻭﻗﺘﻲ ﮐﻪ ﺷﺮﻁ ﻭ ﻫﺮ ﺩﻭ ﺩﺳﺘﻮﺭ ﺧﻴﻠﻲ ﺳﺎﺩﻩ ﻫﺴﺘﻨﺪ.
1
3‐13ﻛﻠﻤﺎﺕ ﻛﻠﻴﺪﻱ
ﺍﮐﻨﻮﻥ ﺑﺎ ﮐﻠﻤﺎﺗﻲ ﻣﺜﻞ ifﻭ caseﻭ floatﺁﺷﻨﺎ ﺷﺪﻳﻢ .ﺩﺍﻧﺴﺘﻴﻢ ﮐﻪ ﺍﻳﻦ ﮐﻠﻤﺎﺕ
ﺑﺮﺍﻱ C++ﻣﻌﺎﻧﻲ ﺧﺎﺻﻲ ﺩﺍﺭﻧﺪ .ﺍﺯ ﺍﻳﻦ ﮐﻠﻤﺎﺕ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﻋﻨﻮﺍﻥ ﻧﺎﻡ ﻳﮏ ﻣﺘﻐﻴﺮ ﻳﺎ ﻫﺮ
ﻣﻨﻈﻮﺭ ﺩﻳﮕﺮﻱ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ ﻭ ﻓﻘﻂ ﺑﺎﻳﺪ ﺑﺮﺍﻱ ﺍﻧﺠﺎﻡ ﻫﻤﺎﻥ ﮐﺎﺭ ﺧﺎﺹ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﻧﺪ .ﻣﺜﻼ
ﮐﻠﻢۀ floatﻓﻘﻂ ﺑﺎﻳﺪ ﺑﺮﺍﻱ ﻣﻌﺮﻓﻲ ﻳﮏ ﻧﻮﻉ ﺍﻋﺸﺎﺭﻱ ﺑﻪ ﮐﺎﺭ ﺭﻭﺩ .ﻳﻚ ﻛﻠﻢۀ ﻛﻠﻴﺪﻱ ﺩﺭ
ﻳﻚ ﺯﺑﺎﻥ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﻛﻠﻤﻪﺍﻱ ﺍﺳﺖ ﻛﻪ ﺍﺯ ﻗﺒﻞ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﻭ ﺑﺮﺍﻱ ﻫﺪﻑ ﻣﺸﺨﺼﻲ
ﻣﻨﻈﻮﺭ ﺷﺪﻩ ﺍﺳﺖ C++ .ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺍﻛﻨﻮﻥ ﺷﺎﻣﻞ 74ﻛﻠﻢۀ ﻛﻠﻴﺪﻱ ﺍﺳﺖ:
and and_eq asm
auto bitand Bitor
bool break case
catch char class
compl const const_cast
continue default delete
dodouble dynamic_cast else
enum explicit export
extern dfalse float
for friend goto
1 – Keywords
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 86
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﺑﻪ ﺍﺯﺍﻱ ﮐﺪ ; if (k = 0) i=kﮐﺪﺍﻡ ﺟﻤﻠﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ( ﺍﮔﺮ kﻣﺴﺎﻭﻱ ﺑﺎ ﺻﻔﺮ ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﻣﻘﺪﺍﺭ kﺩﺭ iﮐﭙﻲ ﻣﻲﺷﻮﺩ.
ﺏ( ﺍﮔﺮ kﻣﺴﺎﻭﻱ ﺑﺎ ﻏﻴﺮ ﺻﻔﺮ ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﻣﻘﺪﺍﺭ kﺩﺭ iﮐﭙﻲ ﻣﻲﺷﻮﺩ.
ﺝ( ﮐﺎﻣﭙﺎﻳﻠﺮ ﺧﻄﺎ ﻣﻲﮔﻴﺮﺩ ﺯﻳﺮﺍ ﻋﻤﻠﮕﺮ ﺑﺮﺍﺑﺮﻱ == ﺍﺳﺖ ﻧﻪ = .
ﺩ( ﺑﻪ ﺍﺯﺍﻱ ﻫﻢۀ ﻣﻘﺎﺩﻳﺮ kﻣﻘﺪﺍﺭ kﺩﺭ iﮐﭙﻲ ﻣﻲﺷﻮﺩ.
– 2ﺍﮔﺮ ﻣﺘﻐﻴﺮ bﺍﺯ ﻧﻮﻉ ﺑﻮﻟﻴﻦ ﺑﺎﺷﺪ ،ﮐﺪ ; if(b) !bﭼﻪ ﮐﺎﺭﻱ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ؟
ﺍﻟﻒ( ﺍﮔﺮ bﺑﺮﺍﺑﺮ ﺑﺎ trueﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ bﺭﺍ falseﻣﻲﮐﻨﺪ.
ﺏ( ﺍﮔﺮ bﺑﺮﺍﺑﺮ ﺑﺎ falseﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ bﺭﺍ trueﻣﻲﮐﻨﺪ.
ﺝ( ﺍﮔﺮ bﺑﺮﺍﺑﺮ ﺑﺎ trueﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ bﺭﺍ falseﻣﻲﮐﻨﺪ ﻭﮔﺮﻧﻪ bﺭﺍ trueﻣﻲﮐﻨﺪ.
ﺩ( ﺍﮔﺮ bﺑﺮﺍﺑﺮ ﺑﺎ falseﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ bﺭﺍ trueﻣﻲﮐﻨﺪ ﻭﮔﺮﻧﻪ bﺭﺍ falseﻣﻲﮐﻨﺪ.
– 3ﮐﺪ ; if (i==0) if (j==0) k=0ﻣﻌﺎﺩﻝ ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﮐﺪﻫﺎﻱ ﺯﻳﺮ ﺍﺳﺖ؟
ﺍﻟﻒ( ;if ((i==0) || (j==0)) k=0
ﺏ( ;if ((i==0) && (j==0)) k=0
ﺝ( ;if (i==0) k=0
ﺩ( ;if (j==0) k=0
– 4ﺩﺭ ﺍﺭﺯﻳﺎﺑﻲ ﻋﺒﺎﺭﺕﻫﺎﻱ ﺷﺮﻃﻲ:
ﺍﻟﻒ( ﺻﻔﺮ ﺑﻪ ﻣﻌﻨﺎﻱ ﺩﺭﺳﺖ ﻭ ﻫﺮ ﻣﻘﺪﺍﺭ ﻏﻴﺮ ﺻﻔﺮ ﺑﻪ ﻣﻌﻨﺎﻱ ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ.
ﺏ( ﺻﻔﺮ ﺑﻪ ﻣﻌﻨﺎﻱ ﻧﺎﺩﺭﺳﺖ ﻭ ﻫﺮ ﻣﻘﺪﺍﺭ ﻏﻴﺮ ﺻﻔﺮ ﺑﻪ ﻣﻌﻨﺎﻱ ﺩﺭﺳﺖ ﺍﺳﺖ.
ﺝ( ﻳﮏ ﺑﻪ ﻣﻌﻨﺎﻱ ﺩﺭﺳﺖ ﻭ ﻫﺮ ﻣﻘﺪﺍﺭ ﻏﻴﺮ ﻳﮏ ﺑﻪ ﻣﻌﻨﺎﻱ ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ.
ﺩ( ﻳﮏ ﺑﻪ ﻣﻌﻨﺎﻱ ﻧﺎﺩﺭﺳﺖ ﻭ ﻫﺮ ﻣﻘﺪﺍﺭ ﻏﻴﺮ ﻳﮏ ﺑﻪ ﻣﻌﻨﺎﻱ ﺩﺭﺳﺖ ﺍﺳﺖ.
– 5ﺍﮔﺮ mﻳﮏ ﻣﺘﻐﻴﺮ ﺑﻮﻟﻴﻦ ﺑﺎﺷﺪ ،ﺩﺭ ﮐﺪ ; if(m) i++ else i--ﭼﻪ ﺭﻭﻱ ﻣﻲﺩﻫﺪ؟
ﺍﻟﻒ( ﺍﮔﺮ mﺑﺮﺍﺑﺮ ﺑﺎ trueﺑﺎﺷﺪ ،ﺑﻪ iﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ ﻭﮔﺮﻧﻪ ﺍﺯ iﻳﮏ ﻭﺍﺣﺪ
ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ
ﺏ( ﺍﮔﺮ mﺑﺮﺍﺑﺮ ﺑﺎ falseﺑﺎﺷﺪ ،ﺑﻪ iﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ ﻭﮔﺮﻧﻪ ﺍﺯ iﻳﮏ ﻭﺍﺣﺪ
ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 88
ﺝ( ﺍﮔﺮ mﺑﺮﺍﺑﺮ ﺑﺎ trueﺑﺎﺷﺪ ،ﺑﻪ iﺩﻭ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ ﻭﮔﺮﻧﻪ ﺍﺯ iﺩﻭ ﻭﺍﺣﺪ
ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ
ﺩ( ﺍﮔﺮ mﺑﺮﺍﺑﺮ ﺑﺎ Falseﺑﺎﺷﺪ ،ﺑﻪ iﺩﻭ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ ﻭﮔﺮﻧﻪ ﺍﺯ iﺩﻭ ﻭﺍﺣﺪ
ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ
– 6ﺩﺭ ﮐﺪ ; if (i<0) i++; j++ﭼﻪ ﺭﺥ ﻣﻲﺩﻫﺪ؟
ﺍﻟﻒ( ﺍﮔﺮ iﺍﺯ ﺻﻔﺮ ﮐﻮﭼﮏﺗﺮ ﺑﺎﺷﺪ ،ﺑﻪ jﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ
ﺏ( ﺍﮔﺮ iﺑﺰﺭﮒﺗﺮ ﻳﺎ ﻣﺴﺎﻭﻱ ﺻﻔﺮ ﺑﺎﺷﺪ ،ﺑﻪ jﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ
ﺝ( ﺍﮔﺮ ﺑﻪ iﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ ﺷﻮﺩ ،ﺑﻪ jﻫﻢ ﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ.
ﺩ( ﻣﻘﺪﺍﺭ iﺭﺑﻄﻲ ﺑﻪ jﻧﺪﺍﺭﺩ ﻭ ﺩﺭ ﻫﺮ ﺣﺎﻝ ﺑﻪ jﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ.
– 7ﺩﺭ ﮐﺪ }; if (i<j) {i++; j--ﭼﻪ ﺍﺗﻔﺎﻗﻲ ﻣﻲﺍﻓﺘﺪ؟
ﺍﻟﻒ( ﺍﮔﺮ iﺍﺯ jﮐﻮﭼﮏﺗﺮ ﺑﺎﺷﺪ ،ﺍﺯ jﻳﮏ ﻭﺍﺣﺪ ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ
ﺏ( ﺍﮔﺮ iﺍﺯ jﺑﺰﺭﮒﺗﺮ ﺑﺎﺷﺪ ،ﺍﺯ jﻳﮏ ﻭﺍﺣﺪ ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ
ﺝ( ﺩﺭ ﻫﺮ ﺣﺎﻝ ﺑﻪ iﻳﮏ ﻭﺍﺣﺪ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ ﻭ ﺭﺑﻄﻲ ﺑﻪ jﻧﺪﺍﺭﺩ
ﺩ( ﺩﺭ ﻫﺮ ﺣﺎﻝ ﺍﺯ jﻳﮏ ﻭﺍﺣﺪ ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ ﻭ ﺭﺑﻄﻲ ﺑﻪ iﻧﺪﺍﺭﺩ
– 8ﺧﺮﻭﺟﻲ ﮐﺪ ﻣﻘﺎﺑﻞ ﭼﻴﺴﺖ؟
;int n=55
;{ int n=77
;cout << n << endl
}
;cout << n
ﺍﻟﻒ( ﺭﻭﻱ ﺍﻭﻟﻴﻦ ﺳﻄﺮ 55ﭼﺎﭖ ﻣﻲﺷﻮﺩ ﻭ ﺭﻭﻱ ﺩﻭﻣﻴﻦ ﺳﻄﺮ 77ﭼﺎﭖ ﻣﻲﺷﻮﺩ
ﺏ( ﺭﻭﻱ ﺍﻭﻟﻴﻦ ﺳﻄﺮ 77ﭼﺎﭖ ﻣﻲﺷﻮﺩ ﻭ ﺭﻭﻱ ﺩﻭﻣﻴﻦ ﺳﻄﺮ 55ﭼﺎﭖ ﻣﻲﺷﻮﺩ
ﺝ( ﺭﻭﻱ ﻫﺮ ﺩﻭ ﺳﻄﺮ ﻣﻘﺪﺍﺭ 55ﭼﺎﭖ ﻣﻲﺷﻮﺩ
ﺩ( ﺭﻭﻱ ﻫﺮ ﺩﻭ ﺳﻄﺮ ﻣﻘﺪﺍﺭ 77ﭼﺎﭖ ﻣﻲﺷﻮﺩ
– 9ﺣﺎﺻﻞ ﺍﺟﺮﺍﻱ ﮐﺪ ; if ((d>1) || (d/m)) d++ﺑﻪ ﺍﺯﺍﻱ d=2ﻭ m=0ﭼﻴﺴﺖ؟
ﺍﻟﻒ( ﺧﻄﺎﻱ ﺗﻘﺴﻴﻢ ﺑﺮ ﺻﻔﺮ ﺭﺥ ﻣﻲﺩﻫﺪ ﻭ ﺑﺮﻧﺎﻣﻪ ﻣﺘﻮﻗﻒ ﻣﻲﺷﻮﺩ
ﺏ( ﺷﺮﻁ ﺩﺳﺘﻮﺭ ifﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ ﭘﺲ ﺩﺳﺘﻮﺭ d++ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ
ﺝ( ﺑﻪ dﻳﮏ ﻭﺍﺣﺪ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ
ﺩ( ﺧﻄﺎﻱ ﺗﻘﺴﻴﻢ ﺑﺮ ﺻﻔﺮ ﺭﺥ ﻣﻲﺩﻫﺪ ﭘﺲ ﺩﺳﺘﻮﺭ d++ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ
89 ﻓﺼﻞ ﺳﻮم /اﻧﺘﺨﺎب
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﻳﻚ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻣﻨﻔﺮﺩ ﺩﺭ C++ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺍﮔﺮ ﻣﺘﻐﻴﺮ coutﺍﺯ 100ﺗﺠﺎﻭﺯ ﻛﺮﺩ
ﻋﺒﺎﺭﺕ " "Too manyﺭﺍ ﭼﺎﭖ ﻛﻨﺪ.
‐2ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﻛﺪﻫﺎﻱ ﺯﻳﺮ ﺍﺳﺖ؟
;a. cin << count
b. if x < y min = x
;else min = y
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 3‐1ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﺗﻨﻬﺎ ﺍﮔﺮ nﺑﺮ dﻗﺎﺑﻞ ﺗﻘﺴﻴﻢ ﺑﺎﺷﺪ ﭘﺎﺳﺨﻲ
ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ.
‐2ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 3‐5ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﮐﻤﻴﻦۀ ﭼﻬﺎﺭ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ.
‐3ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 3‐5ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﺣﺪ ﻭﺳﻂ ﺳﻪ ﻋﺪﺩ ﺻﺤﻴﺢ ﻭﺍﺭﺩ ﺷﺪﻩ ﺭﺍ
ﭼﺎﭖ ﻛﻨﺪ.
‐4ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 3‐6ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﻫﻤﺎﻥ ﺍﺛﺮ ﺭﺍ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺍﻣﺎ ﺑﺪﻭﻥ ﺍﺳﺘﻔﺎﺩﻩ
ﺍﺯ ﺑﻠﻮﻙ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ.
‐5ﭘﻴﺶﺑﻴﻨﻲ ﻛﻨﻴﺪ ﺧﺮﻭﺟﻲ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 3‐17ﭼﻴﺴﺖ ﺍﮔﺮ ﺍﻋﻼﻥ ﺧﻂ ﭘﻨﺠﻢ ﺑﺮﻧﺎﻣﻪ ﺭﺍ
ﭘﺎﻙ ﻛﻨﻴﻢ .ﺑﺮﻧﺎﻡۀ ﺗﻐﻴﻴﺮﻳﺎﻓﺘﻪ ﺭﺍ ﺑﺮﺍﻱ ﺑﺮﺭﺳﻲ ﭘﻴﺶﺑﻴﻨﻲ ﺧﻮﺩ ﺍﺟﺮﺍ ﻛﻨﻴﺪ.
‐6ﺑﺮﻧﺎﻣﻪﺍﻱ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﺳﻦ ﻛﺎﺭﺑﺮ ﺭﺍ ﺑﺨﻮﺍﻧﺪ ﻭ ﺍﮔﺮ ﺳﻦ ﻛﻮﭼﻚﺗﺮ ﺍﺯ 18
ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ ﻭ ﺍﮔﺮ ﺳﻦ ﺑﻴﻦ 18ﻭ 65ﺑﻮﺩ ""You are a child ﺑﻮﺩ ﻋﺒﺎﺭﺕ
"Youﺭﺍ ﭼﺎﭖ ﻛﻨﺪ ﻭ ﺍﮔﺮ ﺳﻦ ﺑﺰﺭﮒﺗﺮ ﻳﺎ ﻣﺴﺎﻭﻱ 65ﺑﻮﺩ "are an adult ﻋﺒﺎﺭﺕ
"youﺭﺍ ﭼﺎﭖ ﻛﻨﺪ. "are a cenior citizen ﻋﺒﺎﺭﺕ
‐7ﺑﺮﻧﺎﻣﻪﺍﻱ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﺩﻭ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﻣﻲﺧﻮﺍﻧﺪ ﻭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻳﻚ
ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ،ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺍﻳﻦ ﻛﻪ ﺁﻳﺎ ﻳﻜﻲ ﺍﺯ ﺍﻳﻦ ﺩﻭ ﻣﻀﺮﺏ ﺩﻳﮕﺮﻱ ﺍﺳﺖ ﻳﺎ
ﺧﻴﺮ ،ﻋﺒﺎﺭﺕ " "multipleﻳﺎ " "notﺭﺍ ﭼﺎﭖ ﻛﻨﺪ.
‐8ﺑﺮﻧﺎﻣﻪﺍﻱ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﻳﻚ ﻣﺎﺷﻴﻦﺣﺴﺎﺏ ﺳﺎﺩﻩ ﺭﺍ ﺷﺒﻴﻪﺳﺎﺯﻱ ﻣﻲﻛﻨﺪ ﻛﻪ ﺩﻭ
ﻋﺪﺩ ﺻﺤﻴﺢ ﻭ ﻳﻚ ﻛﺎﺭﺍﻛﺘﺮ ﺭﺍ ﻣﻲﺧﻮﺍﻧﺪ ﻭ ﺳﭙﺲ ﺍﮔﺮ ﻛﺎﺭﺍﻛﺘﺮ ) (+ﺑﺎﺷﺪ ﻣﺠﻤﻮﻉ ﺭﺍ ﭼﺎﭖ
ﻛﻨﺪ ﻭ ﺍﮔﺮ ﻛﺎﺭﺍﻛﺘﺮ )‐( ﺑﺎﺷﺪ ﺗﻔﺎﺿﻞ ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ ﻭ ﺍﮔﺮ ﻛﺎﺭﺍﻛﺘﺮ)*( ﺑﺎﺷﺪ ﺣﺎﺻﻞﺿﺮﺏ ﺭﺍ
ﭼﺎﭖ ﻛﻨﺪ ﻭ ﺍﮔﺮ ﻛﺎﺭﺍﻛﺘﺮ ) (/ﺑﺎﺷﺪ ﺣﺎﺻﻞﺗﻘﺴﻴﻢ ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ ﻭ ﺍﮔﺮ ﻛﺎﺭﺍﻛﺘﺮ ) (%ﺑﺎﺷﺪ
ﺑﺎﻗﻴﻤﺎﻧﺪﻩ ﺗﻘﺴﻴﻢ ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ .ﺍﺯ ﻳﻚ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ switchﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﺪ.
‐9ﺑﺮﻧﺎﻣﻪﺍﻱ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﺑﺎﺯﻱ "ﺳﻨﮓ – ﻛﺎﻏﺬ – ﻗﻴﭽﻲ" ﺭﺍ ﺍﻧﺠﺎﻡ ﺩﻫﺪ .ﺩﺭ ﺍﻳﻦ
ﺑﺎﺯﻱ ﺩﻭ ﻧﻔﺮ ﺑﻪ ﻃﻮﺭ ﻫﻢﺯﻣﺎﻥ ﻳﻜﻲ ﺍﺯ ﻋﺒﺎﺭﺍﺕ "ﺳﻨﮓ" ﻳﺎ "ﻛﺎﻏﺬ" ﻳﺎ "ﻗﻴﭽﻲ" ﺭﺍ ﻣﻲﮔﻮﻳﻨﺪ
)ﻭ ﻳﺎ ﻳﻜﻲ ﺍﺯ ﻋﻼﻣﺖﻫﺎﻱ ﺍﺯ ﻗﺒﻞ ﻣﺸﺨﺺ ﺭﺍ ﺑﺎ ﺩﺳﺖ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ( .ﺑﺮﻧﺪﻩ ﻛﺴﻲ ﺍﺳﺖ
ﻛﻪ ﺷﻲﺀ ﻏﻠﺒﻪﻛﻨﻨﺪﻩ ﺑﺮ ﺩﻳﮕﺮﻱ ﺭﺍ ﺍﻧﺘﺨﺎﺏ ﻛﺮﺩﻩ ﺑﺎﺷﺪ .ﺣﺎﻻﺕ ﻣﻤﮑﻦ ،ﭼﻨﻴﻦ ﺍﺳﺖ ﻛﻪ ﻛﺎﻏﺬ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 94
ﺑﺮ ﺳﻨﮓ ﻏﻠﺒﻪ ﻣﻲﻛﻨﺪ )ﻣﻲﭘﻮﺷﺎﻧﺪ( ،ﺳﻨﮓ ﺑﺮ ﻗﻴﭽﻲ ﻏﻠﺒﻪ ﻣﻲﻛﻨﺪ )ﻣﻲﺷﻜﻨﺪ( ﻭ ﻗﻴﭽﻲ ﺑﺮ
ﻛﺎﻏﺬ ﻏﻠﺒﻪ ﻣﻲﻛﻨﺪ )ﻣﻲﺑﺮﺩ( .ﺑﺮﺍﻱ ﺍﺷﻴﺎﺀ ﺍﺯ ﻳﻚ ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﺪ.
‐10ﻣﺴﺄﻝۀ 9ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ switchﺣﻞ ﻛﻨﻴﺪ.
‐11ﻣﺴﺄﻝۀ 9ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﺒﺎﺭﺍﺕ ﺷﺮﻃﻲ ﺣﻞ ﮐﻨﻴﺪ.
‐12ﺑﺮﻧﺎﻣﻪﺍﻱ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﻳﻚ ﻣﻌﺎﺩﻝۀ ﺩﺭﺟﻪ ﺩﻭﻡ ﺭﺍ ﺣﻞ ﻣﻲﻛﻨﺪ .ﻣﻌﺎﺩﻝۀ
ﺩﺭﺟﻪ ﺩﻭﻡ ﻣﻌﺎﺩﻟﻪﺍﻱ ﺍﺳﺖ ﻛﻪ ﺑﻪ ﺷﮑﻞ ax2+bx+c=0ﺑﺎﺷﺪ a .ﻭ bﻭ cﺿﺮﺍﻳﺐ
ﻫﺴﺘﻨﺪ ﻭ xﻣﺠﻬﻮﻝ ﺍﺳﺖ .ﺿﺮﺍﻳﺐ ،ﺍﻋﺪﺍﺩ ﺣﻘﻴﻘﻲ ﻫﺴﺘﻨﺪ ﻛﻪ ﺗﻮﺳﻂ ﻛﺎﺭﺑﺮ ﻭﺍﺭﺩ ﻣﻲﺷﻮﻧﺪ.
ﺑﻨﺎﺑﺮﺍﻳﻦ ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ floatﻳﺎ doubleﺍﻋﻼﻥ ﮔﺮﺩﻧﺪ .ﺍﺯ ﺁﻥﺟﺎ ﻛﻪ ﻣﻌﺎﺩﻝۀ ﺩﺭﺟﻪ ﺩﻭﻡ
ﻣﻌﻤﻮﻻ ﺩﻭ ﺭﻳﺸﻪ ﺩﺍﺭﺩ ،ﺑﺮﺍﻱ ﺟﻮﺍﺏﻫﺎ ﺍﺯ x1ﻭ x2ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﺪ .ﺟﻮﺍﺏﻫﺎ ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ
doubleﺍﻋﻼﻥ ﮔﺮﺩﻧﺪ ﺗﺎ ﺍﺯ ﺧﻄﺎﻱ ﮔﺮﺩ ﻛﺮﺩﻥ ﺟﻠﻮﮔﻴﺮﻱ ﺷﻮﺩ.
‐13ﺑﺮﻧﺎﻣﻪﺍﻱ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﻳﻚ ﻋﺪﺩ ﺷﺶ ﺭﻗﻤﻲ ﺭﺍ ﻣﻲﺧﻮﺍﻧﺪ ﻭ ﻣﺠﻤﻮﻉ
ﺷﺶ ﺭﻗﻢ ﺁﻥ ﻋﺪﺩ ﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ .ﺍﺯ ﻋﻤﻠﮕﺮ ﺗﻘﺴﻴﻢ ) (/ﻭ ﻋﻤﻠﮕﺮ ﺑﺎﻗﻴﻤﺎﻧﺪﻩ ) (%ﺑﺮﺍﻱ
ﺑﻴﺮﻭﻥ ﻛﺸﻴﺪﻥ ﺭﻗﻢﻫﺎ ﺍﺯ ﻋﺪﺩ ﻭﺭﻭﺩﻱ ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ ﻋﺪﺩ ﻭﺭﻭﺩﻱ nﺑﺮﺍﺑﺮ ﺑﺎ
876,543ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ n/1000%10ﺑﺮﺍﺑﺮ ﺑﺎ ﺭﻗﻢ ﻳﻜﺎﻥ ﻫﺰﺍﺭ ﻳﻌﻨﻲ 6ﺍﺳﺖ.
ﻓﺼﻞ ﭼﻬﺎﺭﻡ
»ﺗﻜﺮﺍﺭ«
ﻣﻘﺪﻣﻪ
ﺗﻜﺮﺍﺭ ،1ﺍﺟﺮﺍﻱ ﭘﻲ ﺩﺭ ﭘﻲ ﻳﻚ ﺩﺳﺘﻮﺭ ﻳﺎ ﺑﻠﻮﻛﻲ ﺍﺯ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎ ﺩﺭ ﻳﻚ ﺑﺮﻧﺎﻣﻪ
ﺍﺳﺖ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﮑﺮﺍﺭ ﻣﻲﺗﻮﺍﻧﻴﻢ ﮐﻨﺘﺮﻝ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﻣﺠﺒﻮﺭ ﮐﻨﻴﻢ ﺗﺎ ﺑﻪ ﺧﻄﻮﻁ ﻗﺒﻠﻲ
ﺑﺮﮔﺮﺩﺩ ﻭ ﺁﻥﻫﺎ ﺭﺍ ﺩﻭﺑﺎﺭﻩ ﺍﺟﺮﺍ ﻧﻤﺎﻳﺪ C++ .ﺩﺍﺭﺍﻱ ﺳﻪ ﺩﺳﺘﻮﺭ ﺗﻜﺮﺍﺭ ﺍﺳﺖ :ﺩﺳﺘﻮﺭ
،whileﺩﺳﺘﻮﺭ do_whileﻭ ﺩﺳﺘﻮﺭ .forﺩﺳﺘﻮﺭﻫﺎﻱ ﺗﮑﺮﺍﺭ ﺑﻪ ﻋﻠﺖ ﻃﺒﻴﻌﺖ
ﭼﺮﺧﻪﻣﺎﻧﻨﺪﺷﺎﻥ ،ﺣﻠﻘﻪ 2ﻧﻴﺰ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﻧﺪ.
4‐1ﺩﺳﺘﻮﺭ while
ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ ﻭ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ﺑﻌﺪ ﺍﺯ whileﭘﺮﺵ ﻣﻲﻛﻨﺪ .ﺍﮔﺮ ﻣﻘﺪﺍﺭ
ﺷﺮﻁ ﻧﺎﺻﻔﺮ)ﻳﻌﻨﻲ ﺩﺭﺳﺖ( ﺑﺎﺷﺪ statement ،ﺍﺟﺮﺍ ﺷﺪﻩ ﻭ ﺩﻭﺑﺎﺭﻩ ﻣﻘﺪﺍﺭ ﺷﺮﻁ
ﺑﺮﺭﺳﻲ ﻣﻲﺷﻮﺩ .ﺍﻳﻦ ﺗﮑﺮﺍﺭ ﺁﻥ ﻗﺪﺭ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﺷﺮﻁ ﺻﻔﺮ ﺷﻮﺩ .ﺗﻮﺟﻪ
ﮐﻨﻴﺪ ﻛﻪ ﺷﺮﻁ ﺑﺎﻳﺪ ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ ﻗﺮﺍﺭ ﺑﮕﻴﺮﺩ.
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺯ ﺳﻪ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ nﻭ iﻭ sumﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻛﻨﺪ .ﻣﺘﻐﻴﺮ iﺑﺎ ﻣﻘﺪﺍﺭ 1
ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﻣﻲﺷﻮﺩ ﻭ ﻋﺪﺩﻱ ﮐﻪ ﮐﺎﺭﺑﺮ ﻭﺍﺭﺩ ﻣﻲﮐﻨﺪ ﺩﺭ ﻣﺘﻐﻴﺮ nﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﻣﺘﻐﻴﺮ
sumﻧﻴﺰ ﺑﺎ 0ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﻣﻲﺷﻮﺩ .ﺳﭙﺲ ﺣﻠﻖۀ whileﺁﻏﺎﺯ ﻣﻲﮔﺮﺩﺩ :ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ
iﺑﺎ nﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ i<=nﺑﻮﺩ ﻣﻘﺪﺍﺭ iﺑﺎ ﻣﻘﺪﺍﺭ sumﺟﻤﻊ ﺷﺪﻩ ﻭ ﺣﺎﺻﻞ ﺩﺭ
sumﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺑﻪ iﻳﮑﻲ ﺍﻓﺰﻭﺩﻩ ﺷﺪﻩ ﻭ ﺩﻭﺑﺎﺭﻩ ﺷﺮﻁ ﺣﻠﻘﻪ ﺑﺮﺭﺳﻲ ﻣﻲﺷﻮﺩ .ﻫﻨﮕﺎﻣﻲ
ﮐﻪ i>nﺷﻮﺩ ﺣﻠﻘﻪ ﻣﺘﻮﻗﻒ ﻣﻲﺷﻮﺩ .ﭘﺲ nﺁﺧﺮﻳﻦ ﻣﻘﺪﺍﺭﻱ ﺍﺳﺖ ﻛﻪ ﺑﻪ sumﺍﻓﺰﻭﺩﻩ
ﻣﻲﺷﻮﺩ .ﺷﮑﻞ ﺯﻳﺮ ﭘﺎﺳﺦ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺑﻪ ﺍﺯﺍﻱ ﻭﺭﻭﺩﻱ n=8ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﻫﻤﭽﻨﻴﻦ ﻣﻘﺪﺍﺭ
ﻣﺘﻐﻴﺮﻫﺎ ﺩﺭ ﻫﺮ ﮔﺎﻡ ﺣﻠﻘﻪ ﺩﺭ ﺟﺪﻭﻝ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ.
Enter a positive integer: 8
The sum of the first 8 integers is 36
i 0 1 2 3 4 5 6 7 8
sum 0 1 3 6 10 15 21 28 36
97 ﻓﺼﻞ ﭼﻬﺎرم /ﺗﮑﺮار
ﺩﺭ ﺩﻭﻣﻴﻦ ﺍﺟﺮﺍ ،ﻛﺎﺭﺑﺮ ﻋﺪﺩ 100ﺭﺍ ﻭﺍﺭﺩ ﻣﻲﮐﻨﺪ ،ﻟﺬﺍ ﺣﻠﻖۀ whileﻧﻴﺰ 100ﺑﺎﺭ
ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ ﺗﺎ ﻣﺤﺎﺳﺐۀ 1+2+3+…+98+99+100=5050ﺭﺍ ﺍﻧﺠﺎﻡ ﺩﻫﺪ:
Enter a positive integer: 100
The sum of the first 100 integers is 5050
ﺑﻪ ﺗﻮﺭﻓﺘﮕﻲ ﺩﺳﺘﻮﺭ ﺩﺍﺧﻞ ﺣﻠﻘﻪ ﺗﻮﺟﻪ ﻛﻨﻴﺪ .ﺍﻳﻦ ﺷﮑﻞ ﭼﻴﻨﺶ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﻛﻪ ﻣﻨﻄﻖ
ﺑﺮﻧﺎﻣﻪ ﺭﺍﺣﺖﺗﺮ ﺩﻧﺒﺎﻝ ﺷﻮﺩ ،ﺧﺼﻮﺻﺎ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺑﺰﺭﮒ.
ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ ،ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﻋﺒﺎﺭﺕ ) (x > 0ﺍﺳﺖ .ﻣﻘﺪﺍﺭ xﺩﺭﻭﻥ ﺣﻠﻘﻪ ﺑﺎ ﺗﻐﻴﻴﺮ
ﻋﺪﺩ ﻭﺭﻭﺩﻱ ﺗﻐﻴﻴﺮ ﻣﻲﮐﻨﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻓﻘﻂ ﻭﻗﺘﻲ ﺣﻠﻘﻪ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ ﮐﻪ ﻋﺪﺩ ﻭﺭﻭﺩﻱ ﺑﺮﺍﺑﺮ
ﺑﺎ 0ﻳﺎ ﮐﻢﺗﺮ ﺍﺯ ﺁﻥ ﺑﺎﺷﺪ .ﻣﺘﻐﻴﺮﻱ ﻛﻪ ﺑﻪ ﺍﻳﻦ ﺷﮑﻞ ﺑﺮﺍﻱ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ ،ﻣﺘﻐﻴﺮ
ﻛﻨﺘﺮﻝ ﺣﻠﻘﻪ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 98
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺎﻧﻨﺪ ﻣﺜﺎﻝ 4‐1ﮐﺎﺭ ﻣﻲﮐﻨﺪ :ﻫﻤﻴﻦ ﮐﻪ ﻣﻘﺪﺍﺭ iﺑﻪ nﺑﺮﺳﺪ ،ﺣﻠﻘﻪ ﺧﺎﺗﻤﻪ
ﻣﻲﻳﺎﺑﺪ ﻭ ﺩﺳﺘﻮﺭ ﺧﺮﻭﺟﻲ ﺩﺭ ﭘﺎﻳﺎﻥ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ.
ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺷﺮﻁ ﻛﻨﺘﺮﻝ ﺣﻠﻘﻪ trueﺍﺳﺖ .ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺣﻠﻘﻪ ﺑﺮﺍﻱ ﻫﻤﻴﺸﻪ
ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ ﻭ ﻫﻴﭻﮔﺎﻩ ﭘﺎﻳﺎﻥ ﻧﻤﻲﻳﺎﺑﺪ ﺍﻣﺎ ﺩﺭ ﺑﺪﻥۀ ﺣﻠﻘﻪ ﺷﺮﻃﻲ ﻫﺴﺖ ﮐﻪ ﺳﺒﺐ ﭘﺎﻳﺎﻥ
ﮔﺮﻓﺘﻦ ﺣﻠﻘﻪ ﻣﻲﺷﻮﺩ .ﺑﻪ ﻣﺤﺾ ﺍﻳﻦ ﮐﻪ i>nﺷﻮﺩ ﺩﺳﺘﻮﺭ breakﺣﻠﻘﻪ ﺭﺍ ﻣﻲﺷﮑﻨﺪ ﻭ
ﮐﻨﺘﺮﻝ ﺑﻪ ﺑﻴﺮﻭﻥ ﺣﻠﻘﻪ ﭘﺮﺵ ﻣﻲﮐﻨﺪ .ﻭﻗﺘﻲ ﻗﺮﺍﺭ ﺍﺳﺖ ﺣﻠﻘﻪ ﺍﺯ ﺩﺭﻭﻥ ﻛﻨﺘﺮﻝ ﺷﻮﺩ ،ﻣﻌﻤﻮﻻ
ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺭﺍ trueﻣﻲﮔﺬﺍﺭﻧﺪ .ﺑﺎ ﺍﻳﻦ ﺭﻭﺵ ﻋﻤﻼ ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺣﺬﻑ
ﻣﻲﺷﻮﺩ.
99 ﻓﺼﻞ ﭼﻬﺎرم /ﺗﮑﺮار
(f2ﺩﺭﺳﺖ )> bound ﺣﻠﻖۀ whileﺷﺎﻣﻞ ﺑﻠﻮﻛﻲ ﺍﺯ ﭘﻨﺞ ﺩﺳﺘﻮﺭ ﺍﺳﺖ .ﻭﻗﺘﻲ ﺷﺮﻁ
ﺑﺎﺷﺪ ،ﺩﺳﺘﻮﺭ breakﺍﺟﺮﺍ ﺷﺪﻩ ﻭ ﺑﺪﻭﻥ ﺍﻳﻦ ﻛﻪ ﺳﻪ ﺩﺳﺘﻮﺭ ﺁﺧﺮ ﺣﻠﻘﻪ ﺍﺟﺮﺍ ﺷﻮﻧﺪ ،ﺣﻠﻘﻪ
ﻓﻮﺭﺍ ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ.
ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺍﺯ ﻛﺎﺭﺍﻛﺘﺮ ﺧﻂ ﺟﺪﻳﺪ ' '\nﺩﺭ ﺭﺷﺖۀ " ":\n0,1ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ.
ﺍﻳﻦ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﻛﻪ ﻋﻼﻣﺖ ﻛﻮﻟﻦ :ﺩﺭ ﭘﺎﻳﺎﻥ ﺧﻂ ﻓﻌﻠﻲ ﭼﺎﭖ ﺷﻮﺩ ﻭ ﺳﭙﺲ ﻣﮑﺎﻥﻧﻤﺎ
ﺑﻪ ﺧﻂ ﺑﻌﺪﻱ ﺭﻭﻱ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﭘﺮﺵ ﻧﻤﺎﻳﺪ ﻭ ﺭﺷﺖۀ 0,1ﺭﺍ ﺩﺭ ﺷﺮﻭﻉ ﺁﻥ ﺧﻂ ﭼﺎﭖ
ﮐﻨﺪ.
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﭘﺲ ﺍﺯ ﺑﺪﻥۀ ﺣﻠﻘﻪ ﻫﻴﭻ ﺩﺳﺘﻮﺭ ﺩﻳﮕﺮﻱ ﻧﺪﺍﺭﺩ .ﭘﺲ ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ ﺣﻠﻘﻪ ﺑﻪ ﻣﻌﻨﻲ
ﭘﺎﻳﺎﻥ ﺩﺍﺩﻥ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺖ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺎﻧﻨﺪ ﻣﺜﺎﻝ 4‐4ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ.
101 ﻓﺼﻞ ﭼﻬﺎرم /ﺗﮑﺮار
ﺍﻳﻦ ﻣﺜﺎﻝ ﻳﻚ ﺭﺍﻩ ﺑﺮﺍﻱ ﺧﺮﻭﺝ ﺍﺯ ﺣﻠﻖۀ ﻧﺎﻣﺘﻨﺎﻫﻲ ﺭﺍ ﻧﺸﺎﻥ ﺩﺍﺩ .ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺭﻭﺵ
ﺩﻳﮕﺮﻱ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﺍﻣﺎ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺗﺮﺟﻴﺢ ﻣﻲﺩﻫﻨﺪ ﺍﺯ breakﺑﺮﺍﻱ ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ
ﺑﻪ ﺣﻠﻘﻪﻫﺎﻱ ﻧﺎﻣﺘﻨﺎﻫﻲ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻨﺪ ﺯﻳﺮﺍ ﻗﺎﺑﻠﻴﺖ ﺍﻧﻌﻄﺎﻑ ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﺩ.
ﭼﻮﻥ ﻫﻴﭻ ﺷﺮﻁ ﭘﺎﻳﺎﻥ ﺣﻠﻘﻪﺍﻱ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ ،ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺗﺎ
ﺑﻲﻧﻬﺎﻳﺖ ﺍﺩﺍﻣﻪ ﺧﻮﺍﻫﺪ ﻳﺎﻓﺖ )ﺗﺎ ﻭﻗﺘﻲ ﺣﺎﻓﻈﻪ ﺳﺮﺭﻳﺰ ﺷﻮﺩ( .ﭘﺲ ﮐﻠﻴﺪﻫﺎﻱ Ctrl+Cﺭﺍ
ﻓﺸﺎﺭ ﺩﻫﻴﺪ ﺗﺎ ﺑﺮﻧﺎﻣﻪ ﺧﺎﺗﻤﻪ ﻳﺎﺑﺪ.
4‐3ﺩﺳﺘﻮﺭ do..while
}
4‐4ﺩﺳﺘﻮﺭ for
ﺩﺭ ﺣﻠﻖۀ ﺑﺮﻧﺎﻡۀ ﻓﻮﻕ ،ﻋﺒﺎﺭﺕ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ int i=1ﺍﺳﺖ .ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ i<=n
ﻣﻲﺑﺎﺷﺪ ﻭ ﻋﺒﺎﺭﺕ ﭘﻴﺶﺑﺮﻱ ﻣﺘﻐﻴﺮ ﮐﻨﺘﺮﻝ ﻫﻢ i++ﺍﺳﺖ .ﺩﻗﺖ ﮐﻨﻴﺪ ﻛﻪ ﺍﻳﻦﻫﺎ ﻫﻤﺎﻥ
ﻋﺒﺎﺭﺍﺗﻲ ﻫﺴﺘﻨﺪ ﻛﻪ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝﻫﺎﻱ 4‐1ﻭ 4‐3ﻭ 4‐7ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ.
ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ for ﺩﺭ C++ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻭﻗﺘﻲ ﻳﻚ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻝ ﺩﺭﻭﻥ ﻳﻚ ﺣﻠﻖۀ
ﻣﺤﺪﻭﺩ ﻣﻲﮔﺮﺩﺩ .ﻳﻌﻨﻲ ﺁﻥ for ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ( ﺣﻮﺯۀ ﺁﻥ ﻣﺘﻐﻴﺮ ﺑﻪ ﻫﻤﺎﻥ ﺣﻠﻖۀ i )ﻣﺎﻧﻨﺪ
ﻣﺘﻐﻴﺮ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺑﻴﺮﻭﻥ ﺍﺯ ﺁﻥ ﺣﻠﻘﻪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ .ﻧﺘﻴﺞۀ ﺩﻳﮕﺮ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻧﺎﻡ
ﻣﺸﺎﺑﻬﻲ ﺩﺭ ﺧﺎﺭﺝ ﺍﺯ ﺣﻠﻖۀ forﺑﺮﺍﻱ ﻳﻚ ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﻮﺩ.
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 4‐9ﺭﺍ ﺍﻧﺠﺎﻡ for ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻫﻤﺎﻥ ﻣﺤﺎﺳﺒﺎﺕ ﺣﻠﻖۀ for ﺩﻭ ﺣﻠﻖۀ
ﻣﻲﺩﻫﻨﺪ .ﺍﻳﻦ ﺩﻭ ﺣﻠﻘﻪ ،ﻛﺎﺭ ﺭﺍ ﺑﻪ ﺩﻭ ﻗﺴﻤﺖ ﺗﻘﺴﻴﻢ ﻣﻲﻛﻨﻨﺪ n/2 :ﻣﺤﺎﺳﺒﻪ ﺩﺭ ﺣﻠﻖۀ ﺍﻭﻝ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 106
ﺧﻮﺩﺵ i ﺍﻧﺠﺎﻡ ﻣﻲﮔﻴﺮﺩ ﻭ ﻣﺎﺑﻘﻲ ﺩﺭ ﺣﻠﻖۀ ﺩﻭﻡ .ﻫﺮ ﺣﻠﻘﻪ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻞ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻟﻲ
ﺭﺍ ﺩﺍﺭﺩ.
for ﺍﺧﻄﺎﺭ :ﺑﻴﺸﺘﺮ ﻛﺎﻣﭙﺎﻳﻠﺮﻫﺎﻱ ﻗﺒﻞ ﺍﺯ C++ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ،ﺣﻮﺯۀ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻟﻲ ﺣﻠﻖۀ
ﺭﺍ ﺗﺎ ﺑﻌﺪ ﺍﺯ ﭘﺎﻳﺎﻥ ﺣﻠﻘﻪ ﻧﻴﺰ ﮔﺴﺘﺮﺵ ﻣﻲﺩﻫﻨﺪ.
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ ﺑﺎ ﻣﺜﺎﻝ 4‐8ﻣﻘﺎﻳﺴﻪ ﮐﻨﻴﺪ .ﻫﺮ ﺩﻭ ﮐﺎﺭﻫﺎﻱ ﻣﺸﺎﺑﻬﻲ ﺭﺍ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﻨﺪ .ﺩﺭ ﻫﺮ
ﺩﻭ ﺑﺮﻧﺎﻣﻪ ،ﮐﺎﺭﻫﺎﻱ ﺯﻳﺮ ﺍﻧﺠﺎﻡ ﻣﻲﺷﻮﺩ :ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ 1ﺩﺭ fﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ 2
ﺩﺭ iﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﭘﻨﺞ ﮔﺎﻡ ﺗﮑﺮﺍﺭ ﺭﺥ ﻣﻲﺩﻫﺪ :ﭼﺎﭖ ،fﺿﺮﺏ fﺩﺭ ،i
ﺍﻓﺰﺍﻳﺶ ،iﺑﺮﺭﺳﻲ ﺷﺮﻁ ) (f <= boundﻭ ﭘﺎﻳﺎﻥ ﺩﺍﺩﻥ ﺑﻪ ﺣﻠﻘﻪ ﺩﺭ ﺻﻮﺭﺕ ﻧﺎﺩﺭﺳﺖ
ﺑﻮﺩﻥ ﺷﺮﻁ .ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺑﺎ ﺣﻠﻖۀ forﻫﻤﺎﻥ ﺗﺄﺛﻴﺮ ﺑﺮﻧﺎﻣﻪ ﺑﺎ ﺣﻠﻖۀ do..whileﺭﺍ ﺩﺍﺭﺩ.
ﺩﺳﺘﻮﺭ forﺍﻧﻌﻄﺎﻑﭘﺬﻳﺮﻱ ﺑﻴﺸﺘﺮﻱ ﺑﻪ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺩﻫﺪ .ﻣﺜﺎﻝﻫﺎﻱ ﺯﻳﺮ ﺍﻳﻦ ﻣﻄﻠﺐ
ﺭﺍ ﺁﺷﻜﺎﺭ ﻣﻲﻛﻨﻨﺪ.
ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺣﻠﻖۀ forﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺘﻐﻴﺮ ﮐﻨﺘﺮﻟﻲ ﺧﻮﺩ ﻳﻌﻨﻲ dﺭﺍ ﺩﻭ ﻭﺍﺣﺪ ﺩﻭ ﻭﺍﺣﺪ
ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ .ﺳﻌﻲ ﮐﻨﻴﺪ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ.
)(int main
;{ int n, max
;" cout << "Enter positive integers (0 to quit):
;cin >> n
) ;for (max = n; n > 0
;{ if (n > max) max = n
;cin >> n
}
;cout << "max = " << max << endl
}
Enter positive integers (0 to quit): 44 77 55 22 99 33 11 66 88 0
max = 99
ﺣﻠﻖۀ forﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺑﻪ ﻭﺳﻴﻞۀ ﻣﺘﻐﻴﺮ ﻭﺭﻭﺩﻱ nﻛﻨﺘﺮﻝ ﻣﻲﺷﻮﺩ .ﺍﻳﻦ ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ
ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﺯﻣﺎﻧﻲ ﻛﻪ n<=0ﺑﺸﻮﺩ .ﻣﺘﻐﻴﺮ ﻭﺭﻭﺩﻱ ﮐﻪ ﺑﻪ ﺍﻳﻦ ﺷﻴﻮﻩ ﺑﺮﺍﻱ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﻧﻴﺰ
ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ ،ﻧﮕﻬﺒﺎﻥ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ.
ﺑﻪ ﺑﺨﺶ ﮐﻨﺘﺮﻟﻲ ﺍﻳﻦ ﺣﻠﻘﻪ ﮐﻪ ﺑﻪ ﺻﻮﺭﺕ ); (max = n; n > 0ﺍﺳﺖ ﺩﻗﺖ
ﮐﻨﻴﺪ .ﺑﺨﺶ ﭘﻴﺶﺑﺮﻱ ﺩﺭ ﺁﻥ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ ﻭ ﺑﺨﺶ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺁﻥ ﻧﻴﺰ ﻣﺘﻐﻴﺮ ﺟﺪﻳﺪﻱ ﺭﺍ
ﺗﻌﺮﻳﻒ ﻧﻤﻲﮐﻨﺪ ﺑﻠﮑﻪ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﮐﻪ ﻗﺒﻼ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺑﺮﺩ .ﻋﻠﺖ
ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺣﻠﻖۀ ﻣﺬﮐﻮﺭ ﻧﮕﻬﺒﺎﻥ ﺩﺍﺭﺩ ﻭ ﻧﮕﻬﺒﺎﻥ ﺍﺯ ﻃﺮﻳﻖ ﻭﺭﻭﺩﻱ ﭘﻴﺶ ﺑﺮﺩﻩ ﻣﻲﺷﻮﺩ ﻭ
ﺩﻳﮕﺮ ﻧﻴﺎﺯﻱ ﺑﻪ ﺑﺨﺶ ﭘﻴﺶﺑﺮﻱ ﺩﺭ ﺣﻠﻘﻪ ﻧﻴﺴﺖ .ﻣﺘﻐﻴﺮ maxﻧﻴﺰ ﺑﺎﻳﺪ ﻣﻘﺪﺍﺭ ﺧﻮﺩ ﺭﺍ ﭘﺲ
ﺍﺯ ﺍﺗﻤﺎﻡ ﺣﻠﻘﻪ ﺣﻔﻆ ﮐﻨﺪ ﺗﺎ ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﺷﻮﺩ .ﺍﮔﺮ ﻣﺘﻐﻴﺮ maxﺩﺭﻭﻥ ﺣﻠﻘﻪ ﺍﻋﻼﻥ
ﻣﻲﺷﺪ ،ﭘﺲ ﺍﺯ ﺍﺗﻤﺎﻡ ﺣﻠﻘﻪ ﺍﺯ ﺑﻴﻦ ﻣﻲﺭﻓﺖ ﻭ ﺩﻳﮕﺮ ﻗﺎﺑﻞ ﺍﺳﺘﻔﺎﺩﻩ ﻧﺒﻮﺩ.
86%14 = 2
83%15 = 8
ﺩﺭ ﺑﺨﺶ ﻛﻨﺘﺮﻝ ﺍﻳﻦ ﺣﻠﻘﻪ ،ﺩﻭ ﻣﺘﻐﻴﺮ mﻭ nﺑﻪ ﻋﻨﻮﺍﻥ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻝ ﺍﻋﻼﻥ ﻭ
ﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﺍﻳﺶ n ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﺪﻩﺍﻧﺪ .ﺩﺭ ﻫﺮ ﺗﮑﺮﺍﺭ ﺣﻠﻘﻪ m ،ﺳﻪ ﻭﺍﺣﺪ ﮐﺎﺳﺘﻪ ﺷﺪﻩ ﻭ
ﻣﻲﻳﺎﺑﺪ .ﺩﺭ ﻧﺘﻴﺠﻪ ﺯﻭﺝﻫﺎﻱ ) (m,nﺑﻪ ﺷﮑﻞ ) (95,11ﻭ ) (92,12ﻭ ) (89,13ﻭ
) (86,14ﻭ ) (83,15ﻭ ) (80,16ﺗﻮﻟﻴﺪ ﻣﻲﺷﻮﻧﺪ .ﭼﻮﻥ 80ﺑﺮ 16ﺑﺨﺶﭘﺬﻳﺮ
ﺍﺳﺖ ،ﺣﻠﻘﻪ ﺑﺎ ﺯﻭﺝ ) (80,16ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ.
ﺩﺭ ﺍﻭﻟﻴﻦ ﺗﻜﺮﺍﺭ ﺍﺯ ﺣﻠﻖۀ ﺑﻴﺮﻭﻧﻲ ،ﻭﻗﺘﻲ ﮐﻪ x=1ﺍﺳﺖ ،ﺣﻠﻖۀ ﺩﺭﻭﻧﻲ ﺩﻩ ﻣﺮﺗﺒﻪ ﺗﻜﺮﺍﺭ
ﻣﻲﺷﻮﺩ ﻭ ﺑﻪ ﺍﺯﺍﻱ y=1ﺗﺎ 10ﻣﻘﺎﺩﻳﺮ 1*yﺭﺍ ﺭﻭﻱ ﻳﮏ ﺭﺩﻳﻒ ﭼﺎﭖ ﻣﻲﻛﻨﺪ .ﻭﻗﺘﻲ
ﺣﻠﻖۀ ﺩﺭﻭﻧﻲ ﭘﺎﻳﺎﻥ ﻳﺎﻓﺖ ،ﺑﺎ ﺩﺳﺘﻮﺭ ; cout << endlﻣﮑﺎﻥﻧﻤﺎ ﺑﻪ ﺳﻄﺮ ﺑﻌﺪﻱ ﺭﻭﻱ
ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﻣﻨﺘﻘﻞ ﻣﻲﺷﻮﺩ .ﺣﺎﻻ ﺩﻭﻣﻴﻦ ﺗﻜﺮﺍﺭ ﺣﻠﻖۀ ﺑﻴﺮﻭﻧﻲ ﺑﻪ ﺍﺯﺍﻱ x=2ﺁﻏﺎﺯ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 110
ﻣﻲﺷﻮﺩ .ﺩﻭﺑﺎﺭﻩ ﺣﻠﻖۀ ﺩﺭﻭﻧﻲ ﺩﻩ ﻣﺮﺗﺒﻪ ﺗﻜﺮﺍﺭ ﻣﻲﺷﻮﺩ ﻭ ﺍﻳﻦ ﺩﻓﻌﻪ ﻣﻘﺎﺩﻳﺮ 2*yﺭﻭﻱ ﻳﮏ
ﺳﻄﺮ ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﺩﻭﺑﺎﺭﻩ ﺑﺎ ﺩﺳﺘﻮﺭ ; cout << endlﻣﮑﺎﻥﻧﻤﺎ ﺑﻪ ﺳﻄﺮ ﺑﻌﺪﻱ
ﻣﻲﺭﻭﺩ ﻭ ﺗﮑﺮﺍﺭ ﺳﻮﻡ ﺣﻠﻖۀ ﺑﻴﺮﻭﻧﻲ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ .ﺍﻳﻦ ﺭﻭﻳﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ
ﺣﻠﻖۀ ﺑﻴﺮﻭﻧﻲ ﺑﺮﺍﻱ ﺑﺎﺭ ﺩﻫﻢ ﺗﮑﺮﺍﺭ ﺷﺪﻩ ﻭ ﺁﺧﺮﻳﻦ ﺳﻄﺮ ﺟﺪﻭﻝ ﻫﻢ ﭼﺎﭖ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ
ﺑﺮﻧﺎﻣﻪ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ.
ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺷﮑﻞﺩﻫﻨﺪۀ ﻓﺮﺍﻳﻨﺪ setwﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ .ﻋﺒﺎﺭﺕ ) setw(4ﺑﻪ
ﺍﻳﻦ ﻣﻌﻨﻲ ﺍﺳﺖ ﻛﻪ ﻃﻮﻝ ﻧﺎﺣﻲۀ ﭼﺎﭖ ﺭﺍ ﺑﺮﺍﻱ ﺧﺮﻭﺟﻲ ﺑﻌﺪﻱ ﺑﻪ ﺍﻧﺪﺍﺯۀ ﭼﻬﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ
ﺗﻨﻈﻴﻢ ﮐﻦ .ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺍﮔﺮ ﺧﺮﻭﺟﻲ ﮐﻢﺗﺮ ﺍﺯ ﭼﻬﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ ﺑﺎﺷﺪ ،ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﺑﻪ
ﺧﺮﻭﺟﻲ ﻣﺮﺑﻮﻃﻪ ﭘﻴﻮﻧﺪ ﺯﺩﻩ ﻣﻲﺷﻮﺩ ﺗﺎ ﻃﻮﻝ ﺧﺮﻭﺟﻲ ﺑﻪ ﺍﻧﺪﺍﺯۀ ﭼﻬﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ ﺷﻮﺩ .ﻧﺘﻴﺠﻪ
ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺧﺮﻭﺟﻲ ﻧﻬﺎﻳﻲ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺟﺪﻭﻝ ﻣﺮﺗﺐ ﺭﻭﻱ ﺩﻩ ﺳﻄﺮ ﻭ ﺩﻩ ﺳﺘﻮﻥ ﺯﻳﺮ
ﻫﻢ ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﺷﮑﻞﺩﻫﻨﺪﻩﻫﺎﻱ ﻓﺮﺍﻳﻨﺪ ﺩﺭ ﺳﺮﻓﺎﻳﻞ > <iomanipﺗﻌﺮﻳﻒ ﺷﺪﻩﺍﻧﺪ.
ﺑﻨﺎﺑﺮﺍﻳﻦ ﺑﺮﺍﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺷﮑﻞﺩﻫﻨﺪﻩﻫﺎﻱ ﻓﺮﺁﻳﻨﺪ ﺑﺎﻳﺪ ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪۀ
> #include <iomanipﺭﺍ ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻴﺎﻓﺰﺍﻳﻴﺪ .ﻫﻤﭽﻨﻴﻦ ﺑﺮﻧﺎﻣﻪ ﺑﺎﻳﺪ ﺩﺍﺭﺍﻱ
ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪۀ > #include<iostreamﻧﻴﺰ ﺑﺎﺷﺪ.
4‐5ﺩﺳﺘﻮﺭ break
)(int main
;{ int n, count=0, sum=0
;cout << "Enter positive integers (0 to quit):" << endl
);;( for "// "forever
;" { cout << "\t" << count + 1 << ":
;cin >> n
;if (n <= 0) break
;++count
;sum += n
}
cout << "The average of those " << count << " positive
;numbers is " << float(sum)/count << endl
}
Enter positive integers (0 to quit):
1: 4
2: 7
3: 1
4: 5
5: 2
6: 0
The average of those 5 positive numbers is 3.8
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻭﻗﺘﻲ ﮐﻪ 0ﻭﺍﺭﺩ ﺷﻮﺩ ،ﺩﺳﺘﻮﺭ breakﺍﺟﺮﺍ ﺷﺪﻩ ﻭ ﺣﻠﻘﻪ ﻓﻮﺭﺍ ﺧﺎﺗﻤﻪ
ﻣﻲﻳﺎﺑﺪ ﻭ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ﺑﻌﺪ ﺍﺯ ﺣﻠﻘﻪ ﭘﺮﺵ ﻣﻲﮐﻨﺪ .ﺑﻪ ﻧﺤﻮۀ ﻧﻮﺷﺘﻦ
ﺩﺳﺘﻮﺭ forﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺩﻗﺖ ﮐﻨﻴﺪ .ﻫﺮ ﺳﻪ ﺑﺨﺶ ﻛﻨﺘﺮﻟﻲ ﺩﺭ ﺍﻳﻦ ﺣﻠﻘﻪ ،ﺧﺎﻟﻲ ﺍﺳﺖ:
) ; ; ( .forﺍﻳﻦ ﺗﺮﮐﻴﺐ ﺑﻪ ﻣﻌﻨﺎﻱ ﺑﻲﺍﻧﺘﻬﺎﻳﻲ ﺍﺳﺖ .ﻳﻌﻨﻲ ﺑﺪﻭﻥ ﺩﺳﺘﻮﺭ breakﺍﻳﻦ
ﺣﻠﻘﻪ ﻳﻚ ﺣﻠﻖۀ ﻧﺎﻣﺘﻨﺎﻫﻲ ﻣﻲﺷﻮﺩ.
ﻭﻗﺘﻲ ﺩﺳﺘﻮﺭ breakﺩﺭﻭﻥ ﺣﻠﻘﻪﻫﺎﻱ ﺗﻮﺩﺭﺗﻮ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ ،ﻓﻘﻂ ﺭﻭﻱ ﺣﻠﻘﻪﺍﻱ
ﮐﻪ ﻣﺴﺘﻘﻴﻤﺎ ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺗﺎﺛﻴﺮ ﻣﻲﮔﺬﺍﺭﺩ .ﺣﻠﻘﻪﻫﺎﻱ ﺑﻴﺮﻭﻧﻲ ﺑﺪﻭﻥ ﻫﻴﭻ ﺗﻐﻴﻴﺮﻱ
ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﻨﺪ.
ﭼﻮﻥ ﻋﻤﻞ ﺿﺮﺏ ﺟﺎﺑﺠﺎﻳﻲﭘﺬﻳﺮ ﺍﺳﺖ )ﻳﻌﻨﻲ ،(3×4 = 4×3ﺑﺮﺍﻱ ﺍﻳﺠﺎﺩ ﻳﮏ
ﺟﺪﻭﻝ ﺿﺮﺏ ﻓﻘﻂ ﮐﺎﻓﻲ ﺍﺳﺖ ﺍﻋﺪﺍﺩ ﻗﻄﺮ ﭘﺎﻳﻴﻨﻲ ﻣﺸﺨﺺ ﺷﻮﻧﺪ .ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ،ﻣﺜﺎﻝ ‐16
4ﺭﺍ ﺑﺮﺍﻱ ﭼﺎﭖ ﻳﮏ ﺟﺪﻭﻝ ﺿﺮﺏ ﻣﺜﻠﺜﻲ ﺗﻐﻴﻴﺮ ﻣﻲﺩﻫﺪ:
)(int main
){ for (int x=1; x <= 10; x++
){ for (int y=1; y <= 10; y++
;if (y > x) break
;else cout << setw(4) << x*y
;cout << endl
}
}
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
6 12 18 24 30 36
7 14 21 28 35 42 49
8 16 24 32 40 48 56 64
9 18 27 36 45 54 63 72 81
10 20 30 40 50 60 70 80 90 100
ﻭﻗﺘﻲ y>xﺑﺎﺷﺪ ،ﺍﺟﺮﺍﻱ ﺣﻠﻖۀ yﺩﺭﻭﻧﻲ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ ﻭ ﺗﻜﺮﺍﺭ ﺑﻌﺪﻱ ﺣﻠﻖۀ ﺧﺎﺭﺟﻲ x
ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ .ﻣﺜﻼ ﻭﻗﺘﻲ x=3ﺑﺎﺷﺪ ،ﺣﻠﻖۀ yﺳﻪ ﺑﺎﺭ ﺗﻜﺮﺍﺭ ﻣﻲﺷﻮﺩ ﻭ ﺧﺮﻭﺟﻲﻫﺎﻱ 3
ﻭ 6ﻭ 9ﭼﺎﭖ ﻣﻲﺷﻮﻧﺪ .ﺩﺭ ﺗﻜﺮﺍﺭ ﭼﻬﺎﺭﻡ ،ﺷﺮﻁ ) (y>xﺑﺮﺍﺑﺮ ﺑﺎ ﺩﺭﺳﺖ ﺍﺭﺯﻳﺎﺑﻲ
ﻣﻲﺷﻮﺩ .ﭘﺲ ﺩﺳﺘﻮﺭ breakﺍﺟﺮﺍ ﺷﺪﻩ ﻭ ﻛﻨﺘﺮﻝ ﻓﻮﺭﺍ ﺑﻪ ﺧﻂ ; cout<<endlﻣﻨﺘﻘﻞ
ﻣﻲﺷﻮﺩ )ﺯﻳﺮﺍ ﺍﻳﻦ ﺧﻂ ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ﺧﺎﺭﺝ ﺍﺯ ﺣﻠﻖۀ ﺩﺭﻭﻧﻲ yﺍﺳﺖ( .ﺁﻧﮕﺎﻩ ﺣﻠﻖۀ ﺑﻴﺮﻭﻧﻲ
xﺗﻜﺮﺍﺭ ﭼﻬﺎﺭﻡ ﺭﺍ ﺑﺎ x=4ﺁﻏﺎﺯ ﻣﻲﻛﻨﺪ.
4‐6ﺩﺳﺘﻮﺭ continue
ﺍﻳﻦ ﮐﻪ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﺩﻫﺪ ،ﺍﺟﺮﺍ ﺭﺍ ﺑﻪ ﺗﻜﺮﺍﺭ ﺑﻌﺪﻱ ﺣﻠﻘﻪ ﻣﻨﺘﻘﻞ ﻣﻲﻛﻨﺪ .ﺍﻳﻦ ﺩﺳﺘﻮﺭ،
ﺍﺩﺍﻡۀ ﭼﺮﺥۀ ﻓﻌﻠﻲ ﺭﺍ ﻟﻐﻮ ﮐﺮﺩﻩ ﻭ ﺍﺟﺮﺍﻱ ﺩﻭﺭ ﺑﻌﺪﻱ ﺣﻠﻘﻪ ﺭﺍ ﺁﻏﺎﺯ ﻣﻲﮐﻨﺪ.
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺗﻌﺪﺍﺩ ﺗﮑﺮﺍﺭ ﺣﻠﻘﻪ ﺭﺍ ﻣﻲﺷﻤﺎﺭﺩ .ﺩﺭ ﺍﺑﺘﺪﺍﻱ ﻫﺮ ﺣﻠﻘﻪ ﺑﺎ ﭼﺎﭖ nﻣﺸﺨﺺ
ﻣﻲﺷﻮﺩ ﮐﻪ ﭼﻨﺪﻣﻴﻦ ﺩﻭﺭ ﺣﻠﻘﻪ ﺩﺭ ﺣﺎﻝ ﺍﺟﺮﺍﺳﺖ .ﺳﭙﺲ ﺍﺯ ﮐﺎﺭﺑﺮ ﺩﺭﺧﻮﺍﺳﺖ ﻣﻲﺷﻮﺩ ﺗﺎ
ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﺍﻧﺘﺨﺎﺏ ،ﻭﺍﺭﺩ ﮐﻨﺪ .ﺍﮔﺮ ﮐﺎﺭﺍﮐﺘﺮ ﻭﺍﺭﺩ ﺷﺪﻩ ' 'yﺑﺎﺷﺪ ،ﺷﺮﻁ
)' (c=='yﺑﺮﺍﺑﺮ ﺑﺎ ﺩﺭﺳﺖ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﻭ ﻟﺬﺍ ﺩﺳﺘﻮﺭ continueﺍﺟﺮﺍ ﺷﺪﻩ ﻭ
ﺩﻭﺭ ﺟﺪﻳﺪ ﺣﻠﻘﻪ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ ﮐﺎﺭﺍﮐﺘﺮ ﻭﺍﺭﺩ ﺷﺪﻩ ﻫﺮ ﭼﻴﺰﻱ ﻏﻴﺮ ﺍﺯ ' 'yﺑﺎﺷﺪ،
ﺩﺳﺘﻮﺭ breakﺍﻳﻦ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ ﻭ ﮐﻨﺘﺮﻝ ﺍﺟﺮﺍ ﺑﻪ ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ﺑﻴﺮﻭﻥ ﺣﻠﻘﻪ
ﭘﺮﺵ ﻣﻲﮐﻨﺪ .ﺳﭙﺲ ﻣﺠﻤﻮﻉ ﺩﻓﻌﺎﺗﻲ ﮐﻪ ﺣﻠﻘﻪ ﺗﮑﺮﺍﺭ ﺷﺪﻩ ﭼﺎﭖ ﻣﻲﮔﺮﺩﺩ ﻭ ﺑﺮﻧﺎﻣﻪ ﭘﺎﻳﺎﻥ
ﻣﻲﮔﻴﺮﺩ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 114
4‐7ﺩﺳﺘﻮﺭ goto
ﺍﮔﺮ ﺷﺮﻁ ) (i+j+k>Nﺩﺭ ﺩﺭﻭﻧﻲﺗﺮﻳﻦ ﺣﻠﻘﻪ ﺩﺭﺳﺖ ﺷﻮﺩ ،ﺑﻪ ﺩﺳﺘﻮﺭ gotoﻣﻲﺭﺳﻴﻢ.
ﻭﻗﺘﻲ ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺍﺟﺮﺍ ﺷﻮﺩ ،ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺳﻄﺮﻱ ﮐﻪ ﺑﺮﭼﺴﺐ escﺩﺍﺭﺩ ﻣﻨﺘﻘﻞ
ﻣﻲﺷﻮﺩ .ﺍﻳﻦ ﺧﻂ ﺑﻴﺮﻭﻥ ﺍﺯ ﺣﻠﻘﻪﻫﺎﻱ jﻭ kﺍﺳﺖ .ﭘﺲ ﺑﺎ ﺍﻳﻦ ﭘﺮﺵ ﻫﺮ ﺩﻭﻱ ﺍﻳﻦ
ﺣﻠﻘﻪﻫﺎ ﭘﺎﻳﺎﻥ ﻣﻲﮔﻴﺮﻧﺪ .ﻭﻗﺘﻲ iﻭ jﺻﻔﺮ ﻫﺴﺘﻨﺪ ،ﺣﻠﻖۀ kﭘﻨﺞ ﺑﺎﺭ ﺗﮑﺮﺍﺭ ﻣﻲﮔﺮﺩﺩ ﻭ
0 1 2 3 4ﺑﻪ ﻫﻤﺮﺍﻩ ﺳﺘﺎﺭﻩ * ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﺁﻧﮕﺎﻩ jﺑﻪ 1ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ ﻭ ﺣﻠﻖۀ
kﭘﻨﺞ ﺑﺎﺭ ﺩﻳﮕﺮ ﺗﻜﺮﺍﺭ ﺷﺪﻩ ﻭ ﺍﻳﻦ ﺑﺎﺭ 1 2 3 4 5ﻫﻤﺮﺍﻩ ﻳﻚ ﺳﺘﺎﺭﻩ * ﭼﺎﭖ ﻣﻲﺷﻮﺩ.
ﺳﭙﺲ jﺑﻪ 2ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ ﻭ ﺣﻠﻖۀ kﭼﻬﺎﺭ ﺑﺎﺭ ﺩﻳﮕﺮ ﺗﻜﺮﺍﺭ ﻣﻲﺷﻮﺩ ﻭ 2 3 4 5
ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﺍﻣﺎ ﺩﺭ ﺗﻜﺮﺍﺭ ﺑﻌﺪﻱ ﺣﻠﻖۀ kﺷﺮﻁ ) (i+j+k>0ﺩﺭﺳﺖ ﻣﻲﺷﻮﺩ ﺯﻳﺮﺍ
ﺣﺎﻻ i+j+k = 6ﺍﺳﺖ .ﭘﺲ ﺩﺳﺘﻮﺭ gotoﺑﺮﺍﻱ ﺍﻭﻟﻴﻦ ﺑﺎﺭ ﺍﺟﺮﺍ ﺷﺪﻩ ﻭ ﮐﻨﺘﺮﻝ ﺑﺮﻧﺎﻣﻪ
ﺑﻪ ﺳﻄﺮ ﺑﺮﭼﺴﺐﺩﺍﺭ ﮐﻪ ﻳﮏ ﺩﺳﺘﻮﺭ ﺧﺮﻭﺟﻲ ﺍﺳﺖ ﭘﺮﺵ ﻣﻲﮐﻨﺪ ،ﻳﻚ ﻧﻘﻄﻪ ﭼﺎﭖ ﺷﺪﻩ ﻭ
ﻣﮑﺎﻥﻧﻤﺎ ﺑﻪ ﺳﻄﺮ ﺑﻌﺪ ﻣﻨﺘﻘﻞ ﻣﻲﺷﻮﺩ .ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺣﻠﻘﻪﻫﺎﻱ jﻭ kﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ
ﺗﮑﺮﺍﺭﻫﺎﻳﺸﺎﻥ ﺭﺍ ﮐﺎﻣﻞ ﮐﻨﻨﺪ ،ﻧﺎﺗﻤﺎﻡ ﺭﻫﺎ ﻣﻲﺷﻮﻧﺪ .ﺩﺳﺘﻮﺭ ﺑﺮﭼﺴﺐ ﺧﻮﺭﺩﻩ ،ﺧﻮﺩ ﺟﺰﻭ
ﺑﺪﻥۀ ﺣﻠﻖۀ iﺍﺳﺖ .ﻟﺬﺍ ﭘﺲ ﺍﺯ ﭘﺎﻳﺎﻥ ﮔﺮﻓﺘﻦ ﺍﺟﺮﺍﻱ ﺍﻳﻦ ﺳﻄﺮ ،ﺗﮑﺮﺍﺭ ﺑﻌﺪﻱ ﺣﻠﻖۀ iﺁﻏﺎﺯ
ﻣﻲﺷﻮﺩ .ﺣﺎﻻ i=1ﺍﺳﺖ ﻭ ﺣﻠﻖۀ jﺩﻭﺑﺎﺭﻩ ﺑﺎ j=0ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ﻭ ﺍﻳﻦ ﺧﻮﺩ ﺑﺎﻋﺚ
ﻣﻲﮔﺮﺩﺩ ﺣﻠﻖۀ kﻧﻴﺰ ﺑﺎ k=0ﺩﻭﺑﺎﺭﻩ ﺷﺮﻭﻉ ﺷﻮﺩ .ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﻭ
ﺧﺮﻭﺟﻲ ﻧﻬﺎﻳﻲ ﺣﺎﺻﻞ ﻣﻲﺷﻮﺩ.
ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ gotoﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻫﺮ ﻗﺴﻤﺖ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻫﺮ ﻗﺴﻤﺖ ﺩﻳﮕﺮﻱ
ﭘﺮﺵ ﮐﺮﺩ .ﮔﺮﭼﻪ ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﺭﺍﺣﺖﺗﺮ ﺑﺘﻮﺍﻧﻴﻢ ﺍﺯ ﺗﮑﺮﺍﺭ ﺣﻠﻘﻪﻫﺎ ﺧﻼﺹ
ﺷﻮﻳﻢ ﻳﺎ ﺁﺳﺎﻥﺗﺮ ﺑﻪ ﺳﻄﺮ ﺩﻟﺨﻮﺍﻩ ﺍﻧﺸﻌﺎﺏ ﮐﻨﻴﻢ ﺍﻣﺎ ﺗﺠﺮﺑﻪ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﮐﻪ ﺍﺳﺘﻔﺎﺩۀ ﺑﻲﻣﻬﺎﺑﺎ ﺍﺯ
ﺩﺳﺘﻮﺭ gotoﺳﺒﺐ ﺍﻓﺰﺍﻳﺶ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﻭ ﮐﺎﻫﺶ ﭘﺎﻳﺪﺍﺭﻱ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺷﻮﺩ.
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺯ ﻳﮏ ﭘﺮﭼﻢ ﺑﻪ ﻧﺎﻡ doneﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ .ﻭﻗﺘﻲ doneﺑﺮﺍﺑﺮ ﺑﺎ true
ﺷﻮﺩ ،ﻫﺮ ﺩﻭ ﺣﻠﻖۀ ﺩﺭﻭﻧﻲ kﻭ jﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ ﻭ ﺣﻠﻖۀ ﺧﺎﺭﺟﻲ iﺗﻜﺮﺍﺭﺵ ﺭﺍ ﺑﺎ ﭼﺎﭖ
ﻳﮏ ﻧﻘﻄﻪ ﺍﺩﺍﻣﻪ ﻣﻲﺩﻫﺪ ﻭ ﭘﺮﭼﻢ ﺭﺍ ﺩﻭﺑﺎﺭﻩ falseﻣﻲﮐﻨﺪ ﻭ ﺩﻭﺭ ﺟﺪﻳﺪ ﺭﺍ ﺁﻏﺎﺯ
ﻣﻲﻧﻤﺎﻳﺪ .ﮔﺮﭼﻪ ﻣﻨﻄﻖ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﮐﻤﻲ ﭘﻴﭽﻴﺪﻩﺗﺮ ﺍﺳﺖ ﺍﻣﺎ ﻗﺎﺑﻠﻴﺖ ﺍﻃﻤﻴﻨﺎﻥ ﺑﻴﺸﺘﺮﻱ ﻧﺴﺒﺖ
ﺑﻪ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 4‐20ﺩﺍﺭﺩ ﺯﻳﺮﺍ ﻫﻴﭻ ﺣﻠﻘﻪﺍﻱ ﻧﻴﻤﻪﮐﺎﺭﻩ ﻧﻤﻲﻣﺎﻧﺪ ﻭ ﻫﻴﭻ ﻣﺘﻐﻴﺮﻱ
ﺑﻼﺗﮑﻠﻴﻒ ﺭﻫﺎ ﻧﻤﻲﺷﻮﺩ.
1
4‐8ﺗﻮﻟﻴﺪ ﺍﻋﺪﺍﺩ ﺷﺒﻪ ﺗﺼﺎﺩﻓﻲ
ﻳﻜﻲ ﺍﺯ ﻛﺎﺭﺑﺮﺩﻫﺎﻱ ﺑﺴﻴﺎﺭ ﻣﻬﻢ ﺭﺍﻳﺎﻧﻪﻫﺎ» ،ﺷﺒﻴﻪﺳﺎﺯﻱ «2ﺳﻴﺴﺘﻢﻫﺎﻱ ﺩﻧﻴﺎﻱ ﻭﺍﻗﻌﻲ
ﺍﺳﺖ .ﺗﺤﻘﻴﻘﺎﺕ ﻭ ﺗﻮﺳﻌﻪﻫﺎﻱ ﺑﺴﻴﺎﺭ ﭘﻴﺸﺮﻓﺘﻪ ﺑﻪ ﺍﻳﻦ ﺭﺍﻫﮑﺎﺭ ﺧﻴﻠﻲ ﻭﺍﺑﺴﺘﻪ ﺍﺳﺖ .ﺑﻪ
ﻭﺳﻴﻞۀ ﺷﺒﻴﻪﺳﺎﺯﻱ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺭﻓﺘﺎﺭ ﺳﻴﺴﺘﻢﻫﺎﻱ ﻣﺨﺘﻠﻒ ﺭﺍ ﻣﻄﺎﻟﻌﻪ ﮐﻨﻴﻢ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﻻﺯﻡ
ﺑﺎﺷﺪ ﻭﺍﻗﻌﺎ ﺁﻥﻫﺎ ﺭﺍ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻧﻤﺎﻳﻴﻢ .ﺩﺭ ﺷﺒﻴﻪﺳﺎﺯﻱ ﻧﻴﺎﺯ ﺍﺳﺖ »ﺍﻋﺪﺍﺩ ﺗﺼﺎﺩﻓﻲ« ﺗﻮﺳﻂ
ﺭﺍﻳﺎﻧﻪﻫﺎ ﺗﻮﻟﻴﺪ ﺷﻮﺩ ﺗﺎ ﻧﺎﺩﺍﻧﺴﺘﻪﻫﺎﻱ ﺩﻧﻴﺎﻱ ﻭﺍﻗﻌﻲ ﻣﺪﻝﺳﺎﺯﻱ ﺷﻮﺩ .ﺍﻟﺒﺘﻪ ﺭﺍﻳﺎﻧﻪﻫﺎ »ﺛﺎﺑﺖﮐﺎﺭ«
ﻫﺴﺘﻨﺪ ﻳﻌﻨﻲ ﺑﺎ ﺩﺍﺩﻥ ﺩﺍﺩﻩﻫﺎﻱ ﻣﺸﺎﺑﻪ ﺑﻪ ﺭﺍﻳﺎﻧﻪﻫﺎﻱ ﻣﺸﺎﺑﻪ ،ﻫﻤﻴﺸﻪ ﺧﺮﻭﺟﻲ ﻳﮑﺴﺎﻥ ﺗﻮﻟﻴﺪ
ﻣﻲﺷﻮﺩ .ﺑﺎ ﻭﺟﻮﺩ ﺍﻳﻦ ﻣﻲﺗﻮﺍﻥ ﺍﻋﺪﺍﺩﻱ ﺗﻮﻟﻴﺪ ﮐﺮﺩ ﮐﻪ ﺑﻪ ﻇﺎﻫﺮ ﺗﺼﺎﺩﻓﻲ ﻫﺴﺘﻨﺪ؛ ﺍﻋﺪﺍﺩﻱ ﮐﻪ
117 ﻓﺼﻞ ﭼﻬﺎرم /ﺗﮑﺮار
ﺑﻪ ﻃﻮﺭ ﻳﮑﻨﻮﺍﺧﺖ ﺩﺭ ﻳﮏ ﻣﺤﺪﻭﺩۀ ﺧﺎﺹ ﮔﺴﺘﺮﺩﻩﺍﻧﺪ ﻭ ﺑﺮﺍﻱ ﻫﻴﭻﮐﺪﺍﻡ ﺍﻟﮕﻮﻱ ﻣﺸﺨﺼﻲ
ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ .ﭼﻨﻴﻦ ﺍﻋﺪﺍﺩﻱ ﺭﺍ »ﺍﻋﺪﺍﺩ ﺷﺒﻪﺗﺼﺎﺩﻓﻲ« ﻣﻲﻧﺎﻣﻴﻢ.
ﺳﺮﻓﺎﻳﻞ > <cstdlibﺩﺭ cﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺩﺍﺭﺍﻱ ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )( randﺍﺳﺖ ﮐﻪ
ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺷﺒﻪﺗﺼﺎﺩﻓﻲ ﺩﺭ ﻣﺤﺪﻭﺩۀ ﺻﻔﺮ ﺗﺎ RAND_MAXﺗﻮﻟﻴﺪ ﻣﻲﻧﻤﺎﻳﺪ.
)(int main
{ // prints pseudo-random numbers:
)for (int i = 0; i < 8; i++
;cout << rand() << endl
;cout << "RAND_MAX = " << RAND_MAX << endl
}
1103527590
377401575
662824084
1147902781
2035015474
368800899
1508029952
486256185
RAND_MAX = 2147483647
ﻫﺮ ﺑﺎﺭ ﮐﻪ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺟﺮﺍ ﺷﻮﺩ ،ﺭﺍﻳﺎﻧﻪ ﻫﺸﺖ ﻋﺪﺩ ﺻﺤﻴﺢ unsignedﺗﻮﻟﻴﺪ ﻣﻲﮐﻨﺪ ﮐﻪ
ﺑﻪ ﻃﻮﺭ ﻳﮑﻨﻮﺍﺧﺖ ﺩﺭ ﻓﺎﺻﻞۀ 0ﺗﺎ RAND_MAXﮔﺴﺘﺮﺩﻩ ﺷﺪﻩﺍﻧﺪ RAND_MAX .ﺩﺭ ﺍﻳﻦ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 118
ﺭﺍﻳﺎﻧﻪ ﺑﺮﺍﺑﺮ ﺑﺎ 2,147,483,647ﺍﺳﺖ .ﺧﺮﻭﺟﻲ ﺯﻳﺮ ،ﺍﺟﺮﺍﻱ ﺩﻳﮕﺮﻱ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ
ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ:
1103527590
377401575
662824084
1147902781
2035015474
368800899
1508029952
486256185
RAND_MAX = 2147483647
ﻣﺘﺎﺳﻔﺎﻧﻪ ﻫﺮ ﺑﺎﺭ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ،ﻫﻤﺎﻥ ﺍﻋﺪﺍﺩ ﻗﺒﻠﻲ ﺗﻮﻟﻴﺪ ﻣﻲﺷﻮﻧﺪ ﺯﻳﺮﺍ ﺍﻳﻦ ﺍﻋﺪﺍﺩ
ﺍﺯ ﻳﮏ ﻫﺴﺖۀ ﻣﺸﺘﺮﮎ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﻧﺪ.
ﻫﺮ ﻋﺪﺩ ﺷﺒﻪﺗﺼﺎﺩﻓﻲ ﺍﺯ ﺭﻭﻱ ﻋﺪﺩ ﻗﺒﻠﻲ ﺧﻮﺩ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ .ﺍﻭﻟﻴﻦ ﻋﺪﺩ
ﺷﺒﻪﺗﺼﺎﺩﻓﻲ ﺍﺯ ﺭﻭﻱ ﻳﻚ ﻣﻘﺪﺍﺭ ﺩﺍﺧﻠﻲ ﮐﻪ »ﻫﺴﺘﻪ «1ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ ﺍﻳﺠﺎﺩ ﻣﻲﮔﺮﺩﺩ .ﻫﺮ
ﺩﻓﻌﻪ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﺷﻮﺩ ،ﻫﺴﺘﻪ ﺑﺎ ﻳﮏ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﺷﻮﺩ .ﺑﺮﺍﻱ ﺣﺬﻑ
ﺍﻳﻦ ﺍﺛﺮ ﻧﺎﻣﻄﻠﻮﺏ ﮐﻪ ﺍﺯ ﺗﺼﺎﺩﻓﻲ ﺑﻮﺩﻥ ﺍﻋﺪﺍﺩ ﻣﻲﮐﺎﻫﺪ ،ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ
)( srandﺧﻮﺩﻣﺎﻥ ﻣﻘﺪﺍﺭ ﻫﺴﺘﻪ ﺭﺍ ﺍﻧﺘﺨﺎﺏ ﮐﻨﻴﻢ.
)(int main
{ // prints pseudo-random numbers:
;unsigned seed
;" cout << "Enter seed:
;cin >> seed
;)srand(seed // initializes the seed
)for (int i = 0; i < 8; i++
;cout << rand() << endl
}
119 ﻓﺼﻞ ﭼﻬﺎرم /ﺗﮑﺮار
1 – Seed
ﺍﺟﺮﺍﻱ ﺩﻭﻡ ﻣﺎﻧﻨﺪ ﺭﺷﺘﻪ ﺍﻋﺪﺍﺩ ﺗﻮﻟﻴﺪ ﺷﺪﻩ ﺩﺭ ﻣﺜﺎﻝ 4‐22ﺍﺳﺖ .ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺍﻟﻘﺎ ﻣﻲﮐﻨﺪ
ﮐﻪ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﻫﺴﺘﻪ ﺩﺭ ﺍﻳﻦ ﺭﺍﻳﺎﻧﻪ ،ﻋﺪﺩ ﻳﮏ ﺍﺳﺖ.
ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﻫﺴﺘﻪ ﺑﺎﻳﺪ ﺑﻪ ﻃﻮﺭ ﻣﺤﺎﻭﺭﻩﺍﻱ ﻭﺍﺭﺩ ﺷﻮﺩ ﻣﺸﮑﻠﻲ ﺍﺳﺖ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ
ﺍﺯ ﺳﺎﻋﺖ ﺳﻴﺴﺘﻢ ﺣﻞ ﻣﻲﺷﻮﺩ» .ﺳﺎﻋﺖ ﺳﻴﺴﺘﻢ «1ﺯﻣﺎﻥ ﻓﻌﻠﻲ ﺭﺍ ﺑﺮ ﺣﺴﺐ ﺛﺎﻧﻴﻪ ﻧﮕﻪ
ﻣﻲﺩﺍﺭﺩ .ﺗﺎﺑﻊ )( timeﮐﻪ ﺩﺭ ﺳﺮﻓﺎﻳﻞ > <ctimeﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺯﻣﺎﻥ ﻓﻌﻠﻲ ﺭﺍ ﺑﻪ
ﺻﻮﺭﺕ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ unsignedﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﻋﻨﻮﺍﻥ ﻫﺴﺘﻪ
ﺑﺮﺍﻱ ﺗﺎﺑﻊ )( randﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ.
200398846
1379699551
1622702508
715548277
seed = 808148160
892939769
1559273790
1468644255
952730860
1322627253
844657339
440402904
ﺩﺭ ﺍﻭﻟﻴﻦ ﺍﺟﺮﺍ ،ﺗﺎﺑﻊ )( timeﻋﺪﺩ ﺻﺤﻴﺢ 808,148,157ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﮐﻪ ﺑﻪ
ﻋﻨﻮﺍﻥ ﻫﺴﺖۀ ﺗﻮﻟﻴﺪ ﮐﻨﻨﺪۀ ﺍﻋﺪﺍﺩ ﺗﺼﺎﺩﻓﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ .ﺩﻭﻣﻴﻦ ﺍﺟﺮﺍ 3ﺛﺎﻧﻴﻪ ﺑﻌﺪ
ﺍﻧﺠﺎﻡ ﺷﺪﻩ ،ﺑﻨﺎﺑﺮﺍﻳﻦ ﺗﺎﺑﻊ )( timeﻋﺪﺩ ﺻﺤﻴﺢ 808,148,160ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﮐﻪ
ﺍﻳﻦ ﻣﻘﺪﺍﺭ ،ﺭﺷﺘﻪ ﺍﻋﺪﺍﺩ ﮐﺎﻣﻼ ﻣﺘﻔﺎﻭﺗﻲ ﺭﺍ ﺗﻮﻟﻴﺪ ﻣﻲﮐﻨﺪ.
ﺩﻭ ﺍﺟﺮﺍﻱ ﺯﻳﺮ ﺭﻭﻱ ﻳﮏ pcﺑﺎ ﭘﺮﺩﺍﺯﻧﺪۀ intelﺍﻧﺠﺎﻡ ﺷﺪﻩ ﺍﺳﺖ:
seed = 943364015
2948
15841
72
25506
30808
29709
13155
2527
seed = 943364119
17427
20464
13149
5702
12766
1424
16612
31746
seed = 808238101
Enter minimum and maximum: 22 66
63 29 56 22 53 57 39 56 43 36 62 30 41 57 26 61 59 26 28
20 ﺩﻭﻣﻴﻦ ﺍﺟﺮﺍ. ﺗﻮﻟﻴﺪ ﻣﻲﻛﻨﺪ100 ﻭ1 ﻋﺪﺩ ﺻﺤﻴﺢ ﺗﺼﺎﺩﻓﻲ ﺑﻴﻦ20 ﺍﻭﻟﻴﻦ ﺍﺟﺮﺍ
. ﮔﺴﺘﺮﺵ ﻳﺎﻓﺘﻪ ﺭﺍ ﺗﻮﻟﻴﺪ ﻣﻲﻧﻤﺎﻳﺪ66 ﻭ22 ﻋﺪﺩ ﺻﺤﻴﺢ ﮐﻪ ﺑﻴﻦ
ﺗﻘﺴﻴﻢ ﻣﻲﺷﻮﺩ ﺗﺎ ﺩﻭ ﺭﻗﻢ ﺳﻤﺖ100 ﺑﺮrand() ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭfor ﺩﺭ ﺣﻠﻖۀ
ﺭﺍﺳﺖ ﻋﺪﺩ ﺗﺼﺎﺩﻓﻲ ﺣﺬﻑ ﺷﻮﺩ ﺯﻳﺮﺍ ﺍﻳﻦ ﻣﻮﻟﺪ ﺑﻪ ﻃﻮﺭ ﻣﺘﻨﺎﻭﺏ ﺍﻋﺪﺍﺩ ﺯﻭﺝ ﻭ ﻓﺮﺩ ﺗﻮﻟﻴﺪ
123 ﻓﺼﻞ ﭼﻬﺎرم /ﺗﮑﺮار
ﻣﻲﮐﻨﺪ .ﺑﺎ ﺣﺬﻑ ﺩﻭ ﺭﻗﻢ ﺳﻤﺖ ﺭﺍﺳﺖ ﻋﺪﺩ ﺗﻮﻟﻴﺪ ﺷﺪﻩ ،ﺍﻳﻦ ﻣﺸﮑﻞ ﺑﺮﻃﺮﻑ ﻣﻲﺷﻮﺩ.
ﺳﭙﺲ ﻋﺒﺎﺭﺕ rand()/100%rangeﺍﻋﺪﺍﺩ ﺗﺼﺎﺩﻓﻲ ﺩﺭ ﻣﺤﺪﻭﺩۀ 0ﺗﺎ range-1
ﺗﻮﻟﻴﺪ ﻧﻤﻮﺩﻩ ﻭ ﻋﺒﺎﺭﺕ rand()/100%range + minﺍﻋﺪﺍﺩﻱ ﺗﺼﺎﺩﻓﻲ ﺩﺭ
ﻣﺤﺪﻭﺩۀ minﺗﺎ maxﺗﻮﻟﻴﺪ ﻣﻲﻧﻤﺎﻳﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 124
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﺩﺳﺘﻮﺭﺍﺕ ﺯﻳﺮ ،ﻳﮏ ﺣﻠﻘﻪ ﻧﻴﺴﺖ؟
ﺏ – switch ﺍﻟﻒ – while
ﺩ – do..while ﺝ – for
ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟ ;while (false) i++ – 2ﺩﺭ ﻣﻮﺭﺩ ﮐﺪ
ﺍﻟﻒ – ﺣﻠﻖۀ ﻓﻮﻕ ﺗﺎ ﺑﻲﻧﻬﺎﻳﺖ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﻭ ﻣﻘﺪﺍﺭ iﺑﻲﻧﻬﺎﻳﺖ ﻣﻲﺷﻮﺩ.
ﺏ – ﺣﻠﻖۀ ﻓﻮﻕ ﺁﻥ ﻗﺪﺭ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ iﺳﺮﺭﻳﺰ ﺷﻮﺩ.
ﺝ – ﺣﻠﻖۀ ﻓﻮﻕ ﻓﻘﻂ ﻳﮏ ﺑﺎﺭ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ﻭ iﻓﻘﻂ ﻳﮏ ﻭﺍﺣﺪ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ.
ﺩ – ﺣﻠﻖۀ ﻓﻮﻕ ﺍﺻﻼ ﺍﺟﺮﺍ ﻧﻤﻲﺷﻮﺩ.
– 3ﺍﮔﺮ iﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﻭ ﻣﻘﺪﺍﺭ ﺁﻥ 5ﺑﺎﺷﺪ ،ﭘﺲ ﺍﺯ ﺧﺎﺗﻢۀ ﺣﻠﻖۀ ﺯﻳﺮ ﻣﻘﺪﺍﺭ iﺑﺮﺍﺑﺮ
;While (i<10) i+=2 ﺑﺎ ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺍﺳﺖ؟
ﺩ – 12 ﺝ–9 ﺏ – 11 ﺍﻟﻒ – 10
– 4ﺍﮔﺮ nﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﻭ ﻣﻘﺪﺍﺭ ﺁﻥ 0ﺑﺎﺷﺪ ،ﭘﺲ ﺍﺯ ﺧﺎﺗﻢۀ ﺣﻠﻖۀ ﺯﻳﺮ ﻣﻘﺪﺍﺭ nﺑﺮﺍﺑﺮ
)While (n<5 ﺑﺎ ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺍﺳﺖ؟
{ ;if (n>3) break
;n++
}
ﺩ–3 ﺝ–6 ﺏ–5 ﺍﻟﻒ – 4
– 5ﺍﮔﺮ kﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﻭ ﻣﻘﺪﺍﺭ ﺁﻥ 5ﺑﺎﺷﺪ ،ﭘﺲ ﺍﺯ ﺧﺎﺗﻢۀ ﺣﻠﻖۀ ﺯﻳﺮ ﻣﻘﺪﺍﺭ kﺑﺮﺍﺑﺮ
do ﺑﺎ ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺍﺳﺖ؟
k++
;)while (k<5
ﺩ – kﭘﺎﺭﻳﺰ ﻣﻲ ﺷﻮﺩ. ﺝ – kﺳﺮﺭﻳﺰ ﻣﻲ ﺷﻮﺩ ﺏ–6 ﺍﻟﻒ – 5
– 6ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟
ﺍﻟﻒ‐ ﺩﺳﺘﻮﺭ breakﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ.
ﺏ – ﺩﺳﺘﻮﺭ ) exit(0ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ.
ﺝ – ﺩﺳﺘﻮﺭ continueﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ.
ﺩ – ﻏﻠﻂ ﺑﻮﺩﻥ ﺷﺮﻁ ﮐﻨﺘﺮﻝ ،ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ.
}…{ )for (j=0; true; j++ – 7ﺣﻠﻖۀ ﻣﻘﺎﺑﻞ ﭼﻨﺪ ﺑﺎﺭ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ؟
125 ﻓﺼﻞ ﭼﻬﺎرم /ﺗﮑﺮار
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﺩﺭ ﻳﻚ ﺣﻠﻖۀ whileﺍﮔﺮ ﺷﺮﻁ ﻛﻨﺘﺮﻝ ﺩﺭ ﺍﺑﺘﺪﺍ ﺑﺎ ﻣﻘﺪﺍﺭ ) falseﻳﻌﻨﻲ ﺻﻔﺮ(
ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﻮﺩ ،ﭼﻪ ﺍﺗﻔﺎﻗﻲ ﻣﻲﺍﻓﺘﺪ؟
‐2ﭼﻪ ﻭﻗﺖ ﺑﺎﻳﺪ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻝ ﺩﺭ ﺣﻠﻖۀ forﻗﺒﻞ ﺍﺯ ﺣﻠﻘﻪ ﺍﻋﻼﻥ ﮔﺮﺩﺩ )ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﻛﻪ
ﺩﺍﺧﻞ ﺑﺨﺶ ﻛﻨﺘﺮﻟﻲ ﺁﻥ ﺍﻋﻼﻥ ﮔﺮﺩﺩ(؟
‐3ﺩﺳﺘﻮﺭ breakﭼﮕﻮﻧﻪ ﺑﺎﻋﺚ ﻛﻨﺘﺮﻝ ﺑﻬﺘﺮ ﺭﻭﻱ ﺣﻠﻘﻪﻫﺎ ﻣﻲﺷﻮﺩ؟
‐4ﺣﺪﺍﻗﻞ ﺗﻜﺮﺍﺭ ﺩﺭ:
ﺍﻟﻒ ‐ ﻳﻚ ﺣﻠﻖۀ whileﭼﻘﺪﺭ ﺍﺳﺖ؟
ﺏ ‐ ﻳﻚ ﺣﻠﻖۀ do..whileﭼﻘﺪﺭ ﺍﺳﺖ؟
‐5ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﺣﻠﻖۀ ﺯﻳﺮ ﺍﺳﺖ؟
)while (n <= 100
;sum += n*n
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﻗﻄﻌﻪ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺭﺍ ﺩﻧﺒﺎﻝ ﻧﻤﺎﻳﻴﺪ ﻭ ﻣﻘﺪﺍﺭ ﻫﺮ ﻣﺘﻐﻴﺮ ﺭﺍ ﺩﺭ ﻫﺮ ﮔﺎﻡ ﻣﺸﺨﺺ ﮐﻨﻴﺪ:
;float x = 4.15
)for (int i=0; i < 3; i++
;x *= 2
5‐1ﻣﻘﺪﻣﻪ
ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻭﺍﻗﻌﻲ ﻭ ﺗﺠﺎﺭﻱ ﺑﺴﻴﺎﺭ ﺑﺰﺭﮒﺗﺮ ﺍﺯ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﻫﺴﺘﻨﺪ ﮐﻪ ﺗﺎﮐﻨﻮﻥ ﺑﺮﺭﺳﻲ
ﮐﺮﺩﻳﻢ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺑﺰﺭﮒ ﻗﺎﺑﻞ ﻣﺪﻳﺮﻳﺖ ﺑﺎﺷﻨﺪ ،ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺭﺍ
ﺑﻪ ﺯﻳﺮﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﺑﺨﺶﺑﻨﺪﻱ ﻣﻲﮐﻨﻨﺪ .ﺍﻳﻦ ﺯﻳﺮﺑﺮﻧﺎﻣﻪﻫﺎ »ﺗﺎﺑﻊ« ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﻧﺪ .ﺗﻮﺍﺑﻊ ﺭﺍ
ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻃﻮﺭ ﺟﺪﺍﮔﺎﻧﻪ ﮐﺎﻣﭙﺎﻳﻞ ﻭ ﺁﺯﻣﺎﻳﺶ ﻧﻤﻮﺩ ﻭ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻣﺨﺘﻠﻒ ﺩﻭﺑﺎﺭﻩ ﺍﺯ ﺁﻥﻫﺎ
ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ .ﺍﻳﻦ ﺑﺨﺶﺑﻨﺪﻱ ﺩﺭ ﻣﻮﻓﻘﻴﺖ ﻳﮏ ﻧﺮﻡﺍﻓﺰﺍﺭ ﺷﻲﮔﺮﺍ ﺑﺴﻴﺎﺭ ﻣﻮﺛﺮ ﺍﺳﺖ.
> <ctimeﺗﻌﺮﻳﻒ ﺷﺪﻩ )ﻣﺜﺎﻝ .(4‐24ﺍﻭﻟﻴﻦ ﻣﺜﺎﻝ ﺍﻳﻦ ﺑﺨﺶ ،ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻳﻚ ﺗﺎﺑﻊ
ﺭﻳﺎﺿﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ،ﺭﻳﺶۀ ﺩﻭﻡ ﺍﻋﺪﺍﺩ ﺻﻔﺮ ﺗﺎ ﭘﻨﺞ ﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ .ﻫﺮ ﻭﻗﺖ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ
ﻋﺒﺎﺭﺕ ) sqrt(xﻣﻲﺭﺳﺪ ،ﺗﺎﺑﻊ )( sqrtﺍﺟﺮﺍ ﻣﻲﮔﺮﺩﺩ .ﮔﺮﭼﻪ ﮐﺪ ﺍﺻﻠﻲ ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ
ﺩﺭﻭﻥ ﮐﺘﺎﺑﺨﺎﻥۀ C++ﭘﻨﻬﺎﻥ ﺷﺪﻩ ﺍﻣﺎ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﻄﻤﺌﻦ ﺑﺎﺷﻴﻢ ﮐﻪ ﺑﻪ ﺟﺎﻱ ﻋﺒﺎﺭﺕ
) sqrt(xﻣﻘﺪﺍﺭ ﺟﺬﺭ xﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺑﻪ ﺩﺳﺘﻮﺭ > #include <cmathﺩﺭ ﺍﻭﻟﻴﻦ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 132
ﺧﻂ ﺑﺮﻧﺎﻣﻪ ﺗﻮﺟﻪ ﮐﻨﻴﺪ .ﮐﺎﻣﭙﺎﻳﻠﺮ ﺑﻪ ﺍﻳﻦ ﺧﻂ ﻧﻴﺎﺯ ﺩﺍﺭﺩ ﺗﺎ ﺑﺘﻮﺍﻧﺪ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ )( sqrtﺭﺍ
ﭘﻴﺪﺍ ﻛﻨﺪ .ﺍﻳﻦ ﺧﻂ ﺑﻪ ﻛﺎﻣﭙﺎﻳﻠﺮ ﻣﻲﮔﻮﻳﺪ ﻛﻪ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﺟﺬﺭ ﺩﺭ ﺳﺮﻓﺎﻳﻞ ><cmath
ﻭﺟﻮﺩ ﺩﺍﺭﺩ.
ﺑﺮﺍﻱ ﺍﺟﺮﺍﻱ ﻳﻚ ﺗﺎﺑﻊ ﻣﺎﻧﻨﺪ ﺗﺎﺑﻊ )( sqrtﮐﺎﻓﻲ ﺍﺳﺖ ﻧﺎﻡ ﺁﻥ ﺗﺎﺑﻊ ﺑﻪ ﺻﻮﺭﺕ ﻳﮏ
ﻣﺘﻐﻴﺮ ﺩﺭ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻣﻮﺭﺩ ﻧﻈﺮ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ ،ﻣﺎﻧﻨﺪ ﺯﻳﺮ:
y=sqrt(x).
1
ﺍﻳﻦ ﮐﺎﺭ »ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ « ﻳﺎ »ﺍﺣﻀﺎﺭ ﺗﺎﺑﻊ« ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻭﻗﺘﻲ ﻛﺪ )sqrt(x
ﺍﺟﺮﺍ ﺷﻮﺩ ،ﺗﺎﺑﻊ )( sqrtﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﮔﺮﺩﺩ .ﻋﺒﺎﺭﺕ xﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ »ﺁﺭﮔﻮﻣﺎﻥ «2ﻳﺎ
»ﭘﺎﺭﺍﻣﺘﺮ ﻭﺍﻗﻌﻲ« ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ .ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ ﻣﻲﮔﻮﻳﻴﻢ ﻛﻪ xﺗﻮﺳﻂ
»ﻣﻘﺪﺍﺭ« 3ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﻟﺬﺍ ﻭﻗﺘﻲ x=3ﺍﺳﺖ ،ﺑﺎ ﺍﺟﺮﺍﻱ ﮐﺪ ) sqrt(xﺗﺎﺑﻊ
)( sqrtﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﻭ ﻣﻘﺪﺍﺭ 3ﺑﻪ ﺁﻥ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﻧﻴﺰ ﺣﺎﺻﻞ
1.73205ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﭘﺎﺳﺦ
)(main
)(sqrt ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺍﻳﻦ ﻓﺮﺍﻳﻨﺪ ﺩﺭ ﻧﻤﻮﺩﺍﺭ
3
x 3
ﻣﻘﺎﺑﻞ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ .ﻣﺘﻐﻴﺮﻫﺎﻱ x
int
1.73205
y 1.73205 ﻭ yﺩﺭ ﺗﺎﺑﻊ )( mainﺗﻌﺮﻳﻒ
double
ﺷﺪﻩﺍﻧﺪ .ﻣﻘﺪﺍﺭ xﮐﻪ ﺑﺮﺍﺑﺮ ﺑﺎ 3
ﺍﺳﺖ ﺑﻪ ﺗﺎﺑﻊ )( sqrtﻓﺮﺳﺘﺎﺩﻩ
ﻣﻲﺷﻮﺩ ﻭ ﺍﻳﻦ ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ 1.73205ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ )( mainﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺟﻌﺒﻪﺍﻱ ﻛﻪ ﺗﺎﺑﻊ
)( sqrtﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﺑﻪ ﺭﻧﮓ ﺗﻴﺮﻩ ﺍﺳﺖ ،ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎ ﻛﻪ ﻓﺮﺍﻳﻨﺪ ﺩﺍﺧﻠﻲ ﻭ ﻧﺤﻮۀ ﮐﺎﺭ
ﺁﻥ ﻗﺎﺑﻞ ﺭﻭﻳﺖ ﻧﻴﺴﺖ.
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﻘﺪﺍﺭ xﺭﺍ ﺩﺭ ﺳﺘﻮﻥ ﺍﻭﻝ ،ﻣﻘﺪﺍﺭ Sin2xﺭﺍ ﺩﺭ ﺳﺘﻮﻥ ﺩﻭﻡ ﻭ ﻣﻘﺪﺍﺭ
2SinxCosxﺭﺍ ﺩﺭ ﺳﺘﻮﻥ ﺳﻮﻡ ﭼﺎﭖ ﻣﻲﻛﻨﺪ .ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺑﺮﺍﻱ ﻫﺮ
ﻣﻘﺪﺍﺭ ﺁﺯﻣﺎﻳﺸﻲ ،xﻣﻘﺪﺍﺭ Sin2xﺑﺎ ﻣﻘﺪﺍﺭ 2SinxCosxﺑﺮﺍﺑﺮ ﺍﺳﺖ .ﺍﻟﺒﺘﻪ ﺍﻳﻦ ﻧﺘﺎﻳﺞ ﺑﻪ
ﻃﻮﺭ ﮐﻠﻲ ﺍﺛﺒﺎﺕ ﻧﻤﻲﮐﻨﺪ ﮐﻪ ﺭﺍﺑﻂۀ ﻣﺬﮐﻮﺭ ﺻﺤﻴﺢ ﺍﺳﺖ ﺍﻣﺎ ﺑﻪ ﻃﻮﺭ ﺗﺠﺮﺑﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ
ﮐﻪ ﺍﻳﻦ ﺭﺍﺑﻄﻪ ﺩﺭﺳﺖ ﻣﻲﺑﺎﺷﺪ .ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ xﺍﺯ ﻧﻮﻉ floatﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ .ﺍﻳﻦ
ﺍﻣﺮ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ﮐﺪ x += 0.2ﺑﻪ ﺩﺭﺳﺘﻲ ﮐﺎﺭ ﮐﻨﺪ ﻭ ﺧﻄﺎﻱ ﮔﺮﺩﮐﺮﺩﻥ ﺭﺥ ﻧﺪﻫﺪ.
ﺣﺎﺻﻞ ﺗﺎﺑﻊ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﺎﻧﻨﺪ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻌﻤﻮﻟﻲ ﺩﺭ ﻫﺮ ﻋﺒﺎﺭﺗﻲ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ.
ﻳﻌﻨﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻨﻮﻳﺴﻴﻢ:
;)y = sqrt(2
;)cout << 2*sin(x)*cos(x
ﺷﺮﺡ ﺳﺮﻓﺎﻳﻞ
ﺗﺎﺑﻊ > <assertﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ><assert
ﺗﻮﺍﺑﻌﻲ ﺭﺍ ﺑﺮﺍﻱ ﺑﺮﺭﺳﻲ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ><ctype
ﺛﺎﺑﺖﻫﺎﻱ ﻣﺮﺑﻮﻁ ﺑﻪ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ><cfloat
ﻣﺤﺪﻭﺩۀ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺭﺍ ﺭﻭﻱ ﺳﻴﺴﺘﻢ ﻣﻮﺟﻮﺩ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ><climits
ﺗﻮﺍﺑﻊ ﺭﻳﺎﺿﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ><cmath
ﺗﻮﺍﺑﻌﻲ ﺭﺍ ﺑﺮﺍﻱ ﻭﺭﻭﺩﻱ ﻭ ﺧﺮﻭﺟﻲ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ><cstdio
ﺗﻮﺍﺑﻊ ﮐﺎﺭﺑﺮﺩﻱ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ><cstdlib
ﺗﻮﺍﺑﻌﻲ ﺭﺍ ﺑﺮﺍﻱ ﭘﺮﺩﺍﺯﺵ ﺭﺷﺘﻪﻫﺎ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ><cstring
ﺗﻮﺍﺑﻊ ﺗﺎﺭﻳﺦ ﻭ ﺳﺎﻋﺖ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ><ctime
ﺑﺨﻮﺍﻫﻴﻢ ﺗﺎﺑﻊ ﺍﻋﺪﺍﺩ ﺗﺼﺎﺩﻓﻲ )( randﺭﺍ ﺍﺯ ﺳﺮﻓﺎﻳﻞ > <cstdlibﺑﻪ ﻛﺎﺭ ﺑﺒﺮﻳﻢ ،ﺑﺎﻳﺪ
ﺩﺳﺘﻮﺭ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪۀ ﺯﻳﺮ ﺭﺍ ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﻓﺎﻳﻞ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ:
>#include <cstdlib
ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ )( cubeﮐﻪ ﺩﺭ ﺑﺎﻻ ﺗﻌﺮﻳﻒ ﺷﺪ int ،ﺍﺳﺖ .ﻧﺎﻡ ﺁﻥ cubeﻣﻲﺑﺎﺷﺪ
ﻭ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ intﺑﻪ ﻧﺎﻡ xﺩﺍﺭﺩ .ﻳﻌﻨﻲ ﺗﺎﺑﻊ )( cubeﻳﮏ ﻣﻘﺪﺍﺭ ﺍﺯ ﻧﻮﻉ int
ﻣﻲﮔﻴﺮﺩ ﻭ ﭘﺎﺳﺨﻲ ﺍﺯ ﻧﻮﻉ intﺗﺤﻮﻳﻞ ﻣﻲﺩﻫﺪ .ﭘﺲ ﻋﻨﻮﺍﻥ ﺗﺎﺑﻊ ﻓﻮﻕ ﻋﺒﺎﺭﺕ ﺍﺳﺖ ﺍﺯ:
)int cube(int x
ﺑﺪﻥۀ ﺗﺎﺑﻊ ،ﻳﻚ ﺑﻠﻮﻙ ﻛﺪ ﺍﺳﺖ ﻛﻪ ﺩﺭ ﺍﺩﺍﻡۀ ﻋﻨﻮﺍﻥ ﺁﻥ ﻣﻲﺁﻳﺪ .ﺑﺪﻧﻪ ﺷﺎﻣﻞ ﺩﺳﺘﻮﺭﺍﺗﻲ
ﺍﺳﺖ ﻛﻪ ﺑﺎﻳﺪ ﺍﻧﺠﺎﻡ ﺷﻮﺩ ﺗﺎ ﻧﺘﻴﺞۀ ﻣﻮﺭﺩ ﻧﻈﺮ ﺑﻪ ﺩﺳﺖ ﺁﻳﺪ .ﺑﺪﻧﻪ ﺷﺎﻣﻞ ﺩﺳﺘﻮﺭ return
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 136
ﺍﺳﺖ ﻛﻪ ﭘﺎﺳﺦ ﻧﻬﺎﻳﻲ ﺭﺍ ﺑﻪ ﻣﻜﺎﻥ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺑﺪﻥۀ ﺗﺎﺑﻊ cubeﻋﺒﺎﺭﺕ
ﺍﺳﺖ ﺍﺯ:
{ // returns cube of x:
;return x*x*x
}
ﺍﻳﻦ ﺗﻘﺮﻳﺒﺎ ﺳﺎﺩﻩﺗﺮﻳﻦ ﺑﺪﻧﻪﺍﻱ ﺍﺳﺖ ﻛﻪ ﻳﻚ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺗﻮﺍﺑﻊ ﻣﻔﻴﺪﺗﺮ
ﻣﻌﻤﻮﻻ ﺑﺪﻥۀ ﺑﺰﺭﮒﺗﺮﻱ ﺩﺍﺭﻧﺪ ﺍﻣﺎ ﻋﻨﻮﺍﻥ ﺗﺎﺑﻊ ﺍﻏﻠﺐ ﺭﻭﻱ ﻳﻚ ﺳﻄﺮ ﺟﺎ ﻣﻲﺷﻮﺩ.
ﺩﺳﺘﻮﺭ returnﺩﻭ ﻭﻇﻴﻒۀ ﻋﻤﺪﻩ ﺩﺍﺭﺩ .ﺍﻭﻝ ﺍﻳﻦ ﮐﻪ ﺍﺟﺮﺍﻱ ﺗﺎﺑﻊ ﺭﺍ ﺧﺎﺗﻤﻪ
ﻣﻲﺩﻫﺪ ﻭ ﺩﻭﻡ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﻧﻬﺎﻳﻲ ﺭﺍ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﻓﺮﺍﺧﻮﺍﻥ ﺑﺎﺯ ﻣﻲﮔﺮﺩﺍﻧﺪ .ﺩﺳﺘﻮﺭ return
ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ:
;return expression
5‐4ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ
ﻭﻗﺘﻲ ﻳﮏ ﺗﺎﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺍﻳﺠﺎﺩ ﮐﺮﺩﻳﺪ ،ﻓﻮﺭﺍ ﺑﺎﻳﺪ ﺁﻥ ﺗﺎﺑﻊ ﺭﺍ ﺑﺎ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﺳﺎﺩﻩ
ﺍﻣﺘﺤﺎﻥ ﮐﻨﻴﺪ .ﭼﻨﻴﻦ ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ 1ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ .ﺗﻨﻬﺎ ﻫﺪﻑ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ،ﺍﻣﺘﺤﺎﻥ
ﮐﺮﺩﻥ ﺗﺎﺑﻊ ﻭ ﺑﺮﺭﺳﻲ ﺻﺤﺖ ﮐﺎﺭ ﺁﻥ ﺍﺳﺖ .ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﻣﻮﻗﺘﻲ ﺍﺳﺖ ﮐﻪ ﺑﺎﻳﺪ
»ﺳﺮﻳﻊ ﻭ ﮐﺜﻴﻒ« ﺑﺎﺷﺪ؛ ﻳﻌﻨﻲ ﻻﺯﻡ ﻧﻴﺴﺖ ﺩﺭ ﺁﻥ ﺗﻤﺎﻡ ﻇﺮﺍﻓﺖﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ – ﻣﺜﻞ
ﭘﻴﻐﺎﻡﻫﺎﻱ ﺧﺮﻭﺟﻲ ،ﺑﺮﭼﺴﺐﻫﺎ ﻭ ﺭﺍﻫﻨﻤﺎﻫﺎﻱ ﺧﻮﺍﻧﺎ – ﺭﺍ ﻟﺤﺎﻅ ﮐﻨﻴﺪ .ﻭﻗﺘﻲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ،ﺗﺎﺑﻊ ﺭﺍ ﺁﺯﻣﺎﻳﺶ ﮐﺮﺩﻳﺪ ﺩﻳﮕﺮ ﺑﻪ ﺁﻥ ﺍﺣﺘﻴﺎﺟﻲ ﻧﻴﺴﺖ ﻭ ﻣﻲﺗﻮﺍﻧﻴﺪ ﺑﺮﻧﺎﻡۀ
ﺁﺯﻣﻮﻥ ﺭﺍ ﺩﻭﺭ ﺑﺮﻳﺰﻳﺪ.
)(int main
{ // tests the cube() function:
;int n=1
)while (n != 0
;{ cin >> n
;cout << "\tcube(" << n << ") = " << cube(n) << endl
}
}
5
cube(5) = 125
-6
cube(-6) = -216
0
cube(0) = 0
ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ ﻣﻲﮔﻴﺮﺩ ﻭ ﻣﻜﻌﺐ ﺁﻥﻫﺎ ﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ ﺗﺎ ﺍﻳﻦ ﻛﻪ
ﻛﺎﺭﺑﺮ ﻣﻘﺪﺍﺭ 0ﺭﺍ ﻭﺍﺭﺩ ﻛﻨﺪ .ﻫﺮ ﻋﺪﺩ ﺻﺤﻴﺤﻲ ﮐﻪ ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ ،ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﮐﺪ
) cube(nﺑﻪ ﺗﺎﺑﻊ )( cubeﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ ﺍﺯ ﺗﺎﺑﻊ ،ﺟﺎﻳﮕﺰﻳﻦ
ﻋﺒﺎﺭﺕ ) cube(nﮔﺸﺘﻪ ﻭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ coutﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ.
)( cubeﻣﻘﺪﺍﺭ 125ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ )( mainﺑﺎﺯﻣﻲﮔﺮﺩﺍﻧﺪ .ﺁﺭﮔﻮﻣﺎﻥ nﺑﻪ ﻭﺳﻴﻞۀ ﻣﻘﺪﺍﺭ
ﺑﻪ ﭘﺎﺭﺍﻣﺘﺮ ﺻﻮﺭﻱ xﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﺑﻪ ﺑﻴﺎﻥ ﺳﺎﺩﻩﺗﺮ ﻭﻗﺘﻲ ﺗﺎﺑﻊ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩx ،
ﻣﻘﺪﺍﺭ nﺭﺍ ﻣﻲﮔﻴﺮﺩ.
ﺩﻗﺖ ﻛﻨﻴﺪ ﻛﻪ ﺗﺎﺑﻊ )( cubeﺩﺭ ﺑﺎﻻﻱ ﺗﺎﺑﻊ )( mainﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺯﻳﺮﺍ ﻗﺒﻞ ﺍﺯ
ﺍﻳﻦ ﻛﻪ ﺗﺎﺑﻊ)( cubeﺩﺭ ﺗﺎﺑﻊ )( mainﺑﻪ ﻛﺎﺭ ﺭﻭﺩ ،ﻛﺎﻣﭙﺎﻳﻠﺮ C++ﺑﺎﻳﺪ ﺩﺭ ﺑﺎﺭۀ ﺁﻥ
ﺍﻃﻼﻉ ﺣﺎﺻﻞ ﻛﻨﺪ.
ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻳﻚ ﺗﺎﺑﻊ ﺳﺎﺧﺖ ﻛﺎﺭﺑﺮ ﺑﻪ ﻧﺎﻡ )( maxﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﺯ
ﺩﻭ ﻋﺪﺩ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺑﻪ ﺁﻥ ،ﻋﺪﺩ ﺑﺰﺭﮒﺗﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺍﺭﺩ.
)(int main
{ // tests the max() function:
;int m, n
do
;{ cin >> m >> n
" = )" << cout << "\tmax(" << m << "," << n
;<< max(m,n) << endl
}
;)while (m != 0
}
39
max(3,9) = 9
2 -2
139 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
max(2,-2) = 2
00
max(0,0) = 0
ﺗﺎﺑﻊ )( maxﻳﮏ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ﺑﻪ ﻧﺎﻡ zﺩﺍﺭﺩ ﮐﻪ ﻣﻘﺪﺍﺭ ﺑﺰﺭﮒﺗﺮ ﺩﺭ ﺁﻥ ﻧﮕﻬﺪﺍﺭﻱ ﺷﺪﻩ ﻭ
ﺳﭙﺲ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ returnﺑﻪ ﺗﺎﺑﻊ )( mainﻣﻲﮔﺮﺩﺩ.
ﺗﻮﺍﺑﻊ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﻴﺶ ﺍﺯ ﻳﮏ ﺩﺳﺘﻮﺭ returnﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ .ﻣﺜﻼ ﺗﺎﺑﻊ )( maxﺭﺍ
ﻣﺎﻧﻨﺪ ﺍﻳﻦ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﺴﺘﻴﻢ ﺑﻨﻮﻳﺴﻴﻢ:
)int max(int x, int y
{ // returns larger of the two given integers:
;if (x < y) return y
;else return x
}
ﺩﺭ ﺍﻳﻦ ﮐﺪ ﻫﺮ ﺩﺳﺘﻮﺭ returnﮐﻪ ﺯﻭﺩﺗﺮ ﺍﺟﺮﺍ ﺷﻮﺩ ﻣﻘﺪﺍﺭ ﻣﺮﺑﻮﻃﻪﺍﺵ ﺭﺍ ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ
ﻭ ﺗﺎﺑﻊ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ.
ﺩﺳﺘﻮﺭ returnﻧﻮﻋﻲ ﺩﺳﺘﻮﺭ ﭘﺮﺵ ﺍﺳﺖ )ﺷﺒﻴﻪ ﺩﺳﺘﻮﺭ ( breakﺯﻳﺮﺍ ﺍﺟﺮﺍ ﺭﺍ
ﺑﻪ ﺑﻴﺮﻭﻥ ﺍﺯ ﺗﺎﺑﻊ ﻫﺪﺍﻳﺖ ﻣﻲﮐﻨﺪ .ﺍﮔﺮﭼﻪ ﻣﻌﻤﻮﻻ returnﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺗﺎﺑﻊ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ،
ﻣﻲﺗﻮﺍﻥ ﺁﻥ ﺭﺍ ﺩﺭ ﻫﺮ ﻧﻘﻂۀ ﺩﻳﮕﺮﻱ ﺍﺯ ﺗﺎﺑﻊ ﻗﺮﺍﺭ ﺩﺍﺩ.
ﮐﻪ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﺷﻮﺩ ﺑﺎﻳﺪ ﺍﻋﻼﻥ ﺷﻮﺩ .ﺗﺎﺑﻊ ﻫﻢ ﻫﻤﻴﻦ ﻃﻮﺭ ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﻓﺮﻕ ﮐﻪ ﻣﺘﻐﻴﺮ ﺭﺍ
ﺩﺭ ﻫﺮ ﺟﺎﻳﻲ ﺍﺯ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺗﻮﺍﻥ ﺍﻋﻼﻥ ﮐﺮﺩ ﺍﻣﺎ ﺗﺎﺑﻊ ﺭﺍ ﺑﺎﻳﺪ ﻗﺒﻞ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﻋﻼﻥ ﻧﻤﻮﺩ.
ﺩﺭ ﺍﻋﻼﻥ ﺗﺎﺑﻊ ﻓﻘﻂ ﺑﻴﺎﻥ ﻣﻲﺷﻮﺩ ﮐﻪ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ ﭼﻴﺴﺖ ،ﻧﺎﻡ ﺗﺎﺑﻊ ﭼﻴﺴﺖ ﻭ ﻧﻮﻉ
ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﭼﻴﺴﺖ .ﻫﻤﻴﻦﻫﺎ ﺑﺮﺍﻱ ﮐﺎﻣﭙﺎﻳﻠﺮ ﮐﺎﻓﻲ ﺍﺳﺖ ﺗﺎ ﺑﺘﻮﺍﻧﺪ ﮐﺎﻣﭙﺎﻳﻞ ﺑﺮﻧﺎﻣﻪ ﺭﺍ
ﺁﻏﺎﺯ ﮐﻨﺪ .ﺑﻌﺪﺍ ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺑﻪ ﺗﻌﺮﻳﻒ ﺑﺪﻥۀ ﺗﺎﺑﻊ ﻧﻴﺰ ﺍﺣﺘﻴﺎﺝ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻳﻦ ﺑﺪﻧﻪ ﺩﺭ
ﺍﻧﺘﻬﺎﻱ ﺑﺮﻧﺎﻣﻪ ﻭ ﭘﺲ ﺍﺯ ﺗﺎﺑﻊ )( mainﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ.
ﺍﮐﻨﻮﻥ ﺑﺎﻳﺪ ﻓﺮﻕ ﺑﻴﻦ »ﺁﺭﮔﻮﻣﺎﻥ «1ﻭ »ﭘﺎﺭﺍﻣﺘﺮ «2ﺭﺍ ﺑﺪﺍﻧﻴﻢ .ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﻫﺴﺘﻨﺪ
ﮐﻪ ﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮ ﻳﮏ ﺗﺎﺑﻊ ﻧﺎﻡ ﺑﺮﺩﻩ ﻣﻲﺷﻮﻧﺪ .ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻠﻲ xﻭ yﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ
)( maxﻫﺴﺘﻨﺪ .ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ ﺑﺮﺍﻱ ﺗﺎﺑﻊ ﻣﺤﺴﻮﺏ ﻣﻲﺷﻮﻧﺪ؛ ﻳﻌﻨﻲ ﻓﻘﻂ ﺩﺭ
ﻃﻮﻝ ﺍﺟﺮﺍﻱ ﺗﺎﺑﻊ ﻭﺟﻮﺩ ﺩﺍﺭﻧﺪ .ﺁﺭﮔﻮﻣﺎﻥﻫﺎ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﻫﺴﺘﻨﺪ ﮐﻪ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﻪ ﺗﺎﺑﻊ
ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ .ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻠﻲ mﻭ nﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﺗﺎﺑﻊ )( maxﻫﺴﺘﻨﺪ .ﻭﻗﺘﻲ ﻳﮏ
ﺗﺎﺑﻊ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ،ﻣﻘﺪﺍﺭ ﺁﺭﮔﻮﻣﺎﻥﻫﺎ ﺩﺭﻭﻥ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﺗﺎ ﺗﺎﺑﻊ
ﭘﺮﺩﺍﺯﺵ ﺭﺍ ﺷﺮﻭﻉ ﮐﻨﺪ .ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﻣﻲﮔﻮﻳﻴﻢ ﮐﻪ ﺁﺭﮔﻮﻣﺎﻥﻫﺎ »ﺑﻪ ﺭﻭﺵ ﻣﻘﺪﺍﺭ« ﺍﺭﺳﺎﻝ
ﺷﺪﻩ ﺍﻧﺪ .ﻳﻌﻨﻲ ﻣﻘﺪﺍﺭ ﺁﺭﮔﻮﻣﺎﻥﻫﺎ ﺟﺎﻳﮕﺰﻳﻦ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﻣﺘﻨﺎﻇﺮﺷﺎﻥ ﻣﻲﺷﻮﻧﺪ .ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ
ﻭﻗﺘﻲ ﺗﺎﺑﻊ )( maxﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ،ﻣﻘﺪﺍﺭ ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ mﻭ nﺑﻪ ﺗﺮﺗﻴﺐ ﺟﺎﻳﮕﺰﻳﻦ
ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ xﻭ yﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﺗﺎﺑﻊ ﮐﺎﺭﺵ ﺭﺍ ﺷﺮﻭﻉ ﻣﻲﮐﻨﺪ .ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺟﺎﻱ
ﺁﺭﮔﻮﻣﺎﻥﻫﺎ ،ﻳﮏ ﻣﻘﺪﺍﺭ ﺛﺎﺑﺖ ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩ )ﻣﺜﻞ ) (max(22,44ﻳﺎ ﻣﻲﺗﻮﺍﻥ ﻳﮏ
ﻋﺒﺎﺕ ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩ )ﻣﺜﻞ ) max(2*m, 3-nﮐﻪ ﻣﻘﺪﺍﺭ 2*mﺩﺭ xﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ
ﻭ ﻣﻘﺪﺍﺭ 3-nﺩﺭ yﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ(.
)(int main
ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ xﻭ yﺩﺭ ﺑﺨﺶ ﻋﻨﻮﺍﻥ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﺁﻣﺪﻩﺍﻧﺪ )ﻃﺒﻖ ﻣﻌﻤﻮﻝ(
ﻭﻟﻲ ﺩﺭ ﺍﻋﻼﻥ ﺗﺎﺑﻊ ﻭﺟﻮﺩ ﻧﺪﺍﺭﻧﺪ.
ﺩﺍﺩﻩ ﮐﻪ ﭘﻨﻬﺎﻥﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ ،ﻓﻬﻤﻴﺪﻥ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺭﺍ ﺁﺳﺎﻥ ﻣﻲﮐﻨﺪ ﻭ ﭘﺮﻭﮊﻩﻫﺎﻱ ﺑﺰﺭﮒ
ﺑﺎ ﻣﻮﻓﻘﻴﺖ ﺍﺟﺮﺍ ﻣﻲﺷﻮﻧﺪ.
ﻣﺰﻳﺖ ﺩﻳﮕﺮ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺗﻮﺍﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ
ﻧﻮﺷﺘﻪ ﺷﻮﺩ ،ﺟﺪﺍﮔﺎﻧﻪ ﺁﺯﻣﺎﻳﺶ ﻧﻤﻮﺩ .ﻭﻗﺘﻲ ﻳﻘﻴﻦ ﮐﺮﺩﻳﺪ ﮐﻪ ﻳﮏ ﺗﺎﺑﻊ ﻣﻔﺮﻭﺽ ﺑﻪ ﺩﺭﺳﺘﻲ
ﮐﺎﺭ ﻣﻲﮐﻨﺪ ،ﺁﻥ ﺭﺍ ﺩﺭ ﻳﮏ ﻓﺎﻳﻞ ﺫﺧﻴﺮﻩ ﮐﻨﻴﺪ ﻭ ﺟﺰﻳﻴﺎﺕ ﺁﻥ ﺗﺎﺑﻊ ﺭﺍ ﻓﺮﺍﻣﻮﺵ ﮐﻨﻴﺪ ﻭ ﻫﺮ
ﻭﻗﺖ ﮐﻪ ﺑﻪ ﺁﻥ ﺗﺎﺑﻊ ﻧﻴﺎﺯ ﺩﺍﺷﺘﻴﺪ ﺑﺎ ﺧﻴﺎﻟﻲ ﺭﺍﺣﺖ ﺍﺯ ﺁﻥ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺘﺎﻥ ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﺎﻳﻴﺪ.
ﻧﺘﻴﺠﻪ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺗﻮﻟﻴﺪ ﺗﻮﺍﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﻭ ﺗﻮﻟﻴﺪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ،ﻫﻢﺯﻣﺎﻥ ﻭ ﻣﺴﺘﻘﻞ ﺍﺯ ﻫﻢ
ﭘﻴﺶ ﻣﻲﺭﻭﺩ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﻳﮑﻲ ﻣﻨﺘﻈﺮ ﺩﻳﮕﺮﻱ ﺑﻤﺎﻧﺪ .ﺑﻪ ﺍﻳﻦ ﺩﻳﺪﮔﺎﻩ »ﺑﺴﺘﻪﺑﻨﺪﻱ ﻧﺮﻡﺍﻓﺰﺍﺭ«
ﻣﻲﮔﻮﻳﻨﺪ.
ﺳﻮﻣﻴﻦ ﻣﺰﻳﺖ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﻫﺮ ﺯﻣﺎﻧﻲ ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻥ ﺗﻌﺮﻳﻒ ﺗﻮﺍﺑﻊ ﺭﺍ
ﻋﻮﺽ ﮐﺮﺩ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﻻﺯﻡ ﺑﺎﺷﺪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺗﻐﻴﻴﺮ ﻳﺎﺑﺪ .ﻓﺮﺽ ﮐﻨﻴﺪ ﺗﺎﺑﻌﻲ ﺑﺮﺍﻱ
ﻣﺮﺗﺐ ﮐﺮﺩﻥ ﻓﻬﺮﺳﺘﻲ ﺍﺯ ﺍﻋﺪﺍﺩ ﺍﻳﺠﺎﺩ ﮐﺮﺩﻩﺍﻳﺪ ﻭ ﺁﻥ ﺭﺍ ﺟﺪﺍﮔﺎﻧﻪ ﮐﺎﻣﭙﺎﻳﻞ ﻭ ﺫﺧﻴﺮﻩ ﻧﻤﻮﺩﻩﺍﻳﺪ
ﻭ ﺩﺭ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﮐﺎﺭﺑﺮﺩﻱ ﻫﻢ ﺍﺯ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺑﺮﺩﻩﺍﻳﺪ .ﺣﺎﻻ ﻫﺮﮔﺎﻩ ﮐﻪ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺳﺮﻳﻊﺗﺮﻱ
ﺑﺮﺍﻱ ﻣﺮﺗﺐﺳﺎﺯﻱ ﻳﺎﻓﺘﻴﺪ ،ﻓﻘﻂ ﮐﺎﻓﻲ ﺍﺳﺖ ﻓﺎﻳﻞ ﺗﺎﺑﻊ ﺭﺍ ﺍﺻﻼﺡ ﻭ ﮐﺎﻣﭙﺎﻳﻞ ﮐﻨﻴﺪ ﻭ ﺩﻳﮕﺮ
ﻧﻴﺎﺯﻱ ﻧﻴﺴﺖ ﮐﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﻧﻤﺎﻳﻴﺪ.
ﭼﻬﺎﺭﻣﻴﻦ ﻣﺰﻳﺖ ﻫﻢ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻣﻲﺗﻮﺍﻧﻴﺪ ﻳﮏ ﺑﺎﺭ ﻳﮏ ﺗﺎﺑﻊ ﺭﺍ ﮐﺎﻣﭙﺎﻳﻞ ﻭ ﺫﺧﻴﺮﻩ
ﮐﻨﻴﺪ ﻭ ﺍﺯ ﺁﻥ ﭘﺲ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻣﺨﺘﻠﻔﻲ ﺍﺯ ﻫﻤﺎﻥ ﺗﺎﺑﻊ ﺍﺳﺘﻔﺎﺩﻩ ﺑﺒﺮﻳﺪ .ﻭﻗﺘﻲ ﺷﺮﻭﻉ ﺑﻪ
ﻧﻮﺷﺘﻦ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﺟﺪﻳﺪ ﻣﻲﮐﻨﻴﺪ ،ﺷﺎﻳﺪ ﺑﺮﺧﻲ ﺍﺯ ﺗﻮﺍﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺍﺯ ﻗﺒﻞ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ.
ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﻳﮕﺮ ﻻﺯﻡ ﻧﻴﺴﺖ ﮐﻪ ﺁﻥ ﺗﻮﺍﺑﻊ ﺭﺍ ﺩﻭﺑﺎﺭﻩ ﻧﻮﺷﺘﻪ ﻭ ﮐﺎﻣﭙﺎﻳﻞ ﮐﻨﻴﺪ .ﺍﻳﻦ ﮐﺎﺭ ﺳﺮﻋﺖ
ﺗﻮﻟﻴﺪ ﻧﺮﻡ ﺍﻓﺰﺍﺭ ﺭﺍ ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ.
ﺗﺎﺑﻊ )( maxﺭﺍ ﺑﻪ ﺧﺎﻃﺮ ﺑﻴﺎﻭﺭﻳﺪ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﺩﺭ ﻓﺎﻳﻞ ﺟﺪﺍﮔﺎﻧﻪﺍﻱ
max.cpp ﻗﺮﺍﺭ ﺩﻫﻴﻢ ،ﺗﻌﺮﻳﻒ ﺁﻥ ﺭﺍ ﺩﺭ
ﻓﺎﻳﻠﻲ ﺑﻪ ﻧﺎﻡ max.cpp
)int max(int x, int y
;{ if (x < y) return y ﻓﺎﻳﻞ ﻣﻲﮐﻨﻴﻢ. ﺫﺧﻴﺮﻩ
;else return x max.cppﺷﺎﻣﻞ ﮐﺪ ﻣﻘﺎﺑﻞ
}
ﺍﺳﺖ:
143 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
ﺣﺎﻻ ﺳﺮﺍﻍ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﻣﻲﺭﻭﻳﻢ .ﻣﺘﻦ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺭﺍ ﺩﺭ ﻓﺎﻳﻠﻲ ﺑﻪ ﻧﺎﻡ test.cpp
ﺫﺧﻴﺮﻩ ﻣﻲﻧﻤﺎﻳﻴﻢ .ﺍﻳﻦ ﻓﺎﻳﻞ ﺷﺎﻣﻞ ﮐﺪ ﺯﻳﺮ ﺍﺳﺖ:
test.cpp
;)int max(int,int
// returns larger of the two given integers:
)(int main
{ // tests the max() function:
;int m, n
do
;{ cin >> m >> n
" = )" << cout << "\tmax(" << m << "," << n
;<< max(m,n) << endl
}
;)while (m != 0
}
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ،ﺗﺎﺑﻊ )( maxﻓﻘﻂ ﺍﻋﻼﻥ ﺷﺪﻩ ﺍﺳﺖ .ﺩﺭ ﺍﻭﻟﻴﻦ ﺧﻂ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ
ﺍﻋﻼﻥ ﺷﺪﻩ ﮐﻪ ﺗﺎﺑﻊ )( maxﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ intﺩﺍﺭﺩ ﻭ ﻳﮏ ﻣﻘﺪﺍﺭ ﺍﺯ ﻧﻮﻉ int
ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
ﻧﺤﻮۀ ﮐﺎﻣﭙﺎﻳﻞ ﮐﺮﺩﻥ ﻓﺎﻳﻞﻫﺎ ﻭ ﺍﻟﺼﺎﻕ ﺁﻥﻫﺎ ﺑﻪ ﻳﮑﺪﻳﮕﺮ ﺑﻪ ﻧﻮﻉ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﻭ ﻧﻮﻉ
ﮐﺎﻣﭙﺎﻳﻠﺮ ﺑﺴﺘﮕﻲ ﺩﺍﺭﺩ .ﺩﺭ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﻭﻳﻨﺪﻭﺯ ﻣﻌﻤﻮﻻ ﺗﻮﺍﺑﻊ ﺭﺍ ﺩﺭ ﻓﺎﻳﻞﻫﺎﻳﻲ ﺍﺯ ﻧﻮﻉ
DLL1ﮐﺎﻣﭙﺎﻳﻞ ﻭ ﺫﺧﻴﺮﻩ ﻣﻲﮐﻨﻨﺪ ﻭ ﺳﭙﺲ ﺍﻳﻦ ﻓﺎﻳﻞ ﺭﺍ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﺣﻀﺎﺭ ﻣﻲﻧﻤﺎﻳﻨﺪ.
ﻓﺎﻳﻞﻫﺎﻱ DLLﺭﺍ ﺑﻪ ﺩﻭ ﻃﺮﻳﻖ ﺍﻳﺴﺘﺎ ﻭ ﭘﻮﻳﺎ ﻣﻲﺗﻮﺍﻥ ﻣﻮﺭﺩ ﺍﺳﺘﻔﺎﺩﻩ ﻗﺮﺍﺭ ﺩﺍﺩ .ﺑﺮﺍﻱ ﺁﺷﻨﺎﻳﻲ
ﺑﻴﺸﺘﺮ ﺑﺎ ﻓﺎﻳﻞﻫﺎﻱ DLLﺑﻪ ﻣﺮﺟﻊ ﻭﻳﻨﺪﻭﺯ ﻭ ﮐﺎﻣﭙﺎﻳﻠﺮﻫﺎﻱ c++ﻣﺮﺍﺟﻌﻪ ﮐﻨﻴﺪ.
ﺑﺮﺍﻱ ﺁﻥ ﺗﺎﺑﻊ ﻫﺴﺘﻨﺪ .ﺍﻳﻦ ﻣﺘﻐﻴﺮﻫﺎ ﻓﻘﻂ ﺗﺎ ﻭﻗﺘﻲ ﮐﻪ ﺗﺎﺑﻊ ﺩﺭ ﺣﺎﻝ ﮐﺎﺭ ﺍﺳﺖ ﻭﺟﻮﺩ ﺩﺍﺭﻧﺪ.
ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﻧﻴﺰ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ ﻣﺤﺴﻮﺏ ﻣﻲﺷﻮﻧﺪ.
ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﻭ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ﺩﺍﺭﺩ n :ﻭ .fﭘﺎﺭﺍﻣﺘﺮ nﻳﮏ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ﺍﺳﺖ ﺯﻳﺮﺍ ﺩﺭ ﻓﻬﺮﺳﺖ
ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﺍﻋﻼﻥ ﺷﺪﻩ .ﻣﺘﻐﻴﺮ fﻧﻴﺰ ﻣﺤﻠﻲ ﺍﺳﺖ ﺯﻳﺮﺍ ﺩﺭﻭﻥ ﺑﺪﻥۀ ﺗﺎﺑﻊ ﺍﻋﻼﻥ ﺷﺪﻩ.
ﺗﺎﺑﻊ ﻓﺎﮐﺘﻮﺭﻳﻞ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺯﻳﺮ ﻣﻲﺗﻮﺍﻥ ﺁﺯﻣﺎﻳﺶ ﮐﺮﺩ:
;)long fact(int
)// returns n! = n*(n-1)*(n-2)*...*(2)*(1
)(int main
{ // tests the factorial() function:
)for (int i=-1; i < 6; i++
;)cout << " " << fact(i
;cout << endl
}
0 1 1 2 6 24 120
ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻗﺎﺑﻞ ﺍﺟﺮﺍ ﺑﺎﺷﺪ ،ﻳﺎ ﺑﺎﻳﺪ ﻓﺎﻳﻞ ﺗﺎﺑﻊ ﻓﺎﮐﺘﻮﺭﻳﻞ ﺭﺍ ﺑﻪ ﺁﻥ ﺍﻟﺼﺎﻕ ﮐﻨﻴﻢ
ﻭ ﻳﺎ ﺍﻳﻦ ﮐﻪ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﻓﺎﮐﺘﻮﺭﻳﻞ ﺭﺍ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ﺁﻥ ﺍﺿﺎﻓﻪ ﻧﻤﺎﻳﻴﻢ.
145 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
ﻫﻤﺎﻥ ﮔﻮﻧﻪ ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻣﺤﻠﻲ ﺑﺎﺷﻨﺪ ،ﺗﻮﺍﺑﻊ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻣﺤﻠﻲ ﺑﺎﺷﻨﺪ.
ﻳﮏ ﺗﺎﺑﻊ ﻣﺤﻠﻲ 1ﺗﺎﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ﺩﺭﻭﻥ ﻳﮏ ﺗﺎﺑﻊ ﺩﻳﮕﺮ ﺑﻪ ﮐﺎﺭ ﺭﻭﺩ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﭼﻨﺪ ﺗﺎﺑﻊ
ﺳﺎﺩﻩ ﻭ ﺗﺮﮐﻴﺐ ﺁﻥﻫﺎ ﻣﻲﺗﻮﺍﻥ ﺗﻮﺍﺑﻊ ﭘﻴﭽﻴﺪﻩﺗﺮﻱ ﺳﺎﺧﺖ .ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ.
ﺍﻳﻦ ﺗﺎﺑﻊ ،ﺧﻮﺩ ﺍﺯ ﺗﺎﺑﻊ ﺩﻳﮕﺮﻱ ﮐﻪ ﻫﻤﺎﻥ ﺗﺎﺑﻊ ﻓﺎﮐﺘﻮﺭﻳﻞ ﺍﺳﺖ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩ .ﺷﺮﻁ ﺑﻪ ﮐﺎﺭ
ﺭﻓﺘﻪ ﺩﺭ ﺩﺳﺘﻮﺭ ifﺑﺮﺍﻱ ﻣﺤﺪﻭﺩ ﮐﺮﺩﻥ ﺣﺎﻟﺖﻫﺎﻱ ﻏﻴﺮ ﻣﻤﮑﻦ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ .ﺩﺭ ﺍﻳﻦ
ﺣﺎﻟﺖﻫﺎ ،ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ 0ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﺗﺎ ﻧﺸﺎﻥ ﺩﻫﺪ ﮐﻪ ﻳﮏ ﻭﺭﻭﺩﻱ ﺍﺷﺘﺒﺎﻩ ﻭﺟﻮﺩ ﺩﺍﺷﺘﻪ
ﺍﺳﺖ .ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺑﺮﺍﻱ ﺗﺎﺑﻊ )( permﺩﺭ ﺍﺩﺍﻣﻪ ﺁﻣﺪﻩ ﺍﺳﺖ:
long perm(int,int);
// returns P(n,k), the number of permutations of k from n:
int main()
{ // tests the perm() function:
for (int i = -1; i < 8; i++)
{ for (int j= -1; j <= i+1; j++)
cout << " " << perm(i,j);
cout << endl;
}
}
0 0
0 1 0
0 1 1 0
0 1 2 20
0 1 3 660
0 1 4 12 24 24 0
0 1 5 20 60 120 120 0
0 1 6 30 120 360 720 720 0
0 1 7 42 210 840 2520 5040 5040 0
void ﺗﺎﺑﻊ5‐7
int main()
{ // tests the PrintDate() function:
int day, month, year;
do
147 ﺗﻮاﺑﻊ/ ﻓﺼﻞ ﭘﻨﺠﻢ
ﺗﺎﺑﻊ )( PrintDateﻫﻴﭻ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺑﺮﻧﻤﻲﮔﺮﺩﺍﻧﺪ .ﺗﻨﻬﺎ ﻫﺪﻑ ﺍﻳﻦ ﺗﺎﺑﻊ ،ﭼﺎﭖ ﺗﺎﺭﻳﺦ
ﺍﺳﺖ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺁﻥ voidﺍﺳﺖ .ﺍﮔﺮ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﺧﺎﺭﺝ ﺍﺯ ﻣﺤﺪﻭﺩﻩ ﺑﺎﺷﻨﺪ،
ﺗﺎﺑﻊ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﮐﻨﺪ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ .ﺑﺎ ﺍﻳﻦ ﻭﺟﻮﺩ ﺑﺎﺯ ﻫﻢ ﺍﺣﺘﻤﺎﻝ ﺩﺍﺭﺩ
ﻣﻘﺎﺩﻳﺮ ﻏﻴﺮﻣﻤﮑﻨﻲ ﻣﺎﻧﻨﺪ 31 Esfand 1384ﭼﺎﭖ ﺷﻮﻧﺪ .ﺍﺻﻼﺡ ﺍﻳﻦ ﻧﺎﻫﻨﺠﺎﺭﻱ ﺭﺍ
ﺑﻪ ﻋﻨﻮﺍﻥ ﺗﻤﺮﻳﻦ ﺑﻪ ﺩﺍﻧﺸﺠﻮ ﻭﺍ ﻣﻲﮔﺬﺍﺭﻳﻢ.
ﺍﺯ ﺁﻥﺟﺎ ﻛﻪ ﻳﻚ ﺗﺎﺑﻊ voidﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺑﺮﻧﻤﻲﮔﺮﺩﺍﻧﺪ ،ﻧﻴﺎﺯﻱ ﺑﻪ ﺩﺳﺘﻮﺭ return
ﻧﻴﺴﺖ ﻭﻟﻲ ﺍﮔﺮ ﻗﺮﺍﺭ ﺑﺎﺷﺪ ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺭﺍ ﺩﺭ ﺗﺎﺑﻊ voidﻗﺮﺍﺭ ﺩﻫﻴﻢ ،ﺑﺎﻳﺪ ﺁﻥ ﺭﺍ ﺑﻪ ﺷﮑﻞ
ﺗﻨﻬﺎ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﺑﻌﺪ ﺍﺯ ﮐﻠﻢۀ returnﻫﻴﭻ ﭼﻴﺰ ﺩﻳﮕﺮﻱ ﺑﻴﺎﻳﺪ:
;return
5‐8ﺗﻮﺍﺑﻊ ﺑﻮﻟﻲ
ﺩﺭ ﺑﺴﻴﺎﺭﻱ ﺍﺯ ﺍﻭﻗﺎﺕ ﻻﺯﻡ ﺍﺳﺖ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ،ﺷﺮﻃﻲ ﺑﺮﺭﺳﻲ ﺷﻮﺩ .ﺍﮔﺮ ﺑﺮﺭﺳﻲ ﺍﻳﻦ
ﺷﺮﻁ ﺑﻪ ﺩﺳﺘﻮﺭﺍﺕ ﺯﻳﺎﺩﻱ ﻧﻴﺎﺯ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ،ﺑﻬﺘﺮ ﺍﺳﺖ ﮐﻪ ﻳﮏ ﺗﺎﺑﻊ ﺍﻳﻦ ﺑﺮﺭﺳﻲ ﺭﺍ ﺍﻧﺠﺎﻡ
ﺩﻫﺪ .ﺍﻳﻦ ﮐﺎﺭ ﻣﺨﺼﻮﺻﺎ ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺍﺯ ﺣﻠﻘﻪﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﺑﺴﻴﺎﺭ ﻣﻔﻴﺪ ﺍﺳﺖ .ﺗﻮﺍﺑﻊ
ﺑﻮﻟﻲ ﻓﻘﻂ ﺩﻭ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﻨﺪ true :ﻳﺎ . false
ﺗﺎﺑﻊ ﻓﻮﻕ ﺑﺮﺍﻱ ﻋﺪﺩ nﺑﻪ ﺩﻧﺒﺎﻝ ﻳﮏ ﻣﻘﺴﻮﻡﻋﻠﻴﻪ ﻣﻲﮔﺮﺩﺩ .ﺍﮔﺮ ﭘﻴﺪﺍ ﺷﺪ ﻣﻘﺪﺍﺭ falseﺭﺍ
ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻳﻌﻨﻲ nﺍﻭﻝ ﻧﻴﺴﺖ .ﺍﮔﺮ ﻫﻴﭻ ﻣﻘﺴﻮﻡﻋﻠﻴﻬﻲ ﻳﺎﻓﺖ ﻧﺸﺪ ﻣﻘﺪﺍﺭ trueﺭﺍ
ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﮐﻪ ﻳﻌﻨﻲ nﺍﻭﻝ ﺍﺳﺖ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺮﺍﻱ ﻳﺎﻓﺘﻦ ﻣﻘﺴﻮﻡﻋﻠﻴﻪ ﻓﺮﺽﻫﺎﻱ ﺯﻳﺮ ﺭﺍ ﺩﺭ
ﻧﻈﺮ ﻣﻲﮔﻴﺮﺩ – 1 :ﺍﻋﺪﺍﺩ ﮐﻮﭼﮏﺗﺮ ﺍﺯ ﺩﻭ ﺍﻭﻝ ﻧﻴﺴﺘﻨﺪ ‐2 .ﻋﺪﺩ ﺩﻭ ﺍﻭﻝ ﺍﺳﺖ – 3 .ﻫﺮ
ﻋﺪﺩ ﺯﻭﺝ ﻏﻴﺮ ﺍﺯ ﺩﻭ ﺍﻭﻝ ﻧﻴﺴﺖ – 4 .ﺣﺪﺍﻗﻞ ﻳﮑﻲ ﺍﺯ ﻣﻘﺴﻮﻡﻋﻠﻴﻪﻫﺎﻱ ﻋﺪﺩ ﺍﺯ ﺟﺬﺭ ﺁﻥ
ﻋﺪﺩ ﮐﻮﭼﮏﺗﺮ ﺍﺳﺖ .ﺍﻳﻦ ﻓﺮﺽﻫﺎ ﻳﮑﻲ ﻳﮑﻲ ﺑﺮﺭﺳﻲ ﻣﻲﺷﻮﻧﺪ .ﺍﮔﺮ nﺍﺯ ﺩﻭ ﮐﻮﭼﮏﺗﺮ
ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ falseﺑﺮﻣﻲﮔﺮﺩﺩ .ﺍﮔﺮ nﺑﺮﺍﺑﺮ ﺑﺎ 2ﻳﺎ 3ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ trueﺑﺮﻣﻲﮔﺮﺩﺩ
ﻳﻌﻨﻲ nﺍﻭﻝ ﺍﺳﺖ .ﺩﺭ ﻏﻴﺮ ﺍﻳﻦ ﺻﻮﺭﺕ ﺍﮔﺮ nﺯﻭﺝ ﺑﺎﺷﺪ ﺑﺎﺯ ﻫﻢ falseﺑﺮﻣﻲﮔﺮﺩﺩ ﺯﻳﺮﺍ
ﻫﻴﭻ ﻋﺪﺩ ﺯﻭﺟﻲ ﻏﻴﺮ ﺍﺯ ﺩﻭ ﺍﻭﻝ ﻧﻴﺴﺖ .ﺍﮔﺮ nﺯﻭﺝ ﻫﻢ ﻧﺒﻮﺩ ﺁﻧﮕﺎﻩ ﺣﻠﻖۀ forﺷﺮﻭﻉ
ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﺍﻳﻦ ﺣﻠﻘﻪ ﺑﺮﺭﺳﻲ ﻣﻲﺷﻮﺩ ﮐﻪ ﺁﻳﺎ ﻋﺪﺩﻱ ﻫﺴﺖ ﮐﻪ ﺍﺯ ﺟﺬﺭ nﮐﻮﭼﮏﺗﺮ
ﺑﻮﺩﻩ ﻭ ﻣﻘﺴﻮﻡﻋﻠﻴﻪ nﺑﺎﺷﺪ ﻳﺎ ﺧﻴﺮ .ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺩﺭ ﺣﻠﻖۀ forﻓﻘﻂ ﮐﺎﻓﻲ ﺍﺳﺖ ﺍﻋﺪﺍﺩ
ﻓﺮﺩ ﮐﻮﭼﮏﺗﺮ ﺍﺯ ﺟﺬﺭ nﺭﺍ ﺑﺮﺭﺳﻲ ﮐﻨﻴﻢ )ﭼﺮﺍ؟(
ﻳﻚ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﻭ ﺧﺮﻭﺟﻲ ﺁﻥ ﺩﺭ ﺍﺩﺍﻣﻪ ﺁﻣﺪﻩ ﺍﺳﺖ:
>#include <cmath // defines the sqrt() function
>#include <iostream // defines the cout object
;using namespace std
;)bool isPrime(int
;// returns true if n is prime, false otherwise
)(int main
){ for (int n=0; n < 80; n++
;" " << if (isPrime(n)) cout << n
;cout << endl
}
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 150
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79
ﺑﻬﺘﺮ ﺍﺳﺖ ﺑﺪﺍﻧﻴﺪ ﮐﻪ ﺍﻳﻦ ﺗﺎﺑﻊ ،ﺑﻬﻴﻨﻪ ﻧﻴﺴﺖ .ﻫﺮ ﻋﺪﺩ ﻣﺮﮐﺐ)ﻏﻴﺮ ﺍﻭﻝ( ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ
ﺻﻮﺭﺕ ﺿﺮﺏ ﻳﮏ ﻋﺪﺩ ﺍﻭﻝ ﺩﺭ ﻋﺪﺩ ﺩﻳﮕﺮﻱ ﻧﻮﺷﺖ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺑﺮﺍﻱ ﺗﺸﺨﻴﺺ ﺍﻭﻝ
ﺑﻮﺩﻥ ﻳﮏ ﻋﺪﺩ ﮐﺎﻓﻲ ﺍﺳﺖ ﺑﺮﺭﺳﻲ ﺷﻮﺩ ﮐﻪ ﺁﻳﺎ ﺍﻳﻦ ﻋﺪﺩ ﺑﻪ ﺍﻋﺪﺍﺩ ﺍﻭﻝ ﻗﺒﻞ ﺍﺯ ﺧﻮﺩﺵ ﻗﺎﺑﻞ
ﺗﻘﺴﻴﻢ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ .ﺑﺮﺍﻱ ﺍﻳﻦ ﻣﻨﻈﻮﺭ ﻫﻢ ﺑﺎﻳﺪ ﺗﻤﺎﻣﻲ ﺍﻋﺪﺍﺩ ﺍﻭﻝ ﻳﺎﻓﺘﻪ ﺷﺪﻩ ﺭﺍ ﺩﺭ ﺁﺭﺍﻳﻪﺍﻱ
ﺫﺧﻴﺮﻩ ﮐﻨﻴﻢ .ﺁﺭﺍﻳﻪﻫﺎ ﺭﺍ ﺩﺭ ﻓﺼﻞ ﺑﻌﺪﻱ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﻴﻢ.
ﺍﺳﻢ ﺗﻮﺍﺑﻊ ﺑﻮﻟﻲ ﺭﺍ ﻣﻌﻤﻮﻻ ﺑﻪ ﺷﮑﻞ ﺳﻮﺍﻟﻲ ﺍﻧﺘﺨﺎﺏ ﻣﻲﮐﻨﻨﺪ ﺯﻳﺮﺍ ﺗﻮﺍﺑﻊ ﺑﻮﻟﻲ ﻫﻤﻴﺸﻪ
ﺑﻪ ﻳﮏ ﺳﻮﺍﻝ ﻣﻔﺮﻭﺽ ﭘﺎﺳﺦ ﺑﻠﻲ ﻳﺎ ﺧﻴﺮ ﻣﻲﺩﻫﻨﺪ .ﺗﺎﺑﻌﻲ ﮐﻪ ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﺗﻮﺿﻴﺢ ﺩﺍﺩﻩ ﺷﺪ
isPrimeﻧﺎﻡ ﮔﺮﻓﺘﻪ ﺯﻳﺮﺍ ﭘﺎﺳﺦ ﻣﻲﺩﻫﺪ ﮐﻪ ﺁﻳﺎ ﻋﺪﺩ ﻣﺬﮐﻮﺭ ﺍﻭﻝ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ .ﺍﻳﻦ ﻧﺤﻮ
ﻧﺎﻡﮔﺬﺍﺭﻱ ﮔﺮﭼﻪ ﺍﺟﺒﺎﺭﻱ ﻧﻴﺴﺖ ﺍﻣﺎ ﺩﺭﮎ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺁﺳﺎﻥﺗﺮ ﻣﻲﮐﻨﺪ ﻭ ﺑﻪ ﻳﺎﺩﺁﻭﺭﻱ ﻭﻇﻴﻒۀ
ﺗﺎﺑﻊ ﻧﻴﺰ ﮐﻤﮏ ﻣﻲﻧﻤﺎﻳﺪ .ﺩﺭ ﮐﺘﺎﺑﺨﺎﻥۀ C++ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺗﻮﺍﺑﻊ ﺑﻮﻟﻲ ﻣﺜﻞ )( isLowerﻳﺎ
)( isUpperﺑﻪ ﻫﻤﻴﻦ ﺷﻴﻮﻩ ﻧﺎﻡﮔﺬﺍﺭﻱ ﺷﺪﻩﺍﻧﺪ.
ﺩﺭ ﺟﻬﺖ ﻣﻌﮑﻮﺱ .ﻳﻌﻨﻲ ﺗﻮﺍﺑﻊ ﻭﺭﻭﺩﻱ ﻓﻘﻂ ﺑﺮﺍﻱ ﺩﺭﻳﺎﻓﺖ ﻭﺭﻭﺩﻱ ﻭ ﺍﺭﺳﺎﻝ ﺁﻥ ﺑﻪ ﺑﺮﻧﺎﻡۀ
ﺍﺻﻠﻲ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ﻭ ﻫﻴﭻ ﭘﺎﺭﺍﻣﺘﺮﻱ ﻧﺪﺍﺭﻧﺪ .ﻣﺜﺎﻝ ﺑﻌﺪ ﻳﮏ ﺗﺎﺑﻊ ﻭﺭﻭﺩﻱ ﺭﺍ ﻧﺸﺎﻥ
ﻣﻲﺩﻫﺪ.
ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ true ،ﺍﺳﺖ ﻭ ﺍﻳﻦ ﺣﻠﻘﻪ ﺑﻪ ﻇﺎﻫﺮ ﺑﻲﭘﺎﻳﺎﻥ ﺑﻪ ﻧﻈﺮ ﻣﻲﺭﺳﺪ .ﺍﻣﺎ
ﺩﺳﺘﻮﺭ returnﺩﺭﻭﻥ ﺣﻠﻘﻪ ﻧﻪ ﺗﻨﻬﺎ ﻣﻘﺪﺍﺭ ﻭﺭﻭﺩﻱ ﻣﻌﺘﺒﺮ ﺭﺍ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﻣﻲﻓﺮﺳﺘﺪ
ﺑﻠﮑﻪ ﻫﻢ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ ﻭ ﻫﻢ ﺗﺎﺑﻊ ﺭﺍ .ﺑﻪ ﻣﺤﺾ ﺍﻳﻦ ﮐﻪ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﺷﺪﻩ ﺍﺯ
cinﻣﻌﺘﺒﺮ ﺑﺎﺷﺪ ،ﺩﺳﺘﻮﺭ returnﺍﺟﺮﺍ ﺷﺪﻩ ﻭ ﻣﻘﺪﺍﺭ ﻣﺬﮐﻮﺭ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﺭﺳﺎﻝ
ﻣﻲﺷﻮﺩ ﻭ ﺗﺎﺑﻊ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ .ﺍﮔﺮ ﻭﺭﻭﺩﻱ ﻗﺎﺑﻞ ﻗﺒﻮﻝ ﻧﺒﺎﺷﺪ ) n<7ﻳﺎ ( n>120ﺁﻧﮕﺎﻩ
ﻳﮏ ﺑﻮﻕ ﺍﺧﻄﺎﺭ ﭘﺨﺶ ﻣﻲﺷﻮﺩ )ﮐﻪ ﺍﻳﻦ ﺑﻮﻕ ﺣﺎﺻﻞ ﭼﺎﭖ ﮐﺎﺭﺍﮐﺘﺮ \aﺍﺳﺖ( ﻭ ﺳﭙﺲ
ﻳﮏ ﺗﻮﺿﻴﺢ ﺭﻭﻱ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﺩﺭﺝ ﻣﻲﺷﻮﺩ ﮐﻪ ﮐﺎﺭﺑﺮ ﻣﻲ ﺧﻮﺍﻫﺪ ﺩﻭﺑﺎﺭﻩ ﺗﻼﺵ ﮐﻨﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 152
ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﺍﻳﻦ ﻣﺜﺎﻟﻲ ﺍﺳﺖ ﮐﻪ ﺩﺳﺘﻮﺭ returnﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺗﺎﺑﻊ ﻗﺮﺍﺭ ﻧﮕﺮﻓﺘﻪ.
ﻋﻼﻭﻩ ﺑﺮ ﺍﻳﻦ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﺧﺎﻟﻲ ﺍﺳﺖ ﺯﻳﺮﺍ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﭼﻴﺰﻱ ﺩﺭﻳﺎﻓﺖ
ﻧﻤﻲﮐﻨﺪ ﻭ ﻓﻘﻂ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺑﺎ ﺍﻳﻦ ﻭﺟﻮﺩ ﻻﺯﻡ ﺍﺳﺖ
ﮐﻪ ﭘﺮﺍﻧﺘﺰ ﻫﻢ ﺩﺭ ﺍﻋﻼﻥ ﺗﺎﺑﻊ ﻭ ﻫﻢ ﺩﺭ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ ﻗﻴﺪ ﺷﻮﺩ.
ﻳﻚ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﻭ ﺧﺮﻭﺟﻲ ﺣﺎﺻﻞ ﺍﺯ ﺁﻥ ﺩﺭ ﺍﺩﺍﻣﻪ ﺁﻣﺪﻩ ﺍﺳﺖ:
)(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
1 – Reference
153 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
ﺍﻣﺎ ﻧﻤﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ xﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﺪ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺑﻪ xﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ »ﻓﻘﻂ ﺧﻮﺍﻧﺪﻧﻲ«
ﻣﻲﮔﻮﻳﻨﺪ .ﻭﻗﺘﻲ ﺍﺭﺳﺎﻝ ﺑﻪ ﻭﺳﻴﻞۀ ﻣﻘﺪﺍﺭ ﺑﺎﺷﺪ ،ﻫﻨﮕﺎﻡ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻋﺒﺎﺭﺍﺕ
ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ .ﻣﺜﻼ ﺗﺎﺑﻊ )( cubeﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺻﻮﺭﺕ ) cube(2*x-3ﻓﺮﺍﺧﻮﺍﻧﻲ
ﮐﺮﺩ ﻳﺎ ﺑﻪ ﺷﮑﻞ )) cube(2*sqrt(x)-cube(3ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﻮﺩ .ﺩﺭ ﻫﺮ ﻳﮏ ﺍﺯ
ﺍﻳﻦ ﺣﺎﻻﺕ ،ﻋﺒﺎﺭﺕ ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻣﻘﺪﺍﺭ ﺗﮑﻲ ﺑﺮﺁﻭﺭﺩ ﺷﺪﻩ ﻭ ﺣﺎﺻﻞ ﺁﻥ
ﻣﻘﺪﺍﺭ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ.
ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﺯ ﺗﻐﻴﻴﺮﺍﺕ
ﻧﺎﺧﻮﺍﺳﺘﻪ ﺩﺭ ﺗﻮﺍﺑﻊ ﻣﺼﻮﻥ ﺑﻤﺎﻧﻨﺪ .ﺍﻣﺎ ﮔﺎﻫﻲ ﺍﻭﻗﺎﺕ ﻋﻤﺪﺍ ﻣﻲﺧﻮﺍﻫﻴﻢ ﺍﻳﻦ ﺍﺗﻔﺎﻕ ﺭﺥ ﺩﻫﺪ.
ﻳﻌﻨﻲ ﻣﻲﺧﻮﺍﻫﻴﻢ ﮐﻪ ﺗﺎﺑﻊ ﺑﺘﻮﺍﻧﺪ ﻣﺤﺘﻮﻳﺎﺕ ﻣﺘﻐﻴﺮ ﻓﺮﺳﺘﺎﺩﻩ ﺷﺪﻩ ﺑﻪ ﺁﻥ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ.
ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺍﺯ ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ.
ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻣﺸﺨﺺ ﮐﻨﻴﻢ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ ،ﻋﻼﻣﺖ &
ﺭﺍ ﺑﻪ ﻧﻮﻉ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﺍﺿﺎﻓﻪ ﻣﻲﮐﻨﻴﻢ .ﺍﻳﻦ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺗﺎﺑﻊ
ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﮐﭙﻲ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥ ﺁﺭﮔﻮﻣﺎﻥ ﺍﻳﺠﺎﺩ ﮐﻨﺪ ،ﺧﻮﺩ ﺁﺭﮔﻮﻣﺎﻥ ﻣﺤﻠﻲ ﺭﺍ ﺑﻪ ﮐﺎﺭ
ﺑﮕﻴﺮﺩ .ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺗﺎﺑﻊ ﻫﻢ ﻣﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ﺁﺭﮔﻮﻣﺎﻥ ﻓﺮﺳﺘﺎﺩﻩ ﺷﺪﻩ ﺭﺍ ﺑﺨﻮﺍﻧﺪ ﻭ ﻫﻢ
ﻣﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ﺁﻥ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﺪ .ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺁﻥ ﭘﺎﺭﺍﻣﺘﺮ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ »ﺧﻮﺍﻧﺪﻧﻲ‐ﻧﻮﺷﺘﻨﻲ«
ﺧﻮﺍﻫﺪ ﺑﻮﺩ .ﻫﺮ ﺗﻐﻴﻴﺮﻱ ﮐﻪ ﺭﻭﻱ ﭘﺎﺭﺍﻣﺘﺮ ﺧﻮﺍﻧﺪﻧﻲ‐ﻧﻮﺷﺘﻨﻲ ﺩﺭ ﺗﺎﺑﻊ ﺻﻮﺭﺕ ﮔﻴﺮﺩ ﺑﻪ ﻃﻮﺭ
ﻣﺴﺘﻘﻴﻢ ﺭﻭﻱ ﻣﺘﻐﻴﺮ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﻋﻤﺎﻝ ﻣﻲﺷﻮﺩ .ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ.
ﻫﺪﻑ ﺍﻳﻦ ﺗﺎﺑﻊ ﺟﺎﺑﺠﺎ ﮐﺮﺩﻥ ﺩﻭ ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺁﻥ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ .ﺑﺮﺍﻱ ﺍﻳﻦ
ﻣﻨﻈﻮﺭ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ xﻭ yﺑﻪ ﺻﻮﺭﺕ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺭﺟﺎﻉ ﺗﻌﺮﻳﻒ ﺷﺪﻩﺍﻧﺪ:
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 154
ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﻣﻮﺟﺐ ﻣﻲﺷﻮﺩ ﻛﻪ ﺑﻪ ﺟﺎﻱ xﻭ yﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﺍﺭﺳﺎﻟﻲ ﻗﺮﺍﺭ ﺑﮕﻴﺮﻧﺪ.
ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﻭ ﺍﺟﺮﺍﻱ ﺁﺯﻣﺎﻳﺸﻲ ﺁﻥ ﺩﺭ ﺯﻳﺮ ﺁﻣﺪﻩ ﺍﺳﺖ:
)&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
}
a = 55.5, b = 88.8
a = 88.8, b = 55.5
temp 55.5
float
155 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
ﺍﻳﻦ ﺍﻋﻼﻥ ﺷﺎﻣﻞ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﺑﺮﺍﻱ ﻫﺮ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺳﺖ .ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ cﻋﺎﺩﺕ ﺩﺍﺭﻧﺪ ﮐﻪ
ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﭘﻴﺸﻮﻧﺪ ﻧﺎﻡ ﻣﺘﻐﻴﺮ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻨﺪ )ﻣﺜﻞ (float &xﺩﺭ C++
ﻓﺮﺽ ﻣﻲﮐﻨﻴﻢ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﭘﺴﻮﻧﺪ ﻧﻮﻉ ﺍﺳﺖ )ﻣﺜﻞ (float& xﺑﻪ ﻫﺮ ﺣﺎﻝ
ﮐﺎﻣﭙﺎﻳﻠﺮ ﻫﻴﭻ ﻓﺮﻗﻲ ﺑﻴﻦ ﺍﻳﻦ ﺩﻭ ﺍﻋﻼﻥ ﻧﻤﻲﮔﺬﺍﺭﺩ ﻭ ﺷﮑﻞ ﻧﻮﺷﺘﻦ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ ﮐﺎﻣﻼ
ﺍﺧﺘﻴﺎﺭﻱ ﻭ ﺳﻠﻴﻘﻪﺍﻱ ﺍﺳﺖ.
)(int main
{ // tests the f() function:
;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
}
ﺗﺎﺑﻊ )( fﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺍﺭﺩ ﮐﻪ ﺍﻭﻟﻲ ﺑﻪ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻭ ﺩﻭﻣﻲ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ
ﻣﻲﺷﻮﺩ .ﻓﺮﺍﺧﻮﺍﻧﻲ ) f(a,bﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ aﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺑﻪ xﺍﺭﺳﺎﻝ ﺷﻮﺩ ﻭ b
ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺑﻪ yﻓﺮﺳﺘﺎﺩﻩ ﺷﻮﺩ .ﺑﻨﺎﺑﺮﺍﻳﻦ xﻳﻚ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ﺍﺳﺖ ﻛﻪ ﻣﻘﺪﺍﺭ 22ﺑﻪ ﺁﻥ
ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ ﺩﺭ ﺣﺎﻟﻲ ﻛﻪ yﻳﻚ ﺍﺭﺟﺎﻉ ﺑﻪ ﻣﺘﻐﻴﺮ bﺍﺳﺖ ﮐﻪ ﻣﻘﺪﺍﺭ ﻓﻌﻠﻲ ﺁﻥ 44
ﻣﻲﺑﺎﺷﺪ .ﺩﺭ ﺗﺎﺑﻊ )( fﻣﻘﺪﺍﺭ 88ﺩﺭ xﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﮐﻪ ﺍﻳﻦ ﺗﺎﺛﻴﺮﻱ ﺑﺮ aﻧﺪﺍﺭﺩ .ﻫﻤﭽﻨﻴﻦ
ﻣﻘﺪﺍﺭ 99ﺩﺭ yﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﮐﻪ ﭼﻮﻥ yﺩﺭ ﺣﻘﻴﻘﺖ ﻳﮏ ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺑﺮﺍﻱ bﺍﺳﺖ،
ﻣﻘﺪﺍﺭ bﺑﻪ 99ﺗﻐﻴﻴﺮ ﻣﻲﮐﻨﺪ .ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺗﺎﺑﻊ ﺧﺎﺗﻤﻪ ﻳﺎﺑﺪ a ،ﻫﻨﻮﺯ ﻣﻘﺪﺍﺭ 22ﺭﺍ ﺩﺍﺭﺩ
ﻭﻟﻲ ﻣﻘﺪﺍﺭ bﺑﻪ 99ﺗﻐﻴﻴﺮ ﻳﺎﻓﺘﻪ ﺍﺳﺖ .ﺁﺭﮔﻮﻣﺎﻥ aﻓﻘﻂ ﺧﻮﺍﻧﺪﻧﻲ ﺍﺳﺖ ﻭ ﺁﺭﮔﻮﻣﺎﻥ b
ﺧﻮﺍﻧﺪﻧﻲ‐ﻧﻮﺷﺘﻨﻲ ﺍﺳﺖ .ﺷﮑﻞ ﺯﻳﺮ ﻧﺤﻮۀ ﮐﺎﺭ ﺗﺎﺑﻊ )( fﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
هﻨﮕﺎم ﻓﺮاﺧﻮاﻧﯽ
)(main ﺗﺎ )f(a b )(f
ﺑﻌﺪ از
)(f
)(main ﺑﺎزﮔﺸﺖ
ﺩﺭ ﺟﺪﻭﻝ ﺯﻳﺮ ﺧﻼﺹۀ ﺗﻔﺎﻭﺕﻫﺎﻱ ﺑﻴﻦ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻭ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ
ﺍﺭﺟﺎﻉ ﺁﻣﺪﻩ ﺍﺳﺖ.
ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺩﺭ ﻣﻘﺎﻳﺴﻪ ﺑﺎ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ
ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ
;int& x ;int x
ﭘﺎﺭﺍﻣﺘﺮ xﻳﮏ ﺍﺭﺟﺎﻉ ﺍﺳﺖ ﭘﺎﺭﺍﻣﺘﺮ xﻳﮏ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ﺍﺳﺖ
xﻣﺘﺮﺍﺩﻑ ﺑﺎ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺳﺖ xﻳﮏ ﮐﭙﻲ ﺍﺯ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺳﺖ
ﻣﻲﺗﻮﺍﻧﺪ ﻣﺤﺘﻮﻳﺎﺕ ﺁﺭﮔﻮﻣﺎﻥ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﺪ ﺗﻐﻴﻴﺮ ﻣﺤﺘﻮﻳﺎﺕ ﺁﺭﮔﻮﻣﺎﻥ ﻣﻤﮑﻦ ﻧﻴﺴﺖ
157 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
ﺁﺭﮔﻮﻣﺎﻥ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﻓﻘﻂ ﺑﺎﻳﺪ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻣﻲﺗﻮﺍﻧﺪ
ﻳﮏ ﻣﺘﻐﻴﺮ ﺑﺎﺷﺪ ﻳﮏ ﺛﺎﺑﺖ ،ﻳﮏ ﻣﺘﻐﻴﺮ ﻳﺎ ﻳﮏ ﻋﺒﺎﺭﺕ ﺑﺎﺷﺪ
ﺁﺭﮔﻮﻣﺎﻥ ﺧﻮﺍﻧﺪﻧﻲ‐ﻧﻮﺷﺘﻨﻲ ﺍﺳﺖ ﺁﺭﮔﻮﻣﺎﻥ ﻓﻘﻂ ﺧﻮﺍﻧﺪﻧﻲ ﺍﺳﺖ
ﻳﻜﻲ ﺍﺯ ﻣﻮﺍﻗﻌﻲ ﻛﻪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺭﺟﺎﻉ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﻫﺴﺘﻨﺪ ﺟﺎﻳﻲ ﺍﺳﺖ ﻛﻪ ﺗﺎﺑﻊ ﺑﺎﻳﺪ
ﺑﻴﺶ ﺍﺯ ﻳﻚ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺎﺯﮔﺮﺩﺍﻧﺪ .ﺩﺳﺘﻮﺭ returnﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﻳﻚ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ.
ﺑﻨﺎﺑﺮﺍﻳﻦ ﺍﮔﺮ ﺑﺎﻳﺪ ﺑﻴﺶ ﺍﺯ ﻳﻚ ﻣﻘﺪﺍﺭ ﺑﺮﮔﺸﺖ ﺩﺍﺩﻩ ﺷﻮﺩ ،ﺍﻳﻦ ﻛﺎﺭ ﺭﺍ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺭﺟﺎﻉ
ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﻨﺪ.
ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺗﺎﺑﻊ ﻓﻮﻕ ﻭ ﻳﮏ ﺍﺟﺮﺍﻱ ﺁﺯﻣﺎﻳﺸﻲ ﺁﻥ ﺩﺭ ﺷﮑﻞ ﺯﻳﺮ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ:
;)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
}
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 158
ﺩﺭ ﺍﻋﻼﻥ ﻭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﻓﻮﻕ ،ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻳﻲ ﮐﻪ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﻧﺪ ﺩﺭ ﺍﺑﺘﺪﺍﻱ
ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﺷﺪﻩﺍﻧﺪ .ﺭﻋﺎﻳﺖ ﺍﻳﻦ ﻗﺎﻋﺪﻩ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﻧﻈﻢ ﺑﺮﻧﺎﻣﻪ
ﺣﻔﻆ ﺷﻮﺩ ﻭ ﺑﻪ ﺳﺎﺩﮔﻲ ﺑﺘﻮﺍﻧﻴﺪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﺭﺍ ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﺗﻤﻴﺰ ﺩﻫﻴﺪ .ﺍﻟﺒﺘﻪ ﺍﻳﻦ ﻓﻘﻂ
ﻳﮏ ﻗﺮﺍﺭﺩﺍﺩ ﺍﺳﺖ ﻭ ﺭﻋﺎﻳﺖ ﺁﻥ ﺍﺟﺒﺎﺭﻱ ﻧﻴﺴﺖ.
ﺩﺭ ﺗﺎﺑﻊ ﻓﻮﻕ ﺍﻭﻟﻴﻦ ﭘﺎﺭﺍﻣﺘﺮ ﻳﻌﻨﻲ xﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ ،ﺩﻭﻣﻴﻦ ﭘﺎﺭﺍﻣﺘﺮ
ﻳﻌﻨﻲ yﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﻭ ﺳﻮﻣﻴﻦ ﭘﺎﺭﺍﻣﺘﺮ ﻧﻴﺰ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ .ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﻭ ﻳﮏ
ﺍﺟﺮﺍﻱ ﺁﺯﻣﺎﻳﺸﻲ ﺍﺯ ﺁﻥ ﺩﺭ ﺫﻳﻞ ﺁﻣﺪﻩ ﺍﺳﺖ:
;)&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
}
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
ﺗﺎﺑﻊ ﻓﻮﻕ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ xﻭ yﺭﺍ ﻣﻲﺗﻮﺍﻧﺪ ﺗﻐﻴﻴﺮ ﺩﻫﺪ ﻭﻟﻲ ﻗﺎﺩﺭ ﻧﻴﺴﺖ ﭘﺎﺭﺍﻣﺘﺮ zﺭﺍ ﺗﻐﻴﻴﺮ
ﺩﻫﺪ .ﺗﻐﻴﻴﺮﺍﺗﻲ ﮐﻪ ﺭﻭﻱ xﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ ﺍﺛﺮﻱ ﺭﻭﻱ ﺁﺭﮔﻮﻣﺎﻥ aﻧﺨﻮﺍﻫﺪ ﺩﺍﺷﺖ ﺯﻳﺮﺍ a
ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﺷﺪﻩ .ﺗﻐﻴﻴﺮﺍﺗﻲ ﮐﻪ ﺭﻭﻱ yﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ ﺭﻭﻱ ﺁﺭﮔﻮﻣﺎﻥ
bﻫﻢ ﺗﺎﺛﻴﺮ ﻣﻲﮔﺬﺍﺭﺩ ﺯﻳﺮﺍ bﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﺷﺪﻩ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 160
ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺑﻴﺸﺘﺮ ﺑﺮﺍﻱ ﺗﻮﺍﺑﻌﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﮐﻪ ﻋﻨﺎﺻﺮ ﺑﺰﺭﮒ
ﺭﺍ ﻭﻳﺮﺍﻳﺶ ﻣﻲﮐﻨﻨﺪ ﻣﺜﻞ ﺁﺭﺍﻳﻪﻫﺎ ﻳﺎ ﻧﻤﻮﻥۀ ﮐﻼﺱﻫﺎ ﮐﻪ ﺩﺭ ﻓﺼﻞﻫﺎﻱ ﺑﻌﺪﻱ ﺗﻮﺿﻴﺢ ﺁﻥﻫﺎ
ﺁﻣﺪﻩ ﺍﺳﺖ .ﻋﻨﺎﺻﺮﻱ ﮐﻪ ﺍﺯ ﺍﻧﻮﺍﻉ ﺍﺻﻠﻲ ﻫﺴﺘﻨﺪ )ﻣﺜﻞ intﻳﺎ (floatﺑﻪ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ
ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﻧﺪ ﺑﻪ ﺷﺮﻃﻲ ﮐﻪ ﻗﺮﺍﺭ ﻧﺒﺎﺷﺪ ﺗﺎﺑﻊ ﻣﺤﺘﻮﻳﺎﺕ ﺁﻥﻫﺎ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ.
1
5‐12ﺗﻮﺍﺑﻊ ﺑﻲﻭﺍﺳﻄﻪ
ﻭﻗﺘﻲ ﺗﺎﺑﻌﻲ ﺩﺭﻭﻥ ﻳﮏ ﺑﺮﻧﺎﻣﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ،ﺍﺑﺘﺪﺍ ﺑﺎﻳﺪ ﻣﮑﺎﻥ ﻓﻌﻠﻲ ﺍﺟﺮﺍﻱ
ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﻭ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻓﻌﻠﻲ ﺁﻥ ﺩﺭ ﺟﺎﻳﻲ ﻧﮕﻬﺪﺍﺭﻱ ﺷﻮﺩ ﺗﺎ ﭘﺲ ﺍﺯ ﺍﺗﻤﺎﻡ ﺗﺎﺑﻊ ،ﺍﺩﺍﻣﻪ
ﺑﺮﻧﺎﻣﻪ ﭘﻲﮔﻴﺮﻱ ﺷﻮﺩ .ﻫﻤﭽﻨﻴﻦ ﺑﺎﻳﺪ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ ﺗﺎﺑﻊ ﺍﻳﺠﺎﺩ ﺷﻮﻧﺪ ﻭ ﺣﺎﻓﻈﻪﺍﻱ ﺑﺮﺍﻱ
ﺁﻥﻫﺎ ﺗﺨﺼﻴﺺ ﻳﺎﺑﺪ ﻭ ﻫﻤﭽﻨﻴﻦ ﺁﺭﮔﻮﻣﺎﻥﻫﺎ ﺑﻪ ﺍﻳﻦ ﻣﺘﻐﻴﺮﻫﺎ ﺍﺭﺳﺎﻝ ﺷﻮﻧﺪ ﺗﺎ ﺩﺭﻧﻬﺎﻳﺖ ﺗﺎﺑﻊ
ﺷﺮﻭﻉ ﺑﻪ ﮐﺎﺭ ﮐﻨﺪ .ﭘﺲ ﺍﺯ ﭘﺎﻳﺎﻥ ﮐﺎﺭ ﺗﺎﺑﻊ ﻧﻴﺰ ﺑﺎﻳﺪ ﻫﻤﻴﻦ ﻣﺴﻴﺮ ﺑﻪ ﺷﮑﻞ ﻣﻌﮑﻮﺱ ﭘﻴﻤﻮﺩﻩ
ﺷﻮﺩ ﺗﺎ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﺩﺍﻣﻪ ﻳﺎﺑﺪ .ﺍﻧﺠﺎﻡ ﻫﻢۀ ﺍﻳﻦ ﮐﺎﺭﻫﺎ ﻫﻢ ﺯﻣﺎﻥﮔﻴﺮ ﺍﺳﺖ ﻭ ﻫﻢ ﺣﺎﻓﻆۀ
ﺍﺿﺎﻓﻲ ﻣﻲﻃﻠﺒﺪ .ﺩﺭ ﺍﺻﻄﻼﺡ ﻣﻲﮔﻮﻳﻨﺪ ﮐﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻭ ﺍﺟﺮﺍﻱ ﺗﺎﺑﻊ »ﺳﺮﺑﺎﺭ« ﺩﺍﺭﺩ .ﺩﺭ
ﺑﻌﻀﻲ ﺣﺎﻟﺖﻫﺎ ﺑﻬﺘﺮ ﺍﺳﺖ ﺑﺎ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﺑﻪ ﺷﮑﻞ ﺑﻲﻭﺍﺳﻄﻪ ﺍﺯ ﺳﺮﺑﺎﺭ ﺍﺟﺘﻨﺎﺏ ﮐﻨﻴﻢ.
ﺗﺎﺑﻌﻲ ﮐﻪ ﺑﻪ ﺷﮑﻞ ﺑﻲﻭﺍﺳﻄﻪ ﺗﻌﺮﻳﻒ ﻣﻲﺷﻮﺩ ،ﻇﺎﻫﺮﻱ ﺷﺒﻴﻪ ﺑﻪ ﺗﻮﺍﺑﻊ ﻣﻌﻤﻮﻟﻲ ﺩﺍﺭﺩ ﺑﺎ ﺍﻳﻦ
ﻓﺮﻕ ﮐﻪ ﻋﺒﺎﺭﺕ inlineﺩﺭ ﺍﻋﻼﻥ ﻭ ﺗﻌﺮﻳﻒ ﺁﻥ ﻗﻴﺪ ﺷﺪﻩ ﺍﺳﺖ.
ﺗﻨﻬﺎ ﺗﻔﺎﻭﺕ ﺍﻳﻦ ﺍﺳﺖ ﻛﻪ ﻛﻠﻢۀ ﻛﻠﻴﺪﻱ inlineﺩﺭ ﺍﺑﺘﺪﺍﻱ ﻋﻨﻮﺍﻥ ﺗﺎﺑﻊ ﺫﮐﺮ ﺷﺪﻩ .ﺍﻳﻦ
ﻋﺒﺎﺭﺕ ﺑﻪ ﻛﺎﻣﭙﺎﻳﻠﺮ ﻣﻲﮔﻮﻳﺪ ﻛﻪ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺟﺎﻱ ) cube(nﮐﺪ ﻭﺍﻗﻌﻲ
) (n)*(n)*(nﺭﺍ ﻗﺮﺍﺭ ﺩﻫﺪ .ﺑﻪ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ:
1 – Inline
161 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
)(int main
{ // tests the cube() function:
;cout << cube(4) << endl
;int x, y
;cin >> x
;)y = cube(2*x-3
}
ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻨﮕﺎﻡ ﮐﺎﻣﭙﺎﻳﻞ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺩﺭﻣﻲﺁﻳﺪ ،ﮔﻮﻳﻲ ﺍﺻﻼ ﺗﺎﺑﻌﻲ ﻭﺟﻮﺩ ﻧﺪﺍﺷﺘﻪ:
)(int main
{ // tests the cube() function:
;cout << (4) * (4) * (4) << endl
;int x, y
;cin >> x
;)y = (2*x-3) * (2*x-3) * (2*x-3
}
ﺍﺣﺘﻴﺎﻁ :ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﺑﻲﻭﺍﺳﻄﻪ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺛﺮﺍﺕ ﻣﻨﻔﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﻣﺜﻼ ﺍﮔﺮ ﻳﮏ
ﺗﺎﺑﻊ ﺑﻲﻭﺍﺳﻄﻪ ﺩﺍﺭﺍﻱ 40ﺧﻂ ﮐﺪ ﺑﺎﺷﺪ ﻭ ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﺭ 26ﻧﻘﻄﻪ ﻣﺨﺘﻠﻒ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ ،ﻫﻨﮕﺎﻡ ﮐﺎﻣﭙﺎﻳﻞ ﺑﻴﺶ ﺍﺯ ﻫﺰﺍﺭ ﺧﻂ ﮐﺪ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ.
ﻫﻤﭽﻨﻴﻦ ﺗﺎﺑﻊ ﺑﻲﻭﺍﺳﻄﻪ ﻣﻲﺗﻮﺍﻧﺪ ﻗﺎﺑﻠﻴﺖ ﺍﻧﺘﻘﺎﻝ ﺑﺮﻧﺎﻡۀ ﺷﻤﺎ ﺭﺍ ﺭﻭﻱ ﺳﻴﺴﺘﻢﻫﺎﻱ ﻣﺨﺘﻠﻒ
ﮐﺎﻫﺶ ﺩﻫﺪ.
5‐13ﭼﻨﺪﺷﮑﻠﻲ ﺗﻮﺍﺑﻊ
ﺩﺭ C++ﻣﻲﺗﻮﺍﻧﻴﻢ ﭼﻨﺪ ﺗﺎﺑﻊ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ ﮐﻪ ﻫﻤﮕﻲ ﻳﮏ ﻧﺎﻡ ﺩﺍﺭﻧﺪ .ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ
ﻣﻲﮔﻮﻳﻴﻢ ﮐﻪ ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ،ﭼﻨﺪﺷﮑﻠﻲ ﺩﺍﺭﺩ .ﺷﺮﻁ ﺍﻳﻦ ﮐﺎﺭ ﺁﻥ ﺍﺳﺖ ﮐﻪ ﻓﻬﺮﺳﺖ
ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺑﺎ ﻳﮑﺪﻳﮕﺮ ﺗﻔﺎﻭﺕ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﻳﻌﻨﻲ ﺗﻌﺪﺍﺩ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﻣﺘﻔﺎﻭﺕ ﺑﺎﺷﺪ
ﻳﺎ ﺩﺳﺖ ﮐﻢ ﻳﮑﻲ ﺍﺯ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﻣﺘﻨﺎﻇﺮ ﻫﻢ ﻧﻮﻉ ﻧﺒﺎﺷﻨﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 162
)(int main
<< " " << ){ cout << max(99,77) << " " << max(55,66,33
;)max(44.4,88.8
}
ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺳﻪ ﺗﺎﺑﻊ ﺑﺎ ﻧﺎﻡ )( maxﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ .ﻭﻗﺘﻲ ﺗﺎﺑﻊ )( maxﺩﺭ ﺟﺎﻳﻲ ﺍﺯ
ﺑﺮﻧﺎﻣﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ،ﮐﺎﻣﭙﺎﻳﻠﺮ ﻓﻬﺮﺳﺖ ﺁﺭﮔﻮﻣﺎﻥ ﺁﻥ ﺭﺍ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﺪ ﺗﺎ ﺑﻔﻬﻤﺪ ﮐﻪ
ﮐﺪﺍﻡ ﻧﺴﺨﻪ ﺍﺯ maxﺑﺎﻳﺪ ﺍﺣﻀﺎﺭ ﺷﻮﺩ .ﻣﺜﻼ ﺩﺭ ﺍﻭﻟﻴﻦ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ )( maxﺩﻭ
ﺁﺭﮔﻮﻣﺎﻥ intﺍﺭﺳﺎﻝ ﺷﺪﻩ ،ﭘﺲ ﻧﺴﺨﻪﺍﻱ ﮐﻪ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ intﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻳﺶ
163 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
ﺩﺍﺭﺩ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ ﺍﻳﻦ ﻧﺴﺨﻪ ﻭﺟﻮﺩ ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﺪ ،ﮐﺎﻣﭙﺎﻳﻠﺮ intﻫﺎ ﺭﺍ ﺑﻪ
doubleﺍﺭﺗﻘﺎ ﻣﻲﺩﻫﺪ ﻭ ﺳﭙﺲ ﻧﺴﺨﻪﺍﻱ ﮐﻪ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ doubleﺩﺍﺭﺩ ﺭﺍ ﻓﺮﺍ ﻣﻲﺧﻮﺍﻧﺪ.
ﺗﻮﺍﺑﻌﻲ ﮐﻪ ﭼﻨﺪﺷﮑﻠﻲ ﺩﺍﺭﻧﺪ ﺑﺴﻴﺎﺭ ﻓﺮﺍﻭﺍﻥ ﺩﺭ C++ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ .ﭼﻨﺪﺷﮑﻠﻲ
ﺩﺭ ﮐﻼﺱﻫﺎ ﺍﻫﻤﻴﺖ ﻓﺮﺍﻭﺍﻧﻲ ﺩﺍﺭﺩ ﮐﻪ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺩﺭ ﻓﺼﻞ 12ﺑﺤﺚ ﺧﻮﺍﻫﺪ ﺷﺪ.
5‐14ﺗﺎﺑﻊ )(main
ﺍﮐﻨﻮﻥ ﮐﻪ ﺑﺎ ﺗﻮﺍﺑﻊ ﺁﺷﻨﺎ ﺷﺪﻩﺍﻳﻢ ،ﻧﮕﺎﻩ ﺩﻗﻴﻖﺗﺮﻱ ﺑﻪ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺑﻴﺎﻧﺪﺍﺯﻳﻢ .ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ
ﺗﺎ ﮐﻨﻮﻥ ﻧﻮﺷﺘﻴﻢ ﻫﻤﻪ ﺩﺍﺭﺍﻱ ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )( mainﻫﺴﺘﻨﺪ .ﻣﻨﻄﻖ C++ﺍﻳﻦ ﻃﻮﺭ ﺍﺳﺖ
ﮐﻪ ﻫﺮ ﺑﺮﻧﺎﻣﻪ ﺑﺎﻳﺪ ﺩﺍﺭﺍﻱ ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )( mainﺑﺎﺷﺪ .ﺩﺭ ﺣﻘﻴﻘﺖ ﻫﺮ ﺑﺮﻧﺎﻣﻪ ﮐﺎﻣﻞ ،ﺍﺯ
ﻳﮏ ﺗﺎﺑﻊ )( mainﺑﻪ ﻫﻤﺮﺍﻩ ﺗﻮﺍﺑﻊ ﺩﻳﮕﺮ ﺗﺸﮑﻴﻞ ﺷﺪﻩ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﻳﮏ ﺍﺯ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺑﻪ
ﺷﮑﻞ ﻣﺴﺘﻘﻴﻢ ﻳﺎ ﻏﻴﺮ ﻣﺴﺘﻘﻴﻢ ﺍﺯ ﺩﺭﻭﻥ ﺗﺎﺑﻊ )( mainﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﻧﺪ .ﺧﻮﺩ ﺑﺮﻧﺎﻣﻪ ﺑﺎ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ )( mainﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ .ﭼﻮﻥ ﺍﻳﻦ ﺗﺎﺑﻊ ﻳﮏ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ intﺩﺍﺭﺩ،
ﻣﻨﻄﻘﻲ ﺍﺳﺖ ﮐﻪ ﺑﻠﻮﮎ ﺗﺎﺑﻊ )( mainﺷﺎﻣﻞ ﺩﺳﺘﻮﺭ ; return 0ﺑﺎﺷﺪ ﻫﺮﭼﻨﺪ ﮐﻪ ﺩﺭ
ﺑﺮﺧﻲ ﺍﺯ ﮐﺎﻣﭙﺎﻳﻠﺮﻫﺎﻱ C++ﺍﻳﻦ ﺧﻂ ﺍﺟﺒﺎﺭﻱ ﻧﻴﺴﺖ ﻭ ﻣﻲﺗﻮﺍﻥ ﺁﻥ ﺭﺍ ﺫﮐﺮ ﻧﮑﺮﺩ .ﻣﻘﺪﺍﺭ
ﺻﺤﻴﺤﻲ ﮐﻪ ﺑﺎ ﺩﺳﺘﻮﺭ returnﺑﻪ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﺑﺮﻣﻲﮔﺮﺩﺩ ﺑﺎﻳﺪ ﺗﻌﺪﺍﺩ ﺧﻄﺎﻫﺎ ﺭﺍ
ﺷﻤﺎﺭﺵ ﮐﻨﺪ .ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﺁﻥ 0ﺍﺳﺖ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺑﺪﻭﻥ ﺧﻄﺎ ﭘﺎﻳﺎﻥ ﮔﺮﻓﺘﻪ
ﺍﺳﺖ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ returnﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺑﻪ ﻃﻮﺭ ﻏﻴﺮﻣﻌﻤﻮﻝ ﺧﺎﺗﻤﻪ ﺩﻫﻴﻢ.
ﺍﮔﺮ ﻛﺎﺭﺑﺮ ﺑﺮﺍﻱ ﻭﺭﻭﺩﻱ ﺩﻭﻡ 0ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﺪ ،ﺑﺮﻧﺎﻣﻪ ﺑﺪﻭﻥ ﭼﺎﭖ ﺧﺮﻭﺟﻲ ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ:
Enter two integers: 99 0
)(int main
;{ double x
;cin >> x
;)cout << reciprocal(x
}
1 – Exception
165 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﮔﺮ ﻛﺎﺭﺑﺮ ﻋﺪﺩ 0ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﺪ ،ﺗﺎﺑﻊ )( reciprocalﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ ﻭ
ﺑﺮﻧﺎﻣﻪ ﺑﺪﻭﻥ ﻫﻴﭻ ﻣﻘﺪﺍﺭ ﭼﺎﭘﻲ ﺑﻪ ﭘﺎﻳﺎﻥ ﻣﻲﺭﺳﺪ.
1
5‐15ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﭘﻴﺶﻓﺮﺽ
ﺩﺭ C++ﻣﻲﺗﻮﺍﻥ ﺗﻌﺪﺍﺩ ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﻳﮏ ﺗﺎﺑﻊ ﺭﺍ ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺑﻪ ﺩﻟﺨﻮﺍﻩ ﺗﻐﻴﻴﺮ
ﺩﺍﺩ .ﺍﻳﻦ ﺍﻣﺮ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﺍﺧﺘﻴﺎﺭﻱ ﻭ ﻣﻘﺎﺩﻳﺮ ﭘﻴﺶﻓﺮﺽ ﺍﻣﮑﺎﻥﭘﺬﻳﺮ ﺍﺳﺖ.
)(int main
{ // tests the p() function:
;double x = 2.0003
;cout << "p(x,7) = " << p(x,7) << endl
;cout << "p(x,7,6) = " << p(x,7,6) << endl
;cout << "p(x,7,6,5) = " << p(x,7,6,5) << endl
;cout << "p(x,7,6,5,4) = " << p(x,7,6,5,4) << endl
}
)double p(double x, double a0, double a1=0, double a2=0, double a3=0
{ // returns a0 + a1*x + a2*x^2 + a3*x^3:
;return a0 + (a1 + (a2 + a3*x)*x)*x
}
p(x,7) = 7
p(x,7,6) = 19.0018
p(x,7,6,5) = 39.0078
p(x,7,6,5,4) = 71.0222
1 – Default
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 166
ﻫﻨﮕﺎﻣﻲ ﮐﻪ ) p(x, a0, a1, a2, a3ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ ،ﭼﻨﺪﺟﻤﻠﻪﺍﻱ ﺩﺭﺟﻪ ﺳﻮﻡ
a0 + a1 x + a2 x 2 + a3 x3ﻣﺤﺎﺳﺒﻪ ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﭼﻮﻥ a1ﻭ a2ﻭ a3ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ
0ﺭﺍ ﺩﺍﺭﻧﺪ ،ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺻﻮﺭﺕ ) p(x,a0ﻧﻴﺰ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﻮﺩ .ﺍﻳﻦ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻌﺎﺩﻝ ﻓﺮﺍﺧﻮﺍﻧﻲ ) p(x,a0,0,0,0ﺍﺳﺖ ﮐﻪ ﺑﺮﺍﺑﺮ ﺑﺎ a0ﺍﺭﺯﻳﺎﺑﻲ ﺧﻮﺍﻫﺪ
ﺷﺪ .ﻫﻤﭽﻨﻴﻦ ﻣﻲﺗﻮﺍﻥ ﺗﺎﺑﻊ ﻓﻮﻕ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ) p(x,a0,a1ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﻮﺩ .ﺍﻳﻦ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻌﺎﺩﻝ ﻓﺮﺍﺧﻮﺍﻧﻲ ) p(x,a0,a1,0,0ﺍﺳﺖ ﮐﻪ ﭼﻨﺪﺟﻤﻠﻪﺍﻱ ﺩﺭﺟﻪ ﺍﻭﻝ
a0 + a1 xﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻣﻲﻧﻤﺎﻳﺪ .ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﻓﺮﺍﺧﻮﺍﻧﻲ )p(x,a0,a1,a2
ﭼﻨﺪﺟﻤﻠﻪﺍﻱ ﺩﺭﺟﻪ ﺩﻭﻡ a0 + a1 x + a2 x 2ﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻣﻲﮐﻨﺪ ﻭ ﻫﻤﭽﻨﻴﻦ ﻓﺮﺍﺧﻮﺍﻧﻲ
) p(x,a0,a1,a2,a3ﭼﻨﺪ ﺟﻤﻠﻪﺍﻱ ﺩﺭﺟﻪ ﺳﻮﻡ a0 + a1 x + a2 x 2 + a3 x3ﺭﺍ
ﻣﺤﺎﺳﺒﻪ ﻣﻲﮐﻨﺪ .ﭘﺲ ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﺎ 2ﻳﺎ 3ﻳﺎ 4ﻳﺎ 5ﺁﺭﮔﻮﻣﺎﻥ ﻓﺮﺍﺧﻮﺍﻧﻲ ﮐﺮﺩ.
ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺑﻪ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﺑﺪﻫﻴﻢ ﺑﺎﻳﺪ ﺁﻥ ﻣﻘﺪﺍﺭ ﺭﺍ ﺩﺭ ﻓﻬﺮﺳﺖ
ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﻭ ﺟﻠﻮﻱ ﭘﺎﺭﺍﻣﺘﺮ ﻣﺮﺑﻮﻃﻪ ﺑﻪ ﻫﻤﺮﺍﻩ ﻋﻼﻣﺖ ﻣﺴﺎﻭﻱ ﺩﺭﺝ ﮐﻨﻴﻢ .ﺑﻪ ﺍﻳﻦ
ﺗﺮﺗﻴﺐ ﺍﮔﺮ ﻫﻨﮕﺎﻡ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ ،ﺁﻥ ﺁﺭﮔﻮﻣﺎﻥ ﺭﺍ ﺫﮐﺮ ﻧﮑﻨﻴﻢ ،ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﺁﻥ ﺩﺭ
ﻣﺤﺎﺳﺒﺎﺕ ﺗﺎﺑﻊ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﺑﻪ ﻫﻤﻴﻦ ﺧﺎﻃﺮ ﺑﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﺁﺭﮔﻮﻣﺎﻥﻫﺎ ،ﺁﺭﮔﻮﻣﺎﻥ
ﺍﺧﺘﻴﺎﺭﻱ ﻣﻲﮔﻮﻳﻨﺪ.
ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻳﻲ ﮐﻪ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﺩﺍﺭﻧﺪ ﺑﺎﻳﺪ ﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ
ﺗﺎﺑﻊ ﺑﻌﺪ ﺍﺯ ﻫﻢۀ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺟﺒﺎﺭﻱ ﻗﻴﺪ ﺷﻮﻧﺪ ﻣﺜﻞ:
;)void f( int a, int b, int c=4, int d=7, int e=3 // OK
;)void g(int a, int b=2, int c=4, int d, int e=3 // ERROR
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﺗﻮﺍﺑﻊ ﺭﻳﺎﺿﻲ C++ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺩﺭ ﮐﺪﺍﻡ ﺳﺮﻓﺎﻳﻞ ﺗﻌﺮﻳﻒ ﺷﺪﻩﺍﻧﺪ؟
ﺏ – ﺳﺮﻓﺎﻳﻞ ><cmath ﺍﻟﻒ – ﺳﺮﻓﺎﻳﻞ ><iostream
ﺩ – ﺳﺮﻓﺎﻳﻞ ><iomanip ﺝ – ﺳﺮﻓﺎﻳﻞ ><cstdlib
– 2ﺩﺭ ﺗﻌﺮﻳﻒ ) int f(float aﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟
ﺍﻟﻒ – ﺍﻳﻦ ﮐﺪ ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ fﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ
ﺏ – ﺗﺎﺑﻊ ﻓﻮﻕ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ floatﺩﺍﺭﺩ
ﺝ ‐ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﺯ ﻧﻮﻉ intﺍﺳﺖ
ﺩ – ﭘﺎﺭﺍﻣﺘﺮ ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﺯ ﻧﻮﻉ intﺍﺳﺖ.
– 3ﺩﺳﺘﻮﺭ returnﺩﺭ ﺗﺎﺑﻊ ﭼﻪ ﮐﺎﺭﻱ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ؟
ﺍﻟﻒ – ﺗﺎﺑﻊ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ
ﺏ – ﻣﻘﺪﺍﺭ ﻧﻬﺎﻳﻲ ﺭﺍ ﺑﻪ ﻓﺮﺍﺧﻮﺍﻧﻨﺪﻩ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ
ﺝ – ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ
ﺩ – ﺍﻟﻒ ﻭ ﺏ
– 4ﮐﺪﺍﻡ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟
ﺍﻟﻒ – ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ،ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ ﺑﺮﺍﻱ ﺁﻥ ﺗﺎﺑﻊ ﻣﺤﺴﻮﺏ ﻣﻲﺷﻮﻧﺪ
ﺏ – ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﻋﻼﻥ ﺷﺪﻩ ﺩﺭ ﻳﮏ ﺗﺎﺑﻊ ،ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ ﺁﻥ ﺗﺎﺑﻊ ﻣﺤﺴﻮﺏ ﻣﻲﺷﻮﻧﺪ
ﺝ – ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ ﺗﺎﺑﻊ ،ﻓﻘﻂ ﺩﺭ ﻃﻮﻝ ﺍﺟﺮﺍﻱ ﺗﺎﺑﻊ ﻣﻮﺟﻮﺩﻧﺪ
ﺩ – ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ ﺗﺎﺑﻊ ﺩﺭ ﺳﺮﺍﺳﺮ ﺑﺮﻧﺎﻣﻪ ﻣﻌﺘﺒﺮﻧﺪ
– 5ﺗﺎﺑﻌﻲ ﮐﻪ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺑﺮﻧﻤﻲﮔﺮﺩﺍﻧﺪ ،ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺁﻥ ﭼﮕﻮﻧﻪ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ؟
ﺏ – ﺍﺯ ﻧﻮﻉ null ﺍﻟﻒ – ﺍﺯ ﻧﻮﻉ void
ﺩ – ﻻﺯﻡ ﻧﻴﺴﺖ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﻗﻴﺪ ﺷﻮﺩ ﺝ – ﺍﺯ ﻧﻮﻉ ﭘﻴﺶ ﻓﺮﺽ int
– 6ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﻳﮏ ﺗﺎﺑﻊ ﺑﻮﻟﻲ ﭼﻴﺴﺖ؟
ﺩ – const ﺝ – bool ﺏ – void ﺍﻟﻒ – int
– 7ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﮔﺰﻳﻨﻪﻫﺎﻱ ﺯﻳﺮ ﺍﺳﺖ؟
ﺩ‐: ﺝ ‐ >- ﺏ‐& ﺍﻟﻒ ‐ *
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 168
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ ﺑﺮﺍﻱ ﺑﺨﺶﺑﻨﺪﻱ ﺑﺮﻧﺎﻣﻪ ﭼﻪ ﻣﺰﺍﻳﺎﻳﻲ ﺩﺍﺭﺩ؟
‐2ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﻴﻦ ﺍﻋﻼﻥ ﻳﮏ ﺗﺎﺑﻊ ﻭ ﺗﻌﺮﻳﻒ ﺁﻥ ﺍﺳﺖ؟
‐3ﺍﻋﻼﻥ ﻳﮏ ﺗﺎﺑﻊ ﮐﺠﺎ ﻣﻲﺗﻮﺍﻧﺪ ﻗﺮﺍﺭ ﺑﮕﻴﺮﺩ؟
‐4ﺑﺮﺍﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﭼﻪ ﺗﻮﺍﺑﻌﻲ ﺑﻪ ﺩﺳﺘﻮﺭ includeﻧﻴﺎﺯ ﺍﺳﺖ؟
‐5ﮔﺬﺍﺷﺘﻦ ﺗﻌﺮﻳﻒ ﻳﻚ ﺗﺎﺑﻊ ﺩﺭ ﻳﻚ ﻓﺎﻳﻞ ﺟﺪﺍﮔﺎﻧﻪ ﭼﻪ ﻣﺰﻳﺘﻲ ﺩﺍﺭﺩ؟
‐6ﻛﺎﻣﭙﺎﻳﻞ ﻛﺮﺩﻥ ﻳﻚ ﺗﺎﺑﻊ ﺑﻪ ﻃﻮﺭ ﺟﺪﺍﮔﺎﻧﻪ ﭼﻪ ﻣﺰﻳﺘﻲ ﺩﺍﺭﺩ؟
‐7ﭼﻪ ﺗﻔﺎﻭﺕﻫﺎﻳﻲ ﺑﻴﻦ ﺍﺭﺳﺎﻝ ﻳﻚ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻭ ﺍﺭﺳﺎﻝ ﺁﻥ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ
ﻭﺟﻮﺩ ﺩﺍﺭﺩ؟
‐8ﭼﻪ ﺗﻔﺎﻭﺕﻫﺎﻳﻲ ﺑﻴﻦ ﺍﺭﺳﺎﻝ ﻳﻚ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﻭ ﺍﺭﺳﺎﻝ ﺁﻥ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ
ﺛﺎﺑﺖ ﻭﺟﻮﺩ ﺩﺍﺭﺩ؟
‐9ﭼﺮﺍ ﺑﻪ ﭘﺎﺭﺍﻣﺘﺮﻱ ﻛﻪ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ »ﻓﻘﻂ ﺧﻮﺍﻧﺪﻧﻲ« ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ؟
ﭼﺮﺍ ﺑﻪ ﭘﺎﺭﺍﻣﺘﺮﻱ ﻛﻪ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ »ﺧﻮﺍﻧﺪﻧﻲ‐ﻧﻮﺷﺘﻨﻲ« ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ؟
‐10ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﺍﻋﻼﻥ ﺯﻳﺮ ﻫﺴﺖ؟
;)int f(int a, int b=0, int c
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ ﭼﮕﻮﻧﻪ ﻳﻚ ﺗﺎﺑﻊ voidﺑﺎ ﻳﻚ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺭﺟﺎﻉ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﻳﻚ ﺗﺎﺑﻊ ﻏﻴﺮ
voidﺑﺎ ﻳﻚ ﭘﺎﺭﺍﻣﺘﺮ ﻣﻘﺪﺍﺭ ﺗﺒﺪﻳﻞ ﮔﺮﺩﺩ.
‐2ﺑﺮﻧﺎﻣﻪﺍﻱ ﺷﺒﻴﻪ ﻣﺜﺎﻝ 5‐2ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺻﺤﺖ ﺭﺍﺑﻂۀ ﻣﺜﻠﺜﺎﺗﻲ cos 2 x = 2 cos 2 x − 1
ﺭﺍ ﺗﺤﻘﻴﻖ ﻛﻨﺪ.
‐3ﺑﺮﻧﺎﻣﻪﺍﻱ ﺷﺒﻴﻪ ﻣﺜﺎﻝ 5‐2ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺻﺤﺖ ﺭﺍﺑﻂۀ ﻣﺜﻠﺜﺎﺗﻲ cos 2 x + sin 2 x = 1ﺭﺍ
ﺗﺤﻘﻴﻖ ﻛﻨﺪ.
‐4ﺑﺮﻧﺎﻣﻪﺍﻱ ﺷﺒﻴﻪ ﻣﺜﺎﻝ 5‐2ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺻﺤﺖ ﺗﺴﺎﻭﻱ ) b n = e( n log bﺭﺍ ﺗﺤﻘﻴﻖ ﻛﻨﺪ.
‐5ﺗﺎﺑﻊ )( minﺭﺍ ﮐﻪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ ،ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﺯ
ﻣﻴﺎﻥ ﭼﻬﺎﺭ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ،ﻛﻮﭼﻚﺗﺮﻳﻦ ﻋﺪﺩ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ:
;)int min(int,int,int,int
171 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
‐6ﺗﺎﺑﻊ )( maxﺭﺍ ﮐﻪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺎ
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ ) max(int,intﻣﺜﺎﻝ 5‐5ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﺪﺩ ﺩﺭ ﺑﻴﻦ ﭼﻬﺎﺭ ﻋﺪﺩ
ﺻﺤﻴﺢ ﺩﺍﺩﻩ ﺷﺪﻩ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
;)int max(int,int,int,int
‐7ﺗﺎﺑﻊ )( minﮐﻪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺎ
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ ) min(int,intﮐﻮﭼﮏﺗﺮﻳﻦ ﻋﺪﺩ ﺭﺍ ﺍﺯ ﻣﻴﺎﻥ ﭼﻬﺎﺭ ﻋﺪﺩ ﺻﺤﻴﺢ
ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺑﻪ ﺁﻥ ،ﭘﻴﺪﺍ ﮐﺮﺩﻩ ﻭ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
;)int main(int,int,int,int
‐8ﺗﺎﺑﻊ )( averageﺭﺍ ﻛﻪ ﻣﻴﺎﻧﮕﻴﻦ ﭼﻬﺎﺭ ﻋﺪﺩ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ،ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ
ﻛﻨﻴﺪ:
)float average(float x1, float x2, float x3, float x4
‐9ﺗﺎﺑﻊ )( averageﺭﺍ ﮐﻪ ﻣﻴﺎﻧﮕﻴﻦ ﺣﺪﺍﮐﺜﺮ ﭼﻬﺎﺭ ﻋﺪﺩ ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ ،ﻧﻮﺷﺘﻪ ﻭ
ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ:
)float average(float x1, float x2 =0, float x3=0, float x4=0
‐10ﺗﺎﺑﻊ ﻓﺎﮐﺘﻮﺭﻳﺎﻝ )( factﺭﺍ ﺑﺎ ﻳﻚ ﺣﻠﻖۀ forﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻛﻨﻴﺪ)ﻣﺜﺎﻝ 4‐9ﺭﺍ
ﺑﺒﻴﻨﻴﺪ( .ﻣﺸﺨﺺ ﮐﻨﻴﺪ ﮐﻪ ﭼﻪ ﻣﻘﺪﺍﺭﻱ ﺍﺯ nﻣﻮﺟﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ) fact(nﺳﺮﺭﻳﺰ ﺷﻮﺩ.
‐11ﻣﻮﺛﺮﺗﺮﻳﻦ ﻃﺮﻳﻖ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺐۀ ﺟﺎﻳﮕﺸﺖ ﺗﺎﺑﻊ ) p(n,kﻓﺮﻣﻮﻝ ﺯﻳﺮ ﺍﺳﺖ:
)P (n, k ) = n(n − 1)(n − 2)...(n − k + 2)(n − k + 1
ﻳﻌﻨﻲ ﺣﺎﺻﻞﺿﺮﺏ kﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺯ nﺗﺎ . n-k+1ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺭﺍﺑﻄﻪ ،ﺗﺎﺑﻊ
)( permﻣﺜﺎﻝ 5‐10ﺭﺍ ﺑﺎﺯﻧﻮﻳﺴﻲ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ.
‐12ﺗﺎﺑﻊ ﺗﺮﻛﻴﺐ ) c(n,kﺗﻌﺪﺍﺩ ﺯﻳﺮﻣﺠﻤﻮﻋﻪﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ )ﻧﺎﻣﺮﺗﺐ( kﻋﻨﺼﺮﻱ ﮐﻪ
ﻣﻤﮑﻦ ﺍﺳﺖ ﺍﺯ ﻳﮏ ﻣﺠﻤﻮﻉۀ nﻋﻨﺼﺮﻱ ﺳﺎﺧﺘﻪ ﺷﻮﺩ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺎ ﺭﺍﺑﻂۀ
ﺯﻳﺮ ﺑﻴﺎﻥ ﻣﻲﺷﻮﺩ:
!n
= ) C ( n, k
!) k!(n − k
ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ.
‐13ﺗﺎﺑﻊ ﺗﺮﮐﻴﺐ ) c(n,kﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺭﺍﺑﻂۀ ﺯﻳﺮ ﺑﻴﺎﻥ ﻧﻤﻮﺩ:
) P ( n, k
= ) C ( n, k
!k
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 172
ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺭﺍﺑﻄﻪ ،ﺑﺮﻧﺎﻡۀ ﻣﺴﺎﻝۀ 5‐13ﺭﺍ ﺑﺎﺯﻧﻮﻳﺴﻲ ﮐﺮﺩﻩ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ.
‐14ﺭﻭﺵ ﻣﻮﺛﺮﺗﺮ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺐۀ ) c(n,kﺭﺍﺑﻂۀ ﺯﻳﺮ ﺍﺳﺖ:
C (n, k ) = ((((((n / 1)(n − 1)) / 2)(n − 2)) / 3)...(n − k + 2)) /(k − 1))(n − k + 1)) / k
ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﻪ ﻃﻮﺭ ﻣﺘﻨﺎﻭﺏ ﺿﺮﺏ ﻭ ﺗﻘﺴﻴﻢ ﻣﻲﺷﻮﺩ ،ﻫﺮ ﺩﻓﻌﻪ ﺑﺎ ﻳﮏ ﻭﺍﺣﺪ ﮐﻢﺗﺮ ﺍﺯ ﻣﻘﺪﺍﺭ
ﻓﻌﻠﻲ nﺿﺮﺏ ﻣﻲﺷﻮﺩ ﻭ ﺑﺮ ﻳﮏ ﻭﺍﺣﺪ ﺑﻴﺸﺘﺮ ﺍﺯ ﻣﻘﺪﺍﺭ ﻗﺒﻠﻲ ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ ﻳﮏ ،ﺗﻘﺴﻴﻢ
ﻣﻲﺷﻮﺩ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺭﺍﺑﻂۀ ﻓﻮﻕ ،ﺗﺎﺑﻊ ﻣﺴﺎﻝۀ 5‐13ﺭﺍ ﺑﺎﺯﻧﻮﻳﺴﻲ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ.
ﺭﺍﻫﻨﻤﺎﻳﻲ :ﻣﺎﻧﻨﺪ ﻣﺴﺎﻝۀ 5‐12ﺍﺯ ﺣﻠﻖۀ forﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﺪ.
‐15ﻣﺜﻠﺚ ﺧﻴﺎﻡ ﻳﻚ ﺁﺭﺍﻱۀ ﺳﻪﮔﻮﺵ ﺍﺯ ﺍﻋﺪﺍﺩ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
1
1 1
1 2 1
1 1 3 3
4 16 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
ﻫﺮ ﻋﺪﺩ ﺩﺭ ﻣﺜﻠﺚ ﺧﻴﺎﻡ ﻳﻜﻲ ﺍﺯ ﺗﺮﻛﻴﺒﺎﺕ ) c(n,kﺍﺳﺖ )ﺑﻪ ﻣﺴﺎﻟﻪ 5‐13ﻧﮕﺎﻩ ﻛﻨﻴﺪ(.
ﺍﮔﺮ ﺭﺩﻳﻒﻫﺎ ﻭﺳﺘﻮﻥﻫﺎ ﺭﺍ ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ 0ﺷﻤﺎﺭﺵ ﻛﻨﻴﻢ ،ﻋﺪﺩ ﻭﺍﻗﻊ ﺩﺭ ﺭﺩﻳﻒ nﻭ ﺳﺘﻮﻥ k
ﺑﺮﺍﺑﺮ ﺑﺎ ) c(n,kﺍﺳﺖ .ﺑﻪ ﻋﻨﻮﺍﻥ ﻣﺜﺎﻝ ﻋﺪﺩ c(6,2) = 15ﺩﺭ ﺭﺩﻳﻒ ﺷﻤﺎﺭﻩ 6ﻭ
ﺳﺘﻮﻥ ﺷﻤﺎﺭﻩ 2ﺍﺳﺖ .ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ ﻣﺴﺎﻟﻪ 5‐14ﻳﮏ ﻣﺜﻠﺚ
ﺧﻴﺎﻡ ﺩﻭﺍﺯﺩﻩ ﺭﺩﻳﻔﻲ ﭼﺎﭖ ﻛﻨﺪ.
‐16ﺗﺎﺑﻊ )( digitﮐﻪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ:
;)int digit(int n, int k
ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﻗﻢ kﺍﻡ ﻋﺪﺩ ﺻﺤﻴﺢ nﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ nﻋﺪﺩ ﺻﺤﻴﺢ 29415
ﺑﺎﺷﺪ ،ﺗﺎﺑﻊ) digit(n,0ﺭﻗﻢ 5ﺭﺍ ﺑﺎﺯﻣﻲﮔﺮﺩﺍﻧﺪ ﻭ ﻓﺮﺍﺧﻮﺍﻧﻲ ) digit(n,2ﺭﻗﻢ
4ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺭﻗﻢﻫﺎ ﺍﺯ ﺭﺍﺳﺖ ﺑﻪ ﭼﭗ ﻭ ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ 0ﺷﻤﺎﺭﺵ
ﻣﻲﺷﻮﻧﺪ.
‐17ﺗﺎﺑﻌﻲ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ ﻛﻪ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺍﻗﻠﻴﺪﺱ ﺭﺍ ﺑﺮﺍﻱ ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻥ
ﺑﺰﺭﮒﺗﺮﻳﻦ ﻣﻘﺴﻮﻡﻋﻠﻴﻪ ﻣﺸﺘﺮﻙ ﺩﻭ ﻋﺪﺩ ﺻﺤﻴﺢ ﻣﺜﺒﺖ ﺩﺍﺩﻩ ﺷﺪﻩ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﺩ )ﺑﻪ
ﻣﺴﺄﻝۀ 11ﺍﺯ ﻓﺼﻞ ﭼﻬﺎﺭﻡ ﻧﮕﺎﻩ ﻛﻨﻴﺪ(
173 ﻓﺼﻞ ﭘﻨﺠﻢ /ﺗﻮاﺑﻊ
6‐1ﻣﻘﺪﻣﻪ
ﻳﮏ ﻣﺘﻐﻴﺮ ﺑﺨﺸﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺍﺳﺖ ﮐﻪ ﻳﮏ ﻧﺎﻡ ﺩﺍﺭﺩ ﻭ ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺩﺭ ﺁﻥ
ﺫﺧﻴﺮﻩ ﮐﺮﺩ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﭘﺮﺩﺍﺯﺵ ﺩﺍﺩﻩﻫﺎ ﭘﺮﺩﺍﺧﺖ .ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ
ﮐﻮﭼﮏ ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﺘﻮﺍﻧﻴﻢ ﮐﻞ ﭘﺮﺩﺍﺯﺵ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎ ﻋﻤﻠﻲ ﮐﻨﻴﻢ ﻭﻟﻲ ﺩﺭ
ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ ﻓﺮﺍﻭﺍﻧﻲ ﺭﺍ ﭘﺮﺩﺍﺯﺵ ﻣﻲﮐﻨﻨﺪ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﻌﻤﻮﻟﻲ ﮐﺎﺭ
ﻋﺎﻗﻼﻧﻪﺍﻱ ﻧﻴﺴﺖ ﺯﻳﺮﺍ ﺩﺭ ﺑﺴﻴﺎﺭﻱ ﺍﺯ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪﻫﺎ »ﭘﺮﺩﺍﺯﺵ ﺩﺳﺘﻪﺍﻱ« ﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ ﺑﻪ
ﺍﻳﻦ ﻣﻌﻨﻲ ﮐﻪ ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﺩﺍﺩﻩﻫﺎﻱ ﻣﺮﺗﺒﻂ ﺑﺎ ﻫﻢ ﺩﺭ ﺣﺎﻓﻈﻪ ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ﭘﺲ ﺍﺯ
ﭘﺮﺩﺍﺯﺵ ،ﮐﻞ ﺍﻳﻦ ﻣﺠﻤﻮﻋﻪ ﺍﺯ ﺣﺎﻓﻈﻪ ﺧﺎﺭﺝ ﻣﻲﺷﻮﺩ ﻭ ﻣﺠﻤﻮﻉۀ ﺑﻌﺪﻱ ﺩﺭ ﺣﺎﻓﻈﻪ
ﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ ﻗﺮﺍﺭ ﺑﺎﺷﺪ ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﻌﻤﻮﻟﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ ﺑﻴﺸﺘﺮ
ﻭﻗﺖ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺻﺮﻑ ﭘﺮ ﻭ ﺧﺎﻟﻲ ﮐﺮﺩﻥ ﺍﻧﺒﻮﻫﻲ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎ ﻣﻲﺷﻮﺩ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺩﺭ
ﺑﻴﺸﺘﺮ ﺯﺑﺎﻥﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ »ﺁﺭﺍﻳﻪﻫﺎ «1ﺗﺪﺍﺭﮎ ﺩﻳﺪﻩ ﺷﺪﻩﺍﻧﺪ .ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﺘﻐﻴﺮﻱ
ﺗﺼﻮﺭ ﮐﺮﺩ ﮐﻪ ﻳﮏ ﻧﺎﻡ ﺩﺍﺭﺩ ﻭﻟﻲ ﭼﻨﺪﻳﻦ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﻪ ﻃﻮﺭ ﻫﻢﺯﻣﺎﻥ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﻧﻤﺎﻳﺪ.
1 – Arrays
175 ﻓﺼﻞ ﺷﺸﻢ /ﺁراﻳﻪهﺎ
ﭼﻨﺎﻧﭽﻪ ﺑﻌﺪ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ ،ﻭﻳﺮﺍﻳﺶ ﻣﺤﺘﻮﻳﺎﺕ ﺁﺭﺍﻳﻪﻫﺎ ﺑﺴﻴﺎﺭ ﺁﺳﺎﻥ ﺍﺳﺖ ﻭ ﭘﺮﺩﺍﺯﺵ ﺩﺍﺩﻩﻫﺎ
ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﺭﺍﻳﻪﻫﺎ ﺳﺮﻳﻊﺗﺮ ﻭ ﺭﺍﺣﺖﺗﺮ ﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ.
ﻳﮏ ﺁﺭﺍﻳﻪ ،ﻳﻚ ﺯﻧﺠﻴﺮﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺍﺳﺖ ﻛﻪ ﻫﻤﻪ ﺍﺯ ﻳﻚ ﻧﻮﻉ ﻫﺴﺘﻨﺪ .ﺑﻪ ﺍﻳﻦ
ﻣﺘﻐﻴﺮﻫﺎ »ﺍﻋﻀﺎﻱ ﺁﺭﺍﻳﻪ« ﻣﻲﮔﻮﻳﻨﺪ .ﻫﺮ ﻋﻀﻮ ﺁﺭﺍﻳﻪ ﺑﺎ ﻳﮏ ﺷﻤﺎﺭﻩ ﻣﺸﺨﺺ ﻣﻲﺷﻮﺩ ﮐﻪ ﺑﻪ
ﺍﻳﻦ ﺷﻤﺎﺭﻩ »ﺍﻳﻨﺪﮐﺲ «2ﻳﺎ »ﺯﻳﺮﻧﻮﻳﺲ« ﻣﻲﮔﻮﻳﻨﺪ )ﻧﺎﻡ ﺯﻳﺮﻧﻮﻳﺲ ﺍﺯ ﻧﻤﺎﻳﺶ ﺭﻳﺎﺿﻲ ﺁﺭﺍﻳﻪﻫﺎ
ﺍﻗﺘﺒﺎﺱ ﺷﺪﻩ( .ﺍﻳﻨﺪﮐﺲ ﻣﺤﻞ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻦ ﻫﺮ ﻋﻀﻮ ﺁﺭﺍﻳﻪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﻣﺜﻼ ﺍﮔﺮ ﻧﺎﻡ
ﺁﺭﺍﻳﻪﺍﻱ aﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ] a[0ﻧﺎﻡ ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﻣﻮﻗﻌﻴﺖ ﺻﻔﺮ ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﻭ
] a[1ﻧﺎﻡ ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﻣﻮﻗﻴﺖ 1ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﺩﺍﺭﺩ .ﭘﺲ ﻋﻨﺼﺮ nﺍﻡ ﺁﺭﺍﻳﻪ ﺩﺭ ﻣﺤﻞ
] a[n-1ﻗﺮﺍﺭ ﺩﺍﺭﺩ .ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺷﻤﺎﺭﻩﮔﺬﺍﺭﻱ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺍﺯ ﺻﻔﺮ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ﻭ
ﺑﺮﺍﻱ ﻳﮏ ﺁﺭﺍﻱۀ nﻋﻨﺼﺮﻱ ﺍﻳﻦ ﺷﻤﺎﺭﻩ ﺗﺎ n-1ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ .ﻋﻠﺖ ﺍﻳﻦ ﮐﻪ ﺷﻤﺎﺭﻩﮔﺬﺍﺭﻱ
ﺍﺯ ﺻﻔﺮ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺍﻳﻦ ﺭﻭﺵ ،ﺍﻧﺪﻳﺲ ﻳﮏ ﻋﻨﺼﺮ ﺍﺯ ﺁﺭﺍﻳﻪ ،ﻓﺎﺻﻞۀ ﺁﻥ
ﻋﻨﺼﺮ ﺍﺯ ﻋﻨﺼﺮ ﺍﻭﻝ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﻣﺜﻼ ] a[3ﺑﻪ ﻋﻨﺼﺮﻱ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﮐﻪ ﺳﻪ ﺧﺎﻧﻪ ﺍﺯ
ﻋﻨﺼﺮ ﺍﻭﻝ ﻳﻌﻨﻲ ] a[0ﻓﺎﺻﻠﻪ ﺩﺍﺭﺩ .ﺍﻳﻦ ﻓﺎﺻﻠﻪﻳﺎﺑﻲ ﺑﻌﺪﻫﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺁﻳﺪ.
ﻋﻨﺎﺻﺮ ﻳﮏ ﺁﺭﺍﻳﻪ ﺩﺭ ﺧﺎﻧﻪﻫﺎﻱ ﭘﺸﺖ ﺳﺮ ﻫﻢ ﺩﺭ ﺣﺎﻓﻈﻪ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﻧﺪ .ﺑﻪ ﺍﻳﻦ
ﺗﺮﺗﻴﺐ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﺨﺸﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺗﺼﻮﺭ ﮐﺮﺩ ﮐﻪ ﺍﻳﻦ ﺑﺨﺶ ﺧﻮﺩ ﺑﻪ ﻗﺴﻤﺖﻫﺎﻱ
ﻣﺴﺎﻭﻱ ﺗﻘﺴﻴﻢ ﺷﺪﻩ ﻭ ﻫﺮ ﻗﺴﻤﺖ ﺑﻪ ﻳﮏ ﻋﻨﺼﺮ ﺗﻌﻠﻖ ﺩﺍﺭﺩ .ﺷﮑﻞ
0 17.50
1 19.00 ﻣﻘﺎﺑﻞ ﺁﺭﺍﻱۀ aﮐﻪ ﭘﻨﺞ ﻋﻨﺼﺮ ﺩﺍﺭﺩ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﻋﻨﺼﺮ ]a[0
2 16.75 ﺣﺎﻭﻱ ﻣﻘﺪﺍﺭ 17.5ﻭ ﻋﻨﺼﺮ ] a[1ﺣﺎﻭﻱ 19.0ﻭ ﻋﻨﺼﺮ ]a[4
3 15.00
4 18.00 ﺣﺎﻭﻱ ﻣﻘﺪﺍﺭ 18.0ﺍﺳﺖ .ﺍﻳﻦ ﻣﻘﺪﺍﺭﻫﺎ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻧﻤﺮﺍﺕ ﻳﮏ
ﺩﺍﻧﺸﺠﻮ ﺩﺭ ﻳﮏ ﻧﻴﻢﺳﺎﻝ ﺗﺤﺼﻴﻠﻲ ﺭﺍ ﻧﺸﺎﻥ ﺩﻫﻨﺪ.
6‐2ﭘﺮﺩﺍﺯﺵ ﺁﺭﺍﻳﻪﻫﺎ
ﺁﺭﺍﻳﻪﻫﺎ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﺜﻞ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﻌﻤﻮﻟﻲ ﺗﻌﺮﻳﻒ ﻭ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ .ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ
ﺁﺭﺍﻳﻪ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﺮﮐﺐ ﺍﺳﺖ ﻭ ﺑﺮﺍﻱ ﺩﺳﺘﻴﺎﺑﻲ ﺑﻪ ﻫﺮ ﻳﮏ ﺍﺯ ﺧﺎﻧﻪﻫﺎﻱ ﺁﻥ ﺑﺎﻳﺪ ﺍﺯ ﺍﻳﻨﺪﮐﺲ
ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﻮﺩ.
1 – Index
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 176
ﺧﻂ ﺩﻭﻡ ،ﻳﮏ ﺁﺭﺍﻱۀ ﺳﻪ ﻋﻨﺼﺮﻱ ﺍﺯ ﻧﻮﻉ intﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ .ﺳﻪ ﺧﻂ ﺑﻌﺪﻱ ،ﻣﻘﺎﺩﻳﺮﻱ
ﺭﺍ ﺑﻪ ﺍﻳﻦ ﺳﻪ ﻋﻨﺼﺮ ﺗﺨﺼﻴﺺ ﻣﻲﺩﻫﺪ ﻭ ﺳﻪ ﺧﻂ ﺁﺧﺮ ﻫﻢ ﻣﻘﺪﺍﺭ ﻫﺮ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﭼﺎﭖ
ﻣﻲﮐﻨﺪ.
ﺩﻭﻣﻴﻦ ﺧﻂ ﺑﺮﻧﺎﻣﻪ ،ﺛﺎﺑﺘﻲ ﺑﻪ ﻧﺎﻡ SIZEﺍﺯ ﻧﻮﻉ intﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﻭ ﻣﻘﺪﺍﺭ 5ﺭﺍ
ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ .ﺧﻂ ﺳﻮﻡ ﻳﮏ ﺁﺭﺍﻳﻪ ﺑﻪ ﻧﺎﻡ aﻭ ﺑﺎ ﭘﻨﺞ ﻋﻨﺼﺮ ﺍﺯ ﻧﻮﻉ float
ﺗﻌﺮﻳﻒ ﻣﻲﻧﻤﺎﻳﺪ .ﺳﭙﺲ ﺍﻭﻟﻴﻦ ﺣﻠﻖۀ forﭘﻨﺞ ﻋﻨﺼﺮ ﺭﺍ ﺑﻪ ﺩﺍﺧﻞ ﺁﺭﺍﻳﻪ ﻣﻲﺧﻮﺍﻧﺪ ﻭ
ﺩﻭﻣﻴﻦ ﺣﻠﻖۀ forﺁﻥ ﭘﻨﺞ ﻋﻨﺼﺮ ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﻣﻌﮑﻮﺱ ﭼﺎﭖ ﻣﻲﮐﻨﺪ.
ﻣﺜﺎﻝ ﻓﻮﻕ ﻧﺸﺎﻥ ﺩﺍﺩ ﮐﻪ ﻳﮏ ﺁﺭﺍﻳﻪ ﭼﻄﻮﺭ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ .ﻧﺤﻮ ﮐﻠﻲ ﺑﺮﺍﻱ ﺍﻋﻼﻥ ﺁﺭﺍﻳﻪ
ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
;]type array_name[array_size
ﻋﺒﺎﺭﺕ typeﻧﻮﻉ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ array_name .ﻧﺎﻡ ﺁﺭﺍﻳﻪ ﺍﺳﺖ ﻭ
array_sizeﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﺎﻳﺪ ﻳﮏ ﻋﺪﺩ ﺛﺎﺑﺖ
ﺻﺤﻴﺢ ﺑﺎﺷﺪ ﻭ ﺣﺘﻤﺎ ﺑﺎﻳﺪ ﺩﺍﺧﻞ ﮐﺮﻭﺷﻪ ][ ﻗﺮﺍﺭ ﺑﮕﻴﺮﺩ.
ﺩﺭ ﺧﻂ ﺩﻭﻡ ﺍﺯ ﻣﺜﺎﻝ 6‐1ﺁﺭﺍﻳﻪﺍﻱ ﺑﻪ ﻧﺎﻡ aﺑﺎ ﺳﻪ ﻋﻨﺼﺮ ﺍﻋﻼﻥ ﺷﺪﻩ ﮐﻪ ﺍﻳﻦ
ﻋﻨﺎﺻﺮ ﺍﺯ ﻧﻮﻉ intﻫﺴﺘﻨﺪ .ﺩﺭ ﺧﻂ ﺳﻮﻡ ﺍﺯ ﻣﺜﺎﻝ 6‐2ﺁﺭﺍﻳﻪﺍﻱ ﺑﻪ ﻧﺎﻡ aﺑﺎ ﺗﻌﺪﺍﺩ
ﻋﻨﺎﺻﺮﻱ ﮐﻪ ﺛﺎﺑﺖ SIZEﻣﺸﺨﺺ ﻣﻲﻧﻤﺎﻳﺪ ﺍﻋﻼﻥ ﺷﺪﻩ ﮐﻪ ﻋﻨﺎﺻﺮ ﺁﻥ ﺍﺯ ﻧﻮﻉ double
ﻫﺴﺘﻨﺪ .ﻣﻌﻤﻮﻻ ﺑﻬﺘﺮ ﺍﺳﺖ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺛﺎﺑﺖﻫﺎ ﻣﺸﺨﺺ ﮐﻨﻴﻢ ﺗﺎ
ﺑﻌﺪ ﺑﺘﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻫﻤﺎﻥ ﺛﺎﺑﺖ ﺩﺭ ﺣﻠﻖۀ forﺁﺭﺍﻳﻪ ﺭﺍ ﭘﻴﻤﺎﻳﺶ ﻧﻤﺎﻳﻴﻢ.
6‐3ﻣﻘﺪﺍﺭﺩﻫﻲ ﺁﺭﺍﻳﻪﻫﺎ
ﺩﺭ C++ﻣﻲﺗﻮﺍﻧﻴﻢ ﻳﮏ ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ،ﺍﻋﻼﻥ ﻭ
ﻣﻘﺪﺍﺭﮔﺬﺍﺭﻱ ﮐﻨﻴﻢ:
;}float a[] = {22.2,44.4.66.6
ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﻣﻘﺎﺩﻳﺮ ﺩﺍﺧﻞ ﻓﻬﺮﺳﺖ ﺑﻪ ﻫﻤﺎﻥ ﺗﺮﺗﻴﺒﻲ ﮐﻪ ﭼﻴﺪﻩ ﺷﺪﻩﺍﻧﺪ
a ﺩﺭﻭﻥ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﻧﺪ .ﺍﻧﺪﺍﺯﻩ ﺁﺭﺍﻳﻪ ﻧﻴﺰ ﺑﺮﺍﺑﺮ ﺑﺎ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ
0 22.2
1 44.4
ﻣﻮﺟﻮﺩ ﺩﺭ ﻓﻬﺮﺳﺖ ﺧﻮﺍﻫﺪ ﺑﻮﺩ .ﭘﺲ ﻫﻤﻴﻦ ﺧﻂ ﻣﺨﺘﺼﺮ ،ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ
2 66.6 ﻧﻮﻉ floatﻭ ﺑﺎ ﻧﺎﻡ aﻭ ﺑﺎ ﺗﻌﺪﺍﺩ ﺳﻪ ﻋﻨﺼﺮ ﺍﻋﻼﻥ ﮐﺮﺩﻩ ﻭ ﻫﺮ ﺳﻪ
ﻋﻨﺼﺮ ﺭﺍ ﺑﺎ ﻣﻘﺪﺍﺭﻫﺎﻱ ﺩﺭﻭﻥ ﻓﻬﺮﺳﺖ ،ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﮐﻨﺪ.
ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ،ﺁﺭﺍﻱۀ aﺭﺍ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩﻩ ﻭ ﺳﭙﺲ ﻣﻘﺪﺍﺭ ﻫﺮ ﻋﻨﺼﺮ ﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ:
)(int main
;} { float a[] = { 22.2, 44.4, 66.6
;)int size = sizeof(a)/sizeof(float
)for (int i=0; i<size; i++
;cout << "\ta[" << i << "] = " << a[i] << endl
}
a[0] = 22.2
a[1] = 44.4
a[2] = 66.6
ﺩﻭﻣﻴﻦ ﺧﻂ ،ﺁﺭﺍﻱۀ aﺭﺍ ﺑﻪ ﻫﻤﺎﻥ ﺻﻮﺭﺗﻲ ﮐﻪ ﺩﺭ ﺑﺎﻻ ﺁﻣﺪ ﺍﻋﻼﻥ ﻭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﮐﻨﺪ .ﺩﺭ
ﺧﻂ ﺳﻮﻡ ،ﺍﺯ ﺗﺎﺑﻊ )( sizeofﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﻧﺪﺍﺯۀ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺭﺳﺎﻟﻲ ﺑﻪ ﺁﻥ ﺭﺍ
ﺑﺮ ﺣﺴﺐ ﺑﺎﻳﺖ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﻣﻘﺪﺍﺭ ) sizeof(floatﺑﺮﺍﺑﺮ ﺑﺎ 4ﺍﺳﺖ ﺯﻳﺮﺍ ﺩﺭ ﺍﻳﻦ
ﺭﺍﻳﺎﻧﻪ ﻫﺮ ﻣﺘﻐﻴﺮ floatﭼﻬﺎﺭ ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ ﻣﻲﮐﻨﺪ .ﻫﻤﭽﻨﻴﻦ ﻣﻘﺪﺍﺭ
) sizeof(aﺑﺮﺍﺑﺮ ﺑﺎ 12ﺍﺳﺖ ﺯﻳﺮﺍ ﺁﺭﺍﻱۀ ﻣﺬﮐﻮﺭ ﺩﻭﺍﺯﺩﻩ ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ
ﻧﻤﻮﺩﻩ )ﺳﻪ ﺧﺎﻧﻪ ﮐﻪ ﻫﺮ ﮐﺪﺍﻡ ﭼﻬﺎﺭ ﺑﺎﻳﺖ ﺍﺳﺖ( .ﺣﺎﺻﻞ ﺗﻘﺴﻴﻢ ﺍﻳﻦ ﺩﻭ ﻣﻘﺪﺍﺭ ،ﺗﻌﺪﺍﺩ
ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲﻧﻤﺎﻳﺪ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺭﻭﺵ ﻫﻤﻴﺸﻪ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ
ﻳﮏ ﺁﺭﺍﻳﻪ ﺭﺍ ﻓﻘﻂ ﺑﺎ ﺩﺍﻧﺴﺘﻦ ﻧﻮﻉ ﺁﺭﺍﻳﻪ ﻣﺤﺎﺳﺒﻪ ﮐﻨﻴﻢ .ﺣﺎﺻﻞ ﺗﻘﺴﻴﻢ
) sizeof(a)/sizeof(floatﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ sizeﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﺗﺎ ﺍﺯ ﺍﻳﻦ ﻣﻘﺪﺍﺭ
ﺩﺭ ﺣﻠﻖۀ forﺑﺮﺍﻱ ﭘﻴﻤﺎﻳﺶ ﻭ ﭼﺎﭖ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ aﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ.
ﺍﻋﻼﻥ ﺑﺎﻻ ﺁﺭﺍﻱۀ aﺭﺍ ﺑﺎ ﻫﻔﺖ ﻋﻨﺼﺮ ﺍﺯ ﻧﻮﻉ floatﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ .ﺳﻪ ﻋﻨﺼﺮ ﺍﻭﻝ ﺍﻳﻦ
ﺁﺭﺍﻳﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻓﻬﺮﺳﺖ ﻣﺬﮐﻮﺭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﺷﻮﻧﺪ ﻭ ﺩﺭ ﭼﻬﺎﺭ ﻋﻨﺼﺮ ﺑﺎﻗﻲﻣﺎﻧﺪﻩ ﻣﻘﺪﺍﺭ
ﺻﻔﺮ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ.
ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺗﻌﺪﺍﺩ ﻣﻘﺎﺩﻳﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺒﺎﻳﺪ ﺍﺯ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ
ﺑﻴﺸﺘﺮ ﺑﺎﺷﺪ:
;} float a[3] = { 22.2, 44.4, 66.6, 88.8 !// ERROR: too many values
ﻳﻚ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﻃﻮﺭ ﮐﺎﻣﻞ ﺑﺎ ﺻﻔﺮ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﮐﻨﻴﻢ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺳﻪ
ﺍﻋﻼﻥ ﺯﻳﺮ ﺑﺎ ﻫﻢ ﺑﺮﺍﺑﺮﻧﺪ:
;} float a[ ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0
;} float a[9] = { 0, 0
;} float a[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0
ﺍﻣﺎ ﻣﻄﻠﺐ ﻓﻮﻕ ﺍﺻﻼ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﻲ ﻧﻴﺴﺖ ﮐﻪ ﺍﺯ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻧﺸﻮﺩ .ﺩﺭﺳﺖ
ﻣﺜﻞ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻌﻤﻮﻟﻲ ،ﺍﮔﺮ ﻳﮏ ﺁﺭﺍﻳﻪ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﻧﺸﻮﺩ ،ﻋﻨﺎﺻﺮ ﺁﻥ ﺣﺎﻭﻱ ﻣﻘﺎﺩﻳﺮ
ﺯﺑﺎﻟﻪ ﺧﻮﺍﻫﺪ ﺑﻮﺩ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 180
ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﻣﻘﺎﺩﻳﺮ ﺩﺭﻭﻥ ﻳﻚ ﺁﺭﺍﻱۀ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ ﻣﻤﻜﻦ ﺍﺳﺖ ﺻﻔﺮ ﺑﺎﺷﺪ ﻳﺎ ﻧﺒﺎﺷﺪ،
ﺑﺴﺘﻪ ﺑﻪ ﺍﻳﻦ ﮐﻪ ﺩﺭ ﺁﻥ ﻗﺴﻤﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﻗﺒﻼ ﭼﻪ ﺑﻮﺩﻩ ﺍﺳﺖ.
ﺁﺭﺍﻳﻪﻫﺎ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩ ﺍﻣﺎ ﻧﻤﻲﺗﻮﺍﻥ
ﻣﻘﺪﺍﺭ ﺁﻥﻫﺎ ﺭﺍ ﺑﻪ ﻳﮑﺪﻳﮕﺮ ﺗﺨﺼﻴﺺ ﺩﺍﺩ:
;} 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
C++ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ .ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻳﻨﺪﮐﺲ ﻳﮏ ﺁﺭﺍﻳﻪ ﻫﻨﮕﺎﻡ ﺩﺳﺘﻴﺎﺑﻲ
ﻣﻲﺗﻮﺍﻧﺪ ﺑﻴﺸﺘﺮ ﺍﺯ ﻋﻨﺎﺻﺮ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺑﺮﺍﻱ ﺁﻥ ﺑﺎﺷﺪ ﻭ ﺑﺎﺯ ﻫﻢ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﺧﻄﺎﻳﻲ
ﮔﺮﻓﺘﻪ ﺷﻮﺩ ،ﺑﺮﻧﺎﻣﻪ ﺍﺩﺍﻣﻪ ﻳﺎﺑﺪ.
ﺁﺭﺍﻳﻪﺍﻱ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ،ﭼﻬﺎﺭ ﻋﻨﺼﺮ ﺩﺍﺭﺩ ﻭﻟﻲ ﺗﻼﺵ ﻣﻲﺷﻮﺩ ﺑﻪ ﻫﻔﺖ
ﻋﻨﺼﺮ ﺩﺳﺘﻴﺎﺑﻲ ﺷﻮﺩ .ﺳﻪ ﻣﻘﺪﺍﺭ ﺁﺧﺮ ﻭﺍﻗﻌﺎ ﺟﺰﻭ ﺁﺭﺍﻳﻪ ﻧﻴﺴﺘﻨﺪ ﻭ ﻓﻘﻂ ﺳﻠﻮﻝﻫﺎﻳﻲ ﺍﺯ
ﺣﺎﻓﻈﻪﺍﻧﺪ ﮐﻪ ﺩﻗﻴﻘﺎ ﺑﻌﺪ ﺍﺯ ﻋﻨﺼﺮ ﭼﻬﺎﺭﻡ ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪﺍﻧﺪ .ﺍﻳﻦ ﺳﻠﻮﻝﻫﺎ ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ
ﺯﺑﺎﻟﻪ ﻫﺴﺘﻨﺪ.
ﺍﮔﺮ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﺍﺯ ﻣﺤﺪﻭﺩۀ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺑﺮﺍﻱ ﺁﻥ ﺗﺠﺎﻭﺯ ﮐﻨﺪ ،ﻣﻤﮑﻦ ﺍﺳﺖ
ﻧﺎﺧﻮﺍﺳﺘﻪ ﻣﻘﺪﺍﺭ ﺳﺎﻳﺮ ﻣﺘﻐﻴﺮﻫﺎ ﺩﺳﺖﮐﺎﺭﻱ ﺷﻮﻧﺪ ﻭ ﺍﻳﻦ ﺑﺎﻋﺚ ﺑﺮﻭﺯ ﻓﺎﺟﻌﻪ ﺷﻮﺩ .ﺑﻪ ﻣﺜﺎﻝ
ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ.
)(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 !// ERROR: index is out of bounds
;cout << "x = " << x << endl
}
x = 88.8
ﺣﺎﻓﻆۀ ﺁﺭﺍﻳﻪ ﺭﺍ ﺫﺧﻴﺮﻩ ﻣﻲﮐﻨﺪ .ﻻﺯﻡ ﻧﻴﺴﺖ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺑﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﮔﻔﺘﻪ ﺷﻮﺩ ﺯﻳﺮﺍ
ﺍﺯ ﺭﻭﻱ ﻧﺸﺎﻧﻲ ﻣﻮﺟﻮﺩ ﺩﺭ aﻣﻲﺗﻮﺍﻥ ﻋﻨﺎﺻﺮ ﺭﺍ ﺑﺎﺯﻳﺎﺑﻲ ﻧﻤﻮﺩ .ﺑﻪ ﻫﻤﻴﻦ ﻃﺮﻳﻖ ﻣﻲﺗﻮﺍﻥ ﻳﮏ
ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﮐﺮﺩ .ﻳﻌﻨﻲ ﻓﻘﻂ ﻧﻮﻉ ﺁﺭﺍﻳﻪ ﻭ ﻧﺸﺎﻧﻲ ﺣﺎﻓﻆۀ ﺁﻥ ﺑﻪ ﻋﻨﻮﺍﻥ ﭘﺎﺭﺍﻣﺘﺮ ﺑﻪ
ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ.
ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮ ﺗﺎﺑﻊ ﻓﻮﻕ ﺑﻪ ﺷﮑﻞ ) (int a[], int nﺍﺳﺖ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻳﻦ
ﺗﺎﺑﻊ ﻳﮏ ﺁﺭﺍﻳﻪ ﺍﺯ ﻧﻮﻉ intﻭ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ intﺩﺭﻳﺎﻓﺖ ﻣﻲﮐﻨﺪ .ﺑﻪ ﺍﻋﻼﻥ ﺍﻳﻦ ﺗﺎﺑﻊ
ﺩﺭ ﺑﺎﻻﻱ ﺗﺎﺑﻊ )( mainﻧﮕﺎﻩ ﮐﻨﻴﺪ .ﻧﺎﻡ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﺣﺬﻑ ﺷﺪﻩ ﺍﺳﺖ .ﻫﻨﮕﺎﻡ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ
ﻧﻴﺰ ﺍﺯ ﻋﺒﺎﺭﺕ ) sum(a,sizeﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﮐﻪ ﻓﻘﻂ ﻧﺎﻡ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﺷﺪﻩ .ﻧﺎﻡ
ﺁﺭﺍﻳﻪ ﺩﺭ ﺣﻘﻴﻘﺖ ﻧﺸﺎﻧﻲ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺍﺳﺖ )ﻳﻌﻨﻲ ] . (a[0ﺗﺎﺑﻊ ﺍﺯ ﺍﻳﻦ ﻧﺸﺎﻧﻲ ﺑﺮﺍﻱ
ﺩﺳﺘﻴﺎﺑﻲ ﺑﻪ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ .ﻫﻤﭽﻨﻴﻦ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﻧﺸﺎﻧﻲ،
ﻣﺤﺘﻮﻳﺎﺕ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ .ﭘﺲ ﺍﺭﺳﺎﻝ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﺷﺒﻴﻪ ﺍﺭﺳﺎﻝ ﻣﺘﻐﻴﺮ ﺑﻪ
ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺳﺖ .ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺩﻗﺖ ﮐﻨﻴﺪ.
void read(int[],int&;)
void print(int[],int);
int main()
{ const int MAXSIZE=100;
int a[MAXSIZE]={0}, size;
read(a,size);
cout << "The array has " << size << " elements: ";
print(a,size);
}
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] << " ";
}
Enter integers. Terminate with 0:
a[0]: 11
a[1]: 22
a[2]: 33
a[3]: 44
a[4]: 0
The array has 4 elements: 11 22 33 44
ﺩﺭ C++ﺗﻮﺍﺑﻊ ﻗﺎﺩﺭ ﻧﻴﺴﺘﻨﺪ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻱۀ ﺍﺭﺳﺎﻟﻲ ﺭﺍ ﺗﺸﺨﻴﺺ ﺩﻫﻨﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ
ﺑﻪ ﻣﻨﻈﻮﺭ ﺍﺭﺳﺎﻝ ﺁﺭﺍﻳﻪﻫﺎ ﺑﻪ ﺗﺎﺑﻊ ﺍﺯ ﺳﻪ ﻣﺸﺨﺼﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ – 1 :ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ
ﺁﺭﺍﻳﻪ – 2ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ – 3ﻧﻮﻉ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ .ﺗﺎﺑﻊ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺳﻪ ﻋﻨﺼﺮ
ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺗﮏ ﺗﮏ ﺍﻋﻀﺎﻱ ﺁﺭﺍﻳﻪ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﺪ .ﺷﮑﻞ ﮐﺎﺭ ﻫﻢ ﺑﻪ ﺍﻳﻦ ﻃﺮﻳﻖ ﺍﺳﺖ ﮐﻪ ﺑﺎ
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻧﻪ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻣﺤﺘﻮﻳﺎﺕ ﺁﻥ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ .ﺍﺯ ﻃﺮﻓﻲ ﻭﻗﺘﻲ
ﻧﻮﻉ ﻋﻨﺎﺻﺮ ﻣﺸﺨﺺ ﺑﺎﺷﺪ ،ﻣﻌﻠﻮﻡ ﻣﻲﺷﻮﺩ ﮐﻪ ﻫﺮ ﺧﺎﻥۀ ﺁﺭﺍﻳﻪ ﭼﻨﺪ ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ
ﺍﺷﻐﺎﻝ ﻣﻲﮐﻨﺪ .ﭘﺲ ﺍﮔﺮ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﻪ ﺁﺩﺭﺱ ﺧﺎﻥۀ ﺍﻭﻝ ﺍﺿﺎﻓﻪ ﺷﻮﺩ ،ﺁﺩﺭﺱ ﺧﺎﻥۀ ﺩﻭﻡ
ﺑﺪﺳﺖ ﻣﻲﺁﻳﺪ .ﺍﮔﺮ ﻣﻘﺪﺍﺭ ﻣﺬﮐﻮﺭ ﺑﻪ ﺁﺩﺭﺱ ﺧﺎﻥۀ ﺩﻭﻡ ﺍﺿﺎﻓﻪ ﺷﻮﺩ ،ﺧﺎﻥۀ ﺳﻮﻡ ﻣﻌﻠﻮﻡ
ﻣﻲﺷﻮﺩ ﻭ ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﮐﻞ ﺁﺭﺍﻳﻪ ﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﮐﻪ ﺑﺎ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﻣﺠﺰﺍ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ ،ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﺮﺍﻗﺐ ﺑﺎﺷﻴﻢ ﮐﻪ
ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﺍﺯ ﺣﺪ ﻣﺠﺎﺯ ﻓﺮﺍﺗﺮ ﻧﺮﻭﺩ.
ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ ﺁﺭﺍﻳﻪ ،ﻫﻤﺎﻥ ﻧﺎﻡ ﺁﺭﺍﻳﻪ ﺍﺳﺖ .ﭘﺲ ﻭﻗﺘﻲ ﻧﺎﻡ ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ
ﺑﻔﺮﺳﺘﻴﻢ ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻧﻪ ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩﺍﻳﻢ .ﻧﻮﻉ ﺁﺭﺍﻳﻪ ﻧﻴﺰ ﺩﺭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﺍﻋﻼﻥ
ﻣﻲﺷﻮﺩ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﺑﺎ ﺍﻳﻦ ﺩﻭ ﻣﻘﺪﺍﺭ ،ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺁﺭﺍﻳﻪ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ.
ﺑﻪ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 6‐10ﻧﮕﺎﻩ ﮐﻨﻴﺪ .ﺁﺭﺍﻳﻪ aﺑﺎ
0x0064fdbb
0x0064fdbc
100ﻋﻨﺼﺮ ﺍﺯ ﻧﻮﻉ intﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ .ﺑﺎ ﺍﺟﺮﺍﻱ
0x0064fdbd
]a[0
0x0064fdbe
0x0064fdbf
0x0064fdc0
ﮐﺪ ) read(a,sizeﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ ﺁﺭﺍﻳﻪ ﮐﻪ
0x0064fdc1
0x0064fdc2
0x0064fdc3
]a[1
ﺩﺭ aﻗﺮﺍﺭ ﺩﺍﺭﺩ ﺑﻪ ﺗﺎﺑﻊ )( readﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﻫﺮ
0x0064fdc4
0x0064fdc5
0x0064fdc6 ]a[2 ﺑﺎﺭ ﮐﻪ ﺩﺭﻭﻥ ﺗﺎﺑﻊ ﮐﺪ ;] cin >> a[nﺍﺟﺮﺍ ﺷﻮﺩ،
0x0064fdc7
1 – Offset
187 ﻓﺼﻞ ﺷﺸﻢ /ﺁراﻳﻪهﺎ
ﻋﺪﺩﻱ ﺍﺳﺖ ﮐﻪ ﺑﺎﻳﺪ ﺑﻪ ﻧﺸﺎﻧﻲ ﺧﺎﻥۀ ﺍﻭﻝ ﺍﻓﺰﻭﺩﻩ ﺷﻮﺩ ﺗﺎ ﺑﻪ ﺧﺎﻥۀ ﺁﻥ ﻋﻨﺼﺮ ﺑﺮﺳﻴﻢ.
ﺍﺯ ﻫﻢۀ ﮔﻔﺘﻪﻫﺎﻱ ﻓﻮﻕ ﻧﺘﻴﺠﻪ ﻣﻲﺷﻮﺩ ﮐﻪ ﺑﺮﺍﻱ ﺍﺭﺳﺎﻝ ﻳﮏ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﻓﻘﻂ ﮐﺎﻓﻲ
ﺍﺳﺖ ﻧﺎﻡ ﺁﺭﺍﻳﻪ ﻭ ﺍﻧﺪﺍﺯۀ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﺷﻮﺩ .ﺑﺎﺯ ﻫﻢ ﺗﺎﮐﻴﺪ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﻧﺎﻡ ﺁﺭﺍﻳﻪ،
ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﺩﺭ ﺧﻮﺩ ﺩﺍﺭﺩ .ﻣﺜﻼ ﺍﮔﺮ ﺁﺭﺍﻱۀ aﺩﺭ ﺁﺩﺭﺱ 0x0064fdbc
ﻭﺍﻗﻊ ﺷﺪﻩ ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﺩﺭﻭﻥ aﻣﻘﺪﺍﺭ 0x0064fdbcﻗﺮﺍﺭ ﺩﺍﺭﺩ .ﻫﻤﭽﻨﻴﻦ ﻧﺎﻡ ﺁﺭﺍﻳﻪ
ﺷﺒﻴﻪ ﻳﮏ ﺛﺎﺑﺖ ﻋﻤﻞ ﻣﻲﮐﻨﺪ .ﻳﻌﻨﻲ ﺁﺩﺭﺱ ﻳﮏ ﺁﺭﺍﻳﻪ ﻫﻤﻴﺸﻪ ﺛﺎﺑﺖ ﺍﺳﺖ ﻭ ﺁﺭﺍﻳﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ
ﺑﻪ ﻣﮑﺎﻥ ﺩﻳﮕﺮﻱ ﺍﺯ ﺣﺎﻓﻈﻪ ﺗﻐﻴﻴﺮ ﻣﮑﺎﻥ ﺩﻫﺪ.
ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺗﻼﺵ ﻣﻲﮐﻨﺪ ﮐﻪ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ ﻣﻘﺪﺍﺭ aﺭﺍ ﭼﺎﭖ ﮐﻨﺪ .ﻧﺘﻴﺞۀ ﭼﺎﭖ aﺍﻳﻦ
ﺍﺳﺖ ﮐﻪ ﻳﮏ ﺁﺩﺭﺱ ﺑﻪ ﺷﮑﻞ ﺷﺎﻧﺰﺩﻩ ﺩﻫﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﺍﻳﻦ ﻫﻤﺎﻥ ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ
ﺁﺭﺍﻳﻪ ﺍﺳﺖ .ﻳﻌﻨﻲ ﺩﺭﻭﻥ ﻧﺎﻡ aﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ .ﺧﺮﻭﺟﻲ ﻧﻴﺰ ﻧﺸﺎﻥ
ﻣﻲﺩﻫﺪ ﮐﻪ aﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺭﺍ ﺩﺍﺭﺩ ﻭ ] a[0ﻣﻘﺪﺍﺭ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺭﺍ.
1
6‐6ﺍﻟﮕﻮﺭﻳﺘﻢ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ
ﺁﺭﺍﻳﻪﻫﺎ ﺑﻴﺸﺘﺮ ﺑﺮﺍﻱ ﭘﺮﺩﺍﺯﺵ ﻳﮏ ﺯﻧﺠﻴﺮﻩ ﺍﺯ ﺩﺍﺩﻩﻫﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ .ﺍﻏﻠﺐ ﻻﺯﻡ
ﺍﺳﺖ ﮐﻪ ﺑﺮﺭﺳﻲ ﺷﻮﺩ ﺁﻳﺎ ﻳﮏ ﻣﻘﺪﺍﺭ ﺧﺎﺹ ﺩﺭﻭﻥ ﻳﮏ ﺁﺭﺍﻳﻪ ﻣﻮﺟﻮﺩ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ.
ﺳﺎﺩﻩﺗﺮﻳﻦ ﺭﺍﻩ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﺯ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺷﺮﻭﻉ ﮐﻨﻴﻢ ﻭ ﻳﮑﻲ ﻳﮑﻲ ﻫﻢۀ ﻋﻨﺎﺻﺮ
ﺁﺭﺍﻳﻪ ﺭﺍ ﺟﺴﺘﺠﻮ ﻧﻤﺎﻳﻴﻢ ﺗﺎ ﺑﻔﻬﻤﻴﻢ ﮐﻪ ﻣﻘﺪﺍﺭ ﻣﻮﺭﺩ ﻧﻈﺮ ﺩﺭ ﮐﺪﺍﻡ ﻋﻨﺼﺮ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ .ﺑﻪ ﺍﻳﻦ
ﺭﻭﺵ »ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ« ﻣﻲﮔﻮﻳﻨﺪ.
ﺗﺎﺑﻊ )( indexﺳﻪ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺍﺭﺩ :ﭘﺎﺭﺍﻣﺘﺮ xﻣﻘﺪﺍﺭﻱ ﺍﺳﺖ ﮐﻪ ﻗﺮﺍﺭ ﺍﺳﺖ ﺟﺴﺘﺠﻮ ﺷﻮﺩ،
ﭘﺎﺭﺍﻣﺘﺮ aﺁﺭﺍﻳﻪﺍﻱ ﺍﺳﺖ ﮐﻪ ﺑﺎﻳﺪ ﺩﺭ ﺁﻥ ﺟﺴﺘﺠﻮ ﺻﻮﺭﺕ ﮔﻴﺮﺩ ﻭ ﭘﺎﺭﺍﻣﺘﺮ nﻫﻢ ﺍﻳﻨﺪﮐﺲ
ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﻣﻘﺪﺍﺭ ﻣﻮﺭﺩ ﻧﻈﺮ ﺩﺭ ﺁﻥ ﭘﻴﺪﺍ ﺷﺪﻩ ﺍﺳﺖ .ﺩﺭ ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺣﻠﻖۀ
forﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ aﭘﻴﻤﺎﻳﺶ ﺷﺪﻩ ﻭ ﻣﻘﺪﺍﺭ ﻫﺮ ﻋﻨﺼﺮ ﺑﺎ xﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ ﺍﻳﻦ
ﻣﻘﺪﺍﺭ ﺑﺎ xﺑﺮﺍﺑﺮ ﺑﺎﺷﺪ ،ﺍﻳﻨﺪﮐﺲ ﺁﻥ ﻋﻨﺼﺮ ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻩ ﺷﺪﻩ ﻭ ﺗﺎﺑﻊ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ .ﺍﮔﺮ
ﻣﻘﺪﺍﺭ xﺩﺭ ﻫﻴﭻ ﻳﮏ ﺍﺯ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﻣﻮﺟﻮﺩ ﻧﺒﺎﺷﺪ ،ﻣﻘﺪﺍﺭﻱ ﺧﺎﺭﺝ ﺍﺯ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ
ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ ﮐﻪ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﻣﻘﺪﺍﺭ xﺩﺭ ﺁﺭﺍﻱۀ aﻣﻮﺟﻮﺩ ﻧﻴﺴﺖ .ﺩﺭ ﺍﻭﻟﻴﻦ
ﺍﺟﺮﺍﻱ ﺁﺯﻣﺎﻳﺸﻲ ،ﻣﺸﺨﺺ ﺷﺪﻩ ﮐﻪ ﻣﻘﺪﺍﺭ 44ﺩﺭ ] a[1ﻭﺍﻗﻊ ﺍﺳﺖ ﻭ ﺩﺭ ﺍﺟﺮﺍﻱ
ﺁﺯﻣﺎﻳﺸﻲ ﺩﻭﻡ ﻣﺸﺨﺺ ﺷﺪﻩ ﮐﻪ ﻣﻘﺪﺍﺭ 40ﺩﺭ ﺁﺭﺍﻱۀ aﻣﻮﺟﻮﺩ ﻧﻴﺴﺖ )ﻳﻌﻨﻲ ﻣﻘﺪﺍﺭ 44
ﺩﺭ ] a[7ﻭﺍﻗﻊ ﺍﺳﺖ ﻭ ﺍﺯ ﺁﻥﺟﺎ ﮐﻪ ﺁﺭﺍﻱۀ aﻓﻘﻂ ﺗﺎ ] a[6ﻋﻨﺼﺮ ﺩﺍﺭﺩ ،ﻣﻘﺪﺍﺭ 7ﻧﺸﺎﻥ
ﻣﻲﺩﻫﺪ ﮐﻪ 40ﺩﺭ ﺁﺭﺍﻳﻪ ﻣﻮﺟﻮﺩ ﻧﻴﺴﺖ(.
189 ﻓﺼﻞ ﺷﺸﻢ /ﺁراﻳﻪهﺎ
1
6‐7ﻣﺮﺗﺐﺳﺎﺯﻱ ﺣﺒﺎﺑﻲ
ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺧﻴﻠﻲ ﮐﺎﺭﺁﻣﺪ ﻧﻴﺴﺖ .ﻫﻴﭻ ﮐﺲ ﺑﺮﺍﻱ ﻳﺎﻓﺘﻦ ﻣﻌﻨﻲ ﻳﮏ ﮐﻠﻤﻪ ﺩﺭ
ﻭﺍﮊﻩﻧﺎﻣﻪ ،ﻫﻢۀ ﮐﻠﻤﺎﺕ ﺭﺍ ﺍﺯ ﺍﺑﺘﺪﺍ ﺟﺴﺘﺠﻮ ﻧﻤﻲﮐﻨﺪ ﺯﻳﺮﺍ ﮐﻠﻤﺎﺕ ﺩﺭ ﻭﺍﮊﻩﻧﺎﻣﻪ ﺑﻪ ﺗﺮﺗﻴﺐ
ﺣﺮﻭﻑ ﺍﻟﻔﺒﺎ ﻣﺮﺗﺐ ﺷﺪﻩ ﺍﺳﺖ ﻭ ﺑﺮﺍﻱ ﻳﺎﻓﺘﻦ ﻣﻌﻨﻲ ﻳﮏ ﮐﻠﻤﻪ ﮐﺎﻓﻲ ﺍﺳﺖ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ
ﺑﻪ ﺑﺨﺸﻲ ﺑﺮﻭﻳﻢ ﮐﻪ ﺣﺮﻑ ﺍﻭﻝ ﮐﻠﻢۀ ﻣﺎ ﺩﺭ ﺁﻥ ﺑﺨﺶ ﻓﻬﺮﺳﺖ ﺷﺪﻩ ﺍﺳﺖ .ﺑﻪ ﺍﻳﻦ ﺻﻮﺭﺕ
ﺟﺴﺘﺠﻮ ﺑﺴﻴﺎﺭ ﺳﺮﻳﻊﺗﺮ ﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ ﻭ ﭘﺎﺳﺦ ﺩﺭ ﺯﻣﺎﻥ ﮐﻮﺗﺎﻩﺗﺮﻱ ﺣﺎﺻﻞ ﻣﻲﺷﻮﺩ .ﺍﻣﺎ
ﺷﺮﻁ ﺍﻳﻦ ﺟﺴﺘﺠﻮ ﺁﻥ ﺍﺳﺖ ﮐﻪ ﻫﻢۀ ﻋﻨﺎﺻﺮ ﻣﺮﺗﺐ ﺑﺎﺷﻨﺪ.
ﺭﻭﺵﻫﺎﻱ ﺯﻳﺎﺩﻱ ﺑﺮﺍﻱ ﻣﺮﺗﺐ ﮐﺮﺩﻥ ﻳﮏ ﺁﺭﺍﻳﻪ ﻭﺟﻮﺩ ﺩﺍﺭﺩ» .ﻣﺮﺗﺐﺳﺎﺯﻱ ﺣﺒﺎﺑﻲ«
ﻳﮑﻲ ﺍﺯ ﺳﺎﺩﻩﺗﺮﻳﻦ ﺍﻟﮕﻮﺭﻳﺘﻢﻫﺎﻱ ﻣﺮﺗﺐﺳﺎﺯﻱ ﺍﺳﺖ .ﺩﺭ ﺍﻳﻦ ﺭﻭﺵ ،ﺁﺭﺍﻳﻪ ﭼﻨﺪﻳﻦ ﻣﺮﺗﺒﻪ
ﭘﻮﻳﺶ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﻫﺮ ﻣﺮﺗﺒﻪ ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﻨﺼﺮ ﻣﻮﺟﻮﺩ ﺑﻪ ﺳﻤﺖ ﺑﺎﻻ ﻫﺪﺍﻳﺖ ﻣﻲﺷﻮﺩ ﻭ
ﺳﭙﺲ ﻣﺤﺪﻭﺩۀ ﻣﺮﺗﺐﺳﺎﺯﻱ ﺑﺮﺍﻱ ﻣﺮﺗﺐۀ ﺑﻌﺪﻱ ﻳﮑﻲ ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ .ﺩﺭ ﭘﺎﻳﺎﻥ ﻫﻢۀ
ﭘﻮﻳﺶﻫﺎ ،ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﺷﺪﻩ ﺍﺳﺖ .ﻃﺮﻳﻖۀ ﻳﺎﻓﺘﻦ ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﻨﺼﺮ ﻭ ﺍﻧﺘﻘﺎﻝ ﺁﻥ ﺑﻪ ﺑﺎﻻﻱ
ﻋﻨﺎﺻﺮ ﺩﻳﮕﺮ ﺑﻪ ﺍﻳﻦ ﺷﮑﻞ ﺍﺳﺖ ﮐﻪ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺑﺎ ﻋﻨﺼﺮ ﺩﻭﻡ ﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ
ﻋﻨﺼﺮ ﺍﻭﻝ ﺑﺰﺭﮒﺗﺮ ﺑﻮﺩ ،ﺟﺎﻱ ﺍﻳﻦ ﺩﻭ ﺑﺎ ﻫﻢ ﻋﻮﺽ ﻣﻲﺷﻮﺩ .ﺳﭙﺲ ﻋﻨﺼﺮ ﺩﻭﻡ ﺑﺎ ﻋﻨﺼﺮ
ﺳﻮﻡ ﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ ﻋﻨﺼﺮ ﺩﻭﻡ ﺑﺰﺭﮒﺗﺮ ﺑﻮﺩ ،ﺟﺎﻱ ﺍﻳﻦ ﺩﻭ ﺑﺎ ﻫﻢ ﻋﻮﺽ ﻣﻲﺷﻮﺩ ﻭ
ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﻣﻘﺎﻳﺴﻪ ﻭ ﺟﺎﺑﺠﺎﻳﻲ ﺯﻭﺝﻫﺎﻱ ﻫﻤﺴﺎﻳﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﻭﻗﺘﻲ ﺑﻪ ﺍﻧﺘﻬﺎﻱ
ﺁﺭﺍﻳﻪ ﺭﺳﻴﺪﻳﻢ ،ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﻀﻮ ﺁﺭﺍﻳﻪ ﺩﺭ ﺧﺎﻥۀ ﺍﻧﺘﻬﺎﻳﻲ ﻗﺮﺍﺭ ﺧﻮﺍﻫﺪ ﮔﺮﻓﺖ .ﺳﭙﺲ
ﻣﺤﺪﻭﺩۀ ﺟﺴﺘﺠﻮ ﻳﮑﻲ ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ ﻭ ﺩﻭﺑﺎﺭﻩ ﺯﻭﺝﻫﺎﻱ ﮐﻨﺎﺭﻱ ﻳﮑﻲ ﻳﮑﻲ ﻣﻘﺎﻳﺴﻪ
ﻣﻲﺷﻮﻧﺪ ﺗﺎ ﻋﺪﺩ ﺑﺰﺭﮒﺗﺮ ﺑﻌﺪﻱ ﺑﻪ ﻣﮑﺎﻥ ﺑﺎﻻﻱ ﻣﺤﺪﻭﺩﻩ ﻣﻨﺘﻘﻞ ﺷﻮﺩ .ﺍﻳﻦ ﭘﻮﻳﺶ ﺍﺩﺍﻣﻪ
ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﻭﻗﺘﻲ ﻣﺤﺪﻭﺩﻩ ﺟﺴﺘﺠﻮ ﺑﻪ ﻋﻨﺼﺮ ﺍﻭﻝ ﻣﺤﺪﻭﺩ ﺷﺪ ،ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﺷﺪﻩ
ﺍﺳﺖ.
;)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
}
)void sort(float a[], int n
{ // bubble sort:
)for (int i=1; i<n; i++
// bubble up max{a[0..n-i]}:
)for (int j=0; j<n-i; j++
;)]if (a[j] > a[j+1]) swap (a[j],a[j+1
//INVARIANT: a[n-1-i..n-1] is sorted
}
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
ﺗﺎﺑﻊ )( sortﺍﺯ ﺩﻭ ﺣﻠﻖۀ ﺗﻮﺩﺭﺗﻮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻛﻨﺪ .ﺣﻠﻘﻪ forﺩﺍﺧﻠﻲ ﺯﻭﺝﻫﺎﻱ ﻫﻤﺴﺎﻳﻪ
ﺭﺍ ﺑﺎ ﻫﻢ ﻣﻘﺎﻳﺴﻪ ﻣﻲﻛﻨﺪ ﻭ ﺍﮔﺮ ﺁﻥﻫﺎ ﺧﺎﺭﺝ ﺍﺯ ﺗﺮﺗﻴﺐ ﺑﺎﺷﻨﺪ ،ﺟﺎﻱ ﺁﻥ ﺩﻭ ﺭﺍ ﺑﺎ ﻫﻢ ﻋﻮﺽ
ﻣﻲﮐﻨﺪ .ﻭﻗﺘﻲ forﺩﺍﺧﻠﻲ ﺑﻪ ﭘﺎﻳﺎﻥ ﺭﺳﻴﺪ ،ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﻨﺼﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﻣﺤﺪﻭﺩۀ ﻓﻌﻠﻲ ﺑﻪ
ﺍﻧﺘﻬﺎﻱ ﺁﻥ ﻫﺪﺍﻳﺖ ﺷﺪﻩ ﺍﺳﺖ .ﺳﭙﺲ ﺣﻠﻖۀ forﺑﻴﺮﻭﻧﻲ ﻣﺤﺪﻭﺩۀ ﺟﺴﺘﺠﻮ ﺭﺍ ﻳﮑﻲ ﮐﻢ
ﻣﻲﮐﻨﺪ ﻭ ﺩﻭﺑﺎﺭﻩ forﺩﺍﺧﻠﻲ ﺭﺍ ﺭﺍﻩ ﻣﻲﺍﻧﺪﺍﺯﺩ ﺗﺎ ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﻨﺼﺮ ﺑﻌﺪﻱ ﺑﻪ ﺳﻤﺖ ﺑﺎﻻﻱ
ﺁﺭﺍﻳﻪ ﻫﺪﺍﻳﺖ ﺷﻮﺩ.
1
6‐8ﺍﻟﮕﻮﺭﻳﺘﻢ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ
ﺩﺭ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺑﻪ ﻳﮏ ﺁﺭﺍﻱۀ ﻣﺮﺗﺐ ﻧﻴﺎﺯ ﺍﺳﺖ .ﻫﻨﮕﺎﻡ ﺟﺴﺘﺠﻮ ﺁﺭﺍﻳﻪ
ﺍﺯ ﻭﺳﻂ ﺑﻪ ﺩﻭ ﺑﺨﺶ ﺑﺎﻻﻳﻲ ﻭ ﭘﺎﻳﻴﻨﻲ ﺗﻘﺴﻴﻢ ﻣﻲﺷﻮﺩ .ﻣﻘﺪﺍﺭ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺑﺎ ﺁﺧﺮﻳﻦ
ﻋﻨﺼﺮ ﺑﺨﺶ ﭘﺎﻳﻴﻨﻲ ﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ ﺍﻳﻦ ﻋﻨﺼﺮ ﮐﻮﭼﮏﺗﺮ ﺍﺯ ﻣﻘﺪﺍﺭ ﺟﺴﺘﺠﻮ ﺑﻮﺩ،
ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺩﺭ ﺑﺨﺶ ﭘﺎﻳﻴﻨﻲ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ ﻭ ﺑﺎﻳﺪ ﺩﺭ ﺑﺨﺶ ﺑﺎﻻﻳﻲ ﺑﻪ ﺩﻧﺒﺎﻝ ﺁﻥ ﮔﺸﺖ.
ﺩﻭﺑﺎﺭﻩ ﺑﺨﺶ ﺑﺎﻻﻳﻲ ﺑﻪ ﺩﻭ ﺑﺨﺶ ﺗﻘﺴﻴﻢ ﻣﻲﮔﺮﺩﺩ ﻭ ﮔﺎﻡﻫﺎﻱ ﺑﺎﻻ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ .ﺳﺮﺍﻧﺠﺎﻡ
ﻣﺤﺪﻭﺩۀ ﺟﺴﺘﺠﻮ ﺑﻪ ﻳﮏ ﻋﻨﺼﺮ ﻣﺤﺪﻭﺩ ﻣﻲﺷﻮﺩ ﮐﻪ ﻳﺎ ﺁﻥ ﻋﻨﺼﺮ ﺑﺎ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺑﺮﺍﺑﺮ
ﺍﺳﺖ ﻭ ﻋﻨﺼﺮ ﻣﺬﮐﻮﺭ ﻳﺎﻓﺖ ﺷﺪﻩ ﻭ ﻳﺎ ﺍﻳﻦ ﮐﻪ ﺁﻥ ﻋﻨﺼﺮ ﺑﺎ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺑﺮﺍﺑﺮ ﻧﻴﺴﺖ ﻭ
ﻟﺬﺍ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺩﺭ ﺁﺭﺍﻳﻪ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ .ﺍﻳﻦ ﺭﻭﺵ ﭘﻴﭽﻴﺪﻩﺗﺮ ﺍﺯ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ
ﺍﺳﺖ ﺍﻣﺎ ﺩﺭ ﻋﻮﺽ ﺑﺴﻴﺎﺭ ﺳﺮﻳﻊﺗﺮ ﺑﻪ ﺟﻮﺍﺏ ﻣﻲﺭﺳﻴﻢ .ﺍﻟﺒﺘﻪ ﺑﻪ ﺷﺮﻃﻲ ﺑﻪ ﺟﻮﺍﺏ ﻣﻲﺭﺳﻴﻢ
ﮐﻪ ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﺷﺪﻩ ﺑﺎﺷﺪ.
ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺁﺭﺍﻳﻪ ،ﻗﺒﻞ ﺍﺯ ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺑﺎﻳﺪ ﻣﺮﺗﺐ ﺑﺎﺷﺪ .ﺍﻳﻦ
ﭘﻴﺶﺷﺮﻁ ﺑﻪ ﺷﮑﻞ ﺗﻮﺿﻴﺢ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﻗﻴﺪ ﺷﺪﻩ ﺍﺳﺖ.
ﺩﺭ ﺗﺎﺑﻊ ﻓﻮﻕ ﻫﺮ ﺑﺎﺭ ﮐﻪ ﺣﻠﻘﻪ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ ،ﻣﺤﺪﻭﺩۀ ﺟﺴﺘﺠﻮ %50ﮐﻮﭼﮏﺗﺮ
ﻣﻲﺷﻮﺩ .ﺩﺭ ﺁﺭﺍﻱۀ nﻋﻨﺼﺮﻱ ،ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺣﺪﺍﮐﺜﺮ ﺑﻪ log 2 n + 1ﻣﻘﺎﻳﺴﻪ
ﻧﻴﺎﺯ ﺩﺍﺭﺩ ﺗﺎ ﺑﻪ ﭘﺎﺳﺦ ﺑﺮﺳﺪ .ﺣﺎﻝ ﺁﻥ ﮐﻪ ﺩﺭ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ ﺑﻪ nﻣﻘﺎﻳﺴﻪ ﻧﻴﺎﺯ
ﺍﺳﺖ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺩﺭ ﻳﮏ ﺁﺭﺍﻳﻪ 100ﻋﻨﺼﺮﻱ ﺑﺮﺍﻱ ﻣﺸﺨﺺ ﺷﺪﻥ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﻣﻮﺭﺩ
ﻧﻈﺮ ﺩﺭ ﺁﺭﺍﻳﻪ ﻫﺴﺖ ﻳﺎ ﺧﻴﺮ ﺩﺭ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺑﻪ log 2 100 + 1 = 7.64
ﻣﻘﺎﻳﺴﻪ ﻧﻴﺎﺯ ﺍﺳﺖ .ﻳﻌﻨﻲ ﺣﺪﺍﮐﺜﺮ ﺑﺎ 8ﻣﻘﺎﻳﺴﻪ ﺑﻪ ﭘﺎﺳﺦ ﻣﻲﺭﺳﻴﻢ ﻭﻟﻲ ﺩﺭ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ
ﺧﻄﻲ ﺭﻭﻱ ﻫﻤﻴﻦ ﺁﺭﺍﻳﻪ ﺑﻪ ﺣﺪﺍﮐﺜﺮ 100ﻣﻘﺎﻳﺴﻪ ﻧﻴﺎﺯ ﺩﺍﺭﻳﻢ .ﭘﺲ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ
ﺳﺮﻳﻊﺗﺮ ﺍﺯ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ ﺍﺳﺖ .ﺩﻭﻣﻴﻦ ﺗﻔﺎﻭﺕ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﮔﺮ ﭼﻨﺪ ﻋﻨﺼﺮ ﺩﺍﺭﺍﻱ
ﻣﻘﺎﺩﻳﺮ ﻳﮑﺴﺎﻧﻲ ﺑﺎﺷﻨﺪ ،ﺁﻧﮕﺎﻩ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ ﻫﻤﻴﺸﻪ ﮐﻮﭼﮏﺗﺮﻳﻦ ﺍﻳﻨﺪﮐﺲ ﺭﺍ
ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭﻟﻲ ﺩﺭ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﻧﻤﻲﺗﻮﺍﻥ ﮔﻔﺖ ﮐﻪ ﮐﺪﺍﻡ ﺍﻳﻨﺪﮐﺲ
ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ .ﺳﻮﻣﻴﻦ ﻓﺮﻕ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﻓﻘﻂ ﺭﻭﻱ
ﺁﺭﺍﻳﻪﻫﺎﻱ ﻣﺮﺗﺐ ﮐﺎﺭﺍﻳﻲ ﺩﺍﺭﺩ ﻭ ﺍﮔﺮ ﺁﺭﺍﻳﻪﺍﻱ ﻣﺮﺗﺐ ﻧﺒﺎﺷﺪ ،ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﭘﺎﺳﺦ ﻏﻠﻂ
ﻣﻲﺩﻫﺪ ﻭﻟﻲ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ ﻫﻤﻴﺸﻪ ﭘﺎﺳﺦ ﺻﺤﻴﺢ ﺧﻮﺍﻫﺪ ﺩﺍﺩ.
isNondecreasing(a,4) = 1
isNondecreasing(a,7) = 0
ﺍﻳﻦ ﺗﺎﺑﻊ ﻳﮏ ﺑﺎﺭ ﮐﻞ ﺁﺭﺍﻳﻪ ﺭﺍ ﭘﻴﻤﺎﻳﺶ ﮐﺮﺩﻩ ﻭ ﺯﻭﺝﻫﺎﻱ ] a[i-1ﻭ ] a[iﺭﺍ ﻣﻘﺎﻳﺴﻪ
ﻣﻲﮐﻨﺪ .ﺍﮔﺮ ﺯﻭﺟﻲ ﻳﺎﻓﺖ ﺷﻮﺩ ﮐﻪ ﺩﺭ ﺁﻥ ] a[i]<a[i-1ﺑﺎﺷﺪ ،ﻣﻘﺪﺍﺭ falseﺭﺍ ﺑﺮ
ﻣﻲﮔﺮﺩﺍﻧﺪ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﻲ ﮐﻪ ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﻧﻴﺴﺖ .ﺑﺒﻴﻨﻴﺪ ﮐﻪ ﻣﻘﺎﺩﻳﺮ trueﻭ falseﺑﻪ
ﺷﮑﻞ ﺍﻋﺪﺍﺩ 1ﻭ 0ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﻧﺪ ﺯﻳﺮﺍ ﻣﻘﺎﺩﻳﺮ ﺑﻮﻟﻲ ﺩﺭ ﺣﻘﻴﻘﺖ ﺑﻪ ﺷﮑﻞ
ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺩﺭ ﺣﺎﻓﻈﻪ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﻧﺪ.
ﺍﮔﺮ ﭘﻴﺶﺷﺮﻁ 1ﻣﺜﺎﻝ 6‐14ﻳﻌﻨﻲ ﻣﺮﺗﺐ ﺑﻮﺩﻥ ﺁﺭﺍﻳﻪ ﺭﻋﺎﻳﺖ ﻧﺸﻮﺩ ،ﺟﺴﺘﺠﻮﻱ
ﺩﻭﺩﻭﻳﻲ ﭘﺎﺳﺦ ﺩﺭﺳﺘﻲ ﻧﻤﻲﺩﻫﺪ .ﺑﻪ ﺍﻳﻦ ﻣﻨﻈﻮﺭ ﺍﺑﺘﺪﺍ ﺑﺎﻳﺪ ﺍﻳﻦ ﭘﻴﺶﺷﺮﻁ ﺑﺮﺭﺳﻲ ﺷﻮﺩ .ﺑﺎ
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ )( assertﻣﻲﺗﻮﺍﻥ ﺍﺟﺮﺍﻱ ﻳﮏ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺑﻪ ﻳﮏ ﺷﺮﻁ ﻭﺍﺑﺴﺘﻪ ﮐﺮﺩ .ﺍﻳﻦ
ﺗﺎﺑﻊ ﻳﮏ ﺁﺭﮔﻮﻣﺎﻥ ﺑﻮﻟﻲ ﻣﻲﭘﺬﻳﺮﺩ .ﺍﮔﺮ ﻣﻘﺪﺍﺭ ﺁﺭﮔﻮﻣﺎﻥ falseﺑﺎﺷﺪ ،ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺧﺎﺗﻤﻪ
ﺩﺍﺩﻩ ﻭ ﻣﻮﺿﻮﻉ ﺭﺍ ﺑﻪ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﮔﺰﺍﺭﺵ ﻣﻲﮐﻨﺪ .ﺍﮔﺮ ﻣﻘﺪﺍﺭ ﺁﺭﮔﻮﻣﺎﻥ trueﺑﺎﺷﺪ،
ﺑﺮﻧﺎﻣﻪ ﺑﺪﻭﻥ ﺗﻐﻴﻴﺮ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ .ﺗﺎﺑﻊ )( assetﺩﺭ ﺳﺮﻓﺎﻳﻞ > <cassertﺗﻌﺮﻳﻒ
ﺷﺪﻩ ﺍﺳﺖ.
1 - Precondition
195 ﻓﺼﻞ ﺷﺸﻢ /ﺁراﻳﻪهﺎ
ﺁﺭﺍﻱۀ ][ aﮐﻪ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﻛﺎﻣﻼ ﻣﺮﺗﺐ ﻧﻴﺴﺖ ﺍﻣﺎ ﻫﻔﺖ ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﻥ
ﻣﺮﺗﺐ ﺍﺳﺖ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﺭ ﻓﺮﺍﺧﻮﺍﻧﻲ) index(44,a,7ﺗﺎﺑﻊ ﺑﻮﻟﻲ ﻣﻘﺪﺍﺭ trueﺭﺍ ﺑﻪ
)( assertﺍﺭﺳﺎﻝ ﻣﻲﮐﻨﺪ ﻭ ﺑﺮﻧﺎﻣﻪ ﺍﺩﻣﻪ ﻣﻲﻳﺎﺑﺪ .ﺍﻣﺎ ﺩﺭ ﺩﻭﻣﻴﻦ ﻓﺮﺍﺧﻮﺍﻧﻲ
) index(44,a,8ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺗﺎﺑﻊ )( isNondecreasingﻣﻘﺪﺍﺭ
ﺗﺎﺑﻊ ﺑﻪ ﺭﺍ false
)( assertﺍﺭﺳﺎﻝ ﮐﻨﺪ ﻛﻪ
ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ ﺑﺮﻧﺎﻣﻪ
ﻣﺘﻮﻗﻒ ﻣﻲﺷﻮﺩ ﻭ ﻭﻳﻨﺪﻭﺯ
ﭘﻨﺠﺮۀ ﻫﺸﺪﺍﺭ ﻣﻘﺎﺑﻞ ﺭﺍ
ﻧﻤﺎﻳﺶ ﻣﻲﺩﻫﺪ.
ﺑﻪ ﺧﺎﻃﺮ ﺑﻴﺎﻭﺭﻳﺪ ﮐﻪ ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﺑﻪ ﺷﮑﻞ ﻣﻘﺎﺩﻳﺮ ﻋﺪﺩﻱ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﻧﺪ .ﺍﻧﺪﺍﺯۀ
ﺁﺭﺍﻳﻪ SAT+1 ،ﺍﺳﺖ ﺯﻳﺮﺍ SATﻣﻘﺪﺍﺭ ﺻﺤﻴﺢ 6ﺭﺍ ﺩﺍﺭﺩ ﻭ ﺁﺭﺍﻳﻪ ﺑﻪ ﻫﻔﺖ ﻋﻨﺼﺮ ﻧﻴﺎﺯﻣﻨﺪ
ﺍﺳﺖ .ﻣﺘﻐﻴﺮ dayﺍﺯ ﻧﻮﻉ intﺍﺳﺖ ﭘﺲ ﻣﻲﺗﻮﺍﻥ ﻣﻘﺎﺩﻳﺮ Dayﺭﺍ ﺑﻪ ﺁﻥ ﺗﺨﺼﻴﺺ ﺩﺍﺩ.
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﺩﺭ ﺑﺮﺧﻲ ﺍﺯ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﮐﺪ ﺑﺮﻧﺎﻣﻪ »ﺧﻮﺩ ﺍﺳﺘﻨﺎﺩ«
ﺷﻮﺩ .ﻣﺜﻼ ﺩﺭ ﻣﺜﺎﻝ 6‐17ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺑﻪ ﺷﮑﻞ
)for (int day = SUN; day <= SAT; day++
6‐10ﺗﻌﺮﻳﻒ ﺍﻧﻮﺍﻉ
ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﻳﻜﻲ ﺍﺯ ﺭﺍﻩﻫﺎﻳﻲ ﺍﺳﺖ ﮐﻪ ﮐﺎﺭﺑﺮ ﻣﻲﺗﻮﺍﻧﺪ ﻧﻮﻉ ﺳﺎﺧﺖ ﺧﻮﺩﺵ ﺭﺍ
ﺗﻌﺮﻳﻒ ﮐﻨﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺩﺳﺘﻮﺭ ﺯﻳﺮ :
;} enum Color { RED, ORANGE, YELLOW, GREEN, BLUE, VIOLET
197 ﻓﺼﻞ ﺷﺸﻢ /ﺁراﻳﻪهﺎ
ﻳﮏ ﻧﻮﻉ ﺟﺪﻳﺪ ﺑﻪ ﻧﺎﻡ Colorﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺍﺯ ﺍﻳﻦ ﻧﻮﻉ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻣﻘﺎﺩﻳﺮ
REDﻳﺎ ORANGEﻳﺎ YELLOWﻳﺎ GREENﻳﺎ BLUEﻳﺎ VIOLETﺭﺍ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ .ﭘﺲ
ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﻧﻮﻉ ﻣﻲﺗﻮﺍﻥ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺗﻌﺮﻳﻒ ﻧﻤﻮﺩ:
;Color shirt = BLUE
;} Color car[] = { GREEN, RED, BLUE, RED
;}float wavelength[VIOLET+1] = {420, 480, 530, 570, 600, 620
ﻛﻪ typeﻳﮏ ﻧﻮﻉ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻭ aliasﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺑﺮﺍﻱ ﺁﻥ ﺍﺳﺖ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﮐﺴﺎﻧﻲ
ﮐﻪ ﺑﺎ ﭘﺎﺳﮑﺎﻝ ﺑﺮﻧﺎﻣﻪ ﻣﻲﻧﻮﻳﺴﻨﺪ ﺑﻪ ﺟﺎﻱ ﻧﻮﻉ longﺍﺯ ﻋﺒﺎﺭﺕ Integerﺍﺳﺘﻔﺎﺩﻩ
ﻣﻲﮐﻨﻨﺪ ﻭ ﺑﻪ ﺟﺎﻱ ﻧﻮﻉ doubleﺍﺯ ﻋﺒﺎﺭﺕ Realﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻧﻤﺎﻳﻨﺪ .ﺍﻳﻦ ﺍﻓﺮﺍﺩ
ﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺯ ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻨﺪ:
;typedef long Integer
;typedef double Real
ﺍﮔﺮ ﺩﺳﺘﻮﺭ typedefﺭﺍ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺑﮑﺎﺭ ﺑﺒﺮﻳﻢ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﺭﺍﻳﻪﻫﺎ ﺭﺍ ﺑﺪﻭﻥ ﻋﻼﻣﺖ
ﺑﺮﺍﮐﺖ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ:
;][typedef element-type alias
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 198
ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﻮﺍﺑﻊ ﺑﺎﻻ ،ﺑﻌﺪ ﺍﻭﻝ ﻧﺎﻣﺸﺨﺺ ﺍﺳﺖ ﺍﻣﺎ ﺑﻌﺪ ﺩﻭﻡ
ﻣﺸﺨﺺ ﺷﺪﻩ .ﻋﻠﺖ ﻫﻢ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺁﺭﺍﻱۀ ﺩﻭ ﺑﻌﺪﻱ ][][ aﺩﺭ ﺣﻘﻴﻘﺖ ﺁﺭﺍﻳﻪﺍﻱ
ﻳﮏﺑﻌﺪﻱ ﺍﺯ ﺳﻪ ﺁﺭﺍﻱۀ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﺍﺳﺖ .ﮐﺎﻣﭙﺎﻳﻠﺮ ﻧﻴﺎﺯ ﻧﺪﺍﺭﺩ ﺑﺪﺍﻧﺪ ﮐﻪ ﭼﻪ ﺗﻌﺪﺍﺩ ﺍﺯ ﺍﻳﻦ
ﺁﺭﺍﻳﻪﻫﺎﻱ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﻣﻮﺟﻮﺩ ﺍﺳﺖ ،ﺍﻣﺎ ﺑﺎﻳﺪ ﺑﺪﺍﻧﺪ ﮐﻪ ﺁﻥﻫﺎ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﻫﺴﺘﻨﺪ.
201 ﺁراﻳﻪهﺎ/ ﻓﺼﻞ ﺷﺸﻢ
ﺑﻌﺪ ﺍﻭﻝ ﻣﺸﺨﺺ ﻧﻴﺴﺖ ﺍﻣﺎ،ﻭﻗﺘﻲ ﻳﮏ ﺁﺭﺍﻱۀ ﭼﻨﺪ ﺑﻌﺪﻱ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ
.ﻫﻢۀ ﺍﺑﻌﺎﺩ ﺩﻳﮕﺮ ﺑﺎﻳﺪ ﻣﺸﺨﺺ ﺑﺎﺷﻨﺪ
}
)void printClassAverages(Score score
){ for (int q=0; q<NUM_QUIZZES; q++
;{ float sum = 0.0
)for (int s=0; s<NUM_STUDENTS; s++
;]sum += score[s][q
cout << "\tQuiz " << q << ": " << sum/NUM_STUDENTS
;<< endl
}
}
Enter 5 quiz scores for each student:
student 0: 8 7 9 8 9
student 1: 9 9 9 9 8
student 2: 5 6 7 8 9
The quize averages are:
student 0: 8.2
student 1: 8.8
student 2: 7
The class averages are:
Quiz 0: 7.33333
Quiz 1: 7.33333
Quiz 2: 8.33333
Quiz 3: 8.33333
Quiz 4: 8.66667
ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺁﺭﺍﻳﻪ ﭼﮕﻮﻧﻪ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﺪﻩ ﺍﺳﺖ .ﺍﻳﻦ ﻗﺎﻟﺐ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﻪ ﺧﻮﺑﻲ ﻧﻤﺎﻳﺎﻥ
ﻣﻲﮐﻨﺪ ﮐﻪ ﺁﺭﺍﻱۀ ﻣﺬﮐﻮﺭ ﻳﮏ ﺁﺭﺍﻳﻪ ﺩﻭ ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﻋﻨﺼﺮ ،ﺧﻮﺩ ﻳﮏ ﺁﺭﺍﻱۀ
ﭼﻬﺎﺭ ﻋﻀﻮﻱ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﻋﻀﻮ ﺷﺎﻣﻞ ﺁﺭﺍﻳﻪﺍﻱ ﺳﻪ ﻋﻨﺼﺮﻱ ﻣﻲﺑﺎﺷﺪ .ﭘﺲ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺩﺭ
ﻣﺠﻤﻮﻉ 24ﻋﻨﺼﺮ ﺩﺍﺭﺩ .ﺁﺭﺍﻱۀ ﻣﺬﮐﻮﺭ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﻨﻴﻢ:
;}int a[2][4][3]={5,0,2,0,0,9,4,1,0,7,7,7,3,0,0,8,5,0,0,0,0,2,0,9
ﻭ ﻳﺎ ﻣﺎﻧﻨﺪ ﺍﻳﻦ:
= ]int a[2][4][3
;}}{{5,0,2,0,0,9,4,1,0,7,7,7},{3,0,0,8,5,0,0,0,0,2,0,9
ﻫﺮ ﺱۀ ﺍﻳﻦ ﻗﺎﻟﺐﻫﺎ ﺑﺮﺍﻱ ﮐﺎﻣﭙﺎﻳﻠﺮ ﻳﮏ ﻣﻔﻬﻮﻡ ﺭﺍ ﺩﺍﺭﻧﺪ ﺍﻣﺎ ﺑﺎ ﻧﮕﺎﻩ ﮐﺮﺩﻥ ﺑﻪ ﺩﻭ ﻗﺎﻟﺐ ﺍﺧﻴﺮ
ﺑﻪ ﺳﺨﺘﻲ ﻣﻲﺗﻮﺍﻥ ﻓﻬﻤﻴﺪ ﮐﻪ ﮐﺪﺍﻡ ﻋﻨﺼﺮ ﺍﺯ ﺁﺭﺍﻳﻪ ،ﮐﺪﺍﻡ ﻣﻘﺪﺍﺭ ﺭﺍ ﺧﻮﺍﻫﺪ ﺩﺍﺷﺖ.
ﺑﻪ ﺳﻪ ﺣﻠﻖۀ forﺗﻮﺩﺭﺗﻮ ﺩﻗﺖ ﮐﻨﻴﺪ .ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ ﺑﺮﺍﻱ ﭘﻴﻤﺎﻳﺶ ﻳﮏ ﺁﺭﺍﻱۀ n
ﺑﻌﺪﻱ ﺑﻪ nﺣﻠﻖۀ ﺗﻮﺩﺭﺗﻮ ﻧﻴﺎﺯ ﺍﺳﺖ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 204
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺍﺷﺘﺒﺎﻩ ﺍﺳﺖ؟
ﺍﻟﻒ – ﻳﮏ ﺁﺭﺍﻳﻪ ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﺳﺖ ﮐﻪ ﻫﻤﮕﻲ ﻳﮏ ﻧﻮﻉ ﺩﺍﺭﻧﺪ
ﺏ – ﻣﻲﺗﻮﺍﻥ ﺁﺭﺍﻳﻪ ﺭﺍ ﺍﺯ ﻗﺴﻤﺘﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺑﻪ ﻗﺴﻤﺖ ﺩﻳﮕﺮ ﻣﻨﺘﻘﻞ ﻧﻤﻮﺩ
ﺝ – ﻣﺤﻞ ﻗﺮﺍﺭﮔﻴﺮﻱ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺩﺭ ﺣﺎﻓﻈﻪ ،ﭘﺸﺖ ﺳﺮ ﻫﻢ ﻭ ﭘﻴﻮﺳﺘﻪ ﺍﺳﺖ
ﺩ – ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﺮﺍﻱ ﺩﺳﺖﮐﺎﺭﻱ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﮐﺮﺩ
– 2ﺩﺭ ﻣﻮﺭﺩ ﺩﺳﺘﻮﺭ ;] int a[5ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺍﺷﺘﺒﺎﻩ ﺍﺳﺖ؟
ﺍﻟﻒ – ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﻳﮏ ﺁﺭﺍﻱۀ ﻳﮏ ﺑﻌﺪﻱ ﺭﺍ ﺍﻋﻼﻥ ﻣﻲﮐﻨﺪ
ﺏ – ﺍﻋﻀﺎﻱ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺍﺯ ﻧﻮﻉ ﻋﺪﺩﻱ ﺻﺤﻴﺢ ﻫﺴﺘﻨﺪ
ﺝ – ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﭘﻨﺞ ﻋﻀﻮ ﺩﺍﺭﺩ
ﺩ – ﻫﺮ ﻋﻀﻮ ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﺻﻔﺮ ﺍﺳﺖ
– 3ﮐﺪ ;} int a[] = {0, 0, 0ﻣﻌﺎﺩﻝ ﮐﺪﺍﻡ ﮔﺰﻳﻦۀ ﺯﻳﺮ ﺍﺳﺖ؟
ﺏ – ;]int a[0 ﺍﻟﻒ – ;}int a[] = {0
ﺩ – ;}int a[3] = {0 ﺝ – ;]int a[0,0,0
– 4ﺩﺭ ﻣﻮﺭﺩ ﺩﺳﺘﻮﺭ ;} int a[5] = {1, 2, 3ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ – ﻋﻨﺎﺻﺮ ﭼﻬﺎﺭﻡ ﻭ ﭘﻨﺠﻢ ﺁﺭﺍﻳﻪ aﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﺻﻔﺮ ﻫﺴﺘﻨﺪ.
ﺏ – ﺁﺭﺍﻱۀ aﺳﻪ ﻋﻨﺼﺮ ﺩﺍﺭﺩ
ﺝ – ﺩﻭ ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻳﻪ aﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﺯﺑﺎﻟﻪ ﻫﺴﺘﻨﺪ
ﺩ – ﺩﺭ ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﭘﻨﺞ ﺁﺭﺍﻱۀ ﺳﻪ ﻋﻨﺼﺮﻱ ﺍﻋﻼﻥ ﺷﺪﻩ ﺍﺳﺖ
ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ;}float a[2] = {1.11, 2.22, 3.33 – 5ﺩﺭ ﻣﻮﺭﺩ ﺩﺳﺘﻮﺭ
ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ – ﺁﺭﺍﻱۀ aﺳﻪ ﻋﻨﺼﺮ ﺍﺯ ﻧﻮﻉ floatﺩﺍﺭﺩ
ﺏ – ﻫﺮ ﻋﻀﻮ ﺁﺭﺍﻱۀ aﺑﺎﻳﺪ ﺩﻭ ﺭﻗﻢ ﺍﻋﺸﺎﺭ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ
ﺝ – ﻋﻨﺼﺮ ﺳﻮﻡ ﺁﺭﺍﻱۀ aﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﺻﻔﺮ ﺩﺍﺭﺩ
ﺩ – ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺍﺷﺘﺒﺎﻩ ﺍﺳﺖ ﺯﻳﺮﺍ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﻴﺶ ﺍﺯ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﻋﻀﻮ ﺩﺍﺭﺩ
205 ﻓﺼﻞ ﺷﺸﻢ /ﺁراﻳﻪهﺎ
ﺩ – ;)(a.print ﺝ – ;)print(a
;] int c[2][3][4ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ .ﺗﺎﺑﻊ – 11ﺁﺭﺍﻱۀ cﺑﻪ ﺷﮑﻞ
)( printﺍﺯ ﻧﻮﻉ voidﺑﻮﺩﻩ ﻭ ﻗﺮﺍﺭ ﺍﺳﺖ ﮐﻪ ﺁﺭﺍﻱۀ cﺑﻪ ﺁﻥ ﺍﺭﺳﺎﻝ ﺷﻮﺩ .ﺑﺎ ﺍﻳﻦ
ﺗﻮﺿﻴﺤﺎﺕ ،ﺗﺎﺑﻊ )( printﺑﺎﻳﺪ ﭼﮕﻮﻧﻪ ﺍﻋﻼﻥ ﺷﻮﺩ؟
ﺍﻟﻒ ‐ ;)][][][ void print(int
ﺏ – ;)]void print(int [2][3][4
ﺝ ‐ ;)]void print(int[][3][4
;)void print(int, int, int ﺩ–
– 12ﮐﺪﺍﻡ ﺩﺳﺘﻮﺭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻱۀ aﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ؟
ﺏ – ;]cout << a[1 ﺍﻟﻒ ‐ ;]cout << a[0
ﺩ – ;]cout << [a0 ﺝ – ;cout << a
– 13ﺍﮔﺮ ﺁﺭﺍﻱۀ aﺩﺍﺭﺍﻱ ﭘﻨﺞ ﻋﻨﺼﺮ ﺍﺯ ﻧﻮﻉ intﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ ﮐﺪﺍﻡ ﺩﺳﺘﻮﺭ ﻣﻘﺪﺍﺭ 10ﺭﺍ
ﺩﺭﻭﻥ ﺁﺧﺮﻳﻦ ﻋﻀﻮ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ؟
ﺏ – ;a[4] = 10 ;a[5] = 10 ﺍﻟﻒ ‐
ﺩ – ;a(4) = 10 ;a(5) = 10 ﺝ‐
– 14ﺍﮔﺮ ﺁﺭﺍﻱۀ aﺑﻪ ﺷﮑﻞ ;] int a[5][5][5ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ ﮐﺪ
; a[5][5][5] = 0ﭼﻪ ﺍﺛﺮﻱ ﺩﺍﺭﺩ؟
ﺍﻟﻒ – ﺁﺧﺮﻳﻦ ﻋﻀﻮ ﺁﺭﺍﻱۀ aﺭﺍ ﺻﻔﺮ ﻣﻲﮐﻨﺪ
ﺏ – ﻋﻀﻮﻱ ﮐﻪ ﺩﺭ ﻣﺤﻞ ) (5, 5, 5ﺍﺯ ﺁﺭﺍﻱۀ aﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺭﺍ ﺻﻔﺮ ﻣﻲﮐﻨﺪ
ﺝ – ﻫﻢۀ ﺍﻋﻀﺎﻱ ﺁﺭﺍﻱۀ aﺭﺍ ﺻﻔﺮ ﻣﻲﮐﻨﺪ
ﺩ – ﺍﺛﺮﻱ ﺭﻭﻱ ﺍﻋﻀﺎﻱ ﺁﺭﺍﻱۀ aﻧﺪﺍﺭﺩ
– 15ﺩﺳﺘﻮﺭ typedefﭼﻪ ﮐﺎﺭﻱ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ؟
ﺍﻟﻒ – ﻳﮏ ﻧﻮﻉ ﺟﺪﻳﺪ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ
ﺏ – ﻳﮏ ﻣﺘﻐﻴﺮ ﺟﺪﻳﺪ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ
ﺝ – ﺑﺮﺍﻱ ﻳﮏ ﻧﻮﻉ ﻣﻮﺟﻮﺩ ،ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ
ﺩ – ﺑﺮﺍﻱ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻮﺟﻮﺩ ،ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ
207 ﻓﺼﻞ ﺷﺸﻢ /ﺁراﻳﻪهﺎ
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﺍﻋﻀﺎﻱ ﻳﮏ ﺁﺭﺍﻳﻪ ﭼﻨﺪ ﻧﻮﻉ ﻣﺘﻔﺎﻭﺕ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ؟
‐2ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﭼﻪ ﻧﻮﻉ ﻭ ﻣﺤﺪﻭﺩﻩﺍﻱ ﺑﺎﻳﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ؟
‐3ﺍﮔﺮ ﻳﮏ ﺁﺭﺍﻳﻪ ﺍﻋﻼﻥ ﺷﺪﻩ ﺑﺎﺷﺪ ﻭﻟﻲ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ ﺑﺎﺷﺪ ،ﻋﻨﺎﺻﺮ ﺁﻥ ﺁﺭﺍﻳﻪ ﭼﻪ
ﻣﻘﺎﺩﻳﺮﻱ ﺧﻮﺍﻫﻨﺪ ﺩﺍﺷﺖ؟
‐4ﺍﮔﺮ ﻳﮏ ﺁﺭﺍﻳﻪ ﺍﻋﻼﻥ ﺷﺪﻩ ﺑﺎﺷﺪ ﻭﻟﻲ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺁﻥ ﻧﺴﺒﺖ ﺑﻪ ﺍﻋﻀﺎﻱ ﺁﺭﺍﻳﻪ
ﺗﻌﺪﺍﺩ ﮐﻢﺗﺮﻱ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ ﻋﻨﺎﺻﺮ ﺁﻥ ﺁﺭﺍﻳﻪ ﭼﻪ ﻣﻘﺎﺩﻳﺮﻱ ﺧﻮﺍﻫﻨﺪ ﺩﺍﺷﺖ؟
‐5ﺍﮔﺮ ﺩﺭ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻳﮏ ﺁﺭﺍﻳﻪ ،ﻋﻨﺎﺻﺮ ﺑﻴﺸﺘﺮﻱ ﻧﺴﺒﺖ ﺑﻪ ﺍﻧﺪﺍﺯۀ ﺁﺭﺍﻳﻪ ﻭﺟﻮﺩ
ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﭼﻪ ﺍﺗﻔﺎﻗﻲ ﻣﻲﺍﻓﺘﺪ؟
‐6ﺑﻴﻦ ﺩﺳﺘﻮﺭ enumﻭ ﺩﺳﺘﻮﺭ typedefﭼﻪ ﺗﻔﺎﻭﺗﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ؟
‐7ﺍﮔﺮ ﺑﺨﻮﺍﻫﻴﻢ ﻳﮏ ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﻪ ﻳﮏ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﮐﻨﻴﻢ ،ﭼﺮﺍ ﺑﺎﻳﺪ ﺍﻧﺪﺍﺯۀ ﻫﻤﻪ ﺍﺑﻌﺎﺩ ﺑﻪ ﻏﻴﺮ
ﺍﺯ ﺑﻌﺪ ﺍﻭﻝ ﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﺫﮐﺮ ﺷﻮﺩ؟
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 6‐1ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﮐﻪ ﺑﺮﺍﻱ ﻫﺮ ﻭﺭﻭﺩﻱ ،ﻳﮏ ﺧﻂ ﺩﺭﺧﻮﺍﺳﺖ ﻭ
ﺑﺮﺍﻱ ﻫﺮ ﺧﺮﻭﺟﻲ ،ﻳﮏ ﺧﻂ ﺍﻋﻼﻥ ﭼﺎﭖ ﺷﻮﺩ .ﻣﺎﻧﻨﺪ ﺗﺼﻮﻳﺮ ﺯﻳﺮ:
Enter 5 numbers
a[0]: 11.11
a[1]: 33.33
a[2]: 55.55
a[3]: 77.77
a[4]: 99.99
In reverse order, they are:
]a[4 = 99.99
]a[3 = 77.77
]a[2 = 55.55
]a[1 = 33.33
]a[0 = 11.11
209 ﻓﺼﻞ ﺷﺸﻢ /ﺁراﻳﻪهﺎ
‐2ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 6‐1ﺭﺍ ﻃﻮﺯﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﻪ ﻃﻮﺭ ﻣﻌﻜﻮﺱ ﭘﺮ ﻛﻨﺪ ﻭ ﺳﭙﺲ
ﺍﻋﻀﺎﻱ ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﻪ ﻫﻤﺎﻥ ﺗﺮﺗﻴﺒﻲ ﻛﻪ ﺫﺧﻴﺮﻩ ﺷﺪﻩﺍﻧﺪ ﭼﺎﭖ ﻛﻨﺪ .ﻣﺎﻧﻨﺪ ﺗﺼﻮﻳﺮ ﺯﻳﺮ:
Enter 5 numbers:
a[4]: 55.55
a[3]: 66.66
a[2]: 77.77
a[1]: 88.88
a[0]: 99.99
In reverse order, they are:
]a[0 = 99.99
]a[1 = 88.88
]a[2 = 77.77
]a[3 = 66.66
]a[4 = 55.55
‐3ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 6‐9ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ ﺯﻳﺮ ،ﻣﻴﺎﻧﮕﻴﻦ nﻋﻨﺼﺮ
ﺍﻭﻝ ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ:
;)float ave(int[] a, int n
][// returns the average of the first n elements of a
‐4ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 6‐10ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﮐﻪ ﺧﻮﺩ ﺁﺭﺍﻳﻪ ،ﻣﺠﻤﻮﻉ ﺁﻥ ﻭ ﻣﻴﺎﻧﮕﻴﻦ ﺁﻥ ﺭﺍ
ﭼﺎﭖ ﻛﻨﺪ ) .ﺑﻪ ﻣﺜﺎﻝ 6‐9ﻭ ﻣﺴﺎﻝۀ 6‐3ﻧﮕﺎﻩ ﻛﻨﻴﺪ(
‐5ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 6‐11ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﺑﺮﺍﻱ ﻫﺮ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ،ﺁﺩﺭﺱ ﺣﺎﻓﻆۀ ﺁﻥ
ﻭ ﻣﺤﺘﻮﻳﺎﺕ ﺁﻥ ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ .ﺑﺮﺍﻱ ﺁﺭﺍﻳﻪﺍﻱ ﺑﻪ ﻧﺎﻡ ،aﺍﺯ ﻋﺒﺎﺭﺕﻫﺎﻱ aﻭ a+1ﻭ a+2
ﻭ ...ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﺪ ﺗﺎ ﺁﺩﺭﺱﻫﺎﻱ ] a[0ﻭ ] a[1ﻭ ...ﺭﺍ ﺑﺪﺳﺖ ﺁﻭﺭﻳﺪ ﻭ ﺍﺯ ﻋﺒﺎﺭﺕﻫﺎﻱ
*aﻭ ) *(a+1ﻭ ) *(a+2ﻭ ...ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﻴﺪ ﺗﺎ ﻣﺤﺘﻮﻳﺎﺕ ﺍﻳﻦ ﻣﻜﺎﻥﻫﺎ ﺭﺍ ﺑﺪﺳﺖ
ﺁﻭﺭﻳﺪ .ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ][ unsigned int aﺍﻋﻼﻥ ﻛﻨﻴﺪ ﺗﺎ ﻣﻘﺎﺩﻳﺮ ﺁﺭﺍﻳﻪ ﻭﻗﺘﻲ
ﺩﺍﺧﻞ ﺟﺮﻳﺎﻥ coutﺩﺭﺝ ﻣﻲﺷﻮﻧﺪ ،ﺑﻪ ﺷﮑﻞ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﭼﺎﭖ ﺷﻮﻧﺪ.
‐6ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 6‐12ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﺑﻪ ﺟﺎﻱ ﺍﻭﻟﻴﻦ ﻣﺤﻞ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻦ ﻳﮏ
ﻋﻨﺼﺮ ﻣﻔﺮﻭﺽ ،ﺁﺧﺮﻳﻦ ﻣﺤﻞ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻦ ﺁﻥ ﺭﺍ ﺩﺭ ﺁﺭﺍﻳﻪ ﺑﺮﮔﺮﺩﺍﻧﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 210
‐7ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 6‐15ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﻣﻘﺪﺍﺭ trueﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ ﺍﮔﺮ ﻭ ﻓﻘﻂ
ﺍﮔﺮ ﺁﺭﺍﻳﻪ ﻏﻴﺮ ﺻﻌﻮﺩﻱ ﺑﺎﺷﺪ.
‐8ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﺭ ﺑﻴﻦ nﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻳﻪ ،ﻣﻘﺪﺍﺭ
ﻛﻤﻴﻨﻪ)ﻣﻴﻨﻴﻤﻢ( ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
;)float min(float a[], int n
‐9ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ،ﺍﻳﻨﺪﮐﺲ ﺍﻭﻟﻴﻦ ﻣﻘﺪﺍﺭ ﮐﻤﻴﻨﻪ)ﻣﻴﻨﻴﻤﻢ( ﺭﺍ
ﺍﺯ ﻣﻴﺎﻥ nﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻱۀ ﻣﻔﺮﻭﺽ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
;)int minIndex(float a[], int n
‐10ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ ﮐﻤﻴﻨﻪ ﻭ ﺑﻴﺸﻴﻨﻪ ﺭﺍ ﺩﺭ ﺑﻴﻦ n
ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻱۀ ﻣﻔﺮﻭﺽ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺭﺟﺎﻋﻲﺍﺵ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
;)void getEXtremes(float& min, float& max, float a[], int n
‐11ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺰﺭﮒﺗﺮﻳﻦ ﻣﻘﺪﺍﺭ ﻭ ﺩﻭﻣﻴﻦ ﺑﺰﺭﮒﺗﺮﻳﻦ
ﻣﻘﺪﺍﺭ )ﺍﻳﻦ ﺩﻭ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻣﺴﺎﻭﻱ ﺑﺎﺷﻨﺪ( ﺭﺍ ﺍﺯ ﺑﻴﻦ nﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻱۀ ﻣﻔﺮﻭﺽ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ
ﺍﺯ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺭﺟﺎﻋﻲﺍﺵ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
;)void largest(float& max1, float& max2, float a[], int n
‐13ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺳﻌﻲ ﻣﻲﮐﻨﺪ ﻳﮏ ﻋﻨﺼﺮ ﺭﺍ ﺍﺯ ﺁﺭﺍﻳﻪ
ﺣﺬﻑ ﮐﻨﺪ:
;)bool removeFirst(float a[], int& n, float x
211 ﻓﺼﻞ ﺷﺸﻢ /ﺁراﻳﻪهﺎ
ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﺭ ﺑﻴﻦ nﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻱۀ ][ aﺑﻪ ﺩﻧﺒﺎﻝ xﻣﻲﮔﺮﺩﺩ .ﺍﮔﺮ xﭘﻴﺪﺍ ﺷﻮﺩ ﺁﻧﮕﺎﻩ
ﺍﻭﻟﻴﻦ ﻣﺤﻠﻲ ﮐﻪ xﺩﺭ ﺁﻥ ﻭﺍﻗﻊ ﺷﺪﻩ ،ﺣﺬﻑ ﻣﻲﺷﻮﺩ ﻭ ﺗﻤﺎﻡ ﻋﻨﺎﺻﺮ ﺑﻌﺪﻱ ﻳﮏ ﭘﻠﻪ ﺑﻪ
ﻋﻘﺐ ﮐﺸﻴﺪﻩ ﻣﻲﺷﻮﻧﺪ ﻭ nﻧﻴﺰ ﻳﮏ ﻭﺍﺣﺪ ﮐﺎﻫﺶ ﻣﻲﻳﺎﺑﺪ ﻭ ﻣﻘﺪﺍﺭ trueﻧﻴﺰ ﺑﺎﺯﮔﺸﺖ
ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ ﺗﺎ ﻣﺸﺨﺺ ﮐﻨﺪ ﮐﻪ ﺣﺬﻑ ﻣﻮﻓﻘﻴﺖﺁﻣﻴﺰ ﺑﻮﺩﻩ ﺍﺳﺖ .ﺍﮔﺮ xﭘﻴﺪﺍ ﻧﺸﻮﺩ ،ﺁﺭﺍﻳﻪ
ﺑﺪﻭﻥ ﺗﻐﻴﻴﺮ ﻣﻲﻣﺎﻧﺪ ﻭ ﻣﻘﺪﺍﺭ falseﺑﺮﮔﺮﺩﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ) .ﺑﻪ ﻣﺴﺎﻝۀ 12ﻧﮕﺎﻩ ﮐﻨﻴﺪ(
‐14ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﻋﻨﺎﺻﺮﻱ ﺭﺍ ﺍﺯ ﺁﺭﺍﻳﻪ ﺣﺬﻑ ﻣﻲﮐﻨﺪ:
;)void removeAll(float a[], int& n, float x
ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﻫﻢۀ ﻋﻨﺎﺻﺮﻱ ﮐﻪ ﺑﺎ xﺑﺮﺍﺑﺮﻧﺪ ﺭﺍ ﺍﺯ nﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻳﻪ ﺣﺬﻑ ﻣﻲﮐﻨﺪ ﻭ nﺭﺍ
ﺑﻪ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺣﺬﻑ ﺷﺪﻩ ،ﮐﺎﻫﺶ ﻣﻲﺩﻫﺪ) .ﺑﻪ ﻣﺴﺎﻝۀ 13ﻧﮕﺎﻩ ﮐﻨﻴﺪ(
ﺗﺎﺑﻊ ﺑﺎﻻ ،ﺣﺎﺻﻞ ﺿﺮﺏ ﺑﻴﺮﻭﻧﻲ ﺳﻪ ﻋﻨﺼﺮ ﺍﻭﻝ aﺑﺎ ﺳﻪ ﻋﻨﺼﺮ ﺍﻭﻝ bﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ aﺑﺮﺍﺑﺮ ﺑﺎ } {2.2,3.3,4.4ﻭ bﺑﺮﺍﺑﺮ ﺑﺎ }{2.0,-1.0,0.0
ﺑﺎﺷﺪ ،ﻓﺮﺍﺧﻮﺍﻧﻲ ;) outerProduct(p,a,bﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﺁﺭﺍﻱ ۀ ﺩﻭ ﺑﻌﺪﻱ pﺑﻪ
ﺻﻮﺭﺕ ﺯﻳﺮ ﺗﺒﺪﻳﻞ ﺷﻮﺩ:
4.4 -2.2 0.0
6.6 -3.3 0.0
8.8 -4.4 0.0
ﻋﻨﺼﺮ ] p[i][jﺣﺎﺻﻞ ﺿﺮﺏ ] a[iﺑﺎ ] b[jﺍﺳﺖ.
7‐1ﻣﻘﺪﻣﻪ
0x00000000
0x00000001
ﺣﺎﻓﻆۀ ﺭﺍﻳﺎﻧﻪ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺻﻮﺭﺕ ﻳﮏ ﺁﺭﺍﻱۀ ﺑﺰﺭﮒ ﺩﺭ
0x00000002
0x00000003
0x00000004
0x00000005
ﻧﻈﺮ ﮔﺮﻓﺖ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺭﺍﻳﺎﻧﻪﺍﻱ ﺑﺎ 256ﻣﮕﺎﺑﺎﻳﺖ RAMﺩﺭ
0x00000006
0x00000007
…
ﺣﻘﻴﻘﺖ ﺣﺎﻭﻱ ﺁﺭﺍﻳﻪﺍﻱ ﺑﻪ ﺍﻧﺪﺍﺯۀ 268،435،456
…
0x0064fdc5
0x0064fdc6 )= (228ﺧﺎﻧﻪ ﺍﺳﺖ ﮐﻪ ﺍﻧﺪﺍﺯۀ ﻫﺮ ﺧﺎﻧﻪ ﻳﮏ ﺑﺎﻳﺖ ﺍﺳﺖ .ﺍﻳﻦ
0x0064fdc7
0x0064fdc8
…
…
ﺧﺎﻧﻪﻫﺎ ﺩﺍﺭﺍﻱ ﺍﻳﻨﺪﮐﺲ ﺻﻔﺮ ﺗﺎ 268،435،455ﻫﺴﺘﻨﺪ.
0x0ffffffe
0x0fffffff
ﺑﻪ ﺍﻳﻨﺪﮐﺲ ﻫﺮ ﺑﺎﻳﺖ ،ﺁﺩﺭﺱ ﺣﺎﻓﻆۀ ﺁﻥ ﻣﻲﮔﻮﻳﻨﺪ .ﺁﺩﺭﺱﻫﺎﻱ
ﺣﺎﻓﻈﻪ ﺭﺍ ﺑﺎ ﺍﻋﺪﺍﺩ ﺷﺎﻧﺰﺩﻩﺩﻫﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ .ﭘﺲ ﺭﺍﻳﺎﻥۀ ﻣﺬﮐﻮﺭ
ﺩﺍﺭﺍﻱ ﻣﺤﺪﻭﺩﻩ ﺁﺩﺭﺱ 0x00000000ﺗﺎ 0x0fffffffﻣﻲﺑﺎﺷﺪ .ﻫﺮ ﻭﻗﺖ ﮐﻪ
ﻣﺘﻐﻴﺮﻱ ﺭﺍ ﺍﻋﻼﻥ ﻣﻲﮐﻨﻴﻢ ،ﺳﻪ ﻭﻳﮋﮔﻲ ﺍﺳﺎﺳﻲ ﺑﻪ ﺁﻥ ﻣﺘﻐﻴﺮ ﻧﺴﺒﺖ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ» :ﻧﻮﻉ
ﻣﺘﻐﻴﺮ« ﻭ »ﻧﺎﻡ ﻣﺘﻐﻴﺮ« ﻭ »ﺁﺩﺭﺱ ﺣﺎﻓﻈﻪ« ﺁﻥ .ﻣﺜﻼ ﺍﻋﻼﻥ ; int nﻧﻮﻉ intﻭ ﻧﺎﻡ nﻭ
ﺁﺩﺭﺱ ﭼﻨﺪ ﺧﺎﻧﻪ ﺍﺯ ﺣﺎﻓﻈﻪ ﮐﻪ ﻣﻘﺪﺍﺭ nﺩﺭ ﺁﻥ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﺭﺍ ﺑﻪ ﻳﮑﺪﻳﮕﺮ ﻣﺮﺗﺒﻂ
ﻣﻲﺳﺎﺯﺩ .ﻓﺮﺽ ﮐﻨﻴﺪ ﺁﺩﺭﺱ ﺍﻳﻦ ﻣﺘﻐﻴﺮ 0x0050cdc0ﺍﺳﺖ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻣﻲﺗﻮﺍﻧﻴﻢ nﺭﺍ
n ﺧﻮﺩ ﻣﺘﻐﻴﺮ ﺑﻪ ﺷﮑﻞ ﺟﻌﺒﻪ ﻧﻤﺎﻳﺶ ﺩﺍﺩﻩ ﺷﺪﻩ .ﻧﺎﻡ ﻣﺘﻐﻴﺮ،
0x0050cdc0
،nﺩﺭ ﺑﺎﻻﻱ ﺟﻌﺒﻪ ﺍﺳﺖ ﻭ ﺁﺩﺭﺱ ﻣﺘﻐﻴﺮ ﺩﺭ ﺳﻤﺖ ﭼﭗ ﺟﻌﺒﻪ ﻭ
int
ﻧﻮﻉ ﻣﺘﻐﻴﺮ ،int ،ﺩﺭ ﺯﻳﺮ ﺟﻌﺒﻪ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ .ﺩﺭ ﺑﻴﺸﺘﺮ
ﺭﺍﻳﺎﻧﻪﻫﺎ ﻧﻮﻉ intﭼﻬﺎﺭ ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ ﻣﻲﻧﻤﺎﻳﺪ.
0x0050cdb8
0x0050cdb9
0x0050cdc0
0x0050cdc1
ﺑﻨﺎﺑﺮﺍﻳﻦ ﻫﻤﺎﻥ ﻃﻮﺭ ﮐﻪ ﺩﺭ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ،
0x0050cdc2
0x0050cdc3
0x0050cdc4
ﻣﺘﻐﻴﺮ nﻳﮏ ﺑﻠﻮﮎ ﭼﻬﺎﺭﺑﺎﻳﺘﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ ﻣﻲﮐﻨﺪ ﮐﻪ
0x0050cdc5
7‐1ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ
ﺩﺭ C++ﺑﺮﺍﻱ ﺑﺪﺳﺖ ﺁﻭﺭﺩﻥ ﺁﺩﺭﺱ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ& 1
ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﻮﺩ .ﺑﻪ ﺍﻳﻦ ﻋﻤﻠﮕﺮ »ﻋﻠﻤﮕﺮ ﺁﺩﺭﺱ« ﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ .ﻋﺒﺎﺭﺕ &nﺁﺩﺭﺱ ﻣﺘﻐﻴﺮ nﺭﺍ
ﺑﻪ ﺩﺳﺖ ﻣﻲﺩﻫﺪ.
ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﻛﻪ ﺁﺩﺭﺱ nﺩﺭ ﺍﻳﻦ ﺍﺟﺮﺍ ﺑﺮﺍﺑﺮ ﺑﺎ 0x00c9fdc3ﺍﺳﺖ .ﻣﻲﺗﻮﺍﻥ
ﻓﻬﻤﻴﺪ ﮐﻪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﺎﻳﺪ ﻳﮏ ﺁﺩﺭﺱ ﺑﺎﺷﺪ ﺯﻳﺮﺍ ﺑﻪ ﺷﮑﻞ ﺷﺎﻧﺰﺩﻩﺩﻫﻲ ﻧﻤﺎﻳﺶ ﺩﺍﺩﻩ ﺷﺪﻩ.
ﺍﻋﺪﺍﺩ ﺷﺎﻧﺰﺩﻩﺩﻫﻲ ﺭﺍ ﺍﺯ ﺭﻭﻱ ﻋﻼﻣﺖ 0xﻣﻲﺗﻮﺍﻥ ﺗﺸﺨﻴﺺ ﺩﺍﺩ .ﻣﻌﺎﺩﻝ ﺩﻫﺪﻫﻲ ﻋﺪﺩ ﺑﺎﻻ
ﻣﻘﺪﺍﺭ 13,237,699ﻣﻲﺑﺎﺷﺪ.
ﻧﻤﺎﻳﺶ ﺩﺍﺩﻥ ﺁﺩﺭﺱ ﻳﮏ ﻣﺘﻐﻴﺮ ﺑﻪ ﺍﻳﻦ ﺷﻴﻮﻩ ﺧﻴﻠﻲ ﻣﻔﻴﺪ ﻧﻴﺴﺖ .ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ &
ﺍﺳﺘﻔﺎﺩﻩﻫﺎﻱ ﻣﻬﻢﺗﺮﻱ ﺩﺍﺭﺩ .ﻳﮏ ﮐﺎﺭﺑﺮﺩ ﺁﻥ ﺭﺍ ﺩﺭ ﻓﺼﻞ ﭘﻨﺠﻢ ﮔﻔﺘﻪﺍﻳﻢ :ﺳﺎﺧﺘﻦ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ
ﺍﺭﺟﺎﻉ ﺩﺭ ﺍﻋﻼﻥ ﺗﺎﺑﻊ .ﺍﮐﻨﻮﻥ ﮐﺎﺭﺑﺮﺩ ﺩﻳﮕﺮﻱ ﻣﻌﺮﻓﻲ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﺧﻴﻠﻲ ﺑﻪ ﮐﺎﺭﺑﺮﺩ ﻗﺒﻠﻲ ﺷﺒﻴﻪ
ﺍﺳﺖ؛ ﺍﻋﻼﻥ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﺭﺟﺎﻉ.
7‐2ﺍﺭﺟﺎﻉﻫﺎ
ﻳﻚ »ﺍﺭﺟﺎﻉ« ﻳﻚ ﺍﺳﻢ ﻣﺴﺘﻌﺎﺭ ﻳﺎ ﻭﺍﮊۀ ﻣﺘﺮﺍﺩﻑ ﺑﺮﺍﻱ ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮ ﺍﺳﺖ .ﻧﺤﻮ ﺍﻋﻼﻥ
ﻳﮏ ﺍﺭﺟﺎﻉ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
;type& ref_name = var_name
rnﻳﮏ ﺍﺭﺟﺎﻉ ﻳﺎ ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺑﺮﺍﻱ nﺍﺳﺖ .ﺍﻟﺒﺘﻪ nﺑﺎﻳﺪ ﻗﺒﻼ ﺍﻋﻼﻥ ﺷﺪﻩ ﺑﺎﺷﺪ.
nﻭ rnﻧﺎﻡﻫﺎﻱ ﻣﺘﻔﺎﻭﺗﻲ ﺑﺮﺍﻱ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺳﺖ .ﺍﻳﻦ ﺩﻭ ﻫﻤﻴﺸﻪ ﻣﻘﺪﺍﺭ ﻳﮑﺴﺎﻧﻲ ﺩﺍﺭﻧﺪ .ﺍﮔﺮ
nﮐﺎﺳﺘﻪ ﺷﻮﺩ rn ،ﻧﻴﺰ ﮐﺎﺳﺘﻪ ﺷﺪﻩ ﻭ ﺍﮔﺮ rnﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ n ،ﻧﻴﺰ ﺍﻓﺰﺍﻳﺶ ﻳﺎﻓﺘﻪ ﺍﺳﺖ.
ﻫﻤﺎﻧﻨﺪ ﺛﺎﺑﺖﻫﺎ ،ﺍﺭﺟﺎﻉﻫﺎ ﺑﺎﻳﺪ ﻫﻨﮕﺎﻡ ﺍﻋﻼﻥ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺷﻮﻧﺪ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ
ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ ﻳﮏ ﺍﺭﺟﺎﻉ ،ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺳﺖ ﻧﻪ ﻳﮏ ﻟﻴﺘﺮﺍﻝ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﮐﺪ ﺯﻳﺮ ﺍﺷﺘﺒﺎﻩ ﺍﺳﺖ:
;int& rn=44 ;// ERROR: 44 is not a variable
ﮔﺮﭼﻪ ﺑﺮﺧﻲ ﺍﺯ ﮐﺎﻣﭙﺎﻳﻠﺮﻫﺎ ﻣﻤﮑﻦ ﺍﺳﺖ ﺩﺳﺘﻮﺭ ﺑﺎﻻ ﺭﺍ ﻣﺠﺎﺯ ﺑﺪﺍﻧﻨﺪ ﻭﻟﻲ ﺑﺎ ﻧﺸﺎﻥ ﺩﺍﺩﻥ ﻳﮏ
ﻫﺸﺪﺍﺭ ﺍﻋﻼﻡ ﻣﻲﮐﻨﻨﺪ ﮐﻪ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻮﻗﺘﻲ ﺍﻳﺠﺎﺩ ﺷﺪﻩ ﺗﺎ rnﺑﻪ ﺣﺎﻓﻆۀ ﺁﻥ ﻣﺘﻐﻴﺮ ،ﺍﺭﺟﺎﻉ
ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ.
ﺩﺭﺳﺖ ﺍﺳﺖ ﮐﻪ ﺍﺭﺟﺎﻉ ﺑﺎ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﺷﻮﺩ ،ﺍﻣﺎ ﺍﺭﺟﺎﻉ ﺑﻪ ﺧﻮﺩﻱ ﺧﻮﺩ
ﻳﮏ ﻣﺘﻐﻴﺮ ﻧﻴﺴﺖ .ﻳﮏ ﻣﺘﻐﻴﺮ ،ﻓﻀﺎﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻭ ﻧﺸﺎﻧﻲ ﻣﺴﺘﻘﻞ ﺩﺍﺭﺩ ،ﺣﺎﻝ ﺁﻥ ﮐﻪ
ﺍﺭﺟﺎﻉ ﺍﺯ ﻓﻀﺎﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻭ ﻧﺸﺎﻧﻲ ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮﻱ ﺑﻬﺮﻩ ﻣﻲﺑﺮﺩ.
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻓﻮﻕ ﻓﻘﻂ ﻳﮏ ﺷﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﻭ ﺁﻥ ﻫﻢ nﺍﺳﺖ rn .ﻭ rn2ﻭ rn3
ﺍﺭﺟﺎﻉﻫﺎﻳﻲ ﺑﻪ nﻫﺴﺘﻨﺪ .ﺧﺮﻭﺟﻲ ﻧﻴﺰ ﺗﺎﻳﻴﺪ ﻣﻲﮐﻨﺪ ﮐﻪ ﺁﺩﺭﺱ rnﻭ rn2ﻭ rn3ﺑﺎ
ﺁﺩﺭﺱ nﻳﮑﻲ ﺍﺳﺖ .ﻳﮏ ﺷﻲ ﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪ ﺍﺭﺟﺎﻉ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 218
ﺍﺭﺟﺎﻉﻫﺎ ﺑﻴﺸﺘﺮ ﺑﺮﺍﻱ ﺳﺎﺧﺘﻦ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺭﺟﺎﻉ ﺩﺭ ﺗﻮﺍﺑﻊ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ .ﺗﺎﺑﻊ
ﻣﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ﻳﮏ ﺁﺭﮔﻮﻣﺎﻥ ﺭﺍ ﮐﻪ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺗﻐﻴﻴﺮ ﺩﻫﺪ ﺯﻳﺮﺍ ﺁﺭﮔﻮﻣﺎﻥ
ﺍﺻﻠﻲ ﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺭﺟﺎﻉ ﻫﺮ ﺩﻭ ﻳﮏ ﺷﻲ ﻫﺴﺘﻨﺪ .ﺗﻨﻬﺎ ﻓﺮﻕ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺩﺍﻣﻦۀ ﭘﺎﺭﺍﻣﺘﺮ
ﺍﺭﺟﺎﻉ ﺑﻪ ﻫﻤﺎﻥ ﺗﺎﺑﻊ ﻣﺤﺪﻭﺩ ﺷﺪﻩ ﺍﺳﺖ.
7‐3ﺍﺷﺎﺭﻩﮔﺮﻫﺎ
ﻣﻲﺩﺍﻧﻴﻢ ﮐﻪ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺭﺍ ﺑﺎﻳﺪ ﺩﺭ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ intﻧﮕﻬﺪﺍﺭﻱ ﮐﻨﻴﻢ ﻭ ﺍﻋﺪﺍﺩ
ﺍﻋﺸﺎﺭﻱ ﺭﺍ ﺩﺭ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺍﺯ ﻧﻮﻉ .floatﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﺑﺎﻳﺪ ﺩﺭ
ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺍﺯ ﻧﻮﻉ charﻧﮕﻬﺪﺍﺭﻳﻢ ﻭ ﻣﻘﺪﺍﺭﻫﺎﻱ ﻣﻨﻄﻘﻲ ﺭﺍ ﺩﺭ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺍﺯ ﻧﻮﻉ .bool
ﺍﻣﺎ ﺁﺩﺭﺱ ﺣﺎﻓﻈﻪ ﺭﺍ ﺩﺭ ﭼﻪ ﻧﻮﻉ ﻣﺘﻐﻴﺮﻱ ﺑﺎﻳﺪ ﻗﺮﺍﺭ ﺩﻫﻴﻢ؟
ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﺁﺩﺭﺱ ﺣﺎﻓﻆۀ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻮﺟﻮﺩ ﺭﺍ ﺑﻪ ﺩﺳﺖ ﻣﻲﺩﻫﺪ .ﻣﻲﺗﻮﺍﻥ ﺍﻳﻦ
ﺁﺩﺭﺱ ﺭﺍ ﺩﺭ ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮﻱ ﺫﺧﻴﺮﻩ ﻧﻤﻮﺩ .ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﻳﮏ ﺁﺩﺭﺱ ﺩﺭ ﺁﻥ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ
ﺍﺷﺎﺭﻩﮔﺮ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺍﻋﻼﻥ ﮐﻨﻴﻢ ،ﺍﺑﺘﺪﺍ ﺑﺎﻳﺪ ﻣﺸﺨﺺ ﮐﻨﻴﻢ
ﮐﻪ ﺁﺩﺭﺱ ﭼﻪ ﻧﻮﻉ ﺩﺍﺩﻩﺍﻱ ﻗﺮﺍﺭ ﺍﺳﺖ ﺩﺭ ﺁﻥ ﺫﺧﻴﺮﻩ ﺷﻮﺩ .ﺳﭙﺲ ﺍﺯ ﻋﻤﻠﮕﺮ ﺍﺷﺎﺭﻩ *
ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ ﺗﺎ ﺍﺷﺎﺭﻩﮔﺮ ﺭﺍ ﺍﻋﻼﻥ ﮐﻨﻴﻢ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺩﺳﺘﻮﺭ :
;float* px
ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﻧﺎﻡ pxﺍﻋﻼﻥ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ ،ﺁﺩﺭﺱ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺍﺯ ﻧﻮﻉ float
ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﻧﻤﺎﻳﺪ .ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ ﺑﺮﺍﻱ ﺍﻋﻼﻥ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺍﺯ ﻧﺤﻮ ﺯﻳﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ:
;type* pointername
ﮐﻪ typeﻧﻮﻉ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺍﺳﺖ ﮐﻪ ﺍﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ ﺁﺩﺭﺱ ﺁﻥﻫﺎ ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﮐﻨﺪ ﻭ
pointernameﻧﺎﻡ ﺍﺷﺎﺭﻩﮔﺮ ﺍﺳﺖ.
ﺁﺩﺭﺱ ﻳﮏ ﺷﻲ ﺍﺯ ﻧﻮﻉ intﺭﺍ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺯ ﻧﻮﻉ * intﺫﺧﻴﺮﻩ
ﮐﺮﺩ ﻭ ﺁﺩﺭﺱ ﻳﮏ ﺷﻲ ﺍﺯ ﻧﻮﻉ floatﺭﺍ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺯ ﻧﻮﻉ *float
ﺫﺧﻴﺮﻩ ﻧﻤﻮﺩ .ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ،ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﺴﺘﻘﻞ ﺍﺳﺖ.
219 ﻓﺼﻞ هﻔﺘﻢ /اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ
7‐4ﻣﻘﺪﺍﺭﻳﺎﺑﻲ
ﻓﺮﺽ ﮐﻨﻴﺪ nﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ 22ﺑﺎﺷﺪ ﻭ pnﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ nﺑﺎﺷﺪ .ﺑﺎ ﺍﻳﻦ ﺣﺴﺎﺏ
ﺑﺎﻳﺪ ﺑﺘﻮﺍﻥ ﺍﺯ ﻃﺮﻳﻖ pnﺑﻪ ﻣﻘﺪﺍﺭ 22ﺭﺳﻴﺪ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ * ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ
ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﺭﺍ ﺑﻪ ﺩﺳﺖ ﺁﻭﺭﺩ .ﺑﻪ ﺍﻳﻦ ﮐﺎﺭ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ ﺍﺷﺎﺭﻩﮔﺮ ﻣﻲﮔﻮﻳﻴﻢ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 220
}
n = 44 n 44
&n = 0x0064fd78 int
pn = 0x0064fd78
&pn = 0x0064fd7c
*pn = 44 pn
*int
ppn = 0x0064fd7c
&ppn = 0x0064fd80
*ppn = 0x0064fd78 ppn
**ppn = 44 **int
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺘﻐﻴﺮ nﺍﺯ ﻧﻮﻉ intﺗﻌﺮﻳﻒ ﺷﺪﻩ pn .ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺳﺖ ﮐﻪ ﺑﻪ nﺍﺷﺎﺭﻩ
ﺩﺍﺭﺩ .ﭘﺲ ﻧﻮﻉ pnﺑﺎﻳﺪ * intﺑﺎﺷﺪ ppn .ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺳﺖ ﮐﻪ ﺑﻪ pnﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ.
ﭘﺲ ﻧﻮﻉ ppnﺑﺎﻳﺪ ** intﺑﺎﺷﺪ .ﻫﻤﭽﻨﻴﻦ ﭼﻮﻥ ppnﺑﻪ pnﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ،ﭘﺲ *ppn
ﻣﻘﺪﺍﺭ pnﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﻭ ﭼﻮﻥ pnﺑﻪ nﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ،ﭘﺲ *pnﻣﻘﺪﺍﺭ nﺭﺍ ﻣﻲﺩﻫﺪ.
ﺍﮔﺮ ﺍﻳﻦ ﺩﻭ ﺩﺳﺘﻮﺭ ﺭﺍ ﮐﻨﺎﺭ ﻫﻢ ﺑﭽﻴﻨﻴﻢ ﻧﺘﻴﺠﻪ ﺍﻳﻦ ﻣﻲﺷﻮﺩ ﮐﻪ **ppnﻣﻘﺪﺍﺭ nﺭﺍ ﺑﺮ
ﻣﻲﮔﺮﺩﺍﻧﺪ .ﺧﺮﻭﺟﻲ ﺣﺎﺻﻞ ﺍﺯ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﻳﻦ ﮔﻔﺘﻪﻫﺎ ﺭﺍ ﺗﺼﺪﻳﻖ ﻣﻲﻧﻤﺎﻳﺪ.
ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ ﺍﮔﺮ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ Tﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺁﻥ ﺍﺯ ﻧﻮﻉ * Tﺧﻮﺍﻫﺪ
ﺑﻮﺩ .ﺑﻪ * Tﻳﮏ ﻧﻮﻉ »ﻣﺸﺘﻖﺷﺪﻩ« ﻣﻲﮔﻮﻳﻨﺪ ﺯﻳﺮﺍ ﺍﺯ ﺭﻭﻱ ﻧﻮﻉ ﺩﻳﮕﺮﻱ ﺳﺎﺧﺘﻪ ﺷﺪﻩ ﺍﺳﺖ.
* Tﺧﻮﺩ ﻳﮏ ﻧﻮﻉ ﺟﺪﻳﺪ ﺍﺳﺖ .ﺣﺎﻝ ﺍﮔﺮ ﺑﺨﻮﺍﻫﻴﻢ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﻧﻮﻉ * Tﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ
)ﻳﻌﻨﻲ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺩﻳﮕﺮ( ﻃﺒﻖ ﻗﺎﻋﺪۀ ﻓﻮﻕ ﺍﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ ﺟﺪﻳﺪ ﺭﺍ ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ
** Tﺗﻌﺮﻳﻒ ﻧﻤﻮﺩ .ﻧﻤﻮﺩﺍﺭ ﻓﻮﻕ ﻧﺤﻮۀ ﮐﺎﺭ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
ﮔﺮﭼﻪ pnﻭ ppnﻫﺮ ﺩﻭ ﺍﺷﺎﺭﻩﮔﺮ ﻫﺴﺘﻨﺪ ﺍﻣﺎ ﺍﺯ ﻳﮏ ﻧﻮﻉ ﻧﻴﺴﺘﻨﺪ pn .ﺍﺯ ﻧﻮﻉ
* intﺍﺳﺖ ﻭ ppnﺍﺯ ﻧﻮﻉ ** intﺍﺳﺖ.
ﻋﻤﻠﮕﺮ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ * ﻭ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﻣﻌﮑﻮﺱ ﻳﮑﺪﻳﮕﺮ ﺭﻓﺘﺎﺭ ﻣﻲﮐﻨﻨﺪ .ﺍﮔﺮ ﺍﻳﻦ
ﺩﻭ ﺭﺍ ﺑﺎ ﻫﻢ ﺗﺮﮐﻴﺐ ﮐﻨﻴﻢ ،ﻳﮑﺪﻳﮕﺮ ﺭﺍ ﺧﻨﺜﻲ ﻣﻲﻧﻤﺎﻳﻨﺪ .ﺍﮔﺮ nﻳﮏ ﻣﺘﻐﻴﺮ ﺑﺎﺷﺪ &n ،ﺁﺩﺭﺱ
ﺁﻥ ﻣﺘﻐﻴﺮ ﺍﺳﺖ .ﺍﺯ ﻃﺮﻓﻲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ * ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺩﺭ ﺁﺩﺭﺱ &nﻗﺮﺍﺭ
ﮔﺮﻓﺘﻪ ﺭﺍ ﺑﻪ ﺩﺳﺖ ﺁﻭﺭﺩ .ﺑﻨﺎﺑﺮﺍﻳﻦ *&nﺑﺮﺍﺑﺮ ﺑﺎ ﺧﻮﺩ nﺧﻮﺍﻫﺪ ﺑﻮﺩ .ﻫﻤﭽﻨﻴﻦ ﺍﮔﺮ pﻳﮏ
ﺍﺷﺎﺭﻩﮔﺮ ﺑﺎﺷﺪ *p ،ﻣﻘﺪﺍﺭﻱ ﮐﻪ pﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﺭﺍ ﻣﻲﺩﻫﺪ .ﺍﺯ ﻃﺮﻓﻲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﻋﻤﻠﮕﺮ & ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﺩﺭﺱ ﭼﻴﺰﻱ ﮐﻪ ﺩﺭ *pﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺭﺍ ﺑﺪﺳﺖ ﺁﻭﺭﻳﻢ .ﭘﺲ &*pﺑﺮﺍﺑﺮ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 222
ﺑﺎ ﺧﻮﺩ pﺧﻮﺍﻫﺪ ﺑﻮﺩ .ﺗﺮﺗﻴﺐ ﻗﺮﺍﺭﮔﺮﻓﺘﻦ ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﻣﻬﻢ ﺍﺳﺖ .ﻳﻌﻨﻲ *&nﺑﺎ &*n
ﺑﺮﺍﺑﺮ ﻧﻴﺴﺖ .ﻋﻠﺖ ﺍﻳﻦ ﺍﻣﺮ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ.
ﻋﻤﻠﮕﺮ * ﺩﻭ ﮐﺎﺭﺑﺮﺩ ﺩﺍﺭﺩ .ﺍﮔﺮ ﭘﺴﻮﻧ ِﺪ ﻳﮏ ﻧﻮﻉ ﺑﺎﺷﺪ )ﻣﺜﻞ * (intﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ
ﺑﻪ ﺁﻥ ﻧﻮﻉ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﻭ ﺍﮔﺮ ﭘﻴﺸﻮﻧ ِﺪ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﺎﺷﺪ )ﻣﺜﻞ (*pﺁﻧﮕﺎﻩ ﻣﻘﺪﺍﺭﻱ
ﮐﻪ pﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﻋﻤﻠﮕﺮ & ﻧﻴﺰ ﺩﻭ ﮐﺎﺭﺑﺮﺩ ﺩﺍﺭﺩ .ﺍﮔﺮ ﭘﺴﻮﻧﺪ ﻳﮏ
ﻧﻮﻉ ﺑﺎﺷﺪ )ﻣﺜﻞ & (intﻳﮏ ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﻭ ﺍﮔﺮ ﭘﻴﺸﻮﻧﺪ ﻳﮏ ﻣﺘﻐﻴﺮ ﺑﺎﺷﺪ
)ﻣﺜﻞ (&nﺁﺩﺭﺱ ﺁﻥ ﻣﺘﻐﻴﺮ ﺭﺍ ﻣﻲﺩﻫﺪ.
ﺑﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﭼﭗﻣﻘﺪﺍﺭﻫﺎ ،ﭼﭗﻣﻘﺪﺍﺭﻫﺎﻱ »ﺗﻐﻴﻴﺮ ﻧﺎﭘﺬﻳﺮ« ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ .ﻣﺜﻞ ﺁﺭﺍﻳﻪﻫﺎ:
;}int a[] = {1,2,3 // O.K
;}a[] = {1,2,3 // ERROR
ﻳﮏ ﺗﺎﺑﻊ ،ﭼﭗﻣﻘﺪﺍﺭ ﻧﻴﺴﺖ ﺍﻣﺎ ﺍﮔﺮ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺁﻥ ﻳﮏ ﺍﺭﺟﺎﻉ ﺑﺎﺷﺪ ،ﻣﻲﺗﻮﺍﻥ
ﺗﺎﺑﻊ ﺭﺍ ﺑﻪ ﻳﮏ ﭼﭗﻣﻘﺪﺍﺭ ﺗﺒﺪﻳﻞ ﮐﺮﺩ.
ﻭﻗﺘﻲ ﺑﺎﺯﮔﺸﺖ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺑﺎﺷﺪ ،ﺗﺎﺑﻊ ﻳﮏ ﭼﭗﻣﻘﺪﺍﺭ ﺧﻮﺍﻫﺪ ﺑﻮﺩ ﺯﻳﺮﺍ
ﺍﺭﺟﺎﻉﻫﺎ ﭼﭗﻣﻘﺪﺍﺭ ﻫﺴﺘﻨﺪ .ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺗﺎﺑﻊ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﺳﻤﺖ ﭼﭗ ﻳﮏ ﺟﺎﻳﮕﺰﻳﻨﻲ
;f() = m ﻗﺮﺍﺭ ﺩﺍﺩ ﻣﺜﻞ :
ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ ﺭﺍ ﺑﻪ ﺍﺭﺟﺎﻉ ﺗﺒﺪﻳﻞ ﮐﻨﻴﻢ ﮐﺎﻓﻲ ﺍﺳﺖ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ
ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﭘﺴﻮﻧﺪ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺩﺭﺝ ﮐﻨﻴﻢ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 224
ﺗﺎﺑﻊ )( maxﺍﺯ ﺑﻴﻦ mﻭ nﻣﻘﺪﺍﺭ ﺑﺰﺭﮒﺗﺮ ﺭﺍ ﭘﻴﺪﺍ ﮐﺮﺩﻩ ﻭ ﺳﭙﺲ ﺍﺭﺟﺎﻋﻲ ﺑﻪ ﺁﻥ ﺭﺍ ﺑﺎﺯ
ﻣﻲﮔﺮﺩﺍﻧﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﺍﮔﺮ mﺍﺯ nﺑﺰﺭﮒﺗﺮ ﺑﺎﺷﺪ ،ﺗﺎﺑﻊ ) max(m,nﺁﺩﺭﺱ mﺭﺍ
ﻣﻘﺪﺍﺭ 55ﺩﺭ ﺣﻘﻴﻘﺖ ;max(m,n) = 55 ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﭘﺲ ﻭﻗﺘﻲ ﻣﻲﻧﻮﻳﺴﻴﻢ
ﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ mﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ )ﺍﮔﺮ m>nﺑﺎﺷﺪ( .ﺑﻪ ﺑﻴﺎﻧﻲ ﺳﺎﺩﻩ ،ﻓﺮﺍﺧﻮﺍﻧﻲ )max(m,n
ﺧﻮﺩ mﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ ﻧﻪ ﻣﻘﺪﺍﺭ ﺁﻥ ﺭﺍ.
ﺍﺧﻄﺎﺭ :ﻭﻗﺘﻲ ﻳﮏ ﺗﺎﺑﻊ ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ ،ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ ﺁﻥ ﻧﺎﺑﻮﺩ ﻣﻲﺷﻮﻧﺪ .ﭘﺲ ﻫﻴﭻ
ﻭﻗﺖ ﺍﺭﺟﺎﻋﻲ ﺑﻪ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ﺑﺎﺯﮔﺸﺖ ﻧﺪﻫﻴﺪ ﺯﻳﺮﺍ ﻭﻗﺘﻲ ﮐﺎﺭ ﺗﺎﺑﻊ ﺗﻤﺎﻡ ﺷﺪ ،ﺁﺩﺭﺱ
ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲﺍﺵ ﻏﻴﺮ ﻣﻌﺘﺒﺮ ﻣﻲﺷﻮﺩ ﻭ ﺍﺭﺟﺎﻉ ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﺷﺪﻩ ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﻪ ﻳﮏ
ﻣﻘﺪﺍﺭ ﻏﻴﺮ ﻣﻌﺘﺒﺮ ﺍﺷﺎﺭﻩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺗﺎﺑﻊ )( maxﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﻳﮏ ﺍﺭﺟﺎﻉ ﺑﻪ mﻳﺎ nﺭﺍ ﺑﺮ
ﻣﻲﮔﺮﺩﺍﻧﺪ .ﭼﻮﻥ mﻭ nﺧﻮﺩﺷﺎﻥ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﺷﺪﻩﺍﻧﺪ ،ﭘﺲ ﻣﺤﻠﻲ ﻧﻴﺴﺘﻨﺪ ﻭ
ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻥ ﺍﺭﺟﺎﻋﻲ ﺑﻪ ﺁﻥﻫﺎ ﺧﻠﻠﻲ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﻭﺍﺭﺩ ﻧﻤﻲﮐﻨﺪ.
ﺑﻪ ﺍﻋﻼﻥ ﺗﺎﺑﻊ )( maxﺩﻗﺖ ﮐﻨﻴﺪ:
)int& max(int& m, int& n
ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺁﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺍﺭﺟﺎﻉ ﺩﺭﺁﻣﺪﻩ ﺍﺳﺖ.
)(int main
;]{ float v[4
)for (int k = 1; k <= 4; k++
;component(v,k) = 1.0/k
)for (int i = 0; i < 4; i++
;cout << "v[" << i << "] = " << v[i] << endl
}
]v[0 = 1
]v[1 = 0.5
]v[2 = 0.333333
]v[3 = 0.25
ﺗﺎﺑﻊ )( componentﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ vﺍﺯ »ﺷﻤﺎﺭﻩﮔﺬﺍﺭﻱ ﺍﺯ ﺻﻔﺮ« ﺑﻪ
»ﺷﻤﺎﺭﻩﮔﺬﺍﺭﻱ ﺍﺯ ﻳﮏ« ﺗﻐﻴﻴﺮ ﮐﻨﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ ) component(v,3ﻣﻌﺎﺩﻝ ] v[2ﺍﺳﺖ.
ﺍﻳﻦ ﮐﺎﺭ ﺍﺯ ﻃﺮﻳﻖ ﺑﺎﺯﮔﺸﺖ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﻣﻤﮑﻦ ﺷﺪﻩ ﺍﺳﺖ.
7‐8ﺁﺭﺍﻳﻪﻫﺎ ﻭ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ
ﮔﺮﭼﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺍﺯ ﺍﻧﻮﺍﻉ ﻋﺪﺩﻱ ﺻﺤﻴﺢ ﻧﻴﺴﺘﻨﺪ ﺍﻣﺎ ﺑﻌﻀﻲ ﺍﺯ ﺍﻋﻤﺎﻝ ﺣﺴﺎﺑﻲ ﺭﺍ
ﻣﻲﺗﻮﺍﻥ ﺭﻭﻱ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺍﻧﺠﺎﻡ ﺩﺍﺩ .ﺣﺎﺻﻞ ﺍﻳﻦ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺧﺎﻥۀ ﺩﻳﮕﺮﻱ ﺍﺯ
ﺣﺎﻓﻈﻪ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ .ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﺜﻞ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺍﻓﺰﺍﻳﺶ ﻭ ﻳﺎ ﮐﺎﻫﺶ ﺩﺍﺩ ﻭ
ﻣﻲﺗﻮﺍﻥ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﺑﻪ ﺁﻥﻫﺎ ﺍﺿﺎﻓﻪ ﻧﻤﻮﺩ ﻳﺎ ﺍﺯ ﺁﻥ ﮐﻢ ﮐﺮﺩ .ﺍﻟﺒﺘﻪ ﻣﻴﺰﺍﻥ ﺍﻓﺰﺍﻳﺶ ﻳﺎ
ﮐﺎﻫﺶ ﺍﺷﺎﺭﻩﮔﺮ ﺑﺴﺘﮕﻲ ﺑﻪ ﻧﻮﻉ ﺩﺍﺩﻩﺍﻱ ﺩﺍﺭﺩ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ .ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ
ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺜﺎﻝ ﺯﻳﺮ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﻴﻢ.
ﺗﺎﺑﻊ )( sizeofﺗﻌﺪﺍﺩ ﺑﺎﻳﺖﻫﺎﻳﻲ ﮐﻪ ﻳﮏ ﻧﻮﻉ ﺑﻨﻴﺎﺩﻱ ﺍﺷﻐﺎﻝ ﻣﻲﻧﻤﺎﻳﺪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
ﺧﻂ ﺩﻭﻡ ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻧﻮﻉ shortﺩﺭ ﺍﻳﻦ ﺭﺍﻳﺎﻧﻪ 2ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ
ﺍﺷﻐﺎﻝ ﻣﻲﮐﻨﺪ .ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﻧﻮﻉ shortﺑﺎ ﺳﻪ ﻋﻨﺼﺮ ﺍﻋﻼﻥ ﺷﺪﻩ .ﻫﻤﭽﻨﻴﻦ
ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻳﻲ ﺑﻪ ﻧﺎﻡ pﻭ endﺍﺯ ﻧﻮﻉ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ shortﺍﻋﻼﻥ ﺷﺪﻩﺍﻧﺪ .ﭼﻮﻥ p
ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ shortﺍﺳﺖ ،ﻫﺮ ﺯﻣﺎﻥ ﮐﻪ pﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ ،ﺩﻭ ﺑﺎﻳﺖ ﺑﻪ ﺁﺩﺭﺱ
ﺩﺭﻭﻥ pﺍﺿﺎﻓﻪ ﻣﻲﮐﻨﺪ ﻭ pﺩﺭ ﺣﻘﻴﻘﺖ ﺑﻪ ﻋﺪﺩ shortﺑﻌﺪﻱ ﭘﻴﺸﺮﻭﻱ ﻣﻲﻧﻤﺎﻳﺪ )ﻧﻪ ﺑﻪ
ﺧﺎﻥۀ ﺑﻌﺪﻱ ﺣﺎﻓﻈﻪ( .ﺩﺭ ﺣﻠﻖۀ forﺍﺑﺘﺪﺍ ﺁﺩﺭﺱ ﺁﺭﺍﻱۀ aﺩﺭﻭﻥ ﺍﺷﺎﺭﻩﮔﺮ pﻗﺮﺍﺭ
ﻣﻲﮔﻴﺮﺩ .ﭘﺲ pﺑﻪ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ .ﻫﺮ ﺑﺎﺭ ﮐﻪ ﺣﻠﻘﻪ ﺗﮑﺮﺍﺭ ﺷﻮﺩ ،ﻳﮏ
ﻭﺍﺣﺪ ﺑﻪ pﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ ﻭ pﺑﻪ ﻋﻨﺼﺮ ﺑﻌﺪﻱ ﺁﺭﺍﻳﻪ ﺍﺷﺎﺭﻩ ﻣﻲﻧﻤﺎﻳﺪ .ﻋﺒﺎﺭﺕ
; sum += *pﻧﻴﺰ ﻣﻘﺪﺍﺭ ﺁﻥ ﻋﻨﺼﺮ ﺭﺍ ﺩﺭﻳﺎﻓﺖ ﮐﺮﺩﻩ ﻭ ﺑﻪ ﻣﻘﺪﺍﺭ sumﺍﺿﺎﻓﻪ ﻣﻲﮐﻨﺪ.
ﺍﻳﻦ ﻣﺜﺎﻝ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻫﺮ ﮔﺎﻩ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ ،ﻣﻘﺪﺍﺭ ﺁﻥ ﺑﻪ ﺍﻧﺪﺍﺯۀ
ﺗﻌﺪﺍﺩ ﺑﺎﻳﺖﻫﺎﻱ ﺷﻴﺌﻲ ﮐﻪ ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ،ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ .ﻣﺜﻼ ﺍﮔﺮ pﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ
227 ﻓﺼﻞ هﻔﺘﻢ /اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ
ﺍﮔﺮ floatﻫﺎ 4ﺑﺎﻳﺖ ﺭﺍ ﺍﺷﻐﺎﻝ ﻛﻨﻨﺪ ﺁﻧﮕﺎﻩ ++pﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ pﺭﺍ 4ﺑﺎﻳﺖ ﺍﻓﺰﺍﻳﺶ
ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ pﺭﺍ 20ﺑﺎﻳﺖ ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﻲﺩﻫﺪ ﻭ ;p += 5
ﺧﺎﺻﻴﺖ ﻣﺬﮐﻮﺭ ﻣﻲﺗﻮﺍﻥ ﺁﺭﺍﻳﻪ ﺭﺍ ﭘﻴﻤﺎﻳﺶ ﻧﻤﻮﺩ :ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺭﺍ ﺑﺎ ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ
ﺁﺭﺍﻳﻪ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﻨﻴﺪ ،ﺳﭙﺲ ﺍﺷﺎﺭﻩﮔﺮ ﺭﺍ ﭘﻲ ﺩﺭ ﭘﻲ ﺍﻓﺰﺍﻳﺶ ﺩﻫﻴﺪ .ﻫﺮ ﺍﻓﺰﺍﻳﺶ ﺳﺒﺐ
ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻋﻨﺼﺮ ﺑﻌﺪﻱ ﺁﺭﺍﻳﻪ ﺍﺷﺎﺭﻩ ﮐﻨﺪ .ﻳﻌﻨﻲ ﺍﺷﺎﺭﻩﮔﺮﻱ ﮐﻪ ﺑﻪ ﺍﻳﻦ ﻧﺤﻮ ﺑﻪ
ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﺷﻮﺩ ﻣﺜﻞ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﻋﻤﻞ ﻣﻲﮐﻨﺪ .ﻫﻤﭽﻨﻴﻦ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ ﻣﻲﺗﻮﺍﻧﻴﻢ
ﻣﺴﺘﻘﻴﻤﺎ ﺑﻪ ﻋﻨﺼﺮ ﻣﻮﺭﺩ ﻧﻈﺮ ﺩﺭ ﺁﺭﺍﻳﻪ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﻴﻢ:
;float* p = a ]// p points to a[0
;p += 5 ]// now p points to a[5
ﻳﮏ ﻧﮑﺖۀ ﻇﺮﻳﻒ ﺩﺭ ﺍﺭﺗﺒﺎﻁ ﺑﺎ ﺁﺭﺍﻳﻪﻫﺎ ﻭ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﻭﺟﻮﺩ ﺩﺍﺭﺩ :ﺍﮔﺮ ﺍﺷﺎﺭﻩﮔﺮ ﺭﺍ
ﺑﻴﺶ ﺍﺯ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﺍﻓﺰﺍﻳﺶ ﺩﻫﻴﻢ ،ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﻪ ﺑﺨﺶﻫﺎﻳﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺑﺮﻭﻳﻢ ﮐﻪ ﻫﻨﻮﺯ
ﺗﺨﺼﻴﺺ ﺩﺍﺩﻩ ﻧﺸﺪﻩﺍﻧﺪ ﻳﺎ ﺑﺮﺍﻱ ﮐﺎﺭﻫﺎﻱ ﺩﻳﮕﺮ ﺗﺨﺼﻴﺺ ﻳﺎﻓﺘﻪﺍﻧﺪ .ﺗﻐﻴﻴﺮ ﺩﺍﺩﻥ ﻣﻘﺪﺍﺭ ﺍﻳﻦ
ﺑﺨﺶﻫﺎ ﺑﺎﻋﺚ ﺑﺮﻭﺯ ﺧﻄﺎ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﻭ ﮐﻞ ﺳﻴﺴﺘﻢ ﻣﻲﺷﻮﺩ .ﻫﻤﻴﺸﻪ ﺑﺎﻳﺪ ﻣﺮﺍﻗﺐ ﺍﻳﻦ ﺧﻄﺮ
ﺑﺎﺷﻴﺪ .ﮐﺪ ﺯﻳﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﭼﻄﻮﺭ ﺍﻳﻦ ﺍﺗﻔﺎﻕ ﺭﺥ ﻣﻲﺩﻫﺪ.
;]float a[8
;]float* p = a[7 // points to last element in the array
;++p !// now p points to memory past last element
;*p = 22.2 !// TROUBLE
ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﻛﻪ ﺍﺭﺗﺒﺎﻁ ﺗﻨﮕﺎﺗﻨﮕﻲ ﺑﻴﻦ ﺁﺭﺍﻳﻪﻫﺎ ﻭ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﻭﺟﻮﺩ ﺩﺍﺭﺩ .ﻧﺎﻡ
ﺁﺭﺍﻳﻪ ﺩﺭ ﺣﻘﻴﻘﺖ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ) (constﺑﻪ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺍﺳﺖ .ﻫﻤﭽﻨﻴﻦ
ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ ﻣﺎﻧﻨﺪ ﻫﺮ ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮﻱ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﻫﻢ ﻣﻘﺎﻳﺴﻪ ﻧﻤﻮﺩ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 228
ﺩﺭ ﻧﮕﺎﻩ ﺍﻭﻝ a ،ﻭ pﻣﺎﻧﻨﺪ ﻫﻢ ﻫﺴﺘﻨﺪ :ﻫﺮ ﺩﻭ ﺑﻪ ﻧﻮﻉ shortﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﻨﺪ ﻭ ﻫﺮ ﺩﻭ
ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ 0x3fffd08ﻫﺴﺘﻨﺪ .ﺍﻣﺎ aﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ﺍﺳﺖ ﻭ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺍﻓﺰﺍﻳﺶ
ﻳﺎﺑﺪ ﺗﺎ ﺁﺭﺍﻳﻪ ﭘﻴﻤﺎﻳﺶ ﺷﻮﺩ .ﭘﺲ ﺑﻪ ﺟﺎﻱ ﺁﻥ pﺭﺍ ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﻴﻢ ﺗﺎ ﺁﺭﺍﻳﻪ ﺭﺍ ﭘﻴﻤﺎﻳﺶ
ﮐﻨﻴﻢ .ﺷﺮﻁ ) (p < a+5ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ a+5 .ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ:
0x3fffd08 + 5*sizeof(short) = 0x3fffd08 + 5*2 = 0x3fffd08 + 0xa = 0x3fffd12
int main()
{ short a1[9] = {11, 11, 11, 11, 11, 22, 33, 44, 55};
short a2[5] = {11, 11, 11, 22, 33};
cout << "Array a1 begins at location\t" << a1 << endl;
cout << "Array a2 begins at location\t" << a2 << endl;
short* p = loc(a1, a2, 9, 5);
if (p)
{ cout << "Array a2 found at location\t" << p << endl;
for (int i = 0; i < 5; i++)
cout << "\t" << &p[i] << ": " << p[i] << "\t"
<< &a2[i] << ": " << a2[i] << endl;
}
else cout << "Not found.\n";
}
Array a1 begins at location 0x3fffd12
Array a2 begins at location 0x3fffd08
Array a2 found at location 0x3fffd16
0x3fffd16: 11 0x3fffd08: 11
0x3fffd18: 11 0x3fffd0a: 11
0x3fffd1a: 11 0x3fffd0c: 11
0x3fffd1c: 22 0x3fffd0e: 22
0x3fffd1e: 33 0x3fffd10: 33
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 230
ﺍﻟﮕﻮﺭﻳﺘﻢ ﻣﻘﺎﻳﺲۀ ﺍﻟﮕﻮ ﺍﺯ ﺩﻭ ﺣﻠﻘﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻛﻨﺪ .ﺣﻠﻖۀ ﺑﻴﺮﻭﻧﻲ ﺍﺷﺎﺭﻩﮔﺮ p1ﺭﺍ ﺩﺭ
ﺁﺭﺍﻱۀ a1ﺟﻠﻮ ﻣﻲﺑﺮﺩ ﺗﺎ ﺟﺎﻳﻲ ﮐﻪ ﻋﻨﺼﺮﻱ ﮐﻪ p1ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ﺑﺎ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ
ﺁﺭﺍﻱۀ a2ﺑﺮﺍﺑﺮ ﺑﺎﺷﺪ .ﺁﻧﮕﺎﻩ ﺣﻠﻖۀ ﺩﺭﻭﻧﻲ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ .ﺩﺭ ﺍﻳﻦ ﺣﻠﻘﻪ ﻋﻨﺎﺻﺮ ﺑﻌﺪ ﺍﺯ p1
ﻳﮑﻲ ﻳﮑﻲ ﺑﺎ ﻋﻨﺎﺻﺮ ﻣﺘﻨﺎﻇﺮﺷﺎﻥ ﺩﺭ a2ﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﻧﺪ .ﺍﮔﺮ ﻧﺎﺑﺮﺍﺑﺮﻱ ﭘﻴﺪﺍ ﺷﻮﺩ ،ﺣﻠﻖۀ
ﺩﺭﻭﻧﻲ ﻓﻮﺭﺍ ﺧﺎﺗﻤﻪ ﻳﺎﻓﺘﻪ ﻭ ﺣﻠﻖۀ ﺑﻴﺮﻭﻧﻲ ﺩﻭﺭ ﺟﺪﻳﺪﺵ ﺭﺍ ﺁﻏﺎﺯ ﻣﻲﮐﻨﺪ .ﻳﻌﻨﻲ p1ﺩﻭﺑﺎﺭﻩ
ﺩﺭ ﺁﺭﺍﻱۀ a1ﺑﻪ ﭘﻴﺶ ﻣﻲﺭﻭﺩ ﺗﺎ ﺑﻪ ﻋﻨﺼﺮ ﺑﻌﺪﻱ ﺑﺮﺳﺪ ﮐﻪ ﺍﻳﻦ ﻋﻨﺼﺮ ﺑﺎ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ
ﺁﺭﺍﻱۀ a2ﺑﺮﺍﺑﺮ ﺑﺎﺷﺪ .ﻭﻟﻲ ﺍﮔﺮ ﺣﻠﻖۀ ﺩﺍﺧﻠﻲ ﺑﺪﻭﻥ ﺗﻮﻗﻒ ﺑﻪ ﭘﺎﻳﺎﻥ ﺭﺳﻴﺪ ،ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ
ﮐﻪ ﻋﻨﺎﺻﺮ ﺑﻌﺪ ﺍﺯ p1ﺑﺎ ﻋﻨﺎﺻﺮ ﻣﺘﻨﺎﻇﺮﺷﺎﻥ ﺩﺭ a2ﺑﺮﺍﺑﺮﻧﺪ .ﭘﺲ a2ﺩﺭ ﻣﺤﻞ p1ﻳﺎﻓﺖ
ﺷﺪﻩ ﺍﺳﺖ ﻭ p1ﺑﻪ ﻋﻨﻮﺍﻥ ﻣﮑﺎﻥ ﻣﻮﺭﺩ ﻧﻈﺮ ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ .ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺍﮔﺮ ﭼﻪ p1
ﺁﺭﺍﻳﻪ ﻧﻴﺴﺖ ﻭﻟﻲ ﺑﻪ ﺷﮑﻞ ] p1[jﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ .ﻫﻤﺎﻥ ﻃﻮﺭ ﮐﻪ ﻗﺒﻼ ﮔﻔﺘﻴﻢ ﺍﻳﻦ ﻋﺒﺎﺭﺕ ﺑﺎ
ﻋﺒﺎﺭﺕ p1+jﻳﮑﻲ ﺍﺳﺖ .ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﻭﺍﺭﺳﻲ ﻣﻲﮐﻨﺪ ﮐﻪ ﻭﺍﻗﻌﺎ ﺁﺩﺭﺱﻫﺎ ﺑﺮﺭﺳﻲ ﺷﻮﻧﺪ
ﻭ ﻣﻘﺎﺩﻳﺮ ﺩﺭﻭﻥ ﺁﺩﺭﺱﻫﺎ ﻳﮑﺴﺎﻥ ﺑﺎﺷﺪ.
7‐13ﻋﻤﻠﮕﺮ new
ﺧﻄﺎﺳﺖ .ﺯﻳﺮﺍ pﺑﻪ ﻫﻴﭻ ﺁﺩﺭﺳﻲ ﺍﺷﺎﺭﻩ ﻧﻤﻲﮐﻨﺪ ﻭ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﻧﻤﻲﺩﺍﻧﺪ ﮐﻪ ﻣﻘﺪﺍﺭ
3.14159ﺭﺍ ﮐﺠﺎ ﺫﺧﻴﺮﻩ ﮐﻨﺪ .ﺑﺮﺍﻱ ﺭﻓﻊ ﺍﻳﻦ ﻣﺸﮑﻞ ﻣﻲﺗﻮﺍﻥ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ ﻫﻨﮕﺎﻡ
ﺍﻋﻼﻥ ،ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩ:
;float x = 0 // x cintains the value 0
float* p = &x // now p points to x
;*p = 3.14159 // O.K. assigns this value to address that p points to
231 ﻓﺼﻞ هﻔﺘﻢ /اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ
ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﻣﻲﺗﻮﺍﻥ ﺑﻪ *pﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺷﺖ ﺯﻳﺮﺍ ﺣﺎﻻ pﺑﻪ xﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ﻭ ﺁﺩﺭﺱ ﺁﻥ
ﺭﺍ ﺩﺍﺭﺩ .ﺭﺍﻩ ﺣﻞ ﺩﻳﮕﺮ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻳﮏ ﺁﺩﺭﺱ ﺍﺧﺘﺼﺎﺻﻲ ﺍﻳﺠﺎﺩ ﺷﻮﺩ ﻭ ﺩﺭﻭﻥ 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
ﺑﺎ ﺍﻳﻦ ﺩﺳﺘﻮﺭ ،ﺍﺷﺎﺭﻩﮔﺮ pﺍﺯ ﻧﻮﻉ * floatﺗﻌﺮﻳﻒ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﻳﮏ ﺑﻠﻮﮎ ﺧﺎﻟﻲ ﺍﺯ
ﻧﻮﻉ floatﻣﻨﻈﻮﺭ ﺷﺪﻩ ﻭ ﺁﺩﺭﺱ ﺁﻥ ﺑﻪ pﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﺪ ﻭ ﻫﻤﭽﻨﻴﻦ ﻣﻘﺪﺍﺭ
3.14159ﺩﺭ ﺁﻥ ﺁﺩﺭﺱ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺍﮔﺮ ﻋﻤﻠﮕﺮ newﻧﺘﻮﺍﻧﺪ ﺧﺎﻥۀ ﺧﺎﻟﻲ ﺩﺭ ﺣﺎﻓﻈﻪ
ﭘﻴﺪﺍ ﮐﻨﺪ ،ﻣﻘﺪﺍﺭ ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺍﺷﺎﺭﻩﮔﺮﻱ ﮐﻪ ﺍﻳﻦ ﭼﻨﻴﻦ ﺑﺎﺷﺪ» ،ﺍﺷﺎﺭﻩﮔﺮ ﺗﻬﻲ« ﻳﺎ
NULLﻣﻲﻧﺎﻣﻨﺪ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﮐﺪ ﻫﻮﺷﻤﻨﺪ ﺯﻳﺮ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﺮﺍﻗﺐ ﺑﺎﺷﻴﻢ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺗﻬﻲ
ﺍﻳﺠﺎﺩ ﻧﺸﻮﺩ:
;double* p = new double
;)(if (p == 0) abort // allocator failed: insufficent memory
;else *p = 3.141592658979324
ﺩﺭ ﺍﻳﻦ ﻗﻄﻌﻪ ﮐﺪ ،ﻫﺮﮔﺎﻩ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺗﻬﻲ ﺍﻳﺠﺎﺩ ﺷﺪ ،ﺗﺎﺑﻊ )( abortﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﻭ
ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﻟﻐﻮ ﻣﻲﺷﻮﺩ.
ﺗﺎﮐﻨﻮﻥ ﺩﺍﻧﺴﺘﻴﻢ ﮐﻪ ﺑﻪ ﺩﻭ ﻃﺮﻳﻖ ﻣﻲﺗﻮﺍﻥ ﻳﮏ ﻣﺘﻐﻴﺮ ﺭﺍ ﺍﻳﺠﺎﺩ ﻭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩ.
ﺭﻭﺵ ﺍﻭﻝ:
;float x = 3.14159 // allocates named memory
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 232
ﻭ ﺭﻭﺵ ﺩﻭﻡ:
;)float* p = new float(3.14159 // allocates unnamed memory
ﺩﺭ ﺣﺎﻟﺖ ﺍﻭﻝ ،ﺣﺎﻓﻆۀ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺑﺮﺍﻱ xﻫﻨﮕﺎﻡ ﮐﺎﻣﭙﺎﻳﻞ ﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﺪ .ﺩﺭ ﺣﺎﻟﺖ ﺩﻭﻡ
ﺣﺎﻓﻆۀ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﻭ ﺑﻪ ﻳﮏ ﺷﻲﺀ ﺑﻲﻧﺎﻡ ﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﺪ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
*pﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﺍﺳﺖ.
7‐14ﻋﻤﻠﮕﺮ delete
ﻭﻗﺘﻲ ﺍﺷﺎﺭﻩ ﮔﺮ pﺩﺭ ﮐﺪ ﺑﺎﻻ ﺁﺯﺍﺩ ﺷﻮﺩ ،ﺣﺎﻓﻈﻪﺍﻱ ﮐﻪ ﺗﻮﺳﻂ newﺑﻪ ﺁﻥ ﺗﺨﺼﻴﺺ ﻳﺎﻓﺘﻪ
ﺑﻮﺩ ،ﺁﺯﺍﺩ ﺷﺪﻩ ﻭ ﺑﻪ ﻣﻴﺰﺍﻥ ) sizeof(floatﺑﻪ ﺣﺎﻓﻆۀ ﺁﺯﺍﺩ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ .ﻭﻗﺘﻲ
ﺍﺷﺎﺭﻩﮔﺮﻱ ﺁﺯﺍﺩ ﺷﺪ ،ﺑﻪ ﻫﻴﭻ ﭼﻴﺰﻱ ﺍﺷﺎﺭﻩ ﻧﻤﻲﮐﻨﺪ؛ ﻣﺜﻞ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ .ﺑﻪ
ﺍﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ ،ﺍﺷﺎﺭﻩﮔﺮ ﺳﺮﮔﺮﺩﺍﻥ ﻣﻲﮔﻮﻳﻨﺪ.
ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻳﮏ ﺷﻲﺀ ﺛﺎﺑﺖ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺁﺯﺍﺩ ﮐﺮﺩ:
;const int* p = new int
;delete p // ERROR: cannot delete pointer to const objects
ﮐﺪ ﺑﺎﻻ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺣﺎﻓﻆۀ ﺗﺨﺼﻴﺺﻳﺎﻓﺘﻪ ﺑﺮﺍﻱ xﺁﺯﺍﺩ ﺷﻮﺩ .ﺍﻳﻦ ﺍﺷﺘﺒﺎﻩ ﺭﺍ ﺑﻪ
ﺳﺨﺘﻲ ﻣﻲﺗﻮﺍﻥ ﺗﺸﺨﻴﺺ ﺩﺍﺩ ﻭ ﺍﺷﮑﺎﻝﺯﺩﺍﻳﻲ ﮐﺮﺩ.
7‐9ﺁﺭﺍﻳﻪﻫﺎﻱ ﭘﻮﻳﺎ
ﻧﺎﻡ ﺁﺭﺍﻳﻪ ﺩﺭ ﺣﻘﻴﻘﺖ ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ﺍﺳﺖ ﻛﻪ ﺩﺭ ﺯﻣﺎﻥ ﻛﺎﻣﭙﺎﻳﻞ ،ﺍﻳﺠﺎﺩ ﻭ
ﺗﺨﺼﻴﺺ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ:
;]float a[20 // a is a const pointer to a block of 20 floats
;]float* const p = new float[20 // so is p
ﺩﺳﺘﻮﺭ ﺑﺎﻻ 20 ،ﺧﺎﻥۀ ﺧﺎﻟﻲ ﺣﺎﻓﻈﻪ ﺍﺯ ﻧﻮﻉ floatﺭﺍ ﺩﺭ ﺍﺧﺘﻴﺎﺭ ﮔﺬﺍﺷﺘﻪ ﻭ ﺍﺷﺎﺭﻩﮔﺮ p
ﺭﺍ ﺑﻪ ﺧﺎﻥۀ ﺍﻭﻝ ﺁﻥ ﻧﺴﺒﺖ ﻣﻲﺩﻫﺪ .ﺑﻪ ﺍﻳﻦ ﺁﺭﺍﻳﻪ» ،ﺁﺭﺍﻱۀ ﭘﻮﻳﺎ «1ﻣﻲﮔﻮﻳﻨﺪ .ﺑﻪ ﺍﻳﻦ ﻃﺮﺯ
ﺍﻳﺠﺎﺩ ﺍﺷﻴﺎ ﺑﺴﺘﻪﺑﻨﺪﻱ ﭘﻮﻳﺎ 3ﻳﺎ »ﺑﺴﺘﻪﺑﻨﺪﻱ ﺯﻣﺎﻥ ﺟﺮﺍ« ﻣﻲﮔﻮﻳﻨﺪ.
ﺁﺭﺍﻱۀ ﺍﻳﺴﺘﺎﻱ aﻭ ﺁﺭﺍﻱۀ ﭘﻮﻳﺎﻱ pﺭﺍ ﺑﺎ ﻳﮑﺪﻳﮕﺮ ﻣﻘﺎﻳﺴﻪ ﮐﻨﻴﺪ .ﺁﺭﺍﻱۀ ﺍﻳﺴﺘﺎﻱ aﺩﺭ
ﺯﻣﺎﻥ ﮐﺎﻣﭙﺎﻳﻞ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﺗﺎ ﭘﺎﻳﺎﻥ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ،ﺣﺎﻓﻆۀ ﺗﺨﺼﻴﺼﻲ ﺑﻪ ﺁﻥ ﻣﺸﻐﻮﻝ
ﻣﻲﻣﺎﻧﺪ .ﻭﻟﻲ ﺁﺭﺍﻱۀ ﭘﻮﻳﺎﻱ pﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﻭ ﻫﺮ ﺟﺎ ﮐﻪ ﻻﺯﻡ ﺷﺪ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﭘﺲ ﺍﺯ
ﺍﺗﻤﺎﻡ ﮐﺎﺭ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﻋﻤﻠﮕﺮ deleteﺣﺎﻓﻆۀ ﺗﺨﺼﻴﺼﻲ ﺑﻪ ﺁﻥ ﺭﺍ ﺁﺯﺍﺩ ﮐﺮﺩ:
;delete [] p
p ﺑﺎﻳﺪ ﺣﺘﻤﺎ ﻗﻴﺪ ﺷﻮﻧﺪ ﺯﻳﺮﺍp ﺑﺮﺍﮐﺖﻫﺎ ][ ﻗﺒﻞ ﺍﺯ ﻧﺎﻡp ﺑﺮﺍﻱ ﺁﺯﺍﺩ ﮐﺮﺩﻥ ﺁﺭﺍﻱۀ ﭘﻮﻳﺎﻱ
.ﺑﻪ ﻳﮏ ﺁﺭﺍﻳﻪ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ
ﻭﻗﺘﻲ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ،ﺍﺑﺘﺪﺍ ﺍﺷﺎﺭﻩﮔﺮ ﺗﻬﻲ aﺍﺯ ﻧﻮﻉ * doubleﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ .ﺳﭙﺲ
ﺍﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺗﺎﺑﻊ )( getﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﺗﺎﺑﻊ )( getﻳﮏ ﺁﺭﺍﻱۀ ﭘﻮﻳﺎ ﺍﻳﺠﺎﺩ ﮐﺮﺩﻩ
ﻭ ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ ﺁﻥ ﺭﺍ ﺩﺭﻭﻥ ﺍﺷﺎﺭﻩﮔﺮ aﻣﻲﮔﺬﺍﺭﺩ .ﻧﮑﺘﻪ ﺟﺎﻟﺐ ﺍﻳﻦ ﺟﺎﺳﺖ ﮐﻪ ﺗﻌﺪﺍﺩ
ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﻫﻨﮕﺎﻡ ﺍﺟﺮﺍ ﻣﺸﺨﺺ ﻣﻲﺷﻮﺩ .ﻳﻌﻨﻲ ﻭﻗﺘﻲ ﺗﺎﺑﻊ )( getﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪ ،ﺍﺯ
ﮐﺎﺭﺑﺮ ﭘﺮﺳﻴﺪﻩ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻧﺪﺍﺯۀ ﺁﺭﺍﻳﻪ ﭼﻘﺪﺭ ﺑﺎﺷﺪ .ﺳﭙﺲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ new
ﺁﺭﺍﻳﻪﺍﻱ ﺑﻪ ﻫﻤﺎﻥ ﺍﻧﺪﺍﺯﻩ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ .ﭘﺲ ﺍﺯ ﺁﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺣﻠﻖۀ forﻣﻘﺎﺩﻳﺮ ﺁﺭﺍﻳﻪ
ﺩﺭﻭﻥ ﻋﺒﺎﺭﺕ;]cin >> a[i ﻳﮑﻲ ﻳﮑﻲ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﺷﺪﻩ ﻭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ )ﻋﺒﺎﺭﺕ ] a[iﺑﺎ ﻋﺒﺎﺭﺕ a+iﻣﻌﺎﺩﻝ ﺍﺳﺖ .ﻣﺜﺎﻝ 7‐12ﺭﺍ
ﺑﺒﻴﻨﻴﺪ( .ﺩﺭ ﻧﻬﺎﻳﺖ ﺁﺭﺍﻱۀ aﻭ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮﺵ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﺎﺯ ﻣﻲﮔﺮﺩﺩ .ﺗﺎﺑﻊ
)( printﻭﻇﻴﻔﻪ ﺩﺍﺭﺩ ﮐﻪ ﺑﺎ ﭘﻴﺶﺑﺮﺩﻥ ﺍﺷﺎﺭﻩﮔﺮ ﺭﻭﻱ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ،ﻣﻘﺎﺩﻳﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﺁﻥ ﺭﺍ
ﭼﺎﭖ ﮐﻨﺪ .ﭘﺲ ﺍﺯ ﺍﻳﻦ ﮐﺎﺭ ،ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ deleteﺁﺭﺍﻱۀ ﻣﻮﺭﺩ ﻧﻈﺮ ﺁﺯﺍﺩ ﻣﻲﺷﻮﺩ.
ﺩﻭﺑﺎﺭﻩ ﺑﺎ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ )( getﻣﻲﺗﻮﺍﻥ ﺁﺭﺍﻱۀ ﺟﺪﻳﺪﻱ ﺳﺎﺧﺖ .ﺍﻳﻦ ﺁﺭﺍﻱۀ ﺟﺪﻳﺪ
ﻣﻲﺗﻮﺍﻧﺪ ﺍﻧﺪﺍﺯۀ ﻣﺘﻔﺎﻭﺗﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﻋﻤﻠﮕﺮ ﺯﻳﺮﻧﻮﻳﺲ ][ ﺣﺘﻤﺎ ﺑﺎﻳﺪ ﺩﺭ
ﺩﺳﺘﻮﺭ deleteﺑﻪ ﮐﺎﺭ ﺭﻭﺩ ﺗﺎ ﮐﻞ ﺁﺭﺍﻳﻪ ﺁﺯﺍﺩ ﺷﻮﺩ .ﻫﻤﭽﻨﻴﻦ ﺑﺒﻴﻨﻴﺪ ﮐﻪ ﭘﺎﺭﺍﻣﺘﺮ aﺩﺭ ﺗﺎﺑﻊ
)( getﺑﻪ ﭼﻪ ﺷﮑﻠﻲ ﺍﻋﻼﻥ ﺷﺪﻩ:
)void get(double*& a, int& n
ﺗﺎﺑﻊ )( getﻗﺮﺍﺭ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺗﻬﻲ aﻣﻘﺪﺍﺭﻱ ﺭﺍ ﻧﺴﺒﺖ ﺩﻫﺪ .ﺑﻪ ﻫﻤﻴﻦ
ﺩﻟﻴﻞ aﺑﺎﻳﺪ ﺑﻪ ﺷﮑﻞ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﺷﻮﺩ ﺗﺎ ﺗﺎﺑﻊ ﺑﺘﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ﺁﻥ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ .ﭼﻮﻥ
aﺍﺯ ﻧﻮﻉ * doubleﺍﺳﺖ ،ﭘﺲ ﺷﮑﻞ ﺍﺭﺟﺎﻋﻲﺍﺵ ﺑﻪ ﺻﻮﺭﺕ &* doubleﺧﻮﺍﻫﺪ
ﺑﻮﺩ .ﺑﺮﻫﺎﻥ ﺑﺎﻻ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻳﻲ ﻣﺤﻠﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﻭ ﺍﮔﺮ
ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﻧﺸﻮﺩ ،ﺗﺎﺑﻊ ﻳﮏ ﻧﺴﺦۀ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥ ﻣﻲﺳﺎﺯﺩ .ﺣﺎﻻ
ﺑﮕﻮﻳﻴﺪ ﭼﺮﺍ ﺩﺭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ )( printﺍﺷﺎﺭﻩﮔﺮ aﺑﻪ ﺷﮑﻞ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﻧﺸﺪﻩ ﺍﺳﺖ
ﻭﻟﻲ ﺑﺎ ﻭﺟﻮﺩ ﺍﻳﻦ ﻣﻲﺗﻮﺍﻥ ﻋﻨﺎﺻﺮ aﺭﺍ ﺩﺭﻭﻥ ﺗﺎﺑﻊ ﺑﻪ ﺩﺭﺳﺘﻲ ﭼﺎﭖ ﮐﺮﺩ؟
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 236
7‐10ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ
»ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻳﮏ ﺛﺎﺑﺖ« ﺑﺎ »ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ« ﺗﻔﺎﻭﺕ ﺩﺍﺭﺩ .ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﺩﺭ ﻗﺎﻟﺐ ﻣﺜﺎﻝ
ﺯﻳﺮ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ.
ﺍﺷﺎﺭﻩﮔﺮ pﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﻣﺘﻐﻴﺮ nﺍﺳﺖ .ﻫﻢ ﺧﻮﺩ pﻗﺎﺑﻞ ﺍﻓﺰﺍﻳﺶ ﺍﺳﺖ ) (++pﻭ
ﻫﻢ ﻣﻘﺪﺍﺭﻱ ﮐﻪ pﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ﻗﺎﺑﻞ ﺍﻓﺰﺍﻳﺶ ﺍﺳﺖ )) .(++(*Pﺍﺷﺎﺭﻩ ﮔﺮ cpﻳﮏ
ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ﺍﺳﺖ .ﻳﻌﻨﻲ ﺁﺩﺭﺳﻲ ﮐﻪ ﺩﺭ cpﺍﺳﺖ ﻗﺎﺑﻞ ﺗﻐﻴﻴﺮ ﻧﻴﺴﺖ ﻭﻟﻲ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺩﺭ
ﺁﻥ ﺁﺩﺭﺱ ﺍﺳﺖ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺩﺳﺖﮐﺎﺭﻱ ﮐﺮﺩ .ﺍﺷﺎﺭﻩﮔﺮ pcﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺁﺩﺭﺱ
ﻳﮏ ﺛﺎﺑﺖ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ .ﺧﻮﺩ pcﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺗﻐﻴﻴﺮ ﺩﺍﺩ ﻭﻟﻲ ﻣﻘﺪﺍﺭﻱ ﮐﻪ pcﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ
ﺩﺍﺭﺩ ﻗﺎﺑﻞ ﺗﻐﻴﻴﺮ ﻧﻴﺴﺖ .ﺩﺭ ﺁﺧﺮ ﻫﻢ cpcﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ﺑﻪ ﻳﮏ ﺷﻲﺀ ﺛﺎﺑﺖ ﺍﺳﺖ .ﻧﻪ
ﻣﻘﺪﺍﺭ cpcﻗﺎﺑﻞ ﺗﻐﻴﻴﺮ ﺍﺳﺖ ﻭ ﻧﻪ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺁﺩﺭﺱ ﺁﻥ ﺩﺭ cpcﺍﺳﺖ.
237 ﻓﺼﻞ هﻔﺘﻢ /اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ
7‐11ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ
ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﺭﺍﻳﻪﺍﻱ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﮐﻪ ﺍﻋﻀﺎﻱ ﺁﻥ ﺍﺯ ﻧﻮﻉ ﺍﺷﺎﺭﻩﮔﺮ ﺑﺎﺷﻨﺪ .ﻣﺜﻼ ﺩﺳﺘﻮﺭ:
;]float* p[4
p
ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﻲ ﺗﻮﺍﻧﻴﻢ ﺷﺒﻴﻪ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﻣﺠﺴﻢ ﮐﻨﻴﻢ:
0 3.14159
1 double
ﻣﺜﺎﻝ ﺑﻌﺪ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺑﻪ
2
3 1.19 ﭼﻪ ﺩﺭﺩﻱ ﻣﻲﺧﻮﺭﺩ .ﺍﺯ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﻣﻲﺗﻮﺍﻥ ﺑﺮﺍﻱ ﻣﺮﺗﺐﮐﺮﺩﻥ
double
ﻳﮏ ﻓﻬﺮﺳﺖ ﻧﺎﻣﺮﺗﺐ ﺑﻪ ﺭﻭﺵ ﺣﺒﺎﺑﻲ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ .ﺑﻪ
ﺟﺎﻱ ﺍﻳﻦ ﮐﻪ ﺧﻮﺩ ﻋﻨﺎﺻﺮ ﺟﺎﺑﺠﺎ ﺷﻮﻧﺪ ،ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﺁﻥﻫﺎ ﺟﺎﺑﺠﺎ ﻣﻲﺷﻮﻧﺪ.
ﺗﺎﺑﻊ )( sortﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ ﻣﻲﮔﻴﺮﺩ .ﺳﭙﺲ ﺩﺭﻭﻥ ﺣﻠﻘﻪﻫﺎﻱ ﺗﻮﺩﺭﺗﻮﻱ for
ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﺪ ﮐﻪ ﺁﻳﺎ ﻣﻘﺎﺩﻳﺮﻱ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﻣﺠﺎﻭﺭ ﺑﻪ ﺁﻥﻫﺎ ﺍﺷﺎﺭﻩ ﺩﺍﺭﻧﺪ ،ﻣﺮﺗﺐ
ﻫﺴﺘﻨﺪ ﻳﺎ ﻧﻪ .ﺍﮔﺮ ﻣﺮﺗﺐ ﻧﺒﻮﺩﻧﺪ ،ﺟﺎﻱ ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﺁﻥﻫﺎ ﺭﺍ ﺑﺎ ﻫﻢ ﻋﻮﺽ ﻣﻲﮐﻨﺪ .ﺩﺭ ﭘﺎﻳﺎﻥ
ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﻓﻬﺮﺳﺖ ﻣﺮﺗﺐ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ ،ﺁﺭﺍﻳﻪﺍﻱ ﺩﺍﺭﻳﻢ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﺩﺭﻭﻥ
ﺁﻥ ﺑﻪ ﺗﺮﺗﻴﺐ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺍﻧﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 238
7‐13ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺗﻮﺍﺑﻊ
ﺍﻳﻦ ﺑﺨﺶ ﻣﻤﮑﻦ ﺍﺳﺖ ﮐﻤﻲ ﻋﺠﻴﺐ ﺑﻪ ﻧﻈﺮ ﺑﺮﺳﺪ .ﺣﻘﻴﻘﺖ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻧﺎﻡ ﻳﮏ
ﺗﺎﺑﻊ ﻣﺜﻞ ﻧﺎﻡ ﻳﮏ ﺁﺭﺍﻳﻪ ،ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ﺍﺳﺖ .ﻧﺎﻡ ﺗﺎﺑﻊ ،ﺁﺩﺭﺳﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﻧﺸﺎﻥ
ﻣﻲﺩﻫﺪ ﮐﻪ ﮐﺪﻫﺎﻱ ﺩﺭﻭﻥ ﺗﺎﺑﻊ ﺩﺭ ﺁﻥ ﻗﺴﻤﺖ ﺟﺎﻱ ﮔﺮﻓﺘﻪﺍﻧﺪ .ﭘﺲ ﺑﻨﺎﺑﺮ ﻗﺴﻤﺖ ﻗﺒﻞ ﺍﮔﺮ
ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺗﺎﺑﻊ ﺍﻋﻼﻥ ﮐﻨﻴﻢ ،ﺩﺭ ﺍﺻﻞ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺩﻳﮕﺮ ﺗﻌﺮﻳﻒ ﮐﺮﺩﻩﺍﻳﻢ .ﺍﻣﺎ
ﺍﻳﻦ ﺗﻌﺮﻳﻒ ،ﻧﺤﻮ ﻣﺘﻔﺎﻭﺗﻲ ﺩﺍﺭﺩ:
;)int f(int // declares function f
;)int (*pf)(int // declares function pointer pf
;pf = &f // assigns address of f to pf
ﺍﺷﺎﺭﻩﮔﺮ pfﻫﻤﺮﺍﻩ ﺑﺎ * ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ،ﻳﻌﻨﻲ ﺍﻳﻦ ﮐﻪ pfﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﻳﮏ
ﺗﺎﺑﻊ ﺍﺳﺖ .ﺑﻌﺪ ﺍﺯ ﺁﻥ ﻳﮏ intﻫﻢ ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ ﺁﻣﺪﻩ ﺍﺳﺖ ،ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﻲ ﮐﻪ ﺗﺎﺑﻌﻲ ﮐﻪ
pfﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﻧﻤﺎﻳﺪ ،ﭘﺎﺭﺍﻣﺘﺮﻱ ﺍﺯ ﻧﻮﻉ intﺩﺍﺭﺩ .ﺍﺷﺎﺭﻩﮔﺮ pfﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺷﮑﻞ
ﺯﻳﺮ ﺗﺼﻮﺭ ﮐﻨﻴﻢ:
239 ﻓﺼﻞ هﻔﺘﻢ /اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ
)(int main
;{ cout << sum(square,4) << endl // 1 + 4 + 9 + 16
;cout << sum(cube,4) << endl // 1 + 8 + 27 + 64
}
ﺗﺎﺑﻊ )( sumﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﻏﻴﺮ ﻣﻌﻤﻮﻝ ﺩﺍﺭﺩ .ﻧﺎﻡ ﺗﺎﺑﻊ ﺩﻳﮕﺮﻱ ﺑﻪ ﻋﻨﻮﺍﻥ ﺁﺭﮔﻮﻣﺎﻥ ﺑﻪ ﺁﻥ
) sum(square,4ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ ،ﻣﻘﺪﺍﺭ ﺍﺭﺳﺎﻝ ﺷﺪﻩ .ﻫﻨﮕﺎﻣﻲ ﮐﻪ
ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ. )square(1)+square(2)+square(3)+square(4
ﭼﻮﻥ) square(kﻣﻘﺪﺍﺭ k*kﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ،ﻓﺮﺍﺧﻮﺍﻧﻲ ) sum(square,4ﻣﻘﺪﺍﺭ
1+4+9+16=30ﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻧﻤﻮﺩﻩ ﻭ ﺑﺎﺯﻣﻲﮔﺮﺩﺍﻧﺪ .ﺗﻌﺮﻳﻒ ﺗﻮﺍﺑﻊ ﻭ ﺧﺮﻭﺟﻲ ﺁﺯﻣﺎﻳﺸﻲ
ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
)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
;return s
}
pfﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ )( sumﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺗﺎﺑﻊ ﺍﺳﺖ .ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺗﺎﺑﻌﻲ
ﮐﻪ ﺁﻥ ﺗﺎﺑﻊ ﭘﺎﺭﺍﻣﺘﺮﻱ ﺍﺯ ﻧﻮﻉ intﺩﺍﺭﺩ ﻭ ﻣﻘﺪﺍﺭﻱ ﺍﺯ ﻧﻮﻉ intﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ k .ﺩﺭ ﺗﺎﺑﻊ
sumﺍﺻﻼ ﺍﺳﺘﻔﺎﺩﻩ ﻧﺸﺪﻩ ﺍﻣﺎ ﺣﺘﻤﺎ ﺑﺎﻳﺪ ﻗﻴﺪ ﺷﻮﺩ ﺗﺎ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺑﻔﻬﻤﺪ ﮐﻪ pfﺑﻪ ﺗﺎﺑﻌﻲ ﺍﺷﺎﺭﻩ
ﺩﺍﺭﺩ ﮐﻪ ﭘﺎﺭﺍﻣﺘﺮﻱ ﺍﺯ ﻧﻮﻉ intﺩﺍﺭﺩ .ﻋﺒﺎﺭﺕ ) (*pf)(iﻣﻌﺎﺩﻝ ﺑﺎ ) square(iﻳﺎ
) cube(iﺧﻮﺍﻫﺪ ﺑﻮﺩ ،ﺑﺴﺘﻪ ﺑﻪ ﺍﻳﻦ ﮐﻪ ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﺍﻳﻦ ﺩﻭ ﺗﺎﺑﻊ ﺑﻪ ﻋﻨﻮﺍﻥ ﺁﺭﮔﻮﻣﺎﻥ ﺑﻪ
)( sumﺍﺭﺳﺎﻝ ﺷﻮﻧﺪ.
ﻧﺎﻡ ﺗﺎﺑﻊ ،ﺁﺩﺭﺱ ﺷﺮﻭﻉ ﺗﺎﺑﻊ ﺭﺍ ﺩﺍﺭﺩ .ﭘﺲ squareﺁﺩﺭﺱ ﺷﺮﻭﻉ ﺗﺎﺑﻊ
)( squareﺭﺍ ﺩﺍﺭﺩ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻭﻗﺘﻲ ﺗﺎﺑﻊ )( sumﺑﻪ ﺷﮑﻞ )sum(square,4
ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ ،ﺁﺩﺭﺳﻲ ﮐﻪ ﺩﺭﻭﻥ squareﺍﺳﺖ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ pfﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﺑﺎ
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﺒﺎﺭﺕ ) (*pf)(iﻣﻘﺪﺍﺭ iﺑﻪ ﺁﺭﮔﻮﻣﺎﻥ ﺗﺎﺑﻌﻲ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ ﮐﻪ pfﺑﻪ
ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ.
ﺛﺎﺑﺖ ﺻﻔﺮ ) (0ﺍﺯ ﻧﻮﻉ intﺍﺳﺖ ﺍﻣﺎ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﻪ ﻫﺮ ﻧﻮﻉ ﺑﻨﻴﺎﺩﻱ ﺩﻳﮕﺮ
ﻣﻲﺗﻮﺍﻥ ﺗﺨﺼﻴﺺ ﺩﺍﺩ:
;char c = 0 // initializes c to the 'char '\0
;short d = 0 // initializes d to the short int 0
;int n = 0 // initializes n to the int 0
;unsigned u = 0 // initializes u to the unsigned int 0
;float x = 0 // initializes x to the float 0.0
;double z = 0 // initializes z to the double 0.0
ﻣﻘﺪﺍﺭ ﺻﻔﺮ ﻣﻌﻨﺎﻫﺎﻱ ﮔﻮﻧﺎﮔﻮﻧﻲ ﺩﺍﺭﺩ .ﻭﻗﺘﻲ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻱ ﻋﺪﺩﻱ ﺑﻪ ﮐﺎﺭ ﺭﻭﺩ ،ﺑﻪ
ﻣﻌﻨﺎﻱ ﻋﺪﺩ ﺻﻔﺮ ﺍﺳﺖ .ﻭﻗﺘﻲ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﻪ ﮐﺎﺭ ﺭﻭﺩ ،ﺑﻪ ﻣﻌﻨﺎﻱ ﮐﺎﺭﺍﮐﺘﺮ ﺗﻬﻲ ﻳﺎ
NULﺍﺳﺖ NUL .ﻣﻌﺎﺩﻝ ﮐﺎﺭﺍﮐﺘﺮ ' '\0ﻧﻴﺰ ﻫﺴﺖ .ﻭﻗﺘﻲ ﻣﻘﺪﺍﺭ ﺻﻔﺮ ﺑﺮﺍﻱ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ
ﺑﻪ ﮐﺎﺭ ﺭﻭﺩ ،ﺑﻪ ﻣﻌﻨﺎﻱ »ﻫﻴﭻ ﭼﻴﺰ« ﻳﺎ NULLﺍﺳﺖ NULL .ﻳﮏ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ ﺍﺳﺖ ﻭ
241 ﻓﺼﻞ هﻔﺘﻢ /اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ
ﭘﺲ ﺧﻮﺏ ﺍﺳﺖ ﻫﻨﮕﺎﻡ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ،ﺍﺣﺘﻴﺎﻁ ﮐﺮﺩﻩ ﻭ ﺑﺮﺭﺳﻲ ﮐﻨﻴﻢ ﮐﻪ ﺁﻥ
ﺍﺷﺎﺭﻩﮔﺮ NULLﻧﺒﺎﺷﺪ:
;if (p) *p = 22 // O.K.
ﺣﺎﻻ ﺩﺳﺘﻮﺭ ; *p=22ﻭﻗﺘﻲ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ﮐﻪ pﺻﻔﺮ ﻧﺒﺎﺷﺪ .ﻣﻲﺩﺍﻧﻴﺪ ﮐﻪ ﺷﺮﻁ ﺑﺎﻻ
ﻣﻌﺎﺩﻝ ﺷﺮﻁ ﺯﻳﺮ ﺍﺳﺖ:
;if (p != NULL) *p = 22
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﺑﺮﺍﻱ ﺑﻪ ﺩﺳﺖ ﺁﻭﺭﺩﻥ ﺁﺩﺭﺱ ﻣﺘﻐﻴﺮ nﺍﺯ ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﺷﻮﺩ؟
ﺩ( )(n ﺝ( n ﺏ( *n ﺍﻟﻒ( &n
– 2ﺩﺭ ﻣﻮﺭﺩ ﺩﺳﺘﻮﺭ ; int& k=nﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ( kﻣﺘﻐﻴﺮﻱ ﻣﺴﺘﻘﻞ ﺍﺯ nﺍﺳﺖ ﮐﻪ ﻣﻘﺪﺍﺭ nﺭﺍ ﺩﺍﺭﺩ
ﺏ( kﻣﺘﻐﻴﺮﻱ ﻣﺴﺘﻘﻞ ﺍﺯ nﺍﺳﺖ ﮐﻪ ﺁﺩﺭﺱ nﺭﺍ ﺩﺍﺭﺩ
ﺝ( kﻳﮏ ﺍﺭﺟﺎﻉ ﺑﻪ nﺍﺳﺖ
ﺩ( kﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ nﺍﺳﺖ
ﭼﻴﺴﺖ؟ ;int& k=37 – 3ﺣﺎﺻﻞ ﺍﺟﺮﺍﻱ ﮐﺪ
ﺍﻟﻒ( ﻣﻘﺪﺍﺭ 37ﺩﺭ ﻣﺘﻐﻴﺮ ﻣﺴﺘﻌﺎﺭ kﻗﺮﺍﺭ ﻣﻲ ﮔﻴﺮﺩ
ﺏ( ﻣﻘﺪﺍﺭ 37ﺩﺭ ﻣﺘﻐﻴﺮﻱ ﮐﻪ kﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺁﻥ ﺍﺳﺖ ،ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ
ﺝ( ﻣﻘﺪﺍﺭ 37ﺩﺭ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﺁﺩﺭﺱ ﺁﻥ ﺩﺭ kﺍﺳﺖ ،ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ
ﺩ( ﮐﺎﻣﭙﺎﻳﻠﺮ ﺧﻄﺎ ﻣﻲﮔﻴﺮﺩ ﺯﻳﺮﺍ ﺍﺭﺟﺎﻉﻫﺎ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﺎ ﻣﻘﺪﺍﺭ ﺻﺮﻳﺢ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩ
ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟ ;int& c=n – 4ﺩﺭ ﻣﻮﺭﺩ ﺩﺳﺘﻮﺭ
ﺍﻟﻒ( cﻭ nﺁﺩﺭﺱﻫﺎﻱ ﻳﮑﺴﺎﻥ ﻭ ﻣﻘﺪﺍﺭﻫﺎﻱ ﻳﮑﺴﺎﻥ ﺩﺍﺭﻧﺪ
ﺏ( cﻭ nﺁﺩﺭﺱﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ ﻭ ﻣﻘﺪﺍﺭﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ ﻭﻟﻲ ﻧﻮﻉ ﻳﮑﺴﺎﻥ ﺩﺍﺭﻧﺪ
ﺝ( cﻭ nﺁﺩﺭﺱﻫﺎﻱ ﻳﮑﺴﺎﻥ ﻭﻟﻲ ﻣﻘﺪﺍﺭﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ ﺩﺍﺭﻧﺪ
ﺩ( cﻭ nﺁﺩﺭﺱﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ ﻭﻟﻲ ﻣﻘﺪﺍﺭﻫﺎﻱ ﻳﮑﺴﺎﻥ ﺩﺍﺭﻧﺪ
ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟ – 5ﺩﺭ ﺭﺍﺑﻄﻪ ﺑﺎ ﻋﺒﺎﺭﺕ ;float* p=k
ﺍﻟﻒ( ﺍﺷﺎﺭﻩﮔﺮ pﻣﺘﻐﻴﺮ ﻣﺴﺘﻘﻠﻲ ﺍﺳﺖ ﮐﻪ ﻣﻘﺪﺍﺭ kﺩﺭ ﺁﻥ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ
ﺏ( ﺍﺷﺎﺭﻩﮔﺮ pﻣﺘﻐﻴﺮ ﻣﺴﺘﻘﻠﻲ ﺍﺳﺖ ﮐﻪ ﺁﺩﺭﺱ kﺩﺭ ﺁﻥ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ
ﺝ( ﺍﺷﺎﺭﻩﮔﺮ pﻣﺘﻐﻴﺮ ﻣﺴﺘﻘﻠﻲ ﺍﺳﺖ ﮐﻪ ﻧﺎﻡ kﺩﺭ ﺁﻥ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ
ﺩ( ﺍﺷﺎﺭﻩﮔﺮ pﻣﺘﻐﻴﺮ ﻣﺴﺘﻘﻞ ﻧﻴﺴﺖ ﻭ ﻓﻘﻂ ﻳﮏ ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺑﺮﺍﻱ ﻣﺘﻐﻴﺮ kﺍﺳﺖ
– 6ﺍﮔﺮ ntﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﺎ ﻣﻘﺪﺍﺭ 50ﻭ ﺁﺩﺭﺱ 0x000cc70ﺑﺎﺷﺪ ﻭ ﺳﭙﺲ
ﺍﺷﺎﺭﻩﮔﺮ pﺑﻪ ﺷﮑﻞ ; int* p=&ntﺍﻋﻼﻥ ﺷﻮﺩ ،ﺁﻧﮕﺎﻩ ﺣﺎﺻﻞ ﻋﺒﺎﺭﺕ
; cout << pﭼﻪ ﺧﻮﺍﻫﺪ ﺑﻮﺩ؟
243 ﻓﺼﻞ هﻔﺘﻢ /اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﭼﮕﻮﻧﻪ ﺑﻪ ﺁﺩﺭﺱ ﺣﺎﻓﻆۀ ﻳﻚ ﻣﺘﻐﻴﺮ ﺩﺳﺘﻴﺎﺑﻲ ﭘﻴﺪﺍ ﻣﻲﻛﻨﻴﺪ؟
‐2ﭼﮕﻮﻧﻪ ﺑﻪ ﻣﺤﺘﻮﻳﺎﺕ ﻣﻜﺎﻧﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﻛﻪ ﺁﺩﺭﺱ ﺁﻥ ﺩﺭ ﻳﻚ ﻣﺘﻐﻴﺮ ﺍﺷﺎﺭﻩﮔﺮ ﺫﺧﻴﺮﻩ
ﺷﺪﻩ ﺍﺳﺖ ﺩﺳﺘﻴﺎﺑﻲ ﻣﻲﻛﻨﻴﺪ؟
‐3ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺩﻭ ﺍﻋﻼﻥ ﺯﻳﺮ ﺭﺍ ﺷﺮﺡ ﺩﻫﻴﺪ:
;int n1=n
;int& n2=n
‐4ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺩﻭ ﻧﺤﻮۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﺩﺭ ﮐﺪﻫﺎﻱ ﺯﻳﺮ ﺭﺍ ﺷﺮﺡ ﺩﻫﻴﺪ:
;int& r = n
;p = &n
‐5ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺩﻭ ﻧﺤﻮۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺍﺷﺎﺭﻩ * ﺩﺭ ﮐﺪﻫﺎﻱ ﺯﻳﺮ ﺭﺍ ﺷﺮﺡ ﺩﻫﻴﺪ:
;int* q = p
;n = *p
‐6ﺩﺭﺳﺖ ﻳﺎ ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ؟ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ:
ﺍﻟﻒ( ﺍﮔﺮ ) (x == yﺁﻧﮕﺎﻩ )(&x == &y
ﺏ( ﺍﮔﺮ ) (x == yﺁﻧﮕﺎﻩ )(*x == *y
‐7ﺍﻟﻒ( ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﺳﺮﮔﺮﺩﺍﻥ ﭼﻴﺴﺖ؟
ﺏ( ﺍﺯ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺳﺮﮔﺮﺩﺍﻥ ﭼﻪ ﻧﺘﻴﺞ ۀ ﻧﺎﺧﻮﺷﺎﻳﻨﺪﻱ ﺣﺎﺻﻞ ﻣﻲﺷﻮﺩ؟
ﺝ( ﭼﮕﻮﻧﻪ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﺍﻳﻦ ﻧﺘﻴﺞۀ ﻧﺎﻣﻄﻠﻮﺏ ﺍﺟﺘﻨﺎﺏ ﻛﺮﺩ؟
‐8ﭼﻪ ﺧﻄﺎﻳﻲ ﺩﺭ ﻛﺪ ﺯﻳﺮ ﺍﺳﺖ؟
;int& r = 22
‐9ﭼﻪ ﺧﻄﺎﻳﻲ ﺩﺭ ﻛﺪ ﺯﻳﺮ ﺍﺳﺖ؟
;int* p = &44
‐10ﭼﻪ ﺧﻄﺎﻳﻲ ﺩﺭ ﻛﺪ ﺯﻳﺮ ﺍﺳﺖ؟
;'char c = 'w
;char p = &c
‐11ﭼﺮﺍ ﻧﻤﻲﺗﻮﺍﻥ ﻣﺘﻐﻴﺮ ppnﻣﺜﺎﻝ 7‐6ﺭﺍ ﺷﺒﻴﻪ ﺍﻳﻦ ﺍﻋﻼﻥ ﻛﺮﺩ:
;int** ppn = &&n
‐12ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﻴﻦ »ﺑﺴﺘﻪﺑﻨﺪﻱ ﺍﻳﺴﺘﺎ« ﻭ »ﺑﺴﺘﻪﺑﻨﺪﻱ ﭘﻮﻳﺎ« ﺍﺳﺖ؟
‐13ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﻛﺪ ﺯﻳﺮ ﺍﺳﺖ؟
;'char c = 'w
;char* p = c
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 246
;short* q = &d
;p = q
‐18ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﻛﺪ ﺯﻳﺮ ﺍﺳﺖ؟
;int* p = new int
;int* q = new int
cout << "p = " << p << ", p + q = " << p + q
;<< endl
‐19ﺗﻨﻬﺎ ﮐﺎﺭﻱ ﮐﻪ ﻧﺒﺎﻳﺪ ﻫﺮﮔﺰ ﺑﺎ ﺍﺷﺎﺭﻩﮔﺮ NULLﺍﻧﺠﺎﻡ ﺩﻫﻴﺪ ﭼﻴﺴﺖ؟
‐20ﺩﺭ ﺍﻋﻼﻥ ﺯﻳﺮ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ ﻛﻪ ﻧﻮﻉ pﭼﻴﺴﺖ ﻭ ﺑﮕﻮﻳﻴﺪ ﺁﻥ ﭼﮕﻮﻧﻪ ﻣﻲﺗﻮﺍﻧﺪ
ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ:
;double**** p
‐21ﺍﮔﺮ xﺁﺩﺭﺱ 0x3fffd1cﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﻣﻘﺎﺩﻳﺮ pﻭ qﺑﺮﺍﻱ ﻫﺮ ﻳﻚ ﺍﺯ
ﻣﻮﺍﺭﺩ ﺯﻳﺮ ﭼﻴﺴﺖ؟
;double x = 1.01
;double* p = &x
;double* q = p + 5
‐22ﺍﮔﺮ pﻭ qﺍﺷﺎﺭﻩﮔﺮﻫﺎﻳﻲ ﺑﻪ intﺑﺎﺷﻨﺪ ﻭ nﻣﺘﻐﻴﺮﻱ ﺍﺭ ﻧﻮﻉ intﺑﺎﺷﺪ ،ﻛﺪﺍﻡ ﻳﻚ
ﺍﺯ ﻣﻮﺍﺭﺩ ﺯﻳﺮ ﻣﺠﺎﺯ ﺍﺳﺖ؟
ﭖ( p + n ﺏ( p – q ﺍﻟﻒ( p + q
ﺝ( n - q ﺙ( n + p ﺕ( p – n
‐23ﺍﻳﻦ ﮔﻔﺘﻪ ﻛﻪ ﻳﻚ ﺁﺭﺍﻳﻪ ﺩﺭ ﺣﻘﻴﻘﺖ ﻳﻚ ﺍﺷﺎﺭﻩ ﮔﺮ ﺛﺎﺑﺖ ﺍﺳﺖ ﭼﻪ ﻣﻌﻨﻲ ﻣﻲﺩﻫﺪ؟
‐24ﻭﻗﺘﻲ ﺗﻨﻬﺎ ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﻳﻚ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ ،ﭼﮕﻮﻧﻪ ﺍﺳﺖ ﻛﻪ
ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﻫﺮ ﻋﻨﺼﺮﻱ ﺍﺯ ﺁﺭﺍﻳﻪ ﺭﺍ ﺩﺳﺘﻴﺎﺑﻲ ﻛﻨﺪ؟
‐25ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ ﭼﺮﺍ ﺳﻪ ﺷﺮﻁ ﺯﻳﺮ ﺑﺮﺍﻱ ﺁﺭﺍﻱۀ aﻭ ﻳﻚ ﻋﺪﺩ ﺻﺤﻴﺢ iﺩﺭﺳﺖ
ﺍﺳﺖ؟
;)a[i] == *(a + i
;]*(a + i) == i[a
;]a[i] == i[a
‐26ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺩﻭ ﺍﻋﻼﻥ ﺯﻳﺮ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ:
;)(double * f
;))(double (*f
‐27ﺑﺮﺍﻱ ﻫﺮ ﻳﻚ ﺍﺯ ﻣﻮﺍﺭﺩ ﺯﻳﺮ ﻳﻚ ﺍﻋﻼﻥ ﺑﻨﻮﻳﺴﻴﺪ:
ﺍﻟﻒ( ﻳﻚ ﺁﺭﺍﻳﻪ ﺍﺯ ﻫﺸﺖ float
ﺏ( ﻳﻚ ﺁﺭﺍﻳﻪ ﺍﺯ ﻫﺸﺖ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ float
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 248
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﺗﺎﺑﻌﻲ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺑﺮﺍﻱ ﺟﺴﺘﺠﻮﻱ ﺁﺩﺭﺱ ﻳﻚ ﻋﺪﺩ ﺻﺤﻴﺢ ﻣﻔﺮﻭﺽ
ﺩﺭ ﻳﻚ ﺁﺭﺍﻳﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﺪ .ﺍﮔﺮ ﻋﺪﺩ ﻣﻔﺮﻭﺽ ﭘﻴﺪﺍ ﺷﻮﺩ ﺗﺎﺑﻊ ﺁﺩﺭﺱ ﺁﻥ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ ﻭ ﺩﺭ
ﻏﻴﺮ ﺍﻳﻦ ﺻﻮﺭﺕ nullﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ.
‐2ﺗﺎﺑﻌﻲ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ nﺍﺷﺎﺭﻩ ﮔﺮ ﺑﻪ floatﺩﺭﻳﺎﻓﺖ ﻛﻨﺪ ﻭ ﺁﺭﺍﻳﻪ ﺟﺪﻳﺪﻱ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ
ﻛﻪ ﺷﺎﻣﻞ ﻣﻘﺎﺩﻳﺮ ﺁﻥ nﻋﺪﺩ floatﺑﺎﺷﺪ.
‐3ﻛﺪ ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﺑﻨﻮﻳﺴﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﻣﺠﻤﻮﻉ floatﻫﺎﻳﻲ ﻛﻪ ﺑﺎ nﺍﺷﺎﺭﻩ ﮔﺮ ﺩﺭ ﺁﺭﺍﻳﻪ
pﺑﻪ ﺁﻥ ﻫﺎ ﺍﺷﺎﺭﻩ ﻣﻲ ﺷﻮﺩ ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ.
;)float sum(float* p[], int n
‐4ﻛﺪ ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﺑﻨﻮﻳﺴﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﻋﻼﻣﺖ ﻫﺮ ﻳﻚ ﺍﺯ flatﻫﺎﻱ ﻣﻨﻔﻲ ﻛﻪ ﺑﻪ ﻭﺳﻴﻠﻪ
nﺍﺷﺎﺭﻩ ﮔﺮ ﺩﺭ ﺁﺭﺍﻳﻪ pﺑﻪ ﺁﻥ ﻫﺎ ﺍﺷﺎﺭﻩ ﻣﻲ ﺷﻮﺩ ﺭﺍ ﺗﻐﻴﻴﺮ ﻣﻲ ﺩﻫﺪ.
;)void abs(float* p[], int n
‐5ﻛﺪ ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﺑﻨﻮﻳﺴﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﻪ ﺻﻮﺭﺕ ﻏﻴﺮ ﻣﺴﺘﻘﻴﻢ floatﻫﺎﻱ ﺍﺷﺎﺭﻩ ﺷﺪﻩ
ﺗﻮﺳﻂ nﺍﺷﺎﺭﻩ ﮔﺮ ﺩﺭ ﺁﺭﺍﻳﻪ pﺭﺍ ﺑﺎ ﻣﺮﺗﺐ ﺳﺎﺯﻱ ﺍﺷﺎﺭﻩ ﮔﺮﻫﺎ ﻣﺮﺗﺐ ﻣﻲ ﻛﻨﺪ.
;)void sort(float* p[], int n
‐6ﻛﺪ ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﺑﻨﻮﻳﺴﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺗﻌﺪﺍﺩ ﺑﺎﻳﺖ ﻫﺎﻱ ﺩﺭﻭﻥ sﺭﺍ ﻣﻲ ﺷﻤﺎﺭﺩ ﺗﺎ ﺍﻳﻦ ﻛﻪ
sﺑﻪ ﻛﺎﺭﺍﻛﺘﺮ ' '\0ﺍﺷﺎﺭﻩ ﻛﻨﺪ.
;)unsigned len(const char* s
‐7ﻛﺪ ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﺑﻨﻮﻳﺴﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ nﺑﺎﻳﺖ ﺍﻭﻝ ﺣﺎﻓﻈﻪ ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ *s2ﺭﺍ ﺩﺍﺧﻞ
ﺑﺎﻳﺖ ﻫﺎﻱ ﺷﺮﻭﻉ ﺷﺪﻩ ﺍﺯ *s1ﻛﭙﻲ ﻣﻲ ﻛﻨﺪ n .ﺗﻌﺪﺍﺩ ﺑﺎﻳﺖ ﻫﺎﻳﻲ ﺍﺳﺖ ﻛﻪ s2ﻣﻲ ﺗﻮﺍﻧﺪ
ﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﻛﻪ ﺑﻪ ﻛﺎﺭﺍﻛﺘﺮ ' '\0ﺍﺷﺎﺭﻩ ﻛﻨﺪ.
;)void cpy(char* s1, const char* s2
249 ﻓﺼﻞ هﻔﺘﻢ /اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ
‐8ﻛﺪ ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﺑﻨﻮﻳﺴﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺣﺪﺍﻛﺜﺮ nﺑﺎﻳﺖ ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ *s2ﺭﺍ ﺑﺎ ﺑﺎﻳﺖ ﻫﺎﻱ
ﻣﺘﻨﺎﻇﺮ ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ *s1ﻣﻘﺎﻳﺴﻪ ﻣﻲ ﻛﻨﺪ ﻛﻪ nﺗﻌﺪﺍﺩ ﺑﺎﻳﺖ ﻫﺎﻳﻲ ﺍﺳﺖ ﻛﻪ s2ﻣﻲ ﺗﻮﺍﻧﺪ
ﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﻛﻪ ﺑﻪ ﻛﺎﺭﺍﻛﺘﺮ ' '\0ﺍﺷﺎﺭﻩ ﻛﻨﺪ .ﺍﮔﺮ ﻫﻤﻪ nﺑﺎﻳﺖ ﻣﻌﺎﺩﻝ ﺑﺎﺷﻨﺪ
ﺗﺎﺑﻊ ﺑﺎﻳﺪ 0ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ .ﺩﺭ ﻏﻴﺮ ﺍﻳﻦ ﺻﻮﺭﺕ ﺑﺴﺘﻪ ﺑﻪ ﺍﻳﻦ ﻛﻪ ﺩﺭ ﺍﻭﻟﻴﻦ ﺍﺧﺘﻼﻑ ﺑﺎﻳﺖ
ﻣﻮﺟﻮﺩ ﺩﺭ s1ﻛﻮﭼﻚ ﺗﺮ ﻳﺎ ﺑﺰﺭﮒ ﺗﺮ ﺍﺯ ﺑﺎﻳﺖ ﻣﻮﺟﻮﺩ ﺩﺭ s2ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ -1ﻳﺎ 1ﺭﺍ
ﺑﺮﮔﺮﺩﺍﻧﺪ.
;)int cmp(char* s1, char* s2
‐9ﻛﺪ ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﺑﻨﻮﻳﺴﻴﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ nﺑﺎﻳﺖ ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ sﺭﺍ ﺑﻪ ﺩﻧﺒﺎﻝ ﻛﺎﺭﺍﻛﺘﺮ c
ﺟﺴﺘﺠﻮ ﻣﻲ ﻛﻨﺪ ﻛﻪ nﺗﻌﺪﺍﺩ ﺑﺎﻳﺖ ﻫﺎﻳﻲ ﺍﺳﺖ ﻛﻪ sﻣﻲ ﺗﻮﺍﻧﺪ ﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﻛﻪ
ﺑﻪ ﻛﺎﺭﺍﻛﺘﺮ ﺗﻬﻲ ' '\0ﺍﺷﺎﺭﻩ ﻛﻨﺪ .ﺍﮔﺮ ﻛﺎﺭﺍﻛﺘﺮ cﭘﻴﺪﺍ ﺷﻮﺩ ﻳﻚ ﺍﺷﺎﺭﻩ ﮔﺮ ﺑﻪ ﺁﻥ ﺑﺮﮔﺮﺩﺍﻧﺪﻩ
ﻣﻲ ﺷﻮﺩ ﻭ ﺩﺭ ﻏﻴﺮ ﺍﻳﻦ ﺻﻮﺭﺕ NULLﺑﺮﮔﺮﺩﺍﻧﺪﻩ ﻣﻲ ﺷﻮﺩ.
;)char* chr(char* s, char c
‐10ﺗﺎﺑﻊ ﺯﻳﺮ ﻛﻪ ﺣﺎﺻﻞ ﺿﺮﺏ nﻣﻘﺪﺍﺭ ) f(1ﻭ ) f(2ﻭ ...ﻭ ) f(nﺭﺍ ﺑﺮﻣﻲ
ﮔﺮﺩﺍﻧﺪ ﺑﻨﻮﻳﺴﻴﺪ )ﺑﻪ ﻣﺜﺎﻝ 7‐18ﻧﮕﺎﻩ ﻛﻨﻴﺪ(.
;)int product(int (*pf)(int k), int n
‐11ﻗﺎﻧﻮﻥ ﺫﻭﺯﻧﻘﻪ ﺭﺍ ﺑﺮﺍﻱ ﺍﻧﺘﮕﺮﺍﻝ ﮔﻴﺮﻱ ﻳﻚ ﺗﺎﺑﻊ ﭘﻴﺎﺩﻩ ﺳﺎﺯﻱ ﻛﻨﻴﺪ .ﺍﺯ ﺗﺎﺑﻊ ﺯﻳﺮ ﺍﺳﺘﻔﺎﺩﻩ
ﻧﻤﺎﻳﻴﺪ:
double trap(double (*pf)(double x), double a,
;)double b, int n
ﺩﺭ ﺍﻳﻦ ﺟﺎ pfﺑﻪ ﺗﺎﺑﻊ fﻛﻪ ﺑﺎﻳﺪ ﺍﻧﺘﮕﺮﺍﻝ ﮔﻴﺮﻱ ﺷﻮﺩ ﺍﺷﺎﺭﻩ ﻣﻲ ﻛﻨﺪ a .ﻭ bﻓﺎﺻﻠﻪ ﺍﻱ
ﺍﺳﺖ ﻛﻪ fﺩﺭ ﺁﻥ ﻓﺎﺻﻠﻪ ﺍﻧﺘﮕﺮﺍﻝ ﮔﻴﺮﻱ ﻣﻲ ﺷﻮﺩ ﻭ nﺗﻌﺪﺍﺩ ﺯﻳﺮ ﻓﺎﺻﻠﻪ ﻫﺎﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ
ﺍﺳﺖ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﻓﺮﺍﺧﻮﺍﻧﻲ ;) trap(square, 1, 2, 100ﻣﻘﺪﺍﺭ 1.41421
ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ .ﻗﺎﻧﻮﻥ ﺯﻭﺫﻧﻘﻪ ﻣﺠﻤﻮﻉ ﻣﺴﺎﺣﺖ ﻫﺎﻱ ﺫﻭﺯﻧﻘﻪ ﻛﻪ ﻣﺴﺎﺣﺖ ﺗﻘﺮﻳﺒﻲ ﺯﻳﺮ
ﻧﻤﻮﺩﺍﺭ fﺍﺳﺖ ﺭﺍ ﺑﺮﻣﻲ ﮔﺮﺩﺍﻧﺪ .ﺑﻪ ﻃﻮﺭ ﻣﺜﺎﻝ ﺍﮔﺮ h = 5ﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ ﺗﺎﺑﻊ ﻣﺬﻛﻮﺭ ﻣﻘﺪﺍﺭ
ﺯﻳﺮ ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ ﻛﻪ h = (b-a)/5ﭘﻬﻨﺎﻱ ﻫﺮ ﻳﻚ ﺍﺯ ﺫﻭﺯﻧﻘﻪ ﻫﺎﻱ ﺯﻳﺮ ﺍﺳﺖ:
h
])[ f (a) + 2 f (a + h) + 2 f (a + 2h) + 2 f (a + 3h) + 2 f (a + 4h) + f (b
2
ﻓﺼﻞ ﻫﺸﺘﻢ
» ﺭﺷﺘﻪﻫﺎﻱ ﻛﺎﺭﺍﻛﺘﺮﻱ ﻭ ﻓﺎﻳﻞﻫﺎ ﺩﺭ C++ﺍﺳﺘﺎﻧﺪﺍﺭﺩ«
8‐1ﻣﻘﺪﻣﻪ
ﺩﺍﺩﻩﻫﺎﻳﻲ ﮐﻪ ﺩﺭ ﺭﺍﻳﺎﻧﻪﻫﺎ ﭘﺮﺩﺍﺯﺵ ﻣﻲﺷﻮﻧﺪ ﻫﻤﻴﺸﻪ ﻋﺪﺩ ﻧﻴﺴﺘﻨﺪ .ﻣﻌﻤﻮﻻ ﻻﺯﻡ ﺍﺳﺖ
ﮐﻪ ﺍﻃﻼﻋﺎﺕ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻣﺜﻞ ﻧﺎﻡ ﺍﻓﺮﺍﺩ – ﻧﺸﺎﻧﻲﻫﺎ – ﻣﺘﻮﻥ – ﺗﻮﺿﻴﺤﺎﺕ – ﮐﻠﻤﺎﺕ ﻭ ...ﻧﻴﺰ
ﭘﺮﺩﺍﺯﺵ ﮔﺮﺩﻧﺪ ،ﺟﺴﺘﺠﻮ ﺷﻮﻧﺪ ،ﻣﻘﺎﻳﺴﻪ ﺷﻮﻧﺪ ،ﺑﻪ ﻳﮑﺪﻳﮕﺮ ﺍﻟﺼﺎﻕ ﺷﻮﻧﺪ ﻳﺎ ﺍﺯ ﻫﻢ ﺗﻔﮑﻴﮏ
ﮔﺮﺩﻧﺪ .ﺩﺭ ﺍﻳﻦ ﻓﺼﻞ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﭼﻄﻮﺭ ﺍﻃﻼﻋﺎﺕ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ
ﮐﻨﻴﻢ ﻭ ﻳﺎ ﺁﻥﻫﺎ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺩﻟﺨﻮﺍﻩ ﺑﻪ ﺧﺮﻭﺟﻲ ﺑﻔﺮﺳﺘﻴﻢ .ﺩﺭ ﻫﻤﻴﻦ ﺭﺍﺳﺘﺎ ﺗﻮﺍﺑﻌﻲ ﻣﻌﺮﻓﻲ
ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﺍﻧﺠﺎﻡ ﺍﻳﻦ ﮐﺎﺭﻫﺎ ﺭﺍ ﺁﺳﺎﻥ ﻣﻲﮐﻨﻨﺪ.
ﻳﻚ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ )ﮐﻪ ﺑﻪ ﺁﻥ ﺭﺷﺖۀ Cﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ( ﻳﻚ ﺳﻠﺴﻠﻪ ﺍﺯ
ﻛﺎﺭﺍﻛﺘﺮﻫﺎﻱ ﻛﻨﺎﺭ ﻫﻢ ﺩﺭ ﺣﺎﻓﻈﻪ ﺍﺳﺖ ﻛﻪ ﺑﺎ ﻛﺎﺭﺍﻛﺘﺮ NULﻳﻌﻨﻲ ' '\0ﭘﺎﻳﺎﻥ ﻳﺎﻓﺘﻪ ﺍﺳﺖ.
ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻭﺳﻴﻞۀ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺍﺯ ﻧﻮﻉ *) charﻳﻌﻨﻲ ﺍﺷﺎﺭﻩﮔﺮﻱ
ﺑﻪ (charﺩﺳﺘﻴﺎﺑﻲ ﻧﻤﻮﺩ .ﭼﻮﻥ ﺁﺭﺍﻳﻪﻫﺎ ﺑﺴﻴﺎﺭ ﺷﺒﻴﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﻓﺘﺎﺭ ﻣﻲﮐﻨﻨﺪ ،ﺍﺯ
ﺁﺭﺍﻳﻪﻫﺎﻳﻲ ﺑﺎ ﻧﻮﻉ charﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺑﺮﺍﻱ ﭘﺮﺩﺍﺯﺵ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ.
ﺳﺮﻓﺎﻳﻞ > <cstringﺗﻮﺍﺑﻊ ﻭﻳﮋۀ ﺯﻳﺎﺩﻱ ﺩﺍﺭﺩ ﮐﻪ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﻣﺎ ﺭﺍ ﺩﺭ ﺩﺳﺖﮐﺎﺭﻱ
ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻳﺎﺭﻱ ﻣﻲﮐﻨﻨﺪ .ﻣﺜﻼ ﺗﺎﺑﻊ ) strlen(sﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺭﺷﺖۀ
251 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
ﮐﺎﺭﺍﮐﺘﺮﻱ Sﺑﺪﻭﻥ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻧﻲ NULﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﻫﻢۀ ﺗﻮﺍﺑﻊ ﻣﺬﮐﻮﺭ ﺩﺍﺭﺍﻱ
ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻳﻲ ﺍﺯ ﻧﻮﻉ * charﻫﺴﺘﻨﺪ .ﭘﺲ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻣﻄﺎﻟﻌﻪ
ﻧﻤﺎﻳﻴﻢ ،ﺑﻪ ﺍﺧﺘﺼﺎﺭ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ ﻣﺮﻭﺭ ﻣﻲﮐﻨﻴﻢ.
8‐2ﻣﺮﻭﺭﻱ ﺑﺮ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ
ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﻣﺘﻐﻴﺮﻱ ﺍﺳﺖ ﮐﻪ ﺣﺎﻭﻱ ﻳﮏ ﺁﺩﺭﺱ ﺍﺯ ﺣﺎﻓﻈﻪ ﻣﻲﺑﺎﺷﺪ .ﻧﻮﻉ ﺍﻳﻦ
ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ ﻣﻘﺪﺍﺭﻱ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﺁﻥ ﺁﺩﺭﺱ ﺫﺧﻴﺮﻩ ﺷﺪﻩ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ &
ﻣﻲﺗﻮﺍﻥ ﺁﺩﺭﺱ ﻳﮏ ﺷﻲ ﺭﺍ ﭘﻴﺪﺍ ﮐﺮﺩ .ﻫﻤﭽﻨﻴﻦ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ * ﻣﻲﺗﻮﺍﻧﻴﻢ
ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺩﺭ ﻳﮏ ﺁﺩﺭﺱ ﻗﺮﺍﺭ ﺩﺍﺭﺩ ﺭﺍ ﻣﺸﺨﺺ ﮐﻨﻴﻢ .ﺑﻪ ﺗﻌﺎﺭﻳﻒ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ:
;int n = 44
;int* p = &n
ﺍﺷﺎﺭﻩﮔﺮ ﺩﻳﮕﺮﻱ ﺑﻪ ﻧﺎﻡ qﺍﻋﻼﻥ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﻫﻢ ﺑﻪ nﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ .ﺣﺎﻻ ﻫﻢ pﻭ ﻫﻢ q
ﺑﻪ nﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﻨﺪ .ﺍﻟﺒﺘﻪ pﻭ qﺩﻭ ﺍﺷﺎﺭﻩﮔﺮ ﻣﺠﺰﺍ ﻭ ﻣﺴﺘﻘﻞ ﺍﺯ ﻫﻢ ﻫﺴﺘﻨﺪ .ﺑﺎ ﺩﺳﺘﻮﺭ
;cout << *p
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 252
ﺁﺩﺭﺱ ﻣﺘﻐﻴﺮﻱ ﮐﻪ pﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﺍﻟﺒﺘﻪ ﺍﮐﻨﻮﻥ ﺑﻪ ﻳﮏ ﺍﺳﺘﺜﻨﺎ
ﺑﺮﻣﻲﺧﻮﺭﻳﻢ .ﺍﮔﺮ pﺍﺯ ﻧﻮﻉ * charﺑﺎﺷﺪ ،ﺣﺎﺻﻞ ; cout << pﻃﻮﺭ ﺩﻳﮕﺮﻱ
ﺧﻮﺍﻫﺪ ﺑﻮﺩ.
ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ ،ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺩﺭﻭﻥ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ strﻳﮑﻲ ﻳﮑﻲ ﺑﻪ ﺧﺮﻭﺟﻲ
ﻣﻲﺭﻭﻧﺪ ﺗﺎ ﻭﻗﺘﻲ ﮐﻪ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺍﻧﺘﻬﺎﻳﻲ NULﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ.
– 4ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﺜﻞ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻌﻤﻮﻟﻲ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﮐﺮﺩ
;cin >> str ﻣﺜﻞ:
ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ ،ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺍﺭﺩ ﺷﺪﻩ ﻳﮑﻲ ﻳﮑﻲ ﺩﺭﻭﻥ strﺟﺎﻱ ﻣﻲﮔﻴﺮﻧﺪ ﺗﺎ
ﻭﻗﺘﻲ ﮐﻪ ﺑﻪ ﻳﮏ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﺩﺭ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺭﻭﺩﻱ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ .ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺑﺎﻳﺪ
ﻣﻄﻤﺌﻦ ﺑﺎﺷﺪ ﮐﻪ ﺁﺭﺍﻱۀ strﺑﺮﺍﻱ ﺩﺭﻳﺎﻓﺖ ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺍﺭﺩ ﺷﺪﻩ ﺟﺎ ﺩﺍﺭﺩ.
253 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
S ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ sﺩﺍﺭﺍﻱ ﭘﻨﺞ ﻋﻀﻮ ﺍﺳﺖ ﮐﻪ ﻋﻀﻮ ﭘﻨﺠﻢ ،ﮐﺎﺭﺍﮐﺘﺮ ''\0
0 A ﻣﻲﺑﺎﺷﺪ .ﺗﺼﻮﻳﺮ ﺧﺮﻭﺟﻲ ﺍﻳﻦ ﻣﻄﻠﺐ ﺭﺍ ﺗﺎﻳﻴﺪ ﻣﻲﻧﻤﺎﻳﺪ .ﻭﻗﺘﻲ ﮐﺎﺭﺍﮐﺘﺮ
1 B
2 C ' '\0ﺑﻪ coutﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ ،ﻫﻴﭻ ﭼﻴﺰ ﭼﺎﭖ ﻧﻤﻲﺷﻮﺩ .ﺣﺘﻲ ﺟﺎﻱ
3 D
4 Ø ﺧﺎﻟﻲ ﻫﻢ ﭼﺎﭖ ﻧﻤﻲﺷﻮﺩ .ﺧﻂ ﺁﺧﺮ ﺧﺮﻭﺟﻲ ،ﻋﻀﻮ ﭘﻨﺠﻢ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲ ﺩﻫﺪ
ﮐﻪ ﻣﻴﺎﻥ ﺩﻭ ﻋﻼﻣﺖ ﺁﭘﺴﺘﺮﻭﻑ ﻫﻴﭻ ﭼﻴﺰﻱ ﭼﺎﭖ ﻧﺸﺪﻩ.
ﺧﻮﺍﻫﻴﻢ ﭘﺮﺩﺍﺧﺖ .ﺭﻭﺵ ﺩﻳﮕﺮ ،ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﮐﻤﮑﻲ ﺍﺳﺖ ﮐﻪ ﺁﻥ ﺭﺍ ﺩﺭ ﺍﺩﺍﻣﻪ ﺷﺮﺡ
ﻣﻲﺩﻫﻴﻢ.
ﻭﻗﺘﻲ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺩﺳﺘﻮﺭ cinﺑﺮﺳﺪ ،ﻫﻤﺎﻥ ﺟﺎ ﻣﺘﻮﻗﻒ ﻣﻲﺷﻮﺩ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﮐﺎﺭﺑﺮ
ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻳﻲ ﺭﺍ ﺗﺎﻳﭗ ﮐﺮﺩﻩ ﻭ ﺳﭙﺲ ﮐﻠﻴﺪ Enterﺭﺍ ﻓﺸﺎﺭ ﺩﻫﺪ .ﭘﺲ ﺍﺯ ﻓﺸﺮﺩﻥ ﮐﻠﻴﺪ
Enterﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺗﺎﻳﭗ ﺷﺪﻩ ﺑﻪ ﻳﮏ ﺣﺎﻓﻆۀ ﻣﻴﺎﻧﻲ ﻣﻨﺘﻘﻞ ﻣﻲﺷﻮﺩ ﻭ ﻋﻤﻠﮕﺮ cin
ﺍﺯ ﺁﻥ ﺣﺎﻓﻈﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﺑﺮﺩﺍﺷﺖ ﻣﻲﮐﻨﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﻳﺎ ﮐﺎﺭﺍﮐﺘﺮ
ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﺮﺳﺪ .ﺳﭙﺲ ﺑﺮﻧﺎﻣﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ .ﻭﻗﺘﻲ ﺩﻭﺑﺎﺭﻩ ﺑﺮﻧﺎﻣﻪ ﺑﻪ cinﺑﺮﺧﻮﺭﺩ ﮐﻨﺪ ﺑﻪ
ﻫﻤﺎﻥ ﺣﺎﻓﻆۀ ﻣﻴﺎﻧﻲ ﻣﺮﺍﺟﻌﻪ ﻣﻲﻧﻤﺎﻳﺪ ﺗﺎ ﻣﺠﻤﻮﻉۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﺗﺎ ﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺧﺎﻟﻲ
ﺑﻌﺪﻱ ﺑﺮﺩﺍﺷﺖ ﮐﻨﺪ .ﺍﮔﺮ cinﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﺮﺳﺪ ،ﺣﺎﻓﻆۀ ﻣﻴﺎﻧﻲ ﺧﺎﻟﻲ ﺷﺪﻩ ﺍﺳﺖ
ﻭ ﺩﺭ ﺍﺟﺮﺍﻱ ﺑﻌﺪﻱ cinﺩﻭﺑﺎﺭﻩ ﻣﻨﺘﻈﺮ ﻣﻲﻣﺎﻧﺪ ﺗﺎ ﮐﺎﺭﺑﺮ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻳﻲ ﺭﺍ ﻭﺍﺭﺩ ﻧﻤﺎﻳﺪ.
255 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
ﺩﺭ ﻧﻤﻮﻧﻪ ﺍﺟﺮﺍﻱ ﺑﺎﻻ ،ﺣﻠﻘﻪ whileﺩﻩ ﻣﺮﺗﺒﻪ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ ﻭ ﻫﺮ ﺑﺎﺭ ﻳﮏ ﮐﻠﻤﻪ ﺭﺍ
ﻣﻲﺧﻮﺍﻧﺪ )ﺧﻮﺍﻧﺪﻥ Ctrl+Zﻧﻴﺰ ﺩﺭ ﻳﮏ ﺗﮑﺮﺍﺭ ﺍﻧﺠﺎﻡ ﻣﻲﮔﻴﺮﺩ( .ﻫﺮ ﺑﺎﺭ ﮐﻪ ﮐﺎﺭﺑﺮ ﻋﺒﺎﺭﺗﻲ
ﺭﺍ ﺗﺎﻳﭗ ﮐﻨﺪ ﻭ ﮐﻠﻴﺪ Enterﺭﺍ ﻓﺸﺎﺭ ﺩﻫﺪ ،ﺑﺮﻧﺎﻣﻪ ﮐﻠﻤﺎﺕ ﺁﻥ ﻋﺒﺎﺭﺕ ﺭﺍ ﻳﮑﻲ ﻳﮑﻲ
ﺧﻮﺍﻧﺪﻩ ﻭ ﺁﻥ ﮐﻠﻤﺎﺕ ﺭﺍ ﻣﻴﺎﻥ ﺩﻭ ﻋﻼﻣﺖ ﻧﻘﻞ ﻗﻮﻝ "" ﭼﺎﭖ ﻣﻲﮐﻨﺪ .ﻭﻗﺘﻲ ﻫﻢۀ ﮐﻠﻤﺎﺕ
ﺗﻤﺎﻡ ﺷﺪﻧﺪ ،ﺑﺮﻧﺎﻣﻪ ﻣﻨﺘﻈﺮ ﻣﻲﻣﺎﻧﺪ ﺗﺎ ﮐﺎﺭﺑﺮ ﻋﺒﺎﺭﺕ ﺟﺪﻳﺪﻱ ﺭﺍ ﺗﺎﻳﭗ ﮐﺮﺩﻩ ﻭ ﮐﻠﻴﺪ Enter
ﺭﺍ ﻓﺸﺎﺭ ﺩﻫﺪ.
ﻋﺒﺎﺭﺕ *wordﺣﻠﻘﻪ ﺭﺍ ﮐﻨﺘﺮﻝ ﻣﻲﮐﻨﺪ .ﭼﻮﻥ wordﻳﮏ ﺁﺭﺍﻳﻪ ﺍﺳﺖ *word ،ﺑﻪ
ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ ﺁﺭﺍﻳﻪ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻣﻘﺪﺍﺭ ﻋﺒﺎﺭﺕ *wordﺗﻨﻬﺎ ﻭﻗﺘﻲ ﺻﻔﺮ )ﻳﻌﻨﻲ
(falseﺍﺳﺖ ﮐﻪ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ wordﻳﮏ ﺭﺷﺖۀ ﺧﺎﻟﻲ ﺑﺎﺷﺪ ﮐﻪ ﻓﻘﻂ ﺷﺎﻣﻞ
' '\0ﺍﺳﺖ .ﺑﻪ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ،ﺧﺎﻟﻲ ﻣﻲﮔﻮﻳﻨﺪ ﺍﮔﺮ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﻥ ،ﮐﺎﺭﺍﮐﺘﺮ
NULﺑﺎﺷﺪ.
ﺑﻨﺎﺑﺮﺍﻳﻦ ،ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻫﻴﭻ ﻭﻗﺖ ﻣﺘﻮﻗﻒ ﻧﻤﻲﺷﻮﺩ ﻣﮕﺮ ﺍﻳﻦ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮ ' '\0ﻭﺍﺭﺩ
ﺷﻮﺩ .ﺍﻳﻦ ﮐﺎﺭ ﻣﻤﮑﻦ ﻧﻴﺴﺖ ﻣﮕﺮ ﺍﻳﻦ ﮐﻪ ﮐﻠﻴﺪ Ctrl+Zﺭﺍ ﻓﺸﺎﺭ ﺩﻫﻴﺪ .ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ
ﮐﺎﺭﺍﮐﺘﺮ ﺗﻬﻲ ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ wordﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺣﻠﻘﻪ
ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ .ﻋﻤﻞ ﺣﻠﻖۀ ﻣﺜﺎﻝ 8‐2ﻣﻲﺗﻮﺍﻧﺪ ﺑﺎ ﻛﺪ ﺯﻳﺮ ﺟﺎﻳﮕﺰﻳﻦ ﺷﻮﺩ:
cin >> word
)while (*word
;"{ cout << "\t\"" << word << "\"\n
;cin >> word
}
ﺑﻪ cinﺷﻲﺀ ﻓﺮﺁﻳﻨﺪ ﻭﺭﻭﺩﻱ ﻣﻲﮔﻮﻳﻨﺪ .ﺍﻳﻦ ﺷﻲ ﺷﺎﻣﻞ ﺗﻮﺍﺑﻊ ﺯﻳﺮ ﺍﺳﺖ:
)(cin.getline() , cin.get() , cin.ignore() , cin.putback() , cin.peek
ﻫﻢۀ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺷﺎﻣﻞ ﭘﻴﺸﻮﻧﺪ cinﻫﺴﺘﻨﺪ ﺯﻳﺮﺍ ﺁﻥﻫﺎ ﻋﻀﻮﻱ ﺍﺯ cinﻣﻲﺑﺎﺷﻨﺪ .ﺑﻪ
coutﺷﻲﺀ ﻓﺮﺁﻳﻨﺪ ﺧﺮﻭﺟﻲ ﻣﻲﮔﻮﻳﻨﺪ .ﺍﻳﻦ ﺷﻲ ﻧﻴﺰ ﺷﺎﻣﻞ ﺗﺎﺑﻊ )( cout.putﺍﺳﺖ.
ﻧﺤﻮۀ ﮐﺎﺭﺑﺮﺩ ﻫﺮ ﻳﮏ ﺍﺯ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺭﺍ ﺩﺭ ﺍﺩﺍﻣﻪ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ.
ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ nﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ ;)cin.getline(str,n
ﺩﺭﻭﻥ strﺧﻮﺍﻧﺪﻩ ﺷﻮﺩ ﻭ ﻣﺎﺑﻘﻲ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺍﺭﺩ ﺷﺪﻩ ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﻧﺪ.
ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺑﻪ ﺷﮑﻞ ) (*lineﺍﺳﺖ .ﺍﻳﻦ ﺷﺮﻁ ﻓﻘﻂ ﻭﻗﺘﻲ trueﺍﺳﺖ ﮐﻪ
ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ lineﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻏﻴﺮ ﺗﻬﻲ ﺑﺎﺷﺪ .ﻫﺮ ﺑﺎﺭ ﮐﻪ ﺣﻠﻘﻪ ﺍﺟﺮﺍ
ﻣﻲﮔﺮﺩﺩ 80 ،ﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ ﺩﺭﻭﻥ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ lineﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ.
ﺗﺎﺑﻊ )( getlineﻧﺴﺦۀ ﺩﻳﮕﺮﻱ ﻫﻢ ﺩﺍﺭﺩ .ﻭﻗﺘﻲ ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺎ ﺳﻪ ﭘﺎﺭﺍﻣﺘﺮ ﺑﻪ ﺷﮑﻞ
;)cin.getline(str, n, ch
ﻧﻴﺴﺖ ﮐﻪ ﺩﺭ ﺗﺎﺑﻊ )( getlineﻗﻴﺪ ﺷﻮﺩ ﻭ ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﻓﻘﻂ ﺑﺎ ﺩﻭ
ﭘﺎﺭﺍﻣﺘﺮ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ.
ﺩﺭ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﮐﺎﺭﺍﮐﺘﺮ ﮐﺎﻣﺎ ' ',ﺑﻪ ﻋﻨﻮﺍﻥ ﮐﺎﺭﺍﮐﺘﺮ ﻣﺮﺯﺑﻨﺪﻱ ﻓﺮﺽ ﺷﺪﻩ ﺍﺳﺖ.
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﭼﻮﻥ ﮐﺎﺭﺍﮐﺘﺮ ﮐﺎﻣﺎ ' ',ﺑﻪ ﻋﻨﻮﺍﻥ ﮐﺎﺭﺍﮐﺘﺮ ﻣﺮﺯﺑﻨﺪﻱ ﻣﻨﻈﻮﺭ ﺷﺪﻩ ،ﻫﺮ ﮐﺎﺭﺍﮐﺘﺮ
ﺩﻳﮕﺮﻱ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻣﻌﻤﻮﻟﻲ ﻓﺮﺽ ﻣﻲﺷﻮﺩ .ﻣﺜﻼ ﺑﻌﺪ ﺍﺯ ﻋﺒﺎﺭﺕ ""weary,
ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﻪ ﺻﻮﺭﺕ ﻣﺨﻔﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﺍﻣﺎ ﭼﻮﻥ ﻓﻘﻂ ﮐﺎﺭﺍﮐﺘﺮ ﮐﺎﻣﺎ ﺑﺮﺍﻱ
ﻣﺮﺯﺑﻨﺪﻱ ﻣﻨﻈﻮﺭ ﺷﺪﻩ ،ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻣﻌﻤﻮﻟﻲ ﺩﺭ ﻭﺭﻭﺩﻱ ﺑﻌﺪﻱ
ﺍﺳﺘﻔﺎﺩﻩ ﻭ ﭘﺮﺩﺍﺯﺵ ﻣﻲﺷﻮﺩ .ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﻫﺮ ﺩﻓﻌﻪ ﮐﻪ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﻣﺮﺯﺑﻨﺪﻱ ﺑﺮﺧﻮﺭﺩ
ﺷﻮﺩ ،ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ ﺣﺬﻑ ﻣﻲﺷﻮﺩ ﻭ ﻭﺭﻭﺩﻱ ﺑﻌﺪﻱ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻌﺪ ﺍﺯ ﺁﻥ ﺷﺮﻭﻉ ﻣﻲﮐﻨﺪ.
ﺗﺎﺑﻊ )( cin.getﺑﺮﺍﻱ ﺧﻮﺍﻧﺪﻥ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺯ ﻭﺭﻭﺩﻱ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ.
ﻓﺮﺍﺧﻮﺍﻧﻲ ) cin.get(chﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻌﺪﻱ ﺍﺯ ﻭﺭﻭﺩﻱ cinﺧﻮﺍﻧﺪﻩ
ﺷﺪﻩ ﻭ ﺑﻪ ﺩﺍﺧﻞ ﻣﺘﻐﻴﺮ chﮐﭙﻲ ﺷﻮﺩ .ﺍﮔﺮ ﺍﻳﻦ ﮐﺎﺭ ﻣﻮﻓﻘﻴﺖ ﺁﻣﻴﺰ ﺑﺎﺷﺪ ،ﻣﻘﺪﺍﺭ 1ﺑﺎﺯﮔﺸﺖ
ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ ،ﻣﻘﺪﺍﺭ 0ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 258
ﻣﺘﻐﻴﺮ preﻛﺎﺭﺍﻛﺘﺮ ﺧﻮﺍﻧﺪﻩ ﺷﺪۀ ﻗﺒﻠﻲ ﺭﺍ ﻧﮕﻪ ﻣﻲﺩﺍﺭﺩ .ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﺍﺳﺖ ﮐﻪ
ﺍﮔﺮ preﻳﻚ ﮐﺎﺭﺍﮐﺘﺮ ﺧﺎﻟﻲ ﻳﺎ ﻛﺎﺭﺍﻛﺘﺮ ﺧﻂ ﺟﺪﻳﺪ ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﮐﺎﺭﺍﮐﺘﺮﻱ ﮐﻪ ﺩﺭ ch
ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ ﺍﻭﻟﻴﻦ ﺣﺮﻑ ﺍﺯ ﮐﻠﻢۀ ﺑﻌﺪﻱ ﺍﺳﺖ .ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﮐﺎﺭﺍﮐﺘﺮ ﺩﺭﻭﻥ chﺑﺎ
ﺣﺮﻑ ﺑﺰﺭﮒ ﺟﺎﻳﮕﺰﻳﻦ ﻣﻲﺷﻮﺩ.
ﺗﺎﺑﻊ ) toupeer(chﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﮔﺮ chﺣﺮﻑ ﮐﻮﭼﮏ ﺑﺎﺷﺪ ،ﺁﻥ ﺭﺍ ﺑﻪ
ﺣﺮﻑ ﺑﺰﺭﮒ ﻣﻌﺎﺩﻟﺶ ﺗﺒﺪﻳﻞ ﮐﻨﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﺭ ﺳﺮﻓﺎﻳﻞ > <ctype.hﺗﻌﺮﻳﻒ ﺷﺪﻩ.
ﺍﻟﺒﺘﻪ ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻋﺒﺎﺭﺕ ﺯﻳﺮ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ:
;'ch += 'A' – 'a
;break
}
;return n
}
?What is 305 plus 9416
305 + 9416 = 9721
ﺗﺎﺑﻊ )( nextIntﺍﺯ ﺗﻤﺎﻡ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻣﻮﺟﻮﺩ ﺩﺭ cinﮔﺬﺭ ﻣﻲﮐﻨﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﺑﻪ ﺍﻭﻟﻴﻦ
ﻋﺪﺩ ﺑﺮﺧﻮﺭﺩ ﮐﻨﺪ .ﺩﺭ ﺍﺟﺮﺍﻱ ﺁﺯﻣﺎﻳﺸﻲ ﺑﺎﻻ ،ﺍﻭﻟﻴﻦ ﻋﺪﺩ 3ﺍﺳﺖ .ﭼﻮﻥ ﺍﻳﻦ ﺭﻗﻢ ﺑﺨﺸﻲ ﺍﺯ
ﻋﺪﺩ ﺻﺤﻴﺢ 305ﻣﻲﺑﺎﺷﺪ ،ﻣﺠﺪﺩﺍ ﺑﻪ ﺩﺭﻭﻥ cinﺑﺮﮔﺮﺩﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ ﻭ ﺣﺎﻻ ﺩﺳﺘﻮﺭ cin
ﺑﻌﺪﻱ ﺩﻭﺑﺎﺭﻩ ﺍﺯ ﻫﻤﺎﻥ ﮐﺎﺭﺍﮐﺘﺮ ﺷﺮﻭﻉ ﺑﻪ ﺧﻮﺍﻧﺪﻥ ﻣﻲﮐﻨﺪ ﻭ ﺗﺎ ﻓﺎﺻﻞۀ ﺧﺎﻟﻲ ﺑﻌﺪﻱ،
ﺧﻮﺍﻧﺪﻥ ﺭﺍ ﺍﺩﺍﻣﻪ ﺩﺍﺩﻩ ﻭ ﻧﺘﻴﺠﻪ ﺭﺍ ﺑﻪ ﺩﺭﻭﻥ nﻣﻨﺘﻘﻞ ﻣﻲﻧﻤﺎﻳﺪ .ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﮐﻞ ﻋﺪﺩ 305
ﺑﻪ ﺩﺭﻭﻥ nﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ.
ﺗﺎﺑﻊ )( cin.peekﺗﺮﮐﻴﺒﻲ ﺍﺯ ﺩﻭ ﺗﺎﺑﻊ )( cin.getﻭ )(cin.putback
;)( ch = cin.peekﮐﺎﺭﺍﮐﺘﺮ ﺑﻌﺪﻱ ﺭﺍ ﺑﻪ ﺩﺭﻭﻥ ch ﺍﺳﺖ .ﻳﻌﻨﻲ ﻋﺒﺎﺭﺕ
ﻣﻲﺧﻮﺍﻧﺪ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﺍﺯ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺣﺬﻑ ﻧﻤﺎﻳﺪ .ﻣﺜﺎﻝ ﺯﻳﺮ ،ﻃﺮﻳﻖۀ
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﻫﻢۀ ﺗﻮﺍﺑﻊ ﻓﻮﻕ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ intﺩﺭﻳﺎﻓﺖ ﻣﻲﮐﻨﻨﺪ ﻭ ﻳﮏ
ﻣﻘﺪﺍﺭ intﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﻨﺪ .ﻋﻠﺖ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻧﻮﻉ charﺩﺭ ﺍﺻﻞ ﻳﮏ ﻧﻮﻉ ﺻﺤﻴﺢ
ﺍﺳﺖ .ﺩﺭ ﻋﻤﻞ ﻭﻗﺘﻲ ﺗﻮﺍﺑﻊ ﻓﻮﻕ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﻣﻲﺑﺮﻧﺪ ،ﻳﮏ ﻣﻘﺪﺍﺭ charﺑﻪ ﺗﺎﺑﻊ ﻣﻲﻓﺮﺳﺘﻨﺪ
ﻭ ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ ﺭﺍ ﻧﻴﺰ ﺩﺭ ﻳﮏ charﺫﺧﻴﺮﻩ ﻣﻲﮐﻨﻨﺪ .ﺑﻪ ﻫﻤﻴﻦ ﺧﺎﻃﺮ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺭﺍ ﺑﻪ
ﻋﻨﻮﺍﻥ »ﺗﻮﺍﺑﻊ ﮐﺎﺭﺍﮐﺘﺮﻱ« ﺩﺭ ﻧﻈﺮ ﻣﻲﮔﻴﺮﻳﻢ.
8‐7ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺭﺷﺘﻪﻫﺎ
ﺑﻪ ﺧﺎﻃﺮ ﺩﺍﺭﻳﺪ ﮐﻪ ﮔﻔﺘﻴﻢ ﻳﮏ ﺁﺭﺍﻱۀ ﺩﻭﺑﻌﺪﻱ ﺩﺭ ﺣﻘﻴﻘﺖ ﺁﺭﺍﻳﻪﺍﻱ ﻳﮏ ﺑﻌﺪﻱ ﺍﺳﺖ
ﮐﻪ ﻫﺮ ﮐﺪﺍﻡ ﺍﺯ ﺍﻋﻀﺎﻱ ﺁﻥ ﻳﮏ ﺁﺭﺍﻱۀ ﻳﮏ ﺑﻌﺪﻱ ﺩﻳﮕﺮ ﺍﺳﺖ .ﻣﺜﻼ ﺩﺭ ﺁﺭﺍﻱۀ ﺩﻭ ﺑﻌﺪﻱ ﮐﻪ
;]char name[5][20 ﺑﻪ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﺍﻋﻼﻥ ﺷﺪﻩ ﺑﺎﺷﺪ:
ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺩﺭ ﺍﺻﻞ ﭘﻨﺞ ﻋﻀﻮ ﺩﺍﺭﺩ ﮐﻪ ﻫﺮ ﻋﻀﻮ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻴﺴﺖ ﮐﺎﺭﺍﮐﺘﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺍﮔﺮ
ﺁﺭﺍﻱۀ ﻓﻮﻕ ﺭﺍ ﺑﺎ ﺗﻌﺮﻳﻒ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻣﻘﺎﻳﺴﻪ ﮐﻨﻴﻢ ،ﻧﺘﻴﺠﻪ ﺍﻳﻦ ﻣﻲﺷﻮﺩ ﮐﻪ ﺁﺭﺍﻱۀ
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
0
1
2
3
4
263 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
ﺑﺎﻻ ﻳﮏ ﺁﺭﺍﻱۀ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﻋﻨﺼﺮ ﺁﻥ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﻴﺴﺖ ﺣﺮﻓﻲ
ﺍﺳﺖ .ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﺗﺼﻮﺭ ﮐﻨﻴﻢ.
ﺍﺯ ﻃﺮﻳﻖ ] name[0ﻭ ] name[1ﻭ ] name[2ﻭ ] name[3ﻭ ]name[4
ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﻫﺮ ﻳﮏ ﺍﺯ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺩﺭ ﺁﺭﺍﻱۀ ﺑﺎﻻ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ .ﻳﻌﻨﻲ
ﺁﺭﺍﻱۀ nameﮔﺮﭼﻪ ﺑﻪ ﺻﻮﺭﺕ ﻳﮏ ﺁﺭﺍﻱۀ ﺩﻭﺑﻌﺪﻱ ﺍﻋﻼﻥ ﺷﺪﻩ ﻟﻴﮑﻦ ﺑﻪ ﺻﻮﺭﺕ ﻳﮏ
ﺁﺭﺍﻱۀ ﻳﮏ ﺑﻌﺪﻱ ﺑﺎ ﺁﻥ ﺭﻓﺘﺎﺭ ﻣﻲﺷﻮﺩ .ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺩﻗﺖ ﮐﻨﻴﺪ.
)cin.getline(name[count++],20
ﻭﻗﺘﻲ ﺍﻳﻦ ﺑﺨﺶ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ،ﺗﺎﺑﻊ )( cin.getlineﺧﻂ ﺑﻌﺪﻱ ﺭﺍ ﺍﺯ
ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﮐﺮﺩﻩ ﻭ ﺩﺭﻭﻥ ] name[countﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﻭ ﺳﭙﺲ countﺭﺍ
ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ .ﺍﮔﺮ ﺍﻳﻦ ﻋﻤﻞ ﻣﻮﻓﻘﻴﺖﺁﻣﻴﺰ ﺑﺎﺷﺪ ،ﺗﺎﺑﻊ )( getlineﻣﻘﺪﺍﺭ ﻏﻴﺮ ﺻﻔﺮ ﺭﺍ
ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭ ﺩﺭ ﻧﺘﻴﺠﻪ ﺣﻠﻖۀ whileﺩﻭﺑﺎﺭﻩ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ .ﺍﮔﺮ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ
) (Ctrl+Zﻭﺍﺭﺩ ﺷﻮﺩ ،ﻭﻗﺘﻲ ﺗﺎﺑﻊ )( getlineﺑﺎ ﺁﻥ ﺑﺮﺧﻮﺭﺩ ﮐﻨﺪ ،ﻣﺘﻮﻗﻒ ﺷﺪﻩ ﻭ
ﻣﻘﺪﺍﺭ ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭ ﺩﺭ ﺍﺛﺮ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ،ﺣﻠﻖۀ whileﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ .ﺑﺪﻥۀ
ﺣﻠﻖۀ whileﺧﺎﻟﻲ ﺍﺳﺖ ﻭ ﻫﻴﭻ ﺩﺳﺘﻮﺭﻱ ﻧﺪﺍﺭﺩ .ﻳﮏ ﺳﻤﻴﮑﻮﻟﻦ ﺗﻨﻬﺎ ﺩﺭ ﺑﺪﻥۀ while
ﺍﻳﻦ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩ ﮐﺮﺩﻥ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺩﺭ ﻳﮏ ﺁﺭﺍﻳﻪ ،ﺭﺍﻩ ﺑﻬﺘﺮﻱ ﻫﻢ ﻫﺴﺖ:
»ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ« .ﺩﺳﺘﻮﺭ
;]char* name[4
ﻳﮏ ﺁﺭﺍﻳﻪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﭼﻬﺎﺭ ﻋﻀﻮ ﺍﺯ ﻧﻮﻉ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ charﺩﺍﺭﺩ .ﻳﻌﻨﻲ
ﻫﺮ ] name[iﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﻣﺰﻳﺖ ﺁﺭﺍﻱۀ ﻓﻮﻕ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ
ﺍﺯ ﺍﺑﺘﺪﺍ ﻫﻴﭻ ﺣﺎﻓﻈﻪﺍﻱ ﺑﺮﺍﻱ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺗﺨﺼﻴﺺ ﻧﻤﻲﻳﺎﺑﺪ ﻭﻟﺬﺍ ﻃﻮﻝ ﺭﺷﺘﻪﻫﺎﻱ
ﮐﺎﺭﺍﮐﺘﺮﻱ ﻣﻲﺗﻮﺍﻧﺪ ﻣﺘﻔﺎﻭﺕ ﺑﺎﺷﺪ .ﺩﺭ ﻋﻮﺽ ﻣﺠﺒﻮﺭﻳﻢ ﮐﻪ ﻫﺮ ﺭﺷﺘﻪ ﺭﺍ ﺩﺭ ﻳﮏ ﻗﺴﻤﺖ ﺍﺯ
ﺣﺎﻓﻈﻪ ﺫﺧﻴﺮﻩ ﮐﻨﻴﻢ ﻭ ﺳﭙﺲ ﻧﺸﺎﻧﻲ ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ ﺁﻥ ﻗﺴﻤﺖ ﺭﺍ ﺩﺭ ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﺩﻫﻴﻢ .ﺍﻳﻦ
ﺭﻭﺵ ﺩﺭ ﻣﺜﺎﻝ 8‐10ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ .ﺭﻭﺵ ﻣﺬﮐﻮﺭ ﺑﺴﻴﺎﺭ ﻣﻮﺛﺮﺗﺮ ﺍﺳﺖ ﺯﻳﺮﺍ ﺑﺮﺍﻱ
ﻧﮕﻬﺪﺍﺭﻱ ﻫﺮ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻓﻘﻂ ﺑﻪ ﺍﻧﺪﺍﺯۀ ﻫﻤﺎﻥ ﺭﺷﺘﻪ ﺣﺎﻓﻈﻪ ﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﺪ ﻧﻪ
ﺑﻴﺸﺘﺮ .ﻫﺰﻳﻨﻪﺍﻱ ﮐﻪ ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭﺍﻳﻲ ﺑﺎﻳﺪ ﺑﭙﺮﺩﺍﺯﻳﻢ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺭﻭﺍﻝ ﻭﺭﻭﺩﻱ ﮐﻤﻲ
ﭘﻴﭽﻴﺪﻩ ﻣﻲﺷﻮﺩ .ﺩﺭ ﺍﻳﻦ ﺭﻭﺵ ﺑﻪ ﻳﮏ ﻧﮕﻬﺒﺎﻥ ﻧﻴﺎﺯ ﺩﺍﺭﻳﻢ ﺗﺎ ﻭﻗﺘﻲ ﻭﺭﻭﺩﻱ ﻫﺮ ﺭﺷﺘﻪ ﭘﺎﻳﺎﻥ
ﻳﺎﻓﺖ ،ﺑﻪ ﺁﺭﺍﻳﻪ ﻋﻼﻣﺖ ﺑﺪﻫﺪ.
ﻣﻲﺷﻮﺩ ﻭ ﻫﺮ ﺍﺳﻢ ﺑﺎ ﮐﺎﺭﺍﮐﺘﺮ ' '\nﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ .ﺍﻳﻦ ﺍﺳﺎﻣﻲ ﺩﺭ ﺁﺭﺍﻱۀ nameﺫﺧﻴﺮﻩ
ﻣﻲﺷﻮﻧﺪ .ﺳﭙﺲ ﻧﺎﻡﻫﺎﻱ ﺫﺧﻴﺮﻩ ﺷﺪﻩ ﺩﺭ ﺁﺭﺍﻱۀ nameﭼﺎﭖ ﻣﻲﺷﻮﻧﺪ:
)(int main
;]{ char buffer[80
;)'cin.getline(buffer,80,'$
;]char* name[4
;name[0] = buffer
;int count = 0
)for (char* p=buffer; *p ! '\0'; p++
)'if (*p == '\n
;'{ *p = '\0 ]// end name[count
;name[++count] = p+1 // begin next name
}
;"cout << "The names are:\n
)for (int i=0; i<count; i++
;cout << "\t" << i << . [" << name[i] << "]" << endl
}
ﻳﮏ ﻓﻀﺎﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﺑﻪ ﻧﺎﻡ bufferﺑﺎ ﻇﺮﻓﻴﺖ 80ﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﺷﺪﻩ
ﺍﺳﺖ .ﮐﻞ ﻭﺭﻭﺩﻱ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ )( getlineﺑﻪ ﺩﺭﻭﻥ ﺍﻳﻦ ﻓﻀﺎ ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ
ﻃﻮﺭﻱ ﮐﻪ ﻳﺎ ﺗﻌﺪﺍﺩ ﮐﻞ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺑﻪ 80ﺑﺮﺳﺪ ﻭ ﻳﺎ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ' '$ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ ﮐﻪ ﺩﺭ
ﺍﻳﻦ ﺻﻮﺭﺕ ﻋﻤﻞ ﺩﺭﻳﺎﻓﺖ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ .ﺳﭙﺲ ﺁﺭﺍﻱۀ nameﺗﻌﺮﻳﻒ ﺷﺪﻩ ﮐﻪ
ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺩﺍﺭﺍﻱ ﭼﻬﺎﺭ ﻋﻨﺼﺮ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ charﺍﺳﺖ .ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺣﻠﻖۀ ،forﺁﺭﺍﻱۀ
bufferﭘﻮﻳﺶ ﻣﻲﺷﻮﺩ .ﺍﺷﺎﺭﻩﮔﺮ pﺍﻳﻦ ﭘﻮﻳﺶ ﺭﺍ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ .ﻫﺮ ﺩﻓﻌﻪ ﮐﻪ pﺑﻪ
ﮐﺎﺭﺍﮐﺘﺮ ' '\nﺑﺮﺳﺪ ،ﺑﻪ ﺟﺎﻱ ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ ' '\0ﺭﺍ ﻣﻲﮔﺬﺍﺭﺩ ،ﺳﭙﺲ ﺷﻤﺎﺭﻧﺪۀ count
ﺭﺍ ﺍﻓﺰﺍﻳﺶ ﺩﺍﺩﻩ ﻭ ﺁﺩﺭﺱ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻌﺪﻱ ﻳﻌﻨﻲ p+1ﺭﺍ ﺩﺭ ] name[countﺫﺧﻴﺮﻩ
ﻣﻲﻧﻤﺎﻳﺪ .ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ] name[countﺑﻪ ﻧﺎﻡ ﺑﻌﺪﻱ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ .ﺩﻭﻣﻴﻦ ﺣﻠﻖۀ for
ﻭﻇﻴﻒۀ ﭼﺎﭖ ﺁﺭﺍﻱۀ ﺭﺷﺘﻪﺍﻱ nameﺭﺍ ﺩﺍﺭﺩ.
ﻫﻨﮕﺎﻡ ﻭﺍﺭﺩ ﮐﺮﺩﻥ ﺍﺳﺎﻣﻲ ،ﮐﺎﺭﺑﺮ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﻫﺮ ﺗﻌﺪﺍﺩ ﮐﻪ ﺧﻮﺍﺳﺖ ﮐﻠﻴﺪ Enter
ﺭﺍ ﻓﺸﺎﺭ ﺩﻫﺪ .ﭘﺲ ﺍﺯ ﻫﺮ ﺑﺎﺭ ﻓﺸﺮﺩﻥ ﺍﻳﻦ ﮐﻠﻴﺪ ،ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺭﻭﻱ ﺁﻥ ﺧﻂ ﺑﻪ ﻫﻤﺮﺍﻩ
ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ' '\nﺑﻪ cinﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﻫﻤﻴﻦ ﮐﻪ ﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺑﻪ 80ﺭﺳﻴﺪ ﻳﺎ
ﮐﺎﺭﺍﮐﺘﺮ ﻧﮕﻬﺒﺎﻥ ' '$ﺗﺸﺨﻴﺺ ﺩﺍﺩﻩ ﺷﺪ،
0 Mostafa ChamranØ
1 Mehdi zeinoddinØ
2 Ebrahim hemmatØ
3 Ø
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 266
ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﻗﻄﻊ ﻣﻲﺷﻮﺩ ﻭ ﺍﺩﺍﻡۀ ﺑﺮﻧﺎﻣﻪ ﺩﻧﺒﺎﻝ ﻣﻲﺷﻮﺩ .ﺗﺼﻮﻳﺮ ﻣﻘﺎﺑﻞ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ
ﺍﮔﺮ ﺯﻧﺠﻴﺮۀ
""Mostafa chamran\nMehdi Zeinoddin\n Ebrahim Hemmat\n
ﺑﻌﺪﻱ ﺳﺎﺩﻩﺗﺮﻳﻦ ﺁﻥﻫﺎ ﻳﻌﻨﻲ ﺗﺎﺑﻊ ﻃﻮﻝ ﺭﺷﺘﻪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ،ﻃﻮﻝ ﻳﮏ ﺭﺷﺖۀ
ﮐﺎﺭﺍﮐﺘﺮﻱ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺑﻪ ﺁﻥ )ﻳﻌﻨﻲ ﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺁﻥ ﺭﺷﺘﻪ( ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
ﺩﺭ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺳﻪ ﺗﺎﺑﻊ ﺩﻳﮕﺮ ﺭﺍ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﻴﻢ .ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺑﺮﺍﻱ »ﻣﮑﺎﻥﻳﺎﺑﻲ« ﻳﮏ
ﮐﺎﺭﺍﮐﺘﺮ ﻳﺎ ﺯﻳﺮﺭﺷﺘﻪ ﺩﺭ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻣﻔﺮﻭﺽ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ.
ﻭﻗﺘﻲ )' ' strchr(s,ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ،ﺩﺭ ﺭﺷﺖۀ sﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ' '
ﺟﺴﺘﺠﻮ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﺍﻭﻟﻴﻦ ﺧﺎﻧﻪﺍﻱ ﮐﻪ ﻳﺎﻓﺖ ﺷﺪ ،ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺁﻥ ﺧﺎﻧﻪ ﺑﺎﺯﮔﺸﺖ
ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ .ﻋﺒﺎﺭﺕ s-pﺍﻳﻨﺪﮐﺲ ﺍﻭﻟﻴﻦ ﮐﺎﺭﺍﮐﺘﺮ ﻳﺎﻓﺘﻪ ﺷﺪﻩ ﺩﺭ ﺭﺷﺖۀ sﺭﺍ ﻣﺤﺎﺳﺒﻪ
ﻣﻲﮐﻨﺪ )ﺑﻪ ﺧﺎﻃﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﺁﺭﺍﻳﻪﻫﺎ ﺑﺎ ﺍﻳﻨﺪﮐﺲ 0ﺷﺮﻭﻉ ﻣﻲﺷﻮﻧﺪ( .ﺍﻭﻟﻴﻦ ﻓﻀﺎﻱ
ﺧﺎﻟﻲ ﺩﺭ ﺭﺷﺖۀ sﺩﺭ ﺍﻳﻨﺪﮐﺲ 3ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ .ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﻭﻗﺘﻲ
)' strchr(s,'eﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ،ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺍﻭﻟﻴﻦ ﮐﺎﺭﺍﮐﺘﺮ ' 'eﺩﺭ ﺭﺷﺖۀ s
ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ .ﺳﭙﺲ ﻋﺒﺎﺭﺕ s-pﺍﻳﻨﺪﮐﺲ ﺁﻥ ﺧﺎﻧﻪ ﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻣﻲﻧﻤﺎﻳﺪ .ﺍﻭﻟﻴﻦ
' 'eﺩﺭ ﺍﻳﻨﺪﮐﺲ 2ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ.
ﻓﺮﺍﺧﻮﺍﻧﻲ )' strrchr(s, 'eﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺁﺧﺮﻳﻦ ﻣﺤﻞ ﻭﻗﻮﻉ ﮐﺎﺭﺍﮐﺘﺮ
' 'eﺩﺭ ﺭﺷﺖۀ sﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ .ﺁﺧﺮﻳﻦ ﮐﺎﺭﺍﮐﺘﺮ ' 'eﺩﺭ ﺭﺷﺖۀ sﺩﺭ ﺍﻳﻨﺪﮐﺲ 26
ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺍﺳﺖ.
ﻓﺮﺍﺧﻮﺍﻧﻲ )" strstr(s, "isﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺯﻳﺮﺭﺷﺖۀ " "isﺩﺭ
ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ sﺟﺴﺘﺠﻮ ﺷﻮﺩ ﻭ ﺩﺭ ﺍﻭﻟﻴﻦ ﻣﮑﺎﻧﻲ ﮐﻪ ﻳﺎﻓﺖ ﺷﺪ ،ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺁﻥ
269 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
ﻣﮑﺎﻥ ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ .ﺯﻳﺮ ﺭﺷﺖۀ ﻣﺬﮐﻮﺭ ﺩﺭ ] s[22ﻭﺍﻗﻊ ﺷﺪﻩ .ﻓﺮﺍﺧﻮﺍﻧﻲ
)" strstr(s, "isiﺍﺷﺎﺭﻩﮔﺮ NULLﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﺯﻳﺮﺍ ﻋﺒﺎﺭﺕ " "isiﺩﺭ
ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ sﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ.
ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ) = ( ﺩﺭﻭﻥ
ﻳﮑﺪﻳﮕﺮ ﮐﭙﻲ ﮐﻨﻴﻢ )ﭼﺮﺍ؟( ﺍﻣﺎ ﺩﻭ ﺗﺎﺑﻊ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﮐﻪ ﻋﻤﻞ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺭﺍ ﺷﺒﻴﻪﺳﺎﺯﻱ
ﻣﻲﻧﻤﺎﻳﻨﺪ .ﺗﺎﺑﻊ ) strcpy(s1, s2ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ s2ﺩﺭﻭﻥ
ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ s1ﮐﭙﻲ ﺷﻮﺩ .ﻫﻤﭽﻨﻴﻦ ﺗﺎﺑﻊ ) strncpy(s1, s2, nﺑﺎﻋﺚ
ﻣﻲﺷﻮﺩ ﮐﻪ nﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ﺍﺯ ﺭﺷﺖۀ s2ﺭﻭﻱ nﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ﺭﺷﺖۀ s1ﮐﭙﻲ ﺷﻮﺩ .ﻫﺮ
ﺩﻭ ﺗﺎﺑﻊ ﻓﻮﻕ s1ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﻨﺪ ﻭ s2ﺭﺍ ﺑﺪﻭﻥ ﺗﻐﻴﻴﺮ ﻣﻲﮔﺬﺍﺭﻧﺪ .ﻣﺜﺎﻝﻫﺎﻱ ﺑﻌﺪﻱ ﻃﺮﻳﻖۀ
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺩﻭ ﺗﺎﺑﻊ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ.
ﻭﻗﺘﻲ s2ﺑﻪ ﺩﺍﺧﻞ s1ﮐﭙﻲ ﺷﺪ ،ﺍﻳﻦ ﺩﻭ ﺩﻳﮕﺮ ﻓﺮﻗﻲ ﺑﺎ ﻫﻢ ﻧﻤﻲﮐﻨﻨﺪ .ﻫﺮ ﺩﻭ ﺷﺎﻣﻞ ﺳﻪ
ﮐﺎﺭﺍﮐﺘﺮ XYZﻫﺴﺘﻨﺪ .ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ ) strcpy(s1, s2ﭼﻪ
ﺗﺎﺛﻴﺮﻱ ﺩﺍﺭﺩ .ﭼﻮﻥ s2ﺩﺍﺭﺍﻱ ﻃﻮﻝ 3ﺍﺳﺖ ،ﻓﺮﺍﺧﻮﺍﻧﻲ ) strcpy(s1, s2ﺑﺎﻋﺚ
ﻣﻲﺷﻮﺩ ﮐﻪ ﭼﻬﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ ) s2ﮐﺎﺭﺍﮐﺘﺮ NULﻫﻢ ﺟﺰﺋﻲ ﺍﺯ s2ﺍﺳﺖ( ﺭﻭﻱ ﭼﻬﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ
ﺍﻭﻝ s1ﺭﻭﻧﻮﻳﺴﻲ ﺷﻮﺩ .ﺣﺎﻻ s1ﻭ s2ﺩﺍﺭﺍﻱ ﻃﻮﻝ 3ﻫﺴﺘﻨﺪ .ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺍﺿﺎﻓﻲ s1
ﺑﺪﻭﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺭﻫﺎ ﻣﻲﺷﻮﻧﺪ .ﺩﺭﺳﺖ ﺍﺳﺖ ﮐﻪ s1ﻭ S2ﻫﻢ ﻣﻘﺪﺍﺭ ﻫﺴﺘﻨﺪ ﻭﻟﻲ ﺟﺪﺍ ﺍﺯ ﻫﻢ
ﻣﻲﺑﺎﺷﻨﺪ ﻭ ﺍﮔﺮ ﺩﺭ ﺍﺩﺍﻣﻪ ﻳﮑﻲ ﺍﺯ ﺁﻥ ﺩﻭ ﺗﻐﻴﻴﺮ ﮐﻨﺪ ،ﺗﺎﺛﻴﺮﻱ ﺑﺮ ﺩﻳﮕﺮﻱ ﻧﺨﻮﺍﻫﺪ ﺩﺍﺷﺖ.
After strcat(s1,s2):
s1 = [ABCDEFGXYZ], length = 10
s2 = [XYZ], length = 3
nﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ s1ﺭﺍ ﺑﺎ nﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ s2ﻣﻘﺎﻳﺴﻪ ﻣﻲﮐﻨﺪ ﻭ ﺍﮔﺮ ﺯﻳﺮﺭﺷﺖۀ ﺍﻭﻝ ﺑﻪ ﺗﺮﺗﻴﺐ ﺍﻟﻔﺒﺎﻳﻲ ﺍﺯ
)(strncmp ﺯﻳﺮﺭﺷﺖۀ ﺩﻭﻡ ﺑﺰﺭﮒﺗﺮ ،ﻣﺴﺎﻭﻱ ﻳﺎ ﮐﻮﭼﮏﺗﺮ ﺑﺎﺷﺪ ،ﻣﻘﺪﺍﺭ ﻣﺜﺒﺖ ،ﺻﻔﺮ ﻳﺎ ﻣﻘﺪﺍﺭ ﻣﻨﻔﻲ ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ .ﺍﮔﺮ
) n>=strlen(s2ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ) strncmp(s1, s2, nﺗﺎﺛﻴﺮﻱ ﻣﺸﺎﺑﻪ ﺑﺎ
) strcmp(s1, s2ﺧﻮﺍﻫﺪ ﺩﺍﺷﺖ.
ﺑﻔﺮﺳﺘﻴﻢ ،ﺍﻳﻦ ﻧﺘﺎﻳﺞ ﺩﺭ ﻗﺎﻟﺐ ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﻧﻤﺎﻳﺶ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ .ﻻﺯﻡ ﺍﺳﺖ
ﮐﻪ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺑﻪ ﻧﺤﻮﻱ ﺑﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺗﻔﺴﻴﺮ ﺷﻮﻧﺪ .ﻣﺜﻼ ﻭﻗﺘﻲ ﻗﺼﺪ ﺩﺍﺭﻳﻢ ﻳﮏ ﻋﺪﺩ
ﺻﺤﻴﺢ ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﻴﻢ ،ﭼﻨﺪ ﮐﺎﺭﺍﮐﺘﺮ ﻋﺪﺩﻱ ﺗﺎﻳﭗ ﻣﻲﮐﻨﻴﻢ .ﺣﺎﻻ ﺳﺎﺯ ﻭ ﮐﺎﺭﻱ ﻻﺯﻡ ﺍﺳﺖ ﮐﻪ
ﺍﺯ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﻳﮏ ﻣﻘﺪﺍﺭ ﺻﺤﻴﺢ ﺑﺴﺎﺯﺩ ﻭ ﺑﻪ ﺑﺮﻧﺎﻣﻪ ﺗﺤﻮﻳﻞ ﺩﻫﺪ .ﻫﻤﭽﻨﻴﻦ ﻭﻗﺘﻲ ﻗﺼﺪ
ﺩﺍﺭﻳﻢ ﻳﮏ ﻋﺪﺩ ﺍﻋﺸﺎﺭﻱ ﺭﺍ ﺑﻪ ﺧﺮﻭﺟﻲ ﺑﻔﺮﺳﺘﻴﻢ ،ﺑﺎﻳﺪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺭﺍﻩﮐﺎﺭﻱ ،ﺁﻥ ﻋﺪﺩ
ﺍﻋﺸﺎﺭﻱ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻳﻲ ﺗﺒﺪﻳﻞ ﺷﻮﺩ ﺗﺎ ﺩﺭ ﺧﺮﻭﺟﻲ ﻧﻤﺎﻳﺶ ﻳﺎﺑﺪ .ﺟﺮﻳﺎﻥﻫﺎ 1ﺍﻳﻦ ﻭﻇﺎﻳﻒ
ﺭﺍ ﺩﺭ C++ﺑﺮ ﻋﻬﺪﻩ ﺩﺍﺭﻧﺪ .ﺟﺮﻳﺎﻥﻫﺎ ﺷﺒﻴﻪ ﭘﺎﻻﻳﻪﺍﻱ ﻫﺴﺘﻨﺪ ﮐﻪ ﺩﺍﺩﻩﻫﺎ ﺭﺍ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺗﺒﺪﻳﻞ
ﻣﻲﮐﻨﻨﺪ ﻭ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﺑﻪ ﺩﺍﺩﻩﻫﺎﻳﻲ ﺍﺯ ﻳﮏ ﻧﻮﻉ ﺑﻨﻴﺎﺩﻱ ﺗﺒﺪﻳﻞ ﻣﻲﻧﻤﺎﻳﻨﺪ .ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ،
ﻭﺭﻭﺩﻱﻫﺎ ﻭ ﺧﺮﻭﺟﻲﻫﺎ ﺭﺍ ﻳﮏ ﮐﻼﺱ ﺟﺮﻳﺎﻥ ﺑﻪ ﻧﺎﻡ streamﮐﻨﺘﺮﻝ ﻣﻲﮐﻨﺪ .ﺍﻳﻦ ﮐﻼﺱ
ﺧﻮﺩ ﺑﻪ ﺯﻳﺮﮐﻼﺱﻫﺎﻳﻲ ﺗﻘﺴﻴﻢ ﻣﻲﺷﻮﺩ :ﺷﻲﺀ istreamﺟﺮﻳﺎﻧﻲ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ
ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺍﺭﺩ ﺷﺪﻩ ﺍﺯ ﺻﻔﺤﻪ ﮐﻠﻴﺪ ،ﻓﺮﺍﻫﻢ ﻣﻲﮐﻨﺪ .ﺷﻲﺀ ostream
ﺟﺮﻳﺎﻧﻲ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ ﺣﺎﺻﻞ ﺭﺍ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺧﺮﻭﺟﻲ ﻗﺎﺑﻞ ﻧﻤﺎﻳﺶ ﺭﻭﻱ ﺻﻔﺢۀ
ﻧﻤﺎﻳﺶﮔﺮ ﺗﺒﺪﻳﻞ ﻣﻲﻧﻤﺎﻳﺪ .ﺷﻲﺀ ifstreamﺟﺮﻳﺎﻧﻲ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺍﺯ
ﺩﺍﺩﻩﻫﺎﻱ ﺩﺍﺧﻞ ﻳﮏ ﻓﺎﻳﻞ ،ﻓﺮﺍﻫﻢ ﻣﻲﮐﻨﺪ .ﺷﻲﺀ ofstreamﺟﺮﻳﺎﻧﻲ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ
ﺣﺎﺻﻞ ﺭﺍ ﺩﺭﻭﻥ ﻳﮏ ﻓﺎﻳﻞ ﺫﺧﻴﺮﻩ ﻣﻲﻧﻤﺎﻳﺪ .ﺍﻳﻦ ﺟﺮﻳﺎﻥﻫﺎ ﻭ ﻃﺮﻳﻖۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥﻫﺎ ﺭﺍ ﺩﺭ
ﺍﺩﺍﻣﻪ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ.
ﮐﻼﺱ istreamﻧﺤﻮۀ ﺭﻓﺘﺎﺭ ﺑﺎ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺭﻭﺩﻱ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﻧﻤﺎﻳﺪ.
ﻣﻬﻢﺗﺮﻳﻦ ﭼﻴﺰﻱ ﮐﻪ ﺑﺎﻳﺪ ﺗﻌﺮﻳﻒ ﺷﻮﺩ ﻭ ﺍﺗﻔﺎﻗﺎ ﺑﻴﺸﺘﺮﻳﻦ ﺍﺳﺘﻔﺎﺩﻩ ﺭﺍ ﻫﻢ ﺩﺍﺭﺩ ،ﻧﺤﻮۀ ﺭﻓﺘﺎﺭ
»ﻋﻤﻠﮕﺮ ﺑﺮﻭﻥ ﮐﺸﻲ >> « ﺍﺳﺖ )ﺑﻪ ﺁﻥ ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ ﻧﻴﺰ ﻣﻲﮔﻮﻳﻴﻢ( .ﻗﺒﻼ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺍﺯ
ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ .ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺩﻭ ﻋﻤﻠﻮﻧﺪ ﺩﺍﺭﺩ :ﺷﻲﺀ istreamﮐﻪ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ
ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺍﺯ ﮐﺠﺎ ﺑﺎﻳﺪ ﺑﻴﺮﻭﻥ ﮐﺸﻴﺪﻩ ﺷﻮﻧﺪ ،ﻭ ﺷﻴﺌﻲ ﮐﻪ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ ﻣﻘﺪﺍﺭ
ﺑﺮﻭﻥﮐﺸﻲﺷﺪﻩ ﺑﺎﻳﺪ ﺍﺯ ﭼﻪ ﻧﻮﻋﻲ ﺑﺎﺷﺪ ﻭ ﮐﺠﺎ ﺑﺎﻳﺪ ﺫﺧﻴﺮﻩ ﺷﻮﺩ .ﺑﻪ ﺍﻳﻦ ﭘﺮﺩﺍﺯﺵ ﮐﻪ ﺍﺯ
ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺧﺎﻡ ﻭﺭﻭﺩﻱ ﻣﻘﺎﺩﻳﺮﻱ ﺑﺎ ﻧﻮﻉ ﻣﺸﺨﺺ ﺗﻮﻟﻴﺪ ﻣﻲﮐﻨﺪ ،ﻗﺎﻟﺐﺑﻨﺪﻱ 2ﻣﻲﮔﻮﻳﻨﺪ.
;int n
;cin >> n
277 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
ﻭﺭﻭﺩﻱ ﺑﺎﻻ ﺩﺭ ﺣﻘﻴﻘﺖ ﺷﺎﻣﻞ ﻫﻔﺖ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺳﺖ ' ' :ﻭ ' ' ﻭ ' ' ﻭ ' ' ﻭ ''4
ﻭ ' '6ﻭ ' '\nﻳﻌﻨﻲ ﭼﻬﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﻭ ﺳﭙﺲ ' '4ﻭ ﺑﻌﺪ ﺍﺯ ﺁﻥ ' '6ﻭ ﺩﺭ
ﻧﻬﺎﻳﺖ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ' '\nﺁﻣﺪﻩ ﺍﺳﺖ .ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺩﺭﻭﻥ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﻗﺮﺍﺭ
ﻣﻲﮔﻴﺮﻧﺪ .ﺷﻲﺀ ﺟﺮﻳﺎﻥ cinﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﻳﮑﻲ ﻳﮑﻲ ﭘﻮﻳﺶ ﻣﻲﮐﻨﺪ .ﺍﮔﺮ ﺍﻭﻟﻴﻦ ﮐﺎﺭﺍﮐﺘﺮﻱ
ﮐﻪ ﺑﻪ ﺁﻥ ﻭﺍﺭﺩ ﻣﻲﺷﻮﺩ ،ﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﻳﺎ ﻫﺮ ﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺩﻳﮕﺮ )ﻣﺜﻞ tab
ﻳﺎ ﺧﻂ ﺟﺪﻳﺪ( ﺑﺎﺷﺪ ،ﺁﻥ ﺭﺍ ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻭ ﺍﺯ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺣﺬﻑ ﻣﻲﮐﻨﺪ .ﺍﻳﻦ ﮐﺎﺭ
ﻫﻤﭽﻨﺎﻥ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﺑﻪ ﻳﮏ ﮐﺎﺭﮐﺘﺮ ﻏﻴﺮﻓﺎﺻﻠﻪﺍﻱ ﺑﺮﺧﻮﺭﺩ ﮐﻨﺪ .ﭼﻮﻥ ﺩﻭﻣﻴﻦ
ﻋﻤﻠﻮﻧﺪ ﺩﺭ ﻋﻤﻠﮕﺮ ﺑﺮﻭﻥ ﮐﺸﻲ cin >> nﺍﺯ ﻧﻮﻉ intﺍﺳﺖ ،ﭘﺲ ﺷﻲﺀ cinﺑﻪ
ﺩﻧﺒﺎﻝ ﺍﻋﺪﺍﺩﻱ ﻣﻲﮔﺮﺩﺩ ﺗﺎ ﺑﺘﻮﺍﻧﺪ ﻣﻘﺪﺍﺭﻱ ﺍﺯ ﺍﻳﻦ ﻧﻮﻉ ﺣﺎﺻﻞ ﻧﻤﺎﻳﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﺗﻼﺵ ﻣﻲﮐﻨﺪ
ﮐﻪ ﭘﺲ ﺍﺯ ﺩﻭﺭ ﺍﻧﺪﺍﺧﺘﻦ ﻫﻢۀ ﻓﺎﺻﻠﻪﻫﺎ ،ﻳﮑﻲ ﺍﺯ ﺩﻭﺍﺯﺩﻩ ﮐﺎﺭﺍﮐﺘﺮ ' '+ﻳﺎ ' '-ﻳﺎ ' '0ﻳﺎ
' '1ﻳﺎ ' '2ﻳﺎ ' '3ﻳﺎ ' '4ﻳﺎ ' '5ﻳﺎ ' '6ﻳﺎ ' '7ﻳﺎ ' '8ﻳﺎ ' '9ﺭﺍ ﺑﻴﺎﺑﺪ .ﺍﮔﺮ
ﺑﻪ ﻏﻴﺮ ﺍﺯ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺑﻪ ﻫﺮ ﮐﺪﺍﻡ ﺍﺯ 244ﮐﺎﺭﺍﮐﺘﺮ ﺩﻳﮕﺮ ﺑﺮﺧﻮﺭﺩ ﮐﻨﺪ ،ﺍﺯ ﮐﺎﺭ ﻣﻲﺍﻳﺴﺘﺪ.
ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﮐﺎﺭﺍﮐﺘﺮ ' '4ﭘﻴﺪﺍ ﺷﺪﻩ .ﻟﺬﺍ ﺷﻲﺀ cinﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﺗﻔﮑﻴﮏ ﮐﺮﺩﻩ ﻭ
ﮐﺎﺭﺍﮐﺘﺮ ﺑﻌﺪﻱ ﺭﺍ ﺑﻪ ﺍﻣﻴﺪ ﻳﺎﻓﺘﻦ ﻋﺪﺩ ﺩﻳﮕﺮ ،ﭘﻮﻳﺶ ﻣﻲﮐﻨﺪ .ﺗﺎ ﺯﻣﺎﻧﻲ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺑﻌﺪﻱ
ﻫﻢ ﻋﺪﺩ ﺑﺎﺷﻨﺪ cin ،ﺁﻥﻫﺎ ﺭﺍ ﺗﻔﮑﻴﮏ ﻣﻲﻧﻤﺎﻳﺪ ﻭ ﭘﻮﻳﺶ ﺭﺍ ﺍﺩﺍﻣﻪ ﻣﻲﺩﻫﺪ .ﺑﻪ ﻣﺤﺾ ﺍﻳﻦ
ﮐﻪ ﺑﻪ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻏﻴﺮﻋﺪﺩﻱ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ cin ،ﻣﺘﻮﻗﻒ ﻣﻲﺷﻮﺩ ﻭ ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ
ﻏﻴﺮﻋﺪﺩﻱ ﺭﺍ ﻫﻤﭽﻨﺎﻥ ﺩﺭ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﻧﮕﻪ ﻣﻲﺩﺍﺭﺩ .ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ،ﺷﻲﺀ cinﺷﺶ
ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﺍﺯ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺑﺮﺩﺍﺷﺖ ﻣﻲﮐﻨﺪ :ﭼﻬﺎﺭ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﺭﺍ ﺣﺬﻑ ﻣﻲﮐﻨﺪ ﻭ
ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ' '4ﻭ ' '6ﺭﺍ ﻫﻢ ﺑﺎ ﻫﻢ ﺗﺮﮐﻴﺐ ﻣﻲﮐﻨﺪ ﺗﺎ ﻣﻘﺪﺍﺭ 46ﺑﺪﺳﺖ ﺁﻳﺪ ﻭ ﺳﭙﺲ
ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺭﺍ ﺩﺭ nﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ .ﻭﻗﺘﻲ ﮐﻪ ﺑﺮﺩﺍﺷﺖ ﺑﻪ ﭘﺎﻳﺎﻥ ﺭﺳﻴﺪ ،ﻫﻨﻮﺯ ﮐﺎﺭﺍﮐﺘﺮ ﺧﻂ
ﺟﺪﻳﺪ ﺩﺭ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺑﺎﻗﻲ ﻣﺎﻧﺪﻩ ﺍﺳﺖ .ﻭﻗﺘﻲ ﺩﺳﺘﻮﺭ cinﺑﻌﺪﻱ ﺍﺟﺮﺍ ﺷﻮﺩ ،ﺍﻳﻦ
ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻟﻴﻦ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺍﺳﺖ ﮐﻪ ﺍﺯ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺑﺮﺩﺍﺷﺖ ﻣﻲﺷﻮﺩ ﻭ ﭼﻮﻥ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮ
ﺍﺯ ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺍﺳﺖ ،ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﺷﺪﻩ ﻭ ﺣﺬﻑ ﻣﻲﺷﻮﺩ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 278
ﺍﺯ ﮔﻔﺘﻪﻫﺎﻱ ﺑﺎﻻ ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻥ ﺍﺳﺘﻨﺘﺎﺝ ﮐﺮﺩ ﮐﻪ ﺍﺯ ﻋﻤﻠﮕﺮ ﺑﺮﻭﻥ ﮐﺸﻲ >>
ﻧﻤﻲﺗﻮﺍﻧﻴﻢ ﺑﺮﺍﻱ ﻭﺍﺭﺩ ﮐﺮﺩﻥ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭ ﺑﺎﻳﺪ ﺍﺯ
ﻳﮏ ﺗﺎﺑﻊ ﻭﺭﻭﺩﻱ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﻗﺎﻟﺐﺑﻨﺪﻱ ﻧﻤﻲﮐﻨﺪ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ.
ﻳﮏ ﻋﺒﺎﺭﺕ ﻭﺭﻭﺩﻱ ﻣﺜﻞ ; cin >> xﺑﻪ ﻏﻴﺮ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺑﺮﺍﻱ x
ﻓﺮﺍﻫﻢ ﻣﻲﮐﻨﺪ ،ﺣﺎﺻﻞ ﺩﻳﮕﺮﻱ ﻫﻢ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺩﺍﺩۀ ﻣﻨﻄﻘﻲ ﺑﻪ ﺩﺳﺖ ﻣﻲﺩﻫﺪ .ﺍﻳﻦ
ﺣﺎﺻﻞ ،ﺑﺮﺣﺴﺐ ﺍﻳﻦ ﮐﻪ ﻋﻤﻞ ﺑﺮﻭﻥﮐﺸﻲ ﻣﻮﻓﻘﻴﺖﺁﻣﻴﺰ ﺑﻮﺩﻩ ﻳﺎ ﺧﻴﺮ ،ﻣﻘﺪﺍﺭ trueﻳﺎ
falseﺩﺍﺭﺩ .ﺍﺯ ﺍﻳﻦ ﺣﺎﺻﻞ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﺷﺮﻁ ﻣﻨﻄﻘﻲ ﺩﺭ ﺩﺳﺘﻮﺭﺍﺕ ﺩﻳﮕﺮ
ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ .ﻣﺜﻼ ﻣﻲﺗﻮﺍﻥ ﺣﻠﻘﻪﻫﺎ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﮐﻨﺘﺮﻝ ﮐﺮﺩ.
ﺗﺎ ﺯﻣﺎﻧﻲ ﮐﻪ ﺍﻋﺪﺍﺩ ﻭﺭﻭﺩﻱ ﻓﻘﻂ ﺑﻪ ﻭﺳﻴﻞۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻓﻀﺎﻱ ﺳﻔﻴﺪ )ﻣﺜﻞ tabﻳﺎ ﻓﺎﺻﻞۀ
ﺧﺎﻟﻲ ﻳﺎ ﮐﺎﺭﺍﮐﺘﺮ ﺧﻂ ﺟﺪﻳﺪ( ﺍﺯ ﻫﻢ ﺟﺪﺍ ﺷﺪﻩ ﺑﺎﺷﻨﺪ ،ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ .ﻫﻤﻴﻦ ﮐﻪ ﺑﻪ
ﺍﻭﻟﻴﻦ ﮐﺎﺭﺍﮐﺘﺮ ﻏﻴﺮﻓﺎﺻﻠﻪﺍﻱ ﻭ ﻏﻴﺮﻋﺪﺩﻱ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ )ﮐﻪ ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﮐﺎﺭﺍﮐﺘﺮ ﮐﺎﻣﺎ '',
ﺍﺳﺖ( ،ﻋﻤﻠﮕﺮ ﺑﺮﻭﻥﮐﺸﻲ ﺍﺯ ﮐﺎﺭ ﻣﻲﺍﻳﺴﺘﺪ ﻭ ﺑﻪ ﻫﻤﻴﻦ ﻭﺍﺳﻄﻪ ،ﺣﻠﻘﻪ ﻧﻴﺰ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ.
ﻧﺎﺩﻳﺪﻩ ﻧﻤﻲﮔﻴﺮﻧﺪ .ﺭﺍﻳﺞﺗﺮﻳﻦ ﺁﻥﻫﺎ ،ﺗﺎﺑﻊ )( cin.getﺑﺮﺍﻱ ﺩﺭﻳﺎﻓﺖ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺗﮑﻲ ﻭ
ﺗﺎﺑﻊ )( cin.getlineﺑﺮﺍﻱ ﺩﺭﻳﺎﻓﺖ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺍﺳﺖ.
;cout << '\t' << i+1 << ". " << martyr[i] << endl
}
ﺗﺎﺑﻊ )( eraseﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺍﺭﺩ ﮐﻪ ﭘﺎﺭﺍﻣﺘﺮ ﺍﻭﻝ ،ﻧﻘﻄﻪ ﺷﺮﻭﻉ ﺣﺬﻑ ﺭﺍ ﻧﺸﺎﻥ
ﻣﻲﺩﻫﺪ ﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺩﻭﻡ ،ﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻳﻲ ﮐﻪ ﺑﺎﻳﺪ ﺣﺬﻑ ﺷﻮﻧﺪ .ﺗﺎﺑﻊ )( replaceﺳﻪ
ﭘﺎﺭﺍﻣﺘﺮ ﺩﺍﺭﺩ :ﭘﺎﺭﺍﻣﺘﺮﺍﻭﻝ ،ﻧﻘﻄﻪ ﺷﺮﻭﻉ ﺭﻭﻧﻮﻳﺴﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ،ﭘﺎﺭﺍﻣﺘﺮ ﺩﻭﻡ ﺗﻌﺪﺍﺩ
ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻳﻲ ﮐﻪ ﺑﺎﻳﺪ ﺣﺬﻑ ﺷﻮﻧﺪ ﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺳﻮﻡ ﺯﻳﺮﺭﺷﺘﻪ ﺍﻱ ﺍﺳﺖ ﮐﻪ ﺑﺎﻳﺪ ﺑﻪ ﺟﺎﻱ
ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺣﺬﻑ ﺷﺪﻩ ﻗﺮﺍﺭ ﺑﮕﻴﺮﺩ.
ﺗﺎﺑﻊ )( findﺍﻳﻨﺪﮐﺲ ﺍﻭﻟﻴﻦ ﻭﻗﻮﻉ ﻳﮏ ﺯﻳﺮﺭﺷﺘﻪ ﻣﻔﺮﻭﺽ ﺭﺍ ﺩﺭ stringﻓﻌﻠﻲ
ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ:
;"string s7 = "The SOFTWARE MOVEMENT bases
;cout << s7.find("EM") << endl // prints 17
;cout << s7.find("EO") << endl
// prints 27, the length of the string
ﺍﮔﺮ ﺗﺎﺑﻊ )( findﺯﻳﺮﺭﺷﺖۀ ﻣﻮﺭﺩ ﻧﻈﺮ ﺭﺍ ﭘﻴﺪﺍ ﻧﮑﻨﺪ ،ﻃﻮﻝ ﺭﺷﺖۀ ﺗﺤﺖ ﺟﺴﺘﺠﻮ ﺭﺍ
ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻧﻮﻉ stringﺑﺴﻴﺎﺭ ﺁﺳﺎﻥ ﺍﺳﺖ .ﺗﻮﺍﺑﻊ ﮐﻤﮑﻲ ﮐﻪ ﺩﺭ ﺑﺎﻻ ﺑﻪ
ﺍﺧﺘﺼﺎﺭ ﻣﻌﺮﻓﻲ ﺷﺪﻧﺪ ﮐﺎﺭﺑﺮﺩ stringﻫﺎ ﺭﺍ ﺳﻬﻞﺗﺮ ﻣﻲﻧﻤﺎﻳﻨﺪ .ﻧﮑﺖۀ ﻗﺎﺑﻞ ﺗﻮﺟﻪ ،ﻧﺤﻮۀ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺍﺳﺖ ،ﺩﺭ ﻫﻢۀ ﺍﻳﻦ ﻓﺮﺍﺧﻮﺍﻧﻲﻫﺎ )ﺑﻪ ﻏﻴﺮ ﺍﺯ ﺗﺎﺑﻊ )( (getlineﺍﺑﺘﺪﺍ
ﻧﺎﻡ stringﻣﺮﺑﻮﻃﻪ ﺁﻣﺪﻩ ﻭ ﺳﭙﺲ ﻳﮏ ﻧﻘﻄﻪ .ﻭ ﺑﻌﺪ ﺍﺯ ﺁﻥ ﺗﺎﺑﻊ ﻣﻮﺭﺩ ﻧﻈﺮ ﺫﮐﺮ ﺷﺪﻩ
ﺍﺳﺖ .ﻋﻠﺖ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻧﻮﻉ Stringﺍﺯ ﺭﻭﻱ ﮐﻼﺱ stringﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 284
ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﺑﺎﻳﺪ ﺍﺯ ﻗﻮﺍﻧﻴﻦ ﮐﻼﺱﻫﺎ ﭘﻴﺮﻭﻱ ﮐﻨﻴﻢ .ﻣﻮﺿﻮﻉ ﮐﻼﺱﻫﺎ ﺭﺍ ﺩﺭ ﻓﺼﻞﻫﺎﻱ ﺁﺗﻲ
ﺑﻪ ﺩﻗﺖ ﺑﺮﺭﺳﻲ ﻣﻲﻧﻤﺎﻳﻴﻢ.
ﺣﻠﻖۀ whileﺑﻪ ﻭﺳﻴﻞۀ ﻭﺭﻭﺩﻱ ﻛﻨﺘﺮﻝ ﻣﻲﺷﻮﺩ ،ﻭﻗﺘﻲ ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ ﺷﻨﺎﺳﺎﻳﻲ ﺷﻮﺩ ،ﭘﺎﻳﺎﻥ
ﻣﻲﭘﺬﻳﺮﺩ .ﺩﺭ ﺍﻳﻦ ﺣﻠﻘﻪ ﻫﺮ ﺩﻓﻌﻪ ﻳﻚ ﻛﻠﻤﻪ ﺧﻮﺍﻧﺪﻩ ﻣﻴﺸﻮﺩ .ﺍﮔﺮ ﺣﺮﻑ Eﭘﻴﺪﺍ ﺷﻮﺩ ،ﻳﮏ
ﻭﻳﺮﮔﻮﻝ ' ',ﺑﻌﺪ ﺍﺯ ﺁﻥ ﺩﺭﺝ ﻣﻲﺷﻮﺩ.
8‐13ﻓﺎﻳﻞﻫﺎ
ﻳﮑﻲ ﺍﺯ ﻣﺰﻳﺖﻫﺎﻱ ﺭﺍﻳﺎﻧﻪ ،ﻗﺪﺭﺕ ﻧﮕﻬﺪﺍﺭﻱ ﺍﻃﻼﻋﺎﺕ ﺣﺠﻴﻢ ﺍﺳﺖ .ﻓﺎﻳﻞﻫﺎ 1ﺍﻳﻦ
ﻗﺪﺭﺕ ﺭﺍ ﺑﻪ ﺭﺍﻳﺎﻧﻪ ﻣﻲﺩﻫﻨﺪ .ﺍﮔﺮ ﭼﻴﺰﻱ ﺑﻪ ﻧﺎﻡ ﻓﺎﻳﻞ ﻭﺟﻮﺩ ﻧﻤﻲﺩﺍﺷﺖ ،ﺷﺎﻳﺪ ﺭﺍﻳﺎﻧﻪﻫﺎ ﺑﻪ
ﺷﮑﻞ ﺍﻣﺮﻭﺯﻱ ﺗﻮﺳﻌﻪ ﻭ ﮐﺎﺭﺑﺮﺩ ﭘﻴﺪﺍ ﻧﻤﻲﮐﺮﺩﻧﺪ .ﭼﻮﻥ ﺍﻏﻠﺐ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺍﻣﺮﻭﺯﻱ ﺑﺎ ﻓﺎﻳﻞﻫﺎ
ﺳﺮ ﻭ ﮐﺎﺭ ﺩﺍﺭﻧﺪ ،ﻳﮏ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﻻﺯﻡ ﺍﺳﺖ ﮐﻪ ﺑﺎ ﻓﺎﻳﻞ ﺁﺷﻨﺎ ﺑﺎﺷﺪ ﻭ ﺑﺘﻮﺍﻧﺪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ
ﺍﻳﻦ ﺍﻣﮑﺎﻥ ﺫﺧﻴﺮﻩ ﻭ ﺑﺎﺯﻳﺎﺑﻲ ،ﮐﺎﺭﺍﻳﻲ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺶ ﺭﺍ ﺍﺭﺗﻘﺎ ﺩﻫﺪ .ﭘﺮﺩﺍﺯﺵ ﻓﺎﻳﻞ ﺩﺭ C++
ﺑﺴﻴﺎﺭ ﺷﺒﻴﻪ ﺗﺮﺍﮐﻨﺶﻫﺎﻱ ﻣﻌﻤﻮﻟﻲ ﻭﺭﻭﺩﻱ ﻭ ﺧﺮﻭﺟﻲ ﺍﺳﺖ ﺯﻳﺮﺍ ﺍﻳﻦﻫﺎ ﻫﻤﻪ ﺍﺯ ﺍﺷﻴﺎﻱ
1 – Files
285 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
ﺟﺮﻳﺎﻥ ﻣﺸﺎﺑﻬﻲ ﺑﻬﺮﻩ ﻣﻲﺑﺮﻧﺪ .ﺟﺮﻳﺎﻥ fstreamﺑﺮﺍﻱ ﺗﺮﺍﮐﻨﺶ ﺑﺮﻧﺎﻣﻪ ﺑﺎ ﻓﺎﻳﻞﻫﺎ ﺑﻪ ﮐﺎﺭ
ﻣﻲﺭﻭﺩ fstream .ﻧﻴﺰ ﺑﻪ ﺩﻭ ﺯﻳﺮﺷﺎﺥۀ ifstreamﻭ ofstreamﺗﻘﺴﻴﻢ ﻣﻲﺷﻮﺩ.
ﺟﺮﻳﺎﻥ ifstreamﺑﺮﺍﻱ ﺧﻮﺍﻧﺪﻥ ﺍﻃﻼﻋﺎﺕ ﺍﺯ ﻳﮏ ﻓﺎﻳﻞ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ ﻭ ﺟﺮﻳﺎﻥ
ofstreamﺑﺮﺍﻱ ﻧﻮﺷﺘﻦ ﺍﻃﻼﻋﺎﺕ ﺩﺭﻭﻥ ﻳﮏ ﻓﺎﻳﻞ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﻓﺮﺍﻣﻮﺵ ﻧﮑﻨﻴﺪ ﮐﻪ
ﺍﻳﻦ ﺟﺮﻳﺎﻥﻫﺎ ﺩﺭ ﺳﺮﻓﺎﻳﻞ > <fstreamﺗﻌﺮﻳﻒ ﺷﺪﻩﺍﻧﺪ .ﭘﺲ ﺑﺎﻳﺪ ﺩﺳﺘﻮﺭ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪۀ
> #include <fstreamﺭﺍ ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻴﺎﻓﺰﺍﻳﻴﺪ .ﺳﭙﺲ ﻣﻲﺗﻮﺍﻧﻴﺪ ﻋﻨﺎﺻﺮﻱ ﺍﺯ
ﻧﻮﻉ ﺟﺮﻳﺎﻥ ﻓﺎﻳﻞ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺗﻌﺮﻳﻒ ﮐﻨﻴﺪ:
;)"ifstream readfile("INPUT.TXT
;)"ofstream writefile("OUTPUT.TXT
>#include <iostream
;using namespace std
)(int main
;)"{ ifstream phonefile("PHONE.TXT
;long number
;string name, searchname
;bool found=false
;" cout << "Enter a name for findind it's phone number:
;cin >> searchname
;cout << endl
)while (phonefile >> number
;{ phonefile >> name
)if (searchname == name
;{ cout << name << ' ' << number << endl
;found = true
}
if (!found) cout << searchname
;<< " is not in this phonebook." << endl
}
ﺩﻳﮕﺮ ﻭ ﺑﻪ ﺷﮑﻞ ﺩﻳﮕﺮﻱ ﻣﺮﺍﻗﺒﺖ ﮐﻨﻴﻢ ﮐﻪ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ﻓﺎﻳﻞ ﺭﺳﻴﺪﻩﺍﻳﻢ ﻳﺎ ﺧﻴﺮ .ﺍﮔﺮ ﺍﻳﻦ
ﻣﺮﺍﻗﺒﺖ ﺻﻮﺭﺕ ﻧﮕﻴﺮﺩ ﻭ ﻭﻗﺘﻲ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ﻓﺎﻳﻞ ﻣﻮﺭﺩ ﻧﻈﺮ ﺭﺳﻴﺪﻳﻢ ﺩﻭﺑﺎﺭﻩ ﺗﻼﺵ ﮐﻨﻴﻢ ﮐﻪ
ﺩﺍﺩﻩﻫﺎﻱ ﺑﻴﺸﺘﺮﻱ ﺭﺍ ﺍﺯ ﻓﺎﻳﻞ ﺑﺨﻮﺍﻧﻴﻢ ،ﺑﺎ ﺧﻄﺎ ﻣﻮﺍﺟﻪ ﻣﻲﺷﻮﻳﻢ ﻭ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺷﮑﻞ ﻧﺎﺧﻮﺍﺳﺘﻪ
ﭘﺎﻳﺎﻥ ﻣﻲﮔﻴﺮﺩ .ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻠﻲ ،ﻫﻨﮕﺎﻡ ﻧﻮﺷﺘﻦ ﻧﺎﻡﻫﺎ ﻭ ﺷﻤﺎﺭﻩﻫﺎ ،ﻳﮏ
ﻓﺎﺻﻞۀ ﺧﺎﻟﻲ ' ' ﻧﻴﺰ ﺑﻴﻦ ﺁﻥ ﻫﺎ ﺩﺭﺝ ﮐﺮﺩﻳﻢ ﺍﻣﺎ ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ ﻫﻨﮕﺎﻡ ﺧﻮﺍﻧﺪﻥ ﺍﻃﻼﻋﺎﺕ،
ﺗﻮﺟﻬﻲ ﺑﻪ ﺍﻳﻦ ﻓﺎﺻﻠﻪﻫﺎﻱ ﺍﺿﺎﻓﻲ ﻧﮑﺮﺩﻳﻢ .ﺑﻪ ﺍﻳﻦ ﺩﻟﻴﻞ ﮐﻪ ﺑﺮﺍﻱ ﺧﻮﺍﻧﺪﻥ ﺍﻃﻼﻋﺎﺕ ﺍﺯ
ﻋﻤﻠﮕﺮ >> ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ ﻭ ﻫﻤﺎﻥ ﻃﻮﺭ ﮐﻪ ﺩﺭ ﺍﺑﺘﺪﺍﻱ ﻓﺼﻞ ﮔﻔﺘﻴﻢ ،ﺍﻳﻦ ﻋﻤﻠﮕﺮ
ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺭﺍ ﻧﺎﺩﻳﺪﻩ ﻣﻲﮔﻴﺮﺩ.
ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺍﻃﻼﻋﺎﺗﻲ ﺭﺍ ﺍﺯ ﺩﺭﻭﻥ ﻓﺎﻳﻞ ﺑﻪ ﺻﻮﺭﺕ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺑﺨﻮﺍﻧﻴﻢ،
ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﺗﺎﺑﻊ )( getﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ .ﺷﮑﻞ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﻗﺒﻼ ﺩﺭ ﺟﺮﻳﺎﻥ cin
ﺩﻳﺪﻳﻢ .ﻫﻤﭽﻨﻴﻦ ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺍﻃﻼﻋﺎﺕ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺩﺭﻭﻥ ﻳﮏ ﻓﺎﻳﻞ
ﺑﻨﻮﻳﺴﻴﻢ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﺗﺎﺑﻊ )( putﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ .ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﻧﻴﺰ ﻗﺒﻼ ﺩﺭ ﺟﺮﻳﺎﻥ coutﺑﻪ
ﮐﺎﺭ ﺑﺮﺩﻩﺍﻳﻢ .ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺧﻮﺍﻧﺪﻥ ﻭ ﻧﻮﺷﺘﻦ ﻓﺎﻳﻞﻫﺎ ﺑﺴﻴﺎﺭ ﺷﺒﻴﻪ ﺧﻮﺍﻧﺪﻥ ﻭ ﻧﻮﺷﺘﻦ
ﻭﺭﻭﺩﻱ/ﺧﺮﻭﺟﻲ ﻣﻌﻤﻮﻟﻲ ﺍﺳﺖ.
ﺍﻣﺎ ﺩﻧﻴﺎﻱ ﻓﺎﻳﻞﻫﺎ ﺑﻪ ﻫﻤﻴﻦ ﺟﺎ ﺧﺘﻢ ﻧﻤﻲﺷﻮﺩ .ﻓﺎﻳﻞﻫﺎﻳﻲ ﮐﻪ ﺩﺭ ﻣﺜﺎﻝﻫﺎﻱ ﺍﺧﻴﺮ
ﺩﻳﺪﻳﻢ ﻫﻤﮕﻲ ﻓﺎﻳﻞﻫﺎﻱ ﻣﺘﻨﻲ ﻫﺴﺘﻨﺪ .ﻳﻌﻨﻲ ﻓﺎﻳﻞﻫﺎﻳﻲ ﮐﻪ ﺍﻃﻼﻋﺎﺕ ﺩﺭﻭﻥ ﺁﻥﻫﺎ ﺑﻪ ﺻﻮﺭﺕ
ﻣﺘﻨﻲ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ ﻭ ﺑﻪ ﻭﺳﻴﻞۀ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻭﺍﮊﻩﭘﺮﺩﺍﺯﻱ ﻣﻲﺗﻮﺍﻥ ﺍﻃﻼﻋﺎﺕ ﺩﺭﻭﻥ ﺍﻳﻦ
ﻓﺎﻳﻞﻫﺎ ﺭﺍ ﺩﻳﺪﻩ ﻭ ﻭﻳﺮﺍﻳﺶ ﮐﺮﺩ .ﻓﺎﻳﻞﻫﺎﻱ ﺩﻳﮕﺮﻱ ﻧﻴﺰ ﻭﺟﻮﺩ ﺩﺍﺭﻧﺪ ﮐﻪ ﺑﻪ ﺁﻥﻫﺎ ﻓﺎﻳﻞﻫﺎﻱ
ﺩﻭﺩﻭﻳﻲ )ﺑﺎﻳﻨﺮﻱ( ﻣﻲﮔﻮﻳﻨﺪ .ﺍﻃﻼﻋﺎﺕ ﺩﺭﻭﻥ ﺍﻳﻦ ﻓﺎﻳﻞﻫﺎ ﺑﻪ ﺷﮑﻞ ﮐﺪﻫﺎﻱ ﺍﺳﮑﻲ ﺫﺧﻴﺮﻩ
ﻣﻲﺷﻮﻧﺪ ﻭ ﻣﻌﻤﻮﻻ ﺑﻪ ﺳﺎﺩﮔﻲ ﻧﻤﻲﺗﻮﺍﻥ ﻓﻬﻤﻴﺪ ﮐﻪ ﭼﻪ ﺍﻃﻼﻋﺎﺗﻲ ﺩﺭﻭﻥ ﺁﻥﻫﺎ ﺍﺳﺖ .ﺍﻳﻦ ﺩﻭ
ﮔﻮﻧﻪ ﻓﺎﻳﻞ ،ﻫﺮ ﮐﺪﺍﻡ ﮐﺎﺭﺍﻳﻲ ﻭ ﻗﺎﺑﻠﻴﺖﻫﺎﻱ ﺧﺎﺹ ﺧﻮﺩ ﺭﺍ ﺩﺍﺭﻧﺪ.
ﭘﺮﺩﺍﺯﺵ ﻓﺎﻳﻞ ،ﻓﻘﻂ ﺧﻮﺍﻧﺪﻥ ﻭ ﻧﻮﺷﺘﻦ ﺗﺮﺗﻴﺒﻲ ﺍﻃﻼﻋﺎﺕ ﻧﻴﺴﺖ .ﮔﺎﻫﻲ ﻻﺯﻡ ﺍﺳﺖ
ﺍﻃﻼﻋﺎﺕ ﺩﻭ ﻳﺎ ﭼﻨﺪ ﻓﺎﻳﻞ ﺭﺍ ﺑﺎ ﻫﻢ ﺗﺮﮐﻴﺐ ﮐﻨﻴﺪ .ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﺨﻮﺍﻫﻴﺪ ﻓﺎﻳﻠﻲ ﮐﻪ ﺍﺯ ﻗﺒﻞ
ﻭﺟﻮﺩ ﺩﺍﺷﺘﻪ ﺭﺍ ﻭﻳﺮﺍﻳﺶ ﮐﻨﻴﺪ ﻭ ﻓﻘﻂ ﺑﺨﺸﻲ ﺍﺯ ﺁﻥ ﻓﺎﻳﻞ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ .ﻣﻤﮑﻦ ﺍﺳﺖ
ﺑﺨﻮﺍﻫﻴﺪ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ﻳﮏ ﻓﺎﻳﻞ ،ﺍﻃﻼﻋﺎﺗﻲ ﺍﺿﺎﻓﻪ ﮐﻨﻴﺪ ﻳﺎ ﺍﻳﻦ ﮐﻪ ﺍﻃﻼﻋﺎﺗﻲ ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﻓﺎﻳﻞ
ﺑﻴﺎﻓﺰﺍﻳﻴﺪ ﻭ ﻳﺎ ﺍﻃﻼﻋﺎﺗﻲ ﺭﺍ ﺩﺭ ﻣﺤﻞ ﺧﺎﺻﻲ ﺍﺯ ﻣﻴﺎﻥۀ ﻓﺎﻳﻞ ﻗﺮﺍﺭ ﺩﻫﻴﺪ .ﻫﺮ ﺯﺑﺎﻥ
289 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺍﺯ ﺟﻤﻠﻪ C++ﺑﺮﺍﻱ ﺗﻤﺎﻣﻲ ﺍﻳﻦ ﺍﻋﻤﺎﻝ ﺗﻮﺍﺑﻊ ﻭ ﺍﻣﮑﺎﻧﺎﺕ ﺧﺎﺻﻲ ﺗﺪﺍﺭﮎ ﺩﻳﺪﻩ
ﺍﺳﺖ .ﻫﺮ ﭼﻨﺪ ﺩﺭ ﺍﻳﻦ ﮐﺘﺎﺏ ﺑﺮﺍﻱ ﺗﺸﺮﻳﺢ ﻣﻄﺎﻟﺐ ﻓﻮﻕ ﻣﺠﺎﻟﻲ ﻧﻴﺴﺖ ،ﺍﻣﺎ ﻫﻤﻴﻦ ﻧﮑﺘﻪ
ﺷﺮﻭﻉ ﺧﻮﺑﻲ ﺍﺳﺖ ﺗﺎ ﺭﺍﺟﻊ ﺑﻪ ﭘﺮﺩﺍﺯﺵ ﻓﺎﻳﻞ ﺑﻴﺸﺘﺮ ﺗﺤﻘﻴﻖ ﮐﻨﻴﺪ ﻭ ﺩﺍﻧﺶ ﺑﺎﻻﺗﺮﻱ ﮐﺴﺐ
ﻧﻤﺎﻳﻴﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 290
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﺎ ﮐﺎﺭﺍﮐﺘﺮ ...............ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﻨﺪ.
ﺩ( ''\Ø ﺝ( ''\b ﺏ( ''\t ﺍﻟﻒ( ''\n
– 2ﺩﺭ ﻣﻮﺭﺩ ﺩﺳﺘﻮﺭ ;" char str[]="testﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ( strﻳﮏ ﺁﺭﺍﻳﻪ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﺍﺳﺖ
ﺏ( strﻳﮏ ﺁﺭﺍﻳﻪ ﭼﻬﺎﺭ ﻋﻨﺼﺮﻱ ﺍﺳﺖ
ﺝ( strﻳﮏ ﺁﺭﺍﻳﻪ ﺑﺪﻭﻥ ﻋﻨﺼﺮ ﺍﺳﺖ
ﺩ( strﻳﮏ ﺁﺭﺍﻳﻪ ﺗﮏ ﻋﻨﺼﺮﻱ ﺍﺳﺖ
– 3ﺩﺳﺘﻮﺭ ; cout << strﭼﻪ ﮐﺎﺭﻱ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ؟
ﺍﻟﻒ( ﺍﮔﺮ strﺍﺯ ﻧﻮﻉ * intﺑﺎﺷﺪ ،ﺁﺩﺭﺱ ﺩﺭﻭﻥ ﺁﻥ ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ
ﺏ( ﺍﮔﺮ strﺍﺯ ﻧﻮﻉ * charﺑﺎﺷﺪ ،ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺩﺭﻭﻥ ﺁﻥ ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ
ﺝ( ﺍﮔﺮ strﺍﺯ ﻧﻮﻉ * floatﺑﺎﺷﺪ ،ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺩﺭﻭﻥ ﺁﻥ ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ
ﺩ( ﺍﻟﻒ ﻭ ﺏ ﺻﺤﻴﺢ ﺍﺳﺖ
– 4ﺩﺭ ﻣﻮﺭﺩ ﺩﺳﺘﻮﺭ " char* p[] = "testﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ( pﻳﮏ ﺁﺭﺍﻱۀ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﺍﺳﺖ
ﺏ( pﻳﮏ ﺁﺭﺍﻱۀ ﭼﻬﺎﺭ ﻋﻨﺼﺮﻱ ﺍﺳﺖ
ﺝ( pﻳﮏ ﺁﺭﺍﻱۀ ﺑﺪﻭﻥ ﻋﻨﺼﺮ ﺍﺳﺖ
ﺩ( pﻳﮏ ﺁﺭﺍﻱۀ ﺗﮏ ﻋﻨﺼﺮﻱ ﺍﺳﺖ
– 5ﮐﺪﺍﻡ ﺩﺳﺘﻮﺭ ،ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﺑﺎ NULﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ؟
ﺏ( ;"char* p="test ﺍﻟﻒ( ;"char p="test
ﺩ( ;"char* p[]="test ﺝ( ;"char p[]="test
– 6ﮐﺪﺍﻡ ﺗﺎﺑﻊ ،ﻋﻀﻮ cinﻧﻴﺴﺖ؟
ﺩ( )(get ﺝ( )(seek ﺏ( )(getline ﺍﻟﻒ( )(put
– 7ﻧﻘﺶ ﮐﺎﺭﺍﮐﺘﺮ ' '9ﺩﺭ ﺩﺳﺘﻮﺭ ;)' cin.getline(str, p, '9ﭼﻴﺴﺖ؟
ﺍﻟﻒ( ﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻳﻲ ﮐﻪ ﺑﺎﻳﺪ ﺑﻪ ﺩﺭﻭﻥ strﺧﻮﺍﻧﺪﻩ ﺷﻮﻧﺪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ
ﺏ( ﺗﻌﺪﺍﺩ ﺳﻄﺮﻫﺎﻳﻲ ﮐﻪ ﺑﺎﻳﺪ ﺑﻪ ﺩﺭﻭﻥ strﺧﻮﺍﻧﺪﻩ ﺷﻮﻧﺪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ
291 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
ﺝ( ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺭﻭﺩﻱ ﺑﻪ ﻏﻴﺮ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮ ' '9ﺑﻪ ﺩﺭﻭﻥ Strﻣﻨﺘﻘﻞ ﻣﻲﺷﻮﻧﺪ
ﺩ( ' '9ﮐﺎﺭﺍﮐﺘﺮ ﻣﺮﺯﺑﻨﺪﻱ ﺩﺭ ﻭﺭﻭﺩﻱ ﺍﺳﺖ
– 8ﺩﺭ ﻣﻮﺭﺩ ﮐﺪ ;) result = (cin >> xﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ – xﺍﺯ ﻫﺮ ﻧﻮﻋﻲ ﻣﻲﺗﻮﺍﻧﺪ ﺑﺎﺷﺪ ﻭﻟﻲ resultﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ boolﺑﺎﺷﺪ
ﺏ – resultﺍﺯ ﻫﺮ ﻧﻮﻋﻲ ﻣﻲﺗﻮﺍﻧﺪ ﺑﺎﺷﺪ ﻭﻟﻲ xﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ boolﺑﺎﺷﺪ
ﺝ – xﻓﻘﻂ ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ charﻭ resultﻓﻘﻂ ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ boolﺑﺎﺷﺪ.
ﺩ – resultﻓﻘﻂ ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ charﻭ xﻓﻘﻂ ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ boolﺑﺎﺷﺪ
– 9ﮐﺪﺍﻡ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺍﺯ ﻃﺮﻳﻖ ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ >> ﺩﺭﻳﺎﻓﺖ ﻧﻤﻮﺩ؟
ﺩ – '!' ﺝ – ''0 ﺏ–' ' ﺍﻟﻒ – ''n
– 10ﺍﮔﺮ nﺍﺯ ﻧﻮﻉ intﺑﺎ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ 32ﺍﻋﻼﻥ ﺷﺪﻩ ﺑﺎﺷﺪ ﻭ ﮐﺪ ;cin >> n
ﺍﺟﺮﺍ ﺷﻮﺩ ﻭ ﻭﺭﻭﺩﻱ ﺑﻪ ﺷﮑﻞ ' 'p327ﺗﺎﻳﭗ ﺷﻮﺩ ،ﺁﻧﮕﺎﻩ ﻣﻘﺪﺍﺭ nﺑﺮﺍﺑﺮ ﺍﺳﺖ ﺑﺎ:
ﺩ – 327 ﺝ – 32 ﺏ–0 ﺍﻟﻒ – p
– 11ﺗﺎﺑﻊ ﮐﻤﮑﻲ )( cin.getﺩﺭ ﮐﺪﺍﻡ ﺳﺮﻓﺎﻳﻞ ﻣﻌﺮﻓﻲ ﺷﺪﻩ؟
ﺏ ‐ ><fstream ﺍﻟﻒ ‐ ><iostream
ﺩ ‐ ><cmath ﺝ ‐ ><iomanip
– 12ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﮐﺪ ;) cout.put(cﺩﺭﺳﺖ ﮐﺎﺭ ﮐﻨﺪ ،ﻣﺘﻐﻴﺮ cﺑﺎﻳﺪ:
ﺏ – ﺍﺯ ﻧﻮﻉ floatﺑﺎﺷﺪ ﺍﻟﻒ – ﺍﺯ ﻧﻮﻉ stringﺑﺎﺷﺪ
ﺩ – ﺍﺯ ﻧﻮﻉ doubleﺑﺎﺷﺪ ﺝ – ﺍﺯ ﻧﻮﻉ charﺑﺎﺷﺪ
– 13ﺍﮔﺮ s1ﺍﺯ ﻧﻮﻉ stringﻭ s2ﺍﺯ ﻧﻮﻉ * charﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ:
ﺍﻟﻒ – s1ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﮐﺮﺩ ﻭﻟﻲ S2ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ.
ﺏ – s1ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺻﺮﻳﺤﺎ ﺍﺯ ﺭﻭﻱ ﻳﮏ ﻣﺘﻐﻴﺮ ﻫﻢﻧﻮﻉ ﮐﭙﻲ ﮐﺮﺩ ﻭﻟﻲ s2ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ.
ﺝ – s1ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﺧﺮﻭﺟﻲ ﻧﻤﺎﻳﺶ ﺩﺍﺩ ﻭﻟﻲ s2ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ.
ﺩ – s1ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﺴﺘﻘﻴﻤﺎ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﮐﺮﺩ ﻭﻟﻲ S2ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ.
– 14ﺍﮔﺮ s1ﺍﺯ ﻧﻮﻉ stringﻭ ﺑﺎ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ " "1234ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﻣﻘﺪﺍﺭ
] S1[2ﺑﺮﺍﺑﺮ ﺍﺳﺖ ﺑﺎ:
ﺩ – ""34 ﺝ – ""12 ﺏ – ''3 ﺍﻟﻒ – ''2
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 292
– 15ﺍﮔﺮ ﺭﺷﺖۀ Sﺍﺯ ﻧﻮﻉ stringﻭ ﺭﺷﺖۀ cﺍﺯ ﻧﻮﻉ charﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﺑﺮﺍﻱ
ﭘﻴﺪﺍ ﮐﺮﺩﻥ ﻃﻮﻝ sﻭ cﺑﻪ ﺗﺮﺗﻴﺐ ﺍﺯ ﮐﺪﺍﻡ ﺗﺎﺑﻊ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ؟
ﺍﻟﻒ – ﺑﺮﺍﻱ sﺍﺯ ﺗﺎﺑﻊ )( strlenﻭ ﺑﺮﺍﻱ cﺍﺯ ﺗﺎﺑﻊ )(length
ﺏ – ﺑﺮﺍﻱ sﺍﺯ ﺗﺎﺑﻊ )( lengthﻭ ﺑﺮﺍﻱ cﺍﺯ ﺗﺎﺑﻊ )(strlen
ﺝ – ﺑﺮﺍﻱ sﻭ cﻫﺮ ﺩﻭ ﺍﺯ ﺗﺎﺑﻊ )(length
ﺩ – ﺑﺮﺍﻱ sﻭ cﻫﺮ ﺩﻭ ﺍﺯ ﺗﺎﺑﻊ )(strlen
– 16ﺍﮔﺮ ﻣﺘﻐﻴﺮ nﺍﺯ ﻧﻮﻉ stringﻭ ﺑﺎ ﻣﻘﺪﺍﺭ " "IRANﺑﺎﺷﺪ ،ﭘﺲ ﺍﺯ ﺍﺟﺮﺍﻱ ﮐﺪ
;) n.erase(1,2ﻣﻘﺪﺍﺭ nﺑﺮﺍﺑﺮ ﺍﺳﺖ ﺑﺎ:
ﺩ – ""IN ﺝ – ""AN ﺏ – ""RA ﺍﻟﻒ – ""IR
– 17ﺍﮔﺮ ﻣﺘﻐﻴﺮ str1ﺍﺯ ﻧﻮﻉ stringﻭ ﺑﺎ ﻣﻘﺪﺍﺭ " "ABCDﺑﺎﺷﺪ ،ﮐﺪﺍﻡ ﺩﺳﺘﻮﺭ
ﻣﻘﺪﺍﺭ str1ﺭﺍ ﺑﻪ " "EFGHﺗﺒﺪﻳﻞ ﻣﻲﮐﻨﺪ؟
ﺍﻟﻒ – ;)"str1.replace(0,0,"EFGH
ﺏ – ;)"str1.replace(1,1,"EFGH
ﺝ – ;)"str1.replace(0,4,"EFGH
ﺩ – ;)"str1.replace(1,4,"EFGH
– 18ﺍﮔﺮ _t1ﺍﺯ ﻧﻮﻉ stringﻭ ﺑﺎ ﻣﻘﺪﺍﺭ " "PNUﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﻓﺮﺍﺧﻮﺍﻧﻲ
;)" _t1.find("PUﭼﻪ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ؟
ﺩ–3 ﺝ–2 ﺏ–1 ﺍﻟﻒ – 0
‐ 19ﺑﺮﺍﻱ ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ﻓﺎﻳﻞﻫﺎ ﺩﺭ c++ﺑﺎﻳﺪ ﮐﺪﺍﻡ ﺳﺮﻓﺎﻳﻞ ﺭﺍ ﺑﻪ ﺑﺮﻧﺎﻣﻪ ﺑﻴﺎﻓﺰﺍﻳﻴﻢ؟
ﺏ ‐ ><fstream ﺍﻟﻒ ‐ ><iostream
ﺩ ‐ ><cmath ﺝ ‐ ><iomanip
– 20ﺩﺭ ﻣﻮﺭﺩ ﮐﺪ ;)" ifstream file1("test.txtﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ
ﺍﺳﺖ؟
ﺍﻟﻒ – file1ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺭﻭﻥ ﻓﺎﻳﻞ test.txtﺑﻨﻮﻳﺴﺪ.
ﺏ – file1ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺯ ﻓﺎﻳﻞ test.txtﺑﺨﻮﺍﻧﺪ.
ﺝ – file1ﻫﻢ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺭﻭﻥ ﻓﺎﻳﻞ test.txtﻧﻮﺷﺘﻪ ﻭ ﻫﻢ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺯ ﺁﻥ ﺑﺨﻮﺍﻧﺪ
ﺩ – file1ﻓﻘﻂ ﺑﺮﺍﻱ ﭘﺎﮎ ﮐﺮﺩﻥ ﻓﺎﻳﻞ test.txtﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ.
293 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﺑﻪ ﺍﻋﻼﻥﻫﺎﻱ ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ:
;]char s[6
;}'char s[6] = {'H', 'e', 'l', 'l', 'o
;"char s[6] = "Hello
;][char s
;]char s[] = new char[6
;}'char s[] = {'H', 'e', 'l', 'l', 'o
;"char s[] = "Hello
;)"char s[] = new("Hello
;char* s
;]char* s = new char[6
;}'char* s = {'H', 'e', 'l', 'l', 'o
;"char* s = "Hello
;)"char* s = new("Hello
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ ﻛﻪ ﭼﺮﺍ ﺭﺍﻫﻜﺎﺭ ﺯﻳﺮ ﺑﺮﺍﻱ ﻣﺜﺎﻝ 8‐11ﻛﺎﺭ ﻧﻤﻲﻛﻨﺪ؟
)(int main
;]{ char name[10][20], buffer[20
;int count = 0
))while (cin.getline(buffer,20
;name[count] = buffer
;--count
;"cout << "The names are:\n
)for (int i = 0; i < count; i++
;cout << "\t" << i << ". [" << name[i] << "]" << endl
}
ﺑﺠﺎﻱ ﻋﺒﺎﺭﺕ
)do..while (*word
ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﺪ.
‐5ﺗﺎﺑﻌﻲ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺗﻌﺪﺍﺩ ﺗﮑﺮﺍﺭ ﻳﮏ ﻛﺎﺭﺍﻛﺘﺮ ﺩﺍﺩﻩ ﺷﺪﻩ ﺭﺍ ﺩﺭ ﻳﻚ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ
ﻣﻔﺮﻭﺽ ﺑﺮﮔﺮﺩﺍﻧﺪ.
‐6ﮐﺪ ﻫﺮ ﻳﮏ ﺍﺯ ﺗﻮﺍﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ:
)(strcpy )(strncat )(strchr
297 ﻓﺼﻞ هﺸﺘﻢ /رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در C++اﺳﺘﺎﻧﺪارد
;'!' = ]s[8
;)"s.replace(8, 5, "xyz
;)s.erase(6, 4
;)"!"(cout << s.find
;)"?"(cout << s.find
;)cout << s.substr(6, 3
;"s += "abcde
;)string part(s, 4, 8
;)'*' string stars(8,
‐15ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺗﻌﺪﺍﺩ ﺧﻂﻫﺎ ،ﻛﻠﻤﺎﺕ ﻭ ﺗﻌﺪﺍﺩ ﺗﮑﺮﺍﺭ ﺣﺮﻭﻑ ﺩﺭ ﻭﺭﻭﻱ ﺭﺍ
ﺑﺸﻤﺎﺭﺩ ﻭ ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻛﻨﺪ.
‐16ﺑﺮﻧﺎﻡۀ ﺗﻤﺮﻳﻦ ﻗﺒﻠﻲ ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﮐﻪ ﺍﻃﻼﻋﺎﺕ ﻭﺭﻭﺩﻱ ﺭﺍ ﺍﺯ ﻳﮏ ﻓﺎﻳﻞ ﻣﺘﻨﻲ
ﺑﺨﻮﺍﻧﺪ.
‐17ﺍﺑﺘﺪﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 8‐23ﺩﻭ ﻓﺎﻳﻞ ﺑﻪ ﻧﺎﻡﻫﺎﻱ PHONE1.TXTﻭ
PHONE2.TXTﺍﻳﺠﺎﺩ ﮐﻨﻴﺪ ﻭ ﺩﺭ ﻫﺮ ﮐﺪﺍﻡ ﺗﻌﺪﺍﺩﻱ ﻧﺎﻡ ﻭ ﺷﻤﺎﺭۀ ﺗﻠﻔﻦ ﺫﺧﻴﺮﻩ ﮐﻨﻴﺪ.
ﺳﭙﺲ ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﮐﻪ ﻣﺤﺘﻮﻳﺎﺕ ﺍﻳﻦ ﺩﻭ ﻓﺎﻳﻞ ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﺍﻟﻔﺒﺎﻳﻲ ﻧﺎﻡﻫﺎ ﺩﺭ ﻓﺎﻳﻞ
ﺳﻮﻡ ﺑﻪ ﻧﺎﻡ PHONEBOOK.TXTﻣﺮﺗﺐ ﮐﺮﺩﻩ ﻭ ﺫﺧﻴﺮﻩ ﻧﻤﺎﻳﺪ.
ﻓﺼﻞ ﻧﻬﻢ
»ﺷﻲﮔﺮﺍﻳﻲ«
9‐1ﻣﻘﺪﻣﻪ
ﺍﻭﻟﻴﻦ ﻧﺮﻡﺍﻓﺰﺍﺭ ﺑﺮﺍﻱ ﻧﺨﺴﺘﻴﻦ ﺭﺍﻳﺎﻧﻪﻫﺎ ،ﺯﻧﺠﻴﺮﻩﺍﻱ ﺍﺯ ﺻﻔﺮ ﻭ ﻳﮏﻫﺎ ﺑﻮﺩ ﮐﻪ ﻓﻘﻂ ﻋﺪۀ
ﺍﻧﺪﮐﻲ ﺍﺯ ﺍﻳﻦ ﺗﻮﺍﻟﻲ ﺳﺮ ﺩﺭ ﻣﻲﺁﻭﺭﺩﻧﺪ .ﺑﻪ ﺗﺪﺭﻳﺞ ﮐﺎﺭﺑﺮﺩ ﺭﺍﻳﺎﻧﻪ ﮔﺴﺘﺮﺵ ﻳﺎﻓﺖ ﻭ ﻧﻴﺎﺯ ﺑﻮﺩ
ﺗﺎ ﻧﺮﻡﺍﻓﺰﺍﺭﻫﺎﻱ ﺑﻴﺶﺗﺮﻱ ﺍﻳﺠﺎﺩ ﺷﻮﺩ .ﺑﺮﺍﻱ ﺍﻳﻦ ﻣﻨﻈﻮﺭ ،ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﻣﺠﺒﻮﺭ ﺑﻮﺩﻧﺪ ﺑﺎ
ﺍﻧﺒﻮﻫﻲ ﺍﺯ ﺻﻔﺮﻫﺎ ﻭ ﻳﮏﻫﺎ ﺳﺮ ﻭ ﮐﻠﻪ ﺑﺰﻧﻨﺪ ﻭ ﺍﻳﻦ ﺑﺎﻋﺚ ﻣﻲﺷﺪ ﻣﺪﺕ ﺯﻳﺎﺩﻱ ﺑﺮﺍﻱ ﺗﻮﻟﻴﺪ
ﻳﮏ ﻧﺮﻡﺍﻓﺰﺍﺭ ﺻﺮﻑ ﺷﻮﺩ .ﺍﺯ ﺍﻳﻦ ﮔﺬﺷﺘﻪ ،ﺍﮔﺮ ﺍﻳﺮﺍﺩﻱ ﺩﺭ ﮐﺎﺭ ﺑﺮﻧﺎﻣﻪ ﻳﺎﻓﺖ ﻣﻲﺷﺪ ،ﭘﻴﺪﺍ
ﮐﺮﺩﻥ ﻣﺤﻞ ﺍﻳﺮﺍﺩ ﻭ ﺭﻓﻊ ﺁﻥ ﺑﺴﻴﺎﺭ ﻣﺸﮑﻞ ﻭ ﻃﺎﻗﺖﻓﺮﺳﺎ ﺑﻮﺩ .ﺍﺑﺪﺍﻉ »ﺯﺑﺎﻥ ﺍﺳﻤﺒﻠﻲ «1ﺟﻬﺶ
ﺑﺰﺭﮔﻲ ﺑﻪ ﺳﻮﻱ ﺗﻮﻟﻴﺪ ﻧﺮﻡﺍﻓﺰﺍﺭﻫﺎﻱ ﮐﺎﺭﺁﻣﺪ ﺑﻮﺩ.
ﺍﺳﻤﺒﻠﻲ ﻗﺎﺑﻞ ﻓﻬﻢﺗﺮ ﺑﻮﺩ ﻭ ﺩﻧﺒﺎﻝ ﮐﺮﺩﻥ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺳﻬﻮﻟﺖ ﻣﻲﺑﺨﺸﻴﺪ .ﺳﺨﺖﺍﻓﺰﺍﺭ ﺑﻪ
ﺳﺮﻋﺖ ﺭﺷﺪ ﻣﻲﮐﺮﺩ ﻭ ﺍﻳﻦ ﺭﺷﺪ ﺑﻪ ﻣﻌﻨﻲ ﻧﺮﻡﺍﻓﺰﺍﺭﻫﺎﻱ ﮐﺎﻣﻞﺗﺮ ﻭ ﮔﺴﺘﺮﺩﻩﺗﺮ ﺑﻮﺩ .ﮐﻢ ﮐﻢ
ﺯﺑﺎﻥ ﺍﺳﻤﺒﻠﻲ ﻫﻢ ﺟﻮﺍﺏﮔﻮﻱ ﺷﻴﻮﻩﻫﺎﻱ ﻧﻮﻳﻦ ﺗﻮﻟﻴﺪ ﻧﺮﻡﺍﻓﺰﺍﺭ ﻧﺒﻮﺩ .ﻫﺸﺖ ﺧﻂ ﮐﺪ ﺍﺳﻤﺒﻠﻲ
1 – Assembly
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 300
ﺑﺮﺍﻱ ﻳﮏ ﺟﻤﻊ ﺳﺎﺩﻩ ﺑﻪ ﻣﻌﻨﺎﻱ ﺩﻩﻫﺎ ﻫﺰﺍﺭ ﺧﻂ ﮐﺪ ﺑﺮﺍﻱ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﺣﺴﺎﺑﺪﺍﺭﻱ ﺭﻭﺯﺍﻧﻪ
ﺍﺳﺖ .ﺍﻳﻦ ﺑﺎﺭ ﺍﻧﺒﻮﻩ ﮐﺪﻫﺎﻱ ﺍﺳﻤﺒﻠﻲ ﻣﺸﮑﻞﺳﺎﺯ ﺷﺪﻧﺪ» .ﺯﺑﺎﻥﻫﺎﻱ ﺳﻄﺢ ﺑﺎﻻ« ﺩﺭﻭﺍﺯﻩﻫﺎﻱ
ﺗﻤﺪﻥ ﺟﺪﻳﺪ ﺩﺭ ﺩﻧﻴﺎﻱ ﻧﺮﻡﺍﻓﺰﺍﺭ ﺭﺍ ﺑﻪ ﺭﻭﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﮔﺸﻮﺩﻧﺪ.
ﺯﺑﺎﻥﻫﺎﻱ ﺳﻄﺢ ﺑﺎﻻ ﺩﻭ ﻧﺸﺎﻥ ﺩﺭﺧﺸﺎﻥ ﺍﺯ ﺍﺩﺑﻴﺎﺕ ﻭ ﺭﻳﺎﺿﻴﺎﺕ ﻫﻤﺮﺍﻩ ﺧﻮﺩ ﺁﻭﺭﺩﻧﺪ:
ﺍﻭﻝ ﺩﺳﺘﻮﺭﺍﺗﻲ ﺷﺒﻴﻪ ﺯﺑﺎﻥ ﻣﺤﺎﻭﺭﻩﺍﻱ ﮐﻪ ﺑﺎﻋﺚ ﺷﺪﻧﺪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺍﺯ ﺩﺳﺖ ﮐﺪﻫﺎﻱ
ﺗﮑﺮﺍﺭﻱ ﻭ ﻃﻮﻳﻞ ﺍﺳﻤﺒﻠﻲ ﺧﻼﺹ ﺷﻮﻧﺪ ﻭ ﺩﻭﻡ ﻣﻔﻬﻮﻡ »ﺗﺎﺑﻊ« ﮐﻪ ﺳﺮﻋﺖ ﺗﻮﻟﻴﺪ ﻭ
ﻋﻴﺐﻳﺎﺑﻲ ﻧﺮﻡ ﺍﻓﺰﺍﺭ ﺭﺍ ﭼﻨﺪﻳﻦ ﺑﺮﺍﺑﺮ ﮐﺮﺩ .ﺍﺳﺎﺱ ﮐﺎﺭ ﺍﻳﻦ ﮔﻮﻧﻪ ﺑﻮﺩ ﮐﻪ ﻭﻇﻴﻒۀ ﺍﺻﻠﻲ
ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻭﻇﺎﻳﻒ ﮐﻮﭼﮏﺗﺮﻱ ﺗﻘﺴﻴﻢ ﻣﻲﺷﺪ ﻭ ﺑﺮﺍﻱ ﺍﻧﺠﺎﻡ ﺩﺍﺩﻥ ﻫﺮ ﻭﻇﻴﻔﻪ ،ﺗﺎﺑﻌﻲ ﻧﻮﺷﺘﻪ
ﻣﻲﺷﺪ .ﭘﺲ ﺍﻳﻦ ﻣﻤﮑﻦ ﺑﻮﺩ ﮐﻪ ﺗﻮﺍﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﻳﮏ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻃﻮﺭ ﻫﻢﺯﻣﺎﻥ ﻧﻮﺷﺘﻪ ﻭ
ﺁﺯﻣﺎﻳﺶ ﺷﻮﻧﺪ ﻭ ﺳﭙﺲ ﻫﻤﮕﻲ ﺩﺭ ﮐﻨﺎﺭ ﻫﻢ ﭼﻴﺪﻩ ﺷﻮﻧﺪ .ﺩﻳﮕﺮ ﻻﺯﻡ ﻧﺒﻮﺩ ﻗﺴﻤﺘﻲ ﺍﺯ
ﻧﺮﻡﺍﻓﺰﺍﺭ ،ﻣﻨﺘﻈﺮ ﺗﮑﻤﻴﻞ ﺷﺪﻥ ﻗﺴﻤﺖ ﺩﻳﮕﺮﻱ ﺑﻤﺎﻧﺪ .ﻫﻤﭽﻨﻴﻦ ﻋﻴﺐﻳﺎﺑﻲ ﻧﻴﺰ ﺁﺳﺎﻥ ﺻﻮﺭﺕ
ﻣﻲﮔﺮﻓﺖ ﻭ ﺑﻪ ﺳﺮﻋﺖ ﻣﺤﻞ ﺧﻄﺎ ﻳﺎﻓﺖ ﺷﺪﻩ ﻭ ﺍﺻﻼﺡ ﻣﻲﺷﺪ .ﻋﻼﻭﻩ ﺑﺮ ﺍﻳﻦ ،ﺑﺮﺍﻱ ﺑﻬﺒﻮﺩ
ﺩﺍﺩﻥ ﻧﺮﻡﺍﻓﺰﺍﺭ ﻣﻮﺟﻮﺩ ﻳﺎ ﺍﻓﺰﻭﺩﻥ ﺍﻣﮑﺎﻧﺎﺕ ﺍﺿﺎﻓﻲ ﺑﻪ ﺁﻥ ،ﺩﻳﮕﺮ ﻻﺯﻡ ﻧﺒﻮﺩ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﻧﻮ
ﻧﻮﺷﺘﻪ ﺷﻮﺩ؛ ﻓﻘﻂ ﺗﻮﺍﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺗﻮﻟﻴﺪ ﮐﺮﺩﻩ ﻳﺎ ﺑﻬﺒﻮﺩ ﻣﻲﺩﺍﺩﻧﺪ ﻭ ﺁﻥ ﺭﺍ ﺑﻪ ﺑﺮﻧﺎﻡۀ
ﻣﻮﺟﻮﺩ ﭘﻴﻮﻧﺪ ﻣﻲﺯﺩﻧﺪ .ﺍﺯ ﺍﻳﻦ ﺑﻪ ﺑﻌﺪ ﺑﻮﺩ ﮐﻪ ﮔﺮﻭﻩﻫﺎﻱ ﺗﻮﻟﻴﺪ ﻧﺮﻡﺍﻓﺰﺍﺭﻱ ﺑﺮﺍﻱ ﺗﻮﻟﻴﺪ
ﻧﺮﻡﺍﻓﺰﺍﺭﻫﺎﻱ ﺑﺰﺭﮒ ﺍﻳﺠﺎﺩ ﺷﺪﻧﺪ ﻭ ﺑﺤﺚ ﻣﺪﻳﺮﻳﺖ ﭘﺮﻭﮊﻩﻫﺎﻱ ﻧﺮﻡﺍﻓﺰﺍﺭﻱ ﻭ ﺷﻴﻮﻩﻫﺎﻱ ﺗﻮﻟﻴﺪ
ﻧﺮﻡﺍﻓﺰﺍﺭ ﻭ ﭼﺮﺥۀ ﺣﻴﺎﺕ ﻭ ...ﻣﻄﺮﺡ ﺷﺪ.
ﻧﺮﻡﺍﻓﺰﺍﺭﻫﺎﻱ ﺑﺰﺭﮒ ،ﺗﺠﺮﺑﻴﺎﺕ ﺟﺪﻳﺪﻱ ﺑﻪ ﻫﻤﺮﺍﻩ ﺁﻭﺭﺩﻧﺪ ﻭ ﺑﺮﺧﻲ ﺍﺯ ﺍﻳﻦ ﺗﺠﺮﺑﻴﺎﺕ
ﻧﺸﺎﻥ ﻣﻲﺩﺍﺩ ﮐﻪ ﺗﻮﺍﺑﻊ ﭼﻨﺪﺍﻥ ﻫﻢ ﺑﻲﻋﻴﺐ ﻧﻴﺴﺘﻨﺪ .ﺑﺮﺍﻱ ﺍﻳﺠﺎﺩ ﻳﮏ ﻧﺮﻡﺍﻓﺰﺍﺭ ،ﺗﻮﺍﺑﻊ ﺯﻳﺎﺩﻱ
ﻧﻮﺷﺘﻪ ﻣﻲﺷﺪ ﮐﻪ ﺍﻏﻠﺐ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺑﻪ ﻳﮑﺪﻳﮕﺮ ﻭﺍﺑﺴﺘﮕﻲ ﺩﺍﺷﺘﻨﺪ .ﺍﮔﺮ ﻗﺮﺍﺭ ﻣﻲﺷﺪ ﻭﺭﻭﺩﻱ ﻳﺎ
ﺧﺮﻭﺟﻲ ﻳﮏ ﺗﺎﺑﻊ ﺗﻐﻴﻴﺮ ﮐﻨﺪ ،ﺳﺎﻳﺮ ﺗﻮﺍﺑﻌﻲ ﮐﻪ ﺑﺎ ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﺩﺭ ﺍﺭﺗﺒﺎﻁ ﺑﻮﺩﻧﺪ ﻧﻴﺰ ﺑﺎﻳﺪ
ﺷﻨﺎﺳﺎﻳﻲ ﻣﻲﺷﺪﻧﺪ ﻭ ﺑﻪ ﺗﻨﺎﺳﺐ ﺗﻐﻴﻴﺮ ﻣﻲﻧﻤﻮﺩﻧﺪ .ﺍﻳﻦ ﻣﻮﺿﻮﻉ ،ﺍﺻﻼﺡ ﻧﺮﻡﺍﻓﺰﺍﺭﻫﺎ ﺭﺍ
ﻣﺸﮑﻞ ﻣﻲﮐﺮﺩ .ﻋﻼﻭﻩ ﺑﺮ ﺍﻳﻦ ﺍﮔﺮ ﺗﻐﻴﻴﺮ ﻳﮏ ﺗﺎﺑﻊ ﻣﺮﺗﺒﻂ ﻓﺮﺍﻣﻮﺵ ﻣﻲﺷﺪ ،ﺻﺤﺖ ﮐﻞ
ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺧﻄﺮ ﻣﻲﺍﻓﺘﺎﺩ .ﺍﻳﻦ ﺍﺷﮑﺎﻻﺕ ﺑﺮﺍﻱ ﻣﺪﻳﺮﺍﻥ ﻭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺑﺴﻴﺎﺭ ﺟﺪﻱ ﺑﻮﺩ.
ﺑﻨﺎﺑﺮﺍﻳﻦ ﺑﺎﺯ ﻫﻢ ﻣﺘﺨﺼﺼﻴﻦ ﺑﻪ ﻓﮑﺮ ﺭﺍﻩ ﭼﺎﺭﻩ ﺍﻓﺘﺎﺩﻧﺪ .ﭘﺲ ﺍﺯ ﺭﻳﺎﺿﻲ ﻭ ﺍﺩﺑﻴﺎﺕ ،ﺍﻳﻦ ﺑﺎﺭ
ﻧﻮﺑﺖ ﻓﻠﺴﻔﻪ ﺑﻮﺩ.
301 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
»ﺷﻲﮔﺮﺍﻳﻲ «1ﺭﻫﻴﺎﻓﺖ ﺟﺪﻳﺪﻱ ﺑﻮﺩ ﮐﻪ ﺑﺮﺍﻱ ﻣﺸﮑﻼﺕ ﺑﺎﻻ ﺭﺍﻩ ﺣﻞ ﺩﺍﺷﺖ .ﺍﻳﻦ
ﻣﻀﻤﻮﻥ ﺍﺯ ﺩﻧﻴﺎﻱ ﻓﻠﺴﻔﻪ ﺑﻪ ﺟﻬﺎﻥ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺁﻣﺪ ﻭ ﮐﻤﮏ ﮐﺮﺩ ﺗﺎ ﻣﻌﻀﻼﺕ ﺗﻮﻟﻴﺪ ﻭ
ﭘﺸﺘﻴﺒﺎﻧﻲ ﻧﺮﻡﺍﻓﺰﺍﺭ ﮐﻢﺗﺮ ﺷﻮﺩ .ﺩﺭ ﺩﻧﻴﺎﻱ ﻭﺍﻗﻌﻲ ،ﻳﮏ ﺷﻲ ﭼﻴﺰﻱ ﺍﺳﺖ ﮐﻪ ﻣﺸﺨﺼﺎﺗﻲ ﺩﺍﺭﺩ
ﻣﺜﻞ ﺍﺳﻢ ،ﺭﻧﮓ ،ﻭﺯﻥ ،ﺣﺠﻢ ﻭ . ...ﻫﻤﭽﻨﻴﻦ ﻫﺮ ﺷﻲ ﺭﻓﺘﺎﺭﻫﺎﻱ ﺷﻨﺎﺧﺘﻪ ﺷﺪﻩﺍﻱ ﻧﻴﺰ ﺩﺍﺭﺩ
ﻣﺜﻼ ﺩﺭ ﺑﺮﺍﺑﺮ ﻧﻴﺮﻭﻱ ﺟﺎﺫﺑﻪ ﻳﺎ ﺗﺎﺑﺶ ﻧﻮﺭ ﻳﺎ ﻭﺍﺭﺩ ﮐﺮﺩﻥ ﻓﺸﺎﺭ ﻭﺍﮐﻨﺶ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﺍﺷﻴﺎ ﺭﺍ
ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﻣﺸﺨﺼﺎﺕ ﻭ ﺭﻓﺘﺎﺭ ﺁﻥﻫﺎ ﺩﺳﺘﻪ ﺑﻨﺪﻱ ﮐﺮﺩ .ﺑﺮﺍﻱ ﻧﻤﻮﻧﻪ ،ﻣﻲﺗﻮﺍﻧﻴﻢ ﻫﻢۀ
ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﺩﺍﺭﺍﻱ ﺭﻓﺘﺎﺭ »ﺗﻨﻔﺲ« ﻫﺴﺘﻨﺪ ﺭﺍ ﺩﺭ ﺩﺳﺘﻪﺍﻱ ﺑﻪ ﻧﺎﻡ »ﺟﺎﻧﺪﺍﺭﺍﻥ« ﻗﺮﺍﺭ ﺩﻫﻴﻢ ﻭ ﻫﻢۀ
ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﭼﻨﻴﻦ ﺭﻓﺘﺎﺭﻱ ﺭﺍ ﻧﺪﺍﺭﻧﺪ ﺩﺭ ﺩﺳﺖۀ ﺩﻳﮕﺮﻱ ﺑﻪ ﻧﺎﻡ »ﺟﺎﻣﺪﺍﺕ« ﺑﮕﺬﺍﺭﻳﻢ .ﺑﺪﻳﻬﻲ
ﺍﺳﺖ ﮐﻪ ﺍﻋﻀﺎﻱ ﻫﺮ ﺩﺳﺘﻪ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺟﺰﻳﻴﺎﺕ ﺑﻴﺸﺘﺮ ﻭ ﺩﻗﻴﻖﺗﺮ ﺑﻪ ﺯﻳﺮ
ﺩﺳﺘﻪﻫﺎﻳﻲ ﺗﻘﺴﻴﻢ ﮐﻨﻴﻢ .ﻣﺜﻼ ﺩﺳﺖۀ ﺟﺎﻧﺪﺍﺭﺍﻥ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺯﻳﺮ ﺩﺳﺘﻪﻫﺎﻱ »ﮔﻴﺎﻫﺎﻥ« ﻭ
»ﺟﺎﻧﻮﺭﺍﻥ« ﻭ »ﺍﻧﺴﺎﻥﻫﺎ« ﺑﺨﺶﺑﻨﺪﻱ ﮐﻨﻴﻢ .ﺍﻟﺒﺘﻪ ﻫﺮ ﻋﻀﻮ ﺍﺯ ﺍﻳﻦ ﺩﺳﺘﻪﻫﺎ ،ﻋﻼﻭﻩ ﺑﺮ ﺍﻳﻦ ﮐﻪ
ﻣﺸﺨﺼﺎﺗﻲ ﻣﺸﺎﺑﻪ ﺳﺎﻳﺮ ﺍﻋﻀﺎ ﺩﺍﺭﺩ ،ﻣﺸﺨﺼﺎﺕ ﻣﻨﺤﺼﺮ ﺑﻪ ﻓﺮﺩﻱ ﻧﻴﺰ ﺩﺍﺭﺩ ﮐﻪ ﺍﻳﻦ ﺗﻔﺎﻭﺕ
ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﺑﺘﻮﺍﻧﻴﻢ ﺍﺷﻴﺎﻱ ﻫﻤﮕﻮﻥ ﺭﺍ ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﺗﻔﮑﻴﮏ ﮐﻨﻴﻢ .ﻣﺜﻼ ﻫﺮ ﺍﻧﺴﺎﻥ ﺩﺍﺭﺍﻱ
ﻧﺎﻡ ،ﺳﻦ ،ﻭﺯﻥ ،ﺭﻧﮓ ﻣﻮ ،ﺭﻧﮓ ﭼﺸﻢ ﻭ ﻣﺸﺨﺼﺎﺕ ﻓﺮﺩﻱ ﺩﻳﮕﺮ ﺍﺳﺖ ﮐﻪ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ
ﺍﻧﺴﺎﻥﻫﺎ ﺭﺍ ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﺗﻔﮑﻴﮏ ﮐﻨﻴﻢ ﻭ ﻫﺮ ﻓﺮﺩ ﺭﺍ ﺑﺸﻨﺎﺳﻴﻢ.
ﺩﺭ ﺑﺤﺚ ﺷﻲﮔﺮﺍﻳﻲ ﺑﻪ ﺩﺳﺘﻪﻫﺎ »ﮐﻼﺱ «2ﻣﻲﮔﻮﻳﻨﺪ ﻭ ﺑﻪ ﻧﻤﻮﻧﻪﻫﺎﻱ ﻫﺮ ﮐﻼﺱ
»ﺷﻲ «3ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ .ﻣﺸﺨﺼﺎﺕ ﻫﺮ ﺷﻲ ﺭﺍ »ﺻﻔﺖ «4ﻣﻲﻧﺎﻣﻨﺪ ﻭ ﺑﻪ ﺭﻓﺘﺎﺭﻫﺎﻱ ﻫﺮ ﺷﻲ
»ﻣﺘﺪ «5ﻣﻲﮔﻮﻳﻨﺪ .ﺩﺭﺧﺖ ﺳﺮﻭ ﻳﮏ ﺷﻲ ﺍﺯ ﮐﻼﺱ ﺩﺭﺧﺘﺎﻥ ﺍﺳﺖ ﮐﻪ ﺑﺮﺧﻲ ﺍﺯ ﺻﻔﺖﻫﺎﻱ
ﺁﻥ ﻋﺒﺎﺭﺕ ﺍﺳﺖ ﺍﺯ :ﻧﺎﻡ ،ﻃﻮﻝ ﻋﻤﺮ ،ﺍﺭﺗﻔﺎﻉ ،ﻗﻄﺮ ﻭ ...ﻭ ﺑﺮﺧﻲ ﺍﺯ ﻣﺘﺪﻫﺎﻱ ﺁﻥ ﻧﻴﺰ ﻋﺒﺎﺭﺗﻨﺪ
ﺍﺯ :ﻏﺬﺍ ﺳﺎﺧﺘﻦ ،ﺳﺒﺰ ﺷﺪﻥ ،ﺧﺸﮏ ﺷﺪﻥ ،ﺭﺷﺪ ﮐﺮﺩﻥ. ... ،
ﺍﻣﺎ ﺍﻳﻦ ﺷﻲﮔﺮﺍﻳﻲ ﭼﻪ ﮔﺮﻫﻲ ﺍﺯ ﮐﺎﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﻣﻲﮔﺸﺎﻳﺪ؟ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺷﻲﮔﺮﺍ
ﺑﺮ ﺳﻪ ﺳﺘﻮﻥ ﺍﺳﺘﻮﺍﺭ ﺍﺳﺖ:
ﺍﻟﻒ .ﺑﺴﺘﻪﺑﻨﺪﻱ :6ﻳﻌﻨﻲ ﺍﻳﻦ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ ﻣﺮﺗﺒﻂ ،ﺑﺎ ﻫﻢ ﺗﺮﮐﻴﺐ ﺷﻮﻧﺪ ﻭ ﺟﺰﻳﻴﺎﺕ
ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻣﺨﻔﻲ ﺷﻮﺩ .ﻭﻗﺘﻲ ﺩﺍﺩﻩﻫﺎﻱ ﻣﺮﺗﺒﻂ ﺩﺭ ﮐﻨﺎﺭ ﻫﻢ ﺑﺎﺷﻨﺪ ،ﺍﺳﺘﻘﻼﻝ ﮐﺪ ﻭ ﭘﻴﻤﺎﻧﻪﺍﻱ
ﮐﺮﺩﻥ ﺑﺮﻧﺎﻣﻪ ﺭﺍﺣﺖﺗﺮ ﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ ﻭ ﺗﻐﻴﻴﺮ ﺩﺭ ﻳﮏ ﺑﺨﺶ ﺍﺯ ﺑﺮﻧﺎﻣﻪ ،ﺳﺎﻳﺮ ﺑﺨﺶﻫﺎ ﺭﺍ
ﺩﭼﺎﺭ ﺍﺧﺘﻼﻝ ﻧﻤﻲﮐﻨﺪ .ﻣﺨﻔﻲ ﮐﺮﺩﻥ ﺟﺰﻳﻴﺎﺕ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﮐﻪ ﺑﻪ ﺁﻥ »ﺗﺠﺮﻳﺪ «1ﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ
ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻣﻨﻴﺖ ﮐﺪ ﺣﻔﻆ ﺷﻮﺩ ﻭ ﺑﺨﺶﻫﺎﻱ ﺑﻲﺍﻫﻤﻴﺖ ﻳﮏ ﻓﺮﺍﻳﻨﺪ ﺍﺯ ﺩﻳﺪ
ﺍﺳﺘﻔﺎﺩﻩﮐﻨﻨﺪۀ ﺁﻥ ﻣﺨﻔﻲ ﺑﺎﺷﺪ .ﺑﻪ ﺑﻴﺎﻥ ﺳﺎﺩﻩﺗﺮ ،ﻫﺮ ﺑﺨﺶ ﺍﺯ ﺑﺮﻧﺎﻣﻪ ﺗﻨﻬﺎ ﻣﻲﺗﻮﺍﻧﺪ ﺍﻃﻼﻋﺎﺕ
ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺑﺒﻴﻨﺪ ﻭ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺍﻃﻼﻋﺎﺕ ﻧﺎﻣﺮﺑﻮﻁ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﻭ ﺁﻥﻫﺎ ﺭﺍ
ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ .ﺩﺭ ﺑﺮﺧﻲ ﺍﺯ ﮐﺘﺎﺏﻫﺎ ﺍﺯ ﻭﺍﮊۀ »ﮐﭙﺴﻮﻟﻪ ﮐﺮﺩﻥ« ﻳﺎ »ﻣﺤﺼﻮﺭﺳﺎﺯﻱ« ﺑﻪ ﺟﺎﻱ
ﺑﺴﺘﻪﺑﻨﺪﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ.
ﺏ .ﻭﺭﺍﺛﺖ :2ﺩﺭ ﺩﻧﻴﺎﻱ ﻭﺍﻗﻌﻲ ،ﻭﺭﺍﺛﺖ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﻳﮏ ﺷﻲ ﻭﻗﺘﻲ ﻣﺘﻮﻟﺪ
ﻣﻲﺷﻮﺩ ،ﺧﺼﻮﺻﻴﺎﺕ ﻭ ﻭﻳﮋﮔﻲﻫﺎﻳﻲ ﺭﺍ ﺍﺯ ﻭﺍﻟﺪ ﺧﻮﺩ ﺑﻪ ﻫﻤﺮﺍﻩ ﺩﺍﺭﺩ ﻫﺮﭼﻨﺪ ﮐﻪ ﺍﻳﻦ ﺷﻲﺀ
ﺟﺪﻳﺪ ﺑﺎ ﻭﺍﻟﺪﺵ ﺩﺭ ﺑﺮﺧﻲ ﺍﺯ ﺟﺰﻳﻴﺎﺕ ﺗﻔﺎﻭﺕ ﺩﺍﺭﺩ .ﺩﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﻧﻴﺰ ﻭﺭﺍﺛﺖ ﺑﻪ ﻫﻤﻴﻦ
ﻣﻌﻨﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ .ﻳﻌﻨﻲ ﺍﺯ ﺭﻭﻱ ﻳﮏ ﺷﻲﺀ ﻣﻮﺟﻮﺩ ،ﺷﻲﺀ ﺟﺪﻳﺪﻱ ﺳﺎﺧﺘﻪ ﺷﻮﺩ ﮐﻪ
ﺻﻔﺎﺕ ﻭ ﻣﺘﺪﻫﺎﻱ ﺷﻲﺀ ﻭﺍﻟﺪﺵ ﺭﺍ ﺩﺍﺭﺍ ﺑﻮﺩﻩ ﻭﺍﻟﺒﺘﻪ ﺻﻔﺎﺕ ﻭ ﻣﺘﺪﻫﺎﻱ ﺧﺎﺹ ﺧﻮﺩ ﺭﺍ ﻧﻴﺰ
ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺍﻣﺘﻴﺎﺯ ﻭﺭﺍﺛﺖ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﺯ ﮐﺪﻫﺎﻱ ﻣﺸﺘﺮﮎ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ﻋﻼﻭﻩ
ﺑﺮ ﺍﻳﻦ ﮐﻪ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﮐﺪﻫﺎﻱ ﻗﺒﻠﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﺠﺪﺩ ﮐﺮﺩ ،ﺩﺭ ﺯﻣﺎﻥ ﻧﻴﺰ ﺻﺮﻓﻪﺟﻮﻳﻲ ﺷﺪﻩ ﻭ
ﺍﺳﺘﺤﮑﺎﻡ ﻣﻨﻄﻘﻲ ﺑﺮﻧﺎﻣﻪ ﻫﻢ ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ.
ﺝ .ﭼﻨﺪ ﺭﻳﺨﺘﻲ :3ﮐﻪ ﺑﻪ ﺁﻥ ﭼﻨﺪﺷﮑﻠﻲ ﻫﻢ ﻣﻲﮔﻮﻳﻨﺪ ﺑﻪ ﻣﻌﻨﺎﻱ ﻳﮏ ﭼﻴﺰ ﺑﻮﺩﻥ ﻭ
ﭼﻨﺪ ﺷﮑﻞ ﺩﺍﺷﺘﻦ ﺍﺳﺖ .ﭼﻨﺪﺭﻳﺨﺘﻲ ﺑﻴﺸﺘﺮ ﺩﺭ ﻭﺭﺍﺛﺖ ﻣﻌﻨﺎ ﭘﻴﺪﺍ ﻣﻲﮐﻨﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﮔﺮﭼﻪ
ﻫﺮ ﻓﺮﺯﻧﺪﻱ ﻣﺜﻞ ﻭﺍﻟﺪﺵ ﺍﺛﺮ ﺍﻧﮕﺸﺖ ﺩﺍﺭﺩ ،ﻭﻟﻲ ﺍﺛﺮ ﺍﻧﮕﺸﺖ ﻫﺮ ﺷﺨﺺ ﺑﺎ ﻭﺍﻟﺪﺵ ﻳﺎ ﻫﺮ
ﺷﺨﺺ ﺩﻳﮕﺮ ﻣﺘﻔﺎﻭﺕ ﺍﺳﺖ .ﭘﺲ ﺍﺛﺮ ﺍﻧﮕﺸﺖ ﺩﺭ ﺍﻧﺴﺎﻥﻫﺎ ﭼﻨﺪﺷﮑﻠﻲ ﺩﺍﺭﺩ.
ﺩﺭ ﺍﺩﺍﻣﻪ ﺑﻪ ﺷﮑﻞ ﻋﻤﻠﻲ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ ﮐﻪ ﭼﮕﻮﻧﻪ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﻔﺎﻫﻴﻢ ﻓﻮﻕ ﺭﺍ ﺩﺭ ﻗﺎﻟﺐ
ﺑﺮﻧﺎﻣﻪ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﮐﻨﻴﻢ.
ﺩﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ،ﻳﮏ ﮐﻼﺱ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺁﺭﺍﻳﻪﺍﻱ ﺗﺼﻮﺭ ﮐﺮﺩ ﮐﻪ ﺍﻋﻀﺎﻱ ﺁﻥ ﺍﺯ ﺍﻧﻮﻉ
ﻣﺨﺘﻠﻒ ﻭ ﻣﺘﻔﺎﻭﺗﻲ ﻫﺴﺘﻨﺪ ﻭ ﻫﻤﭽﻨﻴﻦ ﺗﻮﺍﺑﻊ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻋﻀﻮﻱ ﺍﺯ ﺁﻥ ﺁﺭﺍﻳﻪ ﺑﺎﺷﻨﺪ .ﻳﮏ
ﺷﻲ ﻧﻴﺰ ﻣﺘﻐﻴﺮﻱ ﺍﺳﺖ ﮐﻪ ﺍﺯ ﻧﻮﻉ ﻳﮏ ﮐﻼﺱ ﺍﺳﺖ .ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ ﻳﮏ ﺷﻲ ﺭﺍ ﻣﻲﺗﻮﺍﻥ
ﻣﻮﺟﻮﺩﻳﺖ ﻣﺴﺘﻘﻠﻲ ﺗﺼﻮﺭ ﮐﺮﺩ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ ﺧﺎﺹ ﺧﻮﺩﺵ ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﮐﻨﺪ ﻭ ﺗﻮﺍﺑﻊ
ﺧﺎﺹ ﺧﻮﺩﺵ ﺭﺍ ﺩﺍﺭﺩ .ﺗﻌﺎﺭﻳﻒ ﮐﻼﺱ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ ﺷﻴﺌﻲ ﮐﻪ ﺍﺯ ﺭﻭﻱ ﺁﻥ ﮐﻼﺱ
ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ ﭼﻪ ﺭﻓﺘﺎﺭﻱ ﺩﺍﺭﺩ .ﻭﺍﺿﺢ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻣﻨﻈﻮﺭ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺷﻲﮔﺮﺍﻳﻲ ،ﺍﺑﺘﺪﺍ
ﺑﺎﻳﺪ ﮐﻼﺱﻫﺎﻱ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﻣﺸﺨﺺ ﻭ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ .ﺳﭙﺲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ،
ﺍﺷﻴﺎﻳﻲ ﺍﺯ ﻧﻮﻉ ﺍﻳﻦ ﮐﻼﺱﻫﺎ ﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﻢ .ﺑﻘﻲۀ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺍﻳﻦ ﺍﺷﻴﺎ ﭘﻴﺶ ﻣﻲﺑﺮﻧﺪ.
9‐2ﺍﻋﻼﻥ ﻛﻼﺱﻫﺎ
ﮐﺪ ﺯﻳﺮ ﺍﻋﻼﻥ ﻳﮏ ﮐﻼﺱ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﺍﺯ ﺭﻭﻱ ﺍﻳﻦ ﮐﻼﺱ ﺳﺎﺧﺘﻪ
ﻣﻲﺷﻮﻧﺪ ،ﺍﻋﺪﺍﺩ ﮐﺴﺮﻱ )ﮔﻮﻳﺎ( ﻫﺴﺘﻨﺪ:
class Ratio
{ public:
;)void assign(int, int
;)(viod print
private:
;int num, den
;}
ﺍﻋﻼﻥ ﮐﻼﺱ ﺑﺎ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ classﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ،ﺳﭙﺲ ﻧﺎﻡ ﮐﻼﺱ ﻣﻲﺁﻳﺪ ﻭ ﺍﻋﻼﻥ
ﺍﻋﻀﺎﻱ ﮐﻼﺱ ﺩﺭﻭﻥ ﻳﮏ ﺑﻠﻮﮎ ﺍﻧﺠﺎﻡ ﻣﻲﺷﻮﺩ ﻭ ﺳﺮﺍﻧﺠﺎﻡ ﻳﮏ ﺳﻤﻴﮑﻮﻟﻦ ﺑﻌﺪ ﺍﺯ ﺑﻠﻮﮎ
ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻋﻼﻥ ﮐﻼﺱ ﭘﺎﻳﺎﻥ ﻳﺎﻓﺘﻪ ﺍﺳﺖ .ﮐﻼﺳﻲ ﮐﻪ ﺩﺭ ﮐﺪ ﺑﺎﻻ ﺍﻋﻼﻥ ﺷﺪﻩ،
Ratioﻧﺎﻡ ﺩﺍﺭﺩ .ﻣﻲﺗﻮﺍﻧﻴﻢ ﺗﺸﺨﻴﺺ ﺑﺪﻫﻴﻢ ﮐﻪ ﺩﺭ ﺑﻠﻮﮎ ﺍﻳﻦ ﮐﻼﺱ ﺩﻭ ﺗﺎﺑﻊ ﻭ ﺩﻭ ﻣﺘﻐﻴﺮ
ﺍﻋﻼﻥ ﺷﺪﻩ ﺍﺳﺖ .ﺗﻮﺍﺑﻊ )( assignﻭ )( printﺭﺍ ﺗﺎﺑﻊ ﻋﻀﻮ 1ﻣﻲﮔﻮﻳﻴﻢ ﺯﻳﺮﺍ ﺁﻥﻫﺎ
ﻋﻀﻮ ﺍﻳﻦ ﮐﻼﺱ ﻫﺴﺘﻨﺪ .ﺑﻪ ﺗﻮﺍﺑﻊ ﻋﻀﻮ» ،ﻣﺘﺪ« ﻳﺎ »ﺳﺮﻭﻳﺲ« ﻧﻴﺰ ﮔﻔﺘﻪ ﺷﺪﻩ ﺍﺳﺖ.
ﻣﺘﻐﻴﺮﻫﺎﻱ numﻭ denﺭﺍ ﻧﻴﺰ ﺩﺍﺩۀ ﻋﻀﻮ 2ﻣﻲﮔﻮﻳﻴﻢ .ﺑﻪ ﻏﻴﺮ ﺍﺯ ﺗﻮﺍﺑﻊ ﻭ ﺩﺍﺩﻩﻫﺎﻱ ﻋﻀﻮ،
ﺩﻭ ﻋﺒﺎﺭﺕ ﺩﻳﮕﺮ ﻧﻴﺰ ﺑﻪ ﭼﺸﻢ ﻣﻲﺧﻮﺭﺩ :ﻋﺒﺎﺭﺕ publicﻭ ﻋﺒﺎﺭﺕ . privateﻫﺮ
ﻋﻀﻮﻱ ﮐﻪ ﺫﻳﻞ ﻋﺒﺎﺭﺕ publicﺍﻋﻼﻥ ﺷﻮﺩ ،ﻳﮏ »ﻋﻀﻮ ﻋﻤﻮﻣﻲ «3ﻣﺤﺴﻮﺏ ﻣﻲﺷﻮﺩ
ﻭ ﻫﺮ ﻋﻀﻮﻱ ﮐﻪ ﺫﻳﻞ ﻋﺒﺎﺭﺕ privateﺍﻋﻼﻥ ﺷﻮﺩ ،ﻳﮏ »ﻋﻀﻮ ﺧﺼﻮﺻﻲ «4ﻣﺤﺴﻮﺏ
ﻣﻲﺷﻮﺩ .ﺗﻔﺎﻭﺕ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﺑﺎ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ
ﮐﻼﺱ ﺩﺭ ﺧﺎﺭﺝ ﺍﺯ ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﻫﺴﺘﻨﺪ ﺍﻣﺎ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﻓﻘﻂ ﺩﺭ ﺩﺍﺧﻞ
ﻫﻤﺎﻥ ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﻫﺴﺘﻨﺪ .ﺍﻳﻦ ﻫﻤﺎﻥ ﺧﺎﺻﻴﺘﻲ ﺍﺳﺖ ﮐﻪ »ﻣﺨﻔﻲﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ«
ﺭﺍ ﻣﻤﮑﻦ ﻣﻲﻧﻤﺎﻳﺪ .ﺩﺭ ﮐﻼﺱ ﻓﻮﻕ ،ﺗﻮﺍﺑﻊ ﺑﻪ ﺷﮑﻞ publicﻭ ﻣﺘﻐﻴﺮﻫﺎ ﺑﻪ ﺻﻮﺭﺕ
privateﻣﺸﺨﺺ ﺷﺪﻩﺍﻧﺪ.
ﺣﺎﻝ ﺑﺒﻴﻨﻴﻢ ﮐﻪ ﭼﻄﻮﺭ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﮐﻼﺱﻫﺎ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻭﺍﻗﻌﻲ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ .ﺑﻪ ﻣﺜﺎﻝ
ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ.
)(int main
;{ Ratio x
;Ratio y
;)x.assign(13, 7
;)y.assign(19,5
;" = cout << "x
;)(x.print
;cout << endl
;" = cout << "y
;)(y.print
;cout << endl
}
)(void Ratio::print
;{ cout << num << '/' << den
}
x = 13/7
y = 19/5
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ،ﺍﺑﺘﺪﺍ ﮐﻼﺱ Ratioﺍﻋﻼﻥ ﺷﺪﻩ .ﺳﭙﺲ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺩﻭ ﻣﺘﻐﻴﺮ
ﺑﻪ ﻧﺎﻡﻫﺎﻱ xﻭ yﺍﺯ ﻧﻮﻉ Ratioﺍﻋﻼﻥ ﺷﺪﻩﺍﻧﺪ .ﺑﻪ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﺍﺯ ﻧﻮﻉ ﻳﮏ ﮐﻼﺱ ﺑﺎﺷﺪ
ﻳﮏ »ﺷﻲ« ﻣﻲﮔﻮﻳﻴﻢ .ﭘﺲ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺩﻭ ﺷﻲ ﺑﻪ ﻧﺎﻡﻫﺎﻱ xﻭ yﺩﺍﺭﻳﻢ .ﻫﺮ ﻳﮏ ﺍﺯ ﺍﻳﻦ
ﺍﺷﻴﺎ ﺩﺍﺭﺍﻱ ﺩﻭ ﺩﺍﺩۀ ﺧﺼﻮﺻﻲ ﻣﺨﺼﻮﺹ ﺑﻪ ﺧﻮﺩ ﻫﺴﺘﻨﺪ ﻭ ﻫﻤﭽﻨﻴﻦ ﺗﻮﺍﻧﺎﻳﻲ ﺩﺳﺘﻴﺎﺑﻲ ﺑﻪ
x y ﺩﻭ ﺗﺎﺑﻊ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﺭﺍ ﻧﻴﺰ ﺩﺍﺭﻧﺪ .ﺍﻳﻦ ﺩﻭ ﺷﻲ ﺭﺍ
num 13 num 13 ﻣﻲ ﺗﻮﺍﻥ ﻣﺎﻧﻨﺪ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﺗﺼﻮﺭ ﻧﻤﻮﺩ.
den 7 den 7
Ratio Ratio ﻋﺒﺎﺭﺕ ;) x.assign(13,7ﻣﻮﺟﺐ
ﻣﻲﺷﻮﺩ ﮐﻪ ﺗﺎﺑﻊ ﻋﻀﻮ )( assignﺑﺮﺍﻱ ﺷﻲﺀ
xﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ .ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﮐﻼﺱ ﺭﺍ ﻓﻘﻂ ﺑﻪ ﺍﻳﻦ ﻃﺮﻳﻖ ﻣﻲﺗﻮﺍﻥ ﻓﺮﺍﺧﻮﺍﻧﻲ ﮐﺮﺩ ﻳﻌﻨﻲ
ﺍﺑﺘﺪﺍ ﻧﺎﻡ ﺷﻲ ﻭ ﺳﭙﺲ ﻳﮏ ﻧﻘﻄﻪ ﻭ ﭘﺲ ﺍﺯ ﺁﻥ ،ﺗﺎﺑﻊ ﻋﻀﻮ ﻣﻮﺭﺩ ﻧﻈﺮ .ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ ،ﺷﻲﺀ
1
ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﻧﺎﻣﻴﻢ .ﺩﺭ ﻋﺒﺎﺭﺕ ;) x.assign(13,7ﺷﻲﺀ x ﻣﺬﮐﻮﺭ ﺭﺍ ﻣﺎﻟﮏ
ﻋﻀﻮ ﺗﺎﺑﻊ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﺎﻟﮏ
Ratio x )( assignﺍﺳﺖ ﻭ ﺍﻳﻦ ﺗﺎﺑﻊ
num 13
)(assign
den
ﺭﻭﻱ ﺷﻲﺀ xﻋﻤﻠﻴﺎﺗﻲ ﺍﻧﺠﺎﻡ ﻣﻲ
7
)(print
Ratio ﺩﻫﺪ .ﺗﺼﻮﻳﺮ ﻣﻘﺎﺑﻞ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ
ﺑﻴﺎﻥ ﻣﻲﮐﻨﺪ.
ﺗﻌﺮﻳﻒ ﺩﻭ ﺗﺎﺑﻊ ﻋﻀﻮ )( assignﻭ )( printﺩﺭ ﺧﻄﻮﻁ ﺍﻧﺘﻬﺎﻳﻲ ﺑﺮﻧﺎﻣﻪ ﺁﻣﺪﻩ
ﺍﻣﺎ ﻧﺎﻡ ﮐﻼﺱ Ratioﺑﻪ ﻫﻤﺮﺍﻩ ﻋﻤﻠﮕﺮ ﺟﺪﺍﺳﺎﺯﻱ ﺩﺍﻣﻨﻪ ::ﻗﺒﻞ ﺍﺯ ﻧﺎﻡ ﻫﺮ ﺗﺎﺑﻊ ﺫﮐﺮ ﺷﺪﻩ
ﺍﺳﺖ .ﺩﻟﻴﻞ ﺍﻳﻦ ﮐﺎﺭ ﺁﻥ ﺍﺳﺖ ﮐﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﻣﺘﻮﺟﻪ ﺷﻮﺩ ﮐﻪ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ،ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ
Ratioﻫﺴﺘﻨﺪ ﻭ ﺍﺯ ﻗﻮﺍﻧﻴﻦ ﺁﻥ ﮐﻼﺱ ﭘﻴﺮﻭﻱ ﻣﻲﮐﻨﻨﺪ.
ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺗﻮﺿﻴﺤﺎﺕ ﺑﺎﻻ ،ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ 9‐1ﺭﺍ ﺗﻔﺴﻴﺮ ﮐﻨﻴﻢ .ﺍﺑﺘﺪﺍ ﮐﻼﺱ
1 – Owner
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 306
Ratioﺍﻋﻼﻥ ﺷﺪﻩ ﺍﺳﺖ .ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺩﻭ ﺷﻲﺀ xﻭ yﺍﺯ ﺭﻭﻱ ﺍﻳﻦ ﮐﻼﺱ ﺳﺎﺧﺘﻪ
ﺷﺪﻩ ﮐﻪ ﻫﺮ ﮐﺪﺍﻡ ﺩﺍﺭﺍﻱ ﺩﻭ ﻋﻀﻮ ﺩﺍﺩۀ ﺧﺼﻮﺻﻲ ﺑﻪ ﻧﺎﻡﻫﺎﻱ numﻭ denﻫﺴﺘﻨﺪ .ﺑﺎ
ﻓﺮﺍﺧﻮﺍﻧﻲ ;) x.assign(13,7ﻣﻘﺎﺩﻳﺮ 7ﻭ 13ﺑﻪ ﺗﺮﺗﻴﺐ ﺩﺭﻭﻥ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ
numﻭ denﺍﺯ ﺷﻲﺀ xﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺑﺎ ﻓﺮﺍﺧﻮﺍﻧﻲ ;) y.assign(19,5ﻣﻘﺎﺩﻳﺮ
19ﻭ 5ﺑﻪ ﺗﺮﺗﻴﺐ ﺩﺭﻭﻥ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ numﻭ denﺍﺯ ﺷﻲﺀ yﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ.
ﺳﭙﺲ ﺑﺎ ﻓﺮﺍﺧﻮﺍﻧﻲ ;)( x.printﻭ ;)( y.printﻣﻘﺎﺩﻳﺮ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ
ﺷﻲﺀ xﻭ ﺷﻲﺀ yﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ .ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺩﻭ ﺷﻲﺀ xﻭ yﮐﺎﻣﻼ ﺍﺯ
ﻳﮑﺪﻳﮕﺮ ﻣﺠﺰﺍ ﻫﺴﺘﻨﺪ ﻭ ﻫﺮ ﮐﺪﺍﻡ ﺩﺍﺩﻩﻫﺎﻱ ﺧﺎﺹ ﺧﻮﺩ ﺭﺍ ﺩﺍﺭﺩ.
ﭼﻮﻥ ﻣﺘﻐﻴﺮﻫﺎﻱ numﻭ denﺍﺯ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﻫﺴﺘﻨﺪ ،ﻧﻤﻲﺗﻮﺍﻧﻴﻢ ﺩﺭﻭﻥ
ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﻪ ﺁﻥﻫﺎ ﻣﺴﺘﻘﻴﻤﺎ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﻴﻢ .ﺍﻳﻦ ﮐﺎﺭ ﻓﻘﻂ ﺍﺯ ﻃﺮﻳﻖ ﺗﻮﺍﺑﻊ )( assignﻭ
)( printﻣﻴﺴﺮ ﺍﺳﺖ ﺯﻳﺮﺍ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﻫﺴﺘﻨﺪ ﻭ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﻪ ﺍﻋﻀﺎﻱ
ﺧﺼﻮﺻﻲ ﻫﻤﺎﻥ ﮐﻼﺱ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﻨﺪ.
ﮐﻼﺱ Ratioﮐﻪ ﺩﺭ ﺑﺎﻻ ﺍﻋﻼﻥ ﺷﺪ ،ﮐﺎﺭﺍﻳﻲ ﺯﻳﺎﺩﻱ ﻧﺪﺍﺭﺩ .ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﻓﺰﻭﺩﻥ
ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺩﻳﮕﺮﻱ ،ﮐﺎﺭﺍﻳﻲ ﺍﻳﻦ ﮐﻼﺱ ﺭﺍ ﺑﻬﺒﻮﺩ ﺩﻫﻴﻢ.
)(int main
;{ Ratio x
;)x.assign(22, 7
;" = cout << "x
;)(x.print
307 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
)(double Ratio::convert
;{ return double(num)/den
}
)(void Ratio::invert
;{ int temp = num
;num = den
;den = temp
}
)(void Ratio::print
;{ cout << num << '/' << den
}
x = 22/7 = 3.14286
1/x = 7/22
ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﺑﺎ ﺍﻓﺰﻭﺩﻥ ﺗﻮﺍﺑﻊ ﻋﻀﻮ )( convertﻭ )( invertﮐﺎﺭﺍﻳﻲ ﺍﺷﻴﺎﻱ ﮐﻼﺱ
Ratioﺑﻬﺒﻮﺩ ﻳﺎﻓﺘﻪ ﺍﺳﺖ .ﺍﻳﻦ ﺩﻭ ﺗﺎﺑﻊ ﻋﻀﻮ ﻧﻴﺰ ﺑﻪ ﺻﻮﺭﺕ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﺗﻌﺮﻳﻒ
ﺷﺪﻩﺍﻧﺪ ﺗﺎ ﺑﺘﻮﺍﻥ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﻪ ﺁﻥﻫﺎ ﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺷﺖ .ﺗﺎﺑﻊ )( convertﻋﺪﺩ
ﮐﺴﺮﻱ ﺩﺭﻭﻥ ﺷﻲﺀ ﻣﺎﻟﮏ ﺭﺍ ﺑﻪ ﻳﮏ ﻋﺪﺩ ﺍﻋﺸﺎﺭﻱ ﺗﺒﺪﻳﻞ ﻣﻲﮐﻨﺪ ﻭ ﺗﺎﺑﻊ )( invertﻧﻴﺰ
ﻋﺪﺩ ﮐﺴﺮﻱ ﺩﺭﻭﻥ ﺷﻲﺀ ﻣﺎﻟﮏ ﺭﺍ ﻣﻌﮑﻮﺱ ﻣﻲﻧﻤﺎﻳﺪ.
ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻗﺎﺑﻠﻴﺖﻫﺎﻱ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﺷﻲﮔﺮﺍ ﺭﺍ ﺑﻬﺒﻮﺩ ﻳﺎ ﺗﻐﻴﻴﺮ
ﺩﻫﻴﻢ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﻣﺠﺒﻮﺭ ﺑﺎﺷﻴﻢ ﺗﻐﻴﻴﺮﺍﺕ ﺍﺳﺎﺳﻲ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻗﺒﻠﻲ ﺍﻳﺠﺎﺩ ﻧﻤﺎﻳﻴﻢ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 308
ﺍﻋﻼﻥ ﻓﻮﻕ ﺭﺍ ﺑﺎ ﺍﻋﻼﻥ ﮐﻼﺱ Ratioﺩﺭ ﻣﺜﺎﻝ 9‐2ﻣﻘﺎﻳﺴﻪ ﻧﻤﺎﻳﻴﺪ .ﺩﺭ ﺍﻋﻼﻥ ﻓﻮﻕ،
ﻫﻢۀ ﺗﻌﺎﺭﻳﻒ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺩﺭﻭﻥ ﺧﻮﺩ ﮐﻼﺱ ﺁﻣﺪﻩ ﺍﺳﺖ ﻭ ﺩﻳﮕﺮ ﺍﺣﺘﻴﺎﺟﻲ ﺑﻪ ﻋﻤﻠﮕﺮ
ﺟﺪﺍﺳﺎﺯﻱ ﺩﺍﻣﻨﻪ ::ﻧﻴﺴﺖ .ﻣﻤﮑﻦ ﺍﺳﺖ ﺍﻋﻼﻥ ﻣﺬﮐﻮﺭ ﺧﻮﺍﻧﺎﺗﺮ ﺍﺯ ﺍﻋﻼﻥ ﻣﺜﺎﻝ 9‐2ﺑﺎﺷﺪ
ﺍﻣﺎ ﺍﻳﻦ ﺭﻭﺵ ﺩﺭ ﺷﻲﮔﺮﺍﻳﻲ ﭘﺴﻨﺪﻳﺪﻩ ﻧﻴﺴﺖ .ﻏﺎﻟﺒﺎ ﺗﺮﺟﻴﺢ ﻣﻲﺩﻫﻨﺪ ﮐﻪ ﺍﺯ ﻋﻤﻠﮕﺮ
ﺟﺪﺍﺳﺎﺯﻱ ﺩﺍﻣﻨﻪ ﻭ ﺗﻌﺮﻳﻒﻫﺎﻱ ﺧﺎﺭﺝ ﺍﺯ ﮐﻼﺱ ﺑﺮﺍﻱ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻨﺪ .ﺩﺭ
ﺣﻘﻴﻘﺖ ﺑﺪﻥۀ ﺗﻮﺍﺑﻊ ﺍﻏﻠﺐ ﺩﺭ ﻓﺎﻳﻞ ﺟﺪﺍﮔﺎﻧﻪﺍﻱ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﻭ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻞ ﮐﺎﻣﭙﺎﻳﻞ
ﻣﻲﺷﻮﺩ .ﺍﻳﻦ ﺑﺎ ﺍﺻﻞ ﭘﻨﻬﺎﻥﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ ﻫﻤﺴﻮﻳﻲ ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﺩ .ﺩﺭ ﭘﺮﻭﮊﻩﻫﺎﻱ ﮔﺮﻭﻫﻲ
ﺗﻮﻟﻴﺪ ﻧﺮﻡﺍﻓﺰﺍﺭ ،ﻣﻌﻤﻮﻻ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﮐﻼﺱﻫﺎ ﺑﻪ ﻋﻬﺪۀ ﻣﻔﺴﺮﻳﻦ ﺍﺳﺖ ﻭ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﮐﻼﺱﻫﺎ
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﺮ ﻋﻬﺪۀ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﮔﺬﺍﺷﺘﻪ ﻣﻲﺷﻮﺩ .ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﻓﻘﻂ ﻣﺎﻳﻠﻨﺪ ﺑﺪﺍﻧﻨﺪ
ﮐﻪ ﮐﻼﺱﻫﺎ ﭼﻪ ﮐﺎﺭﻫﺎﻳﻲ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﮑﻨﻨﺪ ﻭ ﺍﺻﻼ ﻋﻼﻗﻪﺍﻱ ﻧﺪﺍﺭﻧﺪ ﮐﻪ ﺑﺪﺍﻧﻨﺪ ﮐﻼﺱﻫﺎ
309 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
ﭼﻄﻮﺭ ﺍﻳﻦ ﮐﺎﺭﻫﺎ ﺭﺍ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﻨﺪ )ﻧﺒﺎﻳﺪ ﻫﻢ ﺑﺪﺍﻧﻨﺪ( .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﻣﻲﺩﺍﻧﻨﺪ ﺩﺭ
ﺩﺳﺘﻮﺭ ﺗﻘﺴﻴﻢ ﻳﮏ ﻋﺪﺩ ﺍﻋﺸﺎﺭﻱ ﺑﺮ ﻳﮏ ﻋﺪﺩ ﺍﻋﺸﺎﺭﻱ ﺩﻳﮕﺮ ،ﺣﺎﺻﻞ ﭼﻪ ﺧﻮﺍﻫﺪ ﺑﻮﺩ ﺍﻣﺎ
ﻧﻤﻲﺩﺍﻧﻨﺪ ﮐﻪ ﻋﻤﻞ ﺗﻘﺴﻴﻢ ﭼﮕﻮﻧﻪ ﺍﻧﺠﺎﻡ ﻣﻲﺷﻮﺩ ﻭ ﺍﺯ ﭼﻪ ﺍﻟﮕﻮﺭﻳﺘﻤﻲ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺒﻪ ﭘﺎﺳﺦ
ﻭ ﺗﻌﻴﻴﻦ ﺩﻗﺖ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ .ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﻣﺠﺎﻟﻲ ﺑﺮﺍﻱ ﭘﺮﺩﺍﺧﺘﻦ ﺑﻪ ﺍﻳﻦ ﺟﺰﻳﻴﺎﺕ
ﻧﺪﺍﺭﻧﺪ ﻭ ﺍﻳﻦ ﻣﻄﺎﻟﺐ ﺍﺻﻼ ﺑﺮﺍﻱ ﺁﻥﻫﺎ ﺍﻫﻤﻴﺖ ﻧﺪﺍﺭﺩ .ﻓﻘﻂ ﮐﺎﻓﻲ ﺍﺳﺖ ﺍﺯ ﺻﺤﻴﺢ ﺑﻮﺩﻥ
ﻧﺘﻴﺠﻪ ﻣﻄﻤﺌﻦ ﺑﺎﺷﻨﺪ .ﺑﺎ ﺭﻋﺎﻳﺖ ﮐﺮﺩﻥ ﺍﺻﻞ ﭘﻨﻬﺎﻥﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ ،ﻫﻢ ﺗﻘﺴﻴﻢ ﮐﺎﺭﻫﺎ ﺑﻴﻦ
ﺍﻓﺮﺍﺩ ﮔﺮﻭﻩ ﺑﻬﺘﺮ ﺍﻧﺠﺎﻡ ﻣﻲﺷﻮﺩ ﻭ ﻫﻢ ﺍﺯ ﺩﺭﮔﻴﺮﮐﺮﺩﻥ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﺎ ﺟﺰﺋﻴﺎﺕ ﻧﺎﻣﺮﺑﻮﻁ
ﺍﺟﺘﻨﺎﺏ ﺷﺪﻩ ﻭ ﺳﺎﺧﺘﺎﺭ ﻣﻨﻄﻘﻲ ﺑﺮﻧﺎﻣﻪ ﻣﺴﺘﺤﮑﻢﺗﺮ ﻣﻲﺷﻮﺩ.
ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺗﻌﺎﺭﻳﻒ ﺍﺯ ﺍﻋﻼﻥ ﮐﻼﺱ ﺟﺪﺍ ﺑﺎﺷﺪ ،ﺑﻪ ﺑﺨﺶ ﺍﻋﻼﻥ ﮐﻼﺱ ﺭﺍﺑﻂ
ﮐﻼﺱ 1ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ ﻭ ﺑﻪ ﺑﺨﺶ ﺗﻌﺎﺭﻳﻒ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ 2ﻣﻲﮔﻮﻳﻨﺪ .ﺭﺍﺑﻂ ﮐﻼﺱ ﺑﺨﺸﻲ
ﺍﺳﺖ ﮐﻪ ﺩﺭ ﺍﺧﺘﻴﺎﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﻭ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﺩﺭ ﻓﺎﻳﻞ ﻣﺴﺘﻘﻠﻲ ﻧﮕﻬﺪﺍﺭﻱ
ﻣﻲﺷﻮﺩ.
9‐3ﺳﺎﺯﻧﺪﻩﻫﺎ
ﮐﻼﺱ Ratioﮐﻪ ﺩﺭ ﻣﺜﺎﻝ 9‐1ﺍﻋﻼﻥ ﺷﺪ ﺍﺯ ﺗﺎﺑﻊ )( assignﺑﺮﺍﻱ
ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﻪ ﺍﺷﻴﺎﻱ ﺧﻮﺩ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ .ﻳﻌﻨﻲ ﭘﺲ ﺍﺯ ﺍﻋﻼﻥ ﻳﮏ ﺷﻲ ﺍﺯ ﻧﻮﻉ Ratio
ﺑﺎﻳﺪ ﺗﺎﺑﻊ )( assignﺭﺍ ﺑﺮﺍﻱ ﺁﻥ ﺷﻲ ﻓﺮﺍ ﺑﺨﻮﺍﻧﻴﻢ ﺗﺎ ﺑﺘﻮﺍﻧﻴﻢ ﻣﻘﺎﺩﻳﺮﻱ ﺭﺍ ﺑﻪ ﺍﻋﻀﺎﻱ
ﺩﺍﺩﻩﺍﻱ ﺁﻥ ﺷﻲ ﻧﺴﺒﺖ ﺩﻫﻴﻢ .ﻫﻨﮕﺎﻡ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻧﻮﺍﻉ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻣﺜﻞ intﻭ float
ﻣﻲﺗﻮﺍﻧﻴﻢ ﻫﻢﺯﻣﺎﻥ ﺑﺎ ﺍﻋﻼﻥ ﻳﮏ ﻣﺘﻐﻴﺮ ،ﺁﻥ ﺭﺍ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﮐﻨﻴﻢ ﻣﺜﻞ :
;int n=22
;float x=33.0
ﻣﻨﻄﻘﻲﺗﺮ ﺧﻮﺍﻫﺪ ﺑﻮﺩ ﺍﮔﺮ ﺑﺘﻮﺍﻧﻴﻢ ﺑﺮﺍﻱ ﮐﻼﺱ Ratioﻧﻴﺰ ﺑﻪ ﻫﻤﻴﻦ ﺷﻴﻮﻩ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ
ﺗﺪﺍﺭﮎ ﺑﺒﻴﻨﻴﻢ C++ .ﺍﻳﻦ ﺍﻣﮑﺎﻥ ﺭﺍ ﻓﺮﺍﻫﻢ ﮐﺮﺩﻩ ﮐﻪ ﺑﺮﺍﻱ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺑﻪ ﺍﺷﻴﺎﻱ ﻳﮏ
ﮐﻼﺱ ،ﺍﺯ ﺗﺎﺑﻊ ﺧﺎﺻﻲ ﺑﻪ ﻧﺎﻡ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ 3ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ .ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻳﮏ ﺗﺎﺑﻊ ﻋﻀﻮ
ﺍﺳﺖ ﮐﻪ ﺩﺭ ﻫﻨﮕﺎﻡ ﺍﻋﻼﻥ ﻳﮏ ﺷﻲ ،ﺧﻮﺩ ﺑﻪ ﺧﻮﺩ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ .ﻧﺎﻡ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺑﺎﻳﺪ
ﺑﺎ ﻧﺎﻡ ﮐﻼﺱ ﻳﮑﺴﺎﻥ ﺑﺎﺷﺪ ﻭ ﺑﺪﻭﻥ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﻌﺮﻳﻒ ﺷﻮﺩ .ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ
ﭼﻄﻮﺭ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺟﺎﻱ ﺗﺎﺑﻊ )( assignﺍﺯ ﻳﮏ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ.
)(int main
;){ Ratio x(13,7) , y(19,5
;" = cout << "x
;)(x.print
;" = cout << "and y
;)(y.print
}
x = 13/7 and y = 19/5
ﺩﺭ ﮐﺪ ﺑﺎﻻ ﺑﻪ ﻣﺤﺾ ﺍﻳﻦ ﮐﻪ ﺷﻲﺀ xﺍﻋﻼﻥ ﺷﺪ ،ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﻓﺮﺍﺧﻮﺍﻧﻲ
ﺷﺪﻩ ﻭ ﻣﻘﺎﺩﻳﺮ 13ﻭ 7ﺑﻪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ nﻭ dﺁﻥ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ .ﺗﺎﺑﻊ ﺍﻳﻦ ﻣﻘﺎﺩﻳﺮ ﺭﺍ ﺑﻪ
ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ numﻭ denﺗﺨﺼﻴﺺ ﻣﻲﺩﻫﺪ .ﻟﺬﺍ ﺍﻋﻼﻥ
;)Ratio x(13,7), y(19,5
ﻭﻇﻴﻒۀ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺣﺎﻓﻆۀ ﻻﺯﻡ ﺭﺍ ﺑﺮﺍﻱ ﺷﻲﺀ ﺟﺪﻳﺪ ﺗﺨﺼﻴﺺ ﺩﺍﺩﻩ
ﻭ ﺁﻥ ﺭﺍ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﻤﺎﻳﺪ ﻭ ﺑﺎ ﺍﺟﺮﺍﻱ ﻭﻇﺎﻳﻔﻲ ﮐﻪ ﺩﺭ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻣﻨﻈﻮﺭ ﺷﺪﻩ ،ﺷﻲﺀ
ﺟﺪﻳﺪ ﺭﺍ ﺑﺮﺍﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺁﻣﺎﺩﻩ ﮐﻨﺪ.
311 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
ﻫﺮ ﮐﻼﺱ ﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪﻳﻦ ﺳﺎﺯﻧﺪﻩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺩﺭ ﺣﻘﻴﻘﺖ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻣﻲﺗﻮﺍﻧﺪ
ﭼﻨﺪﺷﮑﻠﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ )ﺑﺨﺶ 5‐13ﺭﺍ ﺑﺒﻴﻨﻴﺪ( .ﺍﻳﻦ ﺳﺎﺯﻧﺪﻩﻫﺎ ،ﺍﺯ ﻃﺮﻳﻖ ﻓﻬﺮﺳﺖ
ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﺗﻔﮑﻴﮏ ﻣﻲﺷﻮﻧﺪ .ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﮕﺎﻩ ﮐﻨﻴﺪ.
)(int main
;){ Ratio x, y(4), z(22,7
;" = cout << "x
;)(x.print
;" = cout << "\ny
;)(y.print
;" = cout << "\nz
;)(z.print
}
x = 0/1
y = 4/1
z = 22/7
ﺍﻳﻦ ﻧﺴﺨﻪ ﺍﺯ ﻛﻼﺱ Ratioﺳﻪ ﺳﺎﺯﻧﺪﻩ ﺩﺍﺭﺩ :ﺍﻭﻟﻲ ﻫﻴﭻ ﭘﺎﺭﺍﻣﺘﺮﻱ ﻧﺪﺍﺭﺩ ﻭ ﺷﻲﺀ ﺍﻋﻼﻥ
ﺷﺪﻩ ﺭﺍ ﺑﺎ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ 0ﻭ 1ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﮐﻨﺪ .ﺩﻭﻣﻴﻦ ﺳﺎﺯﻧﺪﻩ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ
intﺩﺍﺭﺩ ﻭ ﺷﻲﺀ ﺍﻋﻼﻥ ﺷﺪﻩ ﺭﺍ ﻃﻮﺭﻱ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﮐﻨﺪ ﮐﻪ ﺣﺎﺻﻞ ﮐﺴﺮ ﺑﺎ ﻣﻘﺪﺍﺭ ﺁﻥ
ﭘﺎﺭﺍﻣﺘﺮ ﺑﺮﺍﺑﺮ ﺑﺎﺷﺪ .ﺳﻮﻣﻴﻦ ﺳﺎﺯﻧﺪﻩ ﻧﻴﺰ ﻫﻤﺎﻥ ﺳﺎﺯﻧﺪۀ ﻣﺜﺎﻝ 9‐4ﺍﺳﺖ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 312
ﻳﮏ ﮐﻼﺱ ﻣﻲﺗﻮﺍﻧﺪ ﺳﺎﺯﻧﺪﻩﻫﺎﻱ ﻣﺨﺘﻠﻔﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺳﺎﺩﻩﺗﺮﻳﻦ ﺁﻥﻫﺎ ،ﺳﺎﺯﻧﺪﻩﺍﻱ
ﺍﺳﺖ ﮐﻪ ﻫﻴﭻ ﭘﺎﺭﺍﻣﺘﺮﻱ ﻧﺪﺍﺭﺩ .ﺑﻪ ﺍﻳﻦ ﺳﺎﺯﻧﺪﻩ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ 1ﻣﻲﮔﻮﻳﻨﺪ .ﺍﮔﺮ ﺩﺭ ﻳﮏ
ﮐﻼﺱ ،ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ﺫﮐﺮ ﻧﺸﻮﺩ ،ﮐﺎﻣﭙﺎﻳﻠﺮ ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﺁﻥ ﺭﺍ ﺑﺮﺍﻱ ﮐﻼﺱ ﻣﺬﮐﻮﺭ
ﺍﻳﺠﺎﺩ ﻣﻲﮐﻨﺪ .ﺩﺭ ﻣﺜﺎﻝ 9‐1ﮐﻪ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ﻣﻨﻈﻮﺭ ﻧﮑﺮﺩﻩﺍﻳﻢ ،ﻳﮑﻲ ﺑﻪ ﻃﻮﺭ
ﺧﻮﺩﮐﺎﺭ ﺑﺮﺍﻱ ﺁﻥ ﮐﻼﺱ ﻣﻨﻈﻮﺭ ﺧﻮﺍﻫﺪ ﺷﺪ.
ﺩﺭ ﺩﺳﺘﻮﺭ ﺑﺎﻻ ،ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎﻱ ﺟﺎﻳﮕﺰﻳﻨﻲ ﮐﻪ ﻗﺒﻼ ﺩﺭ ﺑﺪﻥۀ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻗﺮﺍﺭ ﺩﺍﺷﺘﻨﺪ،
ﺍﮐﻨﻮﻥ ﺩﺭﻭﻥ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺟﺎﻱ ﺩﺍﺩﻩ ﺷﺪﻩﺍﻧﺪ )ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﺎ ﺣﺮﻭﻑ ﺗﻴﺮﻩﺗﺮ
ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ( .ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﺎ ﻳﮏ ﻋﻼﻣﺖ ﮐﻮﻟﻦ :ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ،ﺑﺪﻥۀ ﺗﺎﺑﻊ
ﻧﻴﺰ ﺩﺭ ﺍﻧﺘﻬﺎ ﻣﻲﺁﻳﺪ )ﮐﻪ ﺍﮐﻨﻮﻥ ﺧﺎﻟﻲ ﺍﺳﺖ( .ﺩﺭ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ،ﺳﺎﺯﻧﺪﻩﻫﺎﻱ ﮐﻼﺱ Ratio
ﺭﺍ ﺑﺎ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺧﻼﺻﻪ ﮐﺮﺩﻩﺍﻳﻢ.
)(int main
;){ Ratio x, y(4), z(22,7
}
ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ ﻭﻗﺘﻲ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﺷﻮﺩ ،ﺷﻲﺀ xﺑﺮﺍﺑﺮ ﺑﺎ 0/1ﻭ ﺷﻲﺀ yﺑﺮﺍﺑﺮ ﺑﺎ 4/1ﻭ
ﺷﻲﺀ zﺑﺮﺍﺑﺮ ﺑﺎ 22/7ﺧﻮﺍﻫﺪ ﺷﺪ.
ﻗﺒﻼ ﺩﺭ ﺑﺨﺶ 5‐15ﮔﻔﺘﻴﻢ ﮐﻪ ﻭﻗﺘﻲ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﻭﺍﻗﻌﻲ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﻧﺸﻮﺩ ،ﺑﻪ
ﺟﺎﻱ ﺁﻥﻫﺎ ﻣﻘﺎﺩﻳﺮ ﭘﻴﺶﻓﺮﺽ ﺩﺭ ﺗﺎﺑﻊ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﻧﺪ .ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ،ﭘﺎﺭﺍﻣﺘﺮ n
ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ 0ﻭ ﭘﺎﺭﺍﻣﺘﺮ dﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ 1ﺍﺳﺖ .ﻭﻗﺘﻲ ﺷﻲﺀ xﺍﺯ
ﻧﻮﻉ Ratioﻭ ﺑﺪﻭﻥ ﻫﻴﭻ ﭘﺎﺭﺍﻣﺘﺮﻱ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ ،ﺍﻳﻦ ﻣﻘﺎﺩﻳﺮ ﭘﻴﺶﻓﺮﺽ ﺑﻪ x.nﻭ
x.dﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﻨﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ x.num=0ﻭ x.den=1ﺧﻮﺍﻫﺪ ﺑﻮﺩ .ﻫﻨﮕﺎﻣﻲ ﮐﻪ
ﺷﻲﺀ yﻓﻘﻂ ﺑﺎ ﻣﻘﺪﺍﺭ ﺍﺭﺳﺎﻟﻲ 4ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ y.num=4 ،ﺧﻮﺍﻫﺪ ﺷﺪ ﻭﻟﻲ ﭼﻮﻥ
ﭘﺎﺭﺍﻣﺘﺮ ﺩﻭﻡ ﺩﺭ ﺍﻋﻼﻥ ﺷﻲﺀ yﺫﮐﺮ ﻧﺸﺪﻩ ،ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ 1ﺩﺭ y.denﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ.
ﺷﻲﺀ zﺑﺎ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺭﺳﺎﻟﻲ 22ﻭ 7ﺍﻋﻼﻥ ﺷﺪﻩ .ﭘﺲ ﺩﺭ ﺍﻳﻦ ﺷﻲ ﻣﻘﺎﺩﻳﺮ ﭘﻴﺶﻓﺮﺽ
ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﺷﺪﻩ ﻭ z.numﺑﺮﺍﺑﺮ ﺑﺎ 22ﻭ z.denﺑﺮﺍﺑﺮ ﺑﺎ 7ﺧﻮﺍﻫﺪ ﺷﺪ.
9‐5ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ
ﺩﺍﺩﻩﻫﺎﻱ ﻋﻀﻮ ﻳﮏ ﮐﻼﺱ ﻣﻌﻤﻮﻻ ﺑﻪ ﺻﻮﺭﺕ ﺧﺼﻮﺻﻲ ) (privateﺍﻋﻼﻥ
ﻣﻲﺷﻮﻧﺪ ﺗﺎ ﺩﺳﺘﻴﺎﺑﻲ ﺑﻪ ﺁﻥﻫﺎ ﻣﺤﺪﻭﺩ ﺑﺎﺷﺪ ﺍﻣﺎ ﻫﻤﻴﻦ ﺍﻣﺮ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﻧﺘﻮﺍﻧﻴﻢ ﺩﺭ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 314
ﻣﻮﺍﻗﻊ ﻟﺰﻭﻡ ﺑﻪ ﺍﻳﻦ ﺩﺍﺩﻩﻫﺎ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ .ﺑﺮﺍﻱ ﺣﻞ ﺍﻳﻦ ﻣﺸﮑﻞ ﺍﺯ ﺗﻮﺍﺑﻌﻲ ﺑﺎ ﻋﻨﻮﺍﻥ
ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ 1ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ .ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﻳﮏ ﺗﺎﺑﻊ ﻋﻤﻮﻣﻲ ﻋﻀﻮ ﮐﻼﺱ ﺍﺳﺖ ﻭ ﺑﻪ
ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﺟﺎﺯۀ ﺩﺳﺘﺮﺳﻲ ﺑﻪ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺧﺼﻮﺻﻲ ﺭﺍ ﺩﺍﺭﺩ .ﺍﺯ ﻃﺮﻓﻲ ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ
ﺭﺍ ﻃﻮﺭﻱ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﻨﺪ ﮐﻪ ﻓﻘﻂ ﻣﻘﺪﺍﺭ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ ﻭﻟﻲ ﺁﻥﻫﺎ ﺭﺍ ﺗﻐﻴﻴﺮ
ﻧﺪﻫﺪ .ﺑﻪ ﺑﻴﺎﻥ ﺳﺎﺩﻩﺗﺮ ،ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻥ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺧﺼﻮﺻﻲ
ﺭﺍ ﺧﻮﺍﻧﺪ ﻭﻟﻲ ﻧﻤﻲﺗﻮﺍﻥ ﺁﻥﻫﺎ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﺮﺩ.
)(int main
;){ Ratio x(22,7
;cout << x.numerator() << '/' << x.denumerator() << endl
}
ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﺗﻮﺳﻂ ﺳﺎﻳﺮ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﮐﻼﺱ ﺩﺳﺘﻴﺎﺑﻲ ﺷﻮﺩ .ﺑﻪ ﭼﻨﻴﻦ ﺗﺎﺑﻌﻲ ﻳﮏ
ﺗﺎﺑﻊ ﺳﻮﺩﻣﻨﺪ 1ﻣﺤﻠﻲ ﻣﻲﮔﻮﻳﻴﻢ.
)(double Ratio::toFloat
{ // converts Rational number to Float
;return num/den
}
)(int main
;){ Ratio x(5, 100
;)(x.print
;)(x.printconv
}
5/100
0.05
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ،ﮐﻼﺱ Ratioﺩﺍﺭﺍﻱ ﻳﮏ ﺗﺎﺑﻊ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺑﻪ ﻧﺎﻡ )(toFloat
ﺍﺳﺖ .ﻭﻇﻴﻒۀ ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻣﻌﺎﺩﻝ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﻳﮏ ﻋﺪﺩ ﮐﺴﺮﻱ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ.
ﺍﻳﻦ ﺗﺎﺑﻊ ﻓﻘﻂ ﺩﺭﻭﻥ ﺑﺪﻥۀ ﺗﺎﺑﻊ ﻋﻀﻮ )( printconvﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﻭ ﺑﻪ ﺍﻧﺠﺎﻡ ﻭﻇﻴﻒۀ
ﺁﻥ ﮐﻤﮏ ﻣﻲﻧﻤﺎﻳﺪ ﻭ ﻫﻴﭻ ﻧﻘﺸﻲ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﻧﺪﺍﺭﺩ .ﻳﺎﺩﺁﻭﺭﻱ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﭼﻮﻥ ﺗﺎﺑﻊ
)( printconvﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﺍﺳﺖ ،ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺗﺎﺑﻊ ﺧﺼﻮﺻﻲ )(toFloat
ﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ.
ﺗﻮﺍﺑﻌﻲ ﮐﻪ ﻓﻘﻂ ﺑﻪ ﺍﻧﺠﺎﻡ ﻭﻇﻴﻒۀ ﺳﺎﻳﺮ ﺗﻮﺍﺑﻊ ﮐﻤﮏ ﻣﻲﮐﻨﻨﺪ ﻭ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﻫﻴﭻ
ﮐﺎﺭﺑﺮﺩﻱ ﻧﺪﺍﺭﻧﺪ ،ﺑﻬﺘﺮ ﺍﺳﺖ ﺑﻪ ﺻﻮﺭﺕ ﺧﺼﻮﺻﻲ ﺍﻋﻼﻥ ﺷﻮﻧﺪ ﺗﺎ ﺍﺯ ﺩﺳﺘﺮﺱ ﺳﺎﻳﺮﻳﻦ ﺩﺭ
ﺍﻣﺎﻥ ﺑﻤﺎﻧﻨﺪ.
9‐7ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ
ﻣﻲﺩﺍﻧﻴﻢ ﮐﻪ ﺑﻪ ﺩﻭ ﺷﻴﻮﻩ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﺘﻐﻴﺮ ﺟﺪﻳﺪﻱ ﺗﻌﺮﻳﻒ ﻧﻤﺎﻳﻴﻢ:
;int x
;int x=k
ﺩﺭ ﺭﻭﺵ ﺍﻭﻝ ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ xﺍﺯ ﻧﻮﻉ intﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ .ﺩﺭ ﺭﻭﺵ ﺩﻭﻡ ﻫﻢ
ﻫﻤﻴﻦ ﮐﺎﺭ ﺍﻧﺠﺎﻡ ﻣﻲﮔﻴﺮﺩ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﭘﺲ ﺍﺯ ﺍﻳﺠﺎﺩ xﻣﻘﺪﺍﺭ ﻣﻮﺟﻮﺩ ﺩﺭ ﻣﺘﻐﻴﺮ kﮐﻪ
ﺍﺯ ﻗﺒﻞ ﻭﺟﻮﺩ ﺩﺍﺷﺘﻪ ﺩﺭﻭﻥ xﮐﭙﻲ ﻣﻲﺷﻮﺩ .ﺍﺻﻄﻼﺣﺎ xﻳﮏ ﮐﭙﻲ ﺍﺯ kﺍﺳﺖ.
ﻭﻗﺘﻲ ﮐﻼﺱ ﺟﺪﻳﺪﻱ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﻴﻢ ،ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺷﻴﺎ ﺭﺍ
ﺑﻪ ﺭﻭﺵ ﺍﻭﻝ ﺍﻳﺠﺎﺩ ﮐﻨﻴﻢ:
;Ratio x
ﺩﺭ ﺗﻌﺮﻳﻒ ﺑﺎﻻ ،ﺷﻲ xﺍﺯ ﻧﻮﻉ ﮐﻼﺱ Ratioﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ .ﺣﺎﻝ ﺑﺒﻴﻨﻴﻢ ﭼﻄﻮﺭ
ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺷﻴﻮۀ ﺩﻭﻡ ﻳﮏ ﮐﭙﻲ ﺍﺯ ﺷﻲﺀ ﻣﻮﺟﻮﺩ ﺍﻳﺠﺎﺩ ﮐﻨﻴﻢ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭ ﺍﺯ ﺗﺎﺑﻊ ﻋﻀﻮﻱ
ﺑﻪ ﻧﺎﻡ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ 1ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ .ﺍﻳﻦ ﺗﺎﺑﻊ ﻧﻴﺰ ﺑﺎﻳﺪ ﺑﺎ ﻧﺎﻡ ﮐﻼﺱ ﻫﻢﻧﺎﻡ ﺑﺎﺷﺪ ﻭﻟﻲ
ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺑﺮ ﺧﻼﻑ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﻣﻌﻤﻮﻟﻲ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺑﻪ ﻃﺮﻳﻖۀ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺩﺍﺭﺩ .ﻧﻮﻉ
ﺍﻳﻦ ﭘﺎﺭﺍﻣﺘﺮ ﺑﺎﻳﺪ ﻫﻢﻧﻮﻉ ﮐﻼﺱ ﻣﺬﮐﻮﺭ ﺑﺎﺷﺪ .ﺍﻳﻦ ﭘﺎﺭﺍﻣﺘﺮ ،ﻫﻤﺎﻥ ﺷﻴﺌﻲ ﺍﺳﺖ ﮐﻪ ﻣﻲﺧﻮﺍﻫﻴﻢ
ﺍﺯ ﺭﻭﻱ ﺁﻥ ﮐﭙﻲ ﺑﺴﺎﺯﻳﻢ .ﻋﻠﺖ ﺍﻳﻦ ﮐﻪ ﭘﺎﺭﺍﻣﺘﺮ ﻣﺬﮐﻮﺭ ﺑﻪ ﻃﺮﻳﻖۀ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺍﺭﺳﺎﻝ
ﻣﻲﺷﻮﺩ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺷﻴﺌﻲ ﮐﻪ ﻗﺮﺍﺭ ﺍﺳﺖ ﮐﭙﻲ ﺷﻮﺩ ﻧﺒﺎﻳﺪ ﺗﻮﺳﻂ ﺍﻳﻦ ﺗﺎﺑﻊ ﻗﺎﺑﻞ ﺗﻐﻴﻴﺮ
ﺑﺎﺷﺪ .ﮐﺪﻫﺎﻱ ﺯﻳﺮ ﻫﺮ ﺩﻭ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ﻭ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ:
;)(Ratio // default constructor
;)&Ratio(const Ratio // copy constructor
ﺍﻭﻟﻲ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ﺍﺳﺖ ﻭ ﺩﻭﻣﻲ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺍﺳﺖ .ﺣﺎﻻ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ
ﮐﺪ ﺑﺎﻻ ﻳﮏ ﺷﻲ ﺑﻪ ﻧﺎﻡ yﺍﺯ ﻧﻮﻉ Ratioﺍﻳﺠﺎﺩ ﻣﻲﮐﻨﺪ ﻭ ﺗﻤﺎﻡ ﻣﺸﺨﺼﺎﺕ ﺷﻲﺀ xﺭﺍ
ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ .ﺍﮔﺮ ﺩﺭ ﺗﻌﺮﻳﻒ ﮐﻼﺱ ،ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺫﮐﺮ ﻧﺸﻮﺩ )ﻣﺜﻞ ﻫﻢۀ
ﮐﻼﺱﻫﺎﻱ ﻗﺒﻠﻲ( ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﻳﮏ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﭘﻴﺶﻓﺮﺽ ﺑﻪ ﮐﻼﺱ ﺍﻓﺰﻭﺩﻩ ﺧﻮﺍﻫﺪ
ﺷﺪ .ﺑﺎ ﺍﻳﻦ ﻭﺟﻮﺩ ﺍﮔﺮ ﺧﻮﺩﺗﺎﻥ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﮐﻨﻴﺪ ،ﻣﻲﺗﻮﺍﻧﻴﺪ ﮐﻨﺘﺮﻝ ﺑﻴﺸﺘﺮﻱ
ﺭﻭﻱ ﺑﺮﻧﺎﻣﻪﺗﺎﻥ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ.
ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺩﺭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﭘﻴﺶﻓﺮﺽ
ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ .ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ،ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻃﻮﺭﻱ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﮐﻪ ﻋﻨﺼﺮﻫﺎﻱ numﻭ
denﺍﺯ ﭘﺎﺭﺍﻣﺘﺮ rﺑﻪ ﺩﺭﻭﻥ ﻋﻨﺼﺮﻫﺎﻱ ﻣﺘﻨﺎﻇﺮ ﺩﺭ ﺷﻲﺀ ﺟﺪﻳﺪ ﮐﭙﻲ ﺷﻮﻧﺪ .ﺩﺳﺘﻮﺭ
;) Ratio y(xﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺷﻲﺀ yﺳﺎﺧﺘﻪ ﺷﺪﻩ ﻭ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻓﺮﺍ ﺧﻮﺍﻧﺪﻩ
ﺷﻮﺩ ﺗﺎ ﻣﻘﺎﺩﻳﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﺷﻲﺀ xﺩﺭﻭﻥ yﮐﭙﻲ ﺷﻮﻧﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 318
)(int main
;){ Ratio x(22,7
;)Ratio y(x // calls the copy constructor, copying x to y
;)f(y
}
COPY CONSTRUCTOR CALLED
COPY CONSTRUCTOR CALLED
COPY CONSTRUCTOR CALLED
COPY CONSTRUCTOR CALLED
ﺑﺪﻥۀ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺷﺎﻣﻞ ﻳﮏ ﭘﻴﻐﺎﻡ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﻭﻗﺖ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ ،ﺑﺎ ﭼﺎﭖ ﺁﻥ ﭘﻴﻐﺎﻡ ﺁﮔﺎﻩ ﺷﻮﻳﻢ ﮐﻪ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ .ﻫﻤﺎﻥ ﻃﻮﺭ
ﮐﻪ ﺧﺮﻭﺟﻲ ﺑﺮﻧﺎﻣﻪ ﻧﺸﺎﻥ ﻣﻲ ﺩﻫﺪ ،ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﭼﻬﺎﺭ ﺑﺎﺭ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ:
319 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
9‐8ﻧﺎﺑﻮﺩ ﮐﻨﻨﺪﻩ
ﻭﻗﺘﻲ ﮐﻪ ﻳﮏ ﺷﻲ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ،ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﺑﺮﺍﻱ ﺳﺎﺧﺘﻦ ﺁﻥ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ .ﻭﻗﺘﻲ ﮐﻪ ﺷﻲ ﺑﻪ ﭘﺎﻳﺎﻥ ﺯﻧﺪﮔﻲﺍﺵ ﺑﺮﺳﺪ ،ﺗﺎﺑﻊ ﻋﻀﻮ ﺩﻳﮕﺮﻱ ﺑﻪ ﻃﻮﺭ
ﺧﻮﺩﮐﺎﺭ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ﺗﺎ ﻧﺎﺑﻮﺩﮐﺮﺩﻥ ﺁﻥ ﺷﻲ ﺭﺍ ﻣﺪﻳﺮﻳﺖ ﮐﻨﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﻋﻀﻮ،
ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ 1ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ )ﺩﺭ ﺑﺮﺧﻲ ﺍﺯ ﮐﺘﺎﺏﻫﺎ ﺑﻪ ﺁﻥ »ﺗﺨﺮﻳﺐﮔﺮ« ﻳﺎ »ﻣﻨﻬﺪﻡﮐﻨﻨﺪﻩ«
1 – Destructor
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 320
ﮔﻔﺘﻪﺍﻧﺪ( .ﺳﺎﺯﻧﺪﻩ ﻭﻇﻴﻔﻪ ﺩﺍﺭﺩ ﺗﺎ ﻣﻨﺎﺑﻊ ﻻﺯﻡ ﺭﺍ ﺑﺮﺍﻱ ﺷﻲ ﺗﺨﺼﻴﺺ ﺩﻫﺪ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ
ﻭﻇﻴﻔﻪ ﺩﺍﺭﺩ ﺁﻥ ﻣﻨﺎﺑﻊ ﺭﺍ ﺁﺯﺍﺩ ﮐﻨﺪ.
ﻫﺮ ﮐﻼﺱ ﻓﻘﻂ ﻳﮏ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺩﺍﺭﺩ .ﻧﺎﻡ ﺗﺎﺑﻊ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺑﺎﻳﺪ ﻫﻢ ﻧﺎﻡ ﮐﻼﺱ ﻣﺮﺑﻮﻃﻪ
ﺑﺎﺷﺪ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﻳﮏ ﻋﻼﻣﺖ ﻧﻘﻴﺾ ~ ﺑﻪ ﺁﻥ ﭘﻴﺸﻮﻧﺪ ﺷﺪﻩ .ﻣﺜﻞ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻭ
ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ،ﺍﮔﺮ ﻧﺎﺑﻮﺩ ﮐﻨﻨﺪﻩ ﺩﺭ ﺗﻌﺮﻳﻒ ﮐﻼﺱ ﺫﮐﺮ ﻧﺸﻮﺩ ،ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﻳﮏ
ﻧﺎﺑﻮﺩﮐﻨﻨﺪۀ ﭘﻴﺶﻓﺮﺽ ﺑﻪ ﮐﻼﺱ ﺍﻓﺰﻭﺩﻩ ﺧﻮﺍﻫﺪ ﺷﺪ.
)(int main
;{ { Ratio x // beginning of scope for x
;"cout << "Now x is alive.\n
} // end of scope for x
;"cout << "Now between blocks.\n
;{ Ratio y
;"cout << "Now y is alive.\n
}
}
OBJECT IS BORN.
Now x is alive.
OBJECT DIES.
Now between blocks.
OBJECT IS BORN.
Now y is alive.
OBJECT DIES.
ﺩﺭ ﺑﺪﻥۀ ﺗﻮﺍﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﭘﻴﻐﺎﻣﻲ ﺩﺭﺝ ﺷﺪﻩ ﺗﺎ ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﻳﮏ ﺷﻲ ﺍﺯ ﺍﻳﻦ
ﮐﻼﺱ ﻣﺘﻮﻟﺪ ﺷﺪﻩ ﻳﺎ ﻣﻲﻣﻴﺮﺩ ،ﺍﺯ ﺗﻮﻟﺪ ﻭ ﻣﺮﮒ ﺁﻥ ﺁﮔﺎﻩ ﺷﻮﻳﻢ .ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ
321 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
9‐9ﺍﺷﻴﺎﻱ ﺛﺎﺑﺖ
ﺍﮔﺮ ﻗﺮﺍﺭ ﺍﺳﺖ ﺷﻴﺌﻲ ﺑﺴﺎﺯﻳﺪ ﮐﻪ ﺩﺭ ﻃﻮﻝ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﻫﻴﭻﮔﺎﻩ ﺗﻐﻴﻴﺮ ﻧﻤﻲﮐﻨﺪ ،ﺑﻬﺘﺮ
ﺍﺳﺖ ﻣﻨﻄﻘﻲ ﺭﻓﺘﺎﺭ ﮐﻨﻴﺪ ﻭ ﺁﻥ ﺷﻲ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺛﺎﺑﺖ ﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﺪ .ﺍﻋﻼﻥﻫﺎﻱ ﺯﻳﺮ ﭼﻨﺪ
ﺛﺎﺑﺖ ﺁﺷﻨﺎ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ:
;' ' = const char BLANK
;const int MAX_INT = 2147483647
;const double PI = 3.141592653589793
;)void int(float a[], const int SIZE
ﺍﺷﻴﺎ ﺭﺍ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﺒﺎﺭﺕ constﺑﻪ ﺻﻮﺭﺕ ﻳﮏ ﺷﻲﺀ ﺛﺎﺑﺖ ﺍﻋﻼﻥ ﮐﺮﺩ:
;)const Ratio PI(22,7
ﺍﻣﺎ ﺩﺭ ﻣﻮﺭﺩ ﺍﺷﻴﺎﻱ ﺛﺎﺑﺖ ﻳﮏ ﻣﺤﺪﻭﺩﻳﺖ ﻭﺟﻮﺩ ﺩﺍﺭﺩ :ﮐﺎﻣﭙﺎﻳﻠﺮ ﺍﺟﺎﺯﻩ ﻧﻤﻲﺩﻫﺪ ﮐﻪ ﺗﻮﺍﺑﻊ
ﻋﻀﻮ ﺭﺍ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻱ ﺛﺎﺑﺖ ﻓﺮﺍﺧﻮﺍﻧﻲ ﮐﻨﻴﺪ .ﻣﺜﻼ ﺩﺭ ﻣﻮﺭﺩ ﮐﺪ ﻓﻮﻕ ﮔﺮﭼﻪ ﺗﺎﺑﻊ )(print
ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ Ratioﺍﺳﺖ ﺍﻣﺎ ﺩﺭ ﻣﻮﺭﺩ ﺷﻲﺀ ﺛﺎﺑﺖ PIﻧﻤﻲﺗﻮﺍﻧﻴﻢ ﺁﻥ ﺭﺍ ﻓﺮﺍﺧﻮﺍﻧﻲ
ﮐﻨﻴﻢ:
;)(PI.print // error: call not allowed
ﺩﺭ ﺍﺻﻞ ﺗﻨﻬﺎ ﺗﻮﺍﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻱ ﺛﺎﺑﺖ ﻗﺎﺑﻞ ﻓﺮﺍﺧﻮﺍﻧﻲﺍﻧﺪ .ﻭﻟﻲ ﺍﻳﻦ
ﻣﺸﮑﻞ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺣﻞ ﮐﺮﺩ .ﺑﺮﺍﻱ ﻏﻠﺒﻪ ﺑﺮ ﺍﻳﻦ ﻣﺤﺪﻭﺩﻳﺖ ،ﺗﻮﺍﺑﻊ ﻋﻀﻮﻱ ﮐﻪ ﻣﻲﺧﻮﺍﻫﻴﻢ ﺑﺎ
ﺍﺷﻴﺎﻱ ﺛﺎﺑﺖ ﮐﺎﺭ ﮐﻨﻨﺪ ﺭﺍ ﺑﺎﻳﺪ ﺑﻪ ﺻﻮﺭﺕ constﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ .ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﺗﺎﺑﻊ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 322
ﺍﻳﻦ ﭼﻨﻴﻦ ﺗﻌﺮﻳﻒ ﺷﻮﺩ ،ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ constﺭﺍ ﺑﻴﻦ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﻭ ﺗﻌﺮﻳﻒ ﺑﺪﻥۀ
ﺁﻥ ﻗﺮﺍﺭ ﻣﻲﺩﻫﻴﻢ .ﻣﺜﻼ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ )( printﺩﺭ ﮐﻼﺱ Ratioﺭﺍ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺗﻐﻴﻴﺮ
ﻣﻲﺩﻫﻴﻢ:
} ;void print() const { cout << num << '/' << den << endl
ﺍﮐﻨﻮﻥ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻱ ﺛﺎﺑﺖ ﻧﻴﺰ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﺎﻳﻴﻢ:
;)const Ratio PI(22,7
;)(PI.print // o.k. now
9‐10ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ
ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎﻱ ﮐﻼﺱ ﻧﻴﺰ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ .ﺍﺯ ﺁﻥﺟﺎ ﮐﻪ ﻳﮏ ﮐﻼﺱ
ﻣﻲﺗﻮﺍﻧﺪ ﺍﺷﻴﺎﻱ ﺩﺍﺩﻩﺍﻱ ﻣﺘﻨﻮﻉ ﻭ ﻣﺘﻔﺎﻭﺗﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ،ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ ﺑﺴﻴﺎﺭ ﺳﻮﺩﻣﻨﺪ ﻭ
ﻣﻔﻴﺪ ﺍﺳﺖ .ﺑﻬﺘﺮ ﺍﺳﺖ ﻗﺒﻞ ﺍﺯ ﻣﻄﺎﻟﻊۀ ﻣﺜﺎﻝﻫﺎﻱ ﺯﻳﺮ ،ﻓﺼﻞ ﻫﻔﺘﻢ ﺭﺍ ﻣﺮﻭﺭ ﮐﻨﻴﺪ.
ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ p ،ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺷﻲﺀ xﺍﺳﺖ .ﭘﺲ *pﻳﮏ ﺷﻲﺀ xﺍﺳﺖ ﻭ
(*p).dataﺩﺍﺩۀ ﻋﻀﻮ ﺁﻥ ﺷﻲ ﺭﺍ ﺩﺳﺘﻴﺎﺑﻲ ﻣﻲﮐﻨﺪ .ﺣﺘﻤﺎ ﺑﺎﻳﺪ ﻫﻨﮕﺎﻡ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ *pﺁﻥ
ﺭﺍ ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ ﻗﺮﺍﺭ ﺩﻫﻴﺪ ﺯﻳﺮﺍ ﻋﻤﻠﮕﺮ ﺍﻧﺘﺨﺎﺏ ﻋﻀﻮ ) (.ﺗﻘﺪﻡ ﺑﺎﻻﺗﺮﻱ ﻧﺴﺒﺖ ﺑﻪ ﻋﻤﻠﮕﺮ
ﻣﻘﺪﺍﺭﻳﺎﺑﻲ )*( ﺩﺍﺭﺩ .ﺍﮔﺮ ﭘﺮﺍﻧﺘﺰﻫﺎ ﻗﻴﺪ ﻧﺸﻮﻧﺪ ﻭ ﻓﻘﻂ *p.dataﻧﻮﺷﺘﻪ ﺷﻮﺩ ،ﮐﺎﻣﭙﺎﻳﻠﺮ
ﺍﻳﻦ ﺧﻂ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ) *(p.dataﺗﻔﺴﻴﺮ ﺧﻮﺍﻫﺪ ﮐﺮﺩ ﮐﻪ ﺍﻳﻦ ﺑﺎﻋﺚ ﺧﻄﺎ ﻣﻲﺷﻮﺩ.
323 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
ﻋﺒﺎﺭﺕ ﺑﺎﻻ ﮐﻼﺳﻲ ﺑﻪ ﻧﺎﻡ Nodeﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﺷﻴﺎﻱ ﺍﻳﻦ ﮐﻼﺱ ﺩﺍﺭﺍﻱ ﺩﻭ ﻋﻀﻮ
ﺩﺍﺩﻩﺍﻱ ﻫﺴﺘﻨﺪ ﮐﻪ ﻳﮑﻲ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ intﺍﺳﺖ ﻭ ﺩﻳﮕﺮﻱ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺍﺯ ﻧﻮﻉ ﻫﻤﻴﻦ
ﮐﻼﺱ .ﺷﺎﻳﺪ ﻋﺠﻴﺐ ﺑﺎﺷﺪ ﮐﻪ ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﺑﻪ ﺷﻴﺌﻲ ﺍﺯ ﻧﻮﻉ ﻫﻤﺎﻥ ﮐﻼﺱ ﺍﺷﺎﺭﻩ ﮐﻨﺪ
ﺍﻣﺎ ﺍﻳﻦ ﮐﺎﺭ ﻭﺍﻗﻌﺎ ﻣﻤﮑﻦ ﺍﺳﺖ ﻭ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﺑﺘﻮﺍﻧﻴﻢ ﻳﮏ ﺷﻲ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻫﻤﻴﻦ
ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺷﻲﺀ ﺩﻳﮕﺮ ﭘﻴﻮﻧﺪ ﺩﻫﻴﻢ ﻭ ﻳﮏ ﺯﻧﺠﻴﺮﻩ ﺑﺴﺎﺯﻳﻢ .ﻣﺜﻼ ﺍﮔﺮ ﺍﺷﻴﺎﻱ qﻭ rﻭ sﺍﺯ
ﻧﻮﻉ Nodeﺑﺎﺷﻨﺪ ،ﻣﻲﺗﻮﺍﻧﻴﻢ ﭘﻴﻮﻧﺪ ﺍﻳﻦ ﺳﻪ ﺷﻲ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ﺯﻳﺮ ﻣﺠﺴﻢ ﮐﻨﻴﻢ:
ﺑﻪ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻧﻴﺰ ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﭼﻄﻮﺭ ﻫﺮ ﺩﻭ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺷﻲﺀ ﺟﺪﻳﺪ ﺭﺍ
ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﮐﻨﺪ .ﺍﮐﻨﻮﻥ ﺍﻳﻦ ﮐﻼﺱ ﺭﺍ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﻳﻢ:
)(int main
;{ int n
;Node* p
;Node* q=0
)while (cin >> n
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 324
ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ،ﺍﺑﺘﺪﺍ ﺩﻭ ﺍﺷﺎﺭﻩﮔﺮ ﺍﺯ ﻧﻮﻉ Nodeﺑﻪ ﻧﺎﻡ pﻭ qﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ ﮐﻪ qﺑﻪ ﻳﮏ
ﺷﻲﺀ ﺧﺎﻟﻲ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ .ﺩﺭ ﺣﻠﻖۀ whileﭘﺲ ﺍﺯ ﺍﻭﻟﻴﻦ ﻭﺭﻭﺩﻱ ،ﺣﺎﻓﻆۀ ﺟﺪﻳﺪﻱ ﺑﺮﺍﻱ
ﺷﻲﺀ pﻣﻨﻈﻮﺭ ﻣﻲﺷﻮﺩ ﻭ ﻋﺪﺩ ﻭﺍﺭﺩ ﺷﺪﻩ ﺩﺭ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ dataﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ pﻗﺮﺍﺭ
ﻣﻲﮔﻴﺮﺩ ﻭ ﻫﻤﭽﻨﻴﻦ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ nextﺑﺮﺍﺑﺮ ﺑﺎ qﻣﻲﺷﻮﺩ .ﻳﻌﻨﻲ ﻋﻀﻮ ﺍﺷﺎﺭﻩﮔﺮ pﺑﻪ
ﺣﺎﻓﻆۀ qﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ .ﺳﭙﺲ ﺁﺩﺭﺱ ﺷﻲﺀ pﺩﺭ ﺷﻲﺀ qﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺣﺎﻻ qﺑﻪ ﺷﻲﺀ
pﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﻭ pﺑﻪ ﻳﮏ ﺷﻲﺀ ﺧﺎﻟﻲ.
ﭘﺲ ﺍﺯ ﺩﻭﻣﻴﻦ ﻭﺭﻭﺩﻱ ،ﻣﺠﺪﺩﺍ ﺣﺎﻓﻆۀ ﺟﺪﻳﺪﻱ ﺑﺮﺍﻱ pﻣﻨﻈﻮﺭ ﻣﻲﺷﻮﺩ ﻭ
ﺍﻧﺘﺴﺎﺏﻫﺎﻱ ﻓﻮﻕ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ ﺗﺎ ﺍﻳﻦ ﮐﻪ pﺑﻪ ﺣﺎﻓﻆۀ ﻣﻮﺟﻮﺩ ﻗﺒﻠﻲ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ﻭ qﺑﻪ
ﺷﻲﺀ pﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ .ﺷﮑﻞ ﺯﻳﺮ ﺭﻭﻧﺪ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
next next
p
data
next
ﺗﺎ ﺯﻣﺎﻧﻲ ﮐﻪ ﮐﺎﺭﺑﺮ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ ) (Ctrl+Zﺭ ﺍ ﻓﺸﺎﺭ ﻧﺪﻫﺪ ،ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ
ﻳﺎﻓﺘﻪ ﻭ ﻫﺮ ﺩﻓﻌﻪ ﻳﮏ ﻋﺪﺩ ﺍﺯ ﻭﺭﻭﺩﻱ ﮔﺮﻓﺘﻪ ﺷﺪﻩ ﻭ ﻳﮏ ﺑﻨﺪ ﺑﻪ ﺯﻧﺠﻴﺮۀ ﻣﻮﺟﻮﺩ ﺍﺿﺎﻓﻪ
ﻣﻲﺷﻮﺩ .ﺣﻠﻖۀ forﻭﻇﻴﻒۀ ﭘﻴﻤﺎﻳﺶ ﻓﻬﺮﺳﺖ ﭘﻴﻮﻧﺪﻱ ﺭﺍ ﺩﺍﺭﺩ .ﺑﻪ ﺍﻳﻦ ﺻﻮﺭﺕ ﮐﻪ ﺗﺎ
ﻭﻗﺘﻲ
p->nextﺑﺮﺍﺑﺮ ﺑﺎ NULﻧﺒﺎﺷﺪ ،ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﻭ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﮔﺮﻩ ﻓﻌﻠﻲ ﺭﺍ ﭼﺎﭖ
ﻣﻲﮐﻨﺪ ﻭ ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﮐﻞ ﻓﻬﺮﺳﺖ ﭘﻴﻤﺎﻳﺶ ﻣﻲﺷﻮﺩ .ﻭﺍﺿﺢ ﺍﺳﺖ ﮐﻪ ﺑﺮﺍﻱ ﭘﻴﻤﻮﺩﻥ ﺍﻳﻦ
ﻓﻬﺮﺳﺖ ﭘﻴﻮﻧﺪﻱ ﺑﺎﻳﺪ ﺁﻥ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﻌﮑﻮﺱ ﭘﻴﻤﻮﺩ.
ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ ﺑﺴﻴﺎﺭ ﺳﻮﺩﻣﻨﺪ ﻭ ﻣﻔﻴﺪ ﺍﺳﺖ ﺑﻪ ﺣﺪﻱ ﮐﻪ ﺑﺤﺚ ﺭﺍﺟﻊ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ
ﻭ ﺍﻟﮕﻮﺭﻳﺘﻢﻫﺎ ﻭ ﻣﺰﺍﻳﺎﻱ ﺁﻥ ﺑﻪ ﺷﺎﺥۀ ﻣﺴﺘﻘﻠﻲ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺗﺒﺪﻳﻞ ﺷﺪﻩ ﻭ »ﺳﺎﺧﺘﻤﺎﻥ
ﺩﺍﺩﻩﻫﺎ «1ﻧﺎﻡ ﮔﺮﻓﺘﻪ ﺍﺳﺖ .ﺑﻪ ﺍﺧﺘﺼﺎﺭ ﻣﻲﮔﻮﻳﻴﻢ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ ﺑﺮﺍﻱ ﺳﺎﺧﺘﻦ
ﻓﻬﺮﺳﺖﻫﺎﻱ ﭘﻴﻮﻧﺪﻱ ﻭ ﺩﺭﺧﺖﻫﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ .ﺍﻳﻦﻫﺎ ﺑﻴﺸﺘﺮ ﺑﺮﺍﻱ
ﭘﺮﺩﺍﺯﺵﻫﺎﻱ ﺳﺮﻳﻊ ﻣﺜﻞ ﺟﺴﺘﺠﻮ ﺩﺭ ﻓﻬﺮﺳﺖﻫﺎﻱ ﻃﻮﻻﻧﻲ )ﻣﺎﻧﻨﺪ ﻓﺮﻫﻨﮓ ﻟﻐﺎﺕ( ﻳﺎ
ﻣﺮﺗﺐﺳﺎﺯﻱ ﺭﮐﻮﺭﺩﻫﺎﻱ ﺍﻃﻼﻋﺎﺗﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ .ﺑﺮﺍﻱ ﻣﻄﺎﻟﻌﻪ ﺩﺭ ﺍﻳﻦ ﺯﻣﻴﻨﻪ ﺑﻪ ﻣﺮﺍﺟﻊ
ﺳﺎﺧﺘﻤﺎﻥ ﺩﺍﺩﻩﻫﺎ ﻣﺮﺍﺟﻌﻪ ﮐﻨﻴﺪ.
ﺧﻂ ﺁﺧﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﻳﺴﺘﺎ ﺭﺍ ﺑﺎﻳﺪ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ ﻭ ﻣﺴﺘﻘﻞ ﺍﺯ ﺍﺷﻴﺎ
ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩ.
ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﻳﺴﺘﺎ ﺑﻪ ﻃﻮﺭ ﭘﻴﺶﻓﺮﺽ ﺑﺎ ﺻﻔﺮ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﻣﻲﺷﻮﻧﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ
ﻣﻘﺪﺍﺭﺩﻫﻲ ﺻﺮﻳﺢ ﺑﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﻣﺘﻐﻴﺮﻫﺎ ﺿﺮﻭﺭﻱ ﻧﻴﺴﺖ ﻣﮕﺮ ﺍﻳﻦ ﮐﻪ ﺑﺨﻮﺍﻫﻴﺪ ﻳﮏ ﻣﻘﺪﺍﺭ
ﺍﻭﻟﻲۀ ﻏﻴﺮ ﺻﻔﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ.
. ﺩﺭﻭﻥ ﺑﻠﻮﮎ ﺩﺍﺧﻠﻲ ﺍﻳﺠﺎﺩ ﺷﺪﻩ ﺍﺳﺖwidget ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﭼﮕﻮﻧﻪ ﭼﻬﺎﺭ ﺷﻲﺀ
ﺍﻳﻦ ﺍﺷﻴﺎ ﻧﺎﺑﻮﺩ ﻣﻲﺷﻮﻧﺪ ﻭ ﻟﺬﺍ ﺗﻌﺪﺍﺩ،ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺁﻥ ﺑﻠﻮﮎ ﺧﺎﺭﺝ ﻣﻲﺷﻮﺩ
. ﺗﻘﻠﻴﻞ ﻣﻲﻳﺎﺑﺪ2 ﺑﻪ6 ﻫﺎ ﺍﺯwidget ﮐﻞ
ﻓﻘﻂ ﻳﮏ ﻧﻤﻮﻧﻪ ﺍﺯ ﺁﻥ:ﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺍﻳﺴﺘﺎ ﻣﺜﻞ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻌﻤﻮﻟﻲ ﺍﺳﺖ
ﺍﺯ ﺁﻥﺟﺎ.ﻣﻮﺟﻮﺩ ﺍﺳﺖ ﺑﺪﻭﻥ ﺗﻮﺟﻪ ﺑﻪ ﺍﻳﻦ ﮐﻪ ﭼﻪ ﺗﻌﺪﺍﺩ ﺷﻲ ﺍﺯ ﺁﻥ ﮐﻼﺱ ﻣﻮﺟﻮﺩ ﺑﺎﺷﺪ
ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﻥ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻋﻀﻮ،ﮐﻪ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺍﻳﺴﺘﺎ ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﺍﺳﺖ
.ﺧﺼﻮﺻﻲ ﻧﻴﺰ ﺍﻋﻼﻥ ﮐﻨﻴﻢ
int Widget::count = 0;
main()
{ Widget w, x;
cout << "Now there are " << w.numWidgets() << " widgets.\n";
{ Widget w, x, y, z;
cout << "Now there are " << w.numWidgets() << " widgets.\n";
}
cout << "Now there are " << w.numWidgets() << " widgets.\n";
Widget y;
cout << "Now there are " << w.numWidgets() << " widgets.\n";
}
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 328
ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺎﻧﻨﺪ ﻣﺜﺎﻝ 9‐15ﮐﺎﺭ ﻣﻲﮐﻨﺪ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﻣﺘﻐﻴﺮ ﺍﻳﺴﺘﺎﻱ countﺑﻪ
ﺷﮑﻞ ﻳﮏ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺍﻋﻼﻥ ﺷﺪﻩ
Widget y ﻭ ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺑﻪ ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ
)(Widget
)(~Widget x )( numWidgetsﻧﻴﺎﺯ ﺩﺍﺭﻳﻢ ﺗﺎ
)(numWidgets
w
ﺑﺘﻮﺍﻧﻴﻢ ﺩﺭﻭﻥ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﻪ ﻣﺘﻐﻴﺮ
count 3
ﺑﺎﺷﻴﻢ. ﺩﺍﺷﺘﻪ ﺩﺳﺘﺮﺳﻲ count
ﻣﻲﺗﻮﺍﻧﻴﻢ ﮐﻼﺱ Widgetﻭ ﺍﺷﻴﺎﻱ xﻭ yﻭ wﺭﺍ ﻣﺎﻧﻨﺪ ﻣﻘﺎﺑﻞ ﺗﺼﻮﺭ ﮐﻨﻴﻢ:
ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﻣﺘﻐﻴﺮ ﺍﻳﺴﺘﺎﻱ countﺩﺭﻭﻥ ﺧﻮﺩ ﮐﻼﺱ ﺟﺎﻱ ﮔﺮﻓﺘﻪ ﻧﻪ ﺩﺭﻭﻥ ﺍﺷﻴﺎ.
private:
;static int count
;}
)(int main
{ ;"cout << "Now there are " << Widget::num() << " widgets.\n
;Widget w, x
;"cout << "Now there are " << Widget::num() << " widgets.\n
{ ;Widget w, x, y, z
;"cout << "Now there are " << Widget::num() << " widgets.\n
}
;"cout << "Now there are " << Widget::num() << " widgets.\n
;Widget y
;"cout << "Now there are " << Widget::num() << " widgets.\n
}
ﻭﻗﺘﻲ ﺗﺎﺑﻊ )( numﺑﻪ ﺻﻮﺭﺕ ﺍﻳﺴﺘﺎ ﺗﻌﺮﻳﻒ ﺷﻮﺩ ،ﺍﺯ ﺍﺷﻴﺎﻱ ﮐﻼﺱ ﻣﺴﺘﻘﻞ ﻣﻲﺷﻮﺩ ﻭ
ﺑﺮﺍﻱ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺁﻥ ﻧﻴﺎﺯﻱ ﺑﻪ ﻳﮏ ﺷﻲﺀ ﻣﻮﺟﻮﺩ ﻧﻴﺴﺖ ﻭ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﮐﺪ
)( Widget::numﺑﻪ ﺷﮑﻞ ﻣﺴﺘﻘﻴﻢ ﺁﻥ ﺭﺍ ﻓﺮﺍﺧﻮﺍﻧﻲ ﮐﺮﺩ.
ﺗﺎ ﺍﻳﻦ ﺟﺎ ﺭﺍﺟﻊ ﺑﻪ ﺷﻲﮔﺮﺍﻳﻲ ﻭ ﻧﺤﻮ ۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﻣﻄﺎﻟﺒﻲ ﺁﻣﻮﺧﺘﻴﻢ.
ﺍﮐﻴﺪﺍ ﺗﻮﺻﻴﻪ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﻗﺒﻞ ﺍﺯ ﻣﻄﺎﻟﻊۀ ﻓﺼﻞ ﺑﻌﺪﻱ ،ﻫﻢ ۀ ﺗﻤﺮﻳﻦﻫﺎﻱ ﭘﺎﻳﺎﻥ ﺍﻳﻦ ﻓﺼﻞ ﺭﺍ
ﺣﻞ ﮐﻨﻴﺪ ﺗﺎ ﺑﺎ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺷﻲﮔﺮﺍ ﻣﺄﻧﻮﺱ ﺷﻮﻳﺪ .ﺩﺭ ﻓﺼﻞ ﺑﻌﺪﻱ ﻣﻄﺎﻟﺒﻲ ﺭﺍ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ
ﮐﻪ ﺷﻲﮔﺮﺍﻳﻲ ﺭﺍ ﻣﻔﻴﺪﺗﺮ ﻣﻲﮐﻨﻨﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 330
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺍﺯ ﻣﺰﺍﻳﺎﻱ ﺷﻲﮔﺮﺍﻳﻲ ﻧﻴﺴﺖ؟
ﺩ – ﻧﻤﻮﻧﻪﺳﺎﺯﻱ ﺝ – ﺑﺴﺘﻪﺑﻨﺪﻱ ﺏ – ﭼﻨﺪﺭﻳﺨﺘﻲ ﺍﻟﻒ – ﻭﺭﺍﺛﺖ
– 2ﺩﺭ ﺍﻋﻼﻥ ﻳﮏ ﮐﻼﺱ ،ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ – ﺑﺮﺍﻱ ﻣﻌﺮﻓﻲ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﮐﻼﺱ ﺍﺯ ﻋﺒﺎﺭﺕ privateﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ
ﺏ – ﺑﺮﺍﻱ ﻣﻌﺮﻓﻲ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﺍﺯ ﻋﺒﺎﺭﺕ publicﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ
ﺝ – ﺗﻮﺍﺑﻊ ﻭ ﻣﺘﻐﻴﺮﻫﺎ ﻫﺮ ﺩﻭ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻋﻀﻮ ﻳﮏ ﮐﻼﺱ ﺑﺎﺷﻨﺪ
ﺩ – ﺑﺮﺍﻱ ﻣﻌﺮﻓﻲ ﺍﻋﻀﺎﻱ ﺗﺎﺑﻌﻲ ﮐﻼﺱ ﺍﺯ ﻋﺒﺎﺭﺕ functﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ
– 3ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟
ﺍﻟﻒ – ﺑﻪ ﺍﻋﻼﻥ ﮐﻼﺱ ،ﺭﺍﺑﻂ ﮐﻼﺱ ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ
ﺏ – ﺑﻪ ﺑﺪﻥۀ ﮐﻼﺱ ،ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﮐﻼﺱ ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ
ﺝ – ﺑﻪ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﺍﺯ ﻧﻮﻉ ﻳﮏ ﮐﻼﺱ ﺑﺎﺷﺪ ،ﺷﻲ ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ
ﺩ – ﺑﻪ ﺗﺎﺑﻌﻲ ﮐﻪ ﻋﻀﻮ ﻳﮏ ﮐﻼﺱ ﺑﺎﺷﺪ ،ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ
– 4ﺍﺯ ﮔﺰﻳﻨﻪﻫﺎﻱ ﺯﻳﺮ ،ﮐﺪﺍﻡ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ – ﻫﺮ ﮐﻼﺱ ﻓﻘﻂ ﻳﮏ ﺳﺎﺯﻧﺪﻩ ﻭ ﻓﻘﻂ ﻳﮏ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺩﺍﺭﺩ
ﺏ – ﻫﺮ ﮐﻼﺱ ﻓﻘﻂ ﻳﮏ ﺳﺎﺯﻧﺪﻩ ﺩﺍﺭﺩ ﻭ ﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ
ﺝ – ﻫﺮ ﮐﻼﺱ ﻓﻘﻂ ﻳﮏ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺩﺍﺭﺩ ﻭ ﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪ ﺳﺎﺯﻧﺪﻩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ
ﺩ – ﻫﺮ ﮐﻼﺱ ﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪ ﺳﺎﺯﻧﺪﻩ ﻭ ﭼﻨﺪ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ
– 5ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﭼﻴﺴﺖ؟
ﺍﻟﻒ – ﻳﮏ ﺗﺎﺑﻊ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﮐﻼﺱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻳﮏ ﺩﺍﺩۀ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺭﺩ
ﺏ – ﻳﮏ ﺗﺎﺑﻊ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻳﮏ ﺩﺍﺩۀ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺭﺩ
ﺝ – ﻳﮏ ﺗﺎﺑﻊ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﮐﻼﺱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻳﮏ ﺩﺍﺩۀ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺭﺩ
ﺩ – ﻳﮏ ﺗﺎﺑﻊ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻳﮏ ﺩﺍﺩﻩ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺭﺩ
331 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
– 6ﺍﮔﺮ ﮐﻼﺳﻲ ﺑﻪ ﻧﺎﻡ vectorﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ ﺁﻧﮕﺎﻩ ﮐﺪﺍﻡ ﺗﺎﺑﻊ ﺯﻳﺮ ،ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺭﺍ ﺑﺮﺍﻱ
ﺍﻳﻦ ﮐﻼﺱ ﺍﻋﻼﻥ ﻣﻲﮐﻨﺪ؟
ﺏ – )&vector(const vector ﺍﻟﻒ – )(vector
ﺩ – )vector*(const vector ﺝ ‐ )(~vector
– 7ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻭﻗﺘﻲ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ﮐﻪ:
ﺍﻟﻒ – ﻳﮏ ﺷﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﻣﻘﺪﺍﺭ ﺑﻪ ﻳﮏ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﺷﻮﺩ
ﺏ – ﻳﮏ ﺷﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﺍﺭﺟﺎﻉ ﺑﻪ ﻳﮏ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﺷﻮﺩ
ﺝ – ﻳﮏ ﺷﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺑﻪ ﻳﮏ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﺷﻮﺩ
ﺩ – ﻳﮏ ﺷﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﺍﺭﺟﺎﻉ ﺍﺯ ﻳﮏ ﺗﺎﺑﻊ ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﺷﻮﺩ
– 8ﺍﮔﺮ ﺩﺭ ﺗﻌﺮﻳﻒ ﻳﮏ ﮐﻼﺱ ،ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺫﮐﺮ ﻧﺸﻮﺩ ﺁﻧﮕﺎﻩ:
ﺍﻟﻒ – ﺍﺯ ﺍﺷﻴﺎﻱ ﺁﻥ ﮐﻼﺱ ﻧﻤﻲﺗﻮﺍﻥ ﮐﭙﻲ ﺍﻳﺠﺎﺩ ﮐﺮﺩ
ﺏ – ﺍﺷﻴﺎﻱ ﺁﻥ ﮐﻼﺱ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩ
ﺝ – ﺍﺷﻴﺎﻱ ﺁﻥ ﮐﻼﺱ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺍﺯ ﺗﺎﺑﻊ ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩ
ﺩ – ﻳﮏ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﭘﻴﺶﻓﺮﺽ ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﺑﻪ ﮐﻼﺱ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ
– 9ﺍﮔﺮ ﺷﻲﺀ xﺩﺭ ﺗﺎﺑﻊ ﻣﻔﺮﻭﺽ )( fﺑﻪ ﺷﮑﻞ ﻣﺤﻠﻲ ﺍﻋﻼﻥ ﺷﺪﻩ ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ :
ﺍﻟﻒ – ﺑﺎ ﺷﺮﻭﻉ ﺗﺎﺑﻊ )( mainﺷﻲﺀ xﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺗﺎﺑﻊ )( mainﻣﻲﻣﻴﺮﺩ
ﺏ – ﺑﺎ ﺷﺮﻭﻉ ﺗﺎﺑﻊ )( mainﺷﻲﺀ xﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺗﺎﺑﻊ )( fﻣﻲﻣﻴﺮﺩ
ﺝ – ﺑﺎ ﺷﺮﻭﻉ ﺗﺎﺑﻊ )( fﺷﻲﺀ xﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺗﺎﺑﻊ )( fﻣﻲﻣﻴﺮﺩ
ﺩ – ﺑﺎ ﺷﺮﻭﻉ ﺗﺎﺑﻊ )( fﺷﻲﺀ xﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺗﺎﺑﻊ )( mainﻣﻲﻣﻴﺮﺩ
– 10ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺩﺭ ﻣﻮﺭﺩ ﮐﻼﺱ ﻫﺎ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ – ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻋﻀﻮ ﮐﻼﺱ ﺑﺎﺷﻨﺪ ﻭﻟﻲ ﻧﻤﻲﺗﻮﺍﻧﻨﺪ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ ﺑﺎﺷﻨﺪ
ﺏ – ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ ﺑﺎﺷﻨﺪ ﻭﻟﻲ ﻧﻤﻲﺗﻮﺍﻧﻨﺪ ﻋﻀﻮ ﮐﻼﺱ ﺑﺎﺷﻨﺪ
ﺝ – ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ ﺑﺎﺷﻨﺪ ﺑﻪ ﺷﺮﻃﻲ ﮐﻪ ﻋﻀﻮ ﺁﻥ ﮐﻼﺱ ﻧﺒﺎﺷﻨﺪ
ﺩ – ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻋﻀﻮ ﮐﻼﺱ ﺑﺎﺷﻨﺪ ﻭ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ ﺑﺎﺷﻨﺪ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 332
– 11ﺍﮔﺮ ﻣﺘﻐﻴﺮ kﻳﮏ ﻋﻀﻮ ﺍﻳﺴﺘﺎ ﺑﺮﺍﻱ ﮐﻼﺱ vectorﺑﻮﺩﻩ ﻭ x1ﻭ x2ﺍﺷﻴﺎﻳﻲ ﺍﺯ
ﮐﻼﺱ vectorﺑﺎﺷﻨﺪ ،ﺁﻧﮕﺎﻩ:
ﺍﻟﻒ – ﺍﺯ kﻓﻘﻂ ﻳﮏ ﻧﻤﻮﻧﻪ ﺩﺭ ﺳﺮﺍﺳﺮ ﺑﺮﻧﺎﻣﻪ ﻣﻮﺟﻮﺩ ﺍﺳﺖ.
ﺏ – x1ﻭ x2ﻫﺮ ﮐﺪﺍﻡ ﻋﻀﻮ kﺧﺎﺹ ﺧﻮﺩ ﺭﺍ ﺩﺍﺭﻧﺪ
ﺝ – ﻓﻘﻂ x1ﺩﺍﺭﺍﻱ ﻋﻀﻮ kﺍﺳﺖ ﻭ x2ﺍﺯ ﻫﻤﺎﻥ kﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ
ﺩ – ﻓﻘﻂ x2ﺩﺍﺭﺍﻱ ﻋﻀﻮ kﺍﺳﺖ ﻭ x1ﺍﺯ ﻫﻤﺎﻥ kﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ
– 12ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺩﺭ ﻣﻮﺭﺩ ﺍﻋﻀﺎﻱ ﺍﻳﺴﺘﺎﻱ ﮐﻼﺱ ،ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟
ﺍﻟﻒ – ﺍﻋﻀﺎﻱ ﺍﻳﺴﺘﺎ ﺑﺎ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ staticﻣﺸﺨﺺ ﻣﻲﺷﻮﻧﺪ
ﺏ – ﺍﻋﻀﺎﻱ ﺍﻳﺴﺘﺎ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﮐﻼﺱ ﺑﺎﺷﻨﺪ
ﺝ – ﺍﻋﻀﺎﻱ ﺍﻳﺴﺘﺎ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﺑﺎﺷﻨﺪ
ﺩ – ﺍﻋﻀﺎﻱ ﺍﻳﺴﺘﺎ ﺩﺭ ﺑﺨﺶ static:ﺍﻋﻼﻥ ﻣﻲﺷﻮﻧﺪ
» ‐ 13ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ« ﺩﺭ ﮐﺪﺍﻡ ﺗﺎﺑﻊ ﻋﻀﻮ ﮐﻼﺱ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ؟
ﺏ – ﺗﺎﺑﻊ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺍﻟﻒ – ﺗﺎﺑﻊ ﺳﻮﺩﻣﻨﺪ ﻣﺤﻠﻲ
ﺩ – ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﺝ – ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ
– 14ﺍﮔﺮ ﺷﻲﺀ m1ﺍﺯ ﮐﻼﺱ mediaﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﺑﺎ ﺍﺟﺮﺍﻱ ﮐﺪ ;media m2=m1
ﮐﺪﺍﻡ ﺗﺎﺑﻊ ﻋﻀﻮ ﮐﻼﺱ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ؟
ﺏ – ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺍﻟﻒ – ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ
ﺩ – ﺗﺎﺑﻊ ﺳﻮﺩﻣﻨﺪ ﻣﺤﻠﻲ ﺝ – ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ
333 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﻳﻚ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﻭ ﻳﻚ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺍﺯ ﻳﻚ ﻛﻼﺱ ﺭﺍ ﺗﻮﺿﻴﺢ
ﺩﻫﻴﺪ.
‐2ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺭﺍﺑﻂ ﮐﻼﺱ ﻭ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻛﻼﺱ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ.
‐3ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺗﺎﺑﻊ ﻋﻀﻮ ﻛﻼﺱ ﻭ ﺗﺎﺑﻊ ﻛﺎﺭﺑﺮﺩﻱ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ.
‐4ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺳﺎﺯﻧﺪﻩ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ.
‐5ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ﻭ ﺳﺎﺯﻧﺪﻩﻫﺎﻱ ﺩﻳﮕﺮ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ.
‐6ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ ﻭ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ.
‐7ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﻭ ﺗﺎﺑﻊ ﺳﻮﺩﻣﻨﺪ ﻣﺤﻠﻲ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ.
‐8ﻧﺎﻡ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﭼﮕﻮﻧﻪ ﺑﺎﻳﺪ ﺑﺎﺷﺪ؟
‐9ﻧﺎﻡ ﺗﺎﺑﻊ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺑﺎﻳﺪ ﭼﮕﻮﻧﻪ ﺑﺎﺷﺪ؟
‐10ﻫﺮ ﻛﻼﺱ ﭼﻪ ﺗﻌﺪﺍﺩ ﺳﺎﺯﻧﺪﻩ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ؟
‐11ﻫﺮ ﻛﻼﺱ ﭼﻪ ﺗﻌﺪﺍﺩ ﻧﺎﺑﻮﺩﻛﻨﻨﺪﻩ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ؟
‐12ﭼﮕﻮﻧﻪ ﻭ ﭼﺮﺍ ﺍﺯ ﻋﻤﻠﮕﺮ ﺟﺪﺍﺳﺎﺯﻱ ﺣﻮﺯﻩ ::ﺩﺭ ﺗﻌﺮﻳﻒ ﻛﻼﺱﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ
ﻣﻲﺷﻮﺩ؟
‐13ﻛﺪﺍﻡ ﺗﺎﺑﻊ ﻋﻀﻮ ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﻛﺎﺭ ﺗﻮﺳﻂ ﻛﺎﻣﭙﺎﻳﻠﺮ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﺍﮔﺮ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺁﻥ
ﺭﺍ ﺻﺮﻳﺤﺎ ﺩﺭ ﺗﻌﺮﻳﻒ ﻛﻼﺱ ﻧﮕﻨﺠﺎﻧﻴﺪﻩ ﺑﺎﺷﺪ؟
‐14ﺩﺭ ﮐﺪ ﺯﻳﺮ ﭼﻨﺪ ﺩﻓﻌﻪ ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ؟
)Widget f(Widget u
;){ Widget v(u
;Widget w = v
;return w
}
)(main
;{ Widget x
;))Widget y = f(f(x
}
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 334
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﻛﻼﺱ Pointﺭﺍ ﺑﺮﺍﻱ ﻧﻘﺎﻁ ﺳﻪ ﺑﻌﺪﻱ ) (x, y, zﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻛﻨﻴﺪ .ﻳﻚ
ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ،ﻳﻚ ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ ،ﻳﻚ ﺗﺎﺑﻊ )( negateﺗﺎ ﻧﻘﻂۀ ﻣﻮﺭﺩ ﻧﻈﺮ ﺭﺍ ﻣﻨﻔﻲ
ﮐﻨﺪ ،ﻳﻚ ﺗﺎﺑﻊ )( normﺑﺮﺍﻱ ﺑﺮﮔﺮﺩﺍﻧﺪﻥ ﻓﺎﺻﻠﻪ ﺍﺯ ﻣﺒﺪﺍﺀ ) (0, 0, 0ﻭ ﻳﻚ ﺗﺎﺑﻊ
)( printﺑﻪ ﺍﻳﻦ ﮐﻼﺱ ﺍﺿﺎﻓﻪ ﮐﻨﻴﺪ.
‐2ﻛﻼﺱ stackﺭﺍ ﺑﺮﺍﻱ ﭘﺸﺘﻪﻫﺎﻳﻲ ﺍﺯ ﻧﻮﻉ intﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻛﻨﻴﺪ .ﻳﻚ ﺳﺎﺯﻧﺪۀ
ﭘﻴﺶﻓﺮﺽ ،ﻳﻚ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﻭ ﺗﻮﺍﺑﻊ ﺍﺟﺮﺍﻱ ﻋﻤﻠﻴﺎﺕ ﻣﻌﻤﻮﻝ ﭘﺸﺘﻪ )( pushﻭ )(pop
ﻭ )( isEmptyﻭ )( isFullﺭﺍ ﺑﻪ ﺍﻳﻦ ﮐﻼﺱ ﺍﺿﺎﻓﻪ ﮐﻨﻴﺪ .ﺍﺯ ﺁﺭﺍﻳﻪﻫﺎ ﺑﺮﺍﻱ ﺍﻳﻦ
ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﺪ.
‐3ﻛﻼﺱ Timeﺭﺍ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻛﻨﻴﺪ .ﻫﺮ ﺷﻲ ﺍﺯ ﺍﻳﻦ ﻛﻼﺱ ،ﻳﻚ ﺯﻣﺎﻥ ﻭﻳﮋﻩ ﺍﺯ ﺭﻭﺯ ﺭﺍ
ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺳﺎﻋﺖ ،ﺩﻗﻴﻘﻪ ﻭ ﺛﺎﻧﻴﻪ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﮐﻨﺪ.
ﻳﻚ ﺳﺎﺯﻧﺪﻩ ،ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ،ﺗﺎﺑﻊ) advance(int h,int m,int sﺑﺮﺍﻱ ﺟﻠﻮ
ﺑﺮﺩﻥ ﺯﻣﺎﻥ ﻓﻌﻠﻲ ﻳﻚ ﺷﻲﺀ ﻣﻮﺟﻮﺩ ،ﺗﺎﺑﻊ) reset(int h,int m,int sﺑﺮﺍﻱ
ﻧﻮ ﻛﺮﺩﻥ ﺯﻣﺎﻥ ﻓﻌﻠﻲ ﻳﻚ ﺷﻲﺀ ﻣﻮﺟﻮﺩ ﻭ ﻳﻚ ﺗﺎﺑﻊ )( printﺑﻪ ﺍﻳﻦ ﮐﻼﺱ ﺍﺿﺎﻓﻪ ﮐﻨﻴﺪ.
‐4ﻛﻼﺱ Randomﺭﺍ ﺑﺮﺍﻱ ﺗﻮﻟﻴﺪ ﻛﺮﺩﻥ ﺍﻋﺪﺍﺩ ﺷﺒﻪﺗﺼﺎﺩﻓﻲ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻛﻨﻴﺪ.
‐5ﻛﻼﺱ personﺭﺍ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻛﻨﻴﺪ .ﻫﺮ ﺷﻲ ﺍﺯ ﺍﻳﻦ ﻛﻼﺱ ،ﻧﻤﺎﻳﺎﻥﮔﺮ ﻳﻚ ﺍﻧﺴﺎﻥ
ﺍﺳﺖ .ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺍﻳﻦ ﮐﻼﺱ ﺑﺎﻳﺪ ﺷﺎﻣﻞ ﻧﺎﻡ ﺷﺨﺺ ،ﺳﺎﻝ ﺗﻮﻟﺪ ﻭ ﺳﺎﻝ ﻭﻓﺎﺕ ﺑﺎﺷﺪ.
ﻳﮏ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ،ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ،ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﻭ ﻳﮏ ﺗﺎﺑﻊ )( printﺑﻪ ﺍﻳﻦ
ﮐﻼﺱ ﺍﺿﺎﻓﻪ ﮐﻨﻴﺪ.
‐6ﻛﻼﺱ Matrixﺭﺍ ﺑﺮﺍﻱ ﺁﺭﺍﻳﻪﻫﺎﻱ 2×2ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻛﻨﻴﺪ:
⎤ ⎡a b
⎥ ⎢c d
⎣ ⎦
ﻳﻚ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ،ﻳﻚ ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ ،ﻳﻚ ﺗﺎﺑﻊ )( inverseﻛﻪ ﻣﻌﻜﻮﺱ ﺁﺭﺍﻳﻪ ﺭﺍ
ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ،ﻳﻚ ﺗﺎﺑﻊ )( detﻛﻪ ﺩﺗﺮﻣﻴﻨﺎﻥ ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ،ﻳﻚ ﺗﺎﺑﻊ ﺑﻮﻟﻲ
335 ﻓﺼﻞ ﻢ /ﺷﯽﮔﺮاﻳﯽ
)( isSingularﻛﻪ ﺑﺴﺘﻪ ﺑﻪ ﺍﻳﻦ ﻛﻪ ﺩﺗﺮﻣﻴﻨﺎﻥ ﺻﻔﺮ ﺑﺎﺷﺪ ﻳﺎ ﻧﻪ ﻣﻘﺪﺍﺭ ﻳﮏ ﻳﺎ ﺻﻔﺮ ﺭﺍ
ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭ ﻳﻚ ﺗﺎﺑﻊ )( printﺑﻪ ﺍﻳﻦ ﮐﻼﺱ ﺍﺿﺎﻓﻪ ﮐﻨﻴﺪ.
‐7ﻳﻚ ﻛﻼﺱ pointﺑﺮﺍﻱ ﻧﻘﺎﻁ ﺩﻭ ﺑﻌﺪﻱ ) (x, yﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﮐﻨﻴﺪ .ﻳﻚ ﺳﺎﺯﻧﺪۀ
ﭘﻴﺶﻓﺮﺽ ،ﻳﻚ ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ ،ﻳﻚ ﺗﺎﺑﻊ )( negateﺑﺮﺍﻱ ﺗﺒﺪﻳﻞ ﻧﻘﻂۀ ﻣﻮﺭﺩ ﻧﻈﺮ ﺑﻪ
ﻣﻨﻔﻲ ،ﻳﻚ ﺗﺎﺑﻊ )( normﺑﺮﺍﻱ ﺑﺮﮔﺮﺩﺍﻧﺪﻥ ﻓﺎﺻﻞۀ ﻧﻘﻄﻪ ﺍﺯ ﻣﺒﺪﺍﺀ ) (0,0ﻭ ﻳﻚ ﺗﺎﺑﻊ
)( printﺑﻪ ﺍﻳﻦ ﮐﻼﺱ ﺍﺿﺎﻓﻪ ﮐﻨﻴﺪ.
‐8ﻛﻼﺱ Circleﺭﺍ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﮐﻨﻴﺪ .ﻫﺮ ﺷﻲ ﺩﺭ ﺍﻳﻦ ﻛﻼﺱ ﻳﻚ ﺩﺍﻳﺮﻩ ﺭﺍ ﻧﺸﺎﻥ
ﻣﻲﺩﻫﺪ ﮐﻪ ﺷﻌﺎﻉ ﺁﻥ ﻭ ﻣﺨﺘﺼﺎﺕ xﻭ yﺍﺯ ﻣﺮﻛﺰ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ floatﻧﮕﻬﺪﺍﺭﻱ
ﻣﻲﻛﻨﺪ .ﻳﮏ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ،ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ،ﻳﻚ ﺗﺎﺑﻊ )( areaﻭ ﻳﻚ ﺗﺎﺑﻊ
)( circumferenceﮐﻪ ﻣﺤﻴﻂ ﺩﺍﻳﺮۀ ﻣﺬﮐﻮﺭ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ،ﺑﻪ ﺍﻳﻦ ﮐﻼﺱ ﺍﺿﺎﻓﻪ
ﮐﻨﻴﺪ.
‐9ﮐﻼﺱ Stackﺩﺭ ﻣﺴﺄﻝۀ 2ﺭﺍ ﺑﺎ ﺍﻓﺰﻭﺩﻥ ﺗﺎﺑﻊ )( countﺑﻪ ﺁﻥ ،ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ .ﺗﺎﺑﻊ
ﻣﺬﮐﻮﺭ ﺗﻌﺪﺍﺩ ﺍﻗﻼﻡ ﺩﺭﻭﻥ ﭘﺸﺘﻪ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
‐10ﮐﻼﺱ Stackﺩﺭ ﻣﺴﺄﻝۀ ﻗﺒﻞ ﺭﺍ ﺑﺎ ﺍﻓﺰﻭﺩﻥ ﺗﺎﺑﻊ )( printﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ .ﺗﺎﺑﻊ
ﻣﺬﮐﻮﺭ ﻣﺤﺘﻮﻳﺎﺕ ﭘﺸﺘﻪ ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ.
‐11ﮐﻼﺱ Stackﺩﺭ ﻣﺴﺄﻝۀ ﻗﺒﻞ ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﮐﻪ ﺑﻪ ﺟﺎﻱ ﻣﻘﺎﺩﻳﺮ ﻧﻮﻉ ،int
ﻣﻘﺪﺍﺭﻫﺎﻱ floatﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﮐﻨﺪ.
‐12ﮐﻼﺱ Circleﺩﺭ ﻣﺴﺄﻝۀ 8ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﮐﻪ ﺷﺎﻣﻞ ﺗﺎﺑﻊ )(area
ﺑﺎﺷﺪ .ﺍﻳﻦ ﺗﺎﺑﻊ ﻣﺴﺎﺣﺖ ﺩﺍﻳﺮۀ ﻣﺬﮐﻮﺭ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ.
‐13ﮐﻼﺱ Matrixﺩﺭ ﻣﺴﺄﻝۀ 6ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﮐﻪ ﺁﺭﺍﻳﻪﻫﺎﻱ 3×3ﺭﺍ
ﻧﮕﻬﺪﺍﺭﻱ ﮐﻨﺪ .ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﮐﻪ ﺑﺎ ﺍﻳﻦ ﺁﺭﺍﻳﻪﻫﺎ ﺳﺎﺯﮔﺎﺭ ﺑﺎﺷﻨﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 336
ﻓﺼﻞ ﺩﻫﻢ
»ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ«
10‐1ﻣﻘﺪﻣﻪ
ﺩﺭ C++ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ 45ﻋﻤﻠﮕﺮ ﻣﺨﺘﻠﻒ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﮐﻪ ﺑﺮﺍﻱ ﮐﺎﺭﻫﺎﻱ ﻣﺘﻨﻮﻋﻲ
ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ .ﻫﻢۀ ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﺑﺮﺍﻱ ﮐﺎﺭ ﮐﺮﺩﻥ ﺑﺎ ﺍﻧﻮﺍﻉ ﺑﻨﻴﺎﺩﻱ )ﻣﺜﻞ intﻭ
floatﻭ (charﺳﺎﺯﮔﺎﺭﻱ ﺩﺍﺭﻧﺪ .ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﮐﻼﺳﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﻴﻢ ،ﺩﺭ ﺣﻘﻴﻘﺖ
ﻳﮏ ﻧﻮﻉ ﺟﺪﻳﺪ ﺭﺍ ﺑﻪ ﺍﻧﻮﺍﻉ ﻣﻮﺟﻮﺩ ﺍﺿﺎﻓﻪ ﮐﺮﺩﻩﺍﻳﻢ .ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﺨﻮﺍﻫﻴﻢ ﺍﺷﻴﺎﻱ ﺍﻳﻦ
ﮐﻼﺱ ﺭﺍ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺕ ﺭﻳﺎﺿﻲ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ .ﺍﻣﺎ ﭼﻮﻥ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﻳﺎﺿﻲ )ﻣﺜﻞ +ﻳﺎ = ﻳﺎ
=* ( ﭼﻴﺰﻱ ﺭﺍﺟﻊ ﺑﻪ ﺍﺷﻴﺎﻱ ﮐﻼﺱ ﺟﺪﻳﺪ ﻧﻤﻲﺩﺍﻧﻨﺪ ،ﻧﻤﻲﺗﻮﺍﻧﻨﺪ ﺑﻪ ﺩﺭﺳﺘﻲ ﮐﺎﺭ ﮐﻨﻨﺪ.
C++ﺑﺮﺍﻱ ﺭﻓﻊ ﺍﻳﻦ ﻣﺸﮑﻞ ﭼﺎﺭﻩ ﺍﻧﺪﻳﺸﻴﺪﻩ ﻭ ﺍﻣﮑﺎﻥ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ 1ﺭﺍ ﺗﺪﺍﺭﮎ
ﺩﻳﺪﻩ ﺍﺳﺖ .ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﺑﻪ ﻋﻤﻠﮕﺮﻫﺎ ﺗﻌﺎﺭﻳﻒ ﺟﺪﻳﺪﻱ
ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ ﺗﺎ ﺑﺘﻮﺍﻧﻨﺪ ﺑﺎ ﺍﺷﻴﺎﻱ ﮐﻼﺱ ﻣﻮﺭﺩ ﻧﻈﺮ ﺑﻪ ﺩﺭﺳﺘﻲ ﮐﺎﺭ ﮐﻨﻨﺪ.
ﺩﺭ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﻣﺤﺪﻭﺩﻳﺘﻲ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ .ﻳﻌﻨﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﭼﻨﺪﻳﻦ ﮐﻼﺱ
ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ ﮐﻪ ﻫﺮ ﮐﺪﺍﻡ ﺳﺮﺑﺎﺭﻱ ﺭﺍ ﺑﻪ ﻳﮏ ﻋﻤﻠﮕﺮ ﻣﻔﺮﻭﺽ ﻣﻲﺍﻓﺰﺍﻳﺪ .ﻫﻴﭻ ﻳﮏ ﺍﺯ ﺍﻳﻦ
ﺳﺮﺑﺎﺭﻫﺎ ﺩﻳﮕﺮﻱ ﺭﺍ ﻧﻘﺾ ﻧﻤﻲﮐﻨﺪ ﻭ ﻋﻤﻠﮕﺮ ﻣﺮﺑﻮﻃﻪ ﺑﺎ ﺍﺷﻴﺎﻱ ﻫﺮ ﮐﻼﺱ ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺳﺮﺑﺎﺭ
ﻫﻤﺎﻥ ﮐﻼﺱ ﺭﻓﺘﺎﺭ ﻣﻲﮐﻨﺪ .ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺑﻪ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﺑﭙﺮﺩﺍﺯﻳﻢ ،ﻳﮏ ﻣﻔﻬﻮﻡ
ﺟﺪﻳﺪ ﺭﺍ ﺩﺭ ﺷﻲﮔﺮﺍﻳﻲ ﻣﻌﺮﻓﻲ ﻣﻲﮐﻨﻴﻢ.
10‐2ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ
ﺍﻋﻀﺎﻳﻲ ﺍﺯ ﮐﻼﺱ ﮐﻪ ﺑﻪ ﺷﮑﻞ ﺧﺼﻮﺻﻲ ) (privateﺍﻋﻼﻥ ﻣﻲﺷﻮﻧﺪ ﻓﻘﻂ ﺍﺯ
ﺩﺍﺧﻞ ﻫﻤﺎﻥ ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲﺍﻧﺪ ﻭ ﺍﺯ ﺑﻴﺮﻭﻥ ﮐﻼﺱ )ﺩﺭﻭﻥ ﺑﺪﻥۀ ﺍﺻﻠﻲ( ﺍﻣﮑﺎﻥ
ﺩﺳﺘﺮﺳﻲ ﺑﻪ ﺁﻥﻫﺎ ﻧﻴﺴﺖ .ﺍﻣﺎ ﻳﮏ ﺍﺳﺘﺜﻨﺎ ﻭﺟﻮﺩ ﺩﺍﺭﺩ .ﺗﺎﺑﻊ ﺩﻭﺳﺖ 1ﺗﺎﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ﻋﻀﻮ
ﻳﮏ ﮐﻼﺱ ﻧﻴﺴﺖ ﺍﻣﺎ ﺍﺟﺎﺯﻩ ﺩﺍﺭﺩ ﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺁﻥ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺑﻪ ﮐﺪ
ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ:
class Ratio
;){ friend int numReturn(Ratio
public:
;)(Ratio
;)(~Ratio
private:
;int num, den
}
)(int main
;){ Ratio x(22, 7
;cout << numReturn(x) << endl
}
ﺩﺭ ﮐﺪ ﺑﺎﻻ ﺗﺎﺑﻊ )( numReturnﻋﻀﻮ ﮐﻼﺱ Ratioﻧﻴﺴﺖ ﺑﻠﮑﻪ ﺩﻭﺳﺖ ﺁﻥ ﺍﺳﺖ.
ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﺗﺎﺑﻊ ﺭﺍ ﺩﻭﺳﺖ ﻳﮏ ﮐﻼﺱ ﻣﻌﺮﻓﻲ ﮐﻨﻴﻢ ،ﺁﻥ ﺗﺎﺑﻊ ﺭﺍ ﺩﺭ ﮐﻼﺱ ﻣﺬﮐﻮﺭ
ﺍﻋﻼﻥ ﮐﺮﺩﻩ ﻭ ﺍﺯ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ friendﺩﺭ ﺍﻋﻼﻥ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ .ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ ﺑﺎﻳﺪ
ﻗﺒﻞ ﺍﺯ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﻭ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﺍﻋﻼﻥ ﺷﻮﻧﺪ ﻭ ﺗﻌﺮﻳﻒ ﺁﻥﻫﺎ ﺑﺎﻳﺪ ﺧﺎﺭﺝ ﺍﺯ
ﮐﻼﺱ ﻭ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺗﺎﺑﻊ ﻣﻌﻤﻮﻟﻲ ﺑﺎﺷﺪ ﺯﻳﺮﺍ ﺗﺎﺑﻊ ﺩﻭﺳﺖ ،ﻋﻀﻮ ﮐﻼﺱ ﻧﻴﺴﺖ .ﺗﻮﺍﺑﻊ
ﺩﻭﺳﺖ ﺑﻴﺸﺘﺮ ﺩﺭ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﻧﺪ.
ﺑﻪ ﻧﺤﻮ ﺍﻋﻼﻥ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺩﻗﺖ ﻧﻤﺎﻳﻴﺪ .ﻧﺎﻡ ﺍﻳﻦ ﺗﺎﺑﻊ ﻋﻀﻮ operator= ،ﺍﺳﺖ ﻭ
ﻓﻬﺮﺳﺖ ﺁﺭﮔﻮﻣﺎﻥ ﺁﻥ ﻣﺎﻧﻨﺪ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻣﻲﺑﺎﺷﺪ ﻳﻌﻨﻲ ﻳﮏ ﺁﺭﮔﻮﻣﺎﻥ ﻣﻨﻔﺮﺩ ﺩﺍﺭﺩ ﮐﻪ ﺍﺯ ﻧﻮﻉ
ﻫﻤﺎﻥ ﮐﻼﺱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻃﺮﻳﻖۀ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ .ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺭﺍ
ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ:
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 340
ﮐﺪ ﻓﻮﻕ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺷﻲﺀ rﺭﺍ ﺑﻪ ﺩﺭﻭﻥ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺷﻴﺌﻲ ﮐﻪ ﻣﺎﻟﮏ ﻓﺮﺍﺧﻮﺍﻧﻲ
ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺍﺳﺖ ،ﮐﭙﻲ ﻣﻲﮐﻨﺪ .ﺣﺎﻻ ﺍﮔﺮ xﻭ yﺩﻭ ﺷﻲ ﺍﺯ ﮐﻼﺱ Ratioﺑﺎﺷﻨﺪ ،ﮐﺪ
; x=yﺑﺎ ﺗﻌﺎﺭﻳﻒ ﺑﺎﻻ ﺑﻪ ﺩﺭﺳﺘﻲ ﮐﺎﺭ ﻣﻲﮐﻨﺪ ﻭﻟﻲ ﺍﻳﻦ ﻫﻨﻮﺯ ﮐﺎﻓﻲ ﻧﻴﺴﺖ.
10‐4ﺍﺷﺎﺭﻩﮔﺮ this
ﺩﺭ C++ﻣﻲﺗﻮﺍﻧﻴﻢ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺯﻧﺠﻴﺮﻩﺍﻱ ﻣﺜﻞ ﺯﻳﺮ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ:
;x = y = z = 3.14
ﺍﺟﺮﺍﻱ ﮐﺪ ﺑﺎﻻ ﺍﺯ ﺭﺍﺳﺖ ﺑﻪ ﭼﭗ ﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ .ﻳﻌﻨﻲ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ 3.14ﺩﺭﻭﻥ zﻗﺮﺍﺭ
ﻣﻲﮔﻴﺮﺩ ﻭ ﺳﭙﺲ ﻣﻘﺪﺍﺭ zﺩﺭﻭﻥ yﮐﭙﻲ ﻣﻲﺷﻮﺩ ﻭ ﺳﺮﺍﻧﺠﺎﻡ ﻣﻘﺪﺍﺭ yﺩﺭﻭﻥ xﻗﺮﺍﺭ ﺩﺍﺩﻩ
ﻣﻲﺷﻮﺩ .ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﮐﻪ ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻞ ﺫﮐﺮ ﺷﺪ ،ﻧﻤﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺷﮑﻞ ﺯﻧﺠﻴﺮﻩﺍﻱ ﺑﻪ ﮐﺎﺭ
ﺭﻭﺩ .ﺑﻪ ﺑﺮﻫﺎﻥ ﺯﻳﺮ ﺗﻮﺟﻪ ﮐﻨﻴﺪ:
ﻓﺮﺽ ﮐﻨﻴﻢ ﺳﻪ ﺷﻲﺀ xﻭ yﻭ zﺍﺯ ﻳﮏ ﮐﻼﺱ ﺑﺎﺷﻨﺪ ﻭ ﺩﺭ ﺟﺎﻳﮕﺰﻳﻨﻲ x=y=z
ﺷﺮﮐﺖ ﮐﻨﻨﺪ .ﺟﺎﻳﮕﺰﻳﻨﻲ ﻣﻔﺮﻭﺽ ﺭﺍ ﺑﻪ ﺷﮑﻞ ) x=(y=zﻣﻲﻧﻮﻳﺴﻴﻢ .ﻋﺒﺎﺭﺕ ﺩﺍﺧﻞ
ﭘﺮﺍﻧﺘﺰ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻳﮏ ﺗﺎﺑﻊ ﺗﺼﻮﺭ ﮐﻨﻴﻢ .ﭘﺲ ﺩﺭ ﺣﻘﻴﻘﺖ ) x=f(y,zﺍﺳﺖ .ﻣﺸﺨﺺ
ﺍﺳﺖ ﮐﻪ ﺗﺎﺑﻊ fﺑﺎﻳﺪ ﺩﺍﺭﺍﻱ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺍﺯ ﻧﻮﻉ xﺑﺎﺷﺪ .ﭼﻮﻥ ﺗﺎﺑﻊ fﻫﻤﺎﻥ ﺗﺎﺑﻊ ﻋﻤﻠﮕﺮ
ﺟﺎﻳﮕﺰﻳﻨﻲ ﺍﺳﺖ ،ﻧﺘﻴﺠﻪ ﻣﻲﺷﻮﺩ ﮐﻪ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺑﺎﻳﺪ ﻳﮏ ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ ﺍﺯ ﻧﻮﻉ
ﻫﻤﺎﻥ ﮐﻼﺱ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺍﻣﺎ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ ﭼﻴﺴﺖ؟ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻳﮏ ﺷﻲ ﺭﺍ
ﺩﺭﻭﻥ ﺷﻲﺀ ﺩﻳﮕﺮ ﮐﭙﻲ ﻣﻲﮐﻨﺪ ﻭ ﭼﻴﺰﻱ ﺑﺮﺍﻱ ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻥ ﺑﺎﻗﻲ ﻧﻤﻲﻣﺎﻧﺪ.
ﺍﺷﺎﺭﻩﮔﺮ thisﻣﺴﺎﻟﻪ ﺭﺍ ﺣﻞ ﻣﻲﮐﻨﺪ .ﺍﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ ﻣﺨﻔﻲ ،ﻫﻤﻴﺸﻪ ﺑﻪ ﺷﻴﺌﻲ ﺍﺷﺎﺭﻩ
ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻻﻥ ﺭﻭﻱ ﺁﻥ ﻋﻤﻠﻲ ﺻﻮﺭﺕ ﮔﺮﻓﺘﻪ ﺍﺳﺖ .ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ ﺍﺯ ﻋﻤﻠﮕﺮ
ﺟﺎﻳﮕﺰﻳﻨﻲ ،ﻫﻤﻴﻦ ﺍﺷﺎﺭﻩﮔﺮ thisﺍﺳﺖ ﮐﻪ ﺑﻪ ﺷﻴﺌﻲ ﮐﻪ ﺍﻻﻥ ﻣﻘﺪﺍﺭﻱ ﺩﺭ ﺁﻥ ﮐﭙﻲ ﺷﺪﻩ
ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ .ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺭ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺑﻌﺪﻱ ﺍﺯ ﺯﻧﺠﻴﺮﻩ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﺷﻮﺩ .ﺍﮐﻨﻮﻥ
341 ﻓﺼﻞ دهﻢ /ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ
ﻣﻲﺗﻮﺍﻧﻴﻢ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﮐﺎﻣﻞ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﮐﻨﻴﻢ .ﺍﻟﮕﻮﻱ ﮐﻠﻲ ﺑﺮﺍﻱ
ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺩﺭ ﮐﻼﺱ ﻣﻔﺮﻭﺽ Tﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
;)&T& operator=(const T
ﻫﻤﭽﻨﻴﻦ ﺍﻟﮕﻮﻱ ﮐﻠﻲ ﺗﻌﺮﻳﻒ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺑﺮﺍﻱ ﮐﻼﺱ ﻣﻔﺮﻭﺽ Tﺑﻪ ﺻﻮﺭﺕ ﺯﻳﺮ
ﺍﺳﺖ:
)T& T::operator=(const T& t
{ // assign each member datum of t to the corresponding
// member datum of the owner
;return *this
}
ﮐﻪ ﺑﻪ ﺟﺎﻱ ﺩﻭ ﺧﻂ ﺗﻮﺿﻴﺤﻲ ﺩﺭ ﮐﺪ ﻓﻮﻕ ،ﺩﺳﺘﻮﺭﺍﺕ ﻻﺯﻡ ﻭ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﻣﺜﺎﻝ
ﺑﻌﺪﻱ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪۀ ﮐﺎﻣﻞ ﺑﺮﺍﻱ ﮐﻼﺱ Ratioﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
;)Ratio x, y, z(22,7
;x = y = z
ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﻋﻤﻞ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺑﺎ ﻋﻤﻞ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺗﻔﺎﻭﺕ ﺩﺍﺭﺩ ،ﻫﺮ ﭼﻨﺪ
ﻫﺮ ﺩﻭ ﺍﺯ ﻋﻤﻠﮕﺮ ﻳﮑﺴﺎﻧﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻨﺪ .ﻣﺜﻼ ﺩﺭ ﮐﺪ ﺯﻳﺮ:
;)Ratio x(22,7 // this is an initialization
;)Ratio y(x // this is an initialization
;Ratio z = x // this is an initialization
;Ratio w
;w = x // this is an assignment
ﺳﻪ ﺩﺳﺘﻮﺭ ﺍﻭﻝ ،ﺩﺳﺘﻮﺭﺍﺕ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻫﺴﺘﻨﺪ ﻭﻟﻲ ﺩﺳﺘﻮﺭ ﺁﺧﺮ ﻳﮏ ﺩﺳﺘﻮﺭ ﺟﺎﻳﮕﺰﻳﻨﻲ
ﺍﺳﺖ .ﺩﺳﺘﻮﺭ ﻣﻘﺪﺍﺭﺩﻫﻲ ،ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺭﺍ ﻓﺮﺍ ﻣﻲﺧﻮﺍﻧﺪ ﻭﻟﻲ ﺩﺳﺘﻮﺭ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻋﻤﻠﮕﺮ
ﺟﺎﻳﮕﺰﻳﻨﻲ ﺭﺍ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﮐﻨﺪ.
ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺭﺍﺑﻂۀ ﻓﻮﻕ ﻭ ﺁﻥﭼﻪ ﺩﺭ ﺑﺨﺶ ﻗﺒﻠﻲ ﮔﻔﺘﻴﻢ ،ﻋﻤﻠﮕﺮ ﺿﺮﺏ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪﻩ
ﺑﺎﻳﺪ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ ﻳﮏ ﮐﻼﺱ ﻭ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺑﮕﻴﺮﺩ ﻭ ﻳﮏ ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ
ﺍﺯ ﻧﻮﻉ ﻫﻤﺎﻥ ﮐﻼﺱ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﭘﺲ ﺍﻧﺘﻈﺎﺭ ﺩﺍﺭﻳﻢ ﻗﺎﻟﺐ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺿﺮﺏ
ﺑﺮﺍﻱ ﮐﻼﺱ Ratioﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺑﺎﺷﺪ:
)Ratio operator*(Ratio x, Ratio y
;){ Ratio z(x.num*y.num, x.den*y.den
;return z
}
343 ﻓﺼﻞ دهﻢ /ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ
ﺗﺎﺑﻊ ﻓﻮﻕ ﺑﻪ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ Ratioﻧﻴﺎﺯ ﺩﺍﺭﺩ .ﭼﻨﻴﻦ ﺗﺎﺑﻌﻲ ﻧﻤﻲﺗﻮﺍﻧﺪ ﻋﻀﻮﻱ
ﺍﺯ ﮐﻼﺱ ﺑﺎﺷﺪ .ﺍﮔﺮ ﺑﺨﻮﺍﻫﻴﻢ ﺗﺎﺑﻌﻲ ﻋﻀﻮ ﮐﻼﺱ ﻣﻔﺮﻭﺽ Tﺑﺎﺷﺪ ﺑﺎﻳﺪ ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ
ﺣﺪﺍﮐﺜﺮ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ Tﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ )ﺗﺤﻘﻴﻖ ﮐﻨﻴﺪ ﮐﻪ ﭼﺮﺍ ﭼﻨﻴﻦ ﺍﺳﺖ( .ﺍﺯ
ﻃﺮﻓﻲ ﺍﮔﺮ ﺗﺎﺑﻌﻲ ﻋﻀﻮ ﮐﻼﺱ ﻧﺒﺎﺷﺪ ،ﻧﻤﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺁﻥ ﮐﻼﺱ ﺩﺳﺘﻴﺎﺑﻲ
ﮐﻨﺪ .ﺑﺮﺍﻱ ﺭﻓﻊ ﺍﻳﻦ ﻣﺤﺪﻭﺩﻳﺖﻫﺎ ،ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺿﺮﺏ ﺭﺍ ﺑﺎﻳﺪ ﺑﻪ ﻋﻨﻮﺍﻥ ﺗﺎﺑﻊ
ﺩﻭﺳﺖ ﮐﻼﺱ ﻣﻌﺮﻓﻲ ﮐﻨﻴﻢ .ﻟﺬﺍ ﻗﺎﻟﺐ ﮐﻠﻲ ﺑﺮﺍﻱ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺿﺮﺏ ﺩﺭﻭﻥ ﮐﻼﺱ
ﻣﻔﺮﻭﺽ Tﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
Class T
;)&{ friend T operator*(const T&, const T
public:
// public members
private:
// private members
}
ﻭ ﺍﺯ ﺁﻥﺟﺎ ﮐﻪ ﺗﺎﺑﻊ ﺩﻭﺳﺖ ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﻧﻴﺴﺖ ،ﺗﻌﺮﻳﻒ ﺑﺪﻥۀ ﺁﻥ ﺑﺎﻳﺪ ﺧﺎﺭﺝ ﺍﺯ
ﮐﻼﺱ ﺻﻮﺭﺕ ﭘﺬﻳﺮﺩ .ﺩﺭ ﺗﻌﺮﻳﻒ ﺑﺪﻥۀ ﺗﺎﺑﻊ ﺩﻭﺳﺖ ﺑﻪ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ friendﻧﻴﺎﺯﻱ
ﻧﻴﺴﺖ ﻭ ﻋﻤﻠﮕﺮ ﺟﺪﺍﺳﺎﺯﻱ ﺣﻮﺯﻩ ::ﻧﻴﺰ ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﻲﺷﻮﺩ:
)T operator*(const T& x, const T& y
;{ T z
// required operations for z = x*y
;return z
}
public:
;)Ratio(int = 0, int = 1
;)&Ratio(const Ratio
;)&Ratio& operator=(const Ratio
// other declarations go here
private:
;int num, den
// other declarations go here
;}
)Ratio operator*(const Ratio& x, const Ratio& y
;){ Ratio z(x.num * y.num , x.den * y.den
;return z
}
)(int main
;{ Ratio x(22,7) ,y(-3,8) ,z
;z = x // assignment operator is called
;z.print(); cout << endl
;x = y*z // multiplication operator is called
;x.print(); cout << endl
}
22/7
-66/56
class T
{ public:
;)&T& operator*=(const T
// other public members
private:
// private members
;}
;den = den*r.den
;return *this
}
ﻫﻤﭽﻨﻴﻦ ﻗﺎﻟﺐ ﮐﻠﻲ ﺗﻌﺮﻳﻒ ﺑﺪﻥۀ ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﻪ ﺻﻮﺭﺕ ﺯﻳﺮ ﻣﻲﺑﺎﺷﺪ:
)int operator==(const T& x, const T& y
{ // required operations to finding result
347 ﻓﺼﻞ دهﻢ /ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ
;return result
}
ﮐﻪ ﺑﻪ ﺟﺎﻱ resultﻳﮏ ﻣﻘﺪﺍﺭ ﺑﻮﻟﻴﻦ ﻳﺎ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ .ﺳﺎﻳﺮ
ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﺍﺑﻄﻪﺍﻱ ﻧﻴﺰ ﺍﺯ ﻗﺎﻟﺐ ﺑﺎﻻ ﭘﻴﺮﻭﻱ ﻣﻲﮐﻨﻨﺪ.
ﻫﺴﺘﻨﺪ ،ﺑﺮﺭﺳﻲ ﺗﺴﺎﻭﻱ x==yﻣﻌﺎﺩﻝ a ﭼﻮﻥ ﺍﺷﻴﺎﻱ ﮐﻼﺱ Ratioﺑﻪ ﺻﻮﺭﺕ ﮐﺴﺮ
b
ﺑﺮﺭﺳﻲ a == cﺍﺳﺖ ﮐﻪ ﺑﺮﺍﻱ ﺑﺮﺭﺳﻲ ﺍﻳﻦ ﺗﺴﺎﻭﻱ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﻘﺪﺍﺭ ) (a*d==b*cﺭﺍ
b d
ﺑﺮﺭﺳﻲ ﮐﻨﻴﻢ .ﺑﺪﻥۀ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﻫﻤﻴﻦ ﺭﺍﺑﻄﻪ ﺭﺍ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﺪ.
ﭘﺲ ﻭﻗﺘﻲ yﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ ،ﺩﺭ ﺍﺻﻞ ﻣﻘﺪﺍﺭ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ numﺁﻥ ﺑﺮﺍﺑﺮ ﺑﺎ num+den
ﺧﻮﺍﻫﺪ ﺷﺪ:
class Ratio
{ public:
} { )Ratio(int n=0, int d=1) : num(n) , den(d
;)(Ratio operator++
} ;void print() { cout << num << '/' << den << endl
private:
;int num, den
// other declarations go here
;}
)(int main
;{ Ratio x(22,7), y = ++x
;)(cout << "y = "; y.print
;)(cout << ", x = "; x.print
}
)(Ratio Ratio::operator++
;{ num += den
;return *this
}
y = 29/7, x = 29/7
ﺑﺪﻥۀ ﺁﻥ .ﺍﻳﻦ ﺩﺳﺘﻮﺭﺍﺕ ﺑﺎﻳﺪ ﻃﻮﺭﻱ ﺑﺎﺷﻨﺪ ﮐﻪ ﻣﻘﺪﺍﺭ ﻋﻤﻠﻮﻧﺪ ﻣﺮﺑﻮﻃﻪ ﺭﺍ ﭘﺲ ﺍﺯ ﺍﻧﺠﺎﻡ
ﺳﺎﻳﺮ ﻣﺤﺎﺳﺒﺎﺕ ﺍﻓﺰﺍﻳﺶ ﺩﻫﻨﺪ ﻧﻪ ﭘﻴﺶ ﺍﺯ ﺁﻥ .ﺑﺮﺍﻱ ﺩﺭﮎ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺗﻮﺟﻪ
ﮐﻨﻴﺪ.
)(int main
;{ Ratio x(22,7) , y = x++
;)(cout << "y = "; y.print
;)(cout << ", x = "; x.print
}
)Ratio Ratio::operator++(int
;{ Ratio temp = *this
;num += den
;return temp
}
351 ﻓﺼﻞ دهﻢ /ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ
ﭘﺎﺭﺍﻣﺘﺮ ﮔﻨﮓ ﺩﺭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ )( operator++ﺫﮐﺮ ﺷﺪﻩ ﻭﻟﻲ ﻫﻴﭻ ﻧﺎﻣﻲ ﻧﺪﺍﺭﺩ ﺗﺎ
ﻣﺸﺨﺺ ﺷﻮﺩ ﮐﻪ ﺍﻳﻦ ﭘﺎﺭﺍﻣﺘﺮ ﻓﻘﻂ ﺑﺮﺍﻱ ﺗﻤﻴﺰ ﺩﺍﺩﻥ ﺗﺎﺑﻊ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺁﻣﺪﻩ ﺍﺳﺖ.
ﻋﻤﻠﮕﺮﻫﺎﻱ ﭘﻴﺶﮐﺎﻫﺸﻲ ﻭ ﭘﺲﮐﺎﻫﺸﻲ ﻧﻴﺰ ﺑﻪ ﻫﻤﻴﻦ ﺷﻴﻮۀ ﻋﻤﻠﮕﺮﻫﺎﻱ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ
ﻭ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﺷﻮﻧﺪ .ﻏﻴﺮ ﺍﺯ ﺍﻳﻦﻫﺎ ،ﻋﻤﻠﮕﺮﻫﺎﻱ ﺩﻳﮕﺮﻱ ﻧﻴﺰ ﻣﺜﻞ ﻋﻤﻠﮕﺮ
ﺧﺮﻭﺟﻲ )<<( ،ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ )>>( ،ﻋﻤﻠﮕﺮ ﺍﻧﺪﻳﺲ )][( ﻭ ﻋﻤﻠﮕﺮ ﺗﺒﺪﻳﻞ ﻧﻴﺰ ﻭﺟﻮﺩ
ﺩﺍﺭﻧﺪ ﮐﻪ ﻣﻲﺗﻮﺍﻥ ﺁﻥﻫﺎ ﺭﺍ ﺑﺮﺍﻱ ﺳﺎﺯﮔﺎﺭﻱ ﺑﺮﺍﻱ ﮐﻼﺱﻫﺎﻱ ﺟﺪﻳﺪ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﮐﺮﺩ.
ﭼﻮﻥ ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﮐﺎﺭﺑﺮﺩ ﮐﻤﺘﺮﻱ ﺩﺍﺭﻧﺪ ﺍﺯ ﺗﻮﺿﻴﺢ ﺁﻥﻫﺎ ﺧﻮﺩﺩﺍﺭﻱ ﻣﻲﮐﻨﻴﻢ .ﺍﮐﻨﻮﻥ ﮐﻪ
ﺍﺻﻮﻝ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﺭﺍ ﺁﻣﻮﺧﺘﻴﺪ ،ﻣﻲﺗﻮﺍﻧﻴﺪ ﺑﺎ ﻣﺮﺍﺟﻌﻪ ﺑﻪ ﻣﺮﺍﺟﻊ C++
ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺳﺎﻳﺮ ﻋﻤﻠﮕﺮﻫﺎ ﺭﺍ ﺗﺤﻘﻴﻖ ﮐﻨﻴﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 352
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﺍﮔﺮ ﺗﺎﺑﻌﻲ ﺩﻭﺳﺖ ﻳﮏ ﮐﻼﺱ ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ:
ﺍﻟﻒ – ﺁﻥ ﺗﺎﺑﻊ ﻳﮏ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﺁﻥ ﮐﻼﺱ ﺍﺳﺖ
ﺏ – ﺁﻥ ﺗﺎﺑﻊ ﻳﮏ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺁﻥ ﮐﻼﺱ ﺍﺳﺖ
ﺝ – ﺁﻥ ﺗﺎﺑﻊ ﻳﮏ ﻋﻀﻮ ﻣﺤﺎﻓﻈﺖﺷﺪۀ ﺁﻥ ﮐﻼﺱ ﺍﺳﺖ
ﺩ – ﺁﻥ ﺗﺎﺑﻊ ﺍﺻﻼ ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﻧﻴﺴﺖ
– 2ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺩﺭ ﻣﻮﺭﺩ ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ ﮐﻼﺱ ،ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ – ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ ﮐﻼﺱ ﻓﻘﻂ ﺍﺟﺎﺯﻩ ﺩﺍﺭﻧﺪ ﺑﻪ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﮐﻼﺱ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﻨﺪ
ﺏ – ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ ﮐﻼﺱ ﺍﺯ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﻣﺤﺴﻮﺏ ﻣﻲﺷﻮﻧﺪ
ﺝ – ﺩﺭ ﺗﻌﺮﻳﻒ ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ ﮐﻼﺱ ﻧﺒﺎﻳﺪ ﺍﺯ ﻋﻤﻠﮕﺮ ﺟﺪﺍﺳﺎﺯﻱ ﺩﺍﻣﻨﻪ ::ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ
ﺩ – ﻫﺮ ﮐﻼﺱ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﻳﮏ ﺗﺎﺑﻊ ﺩﻭﺳﺖ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ
– 3ﺍﺷﺎﺭﻩ ﮔﺮ *thisﭼﻴﺴﺖ؟
ﺍﻟﻒ – ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﻣﺨﻔﻲ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺷﻴﺌﻲ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﮐﻪ ﻫﻢﺍﮐﻨﻮﻥ ﻋﻤﻠﻲ ﺭﻭﻱ ﺁﻥ
ﺻﻮﺭﺕ ﮔﺮﻓﺘﻪ
ﺏ – ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﻣﺨﻔﻲ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﮐﻼﺳﻲ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﮐﻪ ﻫﻢﺍﮐﻨﻮﻥ ﻧﻤﻮﻧﻪﺳﺎﺯﻱ ﺷﺪﻩ
ﺝ – ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﻣﺨﻔﻲ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺗﺎﺑﻌﻲ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﮐﻪ ﻫﻢﺍﮐﻨﻮﻥ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ
ﺩ – ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﻣﺨﻔﻲ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻋﻤﻠﮕﺮﻱ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﮐﻪ ﻫﻢﺍﮐﻨﻮﻥ ﺍﺟﺮﺍ ﺷﺪﻩ
– 4ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺩﺭ ﺭﺍﺑﻄﻪ ﺑﺎ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟
ﺍﻟﻒ – ﻧﺎﻡ ﺗﺎﺑﻊ ﺁﻥ operator==() ،ﺍﺳﺖ
ﺏ – ﺗﺎﺑﻊ ﺁﻥ ،ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﺍﺳﺖ
ﺝ – ﺍﮔﺮ ﺑﻪ ﻃﻮﺭ ﺻﺮﻳﺢ ﺫﮐﺮ ﻧﺸﻮﺩ ،ﺁﻧﮕﺎﻩ ﻳﮏ ﻧﺴﺦۀ ﭘﻴﺶﻓﺮﺽ ﺑﻪ ﮐﻼﺱ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ
ﺩ – ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺁﻥ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺍﺭﺟﺎﻉ ﺍﺳﺖ
– 5ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺑﺘﻮﺍﻧﻴﻢ ﺍﺷﻴﺎﻱ ﻳﮏ ﮐﻼﺱ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺯﻧﺠﻴﺮﻩﺍﻱ ﺩﺭ ﻳﮏ ﻋﻤﻞ ﺣﺴﺎﺑﻲ
ﺷﺮﮐﺖ ﺩﻫﻴﻢ ﺑﺎﻳﺪ:
ﺍﻟﻒ – ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺁﻥ ﻋﻤﻞ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﺍﻋﻼﻥ ﮐﻨﻴﻢ
ﺏ – ﭘﺎﺭﺍﻣﺘﺮ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺁﻥ ﻋﻤﻞ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺍﻋﻼﻥ ﮐﻨﻴﻢ
353 ﻓﺼﻞ دهﻢ /ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ
ﺝ – ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺁﻥ ﻋﻤﻞ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺍﺭﺟﺎﻉ ﻭ ﺍﺯ ﻧﻮﻉ ﻫﻤﺎﻥ ﮐﻼﺱ
ﺍﻋﻼﻥ ﮐﻨﻴﻢ
ﺩ – ﺑﺪﻥۀ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺁﻥ ﻋﻤﻞ ﺭﺍ ﺩﺭ ﻓﺎﻳﻞ ﺟﺪﺍﮔﺎﻧﻪﺍﻱ ﻗﺮﺍﺭ ﺩﻫﻴﻢ
– 6ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺑﺎﻳﺪ:
ﺏ – ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﺑﺎﺷﺪ ﺍﻟﻒ – ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﮐﻼﺱ ﺑﺎﺷﺪ
ﺩ – ﺑﻪ ﺷﮑﻞ ﺗﺎﺑﻊ ﺳﻮﺩﻣﻨﺪ ﻣﺤﻠﻲ ﺑﺎﺷﺪ ﺝ – ﺩﻭﺳﺖ ﮐﻼﺱ ﺑﺎﺷﺪ
– 7ﻓﺮﺽ ﮐﻨﻴﺪ ﮐﻪ ﮐﻼﺱ ﻣﻔﺮﻭﺽ Dateﻣﻮﺟﻮﺩ ﺑﺎﺷﺪ .ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ ﺗﺎﺑﻊ
)& operator<(const Date&, const Dateﺑﺎﻳﺪ:
ﺏ – ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﺑﺎﺷﺪ ﺍﻟﻒ – ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﮐﻼﺱ ﺑﺎﺷﺪ
ﺩ – ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﺑﺎﺷﺪ ﺝ – ﺩﻭﺳﺖ ﮐﻼﺱ ﺑﺎﺷﺪ
– 8ﻓﺮﺽ ﮐﻨﻴﺪ ﮐﻪ ﮐﻼﺱ ﻣﻔﺮﻭﺽ Personﻣﻮﺟﻮﺩ ﺑﺎﺷﺪ .ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ ﺗﺎﺑﻊ
;) Person operator--(intﭼﻪ ﭼﻴﺰﻱ ﺭﺍ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﮐﻨﺪ؟
ﺍﻟﻒ – ﻋﻤﻠﮕﺮ ﭘﻴﺶﮐﺎﻫﺸﻲ ﺭﺍ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﮐﻨﺪ
ﺏ – ﻋﻤﻠﮕﺮ ﭘﺲﮐﺎﻫﺸﻲ ﺭﺍ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﮐﻨﺪ
ﺝ – ﻋﻤﻠﮕﺮ ﺍﻳﻨﺪﮐﺲ ﺭﺍ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﮐﻨﺪ
ﺩ – ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ ﺭﺍ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﮐﻨﺪ
– 9ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪۀ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﻭ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺩﺭ ﭼﻴﺴﺖ؟
ﺍﻟﻒ – ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ،ﻋﻀﻮ ﮐﻼﺱ ﺍﺳﺖ ﻭﻟﻲ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ
ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﻋﻀﻮ ﮐﻼﺱ ﻧﻴﺴﺖ
ﺏ – ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺩﻭﺳﺖ ﮐﻼﺱ ﺍﺳﺖ ﻭﻟﻲ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ
ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺩﻭﺳﺖ ﮐﻼﺱ ﻧﻴﺴﺖ
ﺝ – ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﭘﺎﺭﺍﻣﺘﺮ ﮔﻨﮓ ﺩﺍﺭﺩ ﻭﻟﻲ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ
ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﭘﺎﺭﺍﻣﺘﺮ ﮔﻨﮓ ﻧﺪﺍﺭﺩ
ﺩ – ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺍﺷﺎﺭﻩﮔﺮ *thisﺩﺍﺭﺩ ﻭﻟﻲ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ
ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺍﺷﺎﺭﻩﮔﺮ *thisﻧﺪﺍﺭﺩ
– 10ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺍﺯ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﺍﺑﻄﻪﺍﻱ ﭼﻴﺴﺖ؟
ﺩ – float ﺝ – double ﺏ – char ﺍﻟﻒ – int
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 354
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﻛﻠﻢۀ ﻛﻠﻴﺪﻱ operatorﭼﮕﻮﻧﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ؟
‐2ﺍﺷﺎﺭﻩﮔﺮ *thisﺑﻪ ﭼﻪ ﭼﻴﺰﻱ ﺍﺷﺎﺭﻩ ﻣﻲﻛﻨﺪ؟
‐3ﭼﺮﺍ ﺍﺷﺎﺭﻩﮔﺮ *thisﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﺮﺍﻱ ﺗﻮﺍﺑﻊ ﻏﻴﺮ ﻋﻀﻮ ﺍﺳﺘﻔﺎﺩﻩ ﻛﺮﺩ؟
‐4ﭼﺮﺍ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺳﺮﺑﺎﺯﮔﺬﺍﺭﻱ ﺷﺪﻩ *this ،ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ؟
‐5ﻧﺘﻴﺞۀ ﺍﻋﻼﻥﻫﺎﻱ ﺯﻳﺮ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﻫﻢ ﺩﺍﺭﺩ؟
;)Ratio y(x
;Ratio y = x
‐6ﻧﺘﻴﺞۀ ﺩﻭ ﺳﻄﺮ ﺯﻳﺮ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﻫﻢ ﺩﺍﺭﺩ؟
;Ratio y = x
;Ratio y; y = x
‐7ﭼﺮﺍ ﻧﻤﻲﺗﻮﺍﻥ ** ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﻋﻤﻠﮕﺮ ﺗﻮﺍﻥ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻛﺮﺩ؟
‐8ﭼﺮﺍ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ +ﻭ -ﻭ * ﻭ /ﺑﺎﻳﺪ ﺑﻪ ﺻﻮﺭﺕ ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ
ﺷﻮﻧﺪ؟
‐10ﭼﮕﻮﻧﻪ ﺗﻌﺮﻳﻒ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ
ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪﻩ ﺗﺸﺨﻴﺺ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ؟
‐11ﭼﺮﺍ ﺁﺭﮔﻮﻣﺎﻥ intﺩﺭ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺑﺪﻭﻥ ﻧﺎﻡ ﺍﺳﺖ؟
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﻛﻼﺱ Vectorﺭﺍ ﺑﺎ ﻳﻚ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ،ﻳﻚ ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ ،ﻳﻚ ﻧﺎﺑﻮﺩﻛﻨﻨﺪﻩ ﻭ
ﻳﻚ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪﻩ ﻭ ﻋﻤﻠﮕﺮ ﺗﺴﺎﻭﻱ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪﻩ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ
ﻛﻨﻴﺪ .ﻫﺮ ﺷﻲ ﺍﺯ ﺍﻳﻦ ﮐﻼﺱ ،ﻳﮏ ﺑﺮﺩﺍﺭ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
‐2ﻋﻤﻠﮕﺮﻫﺎﻱ ﺗﻘﺴﻴﻢ ﻭ ﺟﻤﻊ ﺭﺍ ﺑﺮﺍﻱ ﻛﻼﺱ Ratioﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻛﻨﻴﺪ.
‐3ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ ﭘﻴﺶﮐﺎﻫﺸﻲ ﻭ ﭘﺲﮐﺎﻫﺸﻲ ﺭﺍ ﺑﺮﺍﻱ ﮐﻼﺱ Ratioﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ
ﮐﻨﻴﺪ.
‐4ﻋﻤﻠﮕﺮﻫﺎﻱ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺣﺴﺎﺑﻲ = /ﻭ = -ﺭﺍ ﺑﺮﺍﻱ ﮐﻼﺱ Ratioﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ
ﮐﻨﻴﺪ ‐5 .ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﺍﺑﻄﻪﺍﻱ > ﻭ =! ﺭﺍ ﺑﺮﺍﻱ ﮐﻼﺱ Ratioﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﮐﻨﻴﺪ.
355 ﻓﺼﻞ دهﻢ /ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ
‐6ﺗﺤﻘﻴﻖ ﮐﻨﻴﺪ ﮐﻪ ﻏﻴﺮ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺫﮐﺮ ﺷﺪﻩ ﺩﺭ ﺍﻳﻦ ﻓﺼﻞ ،ﮐﺪﺍﻡ ﻋﻤﻠﮕﺮﻫﺎ ﺭﺍ ﻣﻲﺗﻮﺍﻥ
ﺩﺭ C++ﺑﺮﺍﻱ ﻳﮏ ﮐﻼﺱ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﮐﺮﺩ .ﺑﻪ ﺩﻟﺨﻮﺍﻩ ﻳﮑﻲ ﺍﺯ ﺁﻥ ﻋﻤﻠﮕﺮﻫﺎ ﺭﺍ ﺑﺮﺍﻱ
ﮐﻼﺱ Ratioﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﮐﻨﻴﺪ.
‐7ﺑﺮﺍﻱ ﮐﻼﺱ ) Timeﻣﺴﺄﻝۀ 3ﻓﺼﻞ (9ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ +ﻭ – ﻭ ﻫﻤﭽﻨﻴﻦ
ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﺍﺑﻄﻪ ﺍﻱ == ﻭ < ﻭ > ﺭﺍ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﮐﻨﻴﺪ.
– 8ﺑﺮﺍﻱ ﮐﻼﺱ ) Matrixﻣﺴﺄﻝۀ 6ﻓﺼﻞ (9ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ – ﻭ * ﺭﺍ
ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﮐﻨﻴﺪ.
– 9ﺑﺮﺍﻱ ﮐﻼﺱ ) Pointﻣﺴﺄﻝۀ 7ﻓﺼﻞ (9ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ +ﻭ /ﺭﺍ
ﮐﻨﻴﺪ. ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 356
ﻓﺼﻞ ﻳﺎﺯﺩﻫﻢ
»ﺗﺮﻛﻴﺐ ﻭ ﻭﺭﺍﺛﺖ«
12‐1ﻣﻘﺪﻣﻪ
ﺍﻏﻠﺐ ﺍﻭﻗﺎﺕ ﺑﺮﺍﻱ ﺍﻳﺠﺎﺩ ﻳﮏ ﮐﻼﺱ ﺟﺪﻳﺪ ،ﻧﻴﺎﺯﻱ ﻧﻴﺴﺖ ﮐﻪ ﻫﻤﻪ ﭼﻴﺰ ﺍﺯ ﺍﻭﻝ
ﻃﺮﺍﺣﻲ ﺷﻮﺩ .ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺮﺍﻱ ﺍﻳﺠﺎﺩ ﮐﻼﺱ ﻣﻮﺭﺩ ﻧﻈﺮ ،ﺍﺯ ﺗﻌﺎﺭﻳﻒ ﮐﻼﺱﻫﺎﻳﻲ ﮐﻪ ﻗﺒﻼ
ﺳﺎﺧﺘﻪﺍﻳﻢ ،ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﺎﻳﻴﻢ .ﺍﻳﻦ ﺑﺎﻋﺚ ﺻﺮﻓﻪﺟﻮﻳﻲ ﺩﺭ ﻭﻗﺖ ﻭ ﺍﺳﺘﺤﮑﺎﻡ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ
ﻣﻲﺷﻮﺩ .ﺩﺭ ﺷﻲﮔﺮﺍﻳﻲ ﺑﻪ ﺩﻭ ﺷﻴﻮﻩ ﻣﻲﺗﻮﺍﻥ ﺍﻳﻦ ﮐﺎﺭ ﺭﺍ ﺍﻧﺠﺎﻡ ﺩﺍﺩ :ﺗﺮﮐﻴﺐ 1ﻭ ﻭﺭﺍﺛﺖ .2ﺩﺭ
ﺍﻳﻦ ﻓﺼﻞ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ ﮐﻪ ﭼﮕﻮﻧﻪ ﻭ ﭼﻪ ﻣﻮﺍﻗﻌﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﺍﻳﻦ ﺩﻭ ﺷﻴﻮﻩ ﺑﻬﺮﻩ ﺑﺒﺮﻳﻢ.
12‐2ﺗﺮﻛﻴﺐ
ﺗﺮﮐﻴﺐ ﮐﻼﺱﻫﺎ )ﻳﺎ ﺗﺠﻤﻴﻊ ﮐﻼﺱﻫﺎ( ﻳﻌﻨﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻳﮏ ﻳﺎ ﭼﻨﺪ ﮐﻼﺱ ﺩﻳﮕﺮ ﺩﺭ
ﺩﺍﺧﻞ ﺗﻌﺮﻳﻒ ﻳﮏ ﮐﻼﺱ ﺟﺪﻳﺪ .ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﮐﻼﺱ ﺟﺪﻳﺪ ،ﺷﻴﺌﻲ ﺍﺯ ﮐﻼﺱ
ﺩﻳﮕﺮ ﺑﺎﺷﺪ ،ﻣﻲﮔﻮﻳﻴﻢ ﮐﻪ ﺍﻳﻦ ﮐﻼﺱ ﺟﺪﻳﺪ ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﺳﺎﻳﺮ ﮐﻼﺱﻫﺎﺳﺖ .ﺑﻪ ﺗﻌﺮﻳﻒ ﺩﻭ
ﮐﻼﺱ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ.
int main()
{ Date memory(1359,6,31);
cout << "SADDAM attacked to IRAN at ";
memory.showDate();
memory.setDate(1367,4,27);
cout << "\nThat war finished at ";
memory.showDate();
cout << "\nEnter your birthday: ";
memory.getDate();
cout << "\nYour birthday is ";
memory.showDate();
}
SADDAM attacked to IRAN at 1359/6/31
That war finished at 1367/4/27
Enter your birthday: 1358 6 15
Your birthday is 1358/6/15
359 ﺗﺮﮐﻴﺐ و وراﺛﺖ/ ﻓﺼﻞ ﻳﺎزدهﻢ
int main()
{ Book reference("C++", 1, 450);
cout << " reference id pages " << endl;
cout << "-----------------------------" << endl;
cout << " " ; reference.printName();
cout << " " ; reference.printId();
cout << " " ; reference.printPage();
}
reference id pages
-----------------------------
C++ 1 450
class Book
{ public:
Book(char* n = " ", int i = 0, int p = 0) :
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 360
ﺑﺎ ﺩﻗﺖ ﺩﺭ ﺍﻳﻦ ﮐﻼﺱ ﺑﻬﺒﻮﺩ ﻳﺎﻓﺘﻪ ،ﻣﻲﺑﻴﻨﻴﻢ ﮐﻪ ﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺧﺼﻮﺻﻲ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ
Dateﺩﺭﻭﻥ ﺍﻋﻀﺎﻱ ﺁﻥ ﻭﺟﻮﺩ ﺩﺍﺭﺩ .ﻫﻤﭽﻨﻴﻦ ﺩﻭ ﺗﺎﺑﻊ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﺟﺪﻳﺪ
)( setDOPﻭ )( showDOPﻧﻴﺰ ﺑﻪ ﺍﻳﻦ ﮐﻼﺱ ﺍﻓﺰﻭﺩﻩ ﺷﺪﻩ .ﺑﻪ ﺑﺪﻥۀ ﺍﻳﻦ ﺩﻭ ﺗﺎﺑﻊ ﻧﮕﺎﻩ
ﮐﻨﻴﺪ .ﺩﻭ ﺗﺎﺑﻊ ﺩﻳﮕﺮ ﺑﻪ ﻧﺎﻡﻫﺎﻱ )( setDateﻭ )( showDateﺩﺭ ﺑﺪﻥۀ ﺍﻳﻦ ﺩﻭ ﺗﺎﺑﻊ
ﻗﺮﺍﺭ ﺩﺍﺭﻧﺪ .ﺍﻳﻦ ﺩﻭ ﺗﺎﺑﻊ ،ﻋﻀﻮ ﮐﻼﺱ Dateﻫﺴﺘﻨﺪ.
)(Book ﭼﻮﻥ publishﺍﺯ ﻧﻮﻉ Dateﺍﺳﺖ ،ﻣﻲﺗﻮﺍﻧﻴﻢ
)(printName
)(printId ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﮐﻼﺱ Dateﺭﺍ ﺑﺮﺍﻱ ﺁﻥ ﺻﺪﺍ ﺑﺰﻧﻴﻢ.
)(printPage
)(setDOP ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﺗﻌﺎﺭﻳﻒ ﮐﻼﺱ Dateﺭﺍ ﺩﺭ ﻓﺎﻳﻞ
)(showDOP
name, author ﺟﺪﺍﮔﺎﻧﻪﺍﻱ ﺑﻪ ﻧﺎﻡ " "Date.hﮔﺬﺍﺷﺘﻪﺍﻳﻢ ﻭ ﺑﺮﺍﻱ
;id, page
ﺗﺮﮐﻴﺐ ﮐﺮﺩﻥ ﺍﻳﻦ ﮐﻼﺱ ﺑﺎ ﮐﻼﺱ ،Bookﻓﺎﻳﻞ
)(Date
)(setDate ﻣﺬﮐﻮﺭ ﺭﺍ includeﮐﺮﺩﻩﺍﻳﻢ .ﮐﻼﺱ Bookﺭﺍ
)(getDate
)(showDate ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﻣﺠﺴﻢ ﮐﻨﻴﻢ .ﮐﻼﺱ Date
year, month, day ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺩﺭ ﺑﺨﺶ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ
ﮐﻼﺱ Bookﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺍﺳﺖ.
ﺣﺎﻻ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﻳﻦ ﮐﻼﺱ ﻣﺮﮐﺐ ﺭﺍ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ:
)(int main
;){ Book reference("C++", 1, 450
;)reference.setDOP(1384, 6, 15
361 ﻓﺼﻞ ﻳﺎزدهﻢ /ﺗﺮﮐﻴﺐ و وراﺛﺖ
cout << " reference id pages ;DOP " << endl
cout << ;"---------------------------------------" << endl
cout << " ; " ;)(reference.printName
cout << " ;)("; reference.printId
cout << " ;)(" ; reference.printPage
cout << " ; " ;)(reference.showDOP
}
reference id pages DOP
---------------------------------------
C++ 1 450 1384/6/15
11‐3ﻭﺭﺍﺛﺖ
ﻭﺭﺍﺛﺖ ﺭﻭﺵ ﺩﻳﮕﺮﻱ ﺑﺮﺍﻱ ﺍﻳﺠﺎﺩ ﮐﻼﺱ ﺟﺪﻳﺪ ﺍﺯ ﺭﻭﻱ ﮐﻼﺱ ﻗﺒﻠﻲ ﺍﺳﺖ .ﮔﺎﻫﻲ
ﺑﻪ ﻭﺭﺍﺛﺖ »ﺍﺷﺘﻘﺎﻕ« ﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ .ﺍﮔﺮ ﺍﺯ ﻗﺒﻞ ﺑﺎ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﻣﺒﺘﻨﻲ ﺑﺮ ﭘﻨﺠﺮﻩﻫﺎ ﺁﺷﻨﺎﻳﻲ
ﻣﺨﺘﺼﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ،ﺍﺣﺘﻤﺎﻻ ﻋﺒﺎﺭﺕ »ﮐﻼﺱ ﻣﺸﺘﻖﺷﺪﻩ« ﺭﺍ ﻓﺮﺍﻭﺍﻥ ﺩﻳﺪﻩﺍﻳﺪ .ﺍﻳﻦ ﻣﻮﺿﻮﻉ
ﺑﻪ ﺧﻮﺑﻲ ﺍﻫﻤﻴﺖ ﻭﺭﺍﺛﺖ ﺭﺍ ﺁﺷﮑﺎﺭ ﻣﻲﻧﻤﺎﻳﺪ.
ﺩﺭ ﺩﻧﻴﺎﻱ ﻭﺍﻗﻌﻲ ،ﻭﺭﺍﺛﺖ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﻫﺮ ﻓﺮﺯﻧﺪﻱ ﺧﻮﺍﺹ ﻋﻤﻮﻣﻲ ﺭﺍ ﺍﺯ ﻭﺍﻟﺪ
ﺧﻮﺩ ﺑﻪ ﺍﺭﺙ ﻣﻲﮔﻴﺮﺩ ،ﻣﺜﻞ ﺭﻧﮓ ﭼﺸﻢ ﻳﺎ ﺭﻧﮓ ﻣﻮ ﻳﺎ ﭼﻬﺮۀ ﻇﺎﻫﺮﻱ ﻳﺎ ﺭﻓﺘﺎﺭﻫﺎﻱ ﻏﺮﻳﺰﻱ
ﻭ . ...ﺩﺭ ﺩﻧﻴﺎﻱ ﻧﺮﻡﺍﻓﺰﺍﺭ ﻧﻴﺰ ﻭﺭﺍﺛﺖ ﺑﻪ ﻫﻤﻴﻦ ﻣﻌﻨﺎﺳﺖ .ﻳﻌﻨﻲ ﮐﻼﺱ ﺟﺪﻳﺪ ﺭﺍ ﻃﻮﺭﻱ
ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﮐﻪ ﺍﻋﻀﺎﻱ ﮐﻼﺱ ﺩﻳﮕﺮ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺑﮕﻴﺮﺩ .ﻓﺮﺽ ﮐﻨﻴﺪ ﮐﻼﺱ xﻗﺒﻼ ﺗﻌﺮﻳﻒ
ﺷﺪﻩ ﻭ ﻭﺟﻮﺩ ﺩﺍﺭﺩ .ﻧﺤﻮ ﮐﻠﻲ ﺑﺮﺍﻱ ﺍﺷﺘﻘﺎﻕ ﮐﻼﺱ yﺍﺯ ﮐﻼﺱ xﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
class Y : public X
{
// ...
;}
ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﻣﻲﮔﻮﻳﻴﻢ ﮐﻪ ﮐﻼﺱ yﺍﺯ ﮐﻼﺱ xﻣﺸﺘﻖ ﺷﺪﻩ ﺍﺳﺖ .ﻋﺒﺎﺭﺕ public
ﺑﻌﺪ ﺍﺯ ﻋﻼﻣﺖ ﮐﻮﻟﻦ ﺑﺮﺍﻱ ﺗﺎﮐﻴﺪ ﺑﺮ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﮐﻼﺱ yﻓﻘﻂ ﺑﻪ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ
ﮐﻼﺱ xﺩﺳﺘﺮﺳﻲ ﺩﺍﺭﺩ .ﺑﻪ ﮐﻼﺱ xﮐﻼﺱ ﺍﺻﻠﻲ 1ﻳﺎ »ﮐﻼﺱ ﻭﺍﻟﺪ «2ﻳﺎ »ﮐﻼﺱ ﭘﺎﻳﻪ«
ﻣﻲﮔﻮﻳﻴﻢ ﻭ ﺑﻪ ﮐﻼﺱ yﺯﻳﺮﮐﻼﺱ 3ﻳﺎ »ﮐﻼﺱ ﻓﺮﺯﻧﺪ «4ﻳﺎ »ﮐﻼﺱ ﻣﺸﺘﻖﺷﺪﻩ« ﻣﻲﮔﻮﻳﻴﻢ.
ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﻣﻲﺗﻮﺍﻧﺪ ﻋﻼﻭﻩ ﺑﺮ ﺍﻋﻀﺎﻱ ﺑﻪ ﺍﺭﺙ ﺑﺮﺩﻩ ﺷﺪﻩ ،ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﻭ ﺧﺼﻮﺻﻲ
ﺧﺎﺹ ﺧﻮﺩ ﺭﺍ ﻧﻴﺰ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ .ﺑﻪ ﮐﺪ ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ:
class X
{ public:
;int a
private:
;int b
;}
class Y : public X
{ public:
;int c
private:
;int d
}
ﮐﻼﺱ Xﻳﮏ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﺑﻪ ﻧﺎﻡ aﻭ ﻳﮏ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺑﻪ ﻧﺎﻡ bﺩﺍﺭﺩ .ﮐﻼﺱ Yﺑﻪ
ﻋﻨﻮﺍﻥ ﻓﺮﺯﻧﺪ ﮐﻼﺱ Xﺍﻋﻼﻥ ﺷﺪﻩ .ﭘﺲ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﮐﻼﺱ xﺭﺍ ﺑﻪ ﺍﺭﺙ ﻣﻲﺑﺮﺩ .ﻳﻌﻨﻲ
ﮐﻼﺱ Yﺩﺍﺭﺍﻱ aﻫﺴﺖ .ﻫﻤﭽﻨﻴﻦ ﻳﮏ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﻣﺨﺼﻮﺹ ﺑﻪ ﺧﻮﺩ ﺑﻪ ﻧﺎﻡ cﻫﻢ
ﺩﺍﺭﺩ .ﭼﻮﻥ bﻳﮏ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺍﺯ ﮐﻼﺱ ﻭﺍﻟﺪ ﻳﻌﻨﻲ Xﺍﺳﺖ ،ﻧﻤﻲﺗﻮﺍﻧﺪ ﺗﻮﺳﻂ ﮐﻼﺱ
ﻓﺮﺯﻧﺪ ﻳﻌﻨﻲ Yﻣﺴﺘﻘﻴﻤﺎ ﺩﺳﺘﻴﺎﺑﻲ ﺷﻮﺩ.
Y
X ﺑﻨﺎﺑﺮﺍﻳﻦ ﮐﻼﺱ Yﻓﻘﻂ ﻳﮏ ﻋﻀﻮ ﺧﺼﻮﺻﻲ
int a
int a int c ﺑﻪ ﻧﺎﻡ dﺩﺍﺭﺩ .ﮐﻼﺱﻫﺎﻱ Xﻭ Yﺭﺍ ﻣﻲﺗﻮﺍﻥ
int b int d
int b ﺑﻪ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﺗﺼﻮﺭ ﻧﻤﻮﺩ .ﺗﺼﻮﻳﺮ ﻧﺸﺎﻥ
ﻣﻲﺩﻫﺪ ﮐﻪ ﮐﻼﺱ Yﻋﻀﻮ bﺭﺍ ﻫﻢ ﺩﺍﺭﺩ ﻭﻟﻲ
ﺍﺟﺎﺯۀ ﺩﺳﺘﺮﺳﻲ ﻣﺴﺘﻘﻴﻢ ﺑﻪ ﺁﻥ ﺭﺍ ﻧﺪﺍﺭﺩ .ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﺗﻮﺟﻪ ﮐﻨﻴﺪ.
ﻓﻘﻂ ﮐﺎﻓﻲ ﺍﺳﺖ ﺗﻮﺍﺑﻊ ﻭ ﺩﺍﺩﻩﻫﺎﻱ.ﺑﻪ ﺍﺭﺙ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﻧﺪ ﻭ ﻧﻴﺎﺯﻱ ﺑﻪ ﺍﻳﺠﺎﺩ ﺁﻥﻫﺎ ﻧﻴﺴﺖ
: ﺭﺍ ﺑﻪ ﮐﻼﺱ ﻣﺸﺘﻖ ﺷﺪﻩ ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢEbook ﺧﺎﺹ ﮐﻼﺱ
#include "Book.h"
class Ebook : public Book
{ public:
Ebook(char* n, int i=0, int p=0) :
Book(n,i,p), format("PDF"), size(0) {}
void printFormat() { cout << format; }
void setSize(int s){ size = s; }
void setFormat(char* f) { format = f; }
void printSize() { cout << size; }
private:
string format;
int size;
}
int main()
{ Ebook reference("C++", 1, 450);
reference.setSize(5500);
cout << " Ebook id pages format size(KB) \n";
cout << "----------------------------------------- \n";
cout << " " ; reference.printName();
cout << " "; reference.printId();
cout << " "; reference.printPage();
cout << " "; reference.printFormat();
cout << " "; reference.printSize();
}
Ebook id pages format size(KB)
-----------------------------------------
C++ 1 450 PDF 5500
ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﺑﻪ ﺍﺭﺙ ﮔﺮﻓﺘﻪ ﺷﺪﻩ ﺍﺯ ﮐﻼﺱ ﻭﺍﻟﺪ ،ﻣﻲﺗﻮﺍﻥ
ﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺁﻥ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ .ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﭼﮕﻮﻧﻪ ﺩﺭ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ
Ebookﺍﺯ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ Bookﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩ ﻭ ﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﮐﻼﺱ
Bookﺩﺳﺘﻴﺎﺑﻲ ﻧﻤﻮﺩﻩﺍﻳﻢ.
ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲEbook ﺍﺯ ﺩﺭﻭﻥ ﺯﻳﺮﮐﻼﺱBook ﺣﺎﻻ ﻫﻢۀ ﺍﻋﻀﺎﻱ ﺣﻔﺎﻇﺖ ﺷﺪۀ ﮐﻼﺱ
:ﻫﺴﺘﻨﺪ
int main()
{ Ebook reference("C++", 1, 450);
reference.setSize(5500);
reference.setAuthor("P.N.U");
cout << "\n Ebook name: "; reference.printName();
cout << "\n id: "; reference.printId();
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 366
ﺑﻨﺎﺑﺮ ﺁﻥﭼﻪ ﮔﻔﺘﻴﻢ ،ﺍﻋﻀﺎﻱ ﻳﮏ ﮐﻼﺱ ﺳﻪ ﮔﺮﻭﻩ ﻫﺴﺘﻨﺪ :ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﻳﺎ
publicﮐﻪ ﺍﺯ ﺑﻴﺮﻭﻥ ﮐﻼﺱ ﻭ ﺍﺯ ﺩﺭﻭﻥ ﮐﻼﺱﻫﺎﻱ ﻓﺮﺯﻧﺪ ﻣﺴﺘﻘﻴﻤﺎ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲﺍﻧﺪ؛
ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﻳﺎ privateﮐﻪ ﻓﻘﻂ ﺍﺯ ﺩﺭﻭﻥ ﻫﻤﺎﻥ ﮐﻼﺱ ﻳﺎ ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ ﮐﻼﺱ
ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺁﻥﻫﺎ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ؛ ﺍﻋﻀﺎﻱ ﺣﻔﺎﻇﺖ ﺷﺪﻩ ﻳﺎ protectedﮐﻪ ﺍﺯ ﺑﻴﺮﻭﻥ
ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﻧﻴﺴﺘﻨﺪ ﻭﻟﻲ ﺍﺯ ﺩﺭﻭﻥ ﻫﻤﺎﻥ ﮐﻼﺱ ﻳﺎ ﺩﺭﻭﻥ ﮐﻼﺱﻫﺎﻱ ﻓﺮﺯﻧﺪ ﻳﺎ
ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ ﮐﻼﺱ ﻣﻲﺗﻮﺍﻥ ﻣﺴﺘﻘﻴﻤﺎ ﺑﻪ ﺁﻥﻫﺎ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ .ﭘﺲ ﻗﺎﻟﺐ ﮐﻠﻲ ﺗﻌﺮﻳﻒ
ﻳﮏ ﮐﻼﺱ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ:
class X
{ public:
// public members
protected:
// protected members
private:
// private members
;}
ﺩﺭ ﻧﻈﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﺍﻋﻀﺎﻱ ﺣﻔﺎﻇﺖ ﺷﺪﻩ ﺍﺯ ﮐﻼﺱ ﻭﺍﻟﺪ ،ﺩﺭ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﻧﻴﺰ ﺑﻪ
ﻋﻨﻮﺍﻥ ﺍﻋﻀﺎﻱ protectedﻣﻨﻈﻮﺭ ﻣﻲﺷﻮﻧﺪ.
ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﭙﺮﺳﻴﺪ ﺑﺎ ﺧﻮﺍﺻﻲ ﮐﻪ ﺍﻋﻀﺎﻱ protectedﺩﺍﺭﻧﺪ ،ﭼﻪ ﻧﻴﺎﺯﻱ ﺑﻪ
ﺍﻋﻀﺎﻱ privateﺍﺳﺖ؟ ﺑﺮﺍﻱ ﭘﺎﺳﺦ ﺑﻪ ﺍﻳﻦ ﺳﻮﺍﻝ ﻳﺎﺩﺁﻭﺭﻱ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﺍﺯ ﻣﺰﻳﺖﻫﺎﻱ
ﻣﻬﻢ ﺷﻲﮔﺮﺍﻳﻲ ،ﻣﺨﻔﻲﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ ﺍﺳﺖ .ﻫﻤﻴﺸﻪ ﺍﻳﻦ ﻃﻮﺭ ﻧﻴﺴﺖ ﮐﻪ ﺑﺨﻮﺍﻫﻴﻢ ﻫﻢۀ
367 ﻓﺼﻞ ﻳﺎزدهﻢ /ﺗﺮﮐﻴﺐ و وراﺛﺖ
ﺍﻋﻀﺎﻱ ﮐﻼﺱ ﻭﺍﻟﺪ ﺩﺭ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﺑﻪ ﺍﺭﺙ ﮔﺬﺍﺷﺘﻪ ﺷﻮﻧﺪ .ﻣﻤﮑﻦ ﺍﺳﺖ ﺩﺭ ﮐﻼﺱ
Bookﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺑﺎ ﻧﺎﻡ paperkindﺑﮕﺬﺍﺭﻳﻢ ﮐﻪ ﻧﻮﻉ ﮐﺎﻏﺬ ﻣﺼﺮﻓﻲ ﺩﺭ ﮐﺘﺎﺏ
ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﻃﺒﻴﻌﻲ ﺍﺳﺖ ﮐﻪ ﭼﻨﻴﻦ ﻋﻀﻮﻱ ﺩﺭ ﮐﻼﺱ Ebookﺍﺻﻼ ﺑﻲﻣﻌﻨﺎﺳﺖ.
ﺑﻨﺎﺑﺮﺍﻳﻦ ﻻﺯﻡ ﻧﻴﺴﺖ )ﻭ ﻧﺒﺎﻳﺪ( ﮐﻪ ﮐﻼﺱ Ebookﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ paperkindﺭﺍ ﺑﻪ
ﺍﺭﺙ ﺑﮕﻴﺮﺩ ﻭ ﺍﻳﻦ ﻋﻀﻮ ﺑﺎﻳﺪ ﺍﺯ ﺩﺳﺘﺮﺱ ﺩﻭﺭ ﺑﻤﺎﻧﺪ .ﻋﻘﻴﺪۀ ﮐﻠﻲ ﺑﺮ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﻋﻀﻮ
ﺩﺍﺩﻩﺍﻱ ﮐﻼﺱ ﺭﺍ ﺑﻪ ﺷﮑﻞ privateﺍﻋﻼﻥ ﮐﻨﻴﺪ ﻣﮕﺮ ﺍﻳﻦ ﮐﻪ ﺍﺣﺘﻤﺎﻝ ﺑﺪﻫﻴﺪ ﺁﻥ ﻋﻀﻮ
ﻣﻤﮑﻦ ﺍﺳﺖ ﻻﺯﻡ ﺑﺎﺷﺪ ﺩﺭ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﺑﻪ ﺍﺭﺙ ﮔﺮﻓﺘﻪ ﺷﻮﺩ .ﺁﻧﮕﺎﻩ ﭼﻨﻴﻦ ﻋﻀﻮﻱ ﺭﺍ ﺑﻪ
ﺷﮑﻞ protectedﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﺪ.
ﺍﻋﻀﺎﻱ ﺯﻳﺮﮐﻼﺱ Yﻫﻤﺎﻥ ﻣﺸﺨﺼﺎﺕ ﺍﻋﻀﺎﻱ ﮐﻼﺱ Xﺭﺍ ﺩﺍﺭﻧﺪ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺗﺎﺑﻊ
)( fﮐﻪ ﺩﺭ ﺯﻳﺮﮐﻼﺱ Yﺍﻋﻼﻥ ﺷﺪﻩ ،ﺗﺎﺑﻊ )( fﻣﻮﺭﻭﺛﻲ ))( (X::fﺭﺍ ﻣﻐﻠﻮﺏ ﻣﻲﮐﻨﺪ
ﻭ ﻋﻀﻮ aﮐﻪ ﺩﺭ ﺯﻳﺮﮐﻼﺱ Yﺍﻋﻼﻥ ﺷﺪﻩ ﻧﻴﺰ ﻋﻀﻮ aﻣﻮﺭﻭﺛﻲ ) (X::aﺭﺍ ﻣﻐﻠﻮﺏ
ﻣﻲﻧﻤﺎﻳﺪ .ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺯﻳﺮ ﺍﻳﻦ ﻣﻄﻠﺐ ﺭﺍ ﺗﺎﻳﻴﺪ ﻣﻲﮐﻨﺪ:
)(int main
;{ X x1
;x1.a = 22
;)(x1.f
;cout << "x1.a = " << x1.a << endl
;Y y1
;y1.a = 44 // assigns 44 to the a defined in Y
;y1.X::a = 66 // assigns 66 to the a defined in X
;)(y1.f // calls the f() defined in Y
;)(y1.X::f // calls the f() defined in X
;cout << "y1.a = " << y1.a << endl
;cout << " y1.X::a = " << y1.X::a << endl
369 ﻓﺼﻞ ﻳﺎزدهﻢ /ﺗﺮﮐﻴﺐ و وراﺛﺖ
;X x2 = Y1
;cout << "x2.a = " << x2.a << endl
}
X::f() is running
x1.a = 22
Y::f() is running
X::f() is running
y1.a = 44
= y1.X::a 66
x2.a = 66
ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺷﻲﺀ y1ﺩﻭ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﻣﺠﺰﺍﻱ aﻭ ﺩﻭ ﻋﻀﻮ ﺗﺎﺑﻌﻲ ﻣﺠﺰﺍﻱ )( fﺩﺍﺭﺩ .ﺑﻪ
ﻃﻮﺭ ﭘﻴﺶﻓﺮﺽ ،ﺁﻥﻫﺎﻳﻲ ﮐﻪ ﻏﺎﻟﺐ ﻫﺴﺘﻨﺪ ﺩﺳﺘﻴﺎﺑﻲ ﻣﻲﺷﻮﻧﺪ ﻭﻟﻲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ
ﺟﺪﺍﺳﺎﺯﻱ ﺣﻮﺯﻩ ::ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺍﻋﻀﺎﻱ ﻣﻮﺭﻭﺛﻲ ﻧﻴﺰ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ.
ﺩﺭ ﺩﺳﺘﻮﺭ ﺟﺎﻳﮕﺰﻳﻨﻲ ; x2 = y1ﻧﮑﺖۀ ﻣﻬﻤﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ x2 .ﺷﻴﺌﻲ ﺍﺯ ﮐﻼﺱ
ﻭﺍﻟﺪ ﺍﺳﺖ ﻭ y1ﺷﻴﺌﻲ ﺍﺯ ﮐﻼﺱ ﻓﺮﺯﻧﺪ .ﻭﻗﺘﻲ ﻗﺮﺍﺭ ﺑﺎﺷﺪ ﻳﮏ ﺷﻲ ﺍﺯ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﺩﺭﻭﻥ
ﻳﮏ ﺷﻲ ﺍﺯ ﮐﻼﺱ ﻭﺍﻟﺪ ﮐﭙﻲ ﺷﻮﺩ ،ﺑﻪ ﻃﻮﺭ ﭘﻴﺶﻓﺮﺽ ﺍﻋﻀﺎﻱ ﻣﻮﺭﻭﺛﻲ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﺑﺮﺍﻱ
ﺟﺎﻳﮕﺰﻳﻨﻲ ﺍﻧﺘﺨﺎﺏ ﻣﻲﺷﻮﻧﺪ ﻧﻪ ﺍﻋﻀﺎﻱ ﻏﺎﻟﺐ .ﻳﻌﻨﻲ ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ y1.X::aﺩﺭ
x2.aﮐﭙﻲ ﻣﻲﺷﻮﺩ ﻧﻪ ) . y1.aﺳﻌﻲ ﮐﻨﻴﺪ ﻋﻠﺖ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ(
ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻭﺍﻗﻌﻲ ،ﺍﺯ ﺗﻮﺍﺑﻊ ﻏﺎﻟﺐ ﺑﺴﻴﺎﺭ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺍﺩﻩﻫﺎﻱ
ﻏﺎﻟﺐ ﭼﻨﺪﺍﻥ ﻣﺮﺳﻮﻡ ﻧﻴﺴﺖ .ﺍﻏﻠﺐ ﺍﻳﻦ ﻃﻮﺭ ﺍﺳﺖ ﮐﻪ ﻧﻮﻉ ﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺩﺭ ﮐﻼﺱ
ﻓﺮﺯﻧﺪ ﺑﺎ ﻧﻮﻉ ﻫﻤﺎﻥ ﻋﻀﻮ ﺩﺭ ﮐﻼﺱ ﻭﺍﻟﺪ ﻣﺘﻔﺎﻭﺕ ﺍﺳﺖ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ a
ﺩﺭ ﮐﻼﺱ ﻭﺍﻟﺪ ﺍﺯ ﻧﻮﻉ intﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺻﺮﻳﺢ aﺩﺭ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﺍﺯ ﻧﻮﻉ
doubleﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ.
ﺳﺎﺯﻧﺪﻩﻫﺎﻱ ﭘﻴﺶﻓﺮﺽ ﻭ ﻧﺎﺑﻮﺩﮔﺮﻫﺎ ﺩﺭ ﻭﺭﺍﺛﺖ ﺭﻓﺘﺎﺭ ﻣﺘﻔﺎﻭﺗﻲ ﺩﺍﺭﻧﺪ .ﺑﻪ ﺍﻳﻦ
ﺻﻮﺭﺕ ﮐﻪ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﻗﺒﻞ ﺍﺯ ﺍﺟﺮﺍﻱ ﺧﻮﺩﺵ ،ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ ﻭﺍﻟﺪﺵ ﺭﺍ ﻓﺮﺍ
ﻣﻲﺧﻮﺍﻧﺪ .ﻧﺎﺑﻮﺩﮔﺮ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﻧﻴﺰ ﭘﺲ ﺍﺯ ﺍﺟﺮﺍﻱ ﺧﻮﺩﺵ ،ﻧﺎﺑﻮﺩﮔﺮ ﮐﻼﺱ ﻭﺍﻟﺪﺵ ﺭﺍ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﮐﻨﺪ .ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﺗﻮﺟﻪ ﻧﻤﺎﻳﻴﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 370
)(int main
;){ Z z(44
}
X::X() constructor executing
Y::Y() constructor executing
Z::Z(int) constructor executing
Z::Z() destructor executing
Y::Y() destructor executing
X::X() destructor executing
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﮐﻼﺱ Zﻓﺮﺯﻧﺪ ﮐﻼﺱ Yﺍﺳﺖ ﮐﻪ ﺧﻮﺩ Yﻓﺮﺯﻧﺪ ﮐﻼﺱ Xﻣﻲﺑﺎﺷﺪ .ﺩﺭ
ﺑﺪﻥۀ ﺗﺎﺑﻊ )( mainﻳﮏ ﺷﻲ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ Zﻧﻤﻮﻧﻪﺳﺎﺯﻱ ﺷﺪﻩ .ﭘﺲ ﺍﻧﺘﻈﺎﺭ ﺍﻳﻦ ﺍﺳﺖ
ﮐﻪ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ Zﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ .ﺍﻣﺎ ﺗﺼﻮﻳﺮ ﺧﺮﻭﺟﻲ ﻧﻴﺰ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻗﺒﻞ ﺍﺯ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﺳﺎﺯﻧﺪۀ ،Zﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ ﻭﺍﻟﺪﺵ ﻳﻌﻨﻲ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ Yﻓﺮﺍﺧﻮﺍﻧﻲ
ﻣﻲﺷﻮﺩ .ﭼﻮﻥ Yﻓﺮﺯﻧﺪ Xﺍﺳﺖ ،ﭘﺲ ﻗﺒﻞ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ ،Yﺳﺎﺯﻧﺪۀ ﮐﻼﺱ
Xﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ .ﻟﺬﺍ ﻫﻨﮕﺎﻡ ﺍﻳﺠﺎﺩ ﻳﮏ ﺷﻲ ﺍﺯ ﮐﻼﺱ Zﺍﺑﺘﺪﺍ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ Xﻭ
ﺳﭙﺲ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ Yﻭ ﺩﺭ ﻧﻬﺎﻳﺖ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ Zﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ.
371 ﻓﺼﻞ ﻳﺎزدهﻢ /ﺗﺮﮐﻴﺐ و وراﺛﺖ
ﻭﻗﺘﻲ ﺑﻪ ﭘﺎﻳﺎﻥ ﺗﺎﺑﻊ )( mainﺑﺮﺳﻴﻢ ،ﺷﻲﺀ Zﺑﻪ ﭘﺎﻳﺎﻥ ﻋﻤﺮﺵ ﻣﻲﺭﺳﺪ .ﭘﺲ ﺑﺎﻳﺪ
ﻧﺎﺑﻮﺩﮔﺮ ﮐﻼﺱ Zﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ .ﻫﻤﻴﻦ ﺍﺗﻔﺎﻕ ﻫﻢ ﻣﻲﺍﻓﺘﺪ ﺍﻣﺎ ﭘﺲ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﺎﺑﻮﺩﮔﺮ
ﮐﻼﺱ ،Zﻧﺎﺑﻮﺩﮔﺮ ﮐﻼﺱ ﻭﺍﻟﺪﺵ ﻳﻌﻨﻲ Yﻫﻢ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ .ﭘﺲ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲ
ﻧﺎﺑﻮﺩﮔﺮ ﮐﻼﺱ ،Yﻧﺎﺑﻮﺩﮔﺮ ﮐﻼﺱ Xﻧﻴﺰ ﮐﻪ ﻭﺍﻟﺪ Yﺍﺳﺖ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ .ﺩﻗﺖ ﮐﻨﻴﺪ
ﮐﻪ ﺳﺎﺯﻧﺪﻩﻫﺎﻱ ﻭﺍﻟﺪ ﺍﺯ ﺑﺮﺗﺮﻳﻦ ﮐﻼﺱ ﺑﻪ ﺯﻳﺮﺗﺮﻳﻦ ﮐﻼﺱ ﺍﺟﺮﺍ ﻣﻲﺷﻮﻧﺪ ﻭﻟﻲ ﻧﺎﺑﻮﺩﮔﺮﻫﺎ ﺍﺯ
ﺯﻳﺮﺗﺮﻳﻦ ﮐﻼﺱ ﺑﻪ ﺳﻤﺖ ﺑﺮﺗﺮﻳﻦ ﮐﻼﺱ ﺍﺟﺮﺍ ﻣﻲﺷﻮﻧﺪ .ﺍﻣﺎ ﭼﺮﺍ ﭼﻨﻴﻦ ﺍﺗﻔﺎﻗﻲ ﻣﻲﺍﻓﺘﺪ؟
ﺍﮔﺮ ﮐﻼﺱ Yﻓﺮﺯﻧﺪ ﮐﻼﺱ Xﺑﺎﺷﺪ ،ﺍﻋﻀﺎﻱ ﮐﻼﺱ Xﺭﺍ ﺑﻪ ﺍﺭﺙ ﻣﻲﮔﻴﺮﺩ .ﺳﺎﺯﻧﺪۀ
ﮐﻼﺱ Yﺭﺍﺟﻊ ﺑﻪ ﺍﻋﻀﺎﻱ ﺻﺮﻳﺢ ﺍﻳﻦ ﮐﻼﺱ ﺁﮔﺎﻫﻲ ﺩﺍﺭﺩ ﻭﻟﻲ ﺍﺯ ﺍﻋﻀﺎﻱ ﮐﻼﺱ ﻭﺍﻟﺪ
ﭼﻴﺰﻱ ﻧﻤﻲﺩﺍﻧﺪ .ﺑﻨﺎﺑﺮﺍﻳﻦ ﻫﻨﮕﺎﻡ ﺍﺟﺮﺍ ﻣﻲﺩﺍﻧﺪ ﺑﺮﺍﻱ ﺍﻋﻀﺎﻱ ﺻﺮﻳﺢ ﮐﻼﺱ Yﭼﻪ ﻣﻴﺰﺍﻥ
ﺣﺎﻓﻈﻪ ﻣﻨﻈﻮﺭ ﮐﻨﺪ ﺍﻣﺎ ﻧﻤﻲﺩﺍﻧﺪ ﺑﺮﺍﻱ ﺍﻋﻀﺎﻱ ﻣﻮﺭﻭﺛﻲ ﭼﻘﺪﺭ ﺣﺎﻓﻈﻪ ﻧﻴﺎﺯ ﺍﺳﺖ .ﺍﺯ ﮐﺠﺎ
ﻣﻲﺗﻮﺍﻥ ﻣﻴﺰﺍﻥ ﺣﺎﻓﻆۀ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺍﻋﻀﺎﻱ ﻣﻮﺭﻭﺛﻲ ﺭﺍ ﻓﻬﻤﻴﺪ؟ ﺍﺯ ﺳﺎﺯﻧﺪۀ ﻭﺍﻟﺪ .ﺑﻪ ﻫﻤﻴﻦ
ﺩﻟﻴﻞ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﺳﺎﺯﻧﺪﻩ ﻗﺒﻞ ﺍﺯ ﺍﺟﺮﺍﻱ ﺧﻮﺩﺵ ،ﺳﺎﺯﻧﺪۀ ﻭﺍﻟﺪﺵ ﺭﺍ ﻓﺮﺍ ﻣﻲﺧﻮﺍﻧﺪ.
ﺳﺎﺯﻧﺪۀ ﻭﺍﻟﺪ ﺣﺎﻓﻆۀ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺑﺮﺍﻱ ﺍﻋﻀﺎﻱ ﻭﺍﻟﺪ ﺭﺍ ﺗﺨﺼﻴﺺ ﺩﺍﺩﻩ ﻭ ﺍﻳﻦ ﺣﺎﻓﻈﻪ ﺭﺍ ﺑﻪ
ﺳﺎﺯﻧﺪۀ ﻓﺮﺯﻧﺪ ﺗﺤﻮﻳﻞ ﻣﻲﺩﻫﺪ .ﺳﺎﺯﻧﺪۀ ﻓﺮﺯﻧﺪ ﻧﻴﺰ ﺣﺎﻓﻆۀ ﻻﺯﻡ ﺑﺮﺍﻱ ﺍﻋﻀﺎﻱ ﺻﺮﻳﺢ ﺭﺍ
ﺗﺨﺼﻴﺺ ﺩﺍﺩﻩ ﻭ ﺑﻪ ﻣﻴﺰﺍﻥ ﻗﺒﻠﻲ ﻣﻲﺍﻓﺰﺍﻳﺪ ﻭ ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺷﻲﺀ ﻓﺮﺯﻧﺪ ﺑﺎ ﺣﺎﻓﻆۀ ﮐﺎﻓﻲ
ﻣﺘﻮﻟﺪ ﻣﻲﺷﻮﺩ .ﻫﻨﮕﺎﻡ ﻧﺎﺑﻮﺩ ﮐﺮﺩﻥ ﺷﻲﺀ ﻓﺮﺯﻧﺪ ﻧﻴﺰ ﺍﺑﺘﺪﺍ ﻧﺎﺑﻮﺩﮔﺮ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﺣﺎﻓﻆۀ
ﺗﺨﺼﻴﺼﻲ ﺑﻪ ﺍﻋﻀﺎﻱ ﺻﺮﻳﺢ ﺭﺍ ﺁﺯﺍﺩ ﻣﻲﮐﻨﺪ ﺍﻣﺎ ﺣﺎﻓﻆۀ ﺗﺨﺼﻴﺺ ﻳﺎﻓﺘﻪ ﺑﻪ ﺍﻋﻀﺎﻱ ﻣﻮﺭﻭﺛﻲ
ﺑﻼﺗﮑﻠﻴﻒ ﺑﺎﻗﻲ ﻣﻲﻣﺎﻧﻨﺪ .ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﻻﺯﻡ ﺍﺳﺖ ﻧﺎﺑﻮﺩﮐﻨﻨﺪۀ ﮐﻼﺱ ﻭﺍﻟﺪ ﻧﻴﺰ ﻓﺮﺍﺧﻮﺍﻧﻲ
ﺷﻮﺩ ﺗﺎ ﺍﻳﻦ ﺣﺎﻓﻆۀ ﺍﺿﺎﻓﻲ ﺁﺯﺍﺩ ﺷﻮﺩ.
11‐6ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺩﺭ ﻭﺭﺍﺛﺖ
ﺩﺭ ﺷﻲﮔﺮﺍﻳﻲ ﺧﺎﺻﻴﺖ ﺟﺎﻟﺒﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﻭ ﺁﻥ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﮔﺮ pﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺯ
ﻧﻮﻉ ﮐﻼﺱ ﻭﺍﻟﺪ ﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ pﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻫﺮ ﻓﺮﺯﻧﺪﻱ ﺍﺯ ﺁﻥ ﮐﻼﺱ ﻧﻴﺰ ﺍﺷﺎﺭﻩ ﺩﺍﺩ .ﺑﻪ
ﮐﺪ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ:
class X
{ public:
;)(void f
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 372
}
class Y : public X // Y is a subclass of X
{ public:
;)(void f
}
)(int main
;{ X* p // p is a pointer to objects of base class X
;Y y
;p = &y // p can also point to objects of subclass Y
}
ﮔﺮﭼﻪ pﺍﺯ ﻧﻮﻉ * Xﺍﺳﺖ ،ﺍﻣﺎ ﺁﻥ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺍﺷﻴﺎﻱ ﮐﻼﺱ Yﮐﻪ ﻓﺮﺯﻧﺪ Xﺍﺳﺖ ﻧﻴﺰ
ﺍﺷﺎﺭﻩ ﺩﺍﺩ .ﻳﺎﺩﺁﻭﺭﻱ ﻣﻲﮐﻨﻴﻢ ﮐﻪ )( p->fﻣﻌﺎﺩﻝ )( *p.fﺍﺳﺖ .ﺣﺎﻻ ﺩﺭ ﮐﺪ ﻓﻮﻕ
ﺗﺼﻮﺭ ﮐﻨﻴﺪ pﮐﻪ ﺍﺯ ﻧﻮﻉ * Xﺍﺳﺖ ﺑﻪ ﻳﮏ ﺷﻲﺀ Yﺍﺷﺎﺭﻩ ﮐﻨﺪ ﻭ )( p->fﻓﺮﺍﺧﻮﺍﻧﻲ
ﺷﻮﺩ .ﺍﮐﻨﻮﻥ ﮐﺪﺍﻡ )( fﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ؟ )( X::fﻳﺎ )( Y::f؟ ﺍﻧﺘﻈﺎﺭ ﺩﺍﺭﻳﻢ ﮐﻪ
)( Y::fﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ ﻭﻟﻲ ﭼﻨﻴﻦ ﻧﻴﺴﺖ p .ﺍﺯ ﻧﻮﻉ * Xﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ ﻭ ﻓﻘﻂ
)( X::fﺭﺍ ﻣﻲﺷﻨﺎﺳﺪ .ﺍﺻﻼ ﻣﻬﻢ ﻧﻴﺴﺖ ﮐﻪ pﺑﻪ ﭼﻪ ﺷﻴﺌﻲ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ .ﻣﻬﻢ ﺍﻳﻦ ﺍﺳﺖ
ﮐﻪ ﺍﺯ ﮐﻼﺱ * Xﺍﺳﺖ ﻭ ﺗﻮﺍﺑﻊ ﺁﻥ ﺭﺍ ﻣﻲﺷﻨﺎﺳﺪ .ﻣﺜﺎﻝ ﺯﻳﺮ ﺍﻳﻦ ﻣﻄﻠﺐ ﺭﺍ ﺗﺎﻳﻴﺪ ﻣﻲﮐﻨﺪ.
)(int main
;{ X x
;Y y
373 ﻓﺼﻞ ﻳﺎزدهﻢ /ﺗﺮﮐﻴﺐ و وراﺛﺖ
;X* p = &x
;)(p->f *// invokes X::f() because p has type X
;p = &y
;)(p->f *// invokes X::f() because p has type X
}
X::f() executing
X::f() executing
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺩﻭ ﺑﺎﺭ )( p->fﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ .ﻳﮏ ﺑﺎﺭ ﺑﺮﺍﻱ ﺷﻲﺀ xﺍﺯ ﮐﻼﺱ Xﻭ ﻳﮏ
ﺑﺎﺭ ﻫﻢ ﺑﺮﺍﻱ ﺷﻲﺀ yﺍﺯ ﮐﻼﺱ Yﻭﻟﻲ ﺩﺭ ﻫﺮ ﺩﻭ ﺑﺎﺭ ﺑﺪﻭﻥ ﺗﻮﺟﻪ ﺑﻪ ﺍﻳﻦ ﮐﻪ pﺑﻪ ﺍﺷﻴﺎﻱ
ﭼﻪ ﮐﻼﺳﻲ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ،ﻓﻘﻂ )( X::fﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ.
ﻣﺸﺨﺺ ﺍﺳﺖ ﮐﻪ ﺍﺛﺮ ﻓﻮﻕ ﻣﻄﻠﻮﺏ ﺑﻪ ﻧﻈﺮ ﻧﻤﻲﺭﺳﺪ .ﺍﻧﺘﻈﺎﺭ ﺩﺍﺭﻳﻢ ﮐﻪ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻱ
،Yﻫﻨﮕﺎﻡ ﺍﺟﺮﺍﻱ )( p->fﺗﺎﺑﻊ )( Y::fﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ ﻭ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻱ Xﻫﻢ ﻫﻨﮕﺎﻡ
ﺍﺟﺮﺍﻱ )( p->fﺗﺎﺑﻊ )( X::fﻓﺮﺍ ﺧﻮﺍﻧﺪﻩ ﺷﻮﺩ .ﺑﺮﺍﻱ ﺑﺮﺁﻭﺭﺩﻥ ﺍﻳﻦ ﺍﻧﺘﻈﺎﺭ ،ﺍﺯ »ﺗﻮﺍﺑﻊ
ﻣﺠﺎﺯﻱ« ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ.
;}
)(int main
;{ X x
;Y y
;X* p = &x
;)(p->f )(// invokes X::f
;p = &y
;)(p->f )(// invokes Y::f
}
X::f() executing
Y::f() executing
ﺍﮐﻨﻮﻥ ﻭﻗﺘﻲ pﺑﻪ ﺷﻴﺌﻲ ﺍﺯ ﻧﻮﻉ Xﺍﺷﺎﺭﻩ ﮐﻨﺪ ﻭ ﺗﺎﺑﻊ )( p->fﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩX::f() ،
ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ﻭ ﻭﻗﺘﻲ pﺑﻪ ﺷﻴﺌﻲ ﺍﺯ ﻧﻮﻉ Yﺍﺷﺎﺭﻩ ﮐﻨﺪ ﻭ ﺗﺎﺑﻊ )( p->fﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ،
ﺍﻳﻦ ﺩﻓﻌﻪ )( Y::fﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ .ﺑﻪ ﺍﻳﻦ ﻣﻔﻬﻮﻡ» ،ﭼﻨﺪﺷﮑﻠﻲ« ﻳﺎ ﭼﻨﺪﺭﻳﺨﺘﻲ ﻣﻲﮔﻮﻳﻨﺪ
ﺯﻳﺮﺍ ﻓﺮﺍﺧﻮﺍﻧﻲ )( p->fﺑﺴﺘﻪ ﺑﻪ ﺍﻳﻦ ﮐﻪ pﺑﻪ ﭼﻪ ﻧﻮﻉ ﺷﻴﺌﻲ ﺍﺷﺎﺭﻩ ﮐﻨﺪ ،ﻧﺘﺎﻳﺞ ﻣﺘﻔﺎﻭﺗﻲ
ﺗﻮﻟﻴﺪ ﻣﻲﮐﻨﺪ .ﺩﻗﺖ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﻓﻘﻂ ﺗﻮﺍﺑﻊ ﮐﻼﺱ ﻭﺍﻟﺪ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ
ﻣﻲﮐﻨﻨﺪ .ﻣﺜﺎﻝ ﺯﻳﺮ ،ﻧﻤﻮﻥۀ ﻣﻔﻴﺪﺗﺮﻱ ﺍﺯ ﭼﻨﺪﺭﻳﺨﺘﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ.
int main()
{ Book* b;
Book mybook("C++");
b = &mybook;
b->print();
Ebook myebook("C#", 5.16);
b = &myebook;
b->print();
Notebook mynotebook(".NET", 230);
b = &mynotebook;
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 376
;)(b->print
}
Here is a book with name C++.
Here is a book with name C#.
Here is a book with name .NET.
ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﮐﻼﺱ Bookﻳﮏ ﮐﻼﺱ ﻭﺍﻟﺪ ﺍﺳﺖ ﮐﻪ ﺩﺍﺭﺍﻱ ﺩﻭ ﻓﺮﺯﻧﺪ ﺑﻪ ﻧﺎﻡﻫﺎﻱ
Ebookﻭ Notebookﻣﻲﺑﺎﺷﺪ .ﻫﺮ ﺱۀ ﺍﻳﻦ ﮐﻼﺱﻫﺎ ﺩﺍﺭﺍﻱ ﺗﺎﺑﻊ )( printﻫﺴﺘﻨﺪ.
ﺍﺷﺎﺭﻩﮔﺮ bﺍﺯ ﻧﻮﻉ ﮐﻼﺱ ﻭﺍﻟﺪ ﻳﻌﻨﻲ * Bookﺗﻌﺮﻳﻒ ﺷﺪﻩ ،ﭘﺲ ﻣﻲﺗﻮﺍﻥ ﺁﻥ ﺭﺍ ﺑﻪ ﺍﺷﻴﺎﻳﻲ
ﻓﺮﺍﺧﻮﺍﻧﻲ ﻫﻨﮕﺎﻡ ﺩﻓﻌﻪ ﻫﺮ ﺍﻣﺎ ﺩﺍﺩ ﺍﺷﺎﺭﻩ ﻧﻴﺰ ﻓﺮﺯﻧﺪ ﮐﻼﺱﻫﺎﻱ ﺍﺯ
)( b->printﻓﻘﻂ ﺗﺎﺑﻊ )( printﺍﺯ ﮐﻼﺱ Bookﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ.
ﺣﺎﻻ ﺗﺎﺑﻊ )( printﺩﺭ ﮐﻼﺱ ﻭﺍﻟﺪ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺍﻋﻼﻥ ﻣﻲﮐﻨﻴﻢ:
class Book
{ public:
;])Book(char* s) { name = new char[strlen(s+1
;)strcpy(name, s
}
virtual void print() { cout << "Here is a book with
;"name " << name << ".\n
}
protected:
;char* name
;}
ﺍﮐﻨﻮﻥ ﮐﻪ ﺑﺎ ﺍﻳﻦ ﺗﻐﻴﻴﺮ ،ﺩﻭﺑﺎﺭﻩ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺍﺟﺮﺍ ﮐﻨﻴﻢ ،ﻫﻤﻪ ﭼﻴﺰ ﺑﻪ ﺩﺭﺳﺘﻲ ﻃﺒﻖ ﺍﻧﺘﻈﺎﺭ ﻣﺎ
ﭘﻴﺶ ﻣﻲﺭﻭﺩ:
Here is a book with name C++.
Here is an Ebook with name C# and size 5.16 MB.
Here is a Notebook with name .NET and pages 230.
ﺯﻣﺎﻧﻲ ﻳﮏ ﺗﺎﺑﻊ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﻨﺪ ﮐﻪ ﺍﺣﺘﻤﺎﻝ ﺑﺪﻫﻨﺪ ﺣﺪﺍﻗﻞ ﻳﮏ
ﺯﻳﺮﮐﻼﺱ ،ﻧﺴﺨﻪﺍﻱ ﻣﺤﻠﻲ ﺍﺯ ﻫﻤﺎﻥ ﺗﺎﺑﻊ ﺭﺍ ﺧﻮﺍﻫﺪ ﺩﺍﺷﺖ.
11‐8ﻧﺎﺑﻮﺩﻛﻨﻨﺪۀ ﻣﺠﺎﺯﻱ
ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺗﻌﺮﻳﻒ ﺗﻮﺍﺑﻊ ﻣﺠﺎﺯﻱ ،ﺑﻪ ﻧﻈﺮ ﻣﻲﺭﺳﺪ ﮐﻪ ﻧﻤﻲﺗﻮﺍﻥ ﺗﻮﺍﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻭ
ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ ﻧﻤﻮﺩ ﺯﻳﺮﺍ ﺳﺎﺯﻧﺪﻩﻫﺎ ﻭ ﻧﺎﺑﻮﺩﮔﺮﻫﺎ ﺩﺭ ﮐﻼﺱﻫﺎﻱ
ﻭﺍﻟﺪ ﻭ ﻓﺮﺯﻧﺪ ،ﻫﻢﻧﺎﻡ ﻧﻴﺴﺘﻨﺪ .ﺩﺭ ﺍﺻﻞ ،ﺳﺎﺯﻧﺪﻩﻫﺎ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ
ﮐﺮﺩ ﺍﻣﺎ ﻧﺎﺑﻮﺩﮔﺮﻫﺎ ﻗﺺۀ ﺩﻳﮕﺮﻱ ﺩﺍﺭﻧﺪ .ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺍﻳﺮﺍﺩ ﻣﻬﻠﮑﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺑﺎ
ﻣﺠﺎﺯﻱ ﮐﺮﺩﻥ ﻧﺎﺑﻮﺩﮔﺮ ،ﺑﺮﻃﺮﻑ ﻣﻲﺷﻮﺩ.
)(int main
){ for (int i=0; i<8; i++
;{ X* r = new Y
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 378
;delete r
}
}
X(). )(Y : Y::q = 0x5821c. ~X().
X(). )(Y : Y::q = 0x5921c. ~X().
X(). )(Y : Y::q = 0x5a21c. ~X().
X(). )(Y : Y::q = 0x5b21c. ~X().
X(). )(Y : Y::q = 0x5c21c. ~X().
X(). )(Y : Y::q = 0x5d21c. ~X().
X(). )(Y : Y::q = 0x5e21c. ~X().
X(). )(Y : Y::q = 0x5f21c. ~X().
ﺩﺭ ﻫﺮ ﺗﮑﺮﺍﺭ ﺣﻠﻖۀ forﻳﮏ ﺷﻲﺀ ﭘﻮﻳﺎﻱ ﺟﺪﻳﺪ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ .ﻃﺒﻖ ﺍﻧﺘﻈﺎﺭ ،ﺳﺎﺯﻧﺪﻩﻫﺎ
ﺍﺯ ﺑﺎﻻ ﺑﻪ ﭘﺎﻳﻴﻦ ﺍﺟﺮﺍ ﻣﻲﺷﻮﻧﺪ ﻳﻌﻨﻲ ﺍﺑﺘﺪﺍ )( Xﻭ ﺳﭙﺲ )( . Yﺑﺎ ﺍﻳﻦ ﺣﺴﺎﺏ ﺑﺮﺍﻱ ﻫﺮ
ﺷﻲ 4100 ،ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﺪ ) 8ﺑﺎﻳﺖ ﺑﺮﺍﻱ Xﻭ 4092ﺑﺎﻳﺖ ﺑﺮﺍﻱ
.(Yﺍﻣﺎ ﭼﻮﻥ rﺑﻪ ﻋﻨﻮﺍﻥ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺍﺷﻴﺎﻱ Xﻣﻌﺮﻓﻲ ﺷﺪﻩ ،ﻓﻘﻂ ﻧﺎﺑﻮﺩﮔﺮ Xﺭﺍ ﺍﺣﻀﺎﺭ
ﻣﻲﮐﻨﺪ ﻭ ﻓﻘﻂ 8ﺑﺎﻳﺖ ﺭﺍ ﺁﺯﺍﺩ ﻣﻲﺳﺎﺯﺩ ﻭ 4092ﺑﺎﻳﺖ ﺑﺎﻗﻲﻣﺎﻧﺪﻩ ،ﺑﻼﺗﮑﻠﻴﻒ ﻣﻲﻣﺎﻧﻨﺪ.
ﭘﺲ ﺩﺭ ﻫﺮ ﺗﮑﺮﺍﺭ 3992ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﻧﺎﭘﺪﻳﺪ ﻣﻲﺷﻮﺩ! ﺧﺮﻭﺟﻲ ﻧﻴﺰ ﺍﻳﻦ ﺭﺍ ﺗﺎﻳﻴﺪ
ﻣﻲﮐﻨﺪ .ﺑﺮﺍﻱ ﺭﻓﻊ ﺍﻳﻦ ﺍﺷﮑﺎﻝ ،ﻧﺎﺑﻮﺩﮔﺮ )( ~Xﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﻣﻌﺮﻓﻲ ﮐﺮﺩﻩ ﻭ ﺑﺮﻧﺎﻣﻪ
ﺭﺍ ﺩﻭﺑﺎﺭﻩ ﺍﺟﺮﺍ ﻣﻲﻧﻤﺎﻳﻴﻢ:
class X
{ public:
x() { p = new int[2]; cout << "X(). } ;"
} "virtual ~X() { delete [] p; cout << "~X().\n
private:
;int* p
;}
X(). )(Y : Y::q = 0x5a220. ~Y(). ~X().
X(). )(Y : Y::q = 0x5a220. ~Y(). ~X().
X(). )(Y : Y::q = 0x5a220. ~Y(). ~X().
X(). )(Y : Y::q = 0x5a220. ~Y(). ~X().
X(). )(Y : Y::q = 0x5a220. ~Y(). ~X().
X(). )(Y : Y::q = 0x5a220. ~Y(). ~X().
X(). )(Y : Y::q = 0x5a220. ~Y(). ~X().
X(). )(Y : Y::q = 0x5a220. ~Y(). ~X().
379 ﻓﺼﻞ ﻳﺎزدهﻢ /ﺗﺮﮐﻴﺐ و وراﺛﺖ
ﺣﺎﻻ ﻫﺮ ﺗﮑﺮﺍﺭ ﺣﻠﻖۀ forﻫﺮ ﺩﻭ ﻧﺎﺑﻮﺩﮔﺮ ﻓﺮﺍ ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﻧﺘﻴﺠﻪ ﻫﻢۀ ﺣﺎﻓﻆۀ
ﺗﺨﺼﻴﺺ ﻳﺎﻓﺘﻪ ﺁﺯﺍﺩ ﻣﻲﺷﻮﺩ ﻭ ﺍﻳﻦ ﺣﺎﻓﻈﻪ ﺩﻭﺑﺎﺭﻩ ﻣﻲﺗﻮﺍﻧﺪ ﺑﺮﺍﻱ ﺍﺷﺎﺭﻩﮔﺮ rﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ.
ﻣﺜﺎﻝ ﺑﺎﻻ ،ﺍﻳﺮﺍﺩ ﺷﮑﺎﻑ ﺣﺎﻓﻈﻪ 1ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﺩﺭ ﻳﮏ ﻧﺮﻡﺍﻓﺰﺍﺭ ﺑﺰﺭﮒ ،ﺍﻳﻦ ﻣﺴﺎﻟﻪ
ﻣﻲﺗﻮﺍﻧﺪ ﺑﺎﻋﺚ ﺑﺮﻭﺯ ﻓﺎﺟﻌﻪ ﺷﻮﺩ .ﻣﺨﺼﻮﺻﺎ ﺍﻳﻦ ﮐﻪ ﭘﻴﺪﺍ ﮐﺮﺩﻥ ﺍﻳﺮﺍﺩ ﻓﻮﻕ ﺑﺴﻴﺎﺭ ﻣﺸﮑﻞ
ﺍﺳﺖ .ﭘﺲ ﺑﺨﺎﻃﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﻫﺮ ﻭﻗﺖ ﺍﺯ ﺍﺷﻴﺎﻱ ﭘﻮﻳﺎ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﺪ،
ﻧﺎﺑﻮﺩﮔﺮ ﮐﻼﺱ ﻭﺍﻟﺪ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﺪ.
BOOK
ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﺨﻮﺍﻫﻴﻢ ﺩﺭ ﻳﮏ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﮐﻼﺱ Htmlﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ .ﺷﻲﮔﺮﺍﻳﻲ
ﺗﻮﺻﻴﻪ ﺩﺍﺭﺩ ﮐﻪ ﺍﺑﺘﺪﺍ ﮐﻼﺱ ﭘﺎﻱۀ Bookﺭﺍ ﺍﻋﻼﻥ ﮐﻨﻴﻢ ﻭ ﺍﺯ ﺁﻥ ﮐﻼﺱ Ebook ،ﺭﺍ
ﻣﺸﺘﻖ 2ﮐﺮﺩﻩ ﻭ ﺍﺯ Ebookﻧﻴﺰ ﺯﻳﺮﮐﻼﺱ Htmlﺭﺍ ﻣﺸﺘﻖ ﻧﻤﺎﻳﻴﻢ .ﮔﺮﭼﻪ ﻣﻤﮑﻦ ﺍﺳﺖ
ﺍﻳﻦ ﺭﻭﺵ ﺩﺭ ﺍﺑﺘﺪﺍ ﺑﻲﻣﻌﻨﻲ ﻭ ﺣﺘﻲ ﻭﻗﺖﮔﻴﺮ ﻭ ﻏﻴﺮﻣﻨﻄﻘﻲ ﺑﻪ ﻧﻈﺮ ﺑﺮﺳﺪ ،ﺍﻣﺎ ﺩﺭ ﺍﺻﻞ
ﺭﻭﺵ ﻣﺬﮐﻮﺭ ﺳﺒﺐ ﺳﻬﻮﻟﺖ ﺩﺭ ﺍﺻﻼﺡ ﻭ ﭘﺸﺘﻴﺒﺎﻧﻲ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺷﻮﺩ .ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺩﺭ
ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺗﺠﺎﺭﻱ ،ﺑﺴﻴﺎﺭ ﻣﻬﻢ ﻭ ﺣﻴﺎﺗﻲ ﺍﺳﺖ.
ﻣﻲﺩﺍﻧﻴﻢ ﮐﻪ ﺩﺭ ﺳﺎﺧﺘﺎﺭ ﻓﻮﻕ ،ﻫﺮ ﮐﻼﺱ ﺩﺍﺭﺍﻱ ﺗﻮﺍﺑﻊ ﺧﺎﺻﻲ ﺍﺳﺖ ﮐﻪ ﺭﻓﺘﺎﺭﻫﺎﻱ
ﻭﻳﮋۀ ﺁﻥ ﮐﻼﺱ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ .ﻣﻤﮑﻦ ﺍﺳﺖ ﺗﻮﺍﺑﻌﻲ ﻣﺠﺎﺯﻱ ﻫﻢ ﻭﺟﻮﺩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ ﮐﻪ
ﺩﺭ ﻫﻢۀ ﺯﻳﺮﮐﻼﺱﻫﺎ ﻣﻐﻠﻮﺏ ﺷﻮﻧﺪ ﻭ ﻧﺴﺨﻪﺍﻱ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥﻫﺎ ﺍﻳﺠﺎﺩ ﺷﻮﺩ .ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ
ﺩﻳﮕﺮ ﻧﻴﺎﺯﻱ ﻧﻴﺴﺖ ﮐﻪ ﺗﻮﺍﺑﻊ ﻣﺬﮐﻮﺭ ﺩﺭ ﮐﻼﺱﻫﺎﻱ ﭘﺎﻳﻪ ﺩﺍﺭﺍﻱ ﺑﺪﻧﻪ ﺑﺎﺷﻨﺪ ﺯﻳﺮﺍ ﺍﻳﻦ ﺑﺪﻧﻪ
ﻫﺮﮔﺰ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﻧﻤﻲﺷﻮﺩ .ﺩﺭ ﺍﻳﻦ ﮔﻮﻧﻪ ﻣﻮﺍﻗﻊ ،ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺗﺎﺑﻊ
ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ 1ﺍﻋﻼﻥ ﻣﻲﮐﻨﻨﺪ .ﻳﮏ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ،ﺗﺎﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ﻫﻴﭻ
ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻧﺪﺍﺭﺩ ﻭ ﻓﺎﻗﺪ ﺑﺪﻧﻪ ﺍﺳﺖ .ﺩﺭ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺑﻪ ﺟﺎﻱ ﺑﺪﻧﻪ ،ﻋﺒﺎﺭﺕ ; =0ﺭﺍ ﻗﺮﺍﺭ
ﻣﻲﺩﻫﻨﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ،ﺩﺭ ﻫﻢۀ ﮐﻼﺱﻫﺎﻱ ﺭﺍﺑﻂۀ ﻓﻮﻕ ،ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )( printﻭﺟﻮﺩ
ﺩﺍﺭﺩ ﮐﻪ ﻫﺮ ﺯﻳﺮﮐﻼﺱ ﻳﮏ ﻧﺴﺦۀ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥ ﺭﺍ ﺩﺍﺭﺩ .ﭘﺲ ﻻﺯﻡ ﻧﻴﺴﺖ ﮐﻪ ﺩﺭ ﮐﻼﺱ
ﭘﺎﻱۀ Bookﺑﺮﺍﻱ ﺍﻳﻦ ﺗﺎﺑﻊ ،ﺑﺪﻧﻪﺍﻱ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ .ﻓﻘﻂ ﮐﺎﻓﻲ ﺍﺳﺖ ﺩﺳﺘﻮﺭ
;virtual void print()=0
ﺭﺍ ﺩﺭ ﮐﻼﺱ Bookﺑﮕﻨﺠﺎﻧﻴﻢ .ﻫﺮ ﻭﻗﺖ ﭼﻨﻴﻦ ﻋﺒﺎﺭﺗﻲ ﺩﺭ ﺑﺪﻥۀ ﻳﮏ ﮐﻼﺱ ﻇﺎﻫﺮ ﺷﻮﺩ،
ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﺩﺭ ﺍﻳﻦ ﮐﻼﺱ ﻫﺮﮔﺰ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﻲﺷﻮﺩ ﻭ ﺯﻳﺮﮐﻼﺳﻲ
ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﮐﻪ ﻧﺴﺦۀ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥ ﺗﺎﺑﻊ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺧﻮﺍﻫﺪ ﮔﺮﻓﺖ .ﮐﻼﺳﻲ ﮐﻪ ﻳﮏ ﻳﺎ ﭼﻨﺪ
ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺭﺍ ﮐﻼﺱ ﭘﺎﻱۀ ﺍﻧﺘﺰﺍﻋﻲ 2ﻣﻲﻧﺎﻣﻴﻢ )ﺑﻪ ﺁﻥ ﮐﻼﺱ ﭘﺎﻱۀ
ﻣﺠﺮﺩ ﻧﻴﺰ ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ( .ﮐﻼﺱﻫﺎﻱ ﭘﺎﻱۀ ﻣﺠﺮﺩ ﻓﻘﻂ ﺑﺮﺍﻱ ﺳﺎﺧﺘﻦ ﻭ ﺍﺷﺘﻘﺎﻕ ﺯﻳﺮﮐﻼﺱﻫﺎ
ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ﻭ ﻫﻴﭻ ﺷﻴﺌﻲ ﻣﺴﺘﻘﻴﻤﺎ ﺍﺯ ﺭﻭﻱ ﺁﻥﻫﺎ ﺳﺎﺧﺘﻪ ﻧﻤﻲﺷﻮﺩ .ﮐﻼﺳﻲ ﮐﻪ ﻫﻴﭻ ﺗﺎﺑﻊ
ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺭﺍ »ﮐﻼﺱ ﻣﺸﺘﻖﺷﺪۀ ﻭﺍﻗﻌﻲ« ﻣﻲﮔﻮﻳﻴﻢ .ﺍﺷﻴﺎﻱ ﺩﺍﺧﻞ ﻳﮏ
ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺭﻭﻱ ﮐﻼﺱﻫﺎﻱ ﻣﺸﺘﻖ ﺷﺪۀ ﻭﺍﻗﻌﻲ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﻧﺪ.
ﺍﮔﺮ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﺍﺻﻼ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﻲﺷﻮﺩ ،ﭘﺲ ﺍﺻﻼ ﭼﺮﺍ ﺁﻥ ﺭﺍ ﺍﻋﻼﻥ ﻣﻲﮐﻨﻴﻢ؟
ﭘﺎﺳﺦ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﺭﺍ ﺍﻋﻼﻥ ﻣﻲﮐﻨﻴﻢ ﺗﺎ ﺗﺎﮐﻴﺪ ﮐﻨﻴﻢ ﮐﻪ ﺩﺳﺖ ﮐﻢ ﻳﮏ
ﺯﻳﺮﮐﻼﺱ ﺑﺎﻳﺪ ﻧﺴﺨﻪﺍﻱ ﻣﺤﻠﻲ ﺍﺯ ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ.
ﺩﺭ ﮐﺪ ﺑﺎﻻ ،ﮐﻼﺱ VCRﻳﮏ ﮐﻼﺱ ﭘﺎﻱۀ ﺍﻧﺘﺰﺍﻋﻲ ﺍﺳﺖ ﮐﻪ ﮐﻼﺱ Videoﻭ Camera
ﺍﺯ ﺁﻥ ﻣﺸﺘﻖ ﻣﻲﺷﻮﺩ .ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﮐﻼﺱ VCRﻫﻤﮕﻲ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ
ﺍﻋﻼﻥ ﺷﺪﻩﺍﻧﺪ .ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺩﺭ ﺯﻳﺮﮐﻼﺱ Videoﻭ Cameraﻧﻴﺰ ﺍﻋﻼﻥ ﺷﺪﻩﺍﻧﺪ ﮐﻪ
ﻧﺴﺨﻪﻫﺎﻱ ﻣﺤﻠﻲ ﻭ ﻏﺎﻟﺐ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ.
ﻣﺜﺎﻝﻫﺎﻳﻲ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﻓﺼﻞ ﻭ ﺩﻭ ﻓﺼﻞ ﻗﺒﻞ ﺩﻳﺪﻳﺪ ﺧﻴﻠﻲ ﮐﺎﺭﺑﺮﺩﻱ ﻧﺴﺘﻨﺪ ﻭ ﻓﻘﻂ
ﺑﺮﺍﻱ ﺁﻣﻮﺯﺵ ﻣﻔﺎﻫﻴﻢ ﺷﻲﮔﺮﺍﻳﻲ ﺑﻴﺎﻥ ﺷﺪﻩﺍﻧﺪ .ﺣﺎﻻ ﮐﻪ ﺑﺎ ﺷﻲﮔﺮﺍﻳﻲ ﻭ ﻣﺰﺍﻳﺎﻱ ﺁﻥ ﺁﺷﻨﺎ
ﺷﺪﻩﺍﻳﺪ ،ﻭﻗﺖ ﺁﻥ ﺭﺳﻴﺪﻩ ﮐﻪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺷﻲﮔﺮﺍ ﺭﺍ ﺑﺎ ﺟﺪﻳﺖ ﺩﻧﺒﺎﻝ ﮐﻨﻴﺪ ﻭ ﺗﻼﺵ ﺩﺍﺷﺘﻪ
ﺑﺎﺷﻴﺪ ﮐﻪ ﺍﺯ ﺍﻳﻦ ﭘﺲ ،ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﻣﻲﻧﻮﻳﺴﻴﺪ ﺷﻲﮔﺮﺍ ﺑﺎﺷﻨﺪ .ﻣﻤﮑﻦ ﺍﺳﺖ ﺩﺭ ﺷﺮﻭﻉ ﮐﺎﺭ
ﺑﺎ ﻣﺸﮑﻼﺗﻲ ﻣﻮﺍﺣﻪ ﺷﻮﻳﺪ ﮐﻪ ﺑﺎ ﻣﺮﻭﺭ ﻣﻄﺎﻟﺐ ﺫﮐﺮ ﺷﺪﻩ ﺧﻮﺍﻫﻴﺪ ﺗﻮﺍﻧﺴﺖ ﺑﺮ ﺁﻥﻫﺎ ﻏﻠﺒﻪ
ﮐﻨﻴﺪ .ﻫﺮ ﭼﻪ ﺑﻴﺸﺘﺮ ﺩﺭ ﺷﻲﮔﺮﺍﻳﻲ ﺗﺒﺤﺮ ﭘﻴﺪﺍ ﮐﻨﻴﺪ ،ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺗﺠﺎﺭﻱ ﻣﻄﻤﺌﻦﺗﺮﻳﻦ ﺧﻮﺍﻫﻴﺪ
ﻧﻮﺷﺖ ﻭ ﺍﺣﺘﻤﺎﻝ ﺷﮑﺴﺖ ﺩﺭ ﭘﺮﻭﮊﻩﻫﺎﻱ ﮔﺮﻭﻫﻲ ﮐﻪ ﺍﺟﺮﺍ ﻣﻲﮐﻨﻴﺪ ،ﮐﻢﺗﺮ ﻣﻲﺷﻮﺩ.
ﻣﺴﻠﻢ ﺍﺳﺖ ﮐﻪ ﺷﻲﮔﺮﺍﻳﻲ ،ﺭﻫﻴﺎﻓﺖ ﻧﻬﺎﻳﻲ ﺩﺭ ﺟﻬﺎﻥ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﻧﻴﺴﺖ ﻭ ﻫﺮ
ﭼﻪ ﺯﻣﺎﻥ ﻣﻲﮔﺬﺭﺩ ،ﺭﺍﻫﮑﺎﺭﻫﺎﻱ ﺗﺎﺯﻩﺍﻱ ﺩﺭ ﺟﻬﺖ ﺁﺳﺎﻥﺳﺎﺯﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﭘﺪﻳﺪ ﻣﻲﺁﻳﺪ
ﻟﻴﮑﻦ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺷﻲﮔﺮﺍﻳﻲ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﺭﺍﻫﮑﺎﺭ ﻗﺎﺑﻞ ﺍﻋﺘﻤﺎﺩ ،ﭘﺬﻳﺮﻓﺘﻪﺍﻧﺪ.
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ 382
ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
– 1ﺩﺭ ﮐﺪ } { class X : public Yﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ – ﮐﻼﺱ Xﻋﻀﻮﻱ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ Yﺩﺍﺭﺩ
ﺏ – ﮐﻼﺱ Xﻭﺍﻟﺪ ﮐﻼﺱ Yﺍﺳﺖ
ﺝ – ﮐﻼﺱ Yﺍﺯ ﮐﻼﺱ Xﻣﺸﺘﻖ ﺷﺪﻩ ﺍﺳﺖ
ﺩ – ﮐﻼﺱ Xﺑﻪ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﮐﻼﺱ Yﺩﺳﺘﺮﺳﻲ ﺩﺍﺭﺩ
– 2ﺍﮔﺮ ﮐﻼﺱ Aﻓﺮﺯﻧﺪ ﮐﻼﺱ Bﺑﺎﺷﺪ ،ﺁﻧﮕﺎﻩ:
ﺍﻟﻒ – ﮐﻼﺱ Aﺑﻪ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﮐﻼﺱ Bﺩﺳﺘﺮﺳﻲ ﺩﺍﺭﺩ
ﺏ – ﮐﻼﺱ Bﺑﻪ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﮐﻼﺱ Aﺩﺳﺘﺮﺳﻲ ﺩﺍﺭﺩ
ﺝ – ﮐﻼﺱ Bﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﮐﻼﺱ Aﺩﺳﺘﺮﺳﻲ ﺩﺍﺭﺩ
ﺩ – ﮐﻼﺱ Bﺑﻪ ﺍﻋﻀﺎﻱ ﺣﻔﺎﻇﺖﺷﺪ ۀ ﮐﻼﺱ Aﺩﺳﺘﺮﺳﻲ ﺩﺍﺭﺩ
– 3ﻓﺮﺽ ﮐﻨﻴﺪ ﮐﻼﺱ Aﻓﺮﺯﻧﺪ ﮐﻼﺱ Bﺍﺳﺖ .ﺍﮔﺮ ﮐﻼﺱ Bﺩﺍﺭﺍﻱ ﻳﮏ ﻋﻀﻮ
ﺣﻔﺎﻇﺖﺷﺪﻩ ﺑﻪ ﻧﺎﻡ mﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ:
ﺍﻟﻒ – ﮐﻼﺱ Aﻋﻀﻮ mﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺑﻪ ﺍﺭﺙ ﻣﻲﮔﻴﺮﺩ
ﺏ – ﮐﻼﺱ Aﻋﻀﻮ mﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﺑﻪ ﺍﺭﺙ ﻣﻲﮔﻴﺮﺩ
ﺝ – ﮐﻼﺱ Aﻋﻀﻮ mﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻋﻀﻮ ﺣﻔﺎﻇﺖ ﺷﺪﻩ ﺑﻪ ﺍﺭﺙ ﻣﻲﮔﻴﺮﺩ
ﺩ – ﮐﻼﺱ Aﺍﺟﺎﺯۀ ﺩﺳﺘﻴﺎﺑﻲ ﺑﻪ ﻋﻀﻮ mﺭﺍ ﻧﺪﺍﺭﺩ
– 4ﻓﺮﺽ ﮐﻨﻴﺪ ﮐﻼﺱ Aﻓﺮﺯﻧﺪ ﮐﻼﺱ Bﺍﺳﺖ ﻭ ﺩﺭ ﻫﺮ ﺩﻭ ﮐﻼﺱ ،ﻳﮏ ﻋﻀﻮ ﻋﻤﻮﻣﻲ
ﺑﻪ ﻧﺎﻡ xﺍﻋﻼﻥ ﺷﺪﻩ .ﺣﺎﻝ ﺍﮔﺮ aﻳﮏ ﺷﻲ ﺍﺯ ﮐﻼﺱ Aﻭ bﻳﮏ ﺷﻲ ﺍﺯ ﮐﻼﺱ Bﺑﺎﺷﺪ،
ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟
ﺍﻟﻒ – a.xﻋﻀﻮ ﻏﺎﻟﺐ ﺍﺳﺖ ﻭ a.B::xﻋﻀﻮ ﻣﻮﺭﻭﺛﻲ ﺍﺳﺖ
ﺏ – b.xﻋﻀﻮ ﻏﺎﻟﺐ ﺍﺳﺖ ﻭ b.A::xﻋﻀﻮ ﻣﻮﺭﻭﺛﻲ ﺍﺳﺖ
ﺝ – a.B::xﻋﻀﻮ ﻏﺎﻟﺐ ﺍﺳﺖ ﻭ a.xﻋﻀﻮ ﻣﻮﺭﻭﺛﻲ ﺍﺳﺖ
ﺩ – b.A::xﻋﻀﻮ ﻏﺎﻟﺐ ﺍﺳﺖ ﻭ b.xﻋﻀﻮ ﻣﻮﺭﻭﺛﻲ ﺍﺳﺖ
383 ﻓﺼﻞ ﻳﺎزدهﻢ /ﺗﺮﮐﻴﺐ و وراﺛﺖ
ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
‐1ﺗﺮﻛﻴﺐ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﻭﺭﺍﺛﺖ ﺩﺍﺭﺩ؟
‐2ﺍﻋﻀﺎﻱ protectedﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﺍﻋﻀﺎﻱ privateﺩﺍﺭﻧﺪ؟
‐3ﺭﻓﺘﺎﺭ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ﻭ ﻧﺎﺑﻮﺩﻛﻨﻨﺪﻩ ﺩﺭ ﻭﺭﺍﺛﺖ ﭼﮕﻮﻧﻪ ﺍﺳﺖ؟
‐4ﺗﺎﺑﻊ ﻋﻀﻮ ) virtualﻣﺠﺎﺯﻱ( ﭼﻴﺴﺖ؟
‐5ﺗﺎﺑﻊ ﻋﻀﻮ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﭼﻴﺴﺖ؟
‐6ﺷﮑﺎﻑ ﺣﺎﻓﻈﻪ ﭼﮕﻮﻧﻪ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﺑﺮﺍﻱ ﺟﻠﻮﮔﻴﺮﻱ ﺍﺯ ﺁﻥ ﭼﻪ ﺑﺎﻳﺪ ﮐﺮﺩ؟
‐8ﻛﻼﺱ ﭘﺎﻱۀ ﺍﻧﺘﺰﺍﻋﻲ ﭼﻴﺴﺖ ﻭ ﭼﺮﺍ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ؟
‐9ﻛﻼﺱ ﻣﺸﺘﻖﺷﺪۀ ﻭﺍﻗﻌﻲ ﭼﻴﺴﺖ؟
‐10ﺑﺴﺘﻪﺑﻨﺪﻱ ﺍﻳﺴﺘﺎ ﻭ ﺑﺴﺘﻪﺑﻨﺪﻱ ﭘﻮﻳﺎ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﻫﻢ ﺩﺍﺭﺩ؟
‐12ﭼﻨﺪﺭﻳﺨﺘﻲ ﭼﻴﺴﺖ ﻭ ﭼﮕﻮﻧﻪ ﺳﺒﺐ ﺗﻮﺳﻊۀ ﮐﻼﺱ ﻣﻲﺷﻮﺩ؟
‐13ﭼﻪ ﺧﻄﺎﻳﻲ ﺩﺭ ﺗﻌﺎﺭﻳﻒ ﺯﻳﺮ ﺍﺳﺖ؟
class X
{ protected:
;int a
;}
ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
‐1ﺳﻠﺴﻠﻪ ﻣﺮﺍﺗﺐ ﻛﻼﺱ ﺯﻳﺮ ﺭﺍ ﭘﻴﺎﺩﻩ ﺳﺎﺯﻱ ﻛﻨﻴﺪ:
shape
TwoDimentional ThreeDimentional
‐2ﻛﻼﺱ Nameﻛﻪ ﺍﺷﻴﺎﻱ ﺁﻥ ﺷﺒﻴﻪ ﺷﻜﻞ ﺯﻳﺮ ﻫﺴﺘﻨﺪ ﺭﺍ ﺗﻌﺮﻳﻒ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ .ﺳﭙﺲ
ﻛﻼﺳﻲ ﺑﻪ ﻧﺎﻡ Personﺍﻳﺠﺎﺩ ﮐﻨﻴﺪ ﮐﻪ ﻣﺸﺨﺼﺎﺕ
name
ﺍﻓﺮﺍﺩ ﺷﺎﻣﻞ ﻧﺎﻡ ،ﺗﺎﺭﻳﺦ ﺗﻮﻟﺪ ،ﺳﻦ ﻭ ﻣﺪﺭﮎ ﺗﺤﺼﻴﻠﻲ
first Mahmoud
ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﮐﻨﺪ .ﮐﻼﺱ Personﺭﺍ ﻃﻮﺭﻱ
last Kaveh ﺗﻌﺮﻳﻒ ﮐﻨﻴﺪ ﮐﻪ ﺑﺮﺍﻱ ﻧﮕﻬﺪﺍﺭﻱ ﻧﺎﻡ ﺑﻪ ﺟﺎﻱ ﻧﻮﻉ
stringﺍﺯ ﻧﻮﻉ Nameﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﺪ:
nick Tehrani
‐3ﮐﻼﺱ Addressﮐﻪ ﺍﺷﻴﺎﻱ ﺁﻥ ﺷﺒﻴﻪ ﺷﮑﻞ ﺯﻳﺮ ﻫﺴﺘﻨﺪ ﺭﺍ ﺗﻌﺮﻳﻒ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ.
ﺳﭙﺲ ﺑﺎ ﺍﻓﺰﻭﺩﻥ ﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ addressﺑﻪ ﮐﻼﺱ Personﺩﺭ ﺗﻤﺮﻳﻦ ﻗﺒﻠﻲ ،ﺁﻥ
address ﺭﺍ ﺑﻬﺒﻮﺩ ﺩﻫﻴﺪ.
country IRAN
state Tehran
city Tehran
street Azadi
ﺿﻤﻴﻢۀ » ﺍﻟﻒ «
ﭘﺎﺳﺦﻧﺎﻡۀ ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
ﺿﻤﻴﻤﻪ » ﺏ «
ﺟﺪﻭﻝ ﺍﺳﮑﻲ
ﻫﺮ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ ﺻﻮﺭﺕ ﻳﮏ ﮐﺪ ﺻﺤﻴﺢ ﺩﺭ ﺣﺎﻓﻈﻪ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ .ﺍﻳﻦ ﮐﺪ ،ﻋﺪﺩﻱ
ﺩﺭ ﻣﺤﺪﻭﺩۀ ﺻﻔﺮ ﺗﺎ 127ﺍﺳﺖ .ﺑﻪ ﺟﺪﻭﻟﻲ ﮐﻪ ﺗﻤﺎﻡ 128ﮐﺎﺭﺍﮐﺘﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﺍﻳﻦ
ﻣﺤﺪﻭﺩﻩ ﺭﺍ ﺑﺎ ﻳﮏ ﺗﺮﺗﻴﺐ ﺍﺯ ﭘﻴﺶ ﻣﺸﺨﺺ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ،ﺟﺪﻭﻝ ASCIIﻣﻲﮔﻮﻳﻨﺪ.
ﺷﺮﺡ ﺍﻳﻦ ﺟﺪﻭﻝ ﺩﺭ ﺍﺩﺍﻣﻪ ﺁﻣﺪﻩ ﺍﺳﺖ .ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ 32ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ
ﭼﺎﭖﻧﺸﺪﻧﻲ ﻫﺴﺘﻨﺪ .ﻟﺬﺍ ﺑﻪ ﺟﺎﻱ ﻧﺸﺎﻥ ﺩﺍﺩﻥ ﺳﻤﺒﻞ ﺁﻥﻫﺎ ﺩﺭ ﺳﺘﻮﻥ ﺍﻭﻝ ،ﺯﻧﺠﻴﺮ ۀ ﮐﻨﺘﺮﻟﻲ
ﺁﻥﻫﺎ ﻳﺎ ﺯﻧﺠﻴﺮۀ ﺧﺮﻭﺟﻲ ﺁﻥﻫﺎ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ .ﺯﻧﺠﻴﺮۀ ﮐﻨﺘﺮﻟﻲ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻏﻴﺮ
ﭼﺎﭘﻲ ،ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﮐﻠﻴﺪ Ctrlﺑﺎ ﮐﻠﻴﺪ ﺩﻳﮕﺮﻱ ﺍﺳﺖ ﮐﻪ ﺍﻳﻦ ﺩﻭ ﺑﺎﻫﻢ ﻓﺸﺎﺭ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ
ﺗﺎ ﮐﺎﺭﺍﮐﺘﺮ ﻣﻮﺭﺩ ﻧﻈﺮ ﻭﺍﺭﺩ ﺷﻮﺩ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ،ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ )ﺑﺎ ﮐﺪ ﺍﺳﮑﻲ (4ﺑﺎ ﺯﻧﺠﻴﺮۀ
Ctrl+Dﻭﺍﺭﺩ ﻣﻲﺷﻮﺩ .ﺯﻧﺠﻴﺮۀ ﺧﺮﻭﺟﻲ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻏﻴﺮ ﭼﺎﭘﻲ ،ﺗﺮﮐﻴﺒﻲ ﺍﺳﺖ ﺍﺯ
ﮐﺎﺭﺍﮐﺘﺮ ﺑﮏ ﺍﺳﻠﺶ \ )ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮ ﮐﻨﺘﺮﻝ ﻧﺎﻣﻴﺪﻩ ﺷﺪﻩ( ﻭ ﻳﮏ ﺣﺮﻑ ﮐﻪ ﺩﺭ ﮐﺪ ﻣﻨﺒﻊ C++
ﺗﺎﻳﭗ ﻣﻲﺷﻮﺩ ﺗﺎ ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﻣﺸﺨﺺ ﮐﻨﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﮐﺎﺭﺍﮐﺘﺮ ﺧﻂ ﺟﺪﻳﺪ )ﺑﺎ ﮐﺪ ﺍﺳﮑﻲ
(10ﺩﺭ ﺑﺮﻧﺎﻡۀ C++ﺑﻪ ﺻﻮﺭﺕ \nﻧﻮﺷﺘﻪ ﻣﻲﺷﻮﺩ.
)(x>0 and x<8 ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﻣﻨﻄﻘﻲ && : AND and
;b1 and_eq b2 ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﺗﺨﺼﻴﺼﻲ ANDﺑﻴﺘﻲ &= : and_eq
;)"asm ("check ﺍﺟﺎﺯﻩ ﻣﻲ ﺩﻫﺪ ﺗﺎ ﺍﻃﻼﻋﺎﺕ ﻣﺴﺘﻘﻴﻤﺎ ﺑﻪ ﺍﺳﻤﺒﻠﺮ ﻓﺮﺳﺘﺎﺩﻩ ﺷﻮﺩ asm
;auto int n ﮐﻼﺱ ﺫﺧﻴﺮﻩ ﺳﺎﺯﻱ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﻓﻘﻂ ﺩﺭﻭﻥ ﺑﻼﮎ ﺧﻮﺩﺷﺎﻥ ﺍﻳﺎﺟﺪ ﻣﻲ ﺷﻮﻧﺪ auto
;b0 = b1 bitand b2 ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ANDﺑﻴﺘﻲ & : bitand
)catch(error ﻓﻌﺎﻟﻴﺖ ﻫﺎﻳﻲ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﻭﻗﺘﻲ ﻳﮏ ﺍﺳﺘﺜﻨﺎ ﺭﺥ ﻣﻲ ﺩﻫﺪ ﺑﺎﻳﺪ ﺍﺟﺮﺍ ﺷﻮﻧﺪ catch
ﺿﻤﻴﻤﻪ » ﺝ «
ﮐﻠﻤﺎﺕ ﮐﻠﻴﺪﻱ C++
;b0 = compl b1 ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﻣﻨﻄﻘﻲ NOTﺑﻴﺘﻲ ~ : compl
)pp = const_cast<T*>(p ﺑﺮﺍﻱ ﺗﻐﻴﻴﺮ ﺩﺍﺩﻥ ﺍﺷﻴﺎ ﺍﺯ ﺩﺭﻭﻥ ﺗﺎﺑﻊ ﻋﻀﻮ ﺗﻐﻴﻴﺮﻧﺎﭘﺬﻳﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﺷﻮﺩ const_cast
;double x ﻧﻮﻉ ﻋﺪﺩﻱ ﺣﻘﻴﻘﻲ )ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺑﺎ ﺩﻗﺖ ﻣﻀﺎﻋﻒ( double
pp = dynamic_cast<T*>p ﺑﺮﺍﻱ ﺍﺷﺎﺭﻩ ﮔﺮ ﺩﺍﺩﻩ ﺷﺪﻩ ،ﺍﺷﺎﺭﻩ ﮔﺮ * Tﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ dynamic_cast
;}…{ enum bool ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﺷﻮﺩ enum
;)explicit X(int n ﺑﺎﻋﺚ ﻣﻲ ﺷﻮﺩ ﺗﺎ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺿﻤﻨﻲ ﻳﮏ ﺳﺎﺯﻧﺪﻩ ﺟﻠﻮﮔﻴﺮﻱ ﺷﻮﺩ explicit
>export template<class T ﺩﺳﺘﺮﺳﻲ ﺍﺯ ﻭﺍﺣﺪ ﮐﺎﻣﭙﺎﻳﻞ ﺩﻳﮕﺮ ﺭﺍ ﻣﻤﮑﻦ ﻣﻲ ﺳﺎﺯﺩ export
;extern int max ﮐﻼﺱ ﺫﺧﻴﺮﻩ ﺳﺎﺯﻱ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﺑﻴﺮﻭﻥ ﺍﺯ ﺑﻠﻮﮎ ﻣﺤﻠﻲ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﻧﺪ extern
;)(friend int f ﺩﺭ ﻳﮏ ﮐﻼﺱ ،ﺗﺎﺑﻊ ﺩﻭﺳﺖ ﺍﻳﺠﺎﺩ ﻣﻲ ﮐﻨﺪ friend
;goto error ﺑﺎﻋﺚ ﻣﻲ ﺷﻮﺩ ﺗﺎ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻳﮏ ﺟﻤﻞۀ ﺑﺮﭼﺴﺐ ﺩﺍﺭ ﭘﺮﺵ ﮐﻨﺪ goto
;)(inline int f ﺗﺎﺑﻌﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﻣﺘﻦ ﺁﻥ ﺗﺎﺑﻊ ﺑﺎﻳﺪ ﺑﻪ ﺟﺎﻱ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺁﻥ ﺩﺭﺝ ﺷﻮﺩ. inline
;long double x ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﺍﻧﻮﺍﻉ ﮔﺴﺘﺮﺵ ﻳﺎﻓﺘﻪ ﺻﺤﻴﺢ ﻭ ﺣﻘﻴﻘﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﺷﻮﺩ long
;mutable string ssn ﺑﻪ ﺗﻮﺍﺑﻊ ﺗﻐﻴﻴﺮ ﻧﺎﭘﺬﻳﺮ ﺍﺟﺎﺯﻩ ﻣﻲ ﺩﻫﺪ ﺗﺎ ﻓﻴﻠﺪ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﻨﺪ mutable
} ;namespace best { int num ﺑﻠﻮﮎ ﻫﺎﻱ ﻓﻀﺎﻱ ﻧﺎﻡ )ﻣﻴﺪﺍﻥ( ﺭﺍ ﻣﻲ ﺷﻨﺎﺳﺎﻧﺪ namespace
)(x not_eq 0 ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﻧﺎﺑﺮﺍﺑﺮﻱ != : not_eq
/ﮐﻠﻤﺎت ﮐﻠﻴﺪی C++
;b1 or_eq b2 ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﺗﺨﺼﻴﺼﻲ ORﺑﻴﺘﻲ |= : or_eq
;protected: int n ﺍﻋﻀﺎﻱ ﺣﻔﺎﻇﺖ ﺷﺪﻩ ﺭﺍ ﺩﺭ ﻳﮏ ﮐﻼﺱ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ protected
;register int i ﻣﺸﺨﺺ ﮐﻨﻨﺪﻩ ﮐﻼﺱ ﺫﺧﻴﺮﻩ ﺳﺎﺯﻱ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﺩﺭ ﺛﺒﺎﺕ ﻫﺎ ﺫﺧﻴﺮﻩ ﻣﻲ ﺷﻮﻧﺪ register
;signed char c ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﺍﻧﻮﺍﻉ ﺻﺤﻴﺢ ﻋﻼﻣﺖ ﺩﺍﺭ ﺑﻪ ﮐﺎﺭ ﻣﻲ ﺭﻭﺩ signed
ﻣﺜﺎﻝ ﺷﺮﺡ ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ
;)n = sizeof(float ﺗﻌﺪﺍﺩ ﺑﺎﻳﺖ ﻫﺎﻳﻲ ﮐﻪ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩ ﺳﺎﺯﻱ ﻳﮏ ﺷﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ sizeof
;static int n ﮐﻼﺱ ﺫﺧﻴﺮﻩ ﺳﺎﺯﻱ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﺩﺭ ﻃﻮﻝ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﻭﺟﻮﺩ ﺩﺍﺭﻧﺪ static
pp = static_cast<T*>p ﺑﺮﺍﻱ ﺍﺷﺎﺭﻩ ﮔﺮ ﺩﺍﺩﻩ ﺷﺪﻩ ﻳﮏ ﺍﺷﺎﺭﻩ ﮔﺮ * Tﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ static_cast
;bool flag = true ﻳﮑﻲ ﺍﺯ ﻣﻘﺎﺩﻳﺮ ﻣﻤﮑﻦ ﺑﺮﺍﻱ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻧﻮﻉ bool true
} … { try ﺑﻠﻮﮐﻲ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﺷﺎﻣﻞ ﻣﺪﻳﺮﻳﺖ ﮐﻨﻨﺪﻩ ﺍﺳﺘﺜﻨﺎ ﺍﺳﺖ try
;typedef int Num ﺑﺮﺍﻱ ﻳﮏ ﻧﻮﻉ ﻣﻮﺟﻮﺩ ،ﻣﺘﺮﺍﺩﻓﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲ ﮐﻨﺪ typedef
;)(cout << typeid(x).name ﺷﻴﺌﻲ ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ ﮐﻪ ﻧﻮﻉ ﻳﮏ ﻋﺒﺎﺭﺕ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲ ﺩﻫﺪ typeid
;using namespace std ﺩﺳﺘﻮﺭﻱ ﮐﻪ ﺍﺟﺎﺯﻩ ﻣﻲ ﺩﻫﺪ ﺗﺎ ﭘﻴﺸﻮﻧﺪ ﻭ ﻓﻀﺎﻱ ﻧﺎﻡ ﺣﺬﻑ ﺷﻮﺩ using
;} … { union z ﺳﺎﺧﺘﺎﺭﻱ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﺍﺟﺰﺍﻱ ﺁﻥ ﺍﺯ ﺣﺎﻓﻈﻪ ﻣﺸﺘﺮﮎ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﮐﻨﻨﺪ union
ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ
;unsigned int b ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﺍﻧﻮﺍﻉ ﺻﺤﻴﺢ ﺑﺪﻭﻥ ﻋﻼﻣﺖ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﺷﻮﺩ unsigned
;)(virtual int f ﺗﺎﺑﻊ ﻋﻀﻮﻱ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﺩﺭ ﻳﮏ ﺯﻳﺮ ﮐﻼﺱ ﻧﻴﺰ ﺗﻌﺮﻳﻒ ﺷﺪﻩ virtual
400
401
;int volatile n ﺍﺷﻴﺎﻳﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﻣﻲ ﺗﻮﺍﻧﻨﺪ ﺧﺎﺭﺝ ﺍﺯ ﮐﻨﺘﺮﻝ ﺑﺮﻧﺎﻣﻪ ﺗﻐﻴﻴﺮ ﺩﺍﺩﻩ ﺷﻮﻧﺪ volatile
;b0 = b1 xor b2 ﻣﻌﺎﺩﻟﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ORﺍﻧﺤﺼﺎﺭﻱ ﺑﻴﺘﻲ ^ : xor
/ﮐﻠﻤﺎت ﮐﻠﻴﺪی C++
;b1 xor_eq b2 ﻣﻌﺎﺩﻟﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﺗﺨﺼﻴﺼﻲ ORﺍﻧﺤﺼﺎﺭﻱ ﺑﻴﺘﻲ ^= : xor_eq
ﺿﻤﻴﻢۀ ج
ﺿﻤﻴﻤﻪ » ﺩ «
ﻋﻤﻠﮕﺮﻫﺎﻱ C++ﺍﺳﺘﺎﻧﺪﺍﺭﺩ
ﺩﺭ ﺍﻳﻦ ﺟﺪﻭﻝ ﻫﻢۀ ﻋﻤﻠﮕﺮﻫﺎﻱ C++ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺣﻖ ﺗﻘﺪﻡ ﺁﻥﻫﺎ ﻓﻬﺮﺳﺖ ﺷﺪﻩ ﺍﺳﺖ .ﻋﻤﻠﮕﺮﻫﺎﻱ
ﺑﺎ ﺳﻄﺢ ﺗﻘﺪﻡ ﺑﺎﻻﺗﺮ ﻗﺒﻞ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺑﺎ ﺳﻄﺢ ﺗﻘﺪﻡ ﭘﺎﻳﻴﻦﺗﺮ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﻧﺪ .ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺩﺭ ﻋﺒﺎﺭﺕ
) (a-b*cﻋﻤﻠﮕﺮ * ﺍﺑﺘﺪﺍ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﻋﻤﻠﮕﺮ ﺩﻭﻡ ﻳﻌﻨﻲ – ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﮔﺮﺩﺩ ﺯﻳﺮﺍ * ﺩﺭ
ﺗﻘﺪﻡ ﺳﻄﺢ 13ﺍﺳﺖ ﮐﻪ ﺑﺎﻻﺗﺮ ﺍﺯ ﺳﻄﺢ ﺗﻘﺪﻡ – ﮐﻪ 12ﺍﺳﺖ ﻣﻲﺑﺎﺷﺪ.
ﺳﺘﻮﻧﻲ ﮐﻪ ﺑﺎ »ﺟﻤﻌﻴﺖ« ﻣﺸﺨﺺ ﺷﺪﻩ ،ﻣﻲﮔﻮﻳﺪ ﮐﻪ ﺁﻥ ﻋﻤﻠﮕﺮ ﺑﺮ ﺭﻭﻱ ﭼﻨﺪ ﻋﻤﻠﮕﺮ ﻋﻤﻞ ﻣﻲﮐﻨﺪ.
ﺳﺘﻮﻧﻲ ﮐﻪ ﺑﺎ »ﺳﺮﺑﺎﺭ« ﻣﺸﺨﺺ ﺷﺪﻩ ،ﻣﻲﮔﻮﻳﺪ ﮐﻪ ﺁﻳﺎ ﻋﻤﻠﮕﺮ ﻗﺎﺑﻞ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻫﺴﺖ ﻳﺎ ﺧﻴﺮ.
)ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺭﺍ ﺩﺭ ﻓﺼﻞ ﺩﻫﻢ ﻣﻄﺎﻟﻌﻪ ﮐﻨﻴﺪ(.
[Cline]
C++ FAQs, Second Edition, by Marshall Cline, Greg Lomow, and Mike Girou.
Addison-Wesley Publishing Company, Reading, MA (1999) 0-201-30983-1
[Deitel]
C++ How to Program, Second Edition by H. M. Deitel and P. J. Deitel.
Prentice Hall, Englewood Cliffs, NJ (1998) 0-13-528910-6.
[Hubbard1]
Foundamentals of Computing with C++, by John R. Hubbard.
McGraw-Hill, Inc, New York, NY (1998) 0-07-030868-3.
[Hubbard2]
Data Structures with C++, by John R. Hubbard.
McGraw-Hill, Inc, New York, NY (1999) 0-07-135345-3.
[Hubbard3]
Programming with C++, Second Edition, by John R. Hubbard.
McGraw-Hill, Inc, New York, NY (2000) 0-07-118372-8.
[Hughes]
Mastering the Standard C++ Classes, by Cameron Hughes and Tracey Hughes.
John Wiley & Sons, Inc, New York, NY (1999) 0-471-32893-6.
[Johnsonbaugh]
Object_Oriented Programming in C++, by Richard Johnsonbaugh and Martin Kalin.
Prentice Hall, Englewood Cliffs, NJ (1995) 0-02-360682-7.
[Perry]
An Introduction to Object-Oriented Design in C++, by Jo Ellen Perry and Harold D. Levin.
Addison-Wesley Publishing Company, Reading, MA (1996) 0-201-76564-0.
[Savitch]
Problem Solving with C++, by Walter Savitch.
Addison-Wesley Publishing Company, Reading, MA (1996) 0-8053-7440-X.
[Stroustrup1]
The C++ Programming Languages, special Edition, by Bjarne Stroustrup.
Addison-Wesley Publishing Company, Reading, MA (2000) 0-201-70073-5.
[Stroustrup2]
The Design and Evolution of C++, by Bjarne Stroustrup.
Addison-Wesley Publishing Company, Reading, MA (1994) 0-201-54330-3.
[Weiss]
Data Structures and Algorithm Analysis in C++, by Mark Allen Weiss.
Benjamin/Cummings Publishing Company, Redwood City, CA (1994) 0-8053-5443-3.
ﻓﻬﺮﺳﺖ ﻣﻄﺎﻟﺐ
ﻓﺼﻞ ﻳﺎﺯﺩﻫﻢ
»ﺗﺮﻛﻴﺐ ﻭ ﻭﺭﺍﺛﺖ«
357 12‐1ﻣﻘﺪﻣﻪ
357 12‐2ﺗﺮﻛﻴﺐ
361 11‐3ﻭﺭﺍﺛﺖ
364 11‐4ﺍﻋﻀﺎﻱ ﺣﻔﺎﻇﺖ ﺷﺪﻩ
367 11‐5ﻏﻠﺒﻪ ﮐﺮﺩﻥ ﺑﺮ ﻭﺭﺍﺛﺖ
371 11‐6ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺩﺭ ﻭﺭﺍﺛﺖ
373 11‐7ﺗﻮﺍﺑﻊ ﻣﺠﺎﺯﻱ ﻭ ﭼﻨﺪﺭﻳﺨﺘﻲ
377 11‐8ﻧﺎﺑﻮﺩﻛﻨﻨﺪۀ ﻣﺠﺎﺯﻱ
379 11‐9ﻛﻼﺱﻫﺎﻱ ﭘﺎﻱۀ ﺍﻧﺘﺰﺍﻋﻲ
382 ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ
385 ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ
386 ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ
ﺿﻤﻴﻤﻪ ﺍﻟﻒ :ﭘﺎﺳﺦﻧﺎﻡ ۀ ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ 383