0% found this document useful (0 votes)
555 views

C

This document is an introduction to an advanced programming textbook for computer science students at Payame Noor University in Iran. It discusses the university's history of modernizing and adapting to change. It emphasizes the need for high-quality educational resources, particularly for distance learning students, and how technology can help enrich course materials. The introduction explains that this textbook was created for the advanced programming course to address this need.

Uploaded by

mirza_farid
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
555 views

C

This document is an introduction to an advanced programming textbook for computer science students at Payame Noor University in Iran. It discusses the university's history of modernizing and adapting to change. It emphasizes the need for high-quality educational resources, particularly for distance learning students, and how technology can help enrich course materials. The introduction explains that this textbook was created for the advanced programming course to address this need.

Uploaded by

mirza_farid
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 415

‫ﺑﺮﻧﺎﻣﻪ ﺳﺎﺯﻱ ﭘﻴﺸﺮﻓﺘﻪ‬

‫ﺩﺍﻧﺸﮕﺎﻩ ﭘﻴﺎﻡ ﻧﻮﺭ‬

‫»ﺑﺮﻧﺎﻣﻪﺳﺎﺯﻱ ﭘﻴﺸﺮﻓﺘﻪ«‬

‫ﻣﻨﺒﻊ ﺩﺭﺳﻲ ﺭﺷﺘﻪ ﮐﺎﻣﭙﻴﻮﺗﺮ‬

‫ﺗﺎﻟﻴﻒ ﻭ ﺗﺪﻭﻳﻦ‪ :‬ﺩﮐﺘﺮ ﺍﺣﻤﺪ ﻓﺮﺍﻫﻲ‬


‫ﻣﻘﺪﻣﻪ‬
‫ﺩﺍﻧﺸﮕﺎﻩ ﺁﻥ ﺯﻣﺎﻥ ﺗﻮﺍﻧﺴﺖ ﺷﺎﻧﻪﻫﺎﻱ ﺧﻮﺩ ﺭﺍ ﺍﺯ ﺳﻨﮕﻴﻨﻲ ﺍﺳﺘﻌﻼﻱ ﻏﺮﺑﻲ ﺳﺒﮏ ﺳﺎﺯﺩ ﻭ ﺭﺍﻩ‬
‫ﺑﻪ ﺳﻮﻱ ﺩﺍﻣﻨﻪﻫﺎﻱ ﻣﻮﻓﻘﻴﺖ ﺑﮕﺸﺎﻳﺪ ﮐﻪ ﻣﺪﺩ ﻧﻴﺮﻭﻫﺎﻱ ﺟﻮﺍﻥ ﻭ ﻋﻤﻞﮔﺮﺍﻱ ﺧﻮﺩ ﺭﺍ ﭘﺬﻳﺮﻓﺖ ﻭ ﺑﺎ‬
‫ﺗﮑﻴﻪ ﺑﺮ ﺍﻧﺪﻳﺶ ۀ ﺩﺍﻧﺸﻤﻨﺪﺍﻥ ﻭ ﻓﺮﻫﻴﺨﺘﮕﺎﻥ ﺩﻟﺴﻮﺯ‪ ،‬ﺭﻭ ﺑﻪ ﺟﻠﻮ ﺣﺮﮐﺖ ﮐﺮﺩ‪ ،‬ﭼﻪ ﺣﺮﮐﺖ ﻧﺘﻴﺞۀ‬
‫ﺑﺎﺯﺍﻧﺪﻳﺸﻲ ﻭ ﺧﻮﺍﺳﺖ ﺗﻐﻴﻴﺮ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺧﻮﺍﺳﺖ ﻣﻬﻢ ﺍﺳﺖ ﻧﻪ ﻓﻘﻂ ﺑﻪ ﺧﺎﻃﺮ ﺁﻥ ﮐﻪ ﺟﻨﺒﺸﻲ ﺍﺯ‬
‫ﺩﺭﻭﻥ ﻭ ﺑﺮﺍﻱ ﺑﻴﺮﻭﻥﺭﻓﺖ ﺍﺯ ﺷﺮﺍﻳﻂ ﺣﮑﻮﻣﺖ ﻏﺮﺏ ﺑﺮ ﺩﺍﻧﺸﮕﺎﻩ ﺑﻮﺩ ﺑﻠﮑﻪ ﺑﻪ ﺁﻥ ﺟﻬﺖ ﮐﻪ ﺩﺍﻧﺸﮕﺎﻩ‬
‫ﻧﻪ ﺩﺭ ﺩﻭﺭﺍﻥ ﺟﻨﮓ ﺗﺤﻤﻴﻠﻲ ﻭ ﻧﻪ ﭘﺲ ﺍﺯ ﺁﻥ ﺩﺭ ﻻﺑﻪﻻﻱ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺳﺎﺯﻧﺪﮔﻲ ﻭ ﺗﺐ ﻭ ﺗﺎﺏ‬
‫ﻧﻮﭘﺎﻳﻲ ﺳﻴﺎﺳﻲ ﺍﺯ ﺯﻣﺎﻥ ﺧﻮﺩ ﻋﻘﺐ ﻧﻤﺎﻧﺪ‪ .‬ﺯﻣﺎﻧﻲ ﮐﻪ ﻋﺰﻡ ﺑﺮ ﺟﺒﺮﺍﻥ ﻭ ﺗﮑﺎﭘﻮ ﺑﺎﺷﺪ‪ ،‬ﺳﺴﺘﻲ ﻭ‬
‫ﮐﺎﺳﺘﻲ ﺑﻪ ﺑﺎﻟﻨﺪﮔﻲ ﻭ ﻏﺮﻭﺭ ﻣﻲﺍﻧﺠﺎﻣﺪ ﻭ ﺷﺮﺍﻳﻂ ﻧﺎﻣﺘﻌﺎﺩﻝ ﺍﺟﺘﻤﺎﻋﻲ ﺑﻪ ﻧﻈﺎﻡﻫﺎﻱ ﻋﻠﻤﻲ ﻭ ﻓﺮﻫﻨﮕﻲ‪.‬‬
‫ﺑﻪ ﺳﺎﺩﮔﻲ ﻧﻤﻲﺗﻮﺍﻥ ﺍﻓﻖ ﺩﺍﻧﺶﻫﺎﻳﻲ ﭼﻮﻥ ﺍﻧﺮﮊﻱ ﺍﺗﻤﻲ ﻭ ﻧﺎﻧﻮﺗﮑﻨﻮﻟﻮﮊﻱ ﺭﺍ ﺩﺭﻧﻮﺭﺩﻳﺪ؛ ﺗﻼﺵ‬
‫ﻣﻀﺎﻋﻒ ﻣﻲﻃﻠﺒﺪ ﻭ ﻫﻤﮕﺎﻧﻲ‪ .‬ﻫﻤﺎﻥ ﮔﻮﻧﻪ ﮐﻪ ﺭﺍﻫﺒﺮ ﻓﺮﺯﺍﻧﻪ ﮔﻔﺖ‪:‬‬
‫»ﺍﮔﺮ ﻫﻤﻪ ﺗﻼﺵ ﮐﻨﻨﺪ ﻗﻠﻪﻫﺎﻱ ﻋﻠﻮﻡ ﻭ ﻓﻨﻮﻥ ﺑﻪ ﺩﺳﺖ ﺍﻳﺮﺍﻧﻴﺎﻥ ﻓﺘﺢ ﺧﻮﺍﻫﺪ ﺷﺪ«‬
‫ﺍﮐﻨﻮﻥ ﻧﻬﻀﺖ ﺩﻳﮕﺮﻱ ﺑﻪ ﺟﻮﺷﺶ ﺩﺭﺁﻣﺪﻩ ﺍﺳﺖ ﻭ ﻣﺴﻴﺮ ﺟﺮﻳﺎﻧﺶ ﺭﺍ ﻣﻲﺟﻮﻳﺪ‪ .‬ﻧﻬﻀﺘﻲ ﺑﺮ‬
‫ﺁﻣﺪﻩ ﺍﺯ ﺩﺭﺩ ‪» ...‬ﺟﻨﺒﺶ ﻧﺮﻡﺍﻓﺰﺍﺭﻱ ﻭ ﻧﻬﻀﺖ ﺗﻮﻟﻴﺪ ﻋﻠﻢ«‪ .‬ﻣﻨﺎﺑﻊ ﻋﻠﻤﻲ ﻏﻨﻲ ﻭ ﺩﺭ ﺧﻮﺭ‪ ،‬ﺍﺯ‬
‫ﻣﻬﻢﺗﺮﻳﻦ ﻣﻠﺰﻭﻣﺎﺗﻲ ﺍﺳﺖ ﮐﻪ ﭘﻴﺸﺮﻭﻱ ﻋﻠﻤﻲ ﺭﺍ ﻫﻤﻮﺍﺭ ﻣﻲﺳﺎﺯﺩ‪ ،‬ﺧﺎﺻﻪ ﺍﻳﻦ ﮐﻪ ﺩﺍﻧﺸﺠﻮﻳﺎﻥ‬
‫ﺩﺍﻧﺸﮕﺎﻩ ﭘﻴﺎﻡ ﻧﻮﺭ ﺑﻪ ﺟﺒﺮ ﻧﻈﺎﻡ ﺁﻣﻮﺯﺵ ﺍﺯ ﺩﻭﺭ ﺍﺯ ﭘﺮﺗﻮ »ﺍﺳﺘﺎﺩ« ﮐﻢﺗﺮ ﺑﻬﺮﻩ ﻣﻲﺑﺮﻧﺪ‪ .‬ﻻﺯﻡ ﺍﺳﺖ ﺑﺮﺍﻱ‬
‫ﻏﻨﻲﺳﺎﺯﻱ ﻣﻨﺎﺑﻊ ﺩﺭﺳﻲ‪ ،‬ﻓﻦﺁﻭﺭﻱ ﺁﻣﻮﺯﺷﻲ ﺑﻪ ﺑﻬﺘﺮﻳﻦ ﺷﮑﻞ ﺑﻪ ﺧﺪﻣﺖ ﮔﺮﻓﺘﻪ ﺷﻮﺩ ﺗﺎ ﺩﺍﻧﺸﺠﻮﻳﺎﻥ‬
‫ﺩﺭ ﺳﺎﻱۀ ﺗﻼﺵ ﻣﻀﺎﻋﻒ‪ ،‬ﺑﺎ ﺍﻃﻤﻴﻨﺎﻥ ﻭ ﺁﺳﺎﻳﺶ ﺑﻴﺸﺘﺮﻱ ﺩﺭ ﻭﺍﺩﻱ ﻋﻠﻢ ﺭﻩ ﺳﭙﺎﺭﻧﺪ‪ .‬ﮐﺘﺎﺏ ﺣﺎﺿﺮ‬
‫ﺩﺭ ﻫﻤﻴﻦ ﺭﺍﺳﺘﺎ‪ ،‬ﻣﻨﺒﻊ ﺩﺭﺳﻲ ﻭﺍﺣﺪ »ﺑﺮﻧﺎﻣﻪﺳﺎﺯﻱ ﭘﻴﺸﺮﻓﺘﻪ« ﺑﺮﺍﻱ ﺭﺷﺖۀ ﮐﺎﻣﭙﻴﻮﺗﺮ ﻭﺿﻊ ﺷﺪﻩ‪.‬‬
‫ﮐﻮﺷﻴﺪﻩﺍﻳﻢ ﻣﺤﮏ »ﻣﺼﻮﺏۀ ﺷﻮﺭﺍﻱ ﻋﺎﻟﻲ ﺍﻧﻘﻼﺏ ﻓﺮﻫﻨﮕﻲ« ﺭﺍ ﺑﻪ ﺩﺳﺖ ﮔﻴﺮﻳﻢ ﻭ ﺑﺎ ﻧﻴﻢﻧﮕﺎﻫﻲ ﺑﻪ‬
‫ﻣﻨﺎﺑﻊ ﺩﺭﺳﻲ ﺩﺍﻧﺸﮕﺎﻩﻫﺎﻱ ﻣﻌﺘﺒﺮ ﺟﻬﺎﻥ ﻭ ﺑﺎ ﺍﺗﮑﺎ ﺑﻪ ﻣﺤﺎﺳﻦ ﻭ ﻧﻮﺍﻗﺺ ﻣﻨﺒﻊ ﻗﺒﻠﻲ‪ ،‬ﻃﺮﺣﻲ ﻧﻮ ﺩﺭ‬
‫ﺍﻧﺪﺍﺯﻳﻢ‪ .‬ﺷﻴﻮۀ ﻧﮕﺎﺭﺵ ﺑﻪ ﮔﻮﻧﻪﺍﻱ ﺍﺳﺖ ﮐﻪ ﺩﺍﻧﺸﺠﻮ ﺧﻮﺩ ﺭﺍ ﺩﺭ ﮐﻼﺱ ﻭ ﺩﺭ ﻧﺰﺩ ﺍﺳﺘﺎﺩ ﺣﺎﺿﺮ‬
‫ﻣﻲﺑﻴﻨﺪ‪ .‬ﺍﻧﺘﺨﺎﺏ ﻣﺜﺎﻝﻫﺎ ﺑﻪ ﺷﮑﻠﻲ ﺍﺳﺖ ﮐﻪ ﻫﻢ ﮐﻮﺗﺎﻩ ﻭ ﻣﻮﺟﺰ ﺑﺎﺷﻨﺪ ﻭ ﻫﻢ ﺩﺭ ﻫﺮ ﮐﺪﺍﻡ ﻧﮑﺎﺕ ﺭﻳﺰ‬
‫ﻭ ﺩﺭﺷﺖ ﺁﻣﻮﺯﺷﻲ ﻟﺤﺎﻅ ﺷﺪﻩ ﺑﺎﺷﺪ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺟﻠﻮﻩﻫﺎﻱ ﺑﺼﺮﻱ ﻣﺘﻦ‪ ،‬ﺧﻮﺍﻧﻨﺪﻩ ﺭﺍ ﻳﺎﺭﻱ ﻣﻲﺩﻫﺪ ﺗﺎ‬
‫ﺗﻤﺮﮐﺰ ﺧﻮﻳﺶ ﺭﺍ ﺭﻭﻱ ﻣﻮﺿﻮﻉ ﻣﻮﺭﺩ ﻣﻄﺎﻟﻌﻪ ﺍﺯ ﺩﺳﺖ ﻧﺪﻫﺪ‪.‬‬
‫ﺍﻳﻦ ﮐﺘﺎﺏ ﻧﻪ ﻓﻘﻂ ﺯﺑﺎﻥ ‪ C++‬ﺭﺍ‪ ،‬ﺑﻠﮑﻪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺭﺍ ﺁﻣﻮﺯﺵ ﻣﻲﺩﻫﺪ‪ ،‬ﺑﻪ ﻫﺮ ﺯﺑﺎﻥ ﮐﻪ‬
‫ﺑﺎﺷﺪ‪ .‬ﺑﻪ ﻧﻈﺮﺍﺕ ﻭ ﭘﻴﺸﻨﻬﺎﺩﺍﺕ ﺍﺳﺎﺗﻴﺪ ﻭ ﺩﺍﻧﺸﺠﻮﻳﺎﻥ ﺻﺎﺩﻗﺎﻧﻪ ﺍﺭﺝ ﻣﻲﻧﻬﻴﻢ ﻭ ﺩﺳﺖﺑﻮﺱ ﺍﻧﺘﻘﺎﺩﻫﺎ ﻭ‬
‫ﺑﻴﺎﻥ ﮐﺎﺳﺘﻲﻫﺎ ﻫﺴﺘﻴﻢ‪.‬‬
‫ﻫﺰﺍﺭﺍﻥ ﺳﭙﺎﺱ ﺍﻟﻄﺎﻑ ﺍﻟﻬﻲ ﺭﺍ ﮐﻪ ﺩﺭ ﺗﺪﺍﺭﮎ ﺍﻳﻦ ﻣﺠﻤﻮﻋﻪ ﺗﻮﻓﻴﻖﻣﺎﻥ ﺩﺍﺩ‪.‬‬
‫ﺭﺍﻫﻨﻤﺎﻱ ﻣﻄﺎﻟﻊۀ ﮐﺘﺎﺏ‬
‫‐ ﺍﺯ ﺣﺠﻢ ﺯﻳﺎﺩ ﮐﺘﺎﺏ ﻧﻬﺮﺍﺳﻴﺪ‪ .‬ﺑﻴﺸﺘﺮ ﺣﺠﻢ ﮐﺘﺎﺏ ﻣﺮﺑﻮﻁ ﺑﻪ ﺷﺮﺡ ﺑﺮﻧﺎﻣﻪﻫﺎ ﻭ ﻣﺜﺎﻝﻫﺎﻱ‬
‫ﮔﻮﻧﺎﮔﻮﻥ ﺍﺳﺖ ﮐﻪ ﺷﻤﺎ ﺭﺍ ﺩﺭ ﻳﺎﺩﮔﻴﺮﻱ ﻣﻄﺎﻟﺐ ﻳﺎﺭﻱ ﻣﻲﮐﻨﻨﺪ‪.‬‬
‫‐ ﻓﺼﻮﻝ ﮐﺘﺎﺏ ﮐﺎﻣﻼ ﺑﺎ ﻳﮑﺪﻳﮕﺮ ﻣﺮﺗﺒﻂﺍﻧﺪ ﻭ ﺍﺯ ﻣﻄﺎﻟﺐ ﺑﺨﺶﻫﺎﻱ ﻗﺒﻠﻲ ﺑﻪ ﻭﻓﻮﺭ ﺩﺭ‬
‫ﺑﺨﺶﻫﺎﻱ ﺑﻌﺪﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﭘﺲ ﺳﻌﻲ ﮐﻨﻴﺪ ﺩﺭﺱ ﺑﻪ ﺩﺭﺱ ﻭ ﻫﻤﺮﺍﻩ ﺑﺎ ﮐﺘﺎﺏ‬
‫ﭘﻴﺶ ﺑﺮﻭﻳﺪ‪.‬‬
‫‐ ﺍﮔﺮ ﺍﺯ ﻗﺒﻞ ﺑﺎ ﺯﺑﺎﻥ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺩﻳﮕﺮﻱ)ﻣﺎﻧﻨﺪ ﭘﺎﺳﮑﺎﻝ( ﺁﺷﻨﺎﻳﻲ ﻭ ﻣﻬﺎﺭﺕ ﻣﺨﺘﺼﺮ ﺩﺍﺷﺘﻪ‬
‫ﺑﺎﺷﻴﺪ‪ ،‬ﻓﺼﻞﻫﺎﻱ ﺍﻭﻝ ﺗﺎ ﻫﺸﺘﻢ ﺭﺍ ﺑﻪ ﺳﺮﻋﺖ ﻓﺮﺍ ﺧﻮﺍﻫﻴﺪ ﮔﺮﻓﺖ‪ .‬ﮐﺎﻓﻲ ﺍﺳﺖ ﻳﮏ ﺑﺎﺭ ﺑﻪ‬
‫ﻃﻮﺭ ﻋﻤﻴﻖ ﺍﻳﻦ ﻓﺼﻮﻝ ﺭﺍ ﻣﻄﺎﻟﻌﻪ ﻧﻤﺎﻳﻴﺪ ﻭ ﺳﭙﺲ ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻧﻴﺪ ﺗﻤﺮﻳﻦﻫﺎﻱ ﺁﺧﺮ ﺍﻳﻦ‬
‫ﻓﺼﻮﻝ ﺭﺍ ﺣﻞ ﮐﻨﻴﺪ‪.‬‬
‫‐ ﻓﺼﻞﻫﺎﻱ ﻫﺸﺘﻢ ﺗﺎ ﺁﺧﺮ )ﻣﺨﺼﻮﺻﺎ ﻓﺼﻞ ﻧﻬﻢ ﺗﺎ ﻳﺎﺯﺩﻫﻢ ﮐﻪ ﻣﺒﺎﺣﺚ ﻣﺮﺑﻮﻁ ﺑﻪ‬
‫ﺷﻲﮔﺮﺍﻳﻲ ﺍﺳﺖ( ﺭﺍ ﺑﻴﺸﺘﺮ ﻣﻄﺎﻟﻌﻪ ﮐﻨﻴﺪ ﻭ ﺯﻣﺎﻥ ﺑﻴﺸﺘﺮﻱ ﺑﺮﺍﻱ ﺍﻳﻦ ﻓﺼﻮﻝ ﻣﻨﻈﻮﺭ ﮐﻨﻴﺪ‪.‬‬
‫ﻣﻤﮑﻦ ﺍﺳﺖ ﻣﺠﺒﻮﺭ ﺷﻮﻳﺪ ﺍﻳﻦ ﻓﺼﻮﻝ ﺭﺍ ﺑﻴﺶ ﺍﺯ ﻳﮏ ﺑﺎﺭ ﻣﻄﺎﻟﻌﻪ ﻭ ﻣﺮﻭﺭ ﮐﻨﻴﺪ ﺍﻣﺎ ﺟﺎﻱ‬
‫ﻧﮕﺮﺍﻧﻲ ﻧﻴﺴﺖ‪ .‬ﺍﻳﻦ ﺍﺷﮑﺎﻝ ﻣﺮﺑﻮﻁ ﺑﻪ ﻣﺎﻫﻴﺖ ﺍﻳﻦ ﻓﺼﻞﻫﺎ ﺍﺳﺖ ﮐﻪ ﺗﺎ ﮐﻨﻮﻥ ﺭﺍﺟﻊ ﺑﻪ ﺁﻥﻫﺎ‬
‫ﮐﻤﺘﺮ ﺧﻮﺍﻧﺪﻩ ﻳﺎ ﺷﻨﻴﺪﻩﺍﻳﺪ‪ .‬ﻣﺎﻳﻮﺱ ﻧﺸﻮﻳﺪ ﻭ ﺑﺎ ﺟﺪﻳﺖ ﻣﻄﺎﻟﻌﻪ ﮐﻨﻴﺪ ﻭ ﻳﻘﻴﻦ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ‬
‫ﮐﻪ ﻣﻄﻠﺐ ﭘﻴﭽﻴﺪﻩﺍﻱ ﺩﺭ ﺍﻳﻦ ﻓﺼﻞﻫﺎ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ‪.‬‬
‫‐ ﻫﻨﮕﺎﻡ ﻣﻄﺎﻟﻌﻪ ﺑﻪ ﻧﺤﻮۀ ﺣﺮﻭﻓﭽﻴﻨﻲ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺩﻗﺖ ﮐﻨﻴﺪ‪ .‬ﻣﻄﺎﻟﺒﻲ ﮐﻪ ﺩﺭ ﺣﺎﻝ ﻓﺮﺍﮔﻴﺮﻱ ﺁﻥ‬
‫ﻫﺴﺘﻴﺪ ﺑﺎ ﺣﺮﻭﻑ ﺗﻴﺮﻩﺗﺮ ﺩﺭ ﻫﺮ ﺑﺮﻧﺎﻣﻪ ﻧﻮﺷﺘﻪ ﺷﺪﻩ ﺗﺎ ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻨﻈﻮﺭ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺩﺭﮎ‬
‫ﻧﻤﺎﻳﻴﺪ ﻭ ﻧﮑﺎﺕ ﺁﻥ ﺭﺍ ﻓﺮﺍ ﺑﮕﻴﺮﻳﺪ‪ .‬ﺑﻌﺪ ﺍﺯ ﻫﺮ ﺑﺮﻧﺎﻣﻪ ﺷﺮﺡ ﻧﺤﻮۀ ﮐﺎﺭ ﮐﺮﺩﻥ ﺁﻥ ﻧﻴﺰ ﺁﻣﺪﻩ‬
‫ﺍﺳﺖ ﺗﺎ ﺍﺑﻬﺎﻣﺎﺕ ﺍﺣﺘﻤﺎﻟﻲ ﺭﺍ ﺍﺯ ﺑﻴﻦ ﺑﺒﺮﺩ‪.‬‬
‫‐ ﻫﺮ ﭼﻨﺪ ﺧﺮﻭﺟﻲ ﻫﺮ ﺑﺮﻧﺎﻣﻪ ﺩﺭ ﭼﻬﺎﺭﮔﻮﺵ ﺗﻴﺮﻩ ﺭﻧﮓ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﻣﺎ ﺳﻌﻲ ﮐﻨﻴﺪ‬
‫ﺧﻮﺩﺗﺎﻥ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺭﺍ ﺭﻭﻱ ﺭﺍﻳﺎﻧﻪ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﮐﻨﻴﺪ ﺗﺎ ﺍﺯ ﻣﻄﺎﻟﻊۀ ﺍﻳﻦ ﺩﺭﺱ ﻟﺬﺕ ﺑﻴﺸﺘﺮﻱ‬
‫ﺑﺒﺮﻳﺪ‪ .‬ﺩﺭ ﺍﻳﻦ ﺭﻫﮕﺬﺍﺭ ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﻪ ﻣﻄﺎﻟﺐ ﺁﻣﻮﺯﺷﻲ ﺟﺎﻟﺒﻲ ﺑﺮﺧﻮﺭﺩ ﮐﻨﻴﺪ ﮐﻪ ﺩﺭ ﮐﺘﺎﺏ‬
‫ﻧﻴﺎﻣﺪﻩ ﺍﺳﺖ‪.‬‬
‫‐ ﺍﻧﺪﺍﺯۀ ﺑﺮﻧﺎﻣﻪﻫﺎ ﻣﺘﻨﺎﺳﺐ ﺑﺎ ﻓﺼﻮﻝ ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻓﺼﻞﻫﺎﻱ ﺁﻏﺎﺯﻳﻦ ﮐﻮﺗﺎﻩﺗﺮ‬
‫ﻭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻓﺼﻞﻫﺎﻱ ﭘﺎﻳﺎﻧﻲ ﻃﻮﻻﻧﻲﺗﺮﻧﺪ‪ .‬ﺍﮔﺮ ﺩﺭ ﻓﻬﻢ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻃﻮﻻﻧﻲ ﺑﺎ ﻣﺸﮑﻞ‬
‫ﻣﻮﺍﺟﻪ ﺷﺪﻳﺪ ﺍﺣﺘﻤﺎﻻ ﻓﺼﻞﻫﺎﻱ ﺁﻏﺎﺯﻳﻦ ﮐﺘﺎﺏ ﺭﺍ ﺑﻪ ﺧﻮﺑﻲ ﻓﺮﺍ ﻧﮕﺮﻓﺘﻪﺍﻳﺪ‪.‬‬
‫‐ ﮐﻮﺷﺶ ﮐﻨﻴﺪ ﺗﺎ ﻫﻢۀ ﺗﻤﺮﻳﻦﻫﺎ ﻭ ﭘﺮﺳﺶﻫﺎ ﺭﺍ ﺣﻞ ﮐﻨﻴﺪ‪ .‬ﺩﺭ ﺗﻤﺮﻳﻦﻫﺎ ﻭ ﻣﺴﺎﻳﻞ ﮐﺘﺎﺏ‪،‬‬
‫ﮔﻨﺞﻫﺎﻳﻲ ﻧﻬﻔﺘﻪ ﺍﺳﺖ ﮐﻪ ﻓﻘﻂ ﺩﺍﻧﺸﺠﻮﻳﺎﻥ ﺳﺨﺖﮐﻮﺵ ﺑﻪ ﺁﻥﻫﺎ ﺩﺳﺖ ﻣﻲﻳﺎﺑﻨﺪ‪.‬‬
‫‐ ﺿﻤﻴﻤﻪﻫﺎﻱ ﮐﺘﺎﺏ ﺑﻪ ﻫﻴﭻ ﻋﻨﻮﺍﻥ ﺟﻨﺐۀ ﺍﻣﺘﺤﺎﻧﻲ ﻧﺪﺍﺭﻧﺪ ﻭ ﻓﻘﻂ ﺑﺮﺍﻱ ﻣﻄﺎﻟﻊۀ ﺑﻴﺸﺘﺮ ﺫﮐﺮ‬
‫ﺷﺪﻩﺍﻧﺪ‪ .‬ﺩﺍﻧﺸﺠﻮﻳﺎﻥ ﻋﻼﻗﻤﻨﺪ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﺎ ﻣﻄﺎﻟﻊۀ ﺿﻤﻴﻤﻪﻫﺎ ﺩﺍﻧﺶ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺑﺎﻻﺗﺮﻱ‬
‫ﮐﺴﺐ ﮐﻨﻨﺪ‪.‬‬
‫‐ ﺑﻬﺘﺮ ﺍﺳﺖ ﺑﻴﻦ ﻳﮏ ﺗﺎ ﺩﻭ ﺳﺎﻋﺖ ﺑﻪ ﻃﻮﺭ ﭘﻴﻮﺳﺘﻪ ﻣﻄﺎﻟﻌﻪ ﮐﻨﻴﺪ ﺗﺎ ﺑﻬﺘﺮ ﻳﺎﺩ ﺑﮕﻴﺮﻳﺪ ﻭ ﮐﻤﺘﺮ‬
‫ﻣﺠﺒﻮﺭ ﺷﻮﻳﺪ ﺑﻪ ﻣﻄﺎﻟﺒﻲ ﮐﻪ ﺩﻓﻊۀ ﻗﺒﻞ ﻣﻄﺎﻟﻌﻪ ﮐﺮﺩﻩﺍﻳﺪ‪ ،‬ﺑﺎﺯﮔﺮﺩﻳﺪ‪ .‬ﺳﻌﻲ ﮐﻨﻴﺪ ﺩﺭ ﺁﺭﺍﻣﺶ ﺑﻪ‬
‫ﻣﻄﺎﻟﻌﻪ ﺑﭙﺮﺩﺍﺯﻳﺪ ﻭ ﻋﻮﺍﻣﻠﻲ ﮐﻪ ﺗﻤﺮﮐﺰﺗﺎﻥ ﺭﺍ ﻣﻲﮐﺎﻫﻨﺪ ﺑﻪ ﺣﺪﺍﻗﻞ ﺑﺮﺳﺎﻧﻴﺪ‪ .‬ﺑﻪ ﺍﻧﺪﺍﺯۀ ﮐﺎﻓﻲ‬
‫ﺍﺳﺘﺮﺍﺣﺖ ﮐﻨﻴﺪ ﺗﺎ ﺧﺴﺘﮕﻲ ﺍﺛﺮ ﺳﻮﻳﻲ ﺭﻭﻱ ﺍﻧﺪﻭﺧﺘﻪﻫﺎﻳﺘﺎﻥ ﻧﮕﺬﺍﺭﺩ‪.‬‬
‫‐ ﻳﺎﺩ ﺧﺪﺍ ﻭ ﺫﮐﺮ ﺍﻟﻄﺎﻑ ﺍﻭ ﻭ ﺍﻣﻴﺪ ﺑﻪ ﺭﺣﻤﺘﺶ ﺁﺭﺍﻣﺶﺑﺨﺶ ﺭﻭﺡ ﻭ ﺭﻭﺍﻥ ﺍﺳﺖ‪ .‬ﺑﻪ ﺍﻭ‬
‫ﺗﻮﮐﻞ ﮐﻨﻴﺪ ﻭ ﺍﻣﻮﺭ ﺧﻮﻳﺶ ﺭﺍ ﺑﻪ ﺍﻭ ﺑﺴﭙﺎﺭﻳﺪ ﻭ ﺍﺯ ﺍﻭ ﻣﺪﺩ ﺑﺨﻮﺍﻫﻴﺪ ﮐﻪ ﺻﺎﺣﺐ ﻫﻤﻪ ﻋﻠﻮﻡ‪،‬‬
‫ﻓﻘﻂ ﺍﻭﺳﺖ‪.‬‬
‫ﻓﺼﻞ ﺍﻭﻝ‬
‫» ﻣﻘﺪﻣﺎﺕ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺑﺎ ‪« C++‬‬

‫‪1 ‐ 1‬ﭼﺮﺍ ‪ C++‬؟‬


‫ﺍﺯ ﺯﻣﺎﻧﻲ ﮐﻪ ﺍﻭﻟﻴﻦ ﺯﺑﺎﻥ ﺍﺯ ﺧﺎﻧﻮﺍﺩۀ ‪ C‬ﺑﻪ ﺷﮑﻞ ﺭﺳﻤﻲ ﺍﻧﺘﺸﺎﺭ ﻳﺎﻓﺖ‪ ،‬ﻣﺘﺨﺼﺼﻴﻦ‬
‫ﺑﺴﻴﺎﺭﻱ ﺩﺭﺑﺎﺭۀ ﺗﻮﺍﻧﺎﻳﻲﻫﺎ ﻭ ﻗﺎﺑﻠﻴﺖﻫﺎﻱ ﺁﻥ ﻗﻠﻢ ﺯﺩﻩ ﻭ ﺩﺭ ﺍﻳﻦ ﻭﺍﺩﻱ ﻗﺪﻡ ﺯﺩﻩﺍﻧﺪ‪ .‬ﺍﺯ ﻧﻈﺮ‬
‫ﺍﻳﺸﺎﻥ ﺁﻥﭼﻪ ﺑﻴﺸﺘﺮ ﺟﻠﺐ ﻧﻈﺮ ﻣﻲﮐﺮﺩ ﻧﮑﺎﺕ ﺯﻳﺮ ﺑﻮﺩ‪:‬‬
‫‐ ﺯﺑﺎﻥ ‪ C‬ﻳﮏ ﺯﺑﺎﻥ ﻫﻤﻪ ﻣﻨﻈﻮﺭﻩ ﺍﺳﺖ‪ .‬ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎﻱ ﺍﻳﻦ ﺯﺑﺎﻥ ﺑﺴﻴﺎﺭ ﺷﺒﻴﻪ ﻋﺒﺎﺭﺍﺕ‬
‫ﺟﺒﺮﻱ ﺍﺳﺖ ﻭ ﻧﺤﻮ ﺁﻥ ﺷﺒﻴﻪ ﺟﻤﻼﺕ ﺍﻧﮕﻠﻴﺴﻲ‪ .‬ﺍﻳﻦ ﺍﻣﺮ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ‪ C‬ﻳﮏ ﺯﺑﺎﻥ‬
‫ﺳﻄﺢ ﺑﺎﻻ ﺑﺎﺷﺪ ﮐﻪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺩﺭ ﺁﻥ ﺁﺳﺎﻥ ﺍﺳﺖ‪.‬‬
‫‐ ﺩﺭ ﺍﻳﻦ ﺯﺑﺎﻥ ﻋﻤﻠﮕﺮﻫﺎﻳﻲ ﺗﻌﺒﻴﻪ ﺷﺪﻩ ﮐﻪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺳﻄﺢ ﭘﺎﻳﻴﻦ ﻭ ﺑﻪ ﺯﺑﺎﻥ ﻣﺎﺷﻴﻦ ﺭﺍ‬
‫ﻧﻴﺰ ﺍﻣﮑﺎﻥﭘﺬﻳﺮ ﻣﻲﺳﺎﺯﺩ‪ .‬ﺍﻳﻦ ﺧﺎﺻﻴﺖ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﺗﺎ ﺑﺘﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ‪ C‬ﺑﺮﻧﺎﻣﻪﻫﺎﻱ‬
‫ﺳﻴﺴﺘﻤﻲ ﻭ ﺑﺴﻴﺎﺭ ﺳﺮﻳﻊ ﺍﻳﺠﺎﺩ ﮐﻨﻴﻢ‪ .‬ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺧﻼﺀ ﺑﻴﻦ ﺯﺑﺎﻥﻫﺎﻱ ﺳﻄﺢ ﺑﺎﻻ ﻭ ﺯﺑﺎﻥ‬
‫ﻣﺎﺷﻴﻦ ﭘﺮ ﻣﻲﺷﻮﺩ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺑﻪ ‪ C‬ﺯﺑﺎﻥ »ﺳﻄﺢ ﻣﺘﻮﺳﻂ« ﻧﻴﺰ ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ‪.‬‬
‫‐ ﭼﻮﻥ ‪ C‬ﻋﻤﻠﮕﺮﻫﺎﻱ ﻓﺮﺍﻭﺍﻧﻲ ﺩﺍﺭﺩ‪ ،‬ﮐﺪ ﻣﻨﺒﻊ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺩﺭ ﺍﻳﻦ ﺯﺑﺎﻥ ﺑﺴﻴﺎﺭ ﮐﻮﺗﺎﻩ ﺍﺳﺖ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪2‬‬

‫‐ ﺯﺑﺎﻥ ‪ 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‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ‬
‫ﻗﺎﺑﻠﻴﺖﻫﺎﻱ ﺑﺼﺮﻱ ﺑﻪ ﮐﺪ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺩﻫﻨﺪ ﺗﺎ ﮐﺪ ﺧﻮﺍﻧﺎﺗﺮ ﺷﻮﺩ ﻭ ﻧﻮﺷﺘﻦ ﻭ ﺩﻧﺒﺎﻝ ﮐﺮﺩﻥ‬
‫ﺑﺮﻧﺎﻣﻪ ﺁﺳﺎﻥﺗﺮ ﺑﺎﺷﺪ‪ .‬ﺑﻪ ﻋﻨﻮﺍﻥ ﻣﺜﺎﻝ‪ ،‬ﺩﺳﺘﻮﺭﺍﺕ ﺭﺍ ﺑﺎ ﺭﻧﮓ ﺧﺎﺻﻲ ﻣﺘﻤﺎﻳﺰ ﻣﻲﺳﺎﺯﻧﺪ‪،‬‬
‫ﻣﺘﻐﻴﺮﻫﺎ ﺭﺍ ﺑﺎ ﺭﻧﮓ ﺩﻳﮕﺮﻱ ﻣﺸﺨﺺ ﻣﻲﮐﻨﻨﺪ‪ ،‬ﺗﻮﺿﻴﺤﺎﺕ ﺍﺿﺎﻓﻲ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺎﻳﻞ ﻧﺸﺎﻥ‬

‫‪1 – Program‬‬ ‫‪2 - Text editor‬‬ ‫‪3 – Compiler‬‬


‫‪4 - Integrated Development Environment‬‬ ‫‪5 - Linker‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪4‬‬

‫ﻣﻲﺩﻫﻨﺪ ﻭ ﺣﺘﻲ ﺑﺎ ﻧﻮﺷﺘﻪﻫﺎﻱ ﺧﺎﺻﻲ ﺷﻤﺎ ﺭﺍ ﺭﺍﻫﻨﻤﺎﻳﻲ ﻣﻲﮐﻨﻨﺪ ﮐﻪ ﮐﺠﺎﻱ ﺑﺮﻧﺎﻣﻪ ﭼﻪ‬
‫ﭼﻴﺰﻫﺎﻳﻲ ﺑﻨﻮﻳﺴﻴﺪ‪ .‬ﺗﻤﺎﻡ ﺍﻳﻦ ﺍﻣﮑﺎﻧﺎﺕ ﺳﺒﺐ ﺷﺪﻩ ﺗﺎ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺟﺬﺍﺏﺗﺮ ﺍﺯ ﮔﺬﺷﺘﻪ‬
‫ﺑﺎﺷﺪ ﻭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺑﻪ ﻋﻮﺽ ﺍﻳﻦ ﮐﻪ ﻧﮕﺮﺍﻥ ﺳﺮﮔﺮﺩﺍﻧﻲ ﺩﺭ ﮐﺪ ﺑﺮﻧﺎﻣﻪ ﻳﺎ ﺭﻓﻊ ﺧﻄﺎ ﺑﺎﺷﺪ‪،‬‬
‫ﺗﻤﺮﮐﺰ ﺧﻮﻳﺶ ﺭﺍ ﺑﺮ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ ﻭ ﻗﺎﺑﻠﻴﺖﻫﺎﻱ ﺁﻥ ﺍﺳﺘﻮﺍﺭ ﮐﻨﺪ‪.‬‬
‫‪C++‬‬ ‫ﺑﺴﺖۀ ‪ Visual C++‬ﻣﺤﺼﻮﻝ ﺷﺮﮐﺖ ﻣﻴﮑﺮﻭﺳﺎﻓﺖ ﻭ ﺑﺴﺖۀ‬
‫‪ Builder‬ﻣﺤﺼﻮﻝ ﺷﺮﮐﺖ ﺑﻮﺭﻟﻨﺪ ﻧﻤﻮﻧﻪﻫﺎﻱ ﺟﺎﻟﺒﻲ ﺍﺯ ﻣﺤﻴﻂ ﻣﺠﺘﻤﻊ ﺗﻮﻟﻴﺪ ﺑﺮﺍﻱ ﺯﺑﺎﻥ‬
‫‪ C++‬ﺑﻪ ﺷﻤﺎﺭ ﻣﻲﺭﻭﻧﺪ‪ .‬ﺍﻟﺒﺘﻪ ﻫﺮ ﺩﻭﻱ ﺍﻳﻦﻫﺎ ﻣﺨﺼﻮﺹ ﺳﻴﺴﺘﻢﻋﺎﻣﻞ ﻭﻳﻨﺪﻭﺯ ﻫﺴﺘﻨﺪ‪ .‬ﺍﮔﺮ‬
‫ﻣﻲﺧﻮﺍﻫﻴﺪ ﺭﻭﻱ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﺩﻳﮕﺮﻱ ﻣﺜﻞ ‪ Unix‬ﻳﺎ ‪ Linux‬ﺑﺮﻧﺎﻣﻪ ﺑﻨﻮﻳﺴﻴﺪ ﺑﺎﻳﺪ‬
‫ﮐﺎﻣﭙﺎﻳﻠﺮﻱ ﮐﻪ ﻣﺨﺼﻮﺹ ﺍﻳﻦ ﺳﻴﺴﺘﻢﻋﺎﻣﻞﻫﺎ ﺍﺳﺖ ﭘﻴﺪﺍ ﮐﻨﻴﺪ‪.‬‬
‫ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺑﺎ ‪ C++‬ﺭﺍ ﺷﺮﻭﻉ ﮐﻨﻴﻢ ﻳﮏ ﻣﺤﻴﻂ ﻣﺠﺘﻤﻊ ﺗﻮﻟﻴﺪ ﺭﻭﻱ‬
‫ﺭﺍﻳﺎﻧﻪﺗﺎﻥ ﻧﺼﺐ ﮐﻨﻴﺪ ﺗﺎ ﺑﺘﻮﺍﻧﻴﺪ ﻣﺜﺎﻝﻫﺎﻱ ﮐﺘﺎﺏ ﺭﺍ ﺧﻮﺩﺗﺎﻥ ﻧﻮﺷﺘﻪ ﻭ ﺍﻣﺘﺤﺎﻥ ﮐﻨﻴﺪ‪ .‬ﺍﻳﻦ ﮐﺎﺭ‬
‫ﻫﻢ ﮐﻤﮏ ﻣﻲﮐﻨﺪ ﺗﺎ ‪ C++‬ﺭﺍ ﺑﻬﺘﺮ ﻳﺎﺩ ﺑﮕﻴﺮﻳﺪ ﻭ ﻫﻢ ﻣﻬﺎﺭﺕﻫﺎﻱ ﺣﺮﻓﻪﺍﻱﺗﺎﻥ ﺭﺍ ﺩﺭ ﮐﺎﺭ ﺑﺎ‬
‫ﻣﺤﻴﻂﻫﺎﻱ ﻣﺠﺘﻤﻊ ﺗﻮﻟﻴﺪ ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ‪.‬‬

‫‪ 1 – 4‬ﺷﺮﻭﻉ ﮐﺎﺭ ﺑﺎ ‪C++‬‬

‫ﺣﺎﻻ ﺷﻤﺎ ﺭﺍﻳﺎﻧﻪﺍﻱ ﺩﺍﺭﻳﺪ ﮐﻪ ﺑﻪ ﻳﮏ ﮐﺎﻣﭙﺎﻳﻠﺮ ‪ C++‬ﻣﺠﻬﺰ ﺍﺳﺖ‪ .‬ﺩﺭ ﺍﺩﺍﻡۀ ﻓﺼﻞ‪،‬‬
‫ﻣﺜﺎﻝﻫﺎﻱ ﺳﺎﺩﻩﺍﻱ ﺍﺯ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ‪ C++‬ﺭﺍ ﺫﮐﺮ ﻣﻲﮐﻨﻴﻢ ﻭ ﻧﮑﺎﺗﻲ ﺭﺍ ﺩﺭ ﻗﺎﻟﺐ ﺍﻳﻦ ﻣﺜﺎﻝﻫﺎ ﺑﻴﺎﻥ‬
‫ﺧﻮﺍﻫﻴﻢ ﮐﺮﺩ‪ .‬ﺍﮔﺮ ﺍﺯ ﻗﺒﻞ ﺑﺎ ‪ C‬ﻳﺎ ‪ C++‬ﺁﺷﻨﺎﻳﻲ ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﻣﻤﮑﻦ ﺍﺳﺖ ﺍﻳﻦ ﻣﺜﺎﻝﻫﺎ ﻣﺒﻬﻢ‬
‫ﺑﻪ ﻧﻈﺮ ﺑﺮﺳﻨﺪ ﻭ ﺑﺮﺧﻲ ﺍﺯ ﻧﮑﺎﺕ ﺭﺍ ﺧﻮﺏ ﺩﺭﮎ ﻧﮑﻨﻴﺪ‪ ،‬ﺍﻣﺎ ﺍﺻﻼ ﺟﺎﻱ ﻧﮕﺮﺍﻧﻲ ﻧﻴﺴﺖ ﺯﻳﺮﺍ‬
‫ﺍﻳﻦ ﻓﺼﻞ ﻳﮏ ﻣﺮﻭﺭ ﮐﻠﻲ ﺭﺍﺟﻊ ﺑﻪ ‪ C++‬ﺍﺳﺖ ﻭ ﺗﻤﺎﻡ ﺍﻳﻦ ﻧﮑﺎﺕ ﺩﺭ ﻓﺼﻞﻫﺎﻱ ﺑﻌﺪﻱ ﺑﻪ‬
‫ﺷﮑﻞ ﮐﺎﻣﻞ ﺷﺮﺡ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺍﻳﻦ ﻓﺼﻞ ﺑﻪ ﺷﻤﺎ ﮐﻤﮏ ﻣﻲﮐﻨﺪ ﺗﺎ ﻧﮑﺎﺕ ﺍﻭﻟﻴﻪ ﻭ‬
‫ﺿﺮﻭﺭﻱ ‪ C++‬ﺭﺍ ﻳﺎﺩ ﺑﮕﻴﺮﻳﺪ ﻭ ﻫﻤﭽﻨﻴﻦ ﻣﻄﻠﻊ ﺷﻮﻳﺪ ﮐﻪ ﺩﺭ ﻓﺼﻮﻝ ﺑﻌﺪﻱ ﺑﺎﻳﺪ ﻣﻨﺘﻈﺮ ﭼﻪ‬
‫ﻣﻄﺎﻟﺒﻲ ﺑﺎﺷﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 1 ‐ 1‬ﺍﻭﻟﻴﻦ ﺑﺮﻧﺎﻣﻪ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﺍﻭﻟﻴﻦ ﺑﺮﻧﺎﻣﻪﺍﻱ ﺍﺳﺖ ﮐﻪ ﻣﻲﻧﻮﻳﺴﻴﻢ‪ .‬ﺍﻣﺎ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﺎﺭ ﻧﮑﺖۀ ﺑﺴﻴﺎﺭ‬
‫ﻣﻬﻢ ﺯﻳﺮ ﺭﺍ ﻫﻤﻴﺸﻪ ﺑﻪ ﺧﺎﻃﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ‪:‬‬
‫‪5‬‬ ‫ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ ‪C++‬‬ ‫ﻓﺼﻞ اول ‪/‬‬

‫‪ C++‬ﻧﺴﺒﺖ ﺑﻪ ﺣﺮﻭﻑ »ﺣﺴﺎﺱ ﺑﻪ ﺣﺎﻟﺖ‪ «1‬ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ‪ A‬ﻭ ‪ a‬ﺭﺍ ﻳﮑﻲ ﻧﻤﻲﺩﺍﻧﺪ‪.‬‬
‫ﭘﺲ ﺩﺭ ﻋﺒﺎﺭﺕﻫﺎﻱ ‪ MY‬ﻭ ‪ My‬ﻭ ‪ mY‬ﻭ ‪ my‬ﻫﻴﭻ ﻳﮏ ﺑﺎ ﺩﻳﮕﺮﻱ ﺑﺮﺍﺑﺮ ﻧﻴﺴﺖ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ‬
‫ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺩﭼﺎﺭ ﺍﻳﻦ ﺍﺷﺘﺒﺎﻩ ﻧﺸﻮﻳﺪ‪ ،‬ﺍﺯ ﻗﺎﻧﻮﻥ ﺯﻳﺮ ﭘﻴﺮﻭﻱ ﮐﻨﻴﺪ‪» :‬ﻫﻤﻪ ﭼﻴﺰ ﺭﺍ ﺑﺎ ﺣﺮﻭﻑ‬
‫ﮐﻮﭼﮏ ﺑﻨﻮﻳﺴﻴﺪ‪ ،‬ﻣﮕﺮ ﺍﻳﻦﮐﻪ ﺑﺮﺍﻱ ﺑﺰﺭﮒ ﻧﻮﺷﺘﻦ ﺑﺮﺧﻲ ﺍﺯ ﺣﺮﻭﻑ ﺩﻟﻴﻞ ﻗﺎﻧﻊﮐﻨﻨﺪﻩﺍﻱ‬
‫ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ«‪.‬‬
‫ﺍﻭﻟﻴﻦ ﺑﺮﻧﺎﻣﻪﺍﻱ ﮐﻪ ﻣﻲﻧﻮﻳﺴﻴﻢ ﺑﻪ ﻣﺤﺾ ﺗﻮﻟﺪ‪ ،‬ﺑﻪ ﺷﻤﺎ ﺳﻼﻡ ﻣﻲﮐﻨﺪ ﻭ ﻋﺒﺎﺭﺕ‬
‫"!‪ "Hello, my programmer‬ﺭﺍ ﻧﻤﺎﻳﺶ ﻣﻲﺩﻫﺪ‪:‬‬
‫>‪#include <iostream‬‬
‫)(‪int main‬‬
‫; "‪{ std::cout << "Hello, my programmer!\n‬‬
‫;‪return 0‬‬
‫}‬

‫ﺍﻭﻟﻴﻦ ﺧﻂ ﺍﺯ ﮐﺪ ﺑﺎﻻ ﻳﮏ »ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﻩ‪ «2‬ﺍﺳﺖ‪ .‬ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﻩ‬


‫ﺷﺎﻣﻞ ﺍﺟﺰﺍﻱ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫‪ – 1‬ﮐﺎﺭﺍﮐﺘﺮ ‪ #‬ﮐﻪ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﺍﻳﻦ ﺧﻂ‪ ،‬ﻳﮏ ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﻩ ﺍﺳﺖ‪ .‬ﺍﻳﻦ‬
‫ﮐﺎﺭﺍﮐﺘﺮ ﺑﺎﻳﺪ ﺩﺭ ﺍﺑﺘﺪﺍﻱ ﻫﻢۀ ﺧﻄﻮﻁ ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﻩ ﺑﺎﺷﺪ‪.‬‬
‫‪ – 2‬ﻋﺒﺎﺭﺕ ‪include‬‬

‫‪ – 3‬ﻧﺎﻡ ﻳﮏ »ﻓﺎﻳﻞ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ« ﮐﻪ ﻣﻴﺎﻥ ﺩﻭ ﻋﻼﻣﺖ >< ﻣﺤﺼﻮﺭ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺑﻪ‬
‫ﻓﺎﻳﻞ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ »ﺳﺮﻓﺎﻳﻞ‪ «3‬ﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﻓﺎﻳﻞ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ ﮐﻪ ﺩﺭ ﺍﻳﻦﺟﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‬
‫‪ iostream‬ﻧﺎﻡ ﺩﺍﺭﺩ‪.‬‬
‫ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺍﺟﺰﺍﻱ ﻓﻮﻕ‪ ،‬ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﻩ ﺧﻄﻲ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺍﻃﻼﻉ‬
‫ﻣﻲﺩﻫﺪ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﻣﻮﺟﻮﺩﻳﺘﻲ ﺍﺳﺖ ﮐﻪ ﺗﻌﺮﻳﻒ ﺁﻥ ﺭﺍ ﺑﺎﻳﺪ ﺩﺭ ﻓﺎﻳﻞ ﮐﺘﺎﺑﺨﺎﻧﻪﺍﻱ ﻣﺬﮐﻮﺭ‬
‫ﺟﺴﺘﺠﻮ ﮐﻨﺪ‪ .‬ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﻮﺟﻮﺩﻳﺖ ‪ std::cout‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﮐﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺭﺍﺟﻊ‬
‫ﺑﻪ ﺁﻥ ﭼﻴﺰﻱ ﻧﻤﻲﺩﺍﻧﺪ‪ ،‬ﭘﺲ ﺑﻪ ﻓﺎﻳﻞ ‪ iostream‬ﻣﺮﺍﺟﻌﻪ ﻣﻲﮐﻨﺪ‪ ،‬ﺗﻌﺮﻳﻒ ﺁﻥ ﺭﺍ‬

‫‪1 – Case Sensitive‬‬ ‫‪2 – Preprocessor Directive‬‬


‫‪3 - Header‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪6‬‬

‫ﻣﻲﻳﺎﺑﺪ ﻭ ﺳﭙﺲ ﺁﻥ ﺭﺍ ﺍﺟﺮﺍ ﻣﻲﮐﻨﺪ‪.‬‬


‫ﻫﺮ ﺑﺮﻧﺎﻣﻪﺍﻱ ﮐﻪ ﺍﺯ ﻭﺭﻭﺩﻱ ﻭ ﺧﺮﻭﺟﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ ﺑﺎﻳﺪ ﺷﺎﻣﻞ ﺍﻳﻦ ﺧﻂ ﺭﺍﻫﻨﻤﺎ ﺑﺎﺷﺪ‪.‬‬
‫ﺧﻂ ﺩﻭﻡ ﺑﺮﻧﺎﻣﻪ ﻧﻴﺰ ﺑﺎﻳﺪ ﺩﺭ ﻫﻤﻪ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ‪ C++‬ﻭﺟﻮﺩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﺍﻳﻦ ﺧﻂ ﺑﻪ‬
‫ﮐﺎﻣﭙﺎﻳﻠﺮ ﻣﻲﮔﻮﻳﺪ ﮐﻪ »ﺑﺪﻥۀ ﺍﺻﻠﻲ ﺑﺮﻧﺎﻣﻪ« ﺍﺯ ﮐﺠﺎ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﺧﻂ ﺩﺍﺭﺍﻱ ﺍﺟﺰﺍﻱ‬
‫ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫‪ – 1‬ﻋﺒﺎﺭﺕ ‪ int‬ﮐﻪ ﻳﮏ ﻧﻮﻉ ﻋﺪﺩﻱ ﺩﺭ ‪ C++‬ﺍﺳﺖ‪ .‬ﺭﺍﺟﻊ ﺑﻪ ﺍﻧﻮﺍﻉ ﻋﺪﺩﻱ ﺩﺭ‬
‫‪ C++‬ﺩﺭ ﻓﺼﻞ ﺩﻭﻡ ﻣﻄﺎﻟﺐ ﮐﺎﻣﻠﻲ ﺧﻮﺍﻫﻴﺪ ﺩﻳﺪ‪.‬‬
‫‪ – 2‬ﻋﺒﺎﺭﺕ ‪ main‬ﮐﻪ ﺑﻪ ﺁﻥ »ﺗﺎﺑﻊ ﺍﺻﻠﻲ« ﺩﺭ ‪ C++‬ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬
‫‪ – 3‬ﺩﻭ ﭘﺮﺍﻧﺘﺰ )( ﮐﻪ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﻋﺒﺎﺭﺕ ‪ main‬ﻳﮏ »ﺗﺎﺑﻊ‪ «1‬ﺍﺳﺖ‪ .‬ﺗﻮﺍﺑﻊ ﺭﺍ ﺩﺭ‬
‫ﻓﺼﻞ ﭘﻨﺠﻢ ﺑﺮﺭﺳﻲ ﺧﻮﺍﻫﻴﻢ ﮐﺮﺩ‪.‬‬
‫ﻫﺮ ﺑﺮﻧﺎﻣﻪ ﻓﻘﻂ ﺑﺎﻳﺪ ﻳﮏ ﺗﺎﺑﻊ )(‪ main‬ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﻭﻗﺘﻲ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﺷﺪ‪ ،‬ﻳﮏ‬
‫ﻋﺪﺩ ﺻﺤﻴﺢ ﺑﻪ ﺳﻴﺴﺘﻢﻋﺎﻣﻞ ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ ﺗﺎ ﺳﻴﺴﺘﻢﻋﺎﻣﻞ ﺑﻔﻬﻤﺪ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺑﺎ‬
‫ﻣﻮﻓﻘﻴﺖ ﺑﻪ ﭘﺎﻳﺎﻥ ﺭﺳﻴﺪﻩ ﻳﺎ ﺧﻴﺮ‪ .‬ﻋﺒﺎﺭﺕ ‪ int‬ﮐﻪ ﻗﺒﻞ ﺍﺯ ‪ main‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﻧﺸﺎﻥ‬
‫ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﺑﻪ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬
‫ﺳﻪ ﺧﻂ ﺁﺧﺮ ﺑﺮﻧﺎﻣﻪ‪» ،‬ﺑﺪﻥۀ ﺍﺻﻠﻲ ﺑﺮﻧﺎﻣﻪ« ﺭﺍ ﺗﺸﮑﻴﻞ ﻣﻲﺩﻫﻨﺪ‪» .‬ﺑﺪﻥۀ ﺍﺻﻠﻲ ﺑﺮﻧﺎﻣﻪ«‬
‫ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﺩﺳﺘﻮﺭﺍﺕ ﻣﺘﻮﺍﻟﻲ ﺍﺳﺖ ﮐﻪ ﻣﻴﺎﻥ ﺩﻭ ﻋﻼﻣﺖ ﺑﺮﺍﮐﺖ }{ ﺑﺴﺘﻪ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬
‫ﺍﻳﻦ ﺑﺮﺍﮐﺖﻫﺎ ﺷﺮﻭﻉ ﺑﺮﻧﺎﻣﻪ ﻭ ﭘﺎﻳﺎﻥ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ‪.‬‬
‫ﺩﺳﺘﻮﺭﺍﺕ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺧﻂ ﺳﻮﻡ ﺷﺮﻭﻉ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻓﻘﻂ ﺩﻭ ﺩﺳﺘﻮﺭ ﺩﺍﺭﺩ‪.‬‬
‫ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ﻳﻌﻨﻲ‪:‬‬
‫;"‪Std::cout << "Hello, my programmer!\n‬‬

‫ﺭﺷﺖۀ "‪ "Hello, my programmer!\n‬ﺭﺍ ﺑﻪ ﻓﺮﺍﻳﻨﺪ ﺧﺮﻭﺟﻲ ‪std::cout‬‬


‫ﻣﻲﻓﺮﺳﺘﺪ‪ .‬ﺍﻳﻦ ﺧﺮﻭﺟﻲ ﻣﻌﻤﻮﻻ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﻣﻲﺑﺎﺷﺪ‪ .‬ﻋﻼﻣﺖ << »ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ‪«2‬‬
‫ﺩﺭ ‪ C++‬ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺍﺟﺰﺍﻱ ﺳﻤﺖ ﺭﺍﺳﺘﺶ ﺭﺍ ﺑﻪ ﺧﺮﻭﺟﻲ ﺳﻤﺖ ﭼﭙﺶ‬

‫‪1 – Function‬‬ ‫‪2 – output operator‬‬


‫‪7‬‬ ‫ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ ‪C++‬‬ ‫ﻓﺼﻞ اول ‪/‬‬

‫ﻣﻲﻓﺮﺳﺘﺪ‪ .‬ﺣﺎﺻﻞ ﮐﺎﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺭﺷﺖۀ‬


‫!‪Hello, my programmer‬‬

‫ﺭﻭﻱ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‪ .‬ﮐﺎﺭﺍﮐﺘﺮ ‪ \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‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 2‬ﻳﮏ ﺑﺮﻧﺎﻡۀ ﺩﻳﮕﺮ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻫﻤﺎﻥ ﺧﺮﻭﺟﻲ ﻣﺜﺎﻝ ‪ 1‐1‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬
‫>‪#include <iostream‬‬
‫;‪using namespace std‬‬
‫)(‪int main‬‬
‫‪{ //prints "Hello, my programmer!" :‬‬
‫; "‪cout << "Hello, my programmer!\n‬‬
‫;‪return 0‬‬
‫}‬

‫ﺩﻭﻣﻴﻦ ﺧﻂ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻳﻌﻨﻲ‬


‫;‪using namespace std‬‬

‫ﺑﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﻣﻲﮔﻮﻳﺪ ﮐﻪ ﻋﺒﺎﺭﺕ ‪ 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‬‬

‫ﻣﻘﺪﺍﺭ ‪ 66‬ﺭﺍ ﺑﻪ ﺧﺮﻭﺟﻲ ‪ cout‬ﻣﻲﻓﺮﺳﺘﺪ ﮐﻪ ‪ cout‬ﻣﻌﻤﻮﻻ ﺑﻪ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ‬


‫ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ .‬ﺩﺭ ﻧﺘﻴﺠﻪ ﻣﻘﺪﺍﺭ ‪ 66‬ﺭﻭﻱ ﺻﻔﺤﻪ ﻧﻤﺎﻳﺶ ﺩﺭﺝ ﻣﻲﺷﻮﺩ‪.‬‬
‫‪ cout‬ﺍﻳﻦ ﻗﺎﺑﻠﻴﺖ ﺭﺍ ﺩﺍﺭﺩ ﮐﻪ ﭼﻨﺪ ﭼﻴﺰ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺘﻮﺍﻟﻲ ﻭ ﭘﺸﺖ ﺳﺮ ﻫﻢ ﺭﻭﻱ‬
‫ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﺩﺭﺝ ﮐﻨﺪ‪ .‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺧﺎﺻﻴﺖ ﻣﻲﺗﻮﺍﻥ ﭼﻨﺪ ﺭﺷﺘﻪ ﻣﺠﺰﺍ ﺭﺍ ﺍﺯ ﻃﺮﻳﻖ‬
‫‪ cout‬ﺑﺎ ﻳﮑﺪﻳﮕﺮ ﭘﻴﻮﻧﺪ ﺩﺍﺩ ﻭ ﺧﺮﻭﺟﻲ ﻭﺍﺣﺪ ﺗﻮﻟﻴﺪ ﻧﻤﻮﺩ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ ﺑﻴﺸﺘﺮ‬
‫ﺭﻭﺷﻦ ﻣﻲﮐﻨﺪ‪ .‬ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﺭﺍ ﺑﺒﻴﻨﻴﺪ ﺑﺎﺯ ﻫﻢ ﻳﺎﺩﺁﻭﺭﻱ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﻓﺮﺍﻣﻮﺵ‬
‫ﻧﮑﻨﻴﺪ ﺩﻭ ﺧﻂ ﺍﺻﻠﻲ ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﻩ ﻭ ﻓﻀﺎﻱ ﻧﺎﻡ ﺭﺍ ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺍﺿﺎﻓﻪ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 3‬ﺑﺮﻧﺎﻣﻪ ﺩﻳﮕﺮﻱ ﺍﺯ ‪Hello‬‬


‫)(‪int main‬‬
‫‪{ //prints "Hello, my programmer!" :‬‬
‫;‪cout << "Hello, m" << "y progra" << "mmer!" << endl‬‬
‫;‪return 0‬‬
‫}‬

‫ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ << ﭼﻬﺎﺭ ﺑﺎﺭ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﻭ ﭼﻬﺎﺭ ﻋﻨﺼﺮ ﺭﺍ ﺑﻪ‬
‫‪ 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‬ﻳﮏ ﻟﻴﺘﺮﺍﻝ ﺭﺷﺘﻪﺍﻱ ﺍﺳﺖ‪.‬‬
‫ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﻣﺎﻧﻨﺪ ﻟﻴﺘﺮﺍﻝﻫﺎﻱ ﺭﺷﺘﻪﺍﻱ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﺧﺮﻭﺟﻲ ﻧﻤﺎﻳﺶ ﺩﺍﺩ‪ .‬ﺑﻪ ﻣﺜﺎﻝ‬
‫ﺑﻌﺪﻱ ﺗﻮﺟﻪ ﻧﻤﺎﻳﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 4‬ﻧﺴﺦۀ ﭼﻬﺎﺭﻡ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺳﻼﻡ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺧﺮﻭﺟﻲ ﻣﺜﺎﻝ ‪ 1‐1‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬

‫‪1 – Literal‬‬ ‫‪2 – Character‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪12‬‬

‫)(‪int main‬‬
‫‪{ // prints "Hello, my programmer!":‬‬
‫;'‪cout << "Hello, " << 'm' << "y programmer" << '!' << '\n‬‬
‫;‪return 0‬‬
‫}‬

‫ﻣﺜﺎﻝ ﺑﺎﻻ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻟﻴﺘﺮﺍﻝ ﺭﺷﺘﻪﺍﻱ ﭘﻴﻮﻧﺪ ﺩﺍﺩ ﻭ‬
‫ﺧﺮﻭﺟﻲ ﺗﺮﮐﻴﺒﻲ ﺩﺭﺳﺖ ﮐﺮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 5‬ﺩﺭﺝ ﻋﺪﺩ ﺩﺭ ﺧﺮﻭﺟﻲ‬


‫)(‪int main‬‬
‫‪{ // prints "Today is Feb 5 2005":‬‬
‫;‪cout << "Today is Feb " << 5 << ' ' << 2005 << endl‬‬
‫;‪return 0‬‬
‫}‬

‫ﻭﻗﺘﻲ ﻣﺜﺎﻝ ﺑﺎﻻ ﺭﺍ ﺍﺟﺮﺍ ﮐﻨﻴﻢ‪ ،‬ﺧﺮﻭﺟﻲ ﺑﻪ ﺷﮑﻞ ‪Today is Feb 5 2005‬‬
‫ﺭﻭﻱ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﭼﺎﭖ ﻣﻲﮔﺮﺩﺩ‪ .‬ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﻳﮏ »ﮐﺎﺭﺍﮐﺘﺮ ﺟﺎﻱ ﺧﺎﻟﻲ« ' ' ﺑﻴﻦ ‪5‬‬
‫ﻭ ‪ 2005‬ﮔﻨﺠﺎﻧﺪﻩﺍﻳﻢ ﺗﺎ ﺍﻳﻦ ﺩﻭ ﻋﺪﺩ ﺑﺎ ﻓﺎﺻﻠﻪ ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﭼﺎﭖ ﺷﻮﻧﺪ ﻭ ﺑﻪ ﻫﻢ ﭘﻴﻮﻧﺪ‬
‫ﻧﺨﻮﺭﻧﺪ‪.‬‬

‫‪ 1 – 7‬ﻣﺘﻐﻴﺮﻫﺎ ﻭ ﺗﻌﺮﻳﻒ ﺁﻥﻫﺎ‪:‬‬


‫ﻫﻢۀ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﻧﻮﺷﺘﻪ ﻣﻲﺷﻮﺩ ﺑﺮﺍﻱ ﭘﺮﺩﺍﺯﺵ ﺩﺍﺩﻩﻫﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‪ .‬ﻳﻌﻨﻲ‬
‫ﺍﻃﻼﻋﺎﺗﻲ ﺭﺍ ﺍﺯ ﻳﮏ ﻭﺭﻭﺩﻱ ﻣﻲﮔﻴﺮﺩ ﻭ ﺁﻥﻫﺎ ﺭﺍ ﭘﺮﺩﺍﺯﺵ ﻣﻲﮐﻨﺪ ﻭ ﻧﺘﺎﻳﺞ ﻣﻮﺭﺩ ﻧﻈﺮ ﺭﺍ ﺑﻪ‬
‫ﻳﮏ ﺧﺮﻭﺟﻲ ﻣﻲﻓﺮﺳﺘﺪ‪ .‬ﺑﺮﺍﻱ ﭘﺮﺩﺍﺯﺵ‪ ،‬ﻻﺯﻡ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎ ﻭ ﻧﺘﺎﻳﺞ ﺍﺑﺘﺪﺍ ﺩﺭ ﺣﺎﻓﻆۀ‬
‫ﺍﺻﻠﻲ ﺫﺧﻴﺮﻩ ﺷﻮﻧﺪ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭ ﺍﺯ »ﻣﺘﻐﻴﺮﻫﺎ« ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪.‬‬
‫»ﻣﺘﻐﻴﺮ‪ «1‬ﻣﮑﺎﻧﻲ ﺩﺭ ﺣﺎﻓﻈﻪ ﺍﺳﺖ ﮐﻪ ﭼﻬﺎﺭ ﻣﺸﺨﺼﻪ ﺩﺍﺭﺩ‪ :‬ﻧﺎﻡ‪ ،‬ﻧﻮﻉ‪ ،‬ﻣﻘﺪﺍﺭ‪ ،‬ﺁﺩﺭﺱ‪.‬‬
‫ﻭﻗﺘﻲ ﻣﺘﻐﻴﺮﻱ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﻴﻢ‪ ،‬ﺍﺑﺘﺪﺍ ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﻧﻮﻉ ﻣﺘﻐﻴﺮ‪ ،‬ﺁﺩﺭﺳﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺩﺭ‬
‫ﻧﻈﺮ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ‪ ،‬ﺳﭙﺲ ﺑﻪ ﺁﻥ ﺁﺩﺭﺱ ﻳﮏ ﻧﺎﻡ ﺗﻌﻠﻖ ﻣﻲﮔﻴﺮﺩ‪ .‬ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﺑﻴﺎﻥ ﻣﻲﮐﻨﺪ ﮐﻪ‬

‫‪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‬ﺧﻮﺍﻫﻨﺪ ﺩﺍﺷﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 6‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻧﻮﻉ ﺻﺤﻴﺢ‬


‫)(‪int main‬‬
‫‪{ // prints "m = 45 and n = 55":‬‬
‫;‪int m = 45‬‬
‫;‪int n = 55‬‬
‫;‪cout << "m = " << m << " and n = " << n << endl‬‬
‫;‪return 0‬‬
‫}‬

‫ﺧﺮﻭﺟﻲ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬


‫‪m = 44 and n = 77‬‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺘﻐﻴﺮ ‪ m‬ﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ‪ int‬ﻭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ ‪ 45‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ‪ .‬ﺳﭙﺲ ﻣﺘﻐﻴﺮ‬
‫‪ n‬ﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ‪ int‬ﻭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ ‪ 55‬ﺗﻌﺮﻳﻒ ﮔﺸﺘﻪ ﺍﺳﺖ‪ .‬ﺳﺮﺍﻧﺠﺎﻡ ﻣﻘﺎﺩﻳﺮ ﺍﻳﻦ ﺩﻭ‬
‫ﻣﺘﻐﻴﺮ ﺑﺎ ﺩﺳﺘﻮﺭ ‪ cout‬ﺭﻭﻱ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬
‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﺘﻐﻴﺮﻫﺎ ﺭﺍ ﻫﻨﮕﺎﻡ ﺗﻌﺮﻳﻒ‪ ،‬ﺑﺪﻭﻥ ﻣﻘﺪﺍﺭ ﺭﻫﺎ ﮐﻨﻴﻢ ﻭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺭﺍ ﺑﻪ ﺩﺭﻭﻥ‬
‫ﺑﺮﻧﺎﻣﻪ ﻣﻮﮐﻮﻝ ﻧﻤﺎﻳﻴﻢ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪:‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 7‬ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮ ﺑﺪﻭﻥ ﻣﻘﺪﺍﺭﺩﻫﻲ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺧﺮﻭﺟﻲ ﻣﺜﺎﻝ ‪ 1 – 6‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫‪{ // prints "m = 45 and n = 55":‬‬
‫;‪int m‬‬
‫;‪int n‬‬
‫;‪m = 45‬‬ ‫‪// assigns the value 45 to m‬‬
‫‪15‬‬ ‫ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ ‪C++‬‬ ‫ﻓﺼﻞ اول ‪/‬‬

‫;‪n = m + 10‬‬ ‫‪// assigns the value 55 to n‬‬


‫;‪cout << "m = " << m << " and n = " << n << endl‬‬
‫;‪return 0‬‬
‫}‬

‫ﺧﺮﻭﺟﻲ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬


‫‪m = 45 and n = 55‬‬

‫ﺩﺭ ﺧﻂ ﺳﻮﻡ ﻭ ﭼﻬﺎﺭﻡ‪ ،‬ﻣﺘﻐﻴﺮﻫﺎﻱ ‪ m‬ﻭ ‪ n‬ﺗﻌﺮﻳﻒ ﺷﺪﻩﺍﻧﺪ ﺍﻣﺎ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩﺍﻧﺪ‪ .‬ﺩﺭ ﺧﻂ‬
‫ﭘﻨﺠﻢ ﻣﻘﺪﺍﺭ ‪ 45‬ﺩﺭ ﻣﺘﻐﻴﺮ ‪ m‬ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺩﺭ ﺧﻂ ﺷﺸﻢ ﻧﻴﺰ ﻣﻘﺪﺍﺭ ‪ m+10‬ﻳﻌﻨﻲ‬
‫‪ 45+10‬ﮐﻪ ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 50‬ﺍﺳﺖ ﺩﺭ ‪ n‬ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﭘﺲ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺩﻭ ﻣﺘﻐﻴﺮ‬
‫ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﺪﻧﺪ‪ ،‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺩﺳﺘﻮﺭ ‪ cout‬ﺁﻥﻫﺎ ﺭﺍ ﭼﺎﭖ ﮐﻨﻴﻢ‪.‬‬
‫ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﻣﻲﺗﻮﺍﻧﺴﺘﻴﻢ ﻣﺘﻐﻴﺮﻫﺎﻱ ‪ m‬ﻭ ‪ n‬ﺭﺍ ﺭﻭﻱ ﻳﮏ ﺧﻂ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ‪:‬‬
‫;‪int m,n‬‬

‫ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﻫﺮ ﺩﻭ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ ‪ int‬ﺗﻌﺮﻳﻒ ﻣﻲﺷﻮﻧﺪ ﻭ ﻫﻴﭻ ﮐﺪﺍﻡ ﻣﻘﺪﺍﺭﺩﻫﻲ‬
‫ﻧﻤﻲﺷﻮﻧﺪ‪ .‬ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ‪ m‬ﻭ ‪ n‬ﺑﺎ ﻳﮏ ﻋﻼﻣﺖ ﮐﺎﻣﺎ ‪ ,‬ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﺟﺪﺍ ﺷﺪﻩﺍﻧﺪ‪ .‬ﻟﺬﺍ‬
‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﭼﻨﺪ ﻣﺘﻐﻴﺮ ﺭﺍ ﺭﻭﻱ ﻳﮏ ﺳﻄﺮ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﺑﻪ ﺷﺮﻃﻲ ﮐﻪ ﻫﻤﻪ ﺍﺯ ﻳﮏ ﻧﻮﻉ ﺑﺎﺷﻨﺪ‪.‬‬

‫‪ 1 – 8‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ‪ 1‬ﺑﻪ ﻣﺘﻐﻴﺮﻫﺎ‬


‫ﺩﺭ ﺑﺴﻴﺎﺭﻱ ﺍﺯ ﻣﻮﺍﺭﺩ ﺑﻬﺘﺮ ﺍﺳﺖ ﻣﺘﻐﻴﺮﻫﺎ ﺭﺍ ﺩﺭ ﻫﻤﺎﻥ ﻣﺤﻠﻲ ﮐﻪ ﺍﻋﻼﻥ ﻣﻲﺷﻮﻧﺪ‬
‫ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﻨﻴﻢ‪ .‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﺎﻋﺚ ﺍﻳﺠﺎﺩ‬
‫ﺩﺭﺩﺳﺮﻫﺎﻳﻲ ﺷﻮﺩ‪ .‬ﻣﺜﺎﻝ ﺯﻳﺮ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 8‬ﻣﺘﻐﻴﺮ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ‬


‫)(‪int main‬‬
‫‪{ // prints "x = ?? and y = 45":‬‬
‫;‪int x‬‬ ‫‪// BAD: x is not initialized‬‬
‫;‪int y=45‬‬
‫;‪cout << "x = " << x << " and y = " << y << endl‬‬

‫‪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‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪ .‬ﻳﮏ ﺛﺎﺑﺖ‪ ،‬ﻳﮏ ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﺍﺳﺖ ﮐﻪ ﻓﻘﻂ ﻳﮏ‬
‫ﺑﺎﺭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﺗﻐﻴﻴﺮ ﺩﺍﺩﻥ ﻣﻘﺪﺍﺭ ﺁﻥ ﺩﺭ ﺍﺩﺍﻡۀ ﺑﺮﻧﺎﻣﻪ ﻣﻤﮑﻦ ﻧﻴﺴﺖ‪.‬‬

‫‪1 – Garbage‬‬ ‫‪2 - Constant‬‬


‫‪17‬‬ ‫ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ ‪C++‬‬ ‫ﻓﺼﻞ اول ‪/‬‬

‫ﺗﻌﺮﻳﻒ ﺛﺎﺑﺖﻫﺎ ﻣﺎﻧﻨﺪ ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮﻫﺎﺳﺖ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ ‪const‬‬
‫ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﺗﻌﺮﻳﻒ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ‪ .‬ﭘﺲ ﺩﺳﺘﻮﺭ;‪ int k=3‬ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ ‪ k‬ﻭ ﺑﺎ ﻣﻘﺪﺍﺭ‬
‫ﺍﻭﻟﻲۀ ‪ 3‬ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﺩﺭ ﺍﺩﺍﻡۀ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭ ﺁﻥ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﺍﺩ ﻭﻟﻲ ﺩﺳﺘﻮﺭ‬
‫;‪const int k=3‬‬
‫ﺛﺎﺑﺘﻲ ﺑﻪ ﻧﺎﻡ ‪ k‬ﻭ ﺑﺎ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ ‪ 3‬ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺩﺭ ﺍﺩﺍﻡۀ‬
‫ﺑﺮﻧﺎﻣﻪ ﺗﻐﻴﻴﺮ ﺩﺍﺩ‪.‬‬
‫ﺛﺎﺑﺖﻫﺎ ﺭﺍ ﺑﺎﻳﺪ ﻫﻨﮕﺎﻡ ﺗﻌﺮﻳﻒ‪ ،‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﻧﻤﻮﺩ‪ .‬ﻳﮏ ﺛﺎﺑﺖ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺯ ﻧﻮﻉ‬
‫ﮐﺎﺭﺍﮐﺘﺮﻱ‪ ،‬ﺻﺤﻴﺢ ‪ ،‬ﺍﻋﺸﺎﺭﻱ ﻭ ‪ ...‬ﺑﺎﺷﺪ‪ .‬ﻣﺜﺎﻝ ﺯﻳﺮ ﭼﻨﺪ ﻧﻮﻉ ﺛﺎﺑﺖ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 9‬ﺗﻌﺮﻳﻒ ﺛﺎﺑﺖﻫﺎ‬


‫ﺑﺮﻧﺎﻣﻪ ﺯﻳﺮ ﺧﺮﻭﺟﻲ ﻧﺪﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫‪{ // defines constants; has no output:‬‬
‫;'‪const char BEEP ='\b‬‬
‫;‪const int MAXINT=2147483647‬‬
‫;‪const float DEGREE=23.53‬‬
‫‪const double PI=3.14159265358979323846‬‬
‫;‪return 0‬‬
‫}‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻧﺎﻡ ﺛﺎﺑﺖﻫﺎ ﺭﺍ ﺑﺎ ﺣﺮﻭﻑ ﺍﻧﮕﻠﻴﺴﻲ ﺑﺰﺭﮒ ﻧﻮﺷﺘﻪﺍﻳﻢ‪ .‬ﻣﻌﻤﻮﻻ ﺩﺭ‬
‫ﺑﺮﻧﺎﻣﻪﻫﺎ ﺑﺮﺍﻱ ﻧﺸﺎﻥ ﺩﺍﺩﻥ ﺛﺎﺑﺖﻫﺎ ﺍﺯ ﺣﺮﻭﻑ ﺑﺰﺭﮒ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻨﺪ‪ .‬ﻫﺮ ﭼﻨﺪ ﺍﻳﻦ ﮐﺎﺭ‬
‫ﺍﺟﺒﺎﺭﻱ ﻧﻴﺴﺖ‪ ،‬ﺍﻣﺎ ﺑﺎ ﺭﻋﺎﻳﺖ ﺍﻳﻦ ﻗﺮﺍﺭﺩﺍﺩ ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺛﺎﺑﺖﻫﺎ ﺭﺍ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎ ﺗﻤﻴﺰ‬
‫ﺩﻫﻴﻢ‪.‬‬

‫‪ 1 – 10‬ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ‬
‫ﺩﺭ ﺑﻴﺸﺘﺮ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺍﺯ ﮐﺎﺭﺑﺮ ﺧﻮﺍﺳﺘﻪ ﻣﻲﺷﻮﺩ ﺗﺎ ﻣﻘﺎﺩﻳﺮﻱ ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﺪ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ‬
‫ﺑﺘﻮﺍﻧﻴﻢ ﻫﻨﮕﺎﻡ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﻣﻘﺎﺩﻳﺮﻱ ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﻴﻢ ﺍﺯ ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ >> ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪18‬‬

‫ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ ﻣﺎﻧﻨﺪ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ ﺍﺳﺖ ﻭ ﺑﻪ ﻫﻤﺎﻥ ﺳﺎﺩﮔﻲ ﮐﺎﺭ ﻣﻲﮐﻨﺪ‪ .‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬
‫ﺩﺳﺘﻮﺭ ﻭﺭﻭﺩﻱ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫;‪cin >> variable‬‬

‫‪ variable‬ﻧﺎﻡ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺳﺖ‪ .‬ﻣﺜﻼ ﺩﺳﺘﻮﺭ ;‪ cin >> m‬ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ‬


‫)ﺻﻔﺤﻪ ﮐﻠﻴﺪ( ﮔﺮﻓﺘﻪ ﻭ ﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ ‪ m‬ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ‪ .‬ﺍﻳﻦ ﮐﻪ ﻭﺭﻭﺩﻱ ﻋﺪﺩ ﺑﺎﺷﺪ ﻳﺎ ﮐﺎﺭﺍﮐﺘﺮ‬
‫ﻳﺎ ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﺍﻳﻦ ﺩﻭ‪ ،‬ﺑﻪ ﻧﻮﻉ ‪ m‬ﺑﺴﺘﮕﻲ ﺩﺍﺭﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 10‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﮏ ﻋﺪﺩ ﺍﺯ ﮐﺎﺭﺑﺮ ﮔﺮﻓﺘﻪ ﻭ ﻫﻤﺎﻥ ﻋﺪﺩ ﺭﺍ ﺩﻭﺑﺎﺭﻩ ﺩﺭ ﺧﺮﻭﺟﻲ ﻧﻤﺎﻳﺶ‬
‫ﻣﻲﺩﻫﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ // reads an integer from input:‬‬
‫;‪int m‬‬
‫;" ‪cout << "Enter a number:‬‬
‫;‪cin >> m‬‬
‫;‪cout << "your number is: " << m << endl‬‬
‫;‪return 0‬‬
‫}‬

‫ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺟﺮﺍ ﺷﻮﺩ‪ ،‬ﻋﺒﺎﺭﺕ ‪ Enter a number:‬ﺭﻭﻱ ﺻﻔﺤﻪ‬


‫ﭼﺎﭖ ﻣﻲﺷﻮﺩ ﻭ ﻣﻨﺘﻈﺮ ﻣﻲﻣﺎﻧﺪ ﺗﺎ ﻳﮏ ﻋﺪﺩ ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﻴﺪ‪ .‬ﺑﺮﺍﻱ ﻭﺍﺭﺩ ﮐﺮﺩﻥ ﻋﺪﺩ ﺑﺎﻳﺪ ﺁﻥ ﺭﺍ‬
‫ﺗﺎﻳﭗ ﮐﺮﺩﻩ ﻭ ﺳﭙﺲ ﮐﻠﻴﺪ ‪ Enter‬ﺭﺍ ﻓﺸﺎﺭ ﺩﻫﻴﺪ‪ .‬ﺧﻂ ;‪ cin >> m‬ﻋﺪﺩ ﺭﺍ ﺍﺯ‬
‫ﻭﺭﻭﺩﻱ ﮔﺮﻓﺘﻪ ﻭ ﺩﺭ ﻣﺘﻐﻴﺮ ‪ m‬ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ‪ .‬ﺗﻮﺳﻂ ﺧﻂ ﺑﻌﺪﻱ ﻧﻴﺰ ﺟﻤﻞۀ‬
‫‪ your number is:‬ﻭ ﺳﭙﺲ ﻣﻘﺪﺍﺭ ‪ m‬ﭼﺎﭖ ﻣﻲﺷﻮﺩ‪ .‬ﺷﮑﻞ ﺯﻳﺮ ﻳﮏ ﻧﻤﻮﻧﻪ ﺍﺯ‬
‫ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪:‬‬
‫‪Enter a number: 52‬‬
‫‪your number is: 52‬‬

‫ﺩﺭ ﺍﻳﻦ ﺷﮑﻞ‪ ،‬ﻋﺪﺩﻱ ﮐﻪ ﮐﺎﺭﺑﺮ ﻭﺍﺭﺩ ﮐﺮﺩﻩ ﺑﺎ ﺣﺮﻭﻑ ﺳﻴﺎﻩﺗﺮ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺑﺎﺯ ﻫﻢ‬
‫ﺑﻪ ﮐﺪ ﺑﺮﻧﺎﻣﻪ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪ .‬ﺩﺭ ﺧﻂ ﭼﻬﺎﺭﻡ ﮐﺪ ﻳﻌﻨﻲ‪:‬‬
‫;" ‪cout << "Enter a number:‬‬
‫‪19‬‬ ‫ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ ‪C++‬‬ ‫ﻓﺼﻞ اول ‪/‬‬

‫ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮ '‪ '\n‬ﻳﺎ ‪ endl‬ﺍﺳﺘﻔﺎﺩﻩ ﻧﮑﺮﺩﻩﺍﻳﻢ ﺗﺎ ﻣﮑﺎﻥﻧﻤﺎ ﺩﺭ ﻫﻤﺎﻥ ﺧﻂ ﺑﺎﻗﻲ ﺑﻤﺎﻧﺪ‬
‫ﻭ ﻭﺭﻭﺩﻱ ﺩﺭ ﺟﻠﻮﻱ ﻫﻤﺎﻥ ﺧﻂ ﻭﺍﺭﺩ ﺷﻮﺩ‪.‬‬
‫ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ ﻧﻴﺰ ﻣﺎﻧﻨﺪ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ ﺑﻪ ﺷﮑﻞ ﺟﺮﻳﺎﻧﻲ ﺭﻓﺘﺎﺭ ﻣﻲﮐﻨﺪ‪ .‬ﻳﻌﻨﻲ‬
‫ﻫﻤﺎﻥ ﻃﻮﺭ ﮐﻪ ﺩﺭ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ ﻣﻲﺗﻮﺍﻧﺴﺘﻴﻢ ﭼﻨﺪ ﻋﺒﺎﺭﺕ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﭼﻨﺪ ﻋﻤﻠﮕﺮ‬
‫<< ﺑﻪ ﺻﻮﺭﺕ ﭘﺸﺖ ﺳﺮ ﻫﻢ ﭼﺎﭖ ﮐﻨﻴﻢ‪ ،‬ﺩﺭ ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬
‫ﭼﻨﺪ ﻋﻤﻠﮕﺮ >> ﭼﻨﺪ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ﭘﺸﺖ ﺳﺮ ﻫﻢ ﺩﺭﻳﺎﻓﺖ ﮐﻨﻴﻢ‪ .‬ﻣﺜﻼ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬
‫ﺩﺳﺘﻮﺭ‪:‬‬
‫;‪cin >> x >> y >> z‬‬

‫ﺳﻪ ﻣﻘﺪﺍﺭ ‪ x‬ﻭ ‪ y‬ﻭ ‪ z‬ﺑﻪ ﺗﺮﺗﻴﺐ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭ ﺑﺎﻳﺪ ﺑﻴﻦ ﻫﺮ‬
‫ﻭﺭﻭﺩﻱ ﻳﮏ ﻓﻀﺎﻱ ﺧﺎﻟﻲ )‪ (space‬ﺑﮕﺬﺍﺭﻳﺪ ﻭ ﭘﺲ ﺍﺯ ﺗﺎﻳﭗ ﮐﺮﺩﻥ ﻫﻢۀ ﻭﺭﻭﺩﻱﻫﺎ‪ ،‬ﮐﻠﻴﺪ‬
‫‪ enter‬ﺭﺍ ﺑﻔﺸﺎﺭﻳﺪ‪ .‬ﺁﺧﺮﻳﻦ ﻣﺜﺎﻝ ﻓﺼﻞ‪ ،‬ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ ﺑﻬﺘﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 1 – 11‬ﭼﻨﺪ ﻭﺭﻭﺩﻱ ﺭﻭﻱ ﻳﮏ ﺧﻂ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻣﺎﻧﻨﺪ ﻣﺜﺎﻝ ‪ 1 – 10‬ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﺳﻪ ﻋﺪﺩ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ‬
‫ﮔﺮﻓﺘﻪ ﻭ ﻫﻤﺎﻥ ﺍﻋﺪﺍﺩ ﺭﺍ ﺩﻭﺑﺎﺭﻩ ﺩﺭ ﺧﺮﻭﺟﻲ ﻧﻤﺎﻳﺶ ﻣﻲﺩﻫﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ // reads 3 integers from input:‬‬
‫;‪int q, r, s‬‬
‫;" ‪cout << "Enter three numbers:‬‬
‫;‪cin >> q >> r >> s‬‬
‫‪cout << "your numbers are: << q << ", " << r‬‬
‫;‪<< ", " << s << endl‬‬
‫;‪return 0‬‬
‫}‬

‫ﻧﻤﻮﻧﻪﺍﻱ ﺍﺯ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺩﺭ ﺯﻳﺮ ﺁﻣﺪﻩ ﺍﺳﺖ‪:‬‬


‫‪Enter three numbers: 35 70 9‬‬
‫‪your numbers are: 35, 70, 9‬‬

‫ﺍﻋﺪﺍﺩﻱ ﮐﻪ ﮐﺎﺭﺑﺮ ﺩﺭ ﺍﻳﻦ ﺍﺟﺮﺍ ﻭﺍﺭﺩ ﻧﻤﻮﺩﻩ ﺑﻪ ﺻﻮﺭﺕ ﺳﻴﺎﻩﺗﺮ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪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‬ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ‬

‫ﺝ ( ﻣﻘﺪﺍﺭ ‪ 9‬ﻭ ‪ 7‬ﻫﺮ ﮐﺪﺍﻡ ﺟﺪﺍ ﺩﺭ ‪ x‬ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ‬


‫‪21‬‬ ‫ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ ‪C++‬‬ ‫ﻓﺼﻞ اول ‪/‬‬

‫ﺩ ( ﺩﺳﺘﻮﺭ ﺩﻭﻡ ﺍﺟﺮﺍ ﻧﻤﻲﺷﻮﺩ ﻭ ﮐﺎﻣﭙﺎﻳﻠﺮ ﺧﻄﺎ ﻣﻲﮔﻴﺮﺩ‪.‬‬


‫‪ – 9‬ﮐﺪ ;‪ cin >> age‬ﭼﻪ ﮐﺎﺭﻱ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ؟‬
‫ﺍﻟﻒ ( ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ ‪ age‬ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ‬
‫ﺏ ( ﻣﻘﺪﺍﺭﻱ ﺍﺯ ﻭﺭﻭﺩﻱ ﮔﺮﻓﺘﻪ ﻭ ﺩﺭ ‪ age‬ﻣﻲﮔﺬﺍﺭﺩ‬
‫ﺝ ( ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﺪ ﮐﻪ ﺁﻳﺎ ‪ cin‬ﺑﺰﺭﮒﺗﺮ ﺍﺯ ‪ age‬ﺍﺳﺖ‬
‫ﺩ ( ﺳﻴﻨﻮﺱ ﻣﻘﺪﺍﺭ ‪ age‬ﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻣﻲﮐﻨﺪ‬
‫‪ – 10‬ﺩﺭ ﻣﻮﺭﺩ ﺩﺳﺘﻮﺭ >‪ #include<iostream‬ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ ( ﻳﮏ ﺩﺳﺘﻮﺭ ﺧﺮﻭﺟﻲ ﺍﺳﺖ ﮐﻪ ﻋﺒﺎﺭﺕ "‪ "iostream‬ﺭﺍ ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﮐﻨﺪ‬
‫ﺏ ( ﻳﮏ ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﻩ ﺍﺳﺖ ﮐﻪ ﺳﺮﻓﺎﻳﻞ ‪ iostream‬ﺭﺍ ﻣﻌﺮﻓﻲ ﻣﻲﮐﻨﺪ‬
‫ﺝ ( ﻳﮏ ﺩﺳﺘﻮﺭ ﻭﺭﻭﺩﻱ ﺍﺳﺖ ﮐﻪ ﻣﻘﺪﺍﺭ ﺩﺭﻳﺎﻓﺘﻲ ﺭﺍ ﺩﺭ ﻣﺘﻐﻴﺮ ‪ iostream‬ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ‬
‫ﺩ ( ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﻣﻌﺘﺒﺮ ﻧﻴﺴﺖ ﺯﻳﺮﺍ ﻋﻼﻣﺖ ﺳﻤﻴﮑﻮﻟﻦ ﻧﺪﺍﺭﺩ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪22‬‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪ ‐1‬ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ ﭼﺮﺍ ﺑﻪ ‪ C++‬ﻳﮏ ﺯﺑﺎﻥ ﺳﻄﺢ ﻣﺘﻮﺳﻂ ﻣﻲﮔﻮﻳﻨﺪ؟‬
‫‪ ‐2‬ﻳﮏ ﺗﻮﺿﻴﺢ ﺣﺎﻟﺖ ‪ C‬ﺑﺎ ﻳﮏ ﺗﻮﺿﻴﺢ ﺣﺎﻟﺖ ‪ C++‬ﭼﻪ ﺗﻔﺎﻭﺕﻫﺎﻳﻲ ﺩﺍﺭﺩ؟‬
‫‪ ‐3‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﺴﺖ؟‬
‫>‪#include <iostream‬‬
‫)(‪int main‬‬
‫‪{ //prints "Hello, World!" :‬‬
‫"‪cout << "Hello, World!\n‬‬
‫;‪return 0‬‬
‫}‬

‫‪ ‐4‬ﺩﺭ ﺗﻮﺿﻴﺢ ﺣﺎﻟﺖ ‪ C‬ﺯﻳﺮ ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ؟‬


‫;"‪cout << "Hello, /* change? */ world.\n‬‬

‫‪ ‐5‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺖ؟‬


‫>‪#include <iostream‬‬
‫‪int main‬‬
‫‪{ //prints "n = 22":‬‬
‫;‪n = 22‬‬
‫;‪cout << "n = << n << endl‬‬
‫;‪return 0‬‬
‫}‬

‫‪ ‐6‬ﺩﺭ ﺩﺳﺘﻮﺭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺯﻳﺮ ﭼﻪ ﺍﺷﮑﺎﻟﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ؟‬


‫;‪int k=6, age=20, grade=1, A+ =20‬‬

‫‪ ‐7‬ﺩﺭ ﮐﺪ ﺯﻳﺮ ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﻫﺴﺖ؟‬


‫;‪int Grade‬‬
‫;‪grade = 18‬‬

‫‪ ‐8‬ﻗﻄﻌﻪ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺭﺍ ﺍﺻﻼﺡ ﮐﻨﻴﺪ‪:‬‬


‫)(‪int main‬‬
‫;"‪cout >> "Enter a number:‬‬
‫;‪cin >> n‬‬
‫‪cout >> "Your number is" >> n >> endl‬‬
‫‪23‬‬ ‫ﻣﻘﺪﻣﺎت ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﯽ ﺑﺎ ‪C++‬‬ ‫ﻓﺼﻞ اول ‪/‬‬

‫‪ ‐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 , \' , \" , \\ ,‬‬

‫‪ ‐5‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ ﻛﻪ ﻣﺠﻤﻮﻉ‪ ،‬ﺗﻔﺎﺿﻞ‪ ،‬ﺣﺎﺻﻞﺿﺮﺏ‪ ،‬ﺧﺎﺭﺝﻗﺴﻤﺖ ﻭ‬


‫ﺑﺎﻗﻴﻤﺎﻧﺪۀ ﺩﻭ ﻋﺪﺩ ‪ 60‬ﻭ ‪ 7‬ﺭﺍ ﭼﺎﭖ ﮐﻨﺪ‪.‬‬
‫‪ ‐6‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﮐﻨﻴﺪ ﮐﻪ ﺩﻭ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺯ ﻭﺭﻭﺩﻱ ﮔﺮﻓﺘﻪ ﻭ ﻣﺠﻤﻮﻉ‪،‬‬
‫ﺗﻔﺎﺿﻞ‪ ،‬ﺣﺎﺻﻞﺿﺮﺏ‪ ،‬ﺧﺎﺭﺝﻗﺴﻤﺖ ﻭ ﺑﺎﻗﻴﻤﺎﻧﺪۀ ﺁﻥ ﺩﻭ ﻋﺪﺩ ﺭﺍ ﭼﺎﭖ ﮐﻨﺪ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪24‬‬
‫ﻓﺼﻞ ﺩﻭﻡ‬
‫»ﺍﻧﻮﺍﻉ ﺍﺻﻠﻲ«‬

‫‪ 2 – 1‬ﺍﻧﻮﺍﻉ ﺩﺍﺩۀ ﻋﺪﺩﻱ‬


‫ﻣﺎ ﺩﺭ ﺯﻧﺪﮔﻲ ﺭﻭﺯﻣﺮﻩ ﺍﺯ ﺩﺍﺩﻩﻫﺎﻱ ﻣﺨﺘﻠﻔﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪ :‬ﺍﻋﺪﺍﺩ ‪ ،‬ﺗﺼﺎﻭﻳﺮ‪،‬‬
‫ﻧﻮﺷﺘﻪﻫﺎ ﻳﺎ ﺣﺮﻭﻑ ﺍﻟﻔﺒﺎ‪ ،‬ﺻﺪﺍﻫﺎ‪ ،‬ﺑﻮﻫﺎ ﻭ ‪ . ...‬ﺑﺎ ﭘﺮﺩﺍﺯﺵ ﺍﻳﻦ ﺩﺍﺩﻩﻫﺎ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺗﺼﻤﻴﻤﺎﺗﻲ‬
‫ﺍﺗﺨﺎﺫ ﮐﻨﻴﻢ‪ ،‬ﻋﮑﺲﺍﻟﻌﻤﻞﻫﺎﻳﻲ ﻧﺸﺎﻥ ﺩﻫﻴﻢ ﻭ ﻣﺴﺎﻟﻪﺍﻱ ﺭﺍ ﺣﻞ ﮐﻨﻴﻢ‪ .‬ﺭﺍﻳﺎﻧﻪﻫﺎ ﻧﻴﺰ ﻗﺮﺍﺭ ﺍﺳﺖ‬
‫ﻫﻤﻴﻦ ﮐﺎﺭ ﺭﺍ ﺍﻧﺠﺎﻡ ﺩﻫﻨﺪ‪ .‬ﻳﻌﻨﻲ ﺩﺍﺩﻩﻫﺎﻳﻲ ﺭﺍ ﺑﮕﻴﺮﻧﺪ‪ ،‬ﺁﻥﻫﺎ ﺭﺍ ﺑﻪ ﺷﮑﻠﻲ ﮐﻪ ﻣﺎ ﺗﻌﻴﻴﻦ‬
‫ﻣﻲﮐﻨﻴﻢ ﭘﺮﺩﺍﺯﺵ ﮐﻨﻨﺪ ﻭ ﺩﺭ ﻧﺘﻴﺠﻪ ﺍﻃﻼﻋﺎﺕ ﻣﻮﺭﺩ ﻧﻴﺎﺯﻣﺎﻥ ﺭﺍ ﺍﺳﺘﺨﺮﺍﺝ ﮐﻨﻨﺪ‪ .‬ﺍﻣﺎ ﺭﺍﻳﺎﻧﻪﻫﺎ‬
‫ﻳﮏ ﻣﺤﺪﻭﺩﻳﺖ ﻣﻬﻢ ﺩﺍﺭﻧﺪ‪ :‬ﻓﻘﻂ ﺍﻋﺪﺍﺩ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻨﺪ ﭘﺮﺩﺍﺯﺵ ﮐﻨﻨﺪ‪ .‬ﭘﺲ ﻫﺮ ﺩﺍﺩﻩﺍﻱ ﺑﺮﺍﻱ‬
‫ﺍﻳﻦ ﮐﻪ ﻗﺎﺑﻞ ﭘﺮﺩﺍﺯﺵ ﺑﺎﺷﺪ ﺑﺎﻳﺪ ﺗﺒﺪﻳﻞ ﺑﻪ ﻋﺪﺩ ﺷﻮﺩ‪ .‬ﻣﻤﮑﻦ ﺍﺳﺖ ﻋﺠﻴﺐ ﺑﻪ ﻧﻈﺮ ﺑﺮﺳﺪ ﮐﻪ‬
‫ﻣﺜﻼ ﺻﺪﺍ ﻳﺎ ﺗﺼﻮﻳﺮ ﺭﺍ ﭼﻄﻮﺭ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺍﻋﺪﺍﺩ ﺗﺒﺪﻳﻞ ﮐﺮﺩ ﺍﻣﺎ ﺍﻳﻦ ﮐﺎﺭ ﻭﺍﻗﻌﺎ ﺩﺭ ﺭﺍﻳﺎﻧﻪﻫﺎ‬
‫ﺍﻧﺠﺎﻡ ﻣﻲﮔﻴﺮﺩ ﻭ ﻫﺮ ﻧﻮﻉ ﺩﺍﺩﻩﺍﻱ ﺑﻪ ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﺻﻔﺮﻫﺎ ﻭ ﻳﮏﻫﺎ ﮐﻪ »ﺍﻋﺪﺍﺩ ﺩﻭﺩﻭﻳﻲ‪«1‬‬
‫ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﻧﺪ‪ ،‬ﺗﺒﺪﻳﻞ ﻣﻲﮔﺮﺩﺩ‪ .‬ﺳﺮ ﻭ ﮐﺎﺭ ﺩﺍﺷﺘﻦ ﺑﺎ ﺍﻋﺪﺍﺩﻱ ﮐﻪ ﻓﻘﻂ ﺍﺯ ﺻﻔﺮﻫﺎ ﻭ‬
‫ﻳﮏﻫﺎﻱ ﻃﻮﻻﻧﻲ ﺗﺸﮑﻴﻞ ﺷﺪﻩﺍﻧﺪ ﺑﺴﻴﺎﺭ ﮔﻴﺞﮐﻨﻨﺪﻩ ﻭ ﻭﻗﺖﮔﻴﺮ ﺍﺳﺖ‪ .‬ﻋﻼﻭﻩ ﺑﺮ ﺍﻳﻦ ﻣﺎﻳﻠﻴﻢ‬
‫ﮐﻪ ﺑﺎ ﺩﺍﺩﻩﻫﺎﻱ ﻭﺍﻗﻌﻲ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎ ﮐﺎﺭ ﮐﻨﻴﻢ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﺭ ﺯﺑﺎﻥﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‪ ،‬ﺍﻳﻦ ﺗﺒﺪﻳﻞ‬

‫‪1 – Binary‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪26‬‬

‫ﺩﺍﺩﻩﻫﺎ ﺑﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﻭﺍﮔﺬﺍﺭ ﺷﺪﻩ ﺍﺳﺖ ﻭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺑﺎ ﺧﻴﺎﻝ ﺭﺍﺣﺖ ﻣﻲﺗﻮﺍﻧﺪ ﺍﻧﻮﺍﻉ ﻭﺍﻗﻌﻲ‬
‫ﺭﺍ ﮐﻪ ﺁﻥ ﺯﺑﺎﻥ ﺩﺭ ﺍﺧﺘﻴﺎﺭ ﻣﻲﮔﺬﺍﺭﺩ ﺑﻪ ﮐﺎﺭ ﺑﺮﺩ‪ .‬ﻭﻗﺘﻲ ﺑﺮﻧﺎﻣﻪ ﮐﺎﻣﭙﺎﻳﻞ ﺷﺪ‪ ،‬ﺍﻳﻦ ﺩﺍﺩﻩﻫﺎ ﺧﻮﺩ‬
‫ﺑﻪ ﺧﻮﺩ ﺑﻪ ﺍﻋﺪﺍﺩ ﺩﻭﺩﻭﻳﻲ ﺗﺒﺪﻳﻞ ﻣﻲﺷﻮﻧﺪ‪.‬‬
‫ﺩﺭ ‪ C++‬ﺩﻭ ﻧﻮﻉ ﺍﺻﻠﻲ ﺩﺍﺩﻩ ﻭﺟﻮﺩ ﺩﺍﺭﺩ‪» :‬ﻧﻮﻉ ﺻﺤﻴﺢ‪ «1‬ﻭ »ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‪.«2‬‬
‫ﻫﻢۀ ﺍﻧﻮﺍﻉ ﺩﻳﮕﺮ ﺍﺯ ﺭﻭﻱ ﺍﻳﻦ ﺩﻭ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﻧﺪ )ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ(‪.‬‬

‫اﻧﻮاع اﺻﻠﯽ‬ ‫ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﺮﺍﻱ ﻧﮕﻬﺪﺍﺭﻱ‬


‫اﻧﻮاع ﺻﺤﻴﺢ‬ ‫ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ )ﺍﻋﺪﺍﺩ ‪ 0‬ﻭ ‪ 1‬ﻭ ‪ 2‬ﻭ‬
‫ﻧﻮع ‪boolean‬‬
‫‪bool‬‬
‫ﻧﻮع ﴰﺎرﺷﯽ‬
‫‪ (...‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﺍﻋﺪﺍﺩ ﺑﻴﺸﺘﺮ‬
‫‪enum‬‬
‫ﻧﻮع ﮐﺎراﮐﱰی‬
‫ﺑﺮﺍﻱ ﺷﻤﺎﺭﺵ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ﻭ‬
‫‪char‬‬
‫‪unsigned char‬‬
‫ﺩﺍﻣﻨﻪ ﻣﺤﺪﻭﺩﻱ ﺩﺍﺭﻧﺪ‪.‬‬
‫‪wchar_t‬‬
‫ﻧﻮع ﻋﺪدی ﺻﺤﻴﺢ‬ ‫ﺑﺮﺍﻱ‬ ‫ﺷﻨﺎﻭﺭ‬ ‫ﻣﻤﻴﺰ‬ ‫ﻧﻮﻉ‬
‫‪short‬‬
‫‪int‬‬ ‫ﻧﮕﻬﺪﺍﺭﻱ ﺍﻋﺪﺍﺩ ﺍﻋﺸﺎﺭﻱ ﺍﺳﺘﻔﺎﺩﻩ‬
‫‪long‬‬
‫‪unsigned short‬‬
‫‪unsigned int‬‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺍﻋﺪﺍﺩ ﺍﻋﺸﺎﺭﻱ ﺑﻴﺸﺘﺮ ﺑﺮﺍﻱ‬
‫‪unsigned long‬‬
‫اﻧﻮاع ﳑﻴﺰ ﺷﻨﺎور‬ ‫ﺍﻧﺪﺍﺯﻩﮔﻴﺮﻱ ﺩﻗﻴﻖ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ﻭ‬
‫‪float‬‬
‫‪double‬‬ ‫ﺩﺍﻣﻦۀ ﺑﺰﺭﮒﺗﺮﻱ ﺩﺍﺭﻧﺪ‪ .‬ﻳﮏ ﻋﺪﺩ‬
‫‪long double‬‬
‫ﺭﺍ‬ ‫‪187/352‬‬ ‫ﻣﺜﻞ‬ ‫ﺍﻋﺸﺎﺭﻱ‬
‫ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺷﮑﻞ ‪ 18/7352×10‬ﻳﺎ‬
‫‪‐1‬‬
‫ﻳﺎ‬ ‫‪1/87352×102‬‬
‫‪ 1873/52×10‬ﻳﺎ ‪ 18735/2×10‐2‬ﻭ ﻳﺎ ‪ ...‬ﻧﻮﺷﺖ‪ .‬ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺑﺎ ﮐﻢ ﻭ ﺯﻳﺎﺩ ﮐﺮﺩﻥ‬
‫ﺗﻮﺍﻥ ﻋﺪﺩ ‪ 10‬ﻣﻤﻴﺰ ﻋﺪﺩ ﻧﻴﺰ ﺟﺎﺑﻪﺟﺎ ﻣﻲﺷﻮﺩ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺍﻋﺪﺍﺩ ﺍﻋﺸﺎﺭﻱ‬
‫»ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ« ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬

‫‪ 2 – 2‬ﻣﺘﻐﻴﺮ ﻋﺪﺩ ﺻﺤﻴﺢ‬


‫‪ C++‬ﺷﺶ ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﻋﺪﺩ ﺻﺤﻴﺢ ﺩﺍﺭﺩ ﮐﻪ ﺩﺭ ﺷﮑﻞ ﺁﻣﺪﻩ ﺍﺳﺖ‪ .‬ﺗﻔﺎﻭﺕ ﺍﻳﻦ ﺷﺶ‬
‫ﻧﻮﻉ ﻣﺮﺑﻮﻁ ﺑﻪ ﻣﻴﺰﺍﻥ ﺣﺎﻓﻆۀ ﻣﻮﺭﺩ ﺍﺳﺘﻔﺎﺩﻩ ﻭ ﻣﺤﺪﻭﺩۀ ﻣﻘﺎﺩﻳﺮﻱ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﮐﺪﺍﻡ‬

‫‪1 – Integer‬‬ ‫‪2 – Floating point‬‬


27 ‫ اﻧﻮاع اﺻﻠﯽ‬/ ‫ﻓﺼﻞ دوم‬

‫ ﺑﺴﺘﮕﻲ ﺯﻳﺎﺩﻱ‬،‫ ﺍﻳﻦ ﻣﻴﺰﺍﻥ ﺣﺎﻓﻆۀ ﻣﻮﺭﺩ ﺍﺳﺘﻔﺎﺩﻩ ﻭ ﻣﺤﺪﻭﺩۀ ﻣﻘﺎﺩﻳﺮ‬.‫ﻣﻲﺗﻮﺍﻧﻨﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ‬
‫ ﻧﻮﻉ‬،‫ ﻳﻌﻨﻲ ﻣﻤﮑﻦ ﺍﺳﺖ ﺭﻭﻱ ﻳﮏ ﺭﺍﻳﺎﻧﻪ‬.‫ﺑﻪ ﺳﺨﺖﺍﻓﺰﺍﺭ ﻭ ﻫﻤﭽﻨﻴﻦ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﺩﺍﺭﺩ‬
‫اﻧﻮاع اﺻﻠﯽ‬ ‫ ﺩﻭ ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ ﮐﻨﺪ ﺩﺭ‬int
‫اﻧﻮاع ﺻﺤﻴﺢ‬
‫ﻧﻮع ﻋﺪدی ﺻﺤﻴﺢ‬ ‫ﺣﺎﻟﻲ ﮐﻪ ﺭﻭﻱ ﺭﺍﻳﺎﻧﻪﺍﻱ ﺍﺯ ﻧﻮﻉ ﺩﻳﮕﺮ ﻧﻮﻉ‬
short
int
‫ ﺑﻪ ﭼﻬﺎﺭ ﺑﺎﻳﺖ ﺣﺎﻓﻈﻪ ﻧﻴﺎﺯ ﺩﺍﺷﺘﻪ‬int
long
unsigned short
<limits> ‫ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺳﺮﻓﺎﻳﻞ‬.‫ﺑﺎﺷﺪ‬
unsigned int
unsigned long
‫ﻣﻲﺗﻮﺍﻥ ﻣﺸﺨﺺ ﻧﻤﻮﺩ ﮐﻪ ﻫﺮ ﻧﻮﻉ ﻋﺪﺩ‬
.‫ﺻﺤﻴﺢ ﺭﻭﻱ ﺭﺍﻳﺎﻧﻪﺗﺎﻥ ﭼﻪ ﻣﺤﺪﻭﺩﻩﺍﻱ ﺩﺍﺭﺩ‬

‫ ﻣﺤﺪﻭﺩﻩﻫﺎﻱ ﻧﻮﻉ ﻋﺪﺩ ﺻﺤﻴﺢ‬2 – 1 ‫* ﻣﺜﺎﻝ‬


:‫ ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ‬C++ ‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺤﺪﻭﺩﻩﻫﺎﻱ ﺷﺶ ﻧﻮﻉ ﻋﺪﺩ ﺻﺤﻴﺢ ﺩﺭ‬
#include <iostream>
#include <limits> //defines the constants SHRT_MIN, etc.
using namespace std;
int main()
{ //prints some of the constants stored in the <limits>
header:
cout << "minimum short = " << SHRT_MIN << endl;
cout << "maximum short = " << SHRT_MAX << endl;
cout << "minimum unsigned short = 0" << endl;
cout << "maximum unsigned short = " << USHRT_MAX << endl;
cout << "minimum int = " << INT_MIN << endl;
cout << "maximum int = " << INT_MAX << endl;
cout << "minimum unsigned int = 0" << endl;
cout << "maximum unsigned int = " << UINT_MAX << endl;
cout << "minimum long = " << LONG_MIN << endl;
cout << "maximum long = " << LONG_MAX << endl;
cout << "minimum unsigned long = 0" << endl;
cout << "maximum unsigned long = " << ULONG_MAX << endl;
return 0;
}
minimum short = -32768
maximum short = 32767
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪28‬‬

‫‪minimum‬‬ ‫‪unsigned short = 0‬‬


‫‪maximum‬‬ ‫‪unsigned short = 65535‬‬
‫‪minimum‬‬ ‫‪int = -2147483648‬‬
‫‪maximum‬‬ ‫‪int = 2147483647‬‬
‫‪minimum‬‬ ‫‪unsigned int = 0‬‬
‫‪maximum‬‬ ‫‪unsigned int = 4294967295‬‬
‫‪minimum‬‬ ‫‪long = -2147483648‬‬
‫‪maximum‬‬ ‫‪long = 2147483647‬‬
‫‪minimum‬‬ ‫‪unsigned long = 0‬‬
‫‪maximum‬‬ ‫‪unsigned long = 4294967295‬‬

‫ﺳﺮﻓﺎﻳﻞ >‪ <limits‬ﺣﺎﻭﻱ ﺗﻌﺮﻳﻒ ﺷﻨﺎﺳﻪﻫﺎﻱ ‪، SHRT_MAX ، SHRT_MIN‬‬


‫‪ USHRT_MAX‬ﻭ ﺳﺎﻳﺮ ﺷﻨﺎﺳﻪﻫﺎﻳﻲ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺍﻳﻦ‬
‫ﺷﻨﺎﺳﻪﻫﺎ ﮔﺴﺘﺮﻩﺍﻱ ﮐﻪ ﻧﻮﻉ ﻋﺪﺩ ﺻﺤﻴﺢ ﻣﺮﺑﻮﻃﻪ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ‪.‬‬
‫ﻣﺜﻼ ﺷﻨﺎﺳﻪ ‪ SHRT_MIN‬ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ ‪ short‬ﺣﺪﺍﻗﻞ ﭼﻪ ﻣﻘﺪﺍﺭﻱ‬
‫ﻣﻲﺗﻮﺍﻧﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﻭ ﺷﻨﺎﺳﻪ ‪ SHRT_MAX‬ﺑﻴﺎﻥ ﻣﻲﮐﻨﺪ ﮐﻪ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ ‪short‬‬
‫ﺣﺪﺍﮐﺜﺮ ﭼﻪ ﻣﻘﺪﺍﺭﻱ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﻣﺜﺎﻝ ﺑﺎﻻ ﺭﻭﻱ ﻳﮏ ﺭﺍﻳﺎﻧﻪ ﺑﺎ ﭘﺮﺩﺍﺯﻧﺪﻩ‬
‫‪ Pentium II‬ﺑﺎ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﻭﻳﻨﺪﻭﺯ ‪ 98‬ﺍﺟﺮﺍ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺧﺮﻭﺟﻲ ﺍﻳﻦ ﻣﺜﺎﻝ ﻧﺸﺎﻥ‬
‫ﻣﻲﺩﻫﺪ ﮐﻪ ﺷﺶ ﻧﻮﻉ ﻋﺪﺩ ﺻﺤﻴﺢ ﺩﺭ ﺍﻳﻦ ﺭﺍﻳﺎﻧﻪ ﻣﺤﺪﻭﺩﻩﻫﺎﻱ ﺯﻳﺮ ﺭﺍ ﺩﺍﺭﻧﺪ‪:‬‬
‫‪short:‬‬ ‫‪ 32,767‬ﺗﺎ ‪-32,786‬‬ ‫)‪(28 ⇒ 1 byte‬‬
‫‪int:‬‬ ‫ﺗﺎ ‪-2,147,483,648‬‬ ‫‪2,147,483,647‬‬ ‫)‪(232 ⇒ 4 bytes‬‬
‫‪long:‬‬ ‫ﺗﺎ ‪-2,147,483,648‬‬ ‫‪2,147,483,647‬‬ ‫)‪(232 ⇒ 4 bytes‬‬
‫‪unsigned short:‬‬ ‫‪ 65,535‬ﺗﺎ ‪0‬‬ ‫)‪(28 ⇒ 1 byte‬‬

‫ﺑﺎ ﺩﻗﺖ ﺩﺭ ﺍﻳﻦ ﺟﺪﻭﻝ ﻣﺸﺨﺺ ﻣﻲﺷﻮﺩ ﮐﻪ ﺩﺭ ﺭﺍﻳﺎﻥۀ ﻣﺬﮐﻮﺭ‪ ،‬ﻧﻮﻉ ‪ long‬ﻣﺎﻧﻨﺪ‬
‫ﻧﻮﻉ ‪ int‬ﺍﺳﺖ ﻭ ﻧﻮﻉ ‪ unsigned long‬ﻧﻴﺰ ﻣﺎﻧﻨﺪ ‪ unsigned int‬ﺍﺳﺖ‪.‬‬
‫ﮔﺮﭼﻪ ﻣﻤﮑﻦ ﺍﺳﺖ ﺍﻳﻦ ﺍﻧﻮﺍﻉ ﺭﻭﻱ ﺭﺍﻳﺎﻧﻪﺍﻱ ﺍﺯ ﻧﻮﻉ ﺩﻳﮕﺮ ﻣﺘﻔﺎﻭﺕ ﺑﺎﺷﺪ‪.‬‬
‫ﻭﻗﺘﻲ ﺑﺮﻧﺎﻣﻪﺍﻱ ﻣﻲﻧﻮﻳﺴﻴﺪ‪ ،‬ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﻣﻨﺎﺳﺐ ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﮐﻨﻴﺪ ﺗﺎ ﻫﻢ ﺑﺮﻧﺎﻣﻪ ﺩﭼﺎﺭ ﺧﻄﺎ ﻧﺸﻮﺩ ﻭ ﻫﻢ ﺣﺎﻓﻆۀ ﺳﻴﺴﺘﻢ ﺭﺍ ﻫﺪﺭ ﻧﺪﻫﻴﺪ‪.‬‬

‫‪ 2 – 3‬ﻣﺤﺎﺳﺒﺎﺕ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ‬


‫ﺍﮐﻨﻮﻥ ﮐﻪ ﺑﺎ ﺍﻧﻮﺍﻉ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻋﺪﺩ ﺻﺤﻴﺢ ﺁﺷﻨﺎ ﺷﺪﻳﻢ‪ ،‬ﻣﻲﺧﻮﺍﻫﻴﻢ ﺍﺯ ﺍﻳﻦ ﻣﺘﻐﻴﺮﻫﺎ ﺩﺭ‬
‫ﻣﺤﺎﺳﺒﺎﺕ ﺭﻳﺎﺿﻲ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪ C++ .‬ﻣﺎﻧﻨﺪ ﺍﻏﻠﺐ ﺯﺑﺎﻥﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺒﺎﺕ‬
‫‪29‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺟﻤﻊ )‪ ، (+‬ﺗﻔﺮﻳﻖ )‪ ، (-‬ﺿﺮﺏ )*( ‪ ،‬ﺗﻘﺴﻴﻢ )‪ (/‬ﻭ ﺑﺎﻗﻴﻤﺎﻧﺪﻩ )‪ (%‬ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﻣﻲﮐﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 2‬ﻣﺤﺎﺳﺒﺎﺕ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻧﺤﻮۀ ﺍﺳﺘﻔﺎﺩﻩ ﻭ ﻋﻤﻠﮑﺮﺩ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ //tests operators +, -, *, /, and %:‬‬
‫;‪int m=54‬‬
‫;‪int n=20‬‬
‫<< " = ‪cout << "m = " << m << " and n‬‬ ‫;‪n << endl‬‬
‫;‪cout << "m+n = " << m+n << endl‬‬ ‫‪//‬‬ ‫‪54+20 = 74‬‬
‫;‪cout << "m-n = " << m-n << endl‬‬ ‫‪//‬‬ ‫‪54-20 = 34‬‬
‫;‪cout << "m*n = " << m*n << endl‬‬ ‫‪//‬‬ ‫‪54*20 = 1080‬‬
‫;‪cout << "m/n = " << m/n << endl‬‬ ‫‪//‬‬ ‫‪54/20 = 2‬‬
‫;‪cout << "m%n = " << m%n << endl‬‬ ‫‪//‬‬ ‫‪54%20 = 14‬‬
‫;‪return 0‬‬
‫}‬
‫=‪m‬‬ ‫‪54 and n = 20‬‬
‫‪m+n‬‬ ‫‪= 74‬‬
‫‪m-n‬‬ ‫‪= 34‬‬
‫‪m*n‬‬ ‫‪= 1080‬‬
‫‪m/n‬‬ ‫‪=2‬‬
‫‪m%n‬‬ ‫‪= 14‬‬

‫ﻧﺘﻴﺞۀ ﺗﻘﺴﻴﻢ ‪ m/n‬ﺟﺎﻟﺐ ﺗﻮﺟﻪ ﺍﺳﺖ‪ .‬ﺣﺎﺻﻞ ﺍﻳﻦ ﺗﻘﺴﻴﻢ ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 2‬ﺍﺳﺖ ﻧﻪ ‪ 2.7‬ﺗﻮﺟﻪ‬
‫ﺑﻪ ﺍﻳﻦ ﻣﻄﻠﺐ ﺑﺴﻴﺎﺭ ﻣﻬﻢ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺍﻣﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺣﺎﺻﻞ ﺗﻘﺴﻴﻢ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ‬
‫ﺑﺮ ﻋﺪﺩ ﺻﺤﻴﺢ ﺩﻳﮕﺮ‪ ،‬ﻫﻤﻮﺍﺭﻩ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺳﺖ ﻧﻪ ﻋﺪﺩ ﺍﻋﺸﺎﺭﻱ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺑﻪ‬
‫ﺣﺎﺻﻞ ‪ m%n‬ﻧﻴﺰ ﺩﻗﺖ ﮐﻨﻴﺪ‪ .‬ﻋﻤﻠﮕﺮ ‪ %‬ﺑﺎﻗﻴﻤﺎﻧﺪۀ ﺗﻘﺴﻴﻢ ﺭﺍ ﺑﻪ ﺩﺳﺖ ﻣﻲﺩﻫﺪ‪ .‬ﻳﻌﻨﻲ ﺣﺎﺻﻞ‬
‫ﻋﺒﺎﺭﺕ ‪ 54%20‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 14‬ﺍﺳﺖ ﮐﻪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ‪ ،‬ﺑﺎﻗﻴﻤﺎﻧﺪۀ ﺗﻘﺴﻴﻢ ‪ 54‬ﺑﺮ ‪ 20‬ﺍﺳﺖ‪.‬‬

‫‪ 2 – 4‬ﻋﻤﻠﮕﺮﻫﺎﻱ ﺍﻓﺰﺍﻳﺸﻲ ﻭ ﮐﺎﻫﺸﻲ‬


‫‪ C++‬ﺑﺮﺍﻱ ﺩﺳﺘﮑﺎﺭﻱ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺻﺤﻴﺢ‪ ،‬ﺩﻭ ﻋﻤﻠﮕﺮ ﺟﺎﻟﺐ ﺩﻳﮕﺮ ﺩﺍﺭﺩ‪:‬‬
‫ﻋﻤﻠﮕﺮ ‪ ++‬ﻣﻘﺪﺍﺭ ﻳﮏ ﻣﺘﻐﻴﺮ ﺭﺍ ﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ ﻭ ﻋﻤﻠﮕﺮ ‪ –-‬ﻣﻘﺪﺍﺭ ﻳﮏ ﻣﺘﻐﻴﺮ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪30‬‬

‫ﺭﺍ ﻳﮏ ﻭﺍﺣﺪ ﮐﺎﻫﺶ ﻣﻲﺩﻫﺪ‪ .‬ﺍﻣﺎ ﻫﺮ ﮐﺪﺍﻡ ﺍﺯ ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﺩﻭ ﺷﮑﻞ ﻣﺘﻔﺎﻭﺕ ﺩﺍﺭﻧﺪ‪:‬‬
‫ﺷﮑﻞ »ﭘﻴﺸﻮﻧﺪﻱ« ﻭ ﺷﮑﻞ »ﭘﺴﻮﻧﺪﻱ«‪.‬‬
‫ﺩﺭ ﺷﮑﻞ ﭘﻴﺸﻮﻧﺪﻱ‪ ،‬ﻋﻤﻠﮕﺮ ﻗﺒﻞ ﺍﺯ ﻧﺎﻡ ﻣﺘﻐﻴﺮ ﻣﻲﺁﻳﺪ ﻣﺜﻞ ‪ ++m‬ﻳﺎ ‪ . --n‬ﺩﺭ ﺷﮑﻞ‬
‫ﭘﺴﻮﻧﺪﻱ‪ ،‬ﻋﻤﻠﮕﺮ ﺑﻌﺪ ﺍﺯ ﻧﺎﻡ ﻣﺘﻐﻴﺮ ﻣﻲﺁﻳﺪ ﻣﺜﻞ ‪ m++‬ﻳﺎ ‪ . n--‬ﺗﻔﺎﻭﺕ ﺷﮑﻞ ﭘﻴﺸﻮﻧﺪﻱ ﺑﺎ‬
‫ﺷﮑﻞ ﭘﺴﻮﻧﺪﻱ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﺷﮑﻞ ﭘﻴﺸﻮﻧﺪﻱ ﺍﺑﺘﺪﺍ ﻣﺘﻐﻴﺮ‪ ،‬ﻣﺘﻨﺎﺳﺐ ﺑﺎ ﻋﻤﻠﮕﺮ‪،‬‬
‫ﺍﻓﺰﺍﻳﺶ ﻳﺎ ﮐﺎﻫﺶ ﻣﻲﻳﺎﺑﺪ ﻭ ﭘﺲ ﺍﺯ ﺁﻥ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺒﺎﺕ ﺩﻳﮕﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ‬
‫ﻭﻟﻲ ﺩﺭ ﺷﮑﻞ ﭘﺴﻮﻧﺪﻱ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺕ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ ﻭ ﭘﺲ ﺍﺯ ﺁﻥ ﻣﻘﺪﺍﺭ‬
‫ﻣﺘﻐﻴﺮ ﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﺍﻳﺶ ﻳﺎ ﮐﺎﻫﺶ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺑﺮﺍﻱ ﺩﺭﮎ ﺑﻬﺘﺮ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ‬
‫ﺗﻮﺟﻪ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 3‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﻭ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ‬


‫)(‪int main‬‬
‫‪{ //shows the difference between m++ and ++m:‬‬
‫;‪int m, n‬‬
‫;‪m = 75‬‬
‫;‪n = ++m‬‬ ‫‪// the pre-increment operator is applied to m‬‬
‫;‪cout << "m = " << m << ", n = " << n << endl‬‬
‫;‪m = 75‬‬
‫;‪n = m++‬‬ ‫‪// the post-increment operator is apllied to m‬‬
‫;‪cout << "m = " << m << ", n = " << n << endl‬‬
‫;‪return 0‬‬
‫}‬
‫‪m = 45, n = 45‬‬
‫‪m = 45, n = 44‬‬

‫ﺩﺭ ﺧﻂ ﭘﻨﺠﻢ ﺑﺮﻧﺎﻣﻪ ﻳﻌﻨﻲ ﺩﺭ ﻋﺒﺎﺭﺕ‬


‫;‪n = ++m‬‬

‫ﺍﺯ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﭘﺲ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ ‪ m‬ﺑﻪ ‪ 76‬ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ ﻭ‬
‫ﺳﭙﺲ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﻪ ‪ n‬ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﻭﻗﺘﻲ ﺩﺭ ﺧﻂ ﺷﺸﻢ ﻣﻘﺪﺍﺭ ﺍﻳﻦ ﺩﻭ ﻣﺘﻐﻴﺮ‬
‫ﭼﺎﭖ ﻣﻲﺷﻮﺩ‪ m = 76 ،‬ﻭ ‪ n = 76‬ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪.‬‬
‫‪31‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫ﺩﺭ ﺧﻂ ﻫﺸﺘﻢ ﺑﺮﻧﺎﻣﻪ ﻳﻌﻨﻲ ﺩﺭ ﻋﺒﺎﺭﺕ ;‪ n = m++‬ﺍﺯ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ‬


‫ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺑﻨﺎ ﺑﺮ ﺍﻳﻦ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ ‪ m‬ﮐﻪ ‪ 75‬ﺍﺳﺖ ﺑﻪ ‪ n‬ﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﺪ ﻭ ﭘﺲ ﺍﺯ‬
‫ﺁﻥ ﻣﻘﺪﺍﺭ ‪ m‬ﺑﻪ ‪ 76‬ﺍﻓﺰﺍﻳﺶ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﭘﺲ ﻭﻗﺘﻲ ﺩﺭ ﺧﻂ ﻧﻬﻢ ﺑﺮﻧﺎﻣﻪ ﻣﻘﺪﺍﺭ ﺍﻳﻦ ﺩﻭ‬
‫ﻣﺘﻐﻴﺮ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‪ m = 76 ،‬ﺍﺳﺖ ﻭﻟﻲ ‪ n = 75‬ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪.‬‬
‫ﻋﻤﻠﮕﺮﻫﺎﻱ ﺍﻓﺰﺍﻳﺸﻲ ﻭ ﮐﺎﻫﺸﻲ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ‪ C++‬ﻓﺮﺍﻭﺍﻥ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ‪ .‬ﮔﺎﻫﻲ‬
‫ﺑﻪ ﺷﮑﻞ ﭘﻴﺸﻮﻧﺪﻱ ﻭ ﮔﺎﻫﻲ ﺑﻪ ﺷﮑﻞ ﭘﺴﻮﻧﺪﻱ؛ ﺍﻳﻦ ﺑﺴﺘﮕﻲ ﺑﻪ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ ﺩﺍﺭﺩ ﮐﻪ ﮐﺠﺎ‬
‫ﺍﺯ ﮐﺪﺍﻡ ﻧﻮﻉ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪.‬‬

‫‪ 2 – 5‬ﻋﻤﻠﮕﺮﻫﺎﻱ ﻣﻘﺪﺍﺭﮔﺬﺍﺭﻱ ﻣﺮﮐﺐ‬


‫ﺑﺮﺍﻱ ﻣﻘﺪﺍﺭﮔﺬﺍﺭﻱ ﺩﺭ ﻣﺘﻐﻴﺮﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻳﻢ‪ .‬ﻣﺜﻼ ﺩﺳﺘﻮﺭ‬ ‫ﻗﺒﻼ ﺍﺯ ﻋﻤﻠﮕﺮ =‬
‫;‪ m=75‬ﻣﻘﺪﺍﺭ ‪ 75‬ﺭﺍ ﺩﺭﻭﻥ ‪ m‬ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﻭ ﻫﻤﭽﻨﻴﻦ ﺩﺳﺘﻮﺭ ;‪ m = m+8‬ﻣﻘﺪﺍﺭ ‪m‬‬
‫ﺭﺍ ﻫﺸﺖ ﻭﺍﺣﺪ ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ‪ C++ .‬ﻋﻤﻠﮕﺮﻫﺎﻱ ﺩﻳﮕﺮﻱ ﺩﺍﺭﺩ ﮐﻪ ﻣﻘﺪﺍﺭﮔﺬﺍﺭﻱ ﺩﺭ‬
‫ﻣﺘﻐﻴﺮﻫﺎ ﺭﺍ ﺗﺴﻬﻴﻞ ﻣﻲﻧﻤﺎﻳﻨﺪ‪ .‬ﻣﺜﻼ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ =‪ +‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﻫﺸﺖ ﻭﺍﺣﺪ ﺑﻪ ‪m‬‬
‫;‪m += 8‬‬ ‫ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ ﺍﻣﺎ ﺑﺎ ﺩﺳﺘﻮﺭ ﮐﻮﺗﺎﻩﺗﺮ‪:‬‬
‫ﺩﺳﺘﻮﺭ ﺑﺎﻻ ﻣﻌﺎﺩﻝ ﺩﺳﺘﻮﺭ ;‪ m = m + 8‬ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﮐﻮﺗﺎﻩﺗﺮ ﺍﺳﺖ‪ .‬ﺑﻪ‬
‫ﻋﻤﻠﮕﺮ =‪» +‬ﻋﻤﻠﮕﺮ ﻣﺮﮐﺐ« ﻣﻲﮔﻮﻳﻨﺪ ﺯﻳﺮﺍ ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ‪ +‬ﻭ = ﻣﻲﺑﺎﺷﺪ‪.‬‬
‫=‪%‬‬ ‫=‪ +‬ﻭ =‪ -‬ﻭ =* ﻭ =‪ /‬ﻭ‬ ‫ﭘﻨﺞ ﻋﻤﻠﮕﺮ ﻣﺮﮐﺐ ﺩﺭ ‪ C++‬ﻋﺒﺎﺭﺗﻨﺪ ﺍﺯ‪:‬‬
‫ﻧﺤﻮۀ ﻋﻤﻞ ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫‪m‬‬ ‫=‪+‬‬ ‫;‪8‬‬ ‫→‬ ‫‪m‬‬ ‫=‬ ‫‪m‬‬ ‫‪+‬‬ ‫;‪8‬‬
‫‪m‬‬ ‫=‪-‬‬ ‫;‪8‬‬ ‫→‬ ‫‪m‬‬ ‫=‬ ‫‪m‬‬ ‫‪-‬‬ ‫;‪8‬‬
‫‪m‬‬ ‫=*‬ ‫;‪8‬‬ ‫→‬ ‫‪m‬‬ ‫=‬ ‫‪m‬‬ ‫*‬ ‫;‪8‬‬
‫‪m‬‬ ‫=‪/‬‬ ‫;‪8‬‬ ‫→‬ ‫‪m‬‬ ‫=‬ ‫‪m‬‬ ‫‪/‬‬ ‫;‪8‬‬
‫‪m‬‬ ‫=‪%‬‬ ‫;‪8‬‬ ‫→‬ ‫‪m‬‬ ‫=‬ ‫‪m‬‬ ‫‪%‬‬ ‫;‪8‬‬

‫ﻣﺜﺎﻝ ﺯﻳﺮ‪ ،‬ﮐﺎﺭ ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 4‬ﮐﺎﺭﺑﺮﺩ ﻋﻤﻠﮕﺮﻫﺎﻱ ﻣﺮﮐﺐ‬


‫)(‪int main‬‬
‫‪{ //tests arithmetic assignment operators:‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪32‬‬

‫;‪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 – 6‬ﺍﻧﻮﺍﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬


‫ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺑﻪ ﺑﻴﺎﻥ ﺳﺎﺩﻩ ﻫﻤﺎﻥ ﻋﺪﺩ ﺍﻋﺸﺎﺭﻱ ﺍﺳﺖ‪ .‬ﻋﺪﺩﻱ ﻣﺜﻞ ‪123.45‬‬
‫ﻳﮏ ﻋﺪﺩ ﺍﻋﺸﺎﺭﻱ ﺍﺳﺖ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﺍﻳﻦ ﻋﺪﺩ ﺩﺭ ﺭﺍﻳﺎﻧﻪ ﺫﺧﻴﺮﻩ ﺷﻮﺩ‪ ،‬ﺍﺑﺘﺪﺍ ﺑﺎﻳﺪ ﺑﻪ‬
‫ﺷﮑﻞ ﺩﻭﺩﻭﻳﻲ ﺗﺒﺪﻳﻞ ﺷﻮﺩ‪:‬‬
‫‪123.45 = 1111011.01110012‬‬

‫ﺍﮐﻨﻮﻥ ﺑﺮﺍﻱ ﻣﺸﺨﺺ ﻧﻤﻮﺩﻥ ﻣﺤﻞ ﺍﻋﺸﺎﺭ ﺩﺭ ﻋﺪﺩ‪ ،‬ﺗﻤﺎﻡ ﺭﻗﻢﻫﺎ ﺭﺍ ﺑﻪ ﺳﻤﺖ ﺭﺍﺳﺖ ﻣﻤﻴﺰ‬
‫ﻣﻨﺘﻘﻞ ﻣﻲﮐﻨﻴﻢ‪ .‬ﺍﻟﺒﺘﻪ ﺑﺎ ﻫﺮ ﺟﺎﺑﺠﺎﻳﻲ ﻣﻤﻴﺰ‪ ،‬ﻋﺪﺩ ﺣﺎﺻﻞ ﺑﺎﻳﺪ ﺩﺭ ﺗﻮﺍﻧﻲ ﺍﺯ ‪ 2‬ﺿﺮﺏ ﺷﻮﺩ‪:‬‬
‫‪123.45 = 0.11110110111001 × 27‬‬

‫ﺑﻪ ﻣﻘﺪﺍﺭ ‪» 11110110111001‬ﻣﺎﻧﺘﻴﺲ ﻋﺪﺩ« ﻭ ﺑﻪ ‪ 7‬ﮐﻪ ﺗﻮﺍﻥ ﺭﻭﻱ ﺩﻭ ﺍﺳﺖ‪» ،‬ﻧﻤﺎﻱ‬


‫ﻋﺪﺩ« ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺍﺯ ﺁﻥﺟﺎ ﮐﻪ ﻣﻤﻴﺰ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺷﮑﻞ ﺷﻨﺎﻭﺭ ﺟﺎﺑﺠﺎ ﺷﻮﺩ‪ ،‬ﺑﻪ ﺍﻋﺪﺍﺩ‬
‫ﺍﻋﺸﺎﺭﻱ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺣﺎﻝ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻋﺪﺩ ﻣﻔﺮﻭﺽ ﮐﺎﻓﻲ ﺍﺳﺖ‬
‫‪33‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫ﮐﻪ ﻣﺎﻧﺘﻴﺲ ﻭ ﻧﻤﺎ ﺭﺍ ﺫﺧﻴﺮﻩ ﮐﻨﻴﻢ‪ .‬ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺑﺨﻮﺍﻫﻴﻢ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺫﺧﻴﺮﻩ ﺷﺪﻩ ﺭﺍ ﺑﺎﺯﻳﺎﺑﻲ‬
‫ﮐﻨﻴﻢ‪ ،‬ﺳﻴﺴﺘﻢﻋﺎﻣﻞ ﻧﻤﺎ ﻭ ﻣﺎﻧﺘﻴﺲ ﺭﺍ ﺩﺭ ﻣﺴﻴﺮﻱ ﻋﮑﺲ ﻣﺴﻴﺮ ﺑﺎﻻ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﺩ ﺗﺎ ﻋﺪﺩ‬
‫‪ 123.45‬ﺭﺍ ﺍﺯ ﺭﻭﻱ ﺁﻥ ﺩﻭﺑﺎﺭﻩ ﺑﺴﺎﺯﺩ‪ .‬ﺩﺭ ﻣﻮﺭﺩ ﻋﺪﺩﻱ ﻣﺜﻞ ﻋﺪﺩ ﻣﺬﮐﻮﺭ ﻣﻤﮑﻦ ﺍﺳﺖ‬
‫ﺍﻳﻦ ﺭﻭﺵ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ‪ ،‬ﻃﻮﻻﻧﻲ ﻭ ﺑﻲﻣﻮﺭﺩ ﺑﻪ ﻧﻈﺮ ﺑﺮﺳﺪ‪ .‬ﺍﻣﺎ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺷﺎﻣﻞ‬
‫ﺍﻋﺪﺍﺩ ﺧﻴﻠﻲ ﮐﻮﭼﮏ ﻣﺜﻞ ‪ 0.000000001‬ﻳﺎ ﺍﻋﺪﺍﺩ ﺧﻴﻠﻲ ﺑﺰﺭﮒ ﻣﺜﻞ‬
‫‪ 100000000.00000002‬ﻫﺴﺘﻨﺪ ﮐﻪ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻭ ﺍﻧﺠﺎﻡ ﻣﺤﺎﺳﺒﺎﺕ ﺭﻳﺎﺿﻲ ﺭﻭﻱ‬
‫ﺁﻥﻫﺎ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺎﻧﺘﻴﺲ ﻭ ﻧﻤﺎ ﺑﺴﻴﺎﺭ ﺁﺳﺎﻥﺗﺮ ﺍﺳﺖ‪.‬‬
‫ﺩﺭ ‪ C++‬ﺳﻪ ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﻭﺟﻮﺩ ﺩﺍﺭﺩ‪ :‬ﻧﻮﻉ ‪ float‬ﻭ ﻧﻮﻉ ‪ double‬ﻭ ﻧﻮﻉ‬
‫‪. long double‬‬
‫ﻣﻌﻤﻮﻻ ﻧﻮﻉ ‪ float‬ﺍﺯ ﭼﻬﺎﺭ ﺑﺎﻳﺖ ﺑﺮﺍﻱ ﻧﮕﻬﺪﺍﺭﻱ ﻋﺪﺩ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ‪ ،‬ﻧﻮﻉ‬
‫‪ double‬ﺍﺯ ﻫﺸﺖ ﺑﺎﻳﺖ ﻭ ﻧﻮﻉ ‪ long double‬ﺍﺯ ﻫﺸﺖ ﻳﺎ ﺩﻩ ﻳﺎ ﺩﻭﺍﺯﺩﻩ ﻳﺎ ﺷﺎﻧﺰﺩﻩ‬
‫ﺑﺎﻳﺖ‪ .‬ﺩﺭ ﻳﮏ ‪ 32 float‬ﺑﻴﺘﻲ )ﭼﻬﺎﺭ ﺑﺎﻳﺘﻲ( ﺍﺯ ‪ 23‬ﺑﻴﺖ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻣﺎﻧﺘﻴﺲ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ‪ 8‬ﺑﻴﺖ ﻧﻴﺰ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻧﻤﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ ﻭ ﻳﮏ ﺑﻴﺖ ﻧﻴﺰ‬
‫ﻋﻼﻣﺖ ﻋﺪﺩ ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﮐﻨﺪ‪.‬‬
‫ﺩﺭ ﻳﮏ ‪ 64 double‬ﺑﻴﺘﻲ )ﻫﺸﺖ ﺑﺎﻳﺘﻲ( ﺍﺯ ‪ 52‬ﺑﻴﺖ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻣﺎﻧﺘﻴﺲ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ‪ 11‬ﺑﻴﺖ ﺑﺮﺍﻱ ﻧﮕﻬﺪﺍﺭﻱ ﻧﻤﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ ﻭ ﻳﮏ ﺑﻴﺖ ﻧﻴﺰ ﻋﻼﻣﺖ‬
‫ﻋﺪﺩ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫‪ 2 – 7‬ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬


‫ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﻣﺎﻧﻨﺪ ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮ ﺻﺤﻴﺢ ﺍﺳﺖ‪ .‬ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﺍﺯ‬
‫ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ ‪ float‬ﻳﺎ ‪ double‬ﺑﺮﺍﻱ ﻣﺸﺨﺺ ﻧﻤﻮﺩﻥ ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪.‬‬
‫ﻣﺘﻐﻴﺮ ‪ x‬ﺭﺍ ﺍﺯ ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‪ .‬ﺩﺳﺘﻮﺭ‬ ‫;‪float x‬‬ ‫ﻣﺜﻼ ﺩﺳﺘﻮﺭ‬
‫ﻣﺘﻐﻴﺮ ‪ x‬ﺭﺍ ﺍﺯ ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺗﻌﺮﻳﻒ ﮐﺮﺩﻩ ﻭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ‬ ‫;‪float x=12.3‬‬
‫ﺩﻭ ﻣﺘﻐﻴﺮ ‪ x‬ﻭ ‪ y‬ﺭﺍ‬ ‫;‪double x,y=0‬‬ ‫‪ 12.3‬ﺭﺍ ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ‪ .‬ﺩﺳﺘﻮﺭ‬
‫ﺍﺯ ﻧﻮﻉ ‪ double‬ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﻣﻘﺪﺍﺭ ‪ x‬ﻫﻨﻮﺯ ﻣﺸﺨﺺ ﻧﻴﺴﺖ ﻭﻟﻲ ‪ y‬ﻣﻘﺪﺍﺭ ‪0.0‬‬
‫ﺩﺍﺭﺩ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪34‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 5‬ﺣﺴﺎﺏ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬


‫ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺭﺍ ﻧﻴﺰ ﻣﺜﻞ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺕ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ‪.‬‬
‫ﻣﺜﺎﻝ ﺯﻳﺮ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪ .‬ﺍﻳﻦ ﻣﺜﺎﻝ ﻣﺎﻧﻨﺪ ﻣﺜﺎﻝ ‪ 2 – 2‬ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ‬
‫ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎ ﺍﺯ ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ‪ float‬ﻫﺴﺘﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ //tests operators +, -, *, /, and %:‬‬
‫;‪float x=54.0‬‬
‫;‪float y=20.0‬‬
‫<< " = ‪cout << "x = " << x << " and y‬‬ ‫;‪y << endl‬‬
‫;‪cout << "x+y = " << x+y << endl‬‬ ‫‪//‬‬ ‫= ‪54.0+20.0‬‬ ‫‪74.0‬‬
‫;‪cout << "x-y = " << x-y << endl‬‬ ‫‪//‬‬ ‫= ‪54.0-20.0‬‬ ‫‪34.0‬‬
‫;‪cout << "x*y = " << x*y << endl‬‬ ‫‪//‬‬ ‫= ‪54.0*20.0‬‬ ‫‪1080.0‬‬
‫;‪cout << "x/y = " << x/y << endl‬‬ ‫‪//‬‬ ‫= ‪54.0/20.0‬‬ ‫‪2.7‬‬
‫;‪return 0‬‬
‫}‬
‫=‪x‬‬ ‫‪54 and y = 20‬‬
‫‪x+y‬‬ ‫‪= 74‬‬
‫‪x-y‬‬ ‫‪= 34‬‬
‫‪x*y‬‬ ‫‪= 1080‬‬
‫‪x/y‬‬ ‫‪= 2.7‬‬

‫ﺑﻪ ﭘﺎﺳﺦﻫﺎﻱ ﺑﺎﻻ ﺩﻗﺖ ﮐﻨﻴﺪ‪ :‬ﺑﺮ ﺧﻼﻑ ﺗﻘﺴﻴﻢ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ‪ ،‬ﺗﻘﺴﻴﻢ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺑﻪ‬
‫‪54.0 / 20.0 = 2.7‬‬ ‫ﺻﻮﺭﺕ ﺑﺮﻳﺪﻩﺷﺪﻩ ﻧﻴﺴﺖ‪:‬‬
‫ﺗﻔﺎﻭﺕ ﻧﻮﻉ ‪ float‬ﺑﺎ ﻧﻮﻉ ‪ double‬ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻧﻮﻉ ‪ double‬ﺩﻭ ﺑﺮﺍﺑﺮ‬
‫‪ float‬ﺍﺯ ﺣﺎﻓﻈﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ‪ .‬ﭘﺲ ﻧﻮﻉ ‪ double‬ﺩﻗﺘﻲ ﺑﺴﻴﺎﺭ ﺑﻴﺸﺘﺮ ﺍﺯ ‪float‬‬
‫ﺩﺍﺭﺩ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﻣﺤﺎﺳﺒﺎﺕ ‪ double‬ﻭﻗﺖﮔﻴﺮﺗﺮ ﺍﺯ ﻣﺤﺎﺳﺒﺎﺕ ‪ float‬ﺍﺳﺖ‪.‬‬
‫ﺑﻨﺎﺑﺮﺍﻳﻦ ﺍﮔﺮ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺘﺎﻥ ﺑﻪ ﻣﺤﺎﺳﺒﺎﺕ ﻭ ﭘﺎﺳﺦﻫﺎﻱ ﺑﺴﻴﺎﺭ ﺩﻗﻴﻖ ﻧﻴﺎﺯ ﺩﺍﺭﻳﺪ‪ ،‬ﺍﺯ ﻧﻮﻉ‬
‫‪ double‬ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﺪ‪ .‬ﻭﻟﻲ ﺍﮔﺮ ﺳﺮﻋﺖ ﺍﺟﺮﺍ ﺑﺮﺍﻳﺘﺎﻥ ﺍﻫﻤﻴﺖ ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﺩ‪ ،‬ﻧﻮﻉ‬
‫‪ float‬ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺑﮕﻴﺮﻳﺪ‪.‬‬
‫‪35‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫‪ 2 – 8‬ﺷﮑﻞ ﻋﻠﻤﻲ ﻣﻘﺎﺩﻳﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬


‫ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺑﻪ ﺩﻭ ﺻﻮﺭﺕ ﺩﺭ ﻭﺭﻭﺩﻱ ﻭ ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ‪ :‬ﺑﻪ‬
‫ﺷﮑﻞ »ﺳﺎﺩﻩ« ﻭ ﺑﻪ ﺷﮑﻞ »ﻋﻠﻤﻲ«‪.‬‬
‫ﻣﻘﺪﺍﺭ ‪ 12345.67‬ﺷﮑﻞ ﺳﺎﺩﻩ ﻋﺪﺩ ﺍﺳﺖ ﻭ ﻣﻘﺪﺍﺭ ‪ 1.234567×104‬ﺷﮑﻞ‬
‫ﻋﻠﻤﻲ ﻫﻤﺎﻥ ﻋﺪﺩ ﺍﺳﺖ‪ .‬ﻣﺸﺨﺺ ﺍﺳﺖ ﮐﻪ ﺷﮑﻞ ﻋﻠﻤﻲ ﺑﺮﺍﻱ ﻧﺸﺎﻥ ﺩﺍﺩﻥ ﺍﻋﺪﺍﺩ ﺧﻴﻠﻲ‬
‫ﮐﻮﭼﮏ ﻭ ﻫﻤﭽﻨﻴﻦ ﺍﻋﺪﺍﺩ ﺧﻴﻠﻲ ﺑﺰﺭﮒ‪ ،‬ﮐﺎﺭﺁﻳﻲ ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﺩ‪:‬‬
‫‪-0.000000000123 = -1.23×10-10‬‬
‫‪123000000000 = 1.23×1011‬‬

‫ﺩﺭ ‪ C++‬ﺑﺮﺍﻱ ﻧﺸﺎﻥ ﺩﺍﺩﻥ ﺣﺎﻟﺖ ﻋﻠﻤﻲ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺍﺯ ﺣﺮﻑ ﺍﻧﮕﻠﻴﺴﻲ ‪ e‬ﻳﺎ‬
‫‪ E‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪:‬‬
‫‪-1.23×10-10 = -1.23e-10‬‬
‫‪1.23×1011 = 1.23e11‬‬

‫ﻫﻨﮕﺎﻡ ﻭﺍﺭﺩ ﮐﺮﺩﻥ ﻣﻘﺎﺩﻳﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‪ ،‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﺷﮑﻞ ﺳﺎﺩﻩ ﻳﺎ ﺷﮑﻞ ﻋﻠﻤﻲ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪ .‬ﻫﻨﮕﺎﻡ ﭼﺎﭖ ﻣﻘﺎﺩﻳﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‪ ،‬ﻣﻌﻤﻮﻻ ﻣﻘﺎﺩﻳﺮ ﺑﻴﻦ ‪ 0.1‬ﺗﺎ ‪ 999.999‬ﺑﻪ‬
‫ﺷﮑﻞ ﺳﺎﺩﻩ ﭼﺎﭖ ﻣﻲﺷﻮﻧﺪ ﻭ ﺳﺎﻳﺮ ﻣﻘﺎﺩﻳﺮ ﺑﻪ ﺷﮑﻞ ﻋﻠﻤﻲ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 6‬ﺷﮑﻞ ﻋﻠﻤﻲ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﮏ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ )‪ (x‬ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ ﮔﺮﻓﺘﻪ ﻭ ﻣﻌﮑﻮﺱ ﺁﻥ )‪ (1/x‬ﺭﺍ‬
‫ﭼﺎﭖ ﻣﻲﮐﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ // prints reciprocal value of x:‬‬
‫;‪double x‬‬
‫;‪cout << "Enter float: "; cin >> x‬‬
‫;‪cout << "Its reciprocal is: " << 1/x << endl‬‬
‫;‪return 0‬‬
‫}‬
‫‪Enter float: 234.567e89‬‬
‫‪Its reciprocal is: 4.26317e-92‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪36‬‬

‫ﺗﺎ ﺍﻳﻦﺟﺎ ﺍﻧﻮﺍﻉ ﻋﺪﺩﻱ ﺭﺍ ﺩﺭ ‪ C++‬ﺩﻳﺪﻳﻢ‪ .‬ﺍﻳﻦ ﺍﻧﻮﺍﻉ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺒﺎﺕ ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﻣﻲﺷﻮﻧﺪ ﻭ ﺗﻘﺮﻳﺒﺎ ﺩﺭ ﻫﺮ ﺑﺮﻧﺎﻣﻪﺍﻱ ﮐﻪ ﻣﻲﻧﻮﻳﺴﻴﺪ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ‪ .‬ﺍﻣﺎ ‪ C++‬ﺍﻧﻮﺍﻉ ﺩﻳﮕﺮﻱ‬
‫ﻧﻴﺰ ﺩﺍﺭﺩ ﮐﻪ ﮐﺎﺭﺑﺮﺩﻫﺎﻱ ﺩﻳﮕﺮﻱ ﺩﺍﺭﻧﺪ‪ .‬ﻧﻮﻉ ﺑﻮﻟﻴﻦ ﮐﻪ ﺑﺮﺍﻱ ﻋﻤﻠﻴﺎﺕ ﻣﻨﻄﻘﻲ ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﻣﻲﺷﻮﺩ ﻭ ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻱ ﮐﻪ ﺑﺮﺍﻱ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺗﺪﺍﺭﮎ ﺩﻳﺪﻩ ﺷﺪﻩ ﺍﺳﺖ ﻭ ﻧﻮﻉ‬
‫ﺷﻤﺎﺭﺷﻲ ﮐﻪ ﺑﻴﺸﺘﺮ ﺑﺮﺍﻱ ﻣﺠﻤﻮﻋﻪﻫﺎﻳﻲ ﮐﻪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‪.‬‬
‫ﺍﻳﻦ ﺍﻧﻮﺍﻉ ﺟﺪﻳﺪ ﮔﺮﭼﻪ ﮐﺎﺭﺑﺮﺩﺷﺎﻥ ﺑﺎ ﺍﻋﺪﺍﺩ ﺗﻔﺎﻭﺕ ﺩﺍﺭﺩ ﺍﻣﺎ ﺩﺭ ﺣﻘﻴﻘﺖ ﺑﻪ ﺷﮑﻞ ﺍﻋﺪﺍﺩ‬
‫ﺻﺤﻴﺢ ﺩﺭ ﺭﺍﻳﺎﻧﻪ ﺫﺧﻴﺮﻩ ﻭ ﺷﻨﺎﺳﺎﻳﻲ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﻳﻦ ﻧﻮﻉﻫﺎ ﺭﺍ ﻧﻴﺰ‬
‫ﺯﻳﺮﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﺍﻧﻮﺍﻉ ﺻﺤﻴﺢ ﺩﺭ ‪ C++‬ﻣﻲﺷﻤﺎﺭﻧﺪ‪ .‬ﺩﺭ ﺍﺩﺍﻡۀ ﺍﻳﻦ ﻓﺼﻞ ﺑﻪ ﺑﺮﺭﺳﻲ ﺍﻳﻦ‬
‫ﺍﻧﻮﺍﻉ ﻣﻲﭘﺮﺩﺍﺯﻳﻢ‪.‬‬

‫‪ 2 – 9‬ﻧﻮﻉ ﺑﻮﻟﻴﻦ‪bool 1‬‬

‫ﻧﻮﻉ ‪ bool‬ﻳﮏ ﻧﻮﻉ ﺻﺤﻴﺢ ﺍﺳﺖ ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﻳﻦ ﻧﻮﻉ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻣﻘﺪﺍﺭ‬
‫‪ true‬ﻳﺎ ‪ false‬ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ‪ true .‬ﺑﻪ ﻣﻌﻨﻲ ﺩﺭﺳﺖ ﻭ ‪ false‬ﺑﻪ ﻣﻌﻨﻲ ﻧﺎﺩﺭﺳﺖ‬
‫ﺍﺳﺖ‪ .‬ﮔﺮﭼﻪ ﺩﺭﻭﻥ ﺑﺮﻧﺎﻣﻪ ﻣﺠﺒﻮﺭﻳﻢ ﺍﺯ ﻋﺒﺎﺭﺍﺕ ‪ true‬ﻳﺎ ‪ false‬ﺑﺮﺍﻱ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﻪ ﺍﻳﻦ‬
‫ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪ ،‬ﺍﻣﺎ ﺍﻳﻦ ﻣﻘﺎﺩﻳﺮ ﺩﺭ ﺍﺻﻞ ﺑﻪ ﺻﻮﺭﺕ ‪ 1‬ﻭ ‪ 0‬ﺩﺭﻭﻥ ﺭﺍﻳﺎﻧﻪ ﺫﺧﻴﺮﻩ‬
‫ﻣﻲﺷﻮﻧﺪ‪ 1 :‬ﺑﺮﺍﻱ ‪ true‬ﻭ ‪ 0‬ﺑﺮﺍﻱ ‪ .false‬ﻣﺜﺎﻝ ﺯﻳﺮ ﺍﻳﻦ ﻣﻄﻠﺐ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 7‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻧﻮﻉ ‪bool‬‬


‫)(‪int main‬‬
‫‪{ //prints the vlaue of a boolean variable:‬‬
‫;‪bool flag=false‬‬
‫;‪cout << "flag = " << flag << endl‬‬
‫;‪flag = true‬‬
‫;‪cout << "flag = " << flag << endl‬‬
‫;‪return 0‬‬
‫}‬
‫‪flag = 0‬‬
‫‪flag = 1‬‬

‫‪1 – Boolean‬‬
‫‪37‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫ﺩﺭ ﺧﻂ ﺳﻮﻡ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺘﻐﻴﺮﻱ ﺑﻪ ﻧﺎﻡ ‪ falg‬ﺍﺯ ﻧﻮﻉ ‪ bool‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﻭ ﺑﺎ‬
‫ﻣﻘﺪﺍﺭ ‪ false‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺩﺭ ﺧﻂ ﺑﻌﺪﻱ ﻣﻘﺪﺍﺭ ﺍﻳﻦ ﻣﺘﻐﻴﺮ ﺩﺭ ﺧﺮﻭﺟﻲ‬
‫ﭼﺎﭖ ﺷﺪﻩ ﻭ ﺩﺭ ﺧﻂ ﭘﻨﺠﻢ ﻣﻘﺪﺍﺭ ﺁﻥ ﺑﻪ ‪ true‬ﺗﻐﻴﻴﺮ ﻳﺎﻓﺘﻪ ﺍﺳﺖ ﻭ ﺩﻭﺑﺎﺭﻩ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ‬
‫ﭼﺎﭖ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﮔﺮﭼﻪ ﺑﻪ ﻣﺘﻐﻴﺮ ‪ flag‬ﻣﻘﺪﺍﺭ ‪ false‬ﻭ ‪ true‬ﺩﺍﺩﻩﺍﻳﻢ ﺍﻣﺎ ﺩﺭ‬
‫ﺧﺮﻭﺟﻲ ﺑﻪ ﺟﺎﻱ ﺁﻥﻫﺎ ﻣﻘﺎﺩﻳﺮ ‪ 0‬ﻭ ‪ 1‬ﭼﺎﭖ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬

‫‪ 2‐ 10‬ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪char‬‬

‫ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻳﮏ ﺣﺮﻑ‪ ،‬ﺭﻗﻢ ﻳﺎ ﻧﺸﺎﻧﻪ ﺍﺳﺖ ﮐﻪ ﻳﮏ ﺷﻤﺎﺭۀ ﻣﻨﺤﺼﺮ ﺑﻪ ﻓﺮﺩ ﺩﺍﺭﺩ‪ .‬ﺑﻪ‬
‫ﻋﺒﺎﺭﺕ ﻋﺎﻣﻴﺎﻧﻪ‪ ،‬ﻫﺮ ﮐﻠﻴﺪﻱ ﮐﻪ ﺭﻭﻱ ﺻﻔﺤﻪﮐﻠﻴﺪ ﺧﻮﺩ ﻣﻲﺑﻴﻨﻴﺪ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﻧﺸﺎﻥ‬
‫ﻣﻲﺩﻫﺪ )ﺍﻟﺒﺘﻪ ﺑﻪ ﻏﻴﺮ ﺍﺯ ﮐﻠﻴﺪﻫﺎﻱ ﻣﺎﻟﺘﻲﻣﺪﻳﺎ ﻳﺎ ﮐﻠﻴﺪﻫﺎﻱ ﺍﻳﻨﺘﺮﻧﺘﻲ ﮐﻪ ﺍﺧﻴﺮﺍ ﺩﺭ‬
‫ﺻﻔﺤﻪﮐﻠﻴﺪﻫﺎ ﻣﺮﺳﻮﻡ ﺷﺪﻩﺍﻧﺪ(‪ .‬ﻣﺜﻼ ﻫﺮ ﻳﮏ ﺍﺯ ﺣﺮﻭﻑ '‪ 'A‬ﺗﺎ '‪ 'Z‬ﻭ '‪ 'a‬ﺗﺎ '‪ 'z‬ﻭ‬
‫ﻫﺮ ﻳﮏ ﺍﺯ ﺍﻋﺪﺍﺩ '‪ '0‬ﺗﺎ '‪ '9‬ﻭ ﻳﺎ ﻧﺸﺎﻧﻪﻫﺎﻱ '~' ﺗﺎ '‪ '+‬ﺭﻭﻱ ﺻﻔﺤﻪﮐﻠﻴﺪ ﺭﺍ ﻳﮏ‬
‫ﮐﺎﺭﺍﮐﺘﺮ ﻣﻲﻧﺎﻣﻨﺪ‪ .‬ﺭﺍﻳﺎﻧﻪﻫﺎ ﺑﺮﺍﻱ ﺷﻨﺎﺳﺎﻳﻲ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺍﺯ ﺟﺪﻭﻝ ﺍﺳﮑﻲ ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﻣﻲﮐﻨﻨﺪ‪ .‬ﺑﺎ ﺩﻗﺖ ﺩﺭ ﺍﻳﻦ ﺟﺪﻭﻝ ﺧﻮﺍﻫﻴﺪ ﺩﻳﺪ ﮐﻪ ﻫﺮ ﮐﺎﺭﺍﮐﺘﺮ ﻳﮏ ﺷﻤﺎﺭۀ ﻣﻨﺤﺼﺮ ﺑﻪ ﻓﺮﺩ‬
‫ﺩﺍﺭﺩ‪ .‬ﻣﺜﻼ ﮐﺎﺭﺍﮐﺘﺮ '‪ 'A‬ﮐﺪ ‪ 65‬ﺩﺍﺭﺩ‪ .‬ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺩﺭ ﺭﺍﻳﺎﻧﻪ ﺑﻪ ﺷﮑﻞ ﻋﺪﺩﻱﺷﺎﻥ ﺫﺧﻴﺮﻩ‬
‫ﻣﻲﺷﻮﻧﺪ ﺍﻣﺎ ﺑﻪ ﺷﮑﻞ ﮐﺎﺭﺍﮐﺘﺮﻱﺷﺎﻥ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ‪ .‬ﻣﺜﻼ ﮐﺎﺭﺍﮐﺘﺮ '‪ 'A‬ﺑﻪ ﺷﮑﻞ ﻋﺪﺩ‬
‫‪ 65‬ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﺍﮔﺮ ﺳﻌﻲ ﮐﻨﻴﻢ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮ '‪ 'A‬ﺩﺭ ﺁﻥ ﺫﺧﻴﺮﻩ ﺷﺪﻩ ﺭﺍ‬
‫ﭼﺎﭖ ﮐﻨﻴﻢ‪ ،‬ﺷﮑﻞ ‪ A‬ﺭﺍ ﺩﺭ ﺧﺮﻭﺟﻲ ﻣﻲ ﺑﻴﻨﻴﻢ ﻧﻪ ﻋﺪﺩ ‪ 65‬ﺭﺍ‪.‬‬
‫ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺯ ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ ‪ char‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪ .‬ﻳﮏ‬
‫ﮐﺎﺭﺍﮐﺘﺮ ﺑﺎﻳﺪ ﺩﺭﻭﻥ ﺩﻭ ﻋﻼﻣﺖ ﺁﭘﺴﺘﺮﻭﻑ )'( ﻣﺤﺼﻮﺭ ﺷﺪﻩ ﺑﺎﺷﺪ‪ .‬ﭘﺲ '‪ 'A‬ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ‬
‫ﺍﺳﺖ؛ ﻫﻤﭽﻨﻴﻦ '‪ '8‬ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺳﺖ ﺍﻣﺎ ‪ 8‬ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻧﻴﺴﺖ ﺑﻠﮑﻪ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ‬
‫ﺍﺳﺖ‪.‬‬
‫ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﺤﻮۀ ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ﻣﺘﻐﻴﺮﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 8‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻧﻮﻉ ‪char‬‬


‫)(‪int main‬‬
‫‪{ //prints the character and its internally stored integer value:‬‬
‫;'‪char c ='A‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪38‬‬

‫‪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‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫‪ 2 – 11‬ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ‪enum‬‬

‫ﻋﻼﻭﻩ ﺑﺮ ﺍﻧﻮﺍﻋﻲ ﮐﻪ ﺗﺎ ﮐﻨﻮﻥ ﺑﺮﺭﺳﻲ ﮐﺮﺩﻳﻢ‪ ،‬ﻣﻲ ﺗﻮﺍﻥ ﺩﺭ ‪ 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‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫‪ – 1‬ﺑﺮﺍﻱ ﻧﺎﻡ ﺛﺎﺑﺖﻫﺎ ﺍﺯ ﺣﺮﻭﻑ ﺑﺰﺭﮒ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﺪ‬


‫‪ – 2‬ﺍﻭﻟﻴﻦ ﺣﺮﻑ ﺍﺯ ﻧﺎﻡ ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ﺭﺍ ﺑﺎ ﺣﺮﻑ ﺑﺰﺭﮒ ﺑﻨﻮﻳﺴﻴﺪ‪.‬‬
‫‪ – 3‬ﺩﺭ ﻫﺮ ﺟﺎﻱ ﺩﻳﮕﺮ ﺍﺯ ﺣﺮﻭﻑ ﮐﻮﭼﮏ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﺪ‪.‬‬
‫ﺭﻋﺎﻳﺖ ﺍﻳﻦ ﺗﻮﺍﻓﻖ ﺑﻪ ﺧﻮﺍﻧﺎﻳﻲ ﺑﺮﻧﺎﻣﻪﺗﺎﻥ ﮐﻤﮏ ﻣﻲﮐﻨﺪ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻧﻮﺍﻉ‬
‫ﺷﻤﺎﺭﺷﻲ ﮐﻪ ﮐﺎﺭﺑﺮ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﺍﺯ ﺍﻧﻮﺍﻉ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻣﺜﻞ ‪ int‬ﻭ ‪ float‬ﻭ ‪char‬‬
‫ﺭﺍﺣﺖﺗﺮ ﺗﻤﻴﺰ ﺩﺍﺩﻩ ﺷﻮﺩ‪.‬‬
‫ﺷﻤﺎﺭﺷﮕﺮﻫﺎ ﻗﻮﺍﻋﺪ ﺧﺎﺻﻲ ﺩﺍﺭﻧﺪ‪ .‬ﻧﺎﻡ ﺷﻤﺎﺭﺷﮕﺮ ﺑﺎﻳﺪ ﻣﻌﺘﺒﺮ ﺑﺎﺷﺪ‪ .‬ﻳﻌﻨﻲ ﮐﻠﻢۀ‬
‫ﮐﻠﻴﺪﻱ ﻧﺒﺎﺷﺪ‪ ،‬ﺑﺎ ﻋﺪﺩ ﺷﺮﻭﻉ ﻧﺸﻮﺩ ﻭ ﻧﺸﺎﻧﻪﻫﺎﻱ ﺭﻳﺎﺿﻲ ﻧﻴﺰ ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﭘﺲ ﺗﻌﺮﻳﻒ ﺯﻳﺮ‬
‫ﻏﻴﺮﻣﻌﺘﺒﺮ ﺍﺳﺖ‪:‬‬
‫}‪enum Score{A+,A,A-,B+,B,B-,C+,C,C-‬‬

‫ﺯﻳﺮﺍ ‪ 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‬‬

‫‪ 2 – 12‬ﺗﺒﺪﻳﻞ ﻧﻮﻉ‪ ،‬ﮔﺴﺘﺮﺵ ﻧﻮﻉ‬


‫ﺩﺭ ﻗﺴﻤﺖﻫﺎﻱ ﻗﺒﻠﻲ ﺑﺎ ﺍﻧﻮﺍﻉ ﻋﺪﺩﻱ ﺁﺷﻨﺎ ﺷﺪﻳﻢ ﻭ ﻧﺤﻮۀ ﺍﻋﻤﺎﻝ ﺭﻳﺎﺿﻲ ﺁﻥﻫﺎ ﺭﺍ‬
‫ﻣﺸﺎﻫﺪﻩ ﻧﻤﻮﺩﻳﻢ ﺍﻣﺎ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺕ ﺭﻳﺎﺿﻲ ﮐﻪ ﺍﻧﺠﺎﻡ ﺩﺍﺩﻳﻢ ﻫﻢۀ ﻣﺘﻐﻴﺮﻫﺎ ﺍﺯ ﻳﮏ ﻧﻮﻉ ﺑﻮﺩﻧﺪ‪.‬‬
‫ﺍﮔﺮ ﺑﺨﻮﺍﻫﻴﻢ ﺩﺭ ﻳﮏ ﻣﺤﺎﺳﺒﻪ ﺩﻭ ﻳﺎ ﭼﻨﺪ ﻣﺘﻐﻴﺮ ﺍﺯ ﺍﻧﻮﺍﻉ ﻣﺨﺘﻠﻒ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ ﭼﻪ ﺍﺗﻔﺎﻗﻲ‬
‫ﻣﻲﺍﻓﺘﺪ؟‬
‫ﻗﺎﻧﻮﻥ ﮐﻠﻲ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺗﻲ ﮐﻪ ﭼﻨﺪ ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﻭﺟﻮﺩ ﺩﺍﺭﺩ‪ ،‬ﺟﻮﺍﺏ‬
‫ﻫﻤﻴﺸﻪ ﺑﻪ ﺷﮑﻞ ﻣﺘﻐﻴﺮﻱ ﺍﺳﺖ ﮐﻪ ﺩﻗﺖ ﺑﺎﻻﺗﺮﻱ ﺩﺍﺭﺩ‪ .‬ﻳﻌﻨﻲ ﺍﮔﺮ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﺑﺎ‬
‫ﻳﮏ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺟﻤﻊ ﺑﺒﻨﺪﻳﻢ‪ ،‬ﭘﺎﺳﺦ ﺑﻪ ﺷﮑﻞ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺍﺳﺖ‪ .‬ﺑﻪ ﺍﻳﻦ ﻣﻨﻈﻮﺭ ﺍﺑﺘﺪﺍ‬
‫ﻣﺘﻐﻴﺮﻫﺎ ﻭ ﻣﻘﺎﺩﻳﺮﻱ ﮐﻪ ﺍﺯ ﻧﻮﻉ ﺑﺎ ﺩﻗﺖ ﮐﻤﺘﺮ ﻫﺴﺘﻨﺪ ﺑﻪ ﻧﻮﻉ ﺑﺎ ﺩﻗﺖ ﺑﻴﺸﺘﺮ ﺗﺒﺪﻳﻞ ﻣﻲﺷﻮﻧﺪ‬
‫ﻭ ﺳﭙﺲ ﻣﺤﺎﺳﺒﻪ ﺭﻭﻱ ﺁﻥﻫﺎ ﺍﻧﺠﺎﻡ ﻣﻲﺷﻮﺩ‪ .‬ﭘﺲ ﺍﮔﺮ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﺑﺎ ﻳﮏ ﻋﺪﺩ ﻣﻤﻴﺰ‬
‫ﺷﻨﺎﻭﺭ ﺟﻤﻊ ﺑﺒﻨﺪﻳﻢ‪ ،‬ﺍﺑﺘﺪﺍ ﻋﺪﺩ ﺻﺤﻴﺢ ﺗﺒﺪﻳﻞ ﺑﻪ ﻳﮏ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﻣﻲﺷﻮﺩ‪ ،‬ﺳﭙﺲ ﺍﻳﻦ‬
‫ﻋﺪﺩ ﺑﺎ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺩﻳﮕﺮ ﺟﻤﻊ ﺑﺴﺘﻪ ﻣﻲﺷﻮﺩ ﻭ ﻭﺍﺿﺢ ﺍﺳﺖ ﮐﻪ ﭘﺎﺳﺦ ﻧﻴﺰ ﺑﻪ ﺷﮑﻞ‬
‫ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪ .‬ﺍﻳﻦ ﮐﺎﺭ ﺑﻪ ﺷﮑﻞ ﺧﻮﺩﮐﺎﺭ ﺍﻧﺠﺎﻡ ﻣﻲﮔﻴﺮﺩ ﻭ ‪ C++‬ﺩﺭ ﭼﻨﻴﻦ‬
‫ﻣﺤﺎﺳﺒﺎﺗﻲ ﺑﻪ ﺷﮑﻞ ﺧﻮﺩﮐﺎﺭ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺑﺎ ﺩﻗﺖ ﮐﻤﺘﺮ ﺭﺍ ﺑﻪ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺑﺎ ﺩﻗﺖ ﺑﻴﺸﺘﺮ ﺗﺒﺪﻳﻞ‬
‫ﻣﻲﮐﻨﺪ ﺗﺎ ﻫﻤﻪ ﻣﺘﻐﻴﺮﻫﺎ ﺍﺯ ﻳﮏ ﻧﻮﻉ ﺷﻮﻧﺪ ﻭ ﺁﻧﮕﺎﻩ ﻣﺤﺎﺳﺒﻪ ﺭﺍ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ ﻭ ﭘﺎﺳﺦ ﺭﺍ ﻧﻴﺰ‬
‫ﺑﻪ ﺷﮑﻞ ﻧﻮﻉ ﺑﺎ ﺩﻗﺖ ﺑﻴﺸﺘﺮ ﺑﻪ ﺩﺳﺖ ﻣﻲﺩﻫﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﻋﻤﻞ ﮔﺴﺘﺮﺵ ﻧﻮﻉ ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬
‫‪43‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫ﺍﻣﺎ ﺍﮔﺮ ﻋﮑﺲ ﺍﻳﻦ ﻋﻤﻞ ﻣﻮﺭﺩ ﻧﻈﺮ ﺑﺎﺷﺪ‪ ،‬ﻳﻌﻨﻲ ﺍﮔﺮ ﺑﺨﻮﺍﻫﻴﻢ ﻳﮏ ﻣﺘﻐﻴﺮ ﺻﺤﻴﺢ ﺭﺍ ﺑﺎ‬
‫ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺟﻤﻊ ﺑﺒﻨﺪﻳﻢ ﻭ ﺑﺨﻮﺍﻫﻴﻢ ﮐﻪ ﺣﺎﺻﻞ ﺍﺯ ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﺎﺷﺪ ﻧﻪ ﻣﻤﻴﺰ‬
‫ﺷﻨﺎﻭﺭ‪ ،‬ﭼﻪ ﺑﺎﻳﺪ ﺑﮑﻨﻴﻢ؟ ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ ﺍﺯ ﻋﻤﻠﮕﺮ ﺗﺒﺪﻳﻞ ﻧﻮﻉ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪ .‬ﺍﻳﻦ ﺗﺒﺪﻳﻞ‬
‫ﺧﻮﺩﮐﺎﺭ ﻧﻴﺴﺖ ﺑﻠﮑﻪ ﮐﺎﻣﻼ ﺑﺎﻳﺪ ﺩﺳﺘﻲ ﺍﻧﺠﺎﻡ ﺷﻮﺩ ﻭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ‪ ،‬ﺧﻮﺩ ﺑﺎﻳﺪ ﻣﺮﺍﻗﺐ ﺍﻳﻦ‬
‫ﻋﻤﻞ ﺑﺎﺷﺪ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺭﺍ ﺑﻪ ﻧﻮﻉ ﺻﺤﻴﺢ ﺗﺒﺪﻳﻞ‬
‫ﮐﻨﻴﻢ ﺍﺯ ﻋﺒﺎﺭﺕ )(‪ int‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪.‬‬
‫ﻣﺜﺎﻝﻫﺎﻱ ﺯﻳﺮ ﺗﺒﺪﻳﻞ ﻧﻮﻉ ﻭ ﮔﺴﺘﺮﺵ ﻧﻮﻉ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 9‬ﺗﺒﺪﻳﻞ ﻧﻮﻉ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﻳﮏ ﻧﻮﻉ ‪ double‬ﺭﺍ ﺑﻪ ﻧﻮﻉ ‪ int‬ﺗﺒﺪﻳﻞ ﻣﻲﮐﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ // casts a double value as an int:‬‬
‫;‪double v=1234.987‬‬
‫;‪int n‬‬
‫;)‪n = int(v‬‬
‫;‪cout << "v = " << v << ", n = " << n << endl‬‬
‫;‪return 0‬‬
‫}‬
‫‪v = 1234.987, n = 1234‬‬

‫ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺘﻐﻴﺮ ‪ v‬ﺍﺯ ﻧﻮﻉ ‪ double‬ﻭ ﺑﺎ ﻣﻘﺪﺍﺭ ‪ 1234.987‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬
‫ﻫﻤﭽﻨﻴﻦ ﻣﺘﻐﻴﺮ ‪ n‬ﺍﺯ ﻧﻮﻉ ‪ int‬ﺗﻌﺮﻳﻒ ﮔﺸﺘﻪ ﺍﺳﺖ‪ .‬ﺩﺭ ﺧﻂ ﭘﻨﺠﻢ ﺍﺯ ﮐﺪ ﺑﺎﻻ ﺍﺯ ﺗﺒﺪﻳﻞ ﻧﻮﻉ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‪:‬‬
‫;)‪n = int(v‬‬

‫ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺩﺳﺘﻮﺭ‪ ،‬ﻣﻘﺪﺍﺭ ‪ v‬ﺍﺑﺘﺪﺍ ﺑﻪ ﻧﻮﻉ ‪ int‬ﺗﺒﺪﻳﻞ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﺍﻳﻦ‬
‫ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ ‪ n‬ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺧﺮﻭﺟﻲ ﺑﺮﻧﺎﻣﻪ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻭﻗﺘﻲ ﺍﺯ ﻋﻤﻠﮕﺮ )(‪int‬‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪ ،‬ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ »ﺑﺮﻳﺪﻩ« ﻣﻲﺷﻮﺩ‪ ،‬ﮔﺮﺩ ﻧﻤﻲﺷﻮﺩ‪ .‬ﻳﻌﻨﻲ ﻗﺴﻤﺖ ﺍﻋﺸﺎﺭﻱ‬
‫ﻋﺪﺩ ﺑﻪ ﻃﻮﺭ ﮐﺎﻣﻞ ﺣﺬﻑ ﻣﻲﺷﻮﺩ ﻭ ﻓﻘﻂ ﻗﺴﻤﺖ ﺻﺤﻴﺢ ﺁﻥ ﺑﺎﻗﻲ ﻣﻲﻣﺎﻧﺪ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﻭﻗﺘﻲ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪44‬‬

‫ﻋﺪﺩ ‪ 1234.987‬ﺑﻪ ﻧﻮﻉ ‪ int‬ﺗﺒﺪﻳﻞ ﺷﻮﺩ‪ ،‬ﺣﺎﺻﻞ ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 1234‬ﺧﻮﺍﻫﺪ ﺑﻮﺩ ﻭ‬


‫ﻗﺴﻤﺖ ﺍﻋﺸﺎﺭﻱ ﺁﻥ )ﻫﺮ ﻗﺪﺭ ﻫﻢ ﺑﺰﺭﮒ ﺑﺎﺷﺪ( ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺩﺭ ﺗﺒﺪﻳﻞ ﻧﻮﻉ ﻫﻤﻮﺍﺭﻩ ﻧﻮﻉ ﻭ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺗﺒﺪﻳﻞ ﺷﺪﻩ ﺑﺪﻭﻥ ﺗﻐﻴﻴﺮ ﻣﻲﻣﺎﻧﺪ‪ .‬ﺩﺭ‬
‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﻘﺪﺍﺭ ‪ v‬ﺗﺎ ﭘﺎﻳﺎﻥ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻫﻤﺎﻥ ﻣﻘﺪﺍﺭ ‪ 1234.987‬ﺑﺎﻗﻲ ﻣﺎﻧﺪﻩ ﻭ ﻧﻮﻉ ‪ v‬ﻧﻴﺰ‬
‫ﺗﻐﻴﻴﺮ ﻧﮑﺮﺩﻩ ﻭ ﻫﻤﭽﻨﺎﻥ ﺍﺯ ﻧﻮﻉ ‪ double‬ﻣﺎﻧﺪﻩ ﺍﺳﺖ‪ .‬ﺗﻨﻬﺎ ﺍﺗﻔﺎﻗﻲ ﮐﻪ ﺍﻓﺘﺎﺩﻩ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ‬
‫ﻣﻘﺪﺍﺭ ‪ v‬ﺩﺭ ﻳﮏ ﻣﺤﻞ ﻣﻮﻗﺘﻲ ﺗﺒﺪﻳﻞ ﺑﻪ ‪ int‬ﺷﺪﻩ ﺗﺎ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ ‪ n‬ﻗﺮﺍﺭ ﮔﻴﺮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 10‬ﮔﺴﺘﺮﺵ ﻧﻮﻉ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﺑﺎ ﻳﮏ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺟﻤﻊ ﻣﻲﮐﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ // adds an int value with a double value:‬‬
‫;‪int n = 22‬‬
‫;‪double p = 3.1415‬‬
‫;‪p += n‬‬
‫;‪cout << "p = " << p << ", n = " << n << endl‬‬
‫;‪return 0‬‬
‫}‬
‫‪p = 24.1415, n = 22‬‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ ‪ n‬ﺍﺯ ﻣﻘﺪﺍﺭ ﺻﺤﻴﺢ ‪ 22‬ﺑﻪ ﻣﻘﺪﺍﺭ ﺍﻋﺸﺎﺭﻱ ‪ 22.0‬ﮔﺴﺘﺮﺵ‬
‫ﻣﻲﻳﺎﺑﺪ ﻭ ﺳﭙﺲ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﺎ ﻣﻘﺪﺍﺭ ﻗﺒﻠﻲ ‪ p‬ﺟﻤﻊ ﻣﻲﺷﻮﺩ‪ .‬ﺣﺎﺻﻞ ﻳﮏ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬
‫ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 11‬ﮔﺴﺘﺮﺵ ﻧﻮﻉ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﻳﮏ ‪ char‬ﺭﺍ ﺑﻪ ‪ float ، int‬ﻭ ‪ double‬ﮔﺴﺘﺮﺵ ﻣﻲﺩﻫﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ //prints promoted values of 65 from‬‬ ‫‪char‬‬ ‫‪to double:‬‬
‫;'‪char c='A‬‬ ‫" << ‪cout‬‬ ‫= ‪char c‬‬ ‫<< "‬ ‫;‪c << endl‬‬
‫;‪short k=c‬‬ ‫= ‪cout << " short k‬‬ ‫<< "‬ ‫;‪k << endl‬‬
‫;‪int m=k‬‬ ‫" << ‪cout‬‬ ‫= ‪int m‬‬ ‫<< "‬ ‫;‪m << endl‬‬
‫;‪long n=m‬‬ ‫" << ‪cout‬‬ ‫= ‪long n‬‬ ‫<< "‬ ‫;‪n << endl‬‬
‫;‪float x=n‬‬ ‫= ‪cout << " float x‬‬ ‫<< "‬ ‫;‪x << endl‬‬
‫‪45‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫;‪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 – 13‬ﺑﺮﺧﻲ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬


‫ﺍﮐﻨﻮﻥ ﮐﻪ ﺍﻧﻮﺍﻉ ﻣﺘﻐﻴﺮ ﺩﺭ ‪ C++‬ﺭﺍ ﺷﻨﺎﺧﺘﻴﻢ‪ ،‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﺍﻳﻦ ﺍﻧﻮﺍﻉ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ‬
‫ﻣﻔﻴﺪﺗﺮ ﻭ ﺟﺪﻱﺗﺮ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪ .‬ﺍﻣﺎ ﺑﺎﻳﺪ ﺩﻗﺖ ﻧﻤﻮﺩ ﮐﻪ ﺍﮔﺮ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎ ﺑﻪ ﺷﮑﻞ ﻧﺎﺩﺭﺳﺖ‬
‫ﻳﺎ ﮐﻨﺘﺮﻝﻧﺸﺪﻩ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪ ،‬ﺑﺮﻧﺎﻣﻪ ﺩﭼﺎﺭ ﺧﻄﺎ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻟﺒﺘﻪ ﻋﻮﺍﻣﻞ ﺩﻳﮕﺮﻱ ﻧﻴﺰ ﻫﺴﺖ ﮐﻪ‬
‫ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﻣﺨﺘﻞ ﮔﺮﺩﺩ‪ ،‬ﻣﺜﻞ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﺗﻌﺮﻳﻒ ﻧﺸﺪﻩ ﻳﺎ ﺟﺎ‬
‫ﺍﻧﺪﺍﺧﺘﻦ ﺳﻤﻴﮑﻮﻟﻦ ﺍﻧﺘﻬﺎﻱ ﺩﺳﺘﻮﺭﻫﺎ‪ .‬ﺍﻳﻦ ﻗﺒﻴﻞ ﺧﻄﺎﻫﺎ ﮐﻪ ﺍﻏﻠﺐ ﺧﻄﺎﻫﺎﻱ ﻧﺤﻮﻱ ﻫﺴﺘﻨﺪ ﻭ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪46‬‬

‫ﺗﻮﺳﻂ ﮐﺎﻣﭙﺎﻳﻠﺮ ﮐﺸﻒ ﻣﻲﺷﻮﻧﺪ »ﺧﻄﺎﻱ ﺯﻣﺎﻥ ﮐﺎﻣﭙﺎﻳﻞ« ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﻧﺪ ﻭ ﺑﻪ ﺭﺍﺣﺘﻲ‬
‫ﻣﻲﺗﻮﺍﻥ ﺁﻥﻫﺎ ﺭﺍ ﺭﻓﻊ ﻧﻤﻮﺩ‪ .‬ﺍﻣﺎ ﺧﻄﺎﻫﺎﻱ ﺩﻳﮕﺮﻱ ﻧﻴﺰ ﻭﺟﻮﺩ ﺩﺍﺭﻧﺪ ﮐﻪ ﮐﺸﻒ ﺁﻥﻫﺎ ﺑﻪ‬
‫ﺭﺍﺣﺘﻲ ﻣﻤﮑﻦ ﻧﻴﺴﺖ ﻭ ﮐﺎﻣﭙﺎﻳﻠﺮ ﻧﻴﺰ ﭼﻴﺰﻱ ﺭﺍﺟﻊ ﺑﻪ ﺁﻥ ﻧﻤﻲﺩﺍﻧﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﺧﻄﺎﻫﺎ »ﺧﻄﺎﻱ‬
‫ﺯﻣﺎﻥ ﺍﺟﺮﺍ« ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺑﺮﺧﻲ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺳﺒﺐ ﻣﻲﺷﻮﻧﺪ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻃﻮﺭ‬
‫ﮐﺎﻣﻞ ﻣﺘﻮﻗﻒ ﺷﻮﺩ ﻭ ﺍﺯ ﮐﺎﺭ ﺑﻴﻔﺘﺪ‪ .‬ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ ﻣﺘﻮﺟﻪ ﻣﻲﺷﻮﻳﻢ ﮐﻪ ﺧﻄﺎﻳﻲ ﺭﺥ ﺩﺍﺩﻩ‬
‫ﺍﺳﺖ ﻭ ﺩﺭ ﺻﺪﺩ ﮐﺸﻒ ﻭ ﺭﻓﻊ ﺁﻥ ﺑﺮﻣﻲﺁﻳﻴﻢ‪ .‬ﺑﺮﺧﻲ ﺩﻳﮕﺮ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ‪ ،‬ﺑﺮﻧﺎﻣﻪ‬
‫ﺭﺍ ﺍﺯ ﮐﺎﺭ ﻧﻤﻲﺍﻧﺪﺍﺯﻧﺪ ﺑﻠﮑﻪ ﺑﺮﻧﺎﻣﻪ ﻫﻤﭽﻨﺎﻥ ﮐﺎﺭ ﻣﻲﮐﻨﺪ ﺍﻣﺎ ﭘﺎﺳﺦﻫﺎﻱ ﻋﺠﻴﺐ ﻭ ﻧﺎﺩﺭﺳﺖ‬
‫ﻣﻲﺩﻫﺪ‪ .‬ﺍﻳﻦ ﺑﺪﺗﺮﻳﻦ ﻧﻮﻉ ﺧﻄﺎﺳﺖ ﺯﻳﺮﺍ ﺩﺭ ﺣﺎﻻﺕ ﺧﺎﺻﻲ ﺭﺥ ﻣﻲﺩﻫﺪ ﻭ ﮔﺎﻫﻲ ﺳﺒﺐ‬
‫ﮔﻴﺞ ﺷﺪﻥ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﻣﻲﮔﺮﺩﺩ‪ .‬ﺩﺭ ﺑﺨﺶﻫﺎﻱ ﺑﻌﺪﻱ ﺑﺮﺧﻲ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺭﺍﻳﺞ ﺯﻣﺎﻥ ﺍﺟﺮﺍ‬
‫ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻴﻢ ﺗﺎ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺘﺎﻥ ﺍﺯ ﺁﻥﻫﺎ ﭘﺮﻫﻴﺰ ﮐﻨﻴﺪ؛ ﺩﺳﺖ ﮐﻢ ﺍﮔﺮ ﺑﺎ ﭘﺎﺳﺦﻫﺎﻱ‬
‫ﻏﻴﺮﻣﻨﺘﻈﺮﻩ ﻭ ﻏﻠﻂ ﻣﻮﺍﺟﻪ ﺷﺪﻳﺪ‪ ،‬ﻣﺤﻞ ﺭﺥ ﺩﺍﺩﻥ ﺧﻄﺎ ﺭﺍ ﺭﺍﺣﺖﺗﺮ ﭘﻴﺪﺍ ﮐﻨﻴﺪ‪.‬‬

‫‪ 2 – 14‬ﺳﺮﺭﻳﺰﻱ‪ 1‬ﻋﺪﺩﻱ‬
‫ﻧﻮﻉ ﺻﺤﻴﺢ ‪ long‬ﻳﺎ ﻧﻮﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ‪ double‬ﻣﺤﺪﻭﺩۀ ﻭﺳﻴﻌﻲ ﺍﺯ ﺍﻋﺪﺍﺩ ﺭﺍ‬
‫ﻣﻲﺗﻮﺍﻧﻨﺪ ﻧﮕﻬﺪﺍﺭﻱ ﮐﻨﻨﺪ‪ .‬ﺑﻪ ﺑﻴﺎﻥ ﺳﺎﺩﻩﺗﺮ‪ ،‬ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﺍﺯ ﻧﻮﻉ ‪ long‬ﻳﺎ ‪ double‬ﺑﺎﺷﺪ‪،‬‬
‫ﮔﻨﺠﺎﻳﺶ ﺯﻳﺎﺩﻱ ﺩﺍﺭﺩ‪ .‬ﺍﻣﺎ ﺣﺎﻓﻆۀ ﺭﺍﻳﺎﻧﻪﻫﺎ ﻣﺘﻨﺎﻫﻲ ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﻫﺮ ﻗﺪﺭ ﻫﻢ ﮐﻪ ﻳﮏ ﻣﺘﻐﻴﺮ‬
‫ﮔﻨﺠﺎﻳﺶ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ ،‬ﺑﺎﻻﺧﺮﻩ ﻣﻘﺪﺍﺭﻱ ﻫﺴﺖ ﮐﻪ ﺍﺯ ﮔﻨﺠﺎﻳﺶ ﺁﻥ ﻣﺘﻐﻴﺮ ﺑﻴﺸﺘﺮ ﺑﺎﺷﺪ‪ .‬ﺍﮔﺮ‬
‫ﺳﻌﻲ ﮐﻨﻴﻢ ﺩﺭ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻘﺪﺍﺭﻱ ﻗﺮﺍﺭ ﺩﻫﻴﻢ ﮐﻪ ﺍﺯ ﮔﻨﺠﺎﻳﺶ ﺁﻥ ﻣﺘﻐﻴﺮ ﻓﺮﺍﺗﺮ ﺑﺎﺷﺪ‪ ،‬ﻣﺘﻐﻴﺮ‬
‫»ﺳﺮﺭﻳﺰ« ﻣﻲﺷﻮﺩ‪ .‬ﻣﺜﻞ ﻳﮏ ﻟﻴﻮﺍﻥ ﺁﺏ ﮐﻪ ﺍﮔﺮ ﺑﻴﺶ ﺍﺯ ﮔﻨﺠﺎﻳﺶ ﺁﻥ ﺩﺭ ﻟﻴﻮﺍﻥ ﺁﺏ ﺑﺮﻳﺰﻳﻢ‪،‬‬
‫ﺳﺮﺭﻳﺰ ﻣﻲﺷﻮﺩ‪ .‬ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ ﻣﻲﮔﻮﻳﻴﻢ ﮐﻪ ﺧﻄﺎﻱ ﺳﺮﺭﻳﺰﻱ ﺭﺥ ﺩﺍﺩﻩ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 12‬ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩ ﺻﺤﻴﺢ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻃﻮﺭ ﻣﻜﺮﺭ ‪ n‬ﺭﺍ ﺩﺭ ‪ 1000‬ﺿﺮﺏ ﻣﻲﻛﻨﺪ ﺗﺎ ﺳﺮﺍﻧﺠﺎﻡ ﺳﺮﺭﻳﺰ ﺷﻮﺩ‪:‬‬
‫)(‪int main‬‬
‫‪{ //prints n until it overflows:‬‬
‫;‪int n =1000‬‬
‫;‪cout << "n = " << n << endl‬‬

‫‪1 – Overflow‬‬
47 ‫ اﻧﻮاع اﺻﻠﯽ‬/ ‫ﻓﺼﻞ دوم‬

n *= 1000; // multiplies n by 1000


cout << "n = " << n << endl;
n *= 1000; // multiplies n by 1000
cout << " n = " << n << endl;
n *= 1000; // multiplies n by 1000
cout << " n = " << n << endl;
return 0;
}
n = 1000
n = 1000000
n = 1000000000
n = -727379968

‫ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺑﻴﺸﺘﺮ‬،‫ﺍﻳﻦ ﻣﺜﺎﻝ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﺭﺍﻳﺎﻧﻪﺍﻱ ﻛﻪ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺍﺟﺮﺍ ﻛﺮﺩﻩ ﺍﺳﺖ‬
.‫ ﺑﻪ ﻃﻮﺭ ﺻﺤﻴﺢ ﺿﺮﺏ ﻛﻨﺪ‬1000 ‫ ﺭﺍ ﺑﺎ‬1,000,000,000‫ﺍﺯ‬

‫ ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬2 – 13 ‫* ﻣﺜﺎﻝ‬


‫ ﺭﺍ ﺑﻪ ﺗﻮﺍﻥ‬x ‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺷﺒﻴﻪ ﭼﻴﺰﻱ ﺍﺳﺖ ﻛﻪ ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻞ ﺫﻛﺮ ﺷﺪ؛ ﺑﻪ ﻃﻮﺭ ﻣﻜﺮﺭ‬
.‫ﻣﻲﺭﺳﺎﻧﺪ ﺗﺎ ﺍﻳﻦ ﻛﻪ ﺳﺮﺭﻳﺰ ﺷﻮﺩ‬
int main()
{ //prints x until it overflows:
float x=1000.0;
cout << "x = " << x << endl;
x *= x; //multiplies n by itself; i.e., it squares x
cout << "x = " << x << endl;
x *= x; //multiplies n by itself; i.e., it squares x
cout << "x = " << x << endl;
x *= x; //multiplies n by itself; i.e., it squares x
cout << "x = " << x << endl;
x *= x; //multiplies n by itself; i.e., it squares x
cout << "x = " << x << endl;
return 0;
}
x = 1000
x = 1e+06
x = 1e+12
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪48‬‬

‫‪x = 1e+24‬‬
‫‪x = inf‬‬

‫ﻣﺜﺎﻝ ﺑﺎﻻ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻳﻦ ﺭﺍﻳﺎﻧﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ ‪ x‬ﺭﺍ ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ ‪ 1000‬ﺑﻴﺶ ﺍﺯ ﺳﻪ ﺑﺎﺭ‬
‫ﻣﺠﺬﻭﺭ ﮐﻨﺪ‪ .‬ﺁﺧﺮﻳﻦ ﺧﺮﻭﺟﻲ ﻳﻌﻨﻲ ‪ inf‬ﻧﻤﺎﺩﻱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻣﻌﻨﺎﻱ ﺑﻲﻧﻬﺎﻳﺖ ﻣﻲﺑﺎﺷﺪ‬
‫)ﺍﻳﻦ ﻧﻤﺎﺩ ﻣﺨﻔﻒ ‪ infinity‬ﺑﻪ ﻣﻌﻨﺎﻱ ﺑﻲﺍﻧﺘﻬﺎ ﺍﺳﺖ(‪.‬‬
‫ﺑﻪ ﺗﻔﺎﻭﺕ ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩ ﺻﺤﻴﺢ ﻭ ﺳﺮﺭﻳﺰﻱ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺗﻮﺟﻪ ﮐﻨﻴﺪ‪ .‬ﻭﻗﺘﻲ ﻳﮏ‬
‫ﻋﺪﺩ ﺻﺤﻴﺢ ﺳﺮﺭﻳﺰ ﺷﻮﺩ‪ ،‬ﻋﺪﺩ ﺳﺮﺭﻳﺰ ﺷﺪﻩ ﺑﻪ ﻳﮏ ﻣﻘﺪﺍﺭ ﻣﻨﻔﻲ »ﮔﺮﺩﺍﻧﻴﺪﻩ« ﻣﻲﺷﻮﺩ ﺍﻣﺎ‬
‫ﻭﻗﺘﻲ ﻳﮏ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺳﺮﺭﻳﺰ ﺷﻮﺩ‪ ،‬ﻧﻤﺎﺩ ‪ inf‬ﺑﻪ ﻣﻌﻨﺎﻱ ﺑﻲﻧﻬﺎﻳﺖ ﺭﺍ ﺑﻪ ﺩﺳﺖ‬
‫ﻣﻲﺩﻫﺪ‪ ،‬ﻧﺸﺎﻧﻪﺍﻱ ﻣﺨﺘﺼﺮ ﻭ ﻣﻔﻴﺪ‪.‬‬

‫‪1‬‬
‫‪ 2 – 15‬ﺧﻄﺎﻱ ﮔﺮﺩ ﮐﺮﺩﻥ‬
‫ﺧﻄﺎﻱ ﮔﺮﺩ ﻛﺮﺩﻥ ﻧﻮﻉ ﺩﻳﮕﺮﻱ ﺍﺯ ﺧﻄﺎﺳﺖ ﻛﻪ ﺍﻏﻠﺐ ﻭﻗﺘﻲ ﺭﺍﻳﺎﻧﻪﻫﺎ ﺭﻭﻱ ﺍﻋﺪﺍﺩ‬
‫ﺣﻘﻴﻘﻲ ﻣﺤﺎﺳﺒﻪ ﻣﻲﻛﻨﻨﺪ‪ ،‬ﺭﺥ ﻣﻲﺩﻫﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﻋﺪﺩ ‪ 1/3‬ﻣﻤﻜﻦ ﺍﺳﺖ ﺑﻪ ﺻﻮﺭﺕ‬
‫ﻧﻴﺴﺖ‪ .‬ﺑﻪ ﺍﻳﻦ ﺍﺧﺘﻼﻑ‪ ،‬ﺧﻄﺎﻱ ﮔﺮﺩ‬ ‫‪ 0.333333‬ﺫﺧﻴﺮﻩ ﺷﻮﺩ ﻛﻪ ﺩﻗﻴﻘﺎ ﻣﻌﺎﺩﻝ ‪1/3‬‬
‫ﻛﺮﺩﻥ ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺍﻳﻦ ﺧﻄﺎ ﺍﺯ ﺁﻥﺟﺎ ﻧﺎﺷﻲ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻋﺪﺍﺩﻱ ﻣﺜﻞ ‪ 1/3‬ﻣﻘﺪﺍﺭ ﺩﻗﻴﻖ‬
‫ﻧﺪﺍﺭﻧﺪ ﻭ ﺭﺍﻳﺎﻧﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺭﺍ ﭘﻴﺪﺍ ﮐﻨﺪ‪ ،‬ﭘﺲ ﻧﺰﺩﻳﮏﺗﺮﻳﻦ ﻋﺪﺩ ﻗﺎﺑﻞ ﻣﺤﺎﺳﺒﻪ ﺭﺍ‬
‫ﺑﻪ ﺟﺎﻱ ﭼﻨﻴﻦ ﺍﻋﺪﺍﺩﻱ ﻣﻨﻈﻮﺭ ﻣﻲﮐﻨﺪ‪ .‬ﺩﺭ ﺑﻌﻀﻲ ﺣﺎﻻﺕ‪ ،‬ﺍﻳﻦ ﺧﻄﺎﻫﺎ ﻣﻲﺗﻮﺍﻧﺪ ﻣﺸﻜﻼﺕ‬
‫ﺣﺎﺩﻱ ﺭﺍ ﺍﻳﺠﺎﺩ ﻛﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 14‬ﺧﻄﺎﻱ ﮔﺮﺩ ﮐﺮﺩﻥ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺤﺎﺳﺒﺎﺕ ﺳﺎﺩﻩﺍﻱ ﺭﺍ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ ﺗﺎ ﺧﻄﺎﻱ ﮔﺮﺩ ﻛﺮﺩﻥ ﺭﺍ ﻧﺸﺎﻥ ﺩﻫﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ //illustrates round-off error:‬‬
‫;‪double x = 1000/3.0‬‬
‫;‪cout << "x = " << x << endl‬‬ ‫‪// x = 1000/3‬‬
‫;‪double y = x-333.0‬‬
‫;‪cout << "y = " << y << endl‬‬ ‫‪// y = 1/3‬‬
‫;‪double z = 3*y-1.0‬‬

‫‪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

‫ ﺧﻄﺎﻱ ﮔﺮﺩ ﮐﺮﺩﻥ ﭘﻨﻬﺎﻥ‬2 – 15 ‫* ﻣﺜﺎﻝ‬


‫ ﺭﻳﺸﻪﻫﺎﻱ ﺍﻳﻦ ﻣﻌﺎﺩﻟﻪﻫﺎ ﺭﺍ ﭘﻴﺪﺍ‬،‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺭﺍﺑﻂۀ ﻣﻌﺎﺩﻻﺕ ﺩﺭﺟﻪ ﺩﻭﻡ‬
:‫ﻣﻲﮐﻨﺪ‬
#include <cmath> //defines the sqrt() function
#include <iostream>
using namespace std;
int main()
{ //implements the quadratic formula
float a, b, c;
cout << "Enter the coefficients of a quadratic equation:"
<< endl;
cout << "\ta: ";
cin >> a;
cout << "\tb: ";
cin >> b;
cout << "\tc: ";
cin >> c;
cout << "The equation is: " << a << "*x*x + " << b
<< "*x + " << c << " = 0" << endl;
float d = b*b - 4*a*c; // discriminant
float sqrtd = sqrt(d);
float x1 = (-b + sqrtd /(2*a);
float x2 = (-b - sqrtd /(2*a);
cout << "The solutions are:" << endl;
cout << "\tx1 = " << x1 << endl;
cout << "\tx2 = " << x2 << endl;
cout << "check:" << endl;
cout << "\ta+x1*x1 + b*x1 + c = " << a*x1*x1 + b*x1 + c
<< endl;
cout << "\ta+x2*x2 + b*x2 + c = " << a*x2*x2 + b*x2 + c
<< endl;
return 0;
}
‫‪51‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺿﺮﺍﻳﺐ ‪ 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 .‬ﻳﮏ ﭘﺎﺳﺦ ﮔﺮﺩﺷﺪﻩ ﺍﺳﺖ ﻧﻪ ﻳﮏ ﭘﺎﺳﺦ ﺩﻗﻴﻖ‪ .‬ﺍﻳﻦ ﭘﺎﺳﺦ‬
‫ﮔﺮﺩﺷﺪﻩ ﺩﻭﺑﺎﺭﻩ ﺩﺭ ﻳﮏ ﻣﺤﺎﺳﺒﻪ ﺩﻳﮕﺮ ﺷﺮﮐﺖ ﻣﻲﮐﻨﺪ‪ .‬ﭘﺎﺳﺦ ﺍﻳﻦ ﻣﺤﺎﺳﺒﻪ ﻫﻢ ﮔﺮﺩﺷﺪﻩ‬
‫ﺍﺳﺖ‪ .‬ﭘﺲ ﺍﻧﺤﺮﺍﻑ ﺍﺯ ﺟﻮﺍﺏ ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ ﻭ ﻧﺘﻴﺠﻪﺍﻱ ﺩﻭﺭ ﺍﺯ ﺍﻧﺘﻈﺎﺭ ﺑﻪ ﺑﺎﺭ ﻣﻲﺁﻭﺭﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 16‬ﺍﻧﻮﺍﻉ ﺩﻳﮕﺮﻱ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ‬


‫ﺩﻭﺑﺎﺭﻩ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﻣﺤﺎﺳﺐۀ ﺭﻳﺸﻪﻫﺎ ﺑﺮﮔﺮﺩﻳﻢ‪ .‬ﺑﻪ ﺍﺟﺮﺍﻱ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪:‬‬
‫‪Enter the coeficients of a quadratic equation:‬‬
‫‪a: 1‬‬
‫‪b: 2‬‬
‫‪c: 3‬‬
‫‪The equation is: 1*x*x + 2*x + 3 = 0‬‬
‫‪The solutions are:‬‬
‫‪x1 = nan‬‬
‫‪x2 = nan‬‬
‫‪check:‬‬
‫‪a*x1*x1 + b*x1 + c = nan‬‬
‫‪a*x2*x2 + b*x2 + c = nan‬‬
‫‪53‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫ﺩﺭ ﺍﻳﻦ ﺍﺟﺮﺍ ﺳﻌﻲ ﺷﺪﻩ ﺗﺎ ﻣﻌﺎﺩﻟﻪ ‪ 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‬ﺻﻔﺮ ﺍﺳﺖ ﻭ ﺩﺭ ﺣﻴﻦ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺳﻌﻲ ﻣﻲﺷﻮﺩ‬
‫ﻋﺪﺩﻱ ﺑﺮ ﺻﻔﺮ ﺗﻘﺴﻴﻢ ﺷﻮﺩ‪ .‬ﻳﻌﻨﻲ ﺑﺮﻧﺎﻣﻪ ﻣﻌﺎﺩﻝۀ ﺯﻳﺮ ﺭﺍ ﺣﻞ ﻣﻲﮐﻨﺪ‪:‬‬

‫‪− b + b 2 − 4ac − (2) + (2)2 − 4(0)(5) − 2 + 2 0‬‬


‫= ‪x1‬‬ ‫=‬ ‫=‬ ‫=‬
‫‪2a‬‬ ‫)‪2(0‬‬ ‫‪0‬‬ ‫‪0‬‬

‫ﺩﺭ ﭼﻨﻴﻦ ﺣﺎﻟﺘﻲ ﺩﻭﺑﺎﺭﻩ ﭘﺎﺳﺦ ‪ nan‬ﺑﺪﺳﺖ ﻣﻲﺁﻳﺪ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺑﺮﺍﻱ ‪ x2‬ﺩﺍﺭﻳﻢ‪:‬‬

‫‪− b − b 2 − 4ac − (2) − (2) 2 − 4(0)(5) − 2 − 2 − 4‬‬


‫= ‪x2‬‬ ‫=‬ ‫=‬ ‫=‬
‫‪2a‬‬ ‫)‪2(0‬‬ ‫‪0‬‬ ‫‪0‬‬

‫ﭘﺎﺳﺦ ﺍﻳﻦ ﺗﻘﺴﻴﻢ‪ ،‬ﻋﺒﺎﺭﺕ ‪ –inf‬ﻳﻌﻨﻲ ﺑﻲﻧﻬﺎﻳﺖ ﻣﻨﻔﻲ ﺍﺳﺖ‪.‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪54‬‬

‫ﺳﻪ ﻧﺸﺎﻥۀ ‪ nan‬ﻭ ‪ inf‬ﻭ ‪ –inf‬ﺛﺎﺑﺖﻫﺎﻱ ﻋﺪﺩﻱ ﻫﺴﺘﻨﺪ‪ .‬ﻳﻌﻨﻲ ﻣﻲﺗﻮﺍﻧﻴﺪ ﺍﻳﻦ‬
‫ﻣﻘﺎﺩﻳﺮ ﺭﺍ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺕ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﺪ ﺍﻣﺎ ﻧﺘﻴﺠﻪ ﻣﻌﻤﻮﻻ ﺑﻲﻓﺎﻳﺪﻩ ﺍﺳﺖ‪ .‬ﻣﺜﻼ ﻣﻲﺗﻮﺍﻧﻴﺪ‬
‫ﻋﺪﺩﻱ ﺭﺍ ﺑﺎ ‪ inf‬ﺟﻤﻊ ﮐﻨﻴﺪ ﻳﺎ ﺍﺯ ﺁﻥ ﺗﻔﺮﻳﻖ ﻧﻤﺎﻳﻴﺪ ﺍﻣﺎ ﻧﺘﻴﺠﻪ ﺑﺎﺯ ﻫﻢ ‪ inf‬ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪.‬‬

‫‪ 2 – 16‬ﺣﻮﺯۀ ﻣﺘﻐﻴﺮﻫﺎ‬
‫ﻣﺘﻐﻴﺮﻫﺎ ﺑﺨﺶ ﻣﻬﻤﻲ ﺍﺯ ﻫﺮ ﺑﺮﻧﺎﻣﻪ ﻫﺴﺘﻨﺪ‪ .‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻳﻲ ﺑﺎ ﻧﻮﻉ ﻧﺎﻣﻨﺎﺳﺐ‬
‫ﺳﺒﺐ ﻫﺪﺭ ﺭﻓﺘﻦ ﺣﺎﻓﻈﻪ ﻭ ﮐﺎﻫﺶ ﺳﺮﻋﺖ ﻭ ﺍﻓﺰﺍﻳﺶ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻧﺘﺨﺎﺏ‬
‫ﻧﺎﻡﻫﺎﻱ ﻧﺎﻣﻔﻬﻮﻡ ﻳﺎ ﻧﺎﻗﺺ ﺳﺒﺐ ﮐﺎﻫﺶ ﺧﻮﺍﻧﺎﻳﻲ ﺑﺮﻧﺎﻣﻪ ﻭ ﺍﻓﺰﺍﻳﺶ ﺧﻄﺎﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪1‬‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎ ﺩﺭ ﺣﻮﺯۀ ﻧﺎﻣﻨﺎﺳﺐ ﻫﻢ ﺳﺒﺐ ﺑﺮﻭﺯ ﺧﻄﺎﻫﺎﻳﻲ ﻣﻲﺷﻮﺩ‪» .‬ﺣﻮﺯﻩ‬
‫ﻣﺘﻐﻴﺮ« ﻣﺤﺪﻭﺩﻩﺍﻱ ﺍﺳﺖ ﮐﻪ ﻳﮏ ﻣﺘﻐﻴﺮ ﺧﺎﺹ ﺍﺟﺎﺯﻩ ﺩﺍﺭﺩ ﺩﺭ ﺁﻥ ﻣﺤﺪﻭﺩﻩ ﺑﻪ ﮐﺎﺭ ﺭﻭﺩ ﻳﺎ‬
‫ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ‪.‬‬
‫ﺍﺻﻄﻼﺡ »ﺑﻠﻮﮎ‪ «2‬ﺩﺭ ‪ C++‬ﻭﺍﮊﻩ ﻣﻨﺎﺳﺒﻲ ﺍﺳﺖ ﮐﻪ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻭﺳﻴﻞۀ ﺁﻥ ﺣﻮﺯۀ‬
‫ﻣﺘﻐﻴﺮ ﺭﺍ ﻣﺸﺨﺺ ﻧﻤﻮﺩ‪ .‬ﻳﮏ ﺑﻠﻮﮎ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﻗﺴﻤﺘﻲ ﺍﺯ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺖ ﮐﻪ ﺩﺭﻭﻥ ﻳﮏ ﺟﻔﺖ‬
‫ﻋﻼﻣﺖ ﮐﺮﻭﺷﻪ } { ﻣﺤﺪﻭﺩ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﺗﺎﮐﻨﻮﻥ ﺩﻳﺪﻳﻢ ﺍﺯ ﺑﻠﻮﮎ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ‪ .‬ﻫﻤﻴﺸﻪ ﺑﻌﺪ ﺍﺯ ﻋﺒﺎﺭﺕ )(‪ int main‬ﻳﮏ ﮐﺮﻭﺷﻪ ﺑﺎﺯ { ﮔﺬﺍﺷﺘﻪﺍﻳﻢ‬
‫ﻭ ﺩﺭ ﭘﺎﻳﺎﻥ ﺑﺮﻧﺎﻣﻪ ﻳﮏ ﮐﺮﻭﺷﻪ ﺑﺴﺘﻪ } ﻗﺮﺍﺭ ﺩﺍﺩﻳﻢ‪ .‬ﭘﺲ ﺗﻤﺎﻡ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﺗﺎ ﮐﻨﻮﻥ ﺫﮐﺮ‬
‫ﺷﺪ‪ ،‬ﻳﮏ ﺑﻠﻮﮎ ﺩﺍﺷﺘﻪ‪ .‬ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ ﻣﻲﺗﻮﺍﻥ ﮔﻔﺖ ﮐﻪ ﺣﻮﺯۀ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺯ ﻣﺤﻞ ﺍﻋﻼﻥ ﺁﻥ‬
‫ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ﻭ ﺗﺎ ﭘﺎﻳﺎﻥ ﻫﻤﺎﻥ ﺑﻠﻮﮎ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺧﺎﺭﺝ ﺍﺯ ﺁﻥ ﺑﻠﻮﮎ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﻣﺘﻐﻴﺮ‬
‫ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ‪ .‬ﻫﻤﭽﻨﻴﻦ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﻣﺘﻐﻴﺮ ﺍﻋﻼﻥ ﺷﻮﺩ ﻧﻤﻲﺗﻮﺍﻥ ﺁﻥ ﺭﺍ ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﻮﺩ‪.‬‬
‫ﻣﺜﺎﻝ ﺯﻳﺮ ﺭﺍ ﺑﺮﺭﺳﻲ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 17‬ﺣﻮﺯۀ ﻣﺘﻐﻴﺮﻫﺎ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺧﻄﺎﺩﺍﺭ ﺍﺳﺖ‪:‬‬
‫)(‪int main‬‬
‫‪{ //illustrates the scope of variables:‬‬
‫;‪x = 11‬‬ ‫‪// ERROR: this is not in the scope of x‬‬
‫;‪int x‬‬
‫‪55‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫{‬
‫;‪x = 22‬‬ ‫‪// OK: this is in the scope of x‬‬
‫;‪y = 33‬‬ ‫‪// ERROR: this is not in the scope of y‬‬
‫;‪int y‬‬

‫‪1 – Scope‬‬ ‫‪2 - Block‬‬

‫;‪x = 44‬‬ ‫‪// OK: this is in the scope of x‬‬


‫;‪y = 55‬‬ ‫‪// OK: this is in the scope of y‬‬
‫}‬
‫;‪x = 66‬‬ ‫‪// OK: this is in the scope of x‬‬
‫;‪y = 77‬‬ ‫‪// ERROR: this is not in the scope of y‬‬
‫;‪return 0‬‬
‫}‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺩﻭ ﺑﻠﻮﮎ ﺗﻮﺩﺭﺗﻮ ﺩﺍﺭﺩ‪ .‬ﺍﻭﻟﻴﻦ ﺑﻠﻮﮎ ﺑﻌﺪ ﺍﺯ ﻋﺒﺎﺭﺕ )(‪ int main‬ﺷﺮﻭﻉ‬
‫ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﺧﻂ ﺁﺧﺮ ﺑﺮﻧﺎﻣﻪ ﺑﺴﺘﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺑﻠﻮﮎ ﺩﺍﺧﻠﻲ ﻧﻴﺰ ﺍﺯ ﺧﻂ ﭘﻨﺠﻢ ﺁﻏﺎﺯ ﻣﻲﺷﻮﺩ‬
‫ﻭ ﺩﺭ ﺧﻂ ﺩﻫﻢ ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ‪ .‬ﻧﺤﻮۀ ﺗﻮﺭﻓﺘﮕﻲ ﺧﻄﻮﻁ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺩﺭﮎ ﻭ ﺗﺸﺨﻴﺺ ﺷﺮﻭﻉ ﻭ‬
‫ﭘﺎﻳﺎﻥ ﺑﻠﻮﮎﻫﺎ ﮐﻤﮏ ﻣﻲﮐﻨﺪ‪ .‬ﺧﻂ ﭘﻨﺠﻢ ﺗﺎ ﺩﻫﻢ ﺗﻮﺭﻓﺘﮕﻲ ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﺩ‪ ،‬ﻳﻌﻨﻲ ﺍﻳﻦ ﺧﻄﻮﻁ‬
‫ﺗﺸﮑﻴﻞ ﻳﮏ ﺑﻠﻮﮎ ﻣﻲﺩﻫﻨﺪ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺧﻂ ﺩﻫﻢ ﺑﻪ ﺑﻌﺪ ﺗﻮﺭﻓﺘﮕﻲ ﺑﻪ ﺍﻧﺪﺍﺯۀ ﺧﻂ ﺳﻮﻡ ﻭ‬
‫ﭼﻬﺎﺭﻡ ﺩﺍﺭﺩ‪ ،‬ﻳﻌﻨﻲ ﻣﺠﻤﻮﻋﻪ ﺍﻳﻦ ﺧﻄﻮﻁ ﻫﻢ ﺩﺭ ﻳﮏ ﺣﻮﺯۀ ﻣﺸﺘﺮﮎ ﻗﺮﺍﺭ ﺩﺍﺭﻧﺪ‪.‬‬
‫ﺍﻭﻟﻴﻦ ﺧﻄﺎ ﺩﺭ ﺧﻂ ﺳﻮﻡ ﺭﺥ ﺩﺍﺩﻩ‪ .‬ﻣﺘﻐﻴﺮ ‪ x‬ﺩﺭ ﺧﻂ ﭼﻬﺎﺭﻡ ﺍﻋﻼﻥ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﭘﺲ‬
‫ﺣﻮﺯۀ ‪ x‬ﺍﺯ ﺧﻂ ﭼﻬﺎﺭﻡ ﺑﻪ ﺑﻌﺪ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ‪ ،‬ﺩﺭ ﺣﺎﻟﻲ ﮐﻪ ﺩﺭ ﺧﻂ ﺳﻮﻡ ﻣﺘﻐﻴﺮ ‪x‬‬
‫ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﻭ ﺍﻳﻦ ﺧﺎﺭﺝ ﺍﺯ ﻣﺤﺪﻭﺩۀ ‪ x‬ﺍﺳﺖ‪.‬‬
‫ﺩﻭﻣﻴﻦ ﺧﻄﺎ ﺩﺭ ﺧﻂ ﺷﺸﻢ ﺍﺗﻔﺎﻕ ﺍﻓﺘﺎﺩﻩ ﺍﺳﺖ‪ .‬ﻣﺘﻐﻴﺮ ‪ y‬ﺩﺭ ﺧﻂ ﻫﻔﺘﻢ ﺍﻋﻼﻥ ﺷﺪﻩ‪.‬‬
‫ﭘﺲ ﺣﻮﺯۀ ‪ y‬ﺍﺯ ﺧﻂ ﻫﻔﺘﻢ ﺑﻪ ﺑﻌﺪ ﺍﺳﺖ‪ ،‬ﺩﺭ ﺣﺎﻟﻲ ﮐﻪ ﺩﺭ ﺧﻂ ﺷﺸﻢ ‪ y‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﻭ‬
‫ﺍﻳﻦ ﺧﺎﺭﺝ ﺍﺯ ﻣﺤﺪﻭﺩۀ ‪ y‬ﺍﺳﺖ‪.‬‬
‫ﺳﻮﻣﻴﻦ ﺧﻄﺎ ﮐﻪ ﺩﺭ ﺧﻂ ﺩﻭﺍﺯﺩﻫﻢ ﺭﻭﻱ ﺩﺍﺩﻩ ﻧﻴﺰ ﻣﺮﺑﻮﻁ ﺑﻪ ‪ y‬ﺍﺳﺖ‪ .‬ﮔﺮﭼﻪ ‪ y‬ﺩﺭ‬
‫ﺧﻄﻮﻁ ﻗﺒﻠﻲ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﻣﺎ ﺍﻳﻦ ﺗﻌﺮﻳﻒ ﺩﺭ ﻳﮏ ﺑﻠﻮﮎ ﺩﺍﺧﻠﻲ ﺑﻮﺩﻩ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺑﻠﻮﮎ‬
‫ﺩﺍﺧﻠﻲ ﺩﺭ ﺧﻂ ﺩﻫﻢ ﺑﻪ ﭘﺎﻳﺎﻥ ﺭﺳﻴﺪﻩ ﺍﺳﺖ‪ .‬ﭘﺲ ﺗﻤﺎﻡ ﺗﻌﺎﺭﻳﻔﻲ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﺑﻠﻮﮎ ﻭﺟﻮﺩ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪56‬‬

‫ﺩﺍﺷﺘﻪ ﻧﻴﺰ ﻓﻘﻂ ﺗﺎ ﺧﻂ ﺩﻫﻢ ﺍﻋﺘﺒﺎﺭ ﺩﺍﺭﺩ‪ .‬ﻳﻌﻨﻲ ﺣﻮﺯۀ ‪ y‬ﻓﻘﻂ ﺍﺯ ﺧﻂ ﻫﻔﺘﻢ ﺗﺎ ﺧﻂ ﺩﻫﻢ‬
‫ﺍﺳﺖ‪ .‬ﻟﺬﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺩﺭ ﺧﻂ ﺩﻭﺍﺯﺩﻫﻢ ﮐﻪ ﺧﺎﺭﺝ ﺍﺯ ﻣﺤﺪﻭﺩﻩ ‪ y‬ﺍﺳﺖ‪ ،‬ﺁﻥ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺑﺮﺩ‪.‬‬
‫ﻣﺜﺎﻝ ﺑﺎﻻ ﻣﻄﻠﺐ ﻇﺮﻳﻔﻲ ﺭﺍ ﺑﻴﺎﻥ ﻣﻲﮐﻨﺪ‪ :‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺩﺭ ﻳﮏ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﭼﻨﺪ ﻣﺘﻐﻴﺮ‬
‫ﻣﺘﻔﺎﻭﺕ ﺑﺎ ﻳﮏ ﻧﺎﻡ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ ﺑﻪ ﺷﺮﻃﻲ ﮐﻪ ﺩﺭ ﺣﻮﺯﻩﻫﺎﻱ ﻣﺸﺘﺮﮎ ﻧﺒﺎﺷﻨﺪ‪ .‬ﺁﺧﺮﻳﻦ ﺑﺮﻧﺎﻡۀ‬
‫ﻓﺼﻞ ﺍﻭﻝ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ ﺑﻪ ﺧﻮﺑﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 2 – 18‬ﻣﺘﻐﻴﺮﻫﺎﻱ ﺗﻮﺩﺭﺗﻮ‬


‫;‪int x = 11‬‬ ‫‪// this x is global‬‬

‫)(‪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‬‬

‫‪ ‐3‬ﺩﻭ ﺩﺳﺘﻮﺭ ﺯﻳﺮ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﻫﻢ ﺩﺍﺭﻧﺪ؟‬


‫;'‪char ch = 'A‬‬
‫;‪char ch = 65‬‬

‫‪ ‐4‬ﺑﺮﺍﻱ ﭘﻴﺪﺍ ﻛﺮﺩﻥ ﻛﺎﺭﺍﻛﺘﺮﻱ ﻛﻪ ﻛﺪ ﺍﺳﻜﻲ ﺁﻥ ‪ 100‬ﺍﺳﺖ‪ ،‬ﭼﻪ ﻛﺪﻱ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﺪ ﺍﺟﺮﺍ‬
‫ﻛﻨﻴﺪ؟‬
‫‪ ‐5‬ﻣﻌﻨﺎﻱ »ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ« ﭼﻴﺴﺖ ﻭ ﭼﺮﺍ ﺑﻪ ﺍﻳﻦ ﻧﺎﻡ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ؟‬
‫‪ ‐6‬ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩﻱ ﭼﻴﺴﺖ؟‬
‫‪ ‐7‬ﻓﺮﻕ ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩ ﺻﺤﻴﺢ ﺑﺎ ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﭼﻴﺴﺖ؟‬
‫‪ ‐8‬ﺧﻄﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﭼﻴﺴﺖ؟ ﻣﺜﺎﻝﻫﺎﻳﻲ ﺑﺮﺍﻱ ﺩﻭ ﻧﻮﻉ ﻣﺘﻔﺎﻭﺕ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺑﻨﻮﻳﺴﻴﺪ‪.‬‬
‫‪ ‐9‬ﺧﻄﺎﻱ ﺯﻣﺎﻥ ﻛﺎﻣﭙﺎﻳﻞ ﭼﻴﺴﺖ؟ ﻣﺜﺎﻝﻫﺎﻳﻲ ﺑﺮﺍﻱ ﺩﻭ ﻧﻮﻉ ﻣﺘﻔﺎﻭﺕ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ‬
‫ﻛﺎﻣﭙﺎﻳﻞ ﺑﻨﻮﻳﺴﻴﺪ‪.‬‬
‫‪ ‐10‬ﻛﺪ ﺯﻳﺮ ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺍﺭﺩ؟‬
‫;}‪enum Semester {FALL, SPRING, SUMMER‬‬
‫;}‪enum Season {SPRING, SUMMER, FALL, WINTER‬‬

‫‪ ‐11‬ﻛﺪ ﺯﻳﺮ ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺍﺭﺩ؟‬


‫‪61‬‬ ‫ﻓﺼﻞ دوم ‪ /‬اﻧﻮاع اﺻﻠﯽ‬

‫;}"‪enum Friends {"Jerry", "Henry", "W.D‬‬

‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪ ‐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‬‬

‫‪ Condition‬ﮐﻪ ﺷﺮﻁ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ ﻳﻚ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﺍﺳﺖ )ﻋﺒﺎﺭﺗﻲ ﮐﻪ ﺑﺎ ﻳﮏ‬


‫ﻣﻘﺪﺍﺭ ﺻﺤﻴﺢ ﺑﺮﺁﻭﺭﺩ ﻣﻲﺷﻮﺩ( ﻭ ‪ statement‬ﻣﻲﺗﻮﺍﻧﺪ ﻫﺮ ﻓﺮﻣﺎﻥ ﻗﺎﺑﻞ ﺍﺟﺮﺍ ﺑﺎﺷﺪ‪.‬‬
‫‪ Statement‬ﻭﻗﺘﻲ ﺍﺟﺮﺍ ﺧﻮﺍﻫﺪ ﺷﺪ ﻛﻪ ‪ condition‬ﻣﻘﺪﺍﺭ ﻏﻴﺮ ﺻﻔﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪.‬‬

‫‪1 – Selection‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪64‬‬

‫ﺩﻗﺖ ﻛﻨﻴﺪ ﻛﻪ ﺷﺮﻁ ﺑﺎﻳﺪ ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﺷﻮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐1‬ﺁﺯﻣﻮﻥ ﺑﺨﺶﭘﺬﻳﺮﻱ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺑﺮﺭﺳﻲ ﻣﻲﻛﻨﺪ ﻛﻪ ﻳﻚ ﻋﺪﺩ ﺻﺤﻴﺢ ﻣﺜﺒﺖ ﺑﺮ ﻋﺪﺩ ﺩﻳﮕﺮ ﻗﺎﺑﻞ ﺗﻘﺴﻴﻢ‬
‫ﻧﺒﺎﺷﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n, d‬‬
‫;" ‪cout << "Enter two positive integers:‬‬
‫;‪cin >> n >> d‬‬
‫" ‪if (n%d) cout << n << " is not divisible by‬‬
‫;‪<< d << endl‬‬
‫}‬

‫ﺩﺭ ﺍﻭﻟﻴﻦ ﺍﺟﺮﺍ‪ ،‬ﺍﻋﺪﺍﺩ ‪ 66‬ﻭ ‪ 7‬ﺭﺍ ﻭﺍﺭﺩ ﻣﻲﻛﻨﻴﻢ‪:‬‬


‫‪Enter two positive integers: 66 7‬‬
‫‪66 is not divisible by 7‬‬

‫ﻣﻘﺪﺍﺭ ‪ 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‬‬

‫ﺩﺳﺘﻮﺭ ‪ if..else‬ﻣﻮﺟﺐ ﻣﻲﺷﻮﺩ ﺑﺴﺘﻪ ﺑﻪ ﺍﻳﻦ ﮐﻪ ﺷﺮﻁ ﺩﺭﺳﺖ ﺑﺎﺷﺪ ﻳﺎ ﺧﻴﺮ‪،‬‬


‫ﻳﻜﻲ ﺍﺯ ﺩﻭ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻓﺮﻋﻲ ﺍﺟﺮﺍ ﮔﺮﺩﺩ‪ .‬ﻧﺤﻮ ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫;‪if (condition) statement1‬‬
‫;‪else statement2‬‬

‫‪ condition‬ﻫﻤﺎﻥ ﺷﺮﻁ ﻣﺴﺎﻟﻪ ﺍﺳﺖ ﮐﻪ ﻳﻚ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﻣﻲﺑﺎﺷﺪ ﻭ‬


‫‪ statement1‬ﻭ ‪ statement2‬ﻓﺮﻣﺎﻥﻫﺎﻱ ﻗﺎﺑﻞ ﺍﺟﺮﺍ ﻫﺴﺘﻨﺪ‪ .‬ﺍﮔﺮ ﻣﻘﺪﺍﺭ ﺷﺮﻁ‪ ،‬ﻏﻴﺮ‬
‫ﺻﻔﺮ ﺑﺎﺷﺪ‪ statement1 ،‬ﺍﺟﺮﺍ ﺧﻮﺍﻫﺪ ﺷﺪ ﻭﮔﺮﻧﻪ ‪ statement2‬ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐2‬ﻳﮏ ﺁﺯﻣﻮﻥ ﺩﻳﮕﺮ ﻗﺎﺑﻠﻴﺖ ﺗﻘﺴﻴﻢ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺎﻧﻨﺪ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 3‐1‬ﺍﺳﺖ ﺑﺠﺰ ﺍﻳﻦ ﻛﻪ ﺩﺳﺘﻮﺭ ‪ if‬ﺑﺎ ﺩﺳﺘﻮﺭ‬
‫‪ if..else‬ﺟﺎﻳﮕﺰﻳﻦ ﺷﺪﻩ ﺍﺳﺖ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n, d‬‬
‫;" ‪cout << " Enter two positive integers:‬‬
‫;‪cin >> n >> d‬‬
‫" ‪if (n%d) cout << n << " is not divisible by‬‬
‫;‪<< d << endl‬‬
‫;‪else cout << n << " is divisible by " << d << endl‬‬
‫}‬

‫ﺣﺎﻻ ﻭﻗﺘﻲ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﻋﺪﺍﺩ ‪ 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‬ﺑﺮﺍﺑﺮ ﺑﺎ ﺻﻔﺮ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ‪ ،‬ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﻲ ﻛﻪ ﺍﻳﻦ ﺷﺮﻁ ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐3‬ﻛﻤﻴﻦۀ ﺩﻭ ﻋﺪﺩ ﺻﺤﻴﺢ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﺯ ﺩﻭ ﻋﺪﺩ ﺻﺤﻴﺢ ﻭﺭﻭﺩﻱ‪ ،‬ﮐﺪﺍﻡ ﻳﮏ ﮐﻮﭼﮏﺗﺮ‬
‫ﺍﺳﺖ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int m, n‬‬
‫;" ‪cout << "Enter two integers:‬‬
‫;‪cin >> m >> n‬‬
‫;‪if ( m < n ) cout << m << " is the minimum." << endl‬‬
‫;‪else cout << n << " is the minimum." << endl‬‬
‫}‬
‫‪Enter two integers: 77 55‬‬
‫‪55 is the minimum.‬‬

‫ﺩﻗﺖ ﮐﻨﻴﺪ ﻛﻪ ﺩﺭ ‪ C++‬ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺑﺎ ﻋﻤﻠﮕﺮ ﺑﺮﺍﺑﺮﻱ ﻓﺮﻕ ﺩﺍﺭﺩ‪ .‬ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ‬
‫ﻳﮏ ﻣﺴﺎﻭﻱ ﺗﮑﻲ " = " ﺍﺳﺖ ﻭﻟﻲ ﻋﻤﻠﮕﺮ ﺑﺮﺍﺑﺮﻱ‪ ،‬ﺩﻭ ﻣﺴﺎﻭﻱ " = = " ﺍﺳﺖ‪ .‬ﻣﺜﻼ‬
‫‪67‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫ﺩﺳﺘﻮﺭ ;‪ x = 33‬ﻣﻘﺪﺍﺭ ‪ 33‬ﺭﺍ ﺩﺭ ‪ x‬ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﻭﻟﻲ ﺩﺳﺘﻮﺭ ;‪ x == 33‬ﺑﺮﺭﺳﻲ‬


‫ﻣﻲﮐﻨﺪ ﮐﻪ ﺁﻳﺎ ﻣﻘﺪﺍﺭ ‪ x‬ﺑﺎ ‪ 33‬ﺑﺮﺍﺑﺮ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ‪ .‬ﺩﺭﮎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﺍﻫﻤﻴﺖ ﺯﻳﺎﺩﻱ ﺩﺍﺭﺩ‪.‬‬
‫;‪x = 33‬‬ ‫ﻣﻘﺪﺍﺭ‪ 33‬ﺭﺍ ﺑﻪ ‪ X‬ﺗﺨﺼﻴﺺ ﻣﻲﺩﻫﺪ ‪//‬‬
‫;‪x == 33‬‬ ‫ﺻﻔﺮ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ )ﺑﻪ ﻣﻌﻨﻲ ﻧﺎﺩﺭﺳﺖ( ﻣﮕﺮ ﺍﻳﻦ ﻛﻪ ﻣﻘﺪﺍﺭ ‪ x‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 33‬ﺑﺎﺷﺪ ‪//‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐4‬ﻳﻚ ﺧﻄﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﻣﺘﺪﺍﻭﻝ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺧﻄﺎﺩﺍﺭ ﺍﺳﺖ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n‬‬
‫;" ‪cout << "Enter an integer:‬‬
‫;‪cin >> n‬‬
‫;‪if (n = 22) cout << "n = 22" << endl‬‬ ‫!‪// LOGICAL ERROR‬‬
‫;‪else cout << "n != 22" << endl‬‬
‫}‬
‫‪Enter an integer: 77‬‬
‫‪n = 22‬‬

‫ﻇﺎﻫﺮﺍ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻡۀ ﻓﻮﻕ ﺑﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﺍﺳﺖ ﮐﻪ ﻋﺪﺩﻱ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﻣﻲﺷﻮﺩ ﻭ ﺍﮔﺮ‬
‫ﺍﻳﻦ ﻋﺪﺩ ﺑﺎ ‪ 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‬ﻧﺎﻡ ﺩﺍﺭﺩ‪ .‬ﺍﻳﻦ ﻧﻮﻉ ﺧﻄﺎ‪،‬‬
‫ﺑﺪﺗﺮﻳﻦ ﻧﻮﻉ ﺧﻄﺎﻫﺎﺳﺖ‪ .‬ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﻛﺎﻣﭙﺎﻳﻞ )ﻣﺎﻧﻨﺪ ﺍﺯ ﻗﻠﻢ ﺍﻓﺘﺎﺩﻥ ﻳﻚ ﺳﻤﻴﻜﻮﻟﻦ( ﺑﻪ‬

‫‪1 – Logical Error‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪68‬‬

‫ﻭﺳﻴﻞۀ ﻛﺎﻣﭙﺎﻳﻠﺮ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ )ﻣﺎﻧﻨﺪ ﺗﻘﺴﻴﻢ ﺑﺮ ﺻﻔﺮ( ﻧﻴﺰ ﺑﻪ ﻭﺳﻴﻞۀ‬
‫ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﺧﻄﺎﻱ ﻣﻨﻄﻘﻲ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﺎ ﺍﻳﻦ ﺍﺑﺰﺍﺭﻫﺎ ﻛﺸﻒ ﮐﺮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐5‬ﻛﻤﻴﻦۀ ﺳﻪ ﻋﺪﺩ ﺻﺤﻴﺢ‬


‫ﺍﻳﻦ ﻣﺜﺎﻝ ﺷﺒﻴﻪ ﻣﺜﺎﻝ ‪ 3‐3‬ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﻛﻪ ﺍﺯ ﺳﻪ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﻣﻲﻛﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n1, n2, n3‬‬
‫;" ‪cout << "Enter three integers:‬‬
‫;‪cin >> n1 >> n2 >> n3‬‬
‫;‪int min=n1‬‬ ‫‪// now min <= n1‬‬
‫‪if (n2 < min) min = n2; // now min <= n1 and n2‬‬
‫‪if (n3 < min) min = n3; // now min <= n1 ,n2 ,and n3‬‬
‫;‪cout << "Their minimum is " << min << endl‬‬
‫}‬
‫‪Enter three integers: 77 33 55‬‬
‫‪Their minimum is 33‬‬

‫ﺳﻪ ﺗﻮﺿﻴﺢ ﺫﻛﺮ ﺷﺪﻩ ﺩﺭ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﻧﺤﻮۀ ﭘﻴﺸﺮﻓﺖ ﮐﺎﺭ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪ :‬ﺍﺑﺘﺪﺍ ‪ 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‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ‪ C++‬ﻳﮏ ﺑﻠﻮﮎ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻣﺎﻧﻨﺪ ﻳﮏ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﺗﮑﻲ ﺍﺳﺖ‪.‬‬


‫ﻳﻌﻨﻲ ﻫﺮ ﺟﺎ ﻛﻪ ﻳﻚ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﺗﻨﻬﺎ ﺑﺘﻮﺍﻧﺪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪ ،‬ﻳﻚ ﺑﻠﻮﻙ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻧﻴﺰ‬
‫ﻣﻲﺗﻮﺍﻧﺪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺗﻮﺟﻪ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐6‬ﻳﻚ ﺑﻠﻮﻙ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﺩﺭﻭﻥ ﻳﻚ ﺩﺳﺘﻮﺭ ‪if‬‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺩﻭ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﮔﺮﻓﺘﻪ ﻭ ﺑﻪ ﺗﺮﺗﻴﺐ ﺑﺰﺭﮒﺗﺮﻱ‪ ،‬ﺁﻥﻫﺎ ﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int x, y‬‬
‫;" ‪cout << "Enter two integers:‬‬
‫;‪cin >> x >> y‬‬
‫;‪if (x > y) { int temp = x‬‬
‫;‪x = y‬‬
‫;‪y = temp‬‬
‫}‬ ‫‪//swap x and y‬‬
‫;‪cout << x << " <= " << y << endl‬‬
‫}‬
‫‪Enter two integers: 66 44‬‬
‫‪44 <= 66‬‬

‫ﺳﻪ ﺩﺳﺘﻮﺭ ﺩﺭﻭﻥ ﺑﻠﻮﻙ‪ ،‬ﻣﻘﺎﺩﻳﺮ ‪ x‬ﻭ ‪ y‬ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﺑﺰﺭﮒﺗﺮﻱ ﻣﺮﺗﺐ ﻣﻲﻛﻨﻨﺪ ﺑﺪﻳﻦ ﺷﮑﻞ‬
‫ﻛﻪ ﺍﮔﺮ ﺁﻥﻫﺎ ﺧﺎﺭﺝ ﺍﺯ ﺗﺮﺗﻴﺐ ﺑﺎﺷﻨﺪ‪ ،‬ﺟﺎﻱ ﺁﻥ ﺩﻭ ﺭﺍ ﻋﻮﺽ ﻣﻲﻛﻨﻨﺪ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﺟﺎﺑﺠﺎﻳﻲ‬
‫ﺑﻪ ﺳﻪ ﮔﺎﻡ ﻣﺘﻮﺍﻟﻲ ﻭ ﻳﮏ ﻣﺤﻞ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻣﻮﻗﺘﻲ ﺍﺣﺘﻴﺎﺝ ﺩﺍﺭﻳﻢ ﻛﻪ ﺩﺭ ﺍﻳﻦﺟﺎ ‪temp‬‬
‫ﻧﺎﻣﻴﺪﻩ ﺷﺪﻩ‪ .‬ﺑﺮﻧﺎﻣﻪ ﻳﺎ ﺑﺎﻳﺪ ﻫﺮ ﺳﻪ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﺭﺍ ﺍﺟﺮﺍ ﻛﻨﺪ ﻭ ﻳﺎ ﻫﻴﭻ ﻳﻚ ﺭﺍ ﻧﺒﺎﻳﺪ ﺍﺟﺮﺍ‬
‫ﻛﻨﺪ‪ .‬ﻭﻗﺘﻲ ﺍﻳﻦ ﺳﻪ ﺩﺳﺘﻮﺭ ﺭﺍ ﺩﺭﻭﻥ ﺑﻠﻮﮎ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻗﺮﺍﺭ ﺩﻫﻴﻢ‪ ،‬ﻣﻨﻈﻮﺭ ﻓﻮﻕ ﺑﺮﺁﻭﺭﺩﻩ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﻣﺘﻐﻴﺮ ‪ temp‬ﺩﺭﻭﻥ ﺑﻠﻮﻙ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺳﺒﺐ ﻣﻲﺷﻮﺩ‬
‫ﻛﻪ ﻣﺘﻐﻴﺮ ﻣﺬﮐﻮﺭ ﺩﺭﻭﻥ ﺑﻠﻮﮎ‪ ،‬ﻳﻚ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ‪ 1‬ﺑﺎﺷﺪ‪ .‬ﻳﻌﻨﻲ ﺍﻳﻦ ﻣﺘﻐﻴﺮ ﻓﻘﻂ ﻭﻗﺘﻲ ﺍﻳﺠﺎﺩ‬
‫ﻣﻲﺷﻮﺩ ﮐﻪ ﺑﻠﻮﮎ ﺍﺟﺮﺍ ﺷﻮﺩ‪ .‬ﺍﮔﺮ ﺷﺮﻁ ﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﺪ )ﻳﻌﻨﻲ ‪ x<=y‬ﺑﺎﺷﺪ( ﻣﺘﻐﻴﺮ ‪temp‬‬
‫ﻫﺮﮔﺰ ﻣﻮﺟﻮﺩ ﻧﺨﻮﺍﻫﺪ ﺷﺪ‪ .‬ﺍﻳﻦ ﻣﺜﺎﻝ‪ ،‬ﺭﻭﺵ ﻣﻨﺎﺳﺒﻲ ﺑﺮﺍﻱ ﻣﺤﻠﻲ ﻛﺮﺩﻥ ﺍﺷﻴﺎ ﺭﺍ ﻧﺸﺎﻥ‬
‫ﻣﻲﺩﻫﺪ‪ ،‬ﻃﻮﺭﻱ ﻛﻪ ﺍﺷﻴﺎ ﻭﻗﺘﻲ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﻧﺪ ﻛﻪ ﺑﻪ ﺁﻥﻫﺎ ﻧﻴﺎﺯ ﺍﺳﺖ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺗﻮﺟﻪ ﮐﻨﻴﺪ‬
‫ﻛﻪ ﻳﻚ ﺑﺮﻧﺎﻡۀ ‪ C++‬ﺧﻮﺩﺵ ﻳﻚ ﺑﻠﻮﻙ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﺍﺳﺖ ﻛﻪ ﺗﻮﺳﻂ ﺗﺎﺑﻊ‬

‫‪1 – Local Variable‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪70‬‬

‫ﺍﺻﻠﻲ )(‪ main‬ﺳﺎﺧﺘﻪ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﻳﺎﺩﺁﻭﺭﻱ ﻣﻲﻛﻨﻴﻢ ﻛﻪ ﺣﻮﺯۀ ﻣﺘﻐﻴﺮ‪ ،‬ﻗﺴﻤﺘﻲ ﺍﺯ ﻳﻚ‬
‫ﺑﺮﻧﺎﻣﻪ ﺍﺳﺖ ﻛﻪ ﻣﺘﻐﻴﺮ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺭ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ)ﺑﺨﺶ ‪ .(1‐5‬ﺍﻳﻦ ﺣﻮﺯﻩ‪ ،‬ﺍﺯ ﻧﻘﻄﻪﺍﻱ‬
‫ﻛﻪ ﻣﺘﻐﻴﺮ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ ﺷﺮﻭﻉ ﺷﺪﻩ ﻭ ﺗﺎ ﭘﺎﻳﺎﻥ ﻫﻤﺎﻥ ﺑﻠﻮﻙ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﭘﺲ ﻳﻚ ﺑﻠﻮﻙ‬
‫ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﻋﻨﻮﺍﻥ ﻣﺤﺪﻭﺩۀ ﺣﻮﺯۀ ﻣﺘﻐﻴﺮ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪ .‬ﻳﮑﻲ ﺍﺯ ﻧﺘﺎﻳﺞ ﻣﻬﻢ ﺍﻳﻦ ﮐﺎﺭ ﺁﻥ ﺍﺳﺖ‬
‫ﮐﻪ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺘﻔﺎﻭﺗﻲ ﺑﺎ ﻳﮏ ﻧﺎﻡ ﺩﺭ ﻗﺴﻤﺖﻫﺎﻱ ﻣﺨﺘﻠﻒ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐7‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺑﻠﻮﻙﻫﺎ ﺑﻪ ﻋﻨﻮﺍﻥ ﻣﺤﺪﻭﺩۀ ﺣﻮﺯﻩ‬


‫ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺳﻪ ﻣﺘﻐﻴﺮ ﻣﺨﺘﻠﻒ ﺑﺎ ﻧﺎﻡ ‪ n‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n=44‬‬
‫;‪cout << "n = " << n << endl‬‬
‫;‪{ int n‬‬ ‫‪// scope extends over 4 lines‬‬
‫;" ‪cout << "Enter an integer:‬‬
‫;‪cin >> n‬‬
‫;‪cout << "n = " << n << endl‬‬
‫}‬
‫‪{ cout << " n = " << n << endl; // n that was declared first‬‬
‫}‬
‫;‪{ int n‬‬ ‫‪// scope extends over 2 lines‬‬
‫;‪cout << "n = " << n << endl‬‬
‫}‬
‫;‪cout << "n = " << n << endl‬‬ ‫‪// n that was declared first‬‬
‫}‬
‫‪n = 44‬‬
‫‪Enter an integer: 77‬‬
‫‪n = 77‬‬
‫‪n = 44‬‬
‫‪n = 4251897‬‬
‫‪n = 44‬‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺳﻪ ﺑﻠﻮﻙ ﺩﺍﺧﻠﻲ ﺩﺍﺭﺩ‪ .‬ﺍﻭﻟﻴﻦ ﺑﻠﻮﻙ ﻳﻚ ‪ 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‬ﺑﺎﺷﺪ‪.‬‬
‫ﺳﻪ ﻋﻤﻠﮕﺮ ﻣﻨﻄﻘﻲ ﺑﺎﻻ ﻣﻌﻤﻮﻻ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺟﺪﺍﻭﻝ ﺩﺭﺳﺘﻲ ﺑﻪ ﮔﻮﻥۀ ﺯﻳﺮ ﺑﻴﺎﻥ‬
‫ﻣﻲﺷﻮﻧﺪ‪:‬‬

‫‪p‬‬ ‫‪q‬‬ ‫‪P&&q‬‬ ‫‪p‬‬ ‫‪q‬‬ ‫‪p||q‬‬ ‫‪p‬‬ ‫‪!p‬‬


‫‪T‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪F‬‬
‫‪T‬‬ ‫‪F‬‬ ‫‪F‬‬ ‫‪T‬‬ ‫‪F‬‬ ‫‪T‬‬ ‫‪F‬‬ ‫‪T‬‬
‫‪F‬‬ ‫‪T‬‬ ‫‪F‬‬ ‫‪F‬‬ ‫‪T‬‬ ‫‪T‬‬
‫‪F‬‬ ‫‪F‬‬ ‫‪F‬‬ ‫‪F‬‬ ‫‪F‬‬ ‫‪F‬‬

‫ﻃﺒﻖ ﺟﺪﻭﻝﻫﺎﻱ ﻓﻮﻕ ﺍﮔﺮ ‪ p‬ﺩﺭﺳﺖ ﻭ ‪ q‬ﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﺪ‪ ،‬ﻋﺒﺎﺭﺕ ‪ p&&q‬ﻧﺎﺩﺭﺳﺖ ﻭ‬


‫ﻋﺒﺎﺭﺕ ‪ p||q‬ﺩﺭﺳﺖ ﺍﺳﺖ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪72‬‬

‫ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻫﻤﺎﻥ ﻣﺴﺄﻝۀ ﻣﺜﺎﻝ ‪ 3‐5‬ﺭﺍ ﺣﻞ ﻣﻲﻛﻨﺪ ﻭﻟﻲ ﺍﻳﻦ ﮐﺎﺭ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬
‫ﺷﺮﻁﻫﺎﻱ ﻣﺮﮐﺐ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐8‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺷﺮﻁﻫﺎﻱ ﻣﺮﻛﺐ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻣﺎﻧﻨﺪ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 3‐5‬ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﻧﺴﺨﻪ ﺑﺮﺍﻱ ﻳﺎﻓﺘﻦ ﻛﻤﻴﻦۀ ﺳﻪ ﻋﺪﺩ ﺍﺯ‬
‫ﺷﺮﻁﻫﺎﻱ ﻣﺮﻛﺐ ﺍﺳﺘﻔﺎﺩﻩ ﻛﺮﺩﻩ ﺍﺳﺖ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n1, n2, n3‬‬
‫;" ‪cout << "Enter three integers:‬‬
‫;‪cin >> n1 >> n2 >> n3‬‬
‫" ‪if (n1<=n2 && n1<=n3) cout << "Their minimum is‬‬
‫;‪<< n1 <<endl‬‬
‫" ‪if (n2<=n1 && n2<=n3) cout << "Their minimum is‬‬
‫;‪<< n2 <<endl‬‬
‫" ‪if (n3<=n1 && n3<=n2) cout << "Their minimum is‬‬
‫;‪<< n3 <<endl‬‬
‫}‬
‫‪Enter three integers: 77 33 55‬‬
‫‪Their minimum is 33‬‬

‫ﺑﺮﻧﺎﻣﻪﺍﻱ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ ﺁﻣﺪ ﻫﻴﭻ ﻣﺰﻳﺘﻲ ﺑﺮ ﻣﺜﺎﻝ ‪ 3‐5‬ﻧﺪﺍﺭﺩ ﻭ ﻓﻘﻂ ﻧﺤﻮۀ ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﺍﺯ ﺷﺮﻁﻫﺎﻱ ﻣﺮﻛﺐ ﺭﺍ ﺑﻴﺎﻥ ﻣﻲﻛﻨﺪ‪ .‬ﺩﺭ ﻣﺜﺎﻝ ﺯﻳﺮ ﻫﻢ ﺍﺯ ﺷﺮﻁ ﻣﺮﻛﺐ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐9‬ﻭﺭﻭﺩﻱ ﻛﺎﺭﺑﺮ ﭘﺴﻨﺪ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻛﺎﺭﺑﺮ ﺍﻣﮑﺎﻥ ﻣﻲﺩﻫﺪ ﻛﻪ ﺑﺮﺍﻱ ﭘﺎﺳﺦ ﻣﺜﺒﺖ "‪ "y‬ﻳﺎ "‪ "Y‬ﺭﺍ ﻭﺍﺭﺩ ﻛﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ char ans‬‬
‫;" ‪cout << "Are you enrolled (y/n):‬‬
‫;‪cin >> ans‬‬
‫;"‪if (ans= ='Y' || ans= ='y') cout << "You are enrolled.\n‬‬
‫;"‪else cout << "You are not enrolled.\n‬‬
‫}‬
‫‪Are you enrolled (y/n): N‬‬
‫‪73‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫‪You are not enrolled.‬‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺯ ﻛﺎﺭﺑﺮ ﭘﺎﺳﺨﻲ ﻣﻲﺧﻮﺍﻫﺪ ﻭ ‪ y‬ﻭ ‪ n‬ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﺟﻮﺍﺏﻫﺎﻱ ﻣﻤﮑﻦ ﭘﻴﺸﻨﻬﺎﺩ‬
‫ﻣﻲﺩﻫﺪ‪ .‬ﺍﻣﺎ ﻫﺮ ﻛﺎﺭﺍﻛﺘﺮ ﺩﻳﮕﺮﻱ ﺭﺍ ﻫﻢ ﻣﻲﭘﺬﻳﺮﺩ ﻭ ﺍﮔﺮ ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ '‪ 'y‬ﻳﺎ '‪ 'Y‬ﻧﺒﺎﺷﺪ‪،‬‬
‫ﻓﺮﺽ ﻣﻲﻛﻨﺪ ﻛﻪ ﭘﺎﺳﺦ ﻛﺎﺭﺑﺮ "‪ "no‬ﺍﺳﺖ‪.‬‬

‫‪ 3‐7‬ﺍﺭﺯﻳﺎﺑﻲ ﻣﻴﺎﻧﺒﺮﻱ‬
‫ﻋﻤﻠﮕﺮﻫﺎﻱ && ﻭ || ﺑﻪ ﺩﻭ ﻋﻤﻠﻮﻧﺪ ﻧﻴﺎﺯ ﺩﺍﺭﻧﺪ‪ .‬ﻳﻌﻨﻲ ﺑﻪ ﺩﻭ ﻣﻘﺪﺍﺭ ﻧﻴﺎﺯ ﺩﺍﺭﻧﺪ ﺗﺎ‬
‫ﻣﻘﺎﻳﺴﻪ ﺭﺍ ﺭﻭﻱ ﺁﻥ ﺩﻭ ﺍﻧﺠﺎﻡ ﺩﻫﻨﺪ‪ .‬ﺷﺮﻁﻫﺎﻱ ﻣﺮﻛﺐ ﻛﻪ ﺍﺯ && ﻭ || ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻛﻨﻨﺪ‬
‫ﻋﻤﻠﻮﻧﺪ ﺩﻭﻡ ﺭﺍ ﺑﺮﺭﺳﻲ ﻧﻤﻲﻛﻨﻨﺪ ﻣﮕﺮ ﺍﻳﻦ ﻛﻪ ﻻﺯﻡ ﺑﺎﺷﺪ‪ .‬ﺟﺪﺍﻭﻝ ﺩﺭﺳﺘﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ‬
‫‪ p&&q‬ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ ﺍﮔﺮ ‪ p‬ﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﺪ‪ .‬ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺩﻳﮕﺮ ﻧﻴﺎﺯﻱ ﻧﻴﺴﺖ ﮐﻪ ‪q‬‬
‫ﺑﺮﺭﺳﻲ ﺷﻮﺩ‪ .‬ﻫﻤﭽﻨﻴﻦ ‪ p||q‬ﺩﺭﺳﺖ ﺍﺳﺖ ﺍﮔﺮ ‪ p‬ﺩﺭﺳﺖ ﺑﺎﺷﺪ ﻭ ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﻫﻢ‬
‫ﻧﻴﺎﺯﻱ ﻧﻴﺴﺖ ﮐﻪ ‪ q‬ﺑﺮﺭﺳﻲ ﺷﻮﺩ‪ .‬ﺩﺭ ﻫﺮ ﺩﻭ ﺣﺎﻟﺖ ﮔﻔﺘﻪ ﺷﺪﻩ‪ ،‬ﺑﺎ ﺍﺭﺯﻳﺎﺑﻲ ﻋﻤﻠﻮﻧﺪ ﺍﻭﻝ ﺑﻪ‬
‫ﺳﺮﻋﺖ ﻧﺘﻴﺠﻪ ﻣﻌﻠﻮﻡ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﻛﺎﺭ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻴﺎﻧﺒﺮﻱ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐10‬ﺍﺭﺯﻳﺎﺑﻲ ﻣﻴﺎﻧﺒﺮﻱ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺑﺨﺶﭘﺬﻳﺮﻱ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺭﺍ ﺑﺮﺭﺳﻲ ﻣﻲﻛﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n, d‬‬
‫;" ‪cout << "Enter two positive integers:‬‬
‫;‪cin >> n >> d‬‬
‫‪if (d != 0 && n%d == 0) cout << d << " divides " << n‬‬
‫;‪<< endl‬‬
‫;‪else cout << d << " does not divide " << n << endl‬‬
‫}‬

‫ﺩﺭ ﺍﺟﺮﺍﻱ ﺯﻳﺮ‪ d ،‬ﻣﺜﺒﺖ ﻭ ‪ n%d‬ﺻﻔﺮ ﺍﺳﺖ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺷﺮﻁ ﻣﺮﻛﺐ ﺩﺭﺳﺖ ﺍﺳﺖ‪:‬‬
‫‪Enter two integers: 300 5‬‬
‫‪5 divides 300‬‬

‫ﺩﺭ ﺍﺟﺮﺍﻱ ﺑﻌﺪﻱ‪ d ،‬ﻣﺜﺒﺖ ﺍﺳﺖ ﺍﻣﺎ ‪ n%d‬ﺻﻔﺮ ﻧﻴﺴﺖ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺷﺮﻁ ﻣﺮﻛﺐ‬
‫ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ‪:‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪74‬‬

‫‪Enter two integers: 300 7‬‬


‫‪7 does not divide 300‬‬

‫ﺩﺭ ﺁﺧﺮﻳﻦ ﺍﺟﺮﺍ‪ 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‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫* ﻣﺜﺎﻝ ‪ 3‐11‬ﻳﻚ ﺧﻄﺎﻱ ﻣﻨﻄﻘﻲ ﺩﻳﮕﺮ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺧﻄﺎﺩﺍﺭ ﺍﺳﺖ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n1, n2, n3‬‬
‫;" ‪cout << "Enter three integers:‬‬
‫;‪cin >> n1 >> n2 >> n3‬‬
‫;‪if (n1 >= n2 >= n3) cout << "max = " << n1‬‬ ‫!‪// LOGICAL ERROR‬‬
‫}‬
‫‪Enter three integers: 0 0 1‬‬
‫‪max = 0‬‬

‫ﻣﻨﺸﺄ ﺧﻄﺎ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﻳﻦ ﺍﺻﻞ ﺍﺳﺖ ﻛﻪ ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ ﻣﻘﺪﺍﺭﻫﺎﻱ ﻋﺪﺩﻱ ﺩﺍﺭﻧﺪ‪ .‬ﭼﻮﻥ‬
‫ﻋﺒﺎﺭﺕ )‪ (n1>=n2>=n3‬ﺍﺯ ﭼﭗ ﺑﻪ ﺭﺍﺳﺖ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ‪ ،‬ﺑﻪ ﺍﺯﺍﻱ ﻭﺭﻭﺩﻱﻫﺎﻱ ﻓﻮﻕ‬
‫ﺍﻭﻟﻴﻦ ﺑﺨﺶ ﺍﺭﺯﻳﺎﺑﻲ ﻳﻌﻨﻲ ‪ n1>=n2‬ﺩﺭﺳﺖ ﺍﺳﺖ ﭼﻮﻥ ‪ 0>=0‬ﺍﻣﺎ »ﺩﺭﺳﺖ« ﺑﻪ ﺷﮑﻞ‬
‫ﻋﺪﺩ ‪ 1‬ﺩﺭ ﺣﺎﻓﻈﻪ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﺷﻮﺩ‪ .‬ﺳﭙﺲ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﺎ ﻣﻘﺪﺍﺭ ‪ n3‬ﻛﻪ ‪ 1‬ﻣﻲﺑﺎﺷﺪ ﻣﻘﺎﻳﺴﻪ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﻳﻌﻨﻲ ﻋﺒﺎﺭﺕ ‪ 1>=1‬ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻳﻦ ﻫﻢ ﺩﺭﺳﺖ ﺍﺳﺖ‪ .‬ﻧﺘﻴﺠﻪ ﺍﻳﻦ ﺍﺳﺖ‬
‫ﮐﻪ ﮐﻞ ﻋﺒﺎﺭﺕ ﺑﻪ ﻋﻨﻮﺍﻥ ﺩﺭﺳﺖ ﺗﻔﺴﻴﺮ ﻣﻲﺷﻮﺩ ﮔﺮﭼﻪ ﺩﺭ ﺣﻘﻴﻘﺖ ﺍﻳﻦ ﻃﻮﺭ ﻧﻴﺴﺖ! ) ‪0‬‬
‫ﺑﻴﺸﻴﻦۀ ‪ 0‬ﻭ ‪ 1‬ﻧﻴﺴﺖ(‬
‫ﺍﻳﺮﺍﺩ ﮐﺎﺭ ﺍﻳﻦﺟﺎﺳﺖ ﻛﻪ ﺧﻂ ﺍﺷﺘﺒﺎﻩ ﺑﻪ ﻃﻮﺭ ﻧﺤﻮﻱ ﺻﺤﻴﺢ ﺍﺳﺖ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﻧﻪ‬
‫ﻛﺎﻣﭙﺎﻳﻠﺮ ﻣﻲﺗﻮﺍﻧﺪ ﺧﻄﺎ ﺑﮕﻴﺮﺩ ﻭ ﻧﻪ ﺳﻴﺴﺘﻢﻋﺎﻣﻞ‪ .‬ﺍﻳﻦ ﻧﻮﻉ ﺩﻳﮕﺮﻱ ﺍﺯ ﺧﻄﺎﻱ ﻣﻨﻄﻘﻲ ﺍﺳﺖ‬
‫ﻛﻪ ﺑﺎ ﺁﻥﭼﻪ ﺩﺭ ﻣﺜﺎﻝ ‪ 3‐4‬ﻣﻄﺮﺡ ﺷﺪ ﻗﺎﺑﻞ ﻣﻘﺎﻳﺴﻪ ﺍﺳﺖ‪ .‬ﻧﺘﻴﺞۀ ﺍﻳﻦ ﻣﺜﺎﻝ ﺁﻥ ﺍﺳﺖ ﻛﻪ‪:‬‬
‫»ﻫﻤﻴﺸﻪ ﺑﻪ ﺧﺎﻃﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ ﻣﻘﺪﺍﺭ ﻋﺪﺩﻱ ﺩﺍﺭﻧﺪ‪ ،‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺷﺮﻁﻫﺎﻱ‬
‫ﻣﺮﻛﺐ ﻣﻲﺗﻮﺍﻧﻨﺪ ﮔﻮﻝﺯﻧﻨﺪﻩ ﺑﺎﺷﻨﺪ«‪.‬‬

‫‪ 3‐9‬ﺩﺳﺘﻮﺭﻫﺎﻱ ﺍﻧﺘﺨﺎﺏ ﺗﻮﺩﺭﺗﻮ‬


‫ﺩﺳﺘﻮﺭﻫﺎﻱ ﺍﻧﺘﺨﺎﺏ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻣﺎﻧﻨﺪ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎﻱ ﻣﺮﻛﺐ ﺑﻪ ﻛﺎﺭ ﺭﻭﻧﺪ‪ .‬ﺑﻪ ﺍﻳﻦ‬
‫ﺻﻮﺭﺕ ﮐﻪ ﻳﻚ ﺩﺳﺘﻮﺭ ﺍﻧﺘﺨﺎﺏ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺭﻭﻥ ﺩﺳﺘﻮﺭ ﺍﻧﺘﺨﺎﺏ ﺩﻳﮕﺮ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪ .‬ﺑﻪ ﺍﻳﻦ‬
‫ﺭﻭﺵ‪ ،‬ﺟﻤﻼﺕ ﺗﻮﺩﺭﺗﻮ ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪76‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐12‬ﺩﺳﺘﻮﺭﻫﺎﻱ ﺍﻧﺘﺨﺎﺏ ﺗﻮﺩﺭﺗﻮ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺍﺛﺮ ﻣﺜﺎﻝ ‪ 3‐10‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n, d‬‬
‫;" ‪cout << "Enter two positive integers:‬‬
‫;‪cin >> n >> d‬‬
‫)‪if (d != 0‬‬
‫;‪if (n%d = = 0) cout << d << " divides " << n << endl‬‬
‫;‪else cout << d << " does not divide " << n << endl‬‬
‫;‪else cout << d << " does not divide " << n << endl‬‬
‫}‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ‪ ،‬ﺩﺳﺘﻮﺭ ‪ 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;

: ‫ﻳﺎ ﺑﻪ ﺍﻳﻦ ﺷﮑﻞ‬


if (a > 0)
if (b > 0) ++a;
else if (c > 0)
if (a < 4) ++b;
else if (b < 4) ++c;
else –a;
else if (c < 4) –b;
else –c;
else a = 0;

.‫ ﺯﻳ ِﺮ ﻫﻢ ﻭ ﺩﺭ ﻳﮏ ﺭﺍﺳﺘﺎ ﻧﻮﺷﺘﻪ ﻣﻲﺷﻮﻧﺪ‬else if ‫ﺩﺭ ﺷﻴﻮۀ ﺩﻭﻡ ﻋﺒﺎﺭﺍﺕ‬

‫ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭﻫﺎﻱ ﺍﻧﺘﺨﺎﺏ ﺗﻮﺩﺭﺗﻮ‬3‐13 ‫* ﻣﺜﺎﻝ‬


‫ ﺩﺭ ﺍﻳﻦ ﻧﺴﺨﻪ ﺑﺮﺍﻱ ﻳﺎﻓﺘﻦ‬.‫ ﺭﺍ ﺩﺍﺭﺩ‬3‐8 ‫ ﻭ‬3‐5 ‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺍﺛﺮ ﻣﺜﺎﻝﻫﺎﻱ‬
:‫ ﺗﻮﺩﺭﺗﻮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ‬if..else ‫ﻛﻤﻴﻦۀ ﺳﻪ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺯ ﺩﺳﺘﻮﺭﻫﺎﻱ‬
int main()
{ int n1, n2, n3;
cout << "Enter three integers: ";
cin >> n1 >> n2 >> n3;
if (n1 < n2)
if (n1 < n3) cout << "Their minimum is " << n1 << endl;
else cout << "Their minimum is " << n3 << endl;
else // n1 >= n2
if (n2 < n3) cout << "Their minimum is " << n2 << endl;
else cout << "Their minimum is " << n3 << endl;
}
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪78‬‬

‫‪Enter two integers: 77 33 55‬‬


‫‪Their minimum is 33‬‬

‫ﺩﺭ ﺍﺟﺮﺍﻱ ﺑﺎﻻ‪ ،‬ﺍﻭﻟﻴﻦ ﺷﺮﻁ )‪ (n1<n2‬ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ ﻭ ﺳﻮﻣﻴﻦ ﺷﺮﻁ )‪ (n2<n3‬ﺩﺭﺳﺖ‬
‫ﺍﺳﺖ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﮔﺰﺍﺭﺵ ﻣﻲﺷﻮﺩ ﻛﻪ ‪ n2‬ﻛﻤﻴﻨﻪ ﺍﺳﺖ‪.‬‬
‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 3‐8‬ﻣﻮﺛﺮﺗﺮ ﺍﺳﺖ ﺯﻳﺮﺍ ﺩﺭ ﻫﺮ ﺍﺟﺮﺍﻱ ﺁﻥ ﻓﻘﻂ ﺩﻭ ﺷﺮﻁ‬
‫ﺳﺎﺩۀ ﺗﻮﺩﺭﺗﻮ ﺑﻪ ﺟﺎﻱ ﺳﻪ ﺷﺮﻁ ﻣﺮﻛﺐ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﻭﻟﻲ ﺑﻪ ﻧﻈﺮ ﻣﻲﺭﺳﺪ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‬
‫ﺍﺭﺯﺵ ﻛﻢﺗﺮﻱ ﻧﺴﺒﺖ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 3‐8‬ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺯﻳﺮﺍ ﻣﻨﻄﻖ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﭘﻴﭽﻴﺪﻩﺗﺮ‬
‫ﺍﺳﺖ‪ .‬ﺩﺭ ﻣﻘﺎﻳﺴﻪ ﺑﻴﻦ ﻛﺎﺭﺍﻳﻲ ﻭ ﺳﺎﺩﮔﻲ‪ ،‬ﻣﻌﻤﻮﻻ ﺑﻬﺘﺮ ﺍﺳﺖ ﺳﺎﺩﮔﻲ ﺍﻧﺘﺨﺎﺏ ﮔﺮﺩﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐14‬ﮐﻤﻲ ﭘﻴﭽﻴﺪﻩﺗﺮ‪ :‬ﻳﻚ ﺑﺎﺯﻱ ﺣﺪﺳﻲ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻋﺪﺩﻱ ﺭﺍ ﻛﻪ ﻛﺎﺭﺑﺮ ﺑﻴﻦ ‪ 1‬ﺗﺎ ‪ 8‬ﺩﺭ ﺫﻫﻦ ﺩﺍﺭﺩ‪ ،‬ﭘﻴﺪﺍ ﻣﻲﻛﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ cout << "Pick a number from 1 to 8." << endl‬‬
‫;‪char answer‬‬
‫;‪cout << "Is it less than 5? (y|n): "; cin >> answer‬‬
‫)'‪if (answer = = 'y‬‬ ‫‪// 1 <=n <= 4‬‬
‫;‪{ cout << "Is it less than 3? (y|n): "; cin >> answer‬‬
‫)'‪if (answer = = 'y‬‬ ‫‪// 1 <= n <= 2‬‬
‫;‪{ cout << "Is it less than 2? (y|n): "; cin >> answer‬‬
‫"‪if (answer = = 'y') cout << "Your number is 1.‬‬
‫;‪<< endl‬‬
‫;‪else cout << "Your number is 2." << endl‬‬
‫}‬
‫‪else‬‬ ‫‪// 3 <= n <= 4‬‬
‫;‪{ cout << "Is it less than 4? (y|n): "; cin >> answer‬‬
‫"‪if (answer = = 'y') cout << "Your number is 3.‬‬
‫;‪<< endl‬‬
‫;‪else cout << "Your number is 4." << endl‬‬
‫}‬
‫}‬
‫‪else‬‬ ‫‪// 5 <= n <= 8‬‬
‫;‪{ cout << "Is it less than 7? (y|n): "; cin >> answer‬‬
‫)'‪if (answer = = 'y‬‬ ‫‪// 5 <= n <= 6‬‬
‫‪79‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫{‬ ‫;‪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‬ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺍﻳﻦ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺭﻭﻱ ﻣﺠﻤﻮﻋﻪﻫﺎﻱ ﻣﺮﺗﺐ ﺑﻪ ﮐﺎﺭ‬
‫ﻣﻲﺭﻭﺩ ﻭ ﺑﻪ ﺳﺮﻋﺖ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ ﺁﻳﺎ ﻳﮏ ﺩﺍﺩۀ ﻣﻔﺮﻭﺽ ﺩﺭ ﺍﻳﻦ ﻣﺠﻤﻮﻋﻪ ﻫﺴﺖ ﻳﺎ‬
‫ﺧﻴﺮ‪ .‬ﺩﺭ ﻓﺼﻞﻫﺎﻱ ﺑﻌﺪﻱ ﺭﻭﺵﻫﺎﻱ ﺩﻳﮕﺮﻱ ﺍﺯ ﺟﺴﺘﺠﻮ ﺭﺍ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ‪.‬‬

‫‪ 3‐10‬ﺳﺎﺧﺘﺎﺭ ‪else if‬‬

‫ﺩﺳﺘﻮﺭ ‪ if..else‬ﺗﻮﺩﺭﺗﻮ‪ ،‬ﺍﻏﻠﺐ ﺑﺮﺍﻱ ﺑﺮﺭﺳﻲ ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﺣﺎﻟﺖﻫﺎﻱ‬


‫ﻣﺘﻨﺎﻭﺏ ﻳﺎ ﻣﻮﺍﺯﻱ ﺑﻪ ﻛﺎﺭ ﻣﻲﺭﻭﺩ‪ .‬ﺩﺭ ﺍﻳﻦ ﺣﺎﻻﺕ ﻓﻘﻂ ﻋﺒﺎﺭﺕ ‪ else‬ﺷﺎﻣﻞ ﺩﺳﺘﻮﺭ ‪if‬‬
‫ﺑﻌﺪﻱ ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪ .‬ﺍﻳﻦ ﻗﺒﻴﻞ ﮐﺪﻫﺎ ﺭﺍ ﻣﻌﻤﻮﻻ ﺑﺎ ﺳﺎﺧﺘﺎﺭ ‪ else if‬ﻣﻲﺳﺎﺯﻧﺪ‪.‬‬

‫‪1 – Binary search‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 80

‫ ﺑﺮﺍﻱ ﺑﺮﺭﺳﻲ ﺣﺎﻟﺖﻫﺎﻱ ﻣﻮﺍﺯﻱ‬else if ‫ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺳﺎﺧﺘﺎﺭ‬3‐15 ‫* ﻣﺜﺎﻝ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺯﺑﺎﻥ ﻛﺎﺭﺑﺮ ﺭﺍ ﺳﻮﺍﻝ ﻣﻲﻛﻨﺪ ﻭ ﺳﭙﺲ ﻳﻚ ﭘﻴﻐﺎﻡ ﺑﻪ ﻫﻤﺎﻥ ﺯﺑﺎﻥ ﺩﺭ‬
:‫ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﻧﻤﺎﻳﺪ‬
int main()
{ char language;
cout << "Engl., Fren., Ger., Ital., or Rus.? (e|f|g|i|r): ";
cin >> language;
if (language = = 'e') cout << "Welcome to ProjectC++.";
else if (language = = 'f') cout << "Bon jour, ProjectC++.";
else if (language = = 'g') cout << "Guten tag, ProjectC++.";
else if (language = = 'i') cout << "Bon giorno, ProjectC++.";
else if (language = = 'r') cout << "Dobre utre, ProjectC++.";
else cout << "Sorry; we don't speak your language.";
}
Engl., Fren., Ger., Ital., or Rus.? (e|f|g|i|r): i
Bon giorno, ProjectC++.

‫ ﻛﺪ ﺑﺎﻻ ﺭﺍ‬.‫ ﺗﻮﺩﺭﺗﻮ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩ‬if..else ‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺩﺭ ﺣﻘﻴﻘﺖ ﺍﺯ ﺩﺳﺘﻮﺭ‬


:‫ﻣﻲﺗﻮﺍﻧﺴﺘﻴﻢ ﺑﻪ ﺗﺮﺗﻴﺐ ﺯﻳﺮ ﺑﻨﻮﻳﺴﻴﻢ‬
if (language = = 'e') cout << "Welcome to ProjectC++.";
else
if (language = = 'f') cout << "Bon jour, ProjectC++.";
else
if (language = = 'g') cout << "Guten tag, ProjectC++.";
else
if (language = = 'i') cout << "Bon giorno, ProjectC++.";
else
if (language = = 'r') cout << "Dobre utre, ProjectC++.";
else cout << "Sorry; we don't speak your language.";

‫ ﺑﻴﺸﺘﺮ ﺍﺳﺘﻔﺎﺩﻩ‬،‫ﺍﻣﺎ ﻗﺎﻟﺐ ﻗﺒﻠﻲ ﺑﻪ ﻋﻠﺖ ﺍﻳﻦ ﻛﻪ ﺩﺭﮎ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺁﺳﺎﻥﺗﺮ ﻣﻲﮐﻨﺪ‬
.‫ ﻫﻤﭽﻨﻴﻦ ﺑﻪ ﺗﻮﺭﻓﺘﮕﻲ ﻛﻤﺘﺮﻱ ﺍﺣﺘﻴﺎﺝ ﺩﺍﺭﺩ‬.‫ﻣﻲﺷﻮﺩ‬
81 ‫ اﻧﺘﺨﺎب‬/ ‫ﻓﺼﻞ ﺳﻮم‬

‫ ﺑﺮﺍﻱ ﻣﺸﺨﺺ ﮐﺮﺩﻥ ﻣﺤﺪﻭﺩۀ ﻧﻤﺮﻩ‬else if ‫ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺳﺎﺧﺘﺎﺭ‬3‐16 ‫* ﻣﺜﺎﻝ‬


:‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﻚ ﻧﻤﺮۀ ﺍﻣﺘﺤﺎﻥ ﺭﺍ ﺑﻪ ﺩﺭﺝۀ ﺣﺮﻓﻲ ﻣﻌﺎﺩﻝ ﺗﺒﺪﻳﻞ ﻣﻲﻛﻨﺪ‬
int main()
{ int score;
cout << "Enter your test score: "; cin >> score;
if (score > 100) cout << "Error: that score is out of range.";
else if (score >= 90) cout << "Your grade is an A." << endl;
else if (score >= 80) cout << "Your grade is a B." << endl;
else if (score >= 70) cout << "Your grade is a C." << endl;
else if (score >= 60) cout << "Your grade is a D." << endl;
else if (score >= 0) cout << "Your grade is an F." << endl;
else cout << "Error: that score is out of range.";
}
Enter your test score: 83
Your grade is a B.

‫ ﺑﻪ ﺷﮑﻞ ﺁﺑﺸﺎﺭﻱ ﺑﺎ ﺩﺳﺘﻮﺭﻫﺎﻱ ﺍﻧﺘﺨﺎﺏ ﺑﻪ ﻃﻮﺭ ﻣﺘﻮﺍﻟﻲ ﺑﺮﺭﺳﻲ‬score ‫ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ‬


.‫ ﺑﺮﺳﻴﻢ‬else ‫ﻣﻲﺷﻮﺩ ﺗﺎ ﺍﻳﻦ ﻛﻪ ﻳﻜﻲ ﺍﺯ ﺷﺮﻁﻫﺎ ﺩﺭﺳﺖ ﺷﻮﺩ ﻭ ﻳﺎ ﺑﻪ ﺁﺧﺮﻳﻦ‬

switch ‫ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ‬3‐11

‫ ﺑﺮﺍﻱ ﺑﺮﺭﺳﻲ ﻣﺠﻤﻮﻋﻪﺍﻱ‬else if ‫ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺟﺎﻱ ﺳﺎﺧﺘﺎﺭ‬switch ‫ﺩﺳﺘﻮﺭ‬


:‫ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‬switch ‫ ﻧﺤﻮ ﺩﺳﺘﻮﺭ‬.‫ﺍﺯ ﺣﺎﻟﺖﻫﺎﻱ ﻣﺘﻨﺎﻭﺏ ﻭ ﻣﻮﺍﺯﻱ ﺑﻪ ﻛﺎﺭ ﺭﻭﺩ‬
switch (expression)
{ case constant1: statementlist1;
case constant2: statementlist2;
case constant3: statementlist3;
:
:
case constantN: statementlistN;
default: statementlist0;
}
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 82

‫ ﺑﻪ‬case ‫ ﺭﺍ ﺑﺮﺁﻭﺭﺩ ﻣﻲﻛﻨﺪ ﻭ ﺳﭙﺲ ﻣﻴﺎﻥ ﺛﺎﺑﺖﻫﺎﻱ‬expression ‫ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺍﺑﺘﺪﺍ‬


،‫ ﺍﮔﺮ ﻣﻘﺪﺍﺭ ﻣﺮﺑﻮﻃﻪ ﺍﺯ ﻣﻴﺎﻥ ﺛﺎﺑﺖﻫﺎﻱ ﻓﻬﺮﺳﺖﺷﺪﻩ ﻳﺎﻓﺖ ﺷﺪ‬.‫ﺩﻧﺒﺎﻝ ﻣﻘﺪﺍﺭ ﺁﻥ ﻣﻲﮔﺮﺩﺩ‬
‫ ﺍﮔﺮ ﻣﻘﺪﺍﺭ ﻣﻮﺭﺩ ﻧﻈﺮ ﻣﻴﺎﻥ‬.‫ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‬case ‫ ﻣﻘﺎﺑﻞ ﺁﻥ‬statementlist ‫ﺩﺳﺘﻮﺭ‬
statementlist ‫ ﺩﺳﺘﻮﺭ‬،‫ ﻭﺟﻮﺩ ﺩﺍﺷﺖ‬default ‫ﻫﺎ ﻳﺎﻓﺖ ﻧﺸﺪ ﻭ ﻋﺒﺎﺭﺕ‬case
‫ ﻳﻌﻨﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ‬.‫ ﻳﮏ ﻋﺒﺎﺭﺕ ﺍﺧﺘﻴﺎﺭﻱ ﺍﺳﺖ‬default ‫ ﻋﺒﺎﺭﺕ‬.‫ﻣﻘﺎﺑﻞ ﺁﻥ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‬
‫ ﺑﺎﻳﺪ ﺑﻪ ﺷﮑﻞ ﻳﻚ ﻧﻮﻉ ﺻﺤﻴﺢ‬expression .‫ ﺁﻥ ﺭﺍ ﻗﻴﺪ ﻧﮑﻨﻴﻢ‬switch ‫ﺩﺭ ﺩﺳﺘﻮﺭ‬
.‫ﻫﺎ ﺑﺎﻳﺪ ﺛﺎﺑﺖﻫﺎﻱ ﺻﺤﻴﺢ ﺑﺎﺷﻨﺪ‬constant ‫ﺍﺭﺯﻳﺎﺑﻲ ﺷﻮﺩ ﻭ‬

3‐16 ‫ ﻧﺴﺦۀ ﺗﻐﻴﻴﺮﻳﺎﻓﺘﻪﺍﻱ ﺍﺯ ﻣﺜﺎﻝ‬3‐17 ‫* ﻣﺜﺎﻝ‬


‫ ﺩﺭ ﺍﻳﻦ ﻧﺴﺨﻪ ﺍﺯ ﺩﺳﺘﻮﺭ‬.‫ ﺭﺍ ﺩﺍﺭﺩ‬3‐16 ‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺍﺛﺮ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ‬
:‫ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‬switch
int main()
{ int score;
cout << "Enter your test score: "; cin >> score;
switch (score/10)
{ case 10:
case 9: cout << "Your grade is an A." << endl; break;
case 8: cout << "Your grade is a B." << endl; break;
case 7: cout << "Your grade is a C." << endl; break;
case 6: cout << "Your grade is a D." << endl; break;
case 5:
case 4:
case 3:
case 2:
case 1:
case 0: cout << "Your grade is an F." << endl; break;
default: cout << "Error: score is out of range.\n";
}
cout << "Goodbye." << endl;
}
Enter your test score: 83
Your grade is a B.
‫‪83‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫‪Goodbye.‬‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺑﺘﺪﺍ ‪ score‬ﺑﺮ ‪ 10‬ﺗﻘﺴﻴﻢ ﻣﻲﺷﻮﺩ ﺗﺎ ﻣﺤﺪﻭﺩۀ ﺍﻋﺪﺍﺩ ﺑﻴﻦ ﺻﻔﺮ ﺗﺎ ‪10‬‬
‫ﻣﺤﺪﻭﺩ ﺷﻮﺩ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﺭ ﺍﺟﺮﺍﻱ ﺁﺯﻣﺎﻳﺸﻲ‪ ،‬ﻧﻤﺮۀ ‪ 83‬ﺑﻪ ‪ 8‬ﺗﺒﺪﻳﻞ ﻣﻲﺷﻮﺩ‪ ،‬ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ‬
‫ﺑﻪ ‪ case 8‬ﺍﻧﺸﻌﺎﺏ ﻣﻲﮐﻨﺪ ﻭ ﺧﺮﻭﺟﻲ ﻣﺮﺑﻮﻃﻪ ﭼﺎﭖ ﻣﻲﮔﺮﺩﺩ‪ .‬ﺳﭙﺲ ﺩﺳﺘﻮﺭ ‪break‬‬
‫ﻣﻮﺟﺐ ﻣﻲﺷﻮﺩ ﻛﻪ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺩﺳﺘﻮﺭ ‪ switch‬ﺧﺎﺭﺝ ﺷﺪﻩ ﻭ ﺑﻪ ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ﺑﻌﺪ‬
‫ﺍﺯ ﺑﻠﻮﻙ ‪ switch‬ﺍﻧﺸﻌﺎﺏ ﻛﻨﺪ‪ .‬ﺩﺭ ﺁﻥﺟﺎ ﻋﺒﺎﺭﺕ "‪ "Goodbye.‬ﭼﺎﭖ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﻻﺯﻡ ﺍﺳﺖ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﻫﺮ ‪ case‬ﺩﺳﺘﻮﺭ ‪ break‬ﻗﺮﺍﺭ ﺑﮕﻴﺮﺩ‪ .‬ﺑﺪﻭﻥ ﺍﻳﻦ ﺩﺳﺘﻮﺭ‪،‬‬
‫ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﭘﺲ ﺍﺯ ﺍﻳﻦ ﻛﻪ ‪ case‬ﻣﺮﺑﻮﻃﻪ ﺭﺍ ﺍﺟﺮﺍ ﮐﺮﺩ ﺍﺯ ﺩﺳﺘﻮﺭ ‪ switch‬ﺧﺎﺭﺝ‬
‫ﻧﻤﻲﺷﻮﺩ‪ ،‬ﺑﻠﮑﻪ ﻫﻢۀ ‪case‬ﻫﺎﻱ ﺯﻳﺮﻳﻦ ﺭﺍ ﻫﻢ ﺧﻂ ﺑﻪ ﺧﻂ ﻣﻲﭘﻴﻤﺎﻳﺪ ﻭ ﺩﺳﺘﻮﺭﺍﺕ ﻣﻘﺎﺑﻞ‬
‫ﺁﻥﻫﺎ ﺭﺍ ﺍﺟﺮﺍ ﻣﻲﮐﻨﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﺍﺗﻔﺎﻕ‪ ،‬ﺗﻞۀ ﺳﻘﻮﻁ‪ 1‬ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐18‬ﺗﻞۀ ﺳﻘﻮﻁ ﺩﺭ ﺩﺳﺘﻮﺭ ‪switch‬‬


‫ﻗﺼﺪ ﺑﺮ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺜﻞ ﺑﺮﻧﺎﻡۀ ‪ 3‐17‬ﺭﻓﺘﺎﺭ ﮐﻨﺪ ﻭﻟﻲ ﺑﺪﻭﻥ‬
‫ﺩﺳﺘﻮﺭﻫﺎﻱ ‪ break‬ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺩﭼﺎﺭ ﺗﻞۀ ﺳﻘﻮﻁ ﻣﻲﺷﻮﺩ‪:‬‬
‫)(‪int main‬‬
‫{‬ ‫;‪int score‬‬
‫;" ‪cout << "Enter your test score:‬‬ ‫;‪cin >> score‬‬
‫)‪switch (score/10‬‬
‫{‬ ‫‪case 10:‬‬
‫‪case‬‬ ‫‪9: cout << "Your grade is an A." << endl; // LOGICAL ERROR‬‬
‫‪case‬‬ ‫;‪8: cout << "Your grade is a B." << endl‬‬ ‫‪// LOGICAL ERROR‬‬
‫‪case‬‬ ‫;‪7: cout << "Your grade is a C." << endl‬‬ ‫‪// LOGICAL ERROR‬‬
‫‪case‬‬ ‫;‪6: cout << "Your grade is a D." << endl‬‬ ‫‪// LOGICAL ERROR‬‬
‫‪case‬‬ ‫‪5:‬‬
‫‪case‬‬ ‫‪4:‬‬
‫‪case‬‬ ‫‪3:‬‬
‫‪case‬‬ ‫‪2:‬‬
‫‪case‬‬ ‫‪1:‬‬
‫‪case‬‬ ‫;‪0: cout << "Your grade is an F." << endl‬‬ ‫‪// LOGICAL ERROR‬‬
‫;"‪default: cout << "Error: score is out of range.\n‬‬
‫}‬

‫‪1 – Fall-throw error‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪84‬‬

‫;‪cout << "Goodbye." << endl‬‬


‫}‬
‫‪Enter your test score: 83‬‬
‫‪Your grade is a B.‬‬
‫‪Your grade is a C.‬‬
‫‪Your grade is a D.‬‬
‫‪Your grade is an F.‬‬
‫‪Error: score is out of range.‬‬
‫‪Goodbye.‬‬

‫ﺩﺭ ﺍﺟﺮﺍﻱ ﻓﻮﻕ ﭘﺲ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺑﻪ ‪ case 8‬ﺍﻧﺸﻌﺎﺏ ﺷﺪ ﻭ ﻋﺒﺎﺭﺕ ﻣﻘﺎﺑﻞ ﺁﻥ ﭼﺎﭖ ﺷﺪ‪،‬‬
‫ﭼﻮﻥ ﺩﺳﺘﻮﺭ ‪ break‬ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ‪ ،‬ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺧﻂ ﺑﻌﺪﻱ ﻳﻌﻨﻲ ‪ case 7‬ﻣﻲﺭﻭﺩ‬
‫ﺭﺍ ﻧﻴﺰ ﭼﺎﭖ ﻣﻲﮐﻨﺪ ﻭ ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﻳﮑﻲ ﻳﮑﻲ‬ ‫"‪"Your grade is a C.‬‬ ‫ﻭ ﻋﺒﺎﺭﺕ‬
‫ﻫﻢۀ ﻋﺒﺎﺭﺕﻫﺎﻱ ‪ case‬ﺭﺍ ﺍﺟﺮﺍ ﻣﻲﻧﻤﺎﻳﺪ ﻭ ﺳﺮﺍﻧﺠﺎﻡ ﻋﺒﺎﺭﺕ ‪ default‬ﺭﺍ ﻫﻢ ﺍﺟﺮﺍ‬
‫ﻧﻤﻮﺩﻩ ﻭ ﺁﻧﮕﺎﻩ ﺍﺯ ﺩﺳﺘﻮﺭ ‪ switch‬ﺧﺎﺭﺝ ﻣﻲﺷﻮﺩ‪.‬‬

‫‪ 3‐12‬ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ‬


‫ﻳﮑﻲ ﺍﺯ ﻣﺰﻳﺖﻫﺎﻱ ‪ C++‬ﺍﺧﺘﺼﺎﺭ ﺩﺭ ﮐﺪﻧﻮﻳﺴﻲ ﺍﺳﺖ‪ .‬ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﻳﮑﻲ‬
‫ﺍﺯ ﺍﻣﮑﺎﻧﺎﺗﻲ ﺍﺳﺖ ﮐﻪ ﺟﻬﺖ ﺍﺧﺘﺼﺎﺭ ﺩﺭ ﮐﺪﻧﻮﻳﺴﻲ ﺗﺪﺍﺭﮎ ﺩﻳﺪﻩ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺭﺍ‬
‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺟﺎﻱ ﺩﺳﺘﻮﺭ ‪ if..else‬ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ‪ .‬ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺍﺯ ﻧﺸﺎﻧﻪﻫﺎﻱ ? ﻭ ‪ :‬ﺑﻪ‬
‫ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻛﻨﺪ‪:‬‬
‫;‪condition ? expression1 : expression2‬‬

‫ﺩﺭ ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺍﺑﺘﺪﺍ ﺷﺮﻁ ‪ condition‬ﺑﺮﺭﺳﻲ ﻣﻲﺷﻮﺩ‪ .‬ﺍﮔﺮ ﺍﻳﻦ ﺷﺮﻁ ﺩﺭﺳﺖ ﺑﻮﺩ‪،‬‬
‫ﺣﺎﺻﻞ ﮐﻞ ﻋﺒﺎﺭﺕ ﺑﺮﺍﺑﺮ ﺑﺎ ‪ expression1‬ﻣﻲﺷﻮﺩ ﻭ ﺍﮔﺮ ﺷﺮﻁ ﻧﺎﺩﺭﺳﺖ ﺑﻮﺩ‪ ،‬ﺣﺎﺻﻞ‬
‫ﮐﻞ ﻋﺒﺎﺭﺕ ﺑﺮﺍﺑﺮ ﺑﺎ ‪ expression2‬ﻣﻲﺷﻮﺩ‪ .‬ﻣﺜﻼ ﺩﺭ ﺩﺳﺘﻮﺭ ﺍﻧﺘﺴﺎﺏ ﺯﻳﺮ‪:‬‬
‫;) ‪min = ( x<y ? x : y‬‬

‫ﺍﮔﺮ ‪ x<y‬ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ ‪ x‬ﺭﺍ ﺩﺭﻭﻥ ‪ min‬ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﻭ ﺍﮔﺮ ‪ x<y‬ﻧﺒﺎﺷﺪ ﻣﻘﺪﺍﺭ ‪ y‬ﺭﺍ ﺩﺭﻭﻥ‬
‫‪ min‬ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ‪ .‬ﻳﻌﻨﻲ ﺑﻪ ﻫﻤﻴﻦ ﺳﺎﺩﮔﻲ ﻭ ﺍﺧﺘﺼﺎﺭ‪ ،‬ﻣﻘﺪﺍﺭ ﮐﻤﻴﻦۀ ‪ x‬ﻭ ‪ y‬ﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ‬
‫‪ min‬ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﻳﮏ ﻋﻤﻠﮕﺮ ﺳﻪﮔﺎﻧﻪ ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﺳﻪ ﻋﻤﻠﻮﻧﺪ ﺭﺍ‬
‫‪85‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫ﺑﺮﺍﻱ ﺗﻬﻲۀ ﻳﮏ ﻣﻘﺪﺍﺭ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺑﻬﺘﺮ ﺍﺳﺖ ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﻓﻘﻂ ﺩﺭ ﻣﻮﺍﻗﻊ‬
‫ﺿﺮﻭﺭﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ؛ ﻭﻗﺘﻲ ﮐﻪ ﺷﺮﻁ ﻭ ﻫﺮ ﺩﻭ ﺩﺳﺘﻮﺭ ﺧﻴﻠﻲ ﺳﺎﺩﻩ ﻫﺴﺘﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 3‐19‬ﻧﺴﺦۀ ﺟﺪﻳﺪﻱ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﻳﺎﻓﺘﻦ ﻣﻘﺪﺍﺭ ﻛﻤﻴﻨﻪ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺛﺮﻱ ﺷﺒﻴﻪ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 3‐3‬ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int m, n‬‬
‫;" ‪cout << "Enter two integers:‬‬
‫;‪cin >> m >> n‬‬
‫;‪cout << ( m<n ? m : n ) << " is the minimum." << endl‬‬
‫}‬

‫ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ) ‪ ( m<n ? m : n‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ m‬ﻣﻲﺷﻮﺩ ﺍﮔﺮ ‪ m<n‬ﺑﺎﺷﺪ ﻭ ﺩﺭ ﻏﻴﺮ ﺍﻳﻦ‬


‫ﺻﻮﺭﺕ ﺑﺮﺍﺑﺮ ﺑﺎ ‪ n‬ﻣﻲﺷﻮﺩ‪.‬‬

‫‪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‬‬

‫‪if‬‬ ‫‪inline‬‬ ‫‪int‬‬


‫‪long‬‬ ‫‪mutable‬‬ ‫‪namespace‬‬
‫‪new‬‬ ‫‪not‬‬ ‫‪not_eq‬‬
‫‪operator‬‬ ‫‪or‬‬ ‫‪or_eq‬‬
‫‪privat‬‬ ‫‪eprotected‬‬ ‫‪public‬‬
‫‪register‬‬ ‫‪reinterpret_cast‬‬ ‫‪return‬‬
‫‪short‬‬ ‫‪signed‬‬ ‫‪sizeof‬‬
‫‪static‬‬ ‫‪static_cast‬‬ ‫‪struct‬‬
‫‪swich‬‬ ‫‪template‬‬ ‫‪this‬‬
‫‪throw‬‬ ‫‪true‬‬ ‫‪try‬‬
‫‪typedef‬‬ ‫‪typoid‬‬ ‫‪typename‬‬
‫‪using‬‬ ‫‪union‬‬ ‫‪unsigned‬‬
‫‪virtual‬‬ ‫‪void‬‬ ‫‪volatile‬‬
‫‪wchar_t‬‬ ‫‪while‬‬ ‫‪xor‬‬
‫‪xor_eq‬‬

‫ﻛﻠﻤﺎﺕ ﻛﻠﻴﺪﻱ ﻣﺎﻧﻨﺪ ‪ if‬ﻭ ‪ else‬ﺗﻘﺮﻳﺒﺎ ﺩﺭ ﻫﺮ ﺯﺑﺎﻥ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﭘﻴﺪﺍ ﻣﻲﺷﻮﻧﺪ‪.‬‬


‫ﺩﻳﮕﺮ ﻛﻠﻤﺎﺕ ﻛﻠﻴﺪﻱ ﻫﻤﭽﻮﻥ ‪ dynamic_cast‬ﻣﻨﺤﺼﺮ ﺑﻪ ‪ C++‬ﻫﺴﺘﻨﺪ‪ 74 .‬ﻛﻠﻢۀ‬
‫ﻛﻠﻴﺪﻱ ﺩﺭ ‪ C++‬ﻫﺴﺖ ﻛﻪ ﻫﻢۀ ‪ 32‬ﻛﻠﻢۀ ﻛﻠﻴﺪﻱ ﺯﺑﺎﻥ ‪ C‬ﺭﺍ ﻧﻴﺰ ﺷﺎﻣﻞ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺩﻭ ﻧﻮﻉ ﻛﻠﻢۀ ﻛﻠﻴﺪﻱ ﻭﺟﻮﺩ ﺩﺍﺭﺩ‪ :‬ﻛﻠﻤﻪﻫﺎﻱ ﺭﺯﺭﻭ ﺷﺪﻩ ﻭ ﺷﻨﺎﺳﻪﻫﺎﻱ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‪.‬‬
‫ﻳﻚ ﻛﻠﻢۀ ﺭﺯﺭﻭ ﺷﺪﻩ ﻛﻠﻤﻪﺍﻱ ﺍﺳﺖ ﮐﻪ ﻳﮏ ﺩﺳﺘﻮﺭ ﺧﺎﺹ ﺍﺯ ﺁﻥ ﺯﺑﺎﻥ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬
‫ﻛﻠﻢۀ ﻛﻠﻴﺪﻱ ‪ if‬ﻭ ‪ else‬ﻛﻠﻤﺎﺕ ﺭﺯﺭﻭ ﺷﺪﻩ ﻫﺴﺘﻨﺪ‪ .‬ﻳﻚ ﺷﻨﺎﺱۀ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻛﻠﻤﻪﺍﻱ‬
‫ﺍﺳﺖ ﻛﻪ ﻳﻚ ﻧﻮﻉ ﺩﺍﺩۀ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺍﺯ ﺯﺑﺎﻥ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲﻛﻨﺪ‪ .‬ﻛﻠﻤﺎﺕ ﻛﻠﻴﺪﻱ ‪ bool‬ﻭ‬
‫‪ int‬ﺷﻨﺎﺳﻪﻫﺎﻱ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻫﺴﺘﻨﺪ ﺯﻳﺮﺍ ﻫﺮ ﻳﮏ ﺍﺯ ﺁﻥﻫﺎ ﻳﮏ ﻧﻮﻉ ﺩﺍﺩۀ ﺧﺎﺹ ﺭﺍ ﺩﺭ ﺯﺑﺎﻥ‬
‫‪ C++‬ﻣﺸﺨﺺ ﻣﻲﻛﻨﻨﺪ‪ .‬ﺑﺮﺍﻱ ﺍﻃﻼﻋﺎﺕ ﺑﻴﺸﺘﺮ ﺩﺭ ﻣﻮﺭﺩ ﻛﻠﻤﺎﺕ ﻛﻠﻴﺪﻱ ‪ C++‬ﺑﻪ ﻣﺮﺍﺟﻊ‬
‫ﺍﻳﻦ ﺯﺑﺎﻥ ﻳﺎ ﺭﺍﻫﻨﻤﺎﻱ ﮐﺎﻣﭙﺎﻳﻠﺮﺗﺎﻥ ﻣﺮﺍﺟﻌﻪ ﻛﻨﻴﺪ‪.‬‬
‫‪87‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬
‫‪ – 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‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫‪ – 10‬ﺍﮔﺮ ‪ a=0‬ﻭ ‪ b=1‬ﻭ ‪ c=2‬ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ ‪ c‬ﭘﺲ ﺍﺯ ﺍﺟﺮﺍﻱ ﮐﺪ ﺯﻳﺮ‪ ،‬ﭼﻴﺴﺖ؟‬


‫)‪if (a==1‬‬
‫;‪if (b==1) c++‬‬
‫;‪else c--‬‬
‫ﺩ( ‪c = 4‬‬ ‫ﺝ( ‪c = 2‬‬ ‫ﺏ( ‪c = 1‬‬ ‫ﺍﻟﻒ( ‪c = 3‬‬
‫‪ – 11‬ﺍﮔﺮ ‪ i = 5‬ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ ‪ i‬ﭘﺲ ﺍﺯ ﺍﺟﺮﺍﻱ ﮐﺪ ﺯﻳﺮ‪ ،‬ﭼﻴﺴﺖ؟‬
‫)‪switch (i‬‬
‫;‪{ case 5: i++‬‬
‫;‪case 0: i--‬‬
‫;‪default: i--‬‬
‫}‬
‫ﺩ( ‪i = 3‬‬ ‫ﺝ( ‪i = 4‬‬ ‫ﺏ( ‪i = 5‬‬ ‫ﺍﻟﻒ( ‪i = 6‬‬
‫‪ – 12‬ﺗﻠﻪ ﺳﻘﻮﻁ ﻭﻗﺘﻲ ﺭﺥ ﻣﻲﺩﻫﺪ ﮐﻪ ‪:‬‬
‫ﺍﻟﻒ( ﺑﻪ ﺟﺎﻱ ﻋﻤﻠﮕﺮ ﺑﺮﺍﺑﺮﻱ )==( ﺍﺯ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ )=( ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‬
‫ﺏ( ﺩﺭ ﺩﺳﺘﻮﺭ ‪ if‬ﭘﺮﺍﻧﺘﺰﻫﺎﻱ ﺷﺮﻁ ﺭﺍ ﻓﺮﺍﻣﻮﺵ ﮐﻨﻴﻢ‬
‫ﺝ( ﺗﻼﺵ ﮐﻨﻴﻢ ﻋﺪﺩﻱ ﺭﺍ ﺑﺮ ﺻﻔﺮ ﺗﻘﺴﻴﻢ ﮐﻨﻴﻢ‬
‫ﺩ( ﺩﺭ ﺩﺳﺘﻮﺭ ‪ switch‬ﺩﺳﺘﻮﺭﻫﺎﻱ ‪ break‬ﺭﺍ ﻓﺮﺍﻣﻮﺵ ﮐﻨﻴﻢ‬
‫‪ – 13‬ﮐﺪ ;‪ if (x>y) p=x; else p=y‬ﻣﻌﺎﺩﻝ ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﮐﺪﻫﺎﻱ ﺯﻳﺮ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ( ;)‪ p=( x>y ? x : y‬ﺏ( ;)‪p=( x>y ? y : x‬‬
‫ﺝ( ;)‪ (x>y ? p=x : p=y‬ﺩ( ;)‪(x>y ? p=y : p=x‬‬
‫‪ – 14‬ﻣﻌﻨﻲ ﺟﻤﻞۀ ﻣﻘﺎﺑﻞ ﭼﻴﺴﺖ؟ »ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﻳﮏ ﻋﻤﻠﮕﺮ ﺳﻪ ﮔﺎﻧﻪ ﺍﺳﺖ«‬
‫ﺍﻟﻒ( ﻳﻌﻨﻲ ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﺳﻪ ﺷﮑﻞ ﻣﺘﻔﺎﻭﺕ ﺩﺍﺭﺩ‬
‫ﺏ( ﻳﻌﻨﻲ ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﺳﻪ ﮐﺎﺭﺑﺮﺩ ﻣﺘﻔﺎﻭﺕ ﺩﺍﺭﺩ‬
‫ﺝ( ﻳﻌﻨﻲ ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﺳﻪ ﺷﺮﻁ ﺍﺳﺖ‬
‫ﺩ( ﻳﻌﻨﻲ ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ﺳﻪ ﻋﻤﻠﻮﻧﺪ ﺭﺍ ﺑﺮﺍﻱ ﺗﻬﻲۀ ﻳﮏ ﻣﻘﺪﺍﺭ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﺩ‬
‫‪ – 15‬ﮐﺪﺍﻡ ﺩﺳﺘﻮﺭ ﺯﻳﺮ‪ ،‬ﻳﮏ ﺩﺳﺘﻮﺭ ﺍﻧﺘﺨﺎﺏ ﻧﻴﺴﺖ؟‬
‫ﺏ( ﺩﺳﺘﻮﺭ ‪if‬‬ ‫ﺍﻟﻒ( ﺩﺳﺘﻮﺭ ‪break‬‬
‫ﺩ( ﺩﺳﺘﻮﺭ ‪switch‬‬ ‫ﺝ( ﺩﺳﺘﻮﺭ ‪if..else‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪90‬‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪ ‐1‬ﻳﻚ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻣﻨﻔﺮﺩ ﺩﺭ‪ C++‬ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺍﮔﺮ ﻣﺘﻐﻴﺮ ‪ cout‬ﺍﺯ ‪ 100‬ﺗﺠﺎﻭﺯ ﻛﺮﺩ‬
‫ﻋﺒﺎﺭﺕ "‪ "Too many‬ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ‪.‬‬
‫‪ ‐2‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﻛﺪﻫﺎﻱ ﺯﻳﺮ ﺍﺳﺖ؟‬
‫;‪a. cin << count‬‬
‫‪b. if x < y min = x‬‬
‫;‪else min = y‬‬

‫‪ ‐3‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﺍﻳﻦ ﻛﺪ ﺑﺮﻧﺎﻣﻪ ﻭﺟﻮﺩ ﺩﺍﺭﺩ؟‬


‫;" ‪cout << "Enter n:‬‬
‫;‪cin >> n‬‬
‫)‪if (n < 0‬‬
‫;‪cout << "That is negative. Try again." << endl‬‬
‫;‪cin >> n‬‬
‫‪else‬‬
‫;‪cout << "o.k. n = " << n << endl‬‬

‫‪ ‐4‬ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﻴﻦ ﻛﻠﻢۀ ﺭﺯﺭﻭ ﺷﺪﻩ ﻭ ﺷﻨﺎﺱۀ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺍﺳﺖ؟‬


‫‪ ‐5‬ﻣﺸﺨﺺ ﻛﻨﻴﺪ ﻫﺮ ﻳﻚ ﺍﺯ ﻋﺒﺎﺭﺍﺕ ﺯﻳﺮ ﺩﺭﺳﺖ ﺍﺳﺖ ﻳﺎ ﻧﺎﺩﺭﺳﺖ‪ .‬ﺍﮔﺮ ﻧﺎﺩﺭﺳﺖ ﺍﺳﺖ‬
‫ﺑﮕﻮﻳﻴﺪ ﭼﺮﺍ؟‬
‫ﺍﻟﻒ ‐ ﻋﺒﺎﺭﺕ)‪ !(p||q‬ﺑﺎ ﻋﺒﺎﺭﺕ ‪ !p || !q‬ﺑﺮﺍﺑﺮ ﺍﺳﺖ‪.‬‬
‫ﺏ ‐ ﻋﺒﺎﺭﺕ ‪ !!!p‬ﺑﺎ ﻋﺒﺎﺭﺕ ‪ !p‬ﺑﺮﺍﺑﺮ ﺍﺳﺖ‪.‬‬
‫ﺝ ‐ ﻋﺒﺎﺭﺕ ‪ p && q || r‬ﺑﺎ ﻋﺒﺎﺭﺕ )‪ p && (q || r‬ﺑﺮﺍﺑﺮ ﺍﺳﺖ‪.‬‬
‫‪ ‐6‬ﺑﺮﺍﻱ ﻫﺮ ﻳﻚ ﺍﺯ ﻋﺒﺎﺭﺕﻫﺎﻱ ﺑﻮﻟﻲ ﺯﻳﺮ ﻳﻚ ﺟﺪﻭﻝ ﺩﺭﺳﺘﻲ ﺑﺴﺎﺯﻳﺪ ﻛﻪ ﻣﻘﺎﺩﻳﺮ ﺩﺭﺳﺘﻲ‬
‫ﺁﻥﻫﺎ ﺭﺍ )‪ 0‬ﻳﺎ ‪ (1‬ﺑﻪ ﺍﺯﺍﻱ ﻫﺮ ﻣﻘﺪﺍﺭ ﺍﺯ ﻋﻤﻠﻮﻧﺪﻫﺎﻱ ‪ p‬ﻭ ‪ q‬ﻧﺸﺎﻥ ﺩﻫﺪ‪:‬‬
‫ﺍﻟﻒ ‐ ‪!p || q‬‬
‫‪p&&q‬‬ ‫ﺏ ‐ ‪|| !p&&!q‬‬
‫ﺝ ‐ )‪(p || q) && !(p&&q‬‬
‫‪ ‐7‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺟﺪﻭﻝ ﺩﺭﺳﺘﻲ ﺗﻌﻴﻴﻦ ﻛﻨﻴﺪ ﻛﻪ ﺁﻳﺎ ﺩﻭ ﻋﺒﺎﺭﺕ ﺑﻮﻟﻲ ﺩﺭ ﻫﺮ ﻳﻚ ﺍﺯ‬
‫ﻣﻌﺎﺩﻻﺕ ﺯﻳﺮ ﺑﺮﺍﺑﺮﻧﺪ ﻳﺎ ﺧﻴﺮ؟‬
‫‪91‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫ﺍﻟﻒ ‐ ‪ !p && !q‬ﻭ )‪!(p && q‬‬


‫ﺏ ‐ ‪ p‬ﻭ ‪!!p‬‬
‫‪!p || q‬‬ ‫ﺝ ‐ ‪ p || !q‬ﻭ‬
‫ﺩ – ‪ (p && q) && r‬ﻭ )‪p && (q && r‬‬
‫ﻩ – ‪ (p || q) && r‬ﻭ )‪p || (q && r‬‬
‫‪ ‐8‬ﺍﺭﺯﻳﺎﺑﻲ ﻣﻴﺎﻧﺒﺮﻱ ﭼﻴﺴﺖ ﻭ ﭼﻪ ﻓﺎﻳﺪﻩﺍﻱ ﺩﺍﺭﺩ؟‬
‫‪ ‐9‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﻛﺪ ﺯﻳﺮ ﺍﺳﺖ؟‬
‫;"‪if (x = 0) cout << x << " = 0\n‬‬
‫;"‪else cout << x << " != 0\n‬‬

‫‪ ‐10‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﻛﺪ ﺯﻳﺮ ﻭﺟﻮﺩ ﺩﺍﺭﺩ؟‬


‫<< " < " << ‪if (x < y < z) cout << x << " < " << y‬‬
‫;‪z << endl‬‬
‫‪ ‐11‬ﺑﺮﺍﻱ ﻫﺮ ﻳﻚ ﺍﺯ ﺷﺮﻁﻫﺎﻱ ﺯﻳﺮ ﻳﻚ ﻋﺒﺎﺭﺕ ﻣﻨﻄﻘﻲ ﺑﺴﺎﺯﻳﺪ‪:‬‬
‫ﺍﻟﻒ ‐ ‪ score‬ﺑﺰﺭﮒﺗﺮ ﻳﺎ ﻣﺴﺎﻭﻱ ‪ 80‬ﻭ ﻛﻮﭼﻚﺗﺮ ﺍﺯ ‪ 90‬ﺑﺎﺷﺪ‬
‫ﺏ ‐ ‪ answer‬ﺑﺮﺍﺑﺮ ﺑﺎ '‪ 'n‬ﻳﺎ '‪ 'N‬ﺑﺎﺷﺪ‬
‫ﺝ ‐ ‪ n‬ﻳﻚ ﻋﺪﺩ ﺯﻭﺝ ﺑﺎﺷﺪ ﻭﻟﻲ ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 8‬ﻧﺒﺎﺷﺪ‬
‫ﺩ ‐ ‪ ch‬ﻳﻚ ﺣﺮﻑ ﺑﺰﺭﮒ )‪ (capital‬ﺑﺎﺷﺪ‬
‫‪ ‐12‬ﺑﺮﺍﻱ ﻫﺮ ﻳﻚ ﺍﺯ ﺷﺮﻁﻫﺎﻱ ﺯﻳﺮ ﻳﻚ ﻋﺒﺎﺭﺕ ﻣﻨﻄﻘﻲ ﺑﺴﺎﺯﻳﺪ‪:‬‬
‫ﺍﻟﻒ ‐ ‪ n‬ﺑﻴﻦ ‪ 0‬ﻭ ‪ 7‬ﺑﺎﺷﺪ ﻭﻟﻲ ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 3‬ﻧﺒﺎﺷﺪ‬
‫ﺏ ‐ ‪ n‬ﺑﻴﻦ ‪ 0‬ﻭ ‪ 7‬ﺑﺎﺷﺪ ﻭﻟﻲ ﺯﻭﺝ ﻧﺒﺎﺷﺪ‬
‫ﺝ ‐ ‪ n‬ﺑﺮ ‪ 3‬ﺑﺨﺶﭘﺬﻳﺮ ﺑﺎﺷﺪ ﻭﻟﻲ ﺑﺮ ‪ 30‬ﺑﺨﺶﭘﺬﻳﺮ ﻧﺒﺎﺷﺪ‬
‫ﺩ ‐ ‪ ch‬ﻳﻚ ﺣﺮﻑ ﺑﺰﺭﮒ ﻳﺎ ﻛﻮﭼﻚ ﺑﺎﺷﺪ‬
‫‪ ‐13‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﺍﻳﻦ ﻛﺪ ﺍﺳﺖ؟‬
‫)‪if (x = = 0‬‬
‫"‪if (y = = 0) cout << "x and y are both zero.‬‬
‫;‪<< endl‬‬
‫;‪else cout << "x is not zero." << endl‬‬
‫‪ ‐14‬ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﻴﻦ ﺩﻭ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﺯﻳﺮ ﺍﺳﺖ؟‬
‫} ;"‪a. if (n > 2) { if (n < 6) cout << "OK‬‬
‫;"‪else cout << "NG‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪92‬‬

‫; "‪b. if (n > 2) { if (n < 6) cout << "OK‬‬


‫} ;"‪else cout << "NG‬‬
‫‪ ‐15‬ﺗﻞۀ ﺳﻘﻮﻁ ﭼﻴﺴﺖ؟‬
‫‪ ‐16‬ﻋﺒﺎﺭﺕ ﺯﻳﺮ ﭼﮕﻮﻧﻪ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ؟‬
‫;) )‪(x < y ? -1 : (x == y ? 0 : 1‬‬
‫‪ ‐17‬ﻳﻚ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻣﻨﻔﺮﺩ ﺩﺭ ‪ C++‬ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ‪،‬‬
‫ﻗﺪﺭﻣﻄﻠﻖ ‪ x‬ﺭﺍ ﺩﺭ ﻣﺘﻐﻴﺮ ‪ absx‬ﻗﺮﺍﺭ ﺩﻫﺪ‪.‬‬
‫‪ ‐18‬ﻳﻚ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ﻣﻨﻔﺮﺩ ﺩﺭ ‪ C++‬ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺍﮔﺮ ﻣﺘﻐﻴﺮ ‪ count‬ﺍﺯ ‪ 100‬ﺗﺠﺎﻭﺯ‬
‫ﻛﺮﺩ ﻋﺒﺎﺭﺕ "‪ "Too many‬ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‪:‬‬
‫ﺍﻟﻒ ‐ ﻳﻚ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ‪if‬‬
‫ﺏ ‐ ﻳﻚ ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ‬
‫‪93‬‬ ‫ﻓﺼﻞ ﺳﻮم ‪ /‬اﻧﺘﺨﺎب‬

‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪ ‐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‬ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬


‫;‪while (condition) statement‬‬

‫ﺑﻪ ﺟﺎﻱ ‪ ،condition‬ﻳﻚ ﺷﺮﻁ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﻭ ﺑﻪ ﺟﺎﻱ ‪ statement‬ﺩﺳﺘﻮﺭﻱ ﮐﻪ ﺑﺎﻳﺪ‬


‫ﺗﮑﺮﺍﺭ ﺷﻮﺩ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺍﮔﺮ ﻣﻘﺪﺍﺭ ﺷﺮﻁ‪ ،‬ﺻﻔﺮ)ﻳﻌﻨﻲ ﻧﺎﺩﺭﺳﺖ( ﺑﺎﺷﺪ‪statement ،‬‬

‫‪1 – Iteration‬‬ ‫‪2 - Loop‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪96‬‬

‫ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﺩ ﻭ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ﺑﻌﺪ ﺍﺯ ‪ while‬ﭘﺮﺵ ﻣﻲﻛﻨﺪ‪ .‬ﺍﮔﺮ ﻣﻘﺪﺍﺭ‬
‫ﺷﺮﻁ ﻧﺎﺻﻔﺮ)ﻳﻌﻨﻲ ﺩﺭﺳﺖ( ﺑﺎﺷﺪ‪ statement ،‬ﺍﺟﺮﺍ ﺷﺪﻩ ﻭ ﺩﻭﺑﺎﺭﻩ ﻣﻘﺪﺍﺭ ﺷﺮﻁ‬
‫ﺑﺮﺭﺳﻲ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﺗﮑﺮﺍﺭ ﺁﻥ ﻗﺪﺭ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﺷﺮﻁ ﺻﻔﺮ ﺷﻮﺩ‪ .‬ﺗﻮﺟﻪ‬
‫ﮐﻨﻴﺪ ﻛﻪ ﺷﺮﻁ ﺑﺎﻳﺪ ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ ﻗﺮﺍﺭ ﺑﮕﻴﺮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐1‬ﻣﺤﺎﺳﺐۀ ﺣﺎﺻﻞ ﺟﻤﻊ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﻣﺘﻮﺍﻟﻲ ﺑﺎ ﺣﻠﻖۀ ‪while‬‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﻘﺪﺍﺭ ‪ 1 + 2 + 3 + … + n‬ﺭﺍ ﺑﺮﺍﻱ ﻋﺪﺩ ﻭﺭﻭﺩﻱ ‪ n‬ﻣﺤﺎﺳﺒﻪ‬
‫ﻣﻲﻛﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n, i=1‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> n‬‬
‫;‪long sum=0‬‬
‫)‪while (i <= n‬‬
‫;‪sum += i++‬‬
‫" ‪cout << "The sum of the first " << n << " integers is‬‬
‫;‪<< sum‬‬
‫}‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺯ ﺳﻪ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ‪ 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‬‬

‫ﺑﻪ ﺗﻮﺭﻓﺘﮕﻲ ﺩﺳﺘﻮﺭ ﺩﺍﺧﻞ ﺣﻠﻘﻪ ﺗﻮﺟﻪ ﻛﻨﻴﺪ‪ .‬ﺍﻳﻦ ﺷﮑﻞ ﭼﻴﻨﺶ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﻛﻪ ﻣﻨﻄﻖ‬
‫ﺑﺮﻧﺎﻣﻪ ﺭﺍﺣﺖﺗﺮ ﺩﻧﺒﺎﻝ ﺷﻮﺩ‪ ،‬ﺧﺼﻮﺻﺎ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺑﺰﺭﮒ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐2‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺣﻠﻖۀ ‪ while‬ﺑﺮﺍﻱ ﺗﮑﺮﺍﺭ ﻳﮏ ﻣﺤﺎﺳﺒﻪ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺟﺬﺭ ﻫﺮ ﻋﺪﺩﻱ ﮐﻪ ﮐﺎﺭﺑﺮ ﻭﺍﺭﺩ ﮐﻨﺪ ﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‬
‫ﺍﺯ ﺣﻠﻖۀ ‪ while‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺗﺎ ﻣﺠﺒﻮﺭ ﻧﺒﺎﺷﻴﻢ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺐۀ ﺟﺬﺭ ﻋﺪﺩ ﺑﻌﺪﻱ‪ ،‬ﺑﺮﻧﺎﻣﻪ‬
‫ﺭﺍ ﺩﻭﺑﺎﺭﻩ ﺍﺟﺮﺍ ﮐﻨﻴﻢ‪:‬‬
‫)(‪int main‬‬
‫;‪{ double x‬‬
‫;" ‪cout << "Enter a positive number:‬‬
‫;‪cin >> x‬‬
‫)‪while (x > 0‬‬
‫;‪{ cout << "sqrt(" << x << ") = " << sqrt(x) << endl‬‬
‫;" ‪cout << "Enter another positive number (or 0 to quit):‬‬
‫;‪cin >> x‬‬
‫}‬
‫}‬
‫‪Enter a positive number: 49‬‬
‫‪sqrt(49) = 7‬‬
‫‪Enter another positive number (or 0 to quit): 3.14159‬‬
‫‪sqrt(3.14159) = 1.77245‬‬
‫‪Enter another positive number (or 0 to quit): 100000‬‬
‫‪sqrt(100000) = 316.228‬‬
‫‪Enter another positive number (or 0 to quit): 0‬‬

‫ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ‪ ،‬ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﻋﺒﺎﺭﺕ )‪ (x > 0‬ﺍﺳﺖ‪ .‬ﻣﻘﺪﺍﺭ ‪ x‬ﺩﺭﻭﻥ ﺣﻠﻘﻪ ﺑﺎ ﺗﻐﻴﻴﺮ‬
‫ﻋﺪﺩ ﻭﺭﻭﺩﻱ ﺗﻐﻴﻴﺮ ﻣﻲﮐﻨﺪ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﻓﻘﻂ ﻭﻗﺘﻲ ﺣﻠﻘﻪ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ ﮐﻪ ﻋﺪﺩ ﻭﺭﻭﺩﻱ ﺑﺮﺍﺑﺮ‬
‫ﺑﺎ ‪ 0‬ﻳﺎ ﮐﻢﺗﺮ ﺍﺯ ﺁﻥ ﺑﺎﺷﺪ‪ .‬ﻣﺘﻐﻴﺮﻱ ﻛﻪ ﺑﻪ ﺍﻳﻦ ﺷﮑﻞ ﺑﺮﺍﻱ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪ ،‬ﻣﺘﻐﻴﺮ‬
‫ﻛﻨﺘﺮﻝ ﺣﻠﻘﻪ ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪98‬‬

‫‪ 4‐2‬ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ ﺑﻪ ﻳﻚ ﺣﻠﻘﻪ‬


‫ﻗﺒﻼ ﺩﻳﺪﻳﻢ ﻛﻪ ﭼﮕﻮﻧﻪ ﺩﺳﺘﻮﺭ ‪ break‬ﺑﺮﺍﻱ ﻛﻨﺘﺮﻝ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ‪switch‬‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ )ﺑﻪ ﻣﺜﺎﻝ ‪ 3‐17‬ﻧﮕﺎﻩ ﻛﻨﻴﺪ(‪ .‬ﺍﺯ ﺩﺳﺘﻮﺭ ‪ break‬ﺑﺮﺍﻱ ﭘﺎﻳﺎﻥ ﺩﺍﺩﻥ ﺑﻪ‬
‫ﺣﻠﻘﻪﻫﺎ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐3‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ ‪ break‬ﺑﺮﺍﻱ ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ ﺑﻪ ﻳﻚ ﺣﻠﻘﻪ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺗﺎﺛﻴﺮ ﻣﺜﺎﻝ ‪ 4‐1‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫{‬ ‫;‪int n, i=1‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> n‬‬
‫;‪long sum=0‬‬
‫)‪while (true‬‬
‫{‬ ‫;‪if (i > n) break‬‬ ‫‪// terminates the loop immediately‬‬
‫;‪sum += i++‬‬
‫}‬
‫;‪cout << "The sum of the first " << n << " integers is " << sum‬‬
‫}‬
‫‪Enter a positive integer: 100‬‬
‫‪The sum of the first 100 integers is 5050‬‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺎﻧﻨﺪ ﻣﺜﺎﻝ ‪ 4‐1‬ﮐﺎﺭ ﻣﻲﮐﻨﺪ‪ :‬ﻫﻤﻴﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ‪ i‬ﺑﻪ ‪ n‬ﺑﺮﺳﺪ‪ ،‬ﺣﻠﻘﻪ ﺧﺎﺗﻤﻪ‬
‫ﻣﻲﻳﺎﺑﺪ ﻭ ﺩﺳﺘﻮﺭ ﺧﺮﻭﺟﻲ ﺩﺭ ﭘﺎﻳﺎﻥ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺷﺮﻁ ﻛﻨﺘﺮﻝ ﺣﻠﻘﻪ ‪ true‬ﺍﺳﺖ‪ .‬ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺣﻠﻘﻪ ﺑﺮﺍﻱ ﻫﻤﻴﺸﻪ‬
‫ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ ﻭ ﻫﻴﭻﮔﺎﻩ ﭘﺎﻳﺎﻥ ﻧﻤﻲﻳﺎﺑﺪ ﺍﻣﺎ ﺩﺭ ﺑﺪﻥۀ ﺣﻠﻘﻪ ﺷﺮﻃﻲ ﻫﺴﺖ ﮐﻪ ﺳﺒﺐ ﭘﺎﻳﺎﻥ‬
‫ﮔﺮﻓﺘﻦ ﺣﻠﻘﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺑﻪ ﻣﺤﺾ ﺍﻳﻦ ﮐﻪ ‪ i>n‬ﺷﻮﺩ ﺩﺳﺘﻮﺭ ‪ break‬ﺣﻠﻘﻪ ﺭﺍ ﻣﻲﺷﮑﻨﺪ ﻭ‬
‫ﮐﻨﺘﺮﻝ ﺑﻪ ﺑﻴﺮﻭﻥ ﺣﻠﻘﻪ ﭘﺮﺵ ﻣﻲﮐﻨﺪ‪ .‬ﻭﻗﺘﻲ ﻗﺮﺍﺭ ﺍﺳﺖ ﺣﻠﻘﻪ ﺍﺯ ﺩﺭﻭﻥ ﻛﻨﺘﺮﻝ ﺷﻮﺩ‪ ،‬ﻣﻌﻤﻮﻻ‬
‫ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺭﺍ ‪ true‬ﻣﻲﮔﺬﺍﺭﻧﺪ‪ .‬ﺑﺎ ﺍﻳﻦ ﺭﻭﺵ ﻋﻤﻼ ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺣﺬﻑ‬
‫ﻣﻲﺷﻮﺩ‪.‬‬
‫‪99‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫ﻳﻜﻲ ﺍﺯ ﻣﺰﻳﺖﻫﺎﻱ ﺩﺳﺘﻮﺭ ‪ break‬ﺍﻳﻦ ﺍﺳﺖ ﻛﻪ ﻓﻮﺭﺍ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‬


‫ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﻣﺎﺑﻘﻲ ﺩﺳﺘﻮﺭﻫﺎﻱ ﺩﺭﻭﻥ ﺣﻠﻘﻪ ﺍﺟﺮﺍ ﺷﻮﻧﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐4‬ﺍﻋﺪﺍﺩ ﻓﻴﺒﻮﻧﺎﭼﻲ‬


‫ﺍﻋﺪﺍﺩ ﻓﻴﺒﻮﻧﺎﭼﻲ … ‪ F0, F1, F2, F3,‬ﺑﻪ ﺷﮑﻞ ﺑﺎﺯﮔﺸﺘﻲ ﺗﻮﺳﻂ ﻣﻌﺎﺩﻟﻪﻫﺎﻱ‬
‫ﺯﻳﺮ ﺗﻌﺮﻳﻒ ﻣﻲﺷﻮﻧﺪ‪:‬‬
‫‪F0 = 0 ,‬‬ ‫‪F1 = 1 ,‬‬ ‫‪Fn = Fn-1 + Fn-2‬‬
‫ﻣﺜﻼ ﺑﺮﺍﻱ ‪ n=2‬ﺩﺍﺭﻳﻢ‪:‬‬
‫‪F2 = F2-1 + F2-2 = F1 + F0 = 0 + 1 = 1‬‬
‫ﻳﺎ ﺑﺮﺍﻱ ‪ n=3‬ﺩﺍﺭﻳﻢ‪:‬‬
‫‪F3 = F3-1 + F3-2 = F2 + F1 = 1 + 1 = 2‬‬
‫ﻭ ﺑﺮﺍﻱ ‪ n=4‬ﺩﺍﺭﻳﻢ‪:‬‬
‫‪F4 = F4-1 + F4-2 = F3 + F2 = 2 + 1 = 3‬‬
‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﻫﻢۀ ﺍﻋﺪﺍﺩ ﻓﻴﺒﻮﻧﺎﭼﻲ ﺭﺍ ﺗﺎ ﻳﻚ ﻣﺤﺪﻭﺩۀ ﻣﺸﺨﺺ ﮐﻪ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ‬
‫ﻣﻲﺷﻮﺩ‪ ،‬ﻣﺤﺎﺳﺒﻪ ﻭ ﭼﺎﭖ ﻣﻲﻛﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ long bound‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> bound‬‬
‫;"‪cout << "Fibonacci numbers < " << bound << ":\n0, 1‬‬
‫;‪long f0=0, f1=1‬‬
‫)‪while (true‬‬
‫;‪{ long f2 = f0 + f1‬‬
‫;‪if (f2 > bound) break‬‬ ‫‪// terminates the loop immediately‬‬
‫;‪cout << ", " << f2‬‬
‫;‪f0 = f1‬‬
‫;‪f1 = f2‬‬
‫}‬
‫}‬
‫‪Enter a positive integer: 1000‬‬
‫‪Fibonacci numbers < 1000:‬‬
‫‪0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪100‬‬

‫‪ (f2‬ﺩﺭﺳﺖ‬ ‫)‪> bound‬‬ ‫ﺣﻠﻖۀ ‪ while‬ﺷﺎﻣﻞ ﺑﻠﻮﻛﻲ ﺍﺯ ﭘﻨﺞ ﺩﺳﺘﻮﺭ ﺍﺳﺖ‪ .‬ﻭﻗﺘﻲ ﺷﺮﻁ‬
‫ﺑﺎﺷﺪ‪ ،‬ﺩﺳﺘﻮﺭ ‪ break‬ﺍﺟﺮﺍ ﺷﺪﻩ ﻭ ﺑﺪﻭﻥ ﺍﻳﻦ ﻛﻪ ﺳﻪ ﺩﺳﺘﻮﺭ ﺁﺧﺮ ﺣﻠﻘﻪ ﺍﺟﺮﺍ ﺷﻮﻧﺪ‪ ،‬ﺣﻠﻘﻪ‬
‫ﻓﻮﺭﺍ ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ‪.‬‬
‫ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺍﺯ ﻛﺎﺭﺍﻛﺘﺮ ﺧﻂ ﺟﺪﻳﺪ '‪ '\n‬ﺩﺭ ﺭﺷﺖۀ "‪ ":\n0,1‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‪.‬‬
‫ﺍﻳﻦ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﻛﻪ ﻋﻼﻣﺖ ﻛﻮﻟﻦ ‪ :‬ﺩﺭ ﭘﺎﻳﺎﻥ ﺧﻂ ﻓﻌﻠﻲ ﭼﺎﭖ ﺷﻮﺩ ﻭ ﺳﭙﺲ ﻣﮑﺎﻥﻧﻤﺎ‬
‫ﺑﻪ ﺧﻂ ﺑﻌﺪﻱ ﺭﻭﻱ ﺻﻔﺤﻪﻧﻤﺎﻳﺶ ﭘﺮﺵ ﻧﻤﺎﻳﺪ ﻭ ﺭﺷﺖۀ ‪ 0,1‬ﺭﺍ ﺩﺭ ﺷﺮﻭﻉ ﺁﻥ ﺧﻂ ﭼﺎﭖ‬
‫ﮐﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐5‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ )‪exit(0‬‬


‫ﺗﺎﺑﻊ )‪ exit(0‬ﺭﻭﺵ ﺩﻳﮕﺮﻱ ﺑﺮﺍﻱ ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ ﺑﻪ ﻳﻚ ﺣﻠﻘﻪ ﺍﺳﺖ‪ .‬ﻫﺮﭼﻨﺪ ﮐﻪ ﺍﻳﻦ‬
‫ﺗﺎﺑﻊ ﺑﻼﻓﺎﺻﻠﻪ ﺍﺟﺮﺍﻱ ﮐﻞ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﭘﺎﻳﺎﻥ ﻣﻲﺩﻫﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ long bound‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> bound‬‬
‫;"‪cout << "Fibonacci numbers < " << bound << ":\n0, 1‬‬
‫;‪long f0=0, f1=1‬‬
‫)‪while (true‬‬
‫;‪{ long f2 = f0 + f1‬‬
‫‪if (f2 > bound) exit(0); // terminates the program immediately‬‬
‫;‪cout << ", " << f2‬‬
‫;‪f0 = f1‬‬
‫;‪f1 = f2‬‬
‫}‬
‫}‬
‫‪Enter a positive integer: 1000‬‬
‫‪Fibonacci numbers < 1000:‬‬
‫‪0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987‬‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﭘﺲ ﺍﺯ ﺑﺪﻥۀ ﺣﻠﻘﻪ ﻫﻴﭻ ﺩﺳﺘﻮﺭ ﺩﻳﮕﺮﻱ ﻧﺪﺍﺭﺩ‪ .‬ﭘﺲ ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ ﺣﻠﻘﻪ ﺑﻪ ﻣﻌﻨﻲ‬
‫ﭘﺎﻳﺎﻥ ﺩﺍﺩﻥ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺖ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺎﻧﻨﺪ ﻣﺜﺎﻝ ‪ 4‐4‬ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‪.‬‬
‫‪101‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫ﺍﻳﻦ ﻣﺜﺎﻝ ﻳﻚ ﺭﺍﻩ ﺑﺮﺍﻱ ﺧﺮﻭﺝ ﺍﺯ ﺣﻠﻖۀ ﻧﺎﻣﺘﻨﺎﻫﻲ ﺭﺍ ﻧﺸﺎﻥ ﺩﺍﺩ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺭﻭﺵ‬
‫ﺩﻳﮕﺮﻱ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪ .‬ﺍﻣﺎ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺗﺮﺟﻴﺢ ﻣﻲﺩﻫﻨﺪ ﺍﺯ ‪ break‬ﺑﺮﺍﻱ ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ‬
‫ﺑﻪ ﺣﻠﻘﻪﻫﺎﻱ ﻧﺎﻣﺘﻨﺎﻫﻲ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻨﺪ ﺯﻳﺮﺍ ﻗﺎﺑﻠﻴﺖ ﺍﻧﻌﻄﺎﻑ ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐6‬ﻣﺘﻮﻗﻒ ﮐﺮﺩﻥ ﻳﻚ ﺣﻠﻖۀ ﻧﺎﻣﺘﻨﺎﻫﻲ‬


‫ﺍﮔﺮ ﺍﺯ ﺭﺍﻫﮑﺎﺭﻫﺎﻱ ﺧﺎﺗﻢۀ ﺣﻠﻘﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻧﮑﻨﻴﺪ‪ ،‬ﺣﻠﻘﻪ ﺑﺮﺍﻱ ﻫﻤﻴﺸﻪ ﺍﺩﺍﻣﻪ ﭘﻴﺪﺍ ﻣﻲﻛﻨﺪ‬
‫ﻭ ﺑﻪ ﻃﺒﻊ ﺁﻥ ﺑﺮﻧﺎﻣﻪ ﻫﻢ ﻫﻴﭻﮔﺎﻩ ﺑﻪ ﭘﺎﻳﺎﻥ ﻧﻤﻲﺭﺳﺪ‪ .‬ﻣﻤﮑﻦ ﺍﺳﺖ ﺷﺮﻁ ﮐﻨﺘﺮﻟﻲ ﮐﻪ ﺑﺮﺍﻱ‬
‫ﺣﻠﻘﻪ ﻣﻲﻧﻮﻳﺴﻴﺪ ﻫﻨﮕﺎﻡ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﻫﻴﭻﮔﺎﻩ »ﻧﺎﺩﺭﺳﺖ« ﻧﺸﻮﺩ ﻭ ﺣﻠﻘﻪ ﺗﺎ ﺑﻲﻧﻬﺎﻳﺖ ﺍﺩﺍﻣﻪ‬
‫ﻳﺎﺑﺪ‪ .‬ﺩﺭ ﭼﻨﻴﻦ ﻣﻮﺍﺭﺩﻱ ﺍﺯ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﮐﻤﮏ ﺑﮕﻴﺮﻳﺪ‪ .‬ﺑﺎ ﻓﺸﺮﺩﻥ ﮐﻠﻴﺪﻫﺎﻱ ‪Ctrl+C‬‬
‫ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﻳﮏ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺑﻪ ﺍﺟﺒﺎﺭ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‪ .‬ﻛﻠﻴﺪ ‪ Ctrl‬ﺭﺍ ﭘﺎﻳﻴﻦ ﻧﮕﻪ ﺩﺍﺷﺘﻪ ﻭ‬
‫ﻛﻠﻴﺪ ‪ C‬ﺭﻭﻱ ﺻﻔﺤﻪﻛﻠﻴﺪ ﺧﻮﺩ ﺭﺍ ﻓﺸﺎﺭ ﺩﻫﻴﺪ ﺗﺎ ﺑﺮﻧﺎﻡۀ ﻓﻌﻠﻲ ﺧﺎﺗﻤﻪ ﭘﻴﺪﺍ ﮐﻨﺪ‪ .‬ﺑﻪ ﮐﺪ ﺯﻳﺮ‬
‫ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ long bound‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> bound‬‬
‫;"‪cout << "Fibonacci numbers < " << bound << ":\n0, 1‬‬
‫;‪long f0=0, f1=1‬‬
‫)‪while (true‬‬ ‫)‪// ERROR: INFINITE LOOP! Press <Ctrl>+c.‬‬
‫;‪{ long f2 = f0 + f1‬‬
‫;‪cout << ", " << f2‬‬
‫;‪f0 = f1‬‬
‫;‪f1 = f2‬‬
‫}‬
‫}‬

‫‪Enter a positive integer: 1000‬‬


‫‪Fibonacci numbers < 1000:‬‬
‫‪0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987,‬‬
‫‪159781, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418,‬‬
‫‪317811, 5040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352,‬‬
‫‪24157817, 63245986, 102334155, 165580141, 267914296, 433494437,‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪102‬‬

‫ﭼﻮﻥ ﻫﻴﭻ ﺷﺮﻁ ﭘﺎﻳﺎﻥ ﺣﻠﻘﻪﺍﻱ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ‪ ،‬ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺗﺎ‬
‫ﺑﻲﻧﻬﺎﻳﺖ ﺍﺩﺍﻣﻪ ﺧﻮﺍﻫﺪ ﻳﺎﻓﺖ )ﺗﺎ ﻭﻗﺘﻲ ﺣﺎﻓﻈﻪ ﺳﺮﺭﻳﺰ ﺷﻮﺩ(‪ .‬ﭘﺲ ﮐﻠﻴﺪﻫﺎﻱ ‪ Ctrl+C‬ﺭﺍ‬
‫ﻓﺸﺎﺭ ﺩﻫﻴﺪ ﺗﺎ ﺑﺮﻧﺎﻣﻪ ﺧﺎﺗﻤﻪ ﻳﺎﺑﺪ‪.‬‬

‫‪ 4‐3‬ﺩﺳﺘﻮﺭ ‪do..while‬‬

‫ﺳﺎﺧﺘﺎﺭ ‪ do..while‬ﺭﻭﺵ ﺩﻳﮕﺮﻱ ﺑﺮﺍﻱ ﺳﺎﺧﺘﻦ ﺣﻠﻘﻪ ﺍﺳﺖ‪ .‬ﻧﺤﻮ ﺁﻥ ﺑﻪ‬


‫ﺻﻮﺭﺕ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫;)‪do statement while (condition‬‬

‫ﺑﻪ ﺟﺎﻱ ‪ condition‬ﻳﻚ ﺷﺮﻁ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﻭ ﺑﻪ ﺟﺎﻱ ‪ statement‬ﺩﺳﺘﻮﺭ ﻳﺎ‬


‫ﺑﻠﻮﮐﻲ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﮐﻪ ﻗﺮﺍﺭ ﺍﺳﺖ ﺗﮑﺮﺍﺭ ﺷﻮﺩ‪ .‬ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺍﺑﺘﺪﺍ ‪ statement‬ﺭﺍ ﺍﺟﺮﺍ‬
‫ﻣﻲﻛﻨﺪ ﻭ ﺳﭙﺲ ﺷﺮﻁ ‪ condition‬ﺭﺍ ﺑﺮﺭﺳﻲ ﻣﻲﻛﻨﺪ‪ .‬ﺍﮔﺮ ﺷﺮﻁ ﺩﺭﺳﺖ ﺑﻮﺩ ﺣﻠﻘﻪ‬
‫ﺩﻭﺑﺎﺭﻩ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ ﻭﮔﺮﻧﻪ ﺣﻠﻘﻪ ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ‪.‬‬
‫ﺩﺳﺘﻮﺭ ‪ do..while‬ﻣﺎﻧﻨﺪ ﺩﺳﺘﻮﺭ ‪ while‬ﺍﺳﺖ‪ .‬ﺑﺎ ﺍﻳﻦ ﻓﺮﻕ ﻛﻪ ﺷﺮﻁ ﮐﻨﺘﺮﻝ‬
‫ﺣﻠﻘﻪ ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﮐﻪ ﺩﺭ ﺍﺑﺘﺪﺍﻱ ﺣﻠﻘﻪ ﺍﺭﺯﻳﺎﺑﻲ ﮔﺮﺩﺩ‪ ،‬ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺣﻠﻘﻪ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﻳﻌﻨﻲ ﻫﺮ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻟﻲ ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﻛﻪ ﻗﺒﻞ ﺍﺯ ﺷﺮﻭﻉ ﺣﻠﻘﻪ ﺗﻨﻈﻴﻢ ﺷﻮﺩ‪ ،‬ﻣﻲﺗﻮﺍﻧﺪ ﺩﺭﻭﻥ ﺁﻥ‬
‫ﺗﻨﻈﻴﻢ ﮔﺮﺩﺩ‪ .‬ﻧﺘﻴﺞۀ ﺩﻳﮕﺮ ﺍﻳﻦ ﺍﺳﺖ ﻛﻪ ﺣﻠﻖۀ ‪ do..while‬ﻫﻤﻴﺸﻪ ﺑﺪﻭﻥ ﺗﻮﺟﻪ ﺑﻪ‬
‫ﻣﻘﺪﺍﺭ ﺷﺮﻁ ﻛﻨﺘﺮﻝ‪ ،‬ﻻﺍﻗﻞ ﻳﻚ ﺑﺎﺭ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﺣﻠﻖۀ ‪ while‬ﻣﻲﺗﻮﺍﻧﺪ ﺍﺻﻼ ﺍﺟﺮﺍ‬
‫ﻧﺸﻮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐7‬ﻣﺤﺎﺳﺐۀ ﺣﺎﺻﻞ ﺟﻤﻊ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﻣﺘﻮﺍﻟﻲ ﺑﺎ ﺣﻠﻖۀ ‪do..while‬‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺗﺄﺛﻴﺮ ﻣﺜﺎﻝ ‪ 4‐1‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n, i=0‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> n‬‬
‫;‪long sum=0‬‬
‫‪do‬‬
‫;‪sum += i++‬‬
‫;)‪while (i <= n‬‬
‫;‪cout << "The sum of the first " << n << " integers is " << sum‬‬
‫‪103‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫}‬

‫* ﻣﺜﺎﻝ ‪ 4‐8‬ﺍﻋﺪﺍﺩ ﻓﺎﻛﺘﻮﺭﻳﺎﻝ‬


‫ﺍﻋﺪﺍﺩ ﻓﺎﻛﺘﻮﺭﻳﺎﻝ !‪ 0‬ﻭ !‪ 1‬ﻭ !‪ 2‬ﻭ !‪ 3‬ﻭ … ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺭﺍﺑﻄﻪﻫﺎﻱ ﺑﺎﺯﮔﺸﺘﻲ ﺯﻳﺮ‬
‫ﺗﻌﺮﻳﻒ ﻣﻲﺷﻮﻧﺪ‪:‬‬
‫‪0! = 1‬‬ ‫‪,‬‬ ‫!)‪n! = n(n-1‬‬
‫ﺑﺮﺍﻱ ﻣﺜﺎﻝ‪ ،‬ﺑﻪ ﺍﺯﺍﻱ ‪ n = 1‬ﺩﺭ ﻣﻌﺎﺩﻝۀ ﺩﻭﻡ ﺩﺍﺭﻳﻢ‪:‬‬
‫‪1! = 1((1-1)!) = 1(0!) = 1(1) = 1‬‬
‫ﻫﻤﭽﻨﻴﻦ ﺑﺮﺍﻱ ‪ n = 2‬ﺩﺍﺭﻳﻢ‪:‬‬
‫‪2! = 2((2-1)!) = 2(1!) = 2(1) = 2‬‬
‫ﻭ ﺑﻪ ﺍﺯﺍﻱ ‪ n = 3‬ﺩﺍﺭﻳﻢ‪:‬‬
‫‪3! = 3((3-1)!) = 3(2!) = 3(2) = 6‬‬
‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻫﻢۀ ﺍﻋﺪﺍﺩ ﻓﺎﻛﺘﻮﺭﻳﺎﻝ ﺭﺍ ﮐﻪ ﺍﺯ ﻋﺪﺩ ﺩﺍﺩﻩ ﺷﺪﻩ ﮐﻮﭼﮏﺗﺮﻧﺪ‪ ،‬ﭼﺎﭖ ﻣﻲﮐﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ long bound‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> bound‬‬
‫;"‪cout << "Factorial numbers < " << bound << ":\n1‬‬
‫;‪long f=1, i=1‬‬
‫‪do‬‬
‫;‪{ cout << ", " << f‬‬
‫;‪f *= ++i‬‬
‫}‬
‫;)‪while (f < bound‬‬
‫}‬
‫‪Enter a positive integer: 100000‬‬
‫‪Factorial numbers < 100000:‬‬
‫‪1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880‬‬

‫ﺣﻠﻖۀ ‪ do..while‬ﺗﺎ ﻭﻗﺘﻲ ﻛﻪ ﺷﺮﻁ ﻛﻨﺘﺮﻝ )‪ (f < bound‬ﻧﺎﺩﺭﺳﺖ ﺷﻮﺩ‪ ،‬ﺗﻜﺮﺍﺭ‬


‫ﻣﻲﮔﺮﺩﺩ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪104‬‬

‫‪ 4‐4‬ﺩﺳﺘﻮﺭ ‪for‬‬

‫ﻧﺤﻮ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ‪ for‬ﺑﻪ ﺻﻮﺭﺕ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬


‫;‪for (initialization; condition; update) statement‬‬

‫ﺳﻪ ﻗﺴﻤﺖ ﺩﺍﺧﻞ ﭘﺮﺍﻧﺘﺰ‪ ،‬ﺣﻠﻘﻪ ﺭﺍ ﮐﻨﺘﺮﻝ ﻣﻲﮐﻨﻨﺪ‪ .‬ﻋﺒﺎﺭﺕ ‪ initialization‬ﺑﺮﺍﻱ‬


‫ﺍﻋﻼﻥ ﻳﺎ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺑﻪ ﻣﺘﻐﻴﺮ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﻋﺒﺎﺭﺕ ﺍﻭﻟﻴﻦ ﻋﺒﺎﺭﺗﻲ‬
‫ﺍﺳﺖ ﮐﻪ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﭘﻴﺶ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﻧﻮﺑﺖ ﺑﻪ ﺗﮑﺮﺍﺭﻫﺎ ﺑﺮﺳﺪ‪ .‬ﻋﺒﺎﺭﺕ ‪condition‬‬
‫ﺑﺮﺍﻱ ﺗﻌﻴﻴﻦ ﺍﻳﻦ ﮐﻪ ﺁﻳﺎ ﺣﻠﻘﻪ ﺑﺎﻳﺪ ﺗﮑﺮﺍﺭ ﺷﻮﺩ ﻳﺎ ﺧﻴﺮ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‪ .‬ﻳﻌﻨﻲ ﺍﻳﻦ ﻋﺒﺎﺭﺕ‪،‬‬
‫ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺍﺳﺖ‪ .‬ﺍﮔﺮ ﺍﻳﻦ ﺷﺮﻁ ﺩﺭﺳﺖ ﺑﺎﺷﺪ ﺩﺳﺘﻮﺭ ‪ statement‬ﺍﺟﺮﺍ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﻋﺒﺎﺭﺕ ‪ update‬ﺑﺮﺍﻱ ﭘﻴﺶﺑﺮﺩﻥ ﻣﺘﻐﻴﺮ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‪ .‬ﺍﻳﻦ ﻋﺒﺎﺭﺕ‬
‫ﭘﺲ ﺍﺯ ﺍﺟﺮﺍﻱ ‪ statement‬ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﮔﺮﺩﺩ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺯﻧﺠﻴﺮۀ ﻭﻗﺎﻳﻌﻲ ﮐﻪ ﺗﮑﺮﺍﺭ ﺭﺍ‬
‫ﺍﻳﺠﺎﺩ ﻣﻲﮐﻨﻨﺪ ﻋﺒﺎﺭﺗﻨﺪ ﺍﺯ‪:‬‬
‫‪ – 1‬ﺍﺭﺯﻳﺎﺑﻲ ﻋﺒﺎﺭﺕ ‪initialization‬‬

‫‪ – 2‬ﺑﺮﺭﺳﻲ ﺷﺮﻁ ‪ . condition‬ﺍﮔﺮ ﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﺪ‪ ،‬ﺣﻠﻘﻪ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ‪.‬‬


‫‪ – 3‬ﺍﺟﺮﺍﻱ ‪statement‬‬

‫‪ – 4‬ﺍﺭﺯﻳﺎﺑﻲ ﻋﺒﺎﺭﺕ ‪update‬‬

‫‪ – 5‬ﺗﮑﺮﺍﺭ ﮔﺎﻡﻫﺎﻱ ‪ 2‬ﺗﺎ ‪4‬‬


‫ﻭ‪ update‬ﻋﺒﺎﺭﺕﻫﺎﻱ‬ ‫ﻋﺒﺎﺭﺕﻫﺎﻱ ‪ initialization‬ﻭ ‪condition‬‬
‫ﺍﺧﺘﻴﺎﺭﻱ ﻫﺴﺘﻨﺪ‪ .‬ﻳﻌﻨﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﻥﻫﺎ ﺭﺍ ﺩﺭ ﺣﻠﻘﻪ ﺫﮐﺮ ﻧﮑﻨﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐9‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺣﻠﻖۀ ‪ for‬ﺑﺮﺍﻱ ﻣﺤﺎﺳﺐۀ ﻣﺠﻤﻮﻉ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﻣﺘﻮﺍﻟﻲ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺗﺄﺛﻴﺮ ﻣﺜﺎﻝ ‪ 4‐1‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫‪105‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫;‪cin >> n‬‬


‫;‪long sum=0‬‬
‫)‪for (int i=1; i <= n; i++‬‬
‫;‪sum += I‬‬
‫;‪cout << "The sum of the first " << n << " integers is " << sum‬‬
‫}‬

‫ﺩﺭ ﺣﻠﻖۀ ﺑﺮﻧﺎﻡۀ ﻓﻮﻕ‪ ،‬ﻋﺒﺎﺭﺕ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ‪ int i=1‬ﺍﺳﺖ‪ .‬ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ‪i<=n‬‬
‫ﻣﻲﺑﺎﺷﺪ ﻭ ﻋﺒﺎﺭﺕ ﭘﻴﺶﺑﺮﻱ ﻣﺘﻐﻴﺮ ﮐﻨﺘﺮﻝ ﻫﻢ ‪ i++‬ﺍﺳﺖ‪ .‬ﺩﻗﺖ ﮐﻨﻴﺪ ﻛﻪ ﺍﻳﻦﻫﺎ ﻫﻤﺎﻥ‬
‫ﻋﺒﺎﺭﺍﺗﻲ ﻫﺴﺘﻨﺪ ﻛﻪ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝﻫﺎﻱ ‪ 4‐1‬ﻭ ‪ 4‐3‬ﻭ ‪ 4‐7‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬
‫ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ‬ ‫‪for‬‬ ‫ﺩﺭ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻭﻗﺘﻲ ﻳﻚ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻝ ﺩﺭﻭﻥ ﻳﻚ ﺣﻠﻖۀ‬
‫ﻣﺤﺪﻭﺩ ﻣﻲﮔﺮﺩﺩ‪ .‬ﻳﻌﻨﻲ ﺁﻥ‬ ‫‪for‬‬ ‫ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ( ﺣﻮﺯۀ ﺁﻥ ﻣﺘﻐﻴﺮ ﺑﻪ ﻫﻤﺎﻥ ﺣﻠﻖۀ‬ ‫‪i‬‬ ‫)ﻣﺎﻧﻨﺪ‬
‫ﻣﺘﻐﻴﺮ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺑﻴﺮﻭﻥ ﺍﺯ ﺁﻥ ﺣﻠﻘﻪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪ .‬ﻧﺘﻴﺞۀ ﺩﻳﮕﺮ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻧﺎﻡ‬
‫ﻣﺸﺎﺑﻬﻲ ﺩﺭ ﺧﺎﺭﺝ ﺍﺯ ﺣﻠﻖۀ ‪ for‬ﺑﺮﺍﻱ ﻳﻚ ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﻮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐10‬ﺍﺳﺘﻔﺎﺩۀ ﻣﺠﺪﺩ ﺍﺯ ﺍﺳﺎﻣﻲ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻛﻨﺘﺮﻝ ﺣﻠﻖۀ ‪for‬‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻫﻤﺎﻥ ﺍﺛﺮ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 4‐1‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> n‬‬
‫;‪long sum=0‬‬
‫)‪for (int i=1; i < n/2; i++‬‬
‫‪// the scope of this i is this loop‬‬
‫;‪sum += i‬‬
‫)‪for (int i=n/2; i <= n; i++‬‬
‫‪// the scope of this i is this loop‬‬
‫;‪sum += i‬‬
‫; ‪cout << "The sum of the first " << n << " integers is " << sum‬‬
‫}‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 4‐9‬ﺭﺍ ﺍﻧﺠﺎﻡ‬ ‫‪for‬‬ ‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻫﻤﺎﻥ ﻣﺤﺎﺳﺒﺎﺕ ﺣﻠﻖۀ‬ ‫‪for‬‬ ‫ﺩﻭ ﺣﻠﻖۀ‬
‫ﻣﻲﺩﻫﻨﺪ‪ .‬ﺍﻳﻦ ﺩﻭ ﺣﻠﻘﻪ‪ ،‬ﻛﺎﺭ ﺭﺍ ﺑﻪ ﺩﻭ ﻗﺴﻤﺖ ﺗﻘﺴﻴﻢ ﻣﻲﻛﻨﻨﺪ‪ n/2 :‬ﻣﺤﺎﺳﺒﻪ ﺩﺭ ﺣﻠﻖۀ ﺍﻭﻝ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪106‬‬

‫ﺧﻮﺩﺵ‬ ‫‪i‬‬ ‫ﺍﻧﺠﺎﻡ ﻣﻲﮔﻴﺮﺩ ﻭ ﻣﺎﺑﻘﻲ ﺩﺭ ﺣﻠﻖۀ ﺩﻭﻡ‪ .‬ﻫﺮ ﺣﻠﻘﻪ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻞ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻟﻲ‬
‫ﺭﺍ ﺩﺍﺭﺩ‪.‬‬
‫‪for‬‬ ‫ﺍﺧﻄﺎﺭ‪ :‬ﺑﻴﺸﺘﺮ ﻛﺎﻣﭙﺎﻳﻠﺮﻫﺎﻱ ﻗﺒﻞ ﺍﺯ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‪ ،‬ﺣﻮﺯۀ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻟﻲ ﺣﻠﻖۀ‬
‫ﺭﺍ ﺗﺎ ﺑﻌﺪ ﺍﺯ ﭘﺎﻳﺎﻥ ﺣﻠﻘﻪ ﻧﻴﺰ ﮔﺴﺘﺮﺵ ﻣﻲﺩﻫﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐11‬ﺩﻭﺑﺎﺭﻩ ﺍﻋﺪﺍﺩ ﻓﻴﺒﻮﻧﺎﭼﻲ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺗﺄﺛﻴﺮ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 4‐8‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫;‪{ long bound‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> bound‬‬
‫;"‪cout << "Factorial numbers < " << bound << ":\n1‬‬
‫;‪long f=1‬‬
‫)‪for (int i=2; f <= bound; i++‬‬
‫;‪{ cout << ", " << f‬‬
‫;‪f *= i‬‬
‫}‬
‫}‬
‫‪Enter a positive integer: 100000‬‬
‫‪Factorial numbers < 100000:‬‬
‫‪1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880‬‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ ﺑﺎ ﻣﺜﺎﻝ ‪ 4‐8‬ﻣﻘﺎﻳﺴﻪ ﮐﻨﻴﺪ‪ .‬ﻫﺮ ﺩﻭ ﮐﺎﺭﻫﺎﻱ ﻣﺸﺎﺑﻬﻲ ﺭﺍ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﻨﺪ‪ .‬ﺩﺭ ﻫﺮ‬
‫ﺩﻭ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﮐﺎﺭﻫﺎﻱ ﺯﻳﺮ ﺍﻧﺠﺎﻡ ﻣﻲﺷﻮﺩ‪ :‬ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ ‪ 1‬ﺩﺭ ‪ f‬ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ ‪2‬‬
‫ﺩﺭ ‪ i‬ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﭘﻨﺞ ﮔﺎﻡ ﺗﮑﺮﺍﺭ ﺭﺥ ﻣﻲﺩﻫﺪ‪ :‬ﭼﺎﭖ ‪ ،f‬ﺿﺮﺏ ‪ f‬ﺩﺭ ‪،i‬‬
‫ﺍﻓﺰﺍﻳﺶ ‪ ،i‬ﺑﺮﺭﺳﻲ ﺷﺮﻁ )‪ (f <= bound‬ﻭ ﭘﺎﻳﺎﻥ ﺩﺍﺩﻥ ﺑﻪ ﺣﻠﻘﻪ ﺩﺭ ﺻﻮﺭﺕ ﻧﺎﺩﺭﺳﺖ‬
‫ﺑﻮﺩﻥ ﺷﺮﻁ‪ .‬ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺑﺎ ﺣﻠﻖۀ ‪ for‬ﻫﻤﺎﻥ ﺗﺄﺛﻴﺮ ﺑﺮﻧﺎﻣﻪ ﺑﺎ ﺣﻠﻖۀ ‪ do..while‬ﺭﺍ ﺩﺍﺭﺩ‪.‬‬
‫ﺩﺳﺘﻮﺭ ‪ for‬ﺍﻧﻌﻄﺎﻑﭘﺬﻳﺮﻱ ﺑﻴﺸﺘﺮﻱ ﺑﻪ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺩﻫﺪ‪ .‬ﻣﺜﺎﻝﻫﺎﻱ ﺯﻳﺮ ﺍﻳﻦ ﻣﻄﻠﺐ‬
‫ﺭﺍ ﺁﺷﻜﺎﺭ ﻣﻲﻛﻨﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐12‬ﻳﻚ ﺣﻠﻖۀ ‪ for‬ﻧﺰﻭﻟﻲ‬


‫‪107‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺩﻩ ﻋﺪﺩ ﺻﺤﻴﺢ ﻣﺜﺒﺖ ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﻧﺰﻭﻟﻲ ﭼﺎﭖ ﻣﻲﻛﻨﺪ‪:‬‬


‫)(‪int main‬‬
‫)‪{ for (int i=10; i > 0; i--‬‬
‫;‪cout << " " << i‬‬
‫}‬
‫‪10 9 8 7 6 5 4 3 2 1‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐13‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺣﻠﻖۀ ‪ for‬ﺑﺎ ﮔﺎﻡﻫﺎﻱ ﺑﺰﺭﮒﺗﺮ ﺍﺯ ﻳﮏ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻣﺸﺨﺺ ﻣﻲﻛﻨﺪ ﻛﻪ ﺁﻳﺎ ﻳﻚ ﻋﺪﺩ ﻭﺭﻭﺩﻱ ﺍﻭﻝ ﻫﺴﺖ ﻳﺎ ﺧﻴﺮ‪:‬‬
‫)(‪int main‬‬
‫;‪{ long n‬‬
‫;" ‪cout << "Enter a positive integer:‬‬
‫;‪cin >> n‬‬
‫;‪if (n < 2) cout << n << " is not prime." << endl‬‬
‫;‪else if (n < 4) cout << n << " is prime." << endl‬‬
‫;‪else if (n%2 == 0) cout << n << " = 2*" << n/2 << endl‬‬
‫‪else‬‬
‫)‪{ for (int d=3; d <= n/2; d+=2‬‬
‫)‪if (n%d == 0‬‬
‫;‪{ cout << n << " = " << d << "*" << n/d << endl‬‬
‫;)‪exit(0‬‬
‫}‬
‫;‪cout << n << " is prime." << endl‬‬
‫;}‬
‫}‬
‫‪Enter a positive integer: 101‬‬
‫‪101 is prime.‬‬

‫‪Enter a positive integer: 975313579‬‬


‫‪975313579 = 17*57371387‬‬

‫ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺣﻠﻖۀ ‪ for‬ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﺘﻐﻴﺮ ﮐﻨﺘﺮﻟﻲ ﺧﻮﺩ ﻳﻌﻨﻲ ‪ d‬ﺭﺍ ﺩﻭ ﻭﺍﺣﺪ ﺩﻭ ﻭﺍﺣﺪ‬
‫ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ‪ .‬ﺳﻌﻲ ﮐﻨﻴﺪ ﻣﻨﻄﻖ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐14‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻧﮕﻬﺒﺎﻥ ﺑﺮﺍﻱ ﻛﻨﺘﺮﻝ ﺣﻠﻖۀ ‪for‬‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﻘﺪﺍﺭ ﺑﻴﺸﻴﻦۀ ﻳﻚ ﺭﺷﺘﻪ ﺍﺯ ﺍﻋﺪﺍﺩ ﻭﺭﻭﺩﻱ ﺭﺍ ﭘﻴﺪﺍ ﻣﻲﻛﻨﺪ‪:‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪108‬‬

‫)(‪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‬ﺩﺭﻭﻥ ﺣﻠﻘﻪ ﺍﻋﻼﻥ‬
‫ﻣﻲﺷﺪ‪ ،‬ﭘﺲ ﺍﺯ ﺍﺗﻤﺎﻡ ﺣﻠﻘﻪ ﺍﺯ ﺑﻴﻦ ﻣﻲﺭﻓﺖ ﻭ ﺩﻳﮕﺮ ﻗﺎﺑﻞ ﺍﺳﺘﻔﺎﺩﻩ ﻧﺒﻮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐15‬ﺑﻴﺸﺘﺮ ﺍﺯ ﻳﻚ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻝ ﺩﺭ ﺣﻠﻖۀ ‪for‬‬


‫ﺣﻠﻖۀ ‪ for‬ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺩﻭ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻝ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫)‪{ for (int m=95, n=11, m%n > 0; m -= 3, n++‬‬
‫;‪cout << m << "%" << n << " = " << m%n << endl‬‬
‫}‬
‫‪95%11 = 7‬‬
‫‪92%12 = 8‬‬
‫‪89%13 = 11‬‬
‫‪109‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫‪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‬ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐16‬ﺣﻠﻘﻪﻫﺎﻱ ‪ for‬ﺗﻮﺩﺭﺗﻮ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﻚ ﺟﺪﻭﻝ ﺿﺮﺏ ﭼﺎﭖ ﻣﻲﻛﻨﺪ‪:‬‬
‫>‪#include <iomanip‬‬ ‫)(‪// defines setw‬‬
‫>‪#include <iostream‬‬ ‫‪// defines cout‬‬
‫;‪using namespace std‬‬
‫)(‪int main‬‬
‫)‪{ for (int x=1; x <= 10; x++‬‬
‫)‪{ for (int y=1; y <= 10; y++‬‬
‫;‪cout << setw(4) << x*y‬‬
‫;‪cout << endl‬‬
‫}‬
‫}‬
‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9‬‬ ‫‪10‬‬
‫‪2‬‬ ‫‪4‬‬ ‫‪6‬‬ ‫‪8‬‬ ‫‪10‬‬ ‫‪12‬‬ ‫‪14‬‬ ‫‪16‬‬ ‫‪18‬‬ ‫‪20‬‬
‫‪3‬‬ ‫‪6‬‬ ‫‪9‬‬ ‫‪12‬‬ ‫‪15‬‬ ‫‪18‬‬ ‫‪21‬‬ ‫‪24‬‬ ‫‪27‬‬ ‫‪30‬‬
‫‪4‬‬ ‫‪8‬‬ ‫‪12‬‬ ‫‪16‬‬ ‫‪20‬‬ ‫‪24‬‬ ‫‪28‬‬ ‫‪32‬‬ ‫‪36‬‬ ‫‪40‬‬
‫‪5‬‬ ‫‪10‬‬ ‫‪15‬‬ ‫‪20‬‬ ‫‪25‬‬ ‫‪30‬‬ ‫‪35‬‬ ‫‪40‬‬ ‫‪45‬‬ ‫‪50‬‬
‫‪6‬‬ ‫‪12‬‬ ‫‪18‬‬ ‫‪24‬‬ ‫‪30‬‬ ‫‪36‬‬ ‫‪42‬‬ ‫‪48‬‬ ‫‪54‬‬ ‫‪60‬‬
‫‪7‬‬ ‫‪14‬‬ ‫‪21‬‬ ‫‪28‬‬ ‫‪35‬‬ ‫‪42‬‬ ‫‪49‬‬ ‫‪56‬‬ ‫‪63‬‬ ‫‪70‬‬
‫‪8‬‬ ‫‪16‬‬ ‫‪24‬‬ ‫‪32‬‬ ‫‪40‬‬ ‫‪48‬‬ ‫‪56‬‬ ‫‪64‬‬ ‫‪72‬‬ ‫‪80‬‬
‫‪9‬‬ ‫‪18‬‬ ‫‪27‬‬ ‫‪36‬‬ ‫‪45‬‬ ‫‪54‬‬ ‫‪63‬‬ ‫‪72‬‬ ‫‪81‬‬ ‫‪90‬‬
‫‪10‬‬ ‫‪20‬‬ ‫‪30‬‬ ‫‪40‬‬ ‫‪50‬‬ ‫‪60‬‬ ‫‪70‬‬ ‫‪80‬‬ ‫‪90‬‬ ‫‪100‬‬

‫ﺩﺭ ﺍﻭﻟﻴﻦ ﺗﻜﺮﺍﺭ ﺍﺯ ﺣﻠﻖۀ ﺑﻴﺮﻭﻧﻲ‪ ،‬ﻭﻗﺘﻲ ﮐﻪ ‪ 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‬‬

‫ﺩﺳﺘﻮﺭ ‪ break‬ﻳﮏ ﺩﺳﺘﻮﺭ ﺁﺷﻨﺎﺳﺖ‪ .‬ﻗﺒﻼ ﺍﺯ ﺁﻥ ﺑﺮﺍﻱ ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ ﺑﻪ ﺩﺳﺘﻮﺭ‬


‫‪ switch‬ﻭ ﻫﻤﭽﻨﻴﻦ ﺣﻠﻘﻪﻫﺎﻱ ‪ while‬ﻭ ‪ do..while‬ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ‪ .‬ﺍﺯ ﺍﻳﻦ‬
‫ﺩﺳﺘﻮﺭ ﺑﺮﺍﻱ ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ ﺑﻪ ﺣﻠﻖۀ ‪ for‬ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪ .‬ﺩﺳﺘﻮﺭ ‪break‬‬
‫ﺍﻧﻌﻄﺎﻑﭘﺬﻳﺮﻱ ﺑﻴﺸﺘﺮﻱ ﺭﺍ ﺑﺮﺍﻱ ﺣﻠﻘﻪﻫﺎ ﺍﻳﺠﺎﺩ ﻣﻲﮐﻨﺪ‪ .‬ﻣﻌﻤﻮﻻ ﻳﮏ ﺣﻠﻖۀ ‪ ، while‬ﻳﮏ‬
‫ﺣﻠﻖۀ ‪ do..while‬ﻳﺎ ﻳﮏ ﺣﻠﻖۀ ‪ for‬ﻓﻘﻂ ﺩﺭ ﺷﺮﻭﻉ ﻳﺎ ﭘﺎﻳﺎﻥ ﻣﺠﻤﻮﻉۀ ﮐﺎﻣﻞ‬
‫ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎﻱ ﻣﻮﺟﻮﺩ ﺩﺭ ﺑﻠﻮﮎ ﺣﻠﻘﻪ‪ ،‬ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺩﺳﺘﻮﺭ ‪ break‬ﺩﺭ ﻫﺮ ﺟﺎﻳﻲ‬
‫ﺩﺭﻭﻥ ﺣﻠﻘﻪ ﻣﻲﺗﻮﺍﻧﺪ ﺟﺎ ﺑﮕﻴﺮﺩ ﻭ ﺩﺭ ﻫﻤﺎﻥ ﺟﺎ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐17‬ﻛﻨﺘﺮﻝ ﻭﺭﻭﺩﻱ ﺑﺎ ﻳﻚ ﻧﮕﻬﺒﺎﻥ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻳﻚ ﺭﺷﺘﻪ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﻣﺜﺒﺖ ﺭﺍ ﺗﺎ ﺯﻣﺎﻧﻲ ﮐﻪ ﺻﻔﺮ ﻭﺍﺭﺩ ﺷﻮﺩ‪ ،‬ﺧﻮﺍﻧﺪﻩ ﻭ‬
‫ﻣﻌﺪﻝ ﺁﻥﻫﺎ ﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻣﻲﻛﻨﺪ‪:‬‬
‫‪111‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫)(‪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‬ﺩﺭﻭﻥ ﺣﻠﻘﻪﻫﺎﻱ ﺗﻮﺩﺭﺗﻮ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪ ،‬ﻓﻘﻂ ﺭﻭﻱ ﺣﻠﻘﻪﺍﻱ‬
‫ﮐﻪ ﻣﺴﺘﻘﻴﻤﺎ ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺗﺎﺛﻴﺮ ﻣﻲﮔﺬﺍﺭﺩ‪ .‬ﺣﻠﻘﻪﻫﺎﻱ ﺑﻴﺮﻭﻧﻲ ﺑﺪﻭﻥ ﻫﻴﭻ ﺗﻐﻴﻴﺮﻱ‬
‫ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐18‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ ‪ break‬ﺩﺭ ﺣﻠﻘﻪﻫﺎﻱ ﺗﻮﺩﺭﺗﻮ‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪112‬‬

‫ﭼﻮﻥ ﻋﻤﻞ ﺿﺮﺏ ﺟﺎﺑﺠﺎﻳﻲﭘﺬﻳﺮ ﺍﺳﺖ )ﻳﻌﻨﻲ ‪ ،(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‬‬

‫ﺩﺳﺘﻮﺭ ‪ break‬ﺑﻘﻲۀ ﺩﺳﺘﻮﺭﻫﺎﻱ ﺩﺭﻭﻥ ﺑﻠﻮﻙ ﺣﻠﻘﻪ ﺭﺍ ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻭ ﺑﻪ ﺍﻭﻟﻴﻦ‬


‫ﺩﺳﺘﻮﺭ ﺑﻴﺮﻭﻥ ﺣﻠﻘﻪ ﭘﺮﺵ ﻣﻲﻛﻨﺪ‪ .‬ﺩﺳﺘﻮﺭ ‪ continue‬ﻧﻴﺰ ﺷﺒﻴﻪ ﻫﻤﻴﻦ ﺍﺳﺖ ﺍﻣﺎ ﺑﻪ ﺟﺎﻱ‬
‫‪113‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫ﺍﻳﻦ ﮐﻪ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﺩﻫﺪ‪ ،‬ﺍﺟﺮﺍ ﺭﺍ ﺑﻪ ﺗﻜﺮﺍﺭ ﺑﻌﺪﻱ ﺣﻠﻘﻪ ﻣﻨﺘﻘﻞ ﻣﻲﻛﻨﺪ‪ .‬ﺍﻳﻦ ﺩﺳﺘﻮﺭ‪،‬‬
‫ﺍﺩﺍﻡۀ ﭼﺮﺥۀ ﻓﻌﻠﻲ ﺭﺍ ﻟﻐﻮ ﮐﺮﺩﻩ ﻭ ﺍﺟﺮﺍﻱ ﺩﻭﺭ ﺑﻌﺪﻱ ﺣﻠﻘﻪ ﺭﺍ ﺁﻏﺎﺯ ﻣﻲﮐﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐19‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭﻫﺎﻱ ‪ break‬ﻭ ‪continue‬‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻡۀ ﻛﻮﭼﻚ‪ ،‬ﺩﺳﺘﻮﺭﻫﺎﻱ ‪ break‬ﻭ ‪ continue‬ﺭﺍ ﺷﺮﺡ ﻣﻲﺩﻫﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n = 1‬‬
‫;‪char c‬‬
‫) ‪for( ; ;n++‬‬
‫;‪{ cout << "\nLoop no: " << n << endl‬‬
‫;" >‪cout << "Continue? <y|n‬‬
‫;‪cin >> c‬‬
‫;‪if (c = = 'y') continue‬‬
‫;‪break‬‬
‫}‬
‫;‪cout << "\nTotal of loops: " << n‬‬
‫}‬
‫‪Loop no: 1‬‬
‫‪Continue? y‬‬
‫‪Loop no: 2‬‬
‫‪Continue? y‬‬
‫‪Loop no: 3‬‬
‫‪Continue? n‬‬
‫‪Total of loops: 3‬‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺗﻌﺪﺍﺩ ﺗﮑﺮﺍﺭ ﺣﻠﻘﻪ ﺭﺍ ﻣﻲﺷﻤﺎﺭﺩ‪ .‬ﺩﺭ ﺍﺑﺘﺪﺍﻱ ﻫﺮ ﺣﻠﻘﻪ ﺑﺎ ﭼﺎﭖ ‪ n‬ﻣﺸﺨﺺ‬
‫ﻣﻲﺷﻮﺩ ﮐﻪ ﭼﻨﺪﻣﻴﻦ ﺩﻭﺭ ﺣﻠﻘﻪ ﺩﺭ ﺣﺎﻝ ﺍﺟﺮﺍﺳﺖ‪ .‬ﺳﭙﺲ ﺍﺯ ﮐﺎﺭﺑﺮ ﺩﺭﺧﻮﺍﺳﺖ ﻣﻲﺷﻮﺩ ﺗﺎ‬
‫ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﺍﻧﺘﺨﺎﺏ‪ ،‬ﻭﺍﺭﺩ ﮐﻨﺪ‪ .‬ﺍﮔﺮ ﮐﺎﺭﺍﮐﺘﺮ ﻭﺍﺭﺩ ﺷﺪﻩ '‪ 'y‬ﺑﺎﺷﺪ‪ ،‬ﺷﺮﻁ‬
‫)'‪ (c=='y‬ﺑﺮﺍﺑﺮ ﺑﺎ ﺩﺭﺳﺖ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﻭ ﻟﺬﺍ ﺩﺳﺘﻮﺭ ‪ continue‬ﺍﺟﺮﺍ ﺷﺪﻩ ﻭ‬
‫ﺩﻭﺭ ﺟﺪﻳﺪ ﺣﻠﻘﻪ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ‪ .‬ﺍﮔﺮ ﮐﺎﺭﺍﮐﺘﺮ ﻭﺍﺭﺩ ﺷﺪﻩ ﻫﺮ ﭼﻴﺰﻱ ﻏﻴﺮ ﺍﺯ '‪ 'y‬ﺑﺎﺷﺪ‪،‬‬
‫ﺩﺳﺘﻮﺭ ‪ break‬ﺍﻳﻦ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ ﻭ ﮐﻨﺘﺮﻝ ﺍﺟﺮﺍ ﺑﻪ ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ﺑﻴﺮﻭﻥ ﺣﻠﻘﻪ‬
‫ﭘﺮﺵ ﻣﻲﮐﻨﺪ‪ .‬ﺳﭙﺲ ﻣﺠﻤﻮﻉ ﺩﻓﻌﺎﺗﻲ ﮐﻪ ﺣﻠﻘﻪ ﺗﮑﺮﺍﺭ ﺷﺪﻩ ﭼﺎﭖ ﻣﻲﮔﺮﺩﺩ ﻭ ﺑﺮﻧﺎﻣﻪ ﭘﺎﻳﺎﻥ‬
‫ﻣﻲﮔﻴﺮﺩ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪114‬‬

‫‪ 4‐7‬ﺩﺳﺘﻮﺭ ‪goto‬‬

‫ﺩﺳﺘﻮﺭﻫﺎﻱ ‪ break‬ﻭ ‪ continue‬ﻭ ‪ switch‬ﺑﺎﻋﺚ ﻣﻲﺷﻮﻧﺪ ﻛﻪ ﺍﺟﺮﺍﻱ‬


‫ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻣﻜﺎﻥ ﺩﻳﮕﺮﻱ ﺍﺯ ﺟﺎﻳﻲ ﻛﻪ ﺑﻪ ﻃﻮﺭ ﻃﺒﻴﻌﻲ ﺑﺎﻳﺪ ﻣﻲﺭﻓﺖ‪ ،‬ﻣﻨﺘﻘﻞ ﺷﻮﺩ‪ .‬ﻣﻘﺼﺪ‬
‫ﺍﻧﺘﻘﺎﻝ ﺭﺍ ﻧﻮﻉ ﺩﺳﺘﻮﺭ ﺗﻌﻴﻴﻦ ﻣﻲﮐﻨﺪ‪ break :‬ﺑﻪ ﺧﺎﺭﺝ ﺍﺯ ﺣﻠﻘﻪ ﻣﻲﺭﻭﺩ‪ continue ،‬ﺑﻪ‬
‫ﺷﺮﻁ ﺍﺩﺍﻡۀ ﺣﻠﻘﻪ)ﺩﻭﺭ ﺑﻌﺪﻱ ﺣﻠﻘﻪ( ﻣﻲﺭﻭﺩ ﻭ ‪ switch‬ﺑﻪ ﻳﮑﻲ ﺍﺯ ﺛﺎﺑﺖﻫﺎﻱ ‪case‬‬
‫ﻣﻲﺭﻭﺩ‪ .‬ﻫﺮ ﺱۀ ﺍﻳﻦ ﺩﺳﺘﻮﺭﻫﺎ ﺩﺳﺘﻮﺭ ﭘﺮﺵ‪ 1‬ﻫﺴﺘﻨﺪ ﺯﻳﺮﺍ ﺑﺎﻋﺚ ﻣﻲﺷﻮﻧﺪ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺍﺯ‬
‫ﺭﻭﻱ ﺩﺳﺘﻮﺭﻫﺎﻱ ﺩﻳﮕﺮ ﭘﺮﺵ ﻛﻨﺪ‪.‬‬
‫ﺩﺳﺘﻮﺭ‪ goto‬ﻧﻮﻉ ﺩﻳﮕﺮﻱ ﺍﺯ ﺩﺳﺘﻮﺭﻫﺎﻱ ﭘﺮﺵ ﺍﺳﺖ‪ .‬ﻣﻘﺼﺪ ﺍﻳﻦ ﭘﺮﺵ ﺗﻮﺳﻂ ﻳﻚ‬
‫ﺑﺮﭼﺴﺐ ﻣﻌﻴﻦ ﻣﻲﺷﻮﺩ‪ .‬ﺑﺮﭼﺴﺐ‪ 2‬ﺷﻨﺎﺳﻪﺍﻱ ﺍﺳﺖ ﻛﻪ ﺟﻠﻮﻱ ﺁﻥ ﻋﻼﻣﺖ ﻛﻮﻟﻦ) ‪( :‬‬
‫ﻣﻲﺁﻳﺪ ﻭ ﺟﻠﻮﻱ ﻳﻚ ﺩﺳﺘﻮﺭ ﺩﻳﮕﺮ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺑﺮﭼﺴﺐﻫﺎ ﺷﺒﻴﻪ ‪case‬ﻫﺎ ﺩﺭ ﺩﺳﺘﻮﺭ‬
‫‪ switch‬ﻫﺴﺘﻨﺪ‪ ،‬ﻳﻌﻨﻲ ﻣﻘﺼﺪ ﭘﺮﺵ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲﻛﻨﻨﺪ‪ .‬ﻳﮏ ﻣﺰﻳﺖ ﺩﺳﺘﻮﺭ ‪ goto‬ﺍﻳﻦ‬
‫ﺍﺳﺖ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻫﻢۀ ﺣﻠﻘﻪﻫﺎﻱ ﺗﻮﺩﺭﺗﻮ ﺧﺎﺭﺝ ﺷﺪ ﻭ ﺑﻪ ﻣﮑﺎﻥ‬
‫ﺩﻟﺨﻮﺍﻫﻲ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﭘﺮﺵ ﻧﻤﻮﺩ‪.‬‬
‫ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﻛﻪ ﺩﺳﺘﻮﺭ ‪ break‬ﻓﻘﻂ ﺩﺭﻭﻧﻲﺗﺮﻳﻦ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ‬
‫ﻣﻲﺩﻫﺪ ﻭﻟﻲ ﺑﺎ ﺩﺳﺘﻮﺭ ‪ goto‬ﻣﻲﺗﻮﺍﻥ ﭼﻨﺪ ﺣﻠﻘﻪ ﻳﺎ ﻫﻢۀ ﺣﻠﻘﻪﻫﺎ ﺭﺍ ﻳﮏﺟﺎ ﺧﺎﺗﻤﻪ ﺩﺍﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐20‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ ‪ goto‬ﺑﺮﺍﻱ ﺧﺎﺭﺝ ﺷﺪﻥ ﺍﺯ ﺣﻠﻘﻪﻫﺎﻱ ﺗﻮﺩﺭﺗﻮ‬


‫)(‪int main‬‬
‫;‪{ const int N=5‬‬
‫)‪for (int i=0; i<N; i++‬‬
‫)‪{ for (int j=0; j<N; j++‬‬
‫)‪{ for (int k=0; k<N; k++‬‬
‫;‪if (i+j+k>N) goto esc‬‬
‫;" " << ‪else cout << i+j+k‬‬
‫;" *" << ‪cout‬‬
‫}‬
‫‪esc: cout << "." << endl; // inside the‬‬ ‫‪i loop, outside the j loop‬‬
‫}‬
‫}‬
‫‪01234*12345*2345.‬‬
‫‪115‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫‪1‬‬ ‫‪2‬‬ ‫‪345*2345.‬‬


‫‪2‬‬ ‫‪3‬‬ ‫‪45.‬‬
‫‪3‬‬ ‫‪4‬‬ ‫‪5.‬‬
‫‪4‬‬ ‫‪5‬‬ ‫‪.‬‬

‫‪1 – Jump‬‬ ‫‪2 - Label‬‬

‫ﺍﮔﺮ ﺷﺮﻁ )‪ (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‬ﺳﺒﺐ ﺍﻓﺰﺍﻳﺶ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﻭ ﮐﺎﻫﺶ ﭘﺎﻳﺪﺍﺭﻱ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺷﻮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐21‬ﺧﺎﺭﺝ ﺷﺪﻥ ﺍﺯ ﭼﻨﺪ ﺣﻠﻖۀ ﺗﻮﺩﺭﺗﻮ ﺑﺪﻭﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ‪goto‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪116‬‬

‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺍﺛﺮ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 4‐20‬ﺭﺍ ﺩﺍﺭﺩ‪:‬‬


‫)(‪int main‬‬
‫;‪{ const int N=5‬‬
‫;‪bool done=false‬‬
‫)‪for (int i=0; i<N; i++‬‬
‫)‪{ for (int j=0; j<N && !done; j++‬‬
‫)‪{ for (int k=0; k<N && !done; k++‬‬
‫;‪if (i+j+k>N) done = true‬‬
‫;" " << ‪else cout << i+j+k‬‬
‫;" *" << ‪cout‬‬
‫}‬
‫;‪cout << "." << endl‬‬ ‫‪// inside the i loop,‬‬ ‫‪outside the j loop‬‬
‫;‪done = false‬‬
‫}‬
‫}‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﺯ ﻳﮏ ﭘﺮﭼﻢ ﺑﻪ ﻧﺎﻡ ‪ done‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‪ .‬ﻭﻗﺘﻲ ‪ done‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪true‬‬
‫ﺷﻮﺩ‪ ،‬ﻫﺮ ﺩﻭ ﺣﻠﻖۀ ﺩﺭﻭﻧﻲ ‪ k‬ﻭ ‪ j‬ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ ﻭ ﺣﻠﻖۀ ﺧﺎﺭﺟﻲ ‪ i‬ﺗﻜﺮﺍﺭﺵ ﺭﺍ ﺑﺎ ﭼﺎﭖ‬
‫ﻳﮏ ﻧﻘﻄﻪ ﺍﺩﺍﻣﻪ ﻣﻲﺩﻫﺪ ﻭ ﭘﺮﭼﻢ ﺭﺍ ﺩﻭﺑﺎﺭﻩ ‪ false‬ﻣﻲﮐﻨﺪ ﻭ ﺩﻭﺭ ﺟﺪﻳﺪ ﺭﺍ ﺁﻏﺎﺯ‬
‫ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﮔﺮﭼﻪ ﻣﻨﻄﻖ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﮐﻤﻲ ﭘﻴﭽﻴﺪﻩﺗﺮ ﺍﺳﺖ ﺍﻣﺎ ﻗﺎﺑﻠﻴﺖ ﺍﻃﻤﻴﻨﺎﻥ ﺑﻴﺸﺘﺮﻱ ﻧﺴﺒﺖ‬
‫ﺑﻪ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 4‐20‬ﺩﺍﺭﺩ ﺯﻳﺮﺍ ﻫﻴﭻ ﺣﻠﻘﻪﺍﻱ ﻧﻴﻤﻪﮐﺎﺭﻩ ﻧﻤﻲﻣﺎﻧﺪ ﻭ ﻫﻴﭻ ﻣﺘﻐﻴﺮﻱ‬
‫ﺑﻼﺗﮑﻠﻴﻒ ﺭﻫﺎ ﻧﻤﻲﺷﻮﺩ‪.‬‬

‫‪1‬‬
‫‪ 4‐8‬ﺗﻮﻟﻴﺪ ﺍﻋﺪﺍﺩ ﺷﺒﻪ ﺗﺼﺎﺩﻓﻲ‬
‫ﻳﻜﻲ ﺍﺯ ﻛﺎﺭﺑﺮﺩﻫﺎﻱ ﺑﺴﻴﺎﺭ ﻣﻬﻢ ﺭﺍﻳﺎﻧﻪﻫﺎ‪» ،‬ﺷﺒﻴﻪﺳﺎﺯﻱ‪ «2‬ﺳﻴﺴﺘﻢﻫﺎﻱ ﺩﻧﻴﺎﻱ ﻭﺍﻗﻌﻲ‬
‫ﺍﺳﺖ‪ .‬ﺗﺤﻘﻴﻘﺎﺕ ﻭ ﺗﻮﺳﻌﻪﻫﺎﻱ ﺑﺴﻴﺎﺭ ﭘﻴﺸﺮﻓﺘﻪ ﺑﻪ ﺍﻳﻦ ﺭﺍﻫﮑﺎﺭ ﺧﻴﻠﻲ ﻭﺍﺑﺴﺘﻪ ﺍﺳﺖ‪ .‬ﺑﻪ‬
‫ﻭﺳﻴﻞۀ ﺷﺒﻴﻪﺳﺎﺯﻱ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺭﻓﺘﺎﺭ ﺳﻴﺴﺘﻢﻫﺎﻱ ﻣﺨﺘﻠﻒ ﺭﺍ ﻣﻄﺎﻟﻌﻪ ﮐﻨﻴﻢ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﻻﺯﻡ‬
‫ﺑﺎﺷﺪ ﻭﺍﻗﻌﺎ ﺁﻥﻫﺎ ﺭﺍ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻧﻤﺎﻳﻴﻢ‪ .‬ﺩﺭ ﺷﺒﻴﻪﺳﺎﺯﻱ ﻧﻴﺎﺯ ﺍﺳﺖ »ﺍﻋﺪﺍﺩ ﺗﺼﺎﺩﻓﻲ« ﺗﻮﺳﻂ‬
‫ﺭﺍﻳﺎﻧﻪﻫﺎ ﺗﻮﻟﻴﺪ ﺷﻮﺩ ﺗﺎ ﻧﺎﺩﺍﻧﺴﺘﻪﻫﺎﻱ ﺩﻧﻴﺎﻱ ﻭﺍﻗﻌﻲ ﻣﺪﻝﺳﺎﺯﻱ ﺷﻮﺩ‪ .‬ﺍﻟﺒﺘﻪ ﺭﺍﻳﺎﻧﻪﻫﺎ »ﺛﺎﺑﺖﮐﺎﺭ«‬
‫ﻫﺴﺘﻨﺪ ﻳﻌﻨﻲ ﺑﺎ ﺩﺍﺩﻥ ﺩﺍﺩﻩﻫﺎﻱ ﻣﺸﺎﺑﻪ ﺑﻪ ﺭﺍﻳﺎﻧﻪﻫﺎﻱ ﻣﺸﺎﺑﻪ‪ ،‬ﻫﻤﻴﺸﻪ ﺧﺮﻭﺟﻲ ﻳﮑﺴﺎﻥ ﺗﻮﻟﻴﺪ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺑﺎ ﻭﺟﻮﺩ ﺍﻳﻦ ﻣﻲﺗﻮﺍﻥ ﺍﻋﺪﺍﺩﻱ ﺗﻮﻟﻴﺪ ﮐﺮﺩ ﮐﻪ ﺑﻪ ﻇﺎﻫﺮ ﺗﺼﺎﺩﻓﻲ ﻫﺴﺘﻨﺪ؛ ﺍﻋﺪﺍﺩﻱ ﮐﻪ‬
‫‪117‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫ﺑﻪ ﻃﻮﺭ ﻳﮑﻨﻮﺍﺧﺖ ﺩﺭ ﻳﮏ ﻣﺤﺪﻭﺩۀ ﺧﺎﺹ ﮔﺴﺘﺮﺩﻩﺍﻧﺪ ﻭ ﺑﺮﺍﻱ ﻫﻴﭻﮐﺪﺍﻡ ﺍﻟﮕﻮﻱ ﻣﺸﺨﺼﻲ‬
‫ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ‪ .‬ﭼﻨﻴﻦ ﺍﻋﺪﺍﺩﻱ ﺭﺍ »ﺍﻋﺪﺍﺩ ﺷﺒﻪﺗﺼﺎﺩﻓﻲ« ﻣﻲﻧﺎﻣﻴﻢ‪.‬‬
‫ﺳﺮﻓﺎﻳﻞ >‪ <cstdlib‬ﺩﺭ ‪ c‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺩﺍﺭﺍﻱ ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )(‪ rand‬ﺍﺳﺖ ﮐﻪ‬
‫ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺷﺒﻪﺗﺼﺎﺩﻓﻲ ﺩﺭ ﻣﺤﺪﻭﺩۀ ﺻﻔﺮ ﺗﺎ ‪ RAND_MAX‬ﺗﻮﻟﻴﺪ ﻣﻲﻧﻤﺎﻳﺪ‪.‬‬

‫‪1 – Pseudo Random‬‬ ‫‪2 - Simulation‬‬

‫‪ RAND_MAX‬ﺛﺎﺑﺘﻲ ﺍﺳﺖ ﮐﻪ ﺁﻥ ﻫﻢ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪ <cstdlib‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ‪ .‬ﻫﺮ ﺑﺎﺭ ﮐﻪ‬


‫ﺗﺎﺑﻊ )(‪ rand‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ‪ ،‬ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﻣﺘﻔﺎﻭﺕ ﺍﺯ ﻧﻮﻉ ‪ unsigned‬ﺗﻮﻟﻴﺪ‬
‫ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﻋﺪﺩ ﺩﺭ ﻣﺤﺪﻭﺩۀ ﺫﮐﺮ ﺷﺪﻩ ﻗﺮﺍﺭ ﺩﺍﺭﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐22‬ﺗﻮﻟﻴﺪ ﺍﻋﺪﺍﺩ ﺷﺒﻪ ﺗﺼﺎﺩﻓﻲ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺗﺎﺑﻊ )(‪ rand‬ﺑﺮﺍﻱ ﺗﻮﻟﻴﺪ ﺍﻋﺪﺍﺩ ﺷﺒﻪﺗﺼﺎﺩﻓﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻛﻨﺪ‪:‬‬
‫‪#include <cstdlib> // defines the rand() and RAND_MAX‬‬
‫>‪#include <iostream‬‬

‫)(‪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‬ﺧﻮﺩﻣﺎﻥ ﻣﻘﺪﺍﺭ ﻫﺴﺘﻪ ﺭﺍ ﺍﻧﺘﺨﺎﺏ ﮐﻨﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐23‬ﻛﺎﺭﮔﺬﺍﺭﻱ ﻫﺴﺘﻪ ﺑﻪ ﻃﻮﺭ ﻣﺤﺎﻭﺭﻩﺍﻱ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﺎﻧﻨﺪ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 4‐22‬ﺍﺳﺖ ﺑﺠﺰ ﺍﻳﻦ ﻛﻪ ﻣﻲﺗﻮﺍﻥ ﻫﺴﺖۀ ﺗﻮﻟﻴﺪﮐﻨﻨﺪۀ‬
‫ﺍﻋﺪﺍﺩ ﺗﺼﺎﺩﻓﻲ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺤﺎﻭﺭﻩﺍﻱ ﻭﺍﺭﺩ ﻧﻤﻮﺩ‪:‬‬
‫)(‪#include <cstdlib> // defines the rand() and srand‬‬
‫>‪#include <iostream‬‬

‫)(‪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‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫ﺳﻪ ﺍﺟﺮﺍﻱ ﻣﺘﻔﺎﻭﺕ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪:‬‬


‫‪Enter seed: 0‬‬
‫‪12345‬‬
‫‪1406932606‬‬
‫‪654583775‬‬
‫‪1449466924‬‬
‫‪229283573‬‬
‫‪1109335178‬‬
‫‪1051550459‬‬
‫‪1293799192‬‬

‫‪1 – Seed‬‬

‫‪Enter seed: 1‬‬


‫‪1103527590‬‬
‫‪377401575‬‬
‫‪662824084‬‬
‫‪1147902781‬‬
‫‪2035015474‬‬
‫‪368800899‬‬
‫‪1508029952‬‬
‫‪486256185‬‬

‫‪Enter seed: 12345‬‬


‫‪1406932606‬‬
‫‪654583775‬‬
‫‪1449466924‬‬
‫‪229283573‬‬
‫‪1109335178‬‬
‫‪1051550459‬‬
‫‪1293799192‬‬
‫‪794471793‬‬

‫ﺧﻂ ;)‪ srand(seed‬ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ ‪ seed‬ﺭﺍ ﺑﻪ ﻫﺴﺖۀ ﺩﺍﺧﻠﻲ ﺗﺨﺼﻴﺺ ﻣﻲﺩﻫﺪ‪.‬‬


‫ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺗﻮﺳﻂ ﺗﺎﺑﻊ )(‪ rand‬ﺑﺮﺍﻱ ﺗﻮﻟﻴﺪ ﺍﻋﺪﺍﺩ ﺷﺒﻪﺗﺼﺎﺩﻓﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﻫﺴﺘﻪﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ‪ ،‬ﻧﺘﺎﻳﺞ ﻣﺘﻔﺎﻭﺗﻲ ﺭﺍ ﺗﻮﻟﻴﺪ ﻣﻲﻛﻨﻨﺪ‪.‬‬
‫ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮ ‪ seed‬ﮐﻪ ﺩﺭ ﺳﻮﻣﻴﻦ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‬
‫)‪ (12345‬ﺍﻭﻟﻴﻦ ﻋﺪﺩﻱ ﺍﺳﺖ ﮐﻪ ﺗﻮﺳﻂ ﺗﺎﺑﻊ )(‪ rand‬ﺩﺭ ﺍﺟﺮﺍﻱ ﺍﻭﻝ ﺗﻮﻟﻴﺪ ﺷﺪﻩ ﺑﻮﺩ‪.‬‬
‫ﺩﺭ ﻧﺘﻴﺠﻪ ﺍﻋﺪﺍﺩ ﺍﻭﻝ ﺗﺎ ﻫﺸﺘﻢ ﮐﻪ ﺩﺭ ﺍﺟﺮﺍﻱ ﺳﻮﻡ ﺗﻮﻟﻴﺪ ﺷﺪﻩ ﺑﺎ ﺍﻋﺪﺍﺩ ﺩﻭﻡ ﺗﺎ ﻧﻬﻢ ﮐﻪ ﺩﺭ‬
‫ﺍﺟﺮﺍﻱ ﺍﻭﻝ ﺗﻮﻟﻴﺪ ﺷﺪﻩ ﺑﻮﺩ ﺑﺮﺍﺑﺮ ﺍﺳﺖ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺩﻗﺖ ﮐﻨﻴﺪ ﻛﻪ ﺭﺷﺘﻪ ﺍﻋﺪﺍﺩ ﺗﻮﻟﻴﺪ ﺷﺪﻩ ﺩﺭ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪120‬‬

‫ﺍﺟﺮﺍﻱ ﺩﻭﻡ ﻣﺎﻧﻨﺪ ﺭﺷﺘﻪ ﺍﻋﺪﺍﺩ ﺗﻮﻟﻴﺪ ﺷﺪﻩ ﺩﺭ ﻣﺜﺎﻝ ‪ 4‐22‬ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺍﻟﻘﺎ ﻣﻲﮐﻨﺪ‬
‫ﮐﻪ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﻫﺴﺘﻪ ﺩﺭ ﺍﻳﻦ ﺭﺍﻳﺎﻧﻪ‪ ،‬ﻋﺪﺩ ﻳﮏ ﺍﺳﺖ‪.‬‬
‫ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﻫﺴﺘﻪ ﺑﺎﻳﺪ ﺑﻪ ﻃﻮﺭ ﻣﺤﺎﻭﺭﻩﺍﻱ ﻭﺍﺭﺩ ﺷﻮﺩ ﻣﺸﮑﻠﻲ ﺍﺳﺖ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﺍﺯ ﺳﺎﻋﺖ ﺳﻴﺴﺘﻢ ﺣﻞ ﻣﻲﺷﻮﺩ‪» .‬ﺳﺎﻋﺖ ﺳﻴﺴﺘﻢ‪ «1‬ﺯﻣﺎﻥ ﻓﻌﻠﻲ ﺭﺍ ﺑﺮ ﺣﺴﺐ ﺛﺎﻧﻴﻪ ﻧﮕﻪ‬
‫ﻣﻲﺩﺍﺭﺩ‪ .‬ﺗﺎﺑﻊ )(‪ time‬ﮐﻪ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪ <ctime‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺯﻣﺎﻥ ﻓﻌﻠﻲ ﺭﺍ ﺑﻪ‬
‫ﺻﻮﺭﺕ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ‪ unsigned‬ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﻋﻨﻮﺍﻥ ﻫﺴﺘﻪ‬
‫ﺑﺮﺍﻱ ﺗﺎﺑﻊ )(‪ rand‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪.‬‬

‫‪1 – System timer‬‬

‫* ﻣﺜﺎﻝ ‪ 4‐24‬ﻛﺎﺭﮔﺬﺍﺭﻱ ﻫﺴﺘﻪ ﺍﺯ ﺳﺎﻋﺖ ﺳﻴﺴﺘﻢ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﻫﻤﺎﻥ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 4‐23‬ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﻓﺮﻕ ﻛﻪ ﻫﺴﺖۀ ﺗﻮﻟﻴﺪﮐﻨﻨﺪۀ‬
‫ﺍﻋﺪﺍﺩ ﺷﺒﻪﺗﺼﺎﺩﻓﻲ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺳﺎﻋﺖ ﺳﻴﺴﺘﻢ ﺗﻨﻈﻴﻢ ﻣﻲﮐﻨﺪ‪.‬‬
‫ﺗﻮﺟﻪ‪ :‬ﺍﮔﺮ ﻛﺎﻣﭙﺎﻳﻠﺮ ﺷﻤﺎ ﺳﺮﻓﺎﻳﻞ >‪ <ctime‬ﺭﺍ ﺗﺸﺨﻴﺺ ﻧﻤﻲﺩﻫﺪ‪ ،‬ﺑﻪ ﺟﺎﻱ ﺁﻥ‬
‫ﺍﺯ ﺳﺮﻓﺎﻳﻞ >‪ <time.h‬ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﺪ‪.‬‬
‫>‪#include <cstdlib‬‬
‫>‪#include <ctime‬‬ ‫‪// defines the time() function‬‬
‫>‪#include <iostream‬‬
‫>‪//#include <time.h‬‬ ‫‪// use this if <ctime> is not recognized‬‬
‫)(‪int main‬‬
‫{‬ ‫‪// prints pseudo-random numbers:‬‬
‫;)‪unsigned seed = time(NULL‬‬ ‫‪// uses the system clock‬‬
‫;‪cout << "seed = " << seed << endl‬‬
‫;)‪srand(seed‬‬ ‫‪// initializes the seed‬‬
‫)‪for (int i = 0; i < 8; i++‬‬
‫;‪cout << rand() << endl‬‬
‫}‬
‫‪seed = 808148157‬‬
‫‪1877361330‬‬
‫‪352899587‬‬
‫‪1443923328‬‬
‫‪1857423289‬‬
‫‪121‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫‪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‬‬

‫ﺩﺭ ﺑﻴﺸﺘﺮ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﮐﺎﺭﺑﺮﺩﻱ‪ ،‬ﻧﻴﺎﺯ ﺍﺳﺖ ﮐﻪ ﺍﻋﺪﺍﺩ ﺗﺼﺎﺩﻓﻲ ﺩﺭ ﻣﺤﺪﻭﺩۀ‬


‫ﻣﺸﺨﺼﻲ ﭘﺨﺶ ﺷﺪﻩ ﺑﺎﺷﻨﺪ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻃﺮﻳﻖۀ ﺍﻧﺠﺎﻡ ﺍﻳﻦ ﮐﺎﺭ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 122

‫ ﺗﻮﻟﻴﺪ ﺍﻋﺪﺍﺩ ﺗﺼﺎﺩﻓﻲ ﺩﺭ ﻳﮏ ﻣﺤﺪﻭﺩۀ ﻣﺸﺨﺺ‬4‐25 ‫* ﻣﺜﺎﻝ‬


‫ ﺍﺳﺖ ﺑﻪ ﺟﺰ ﺍﻳﻦ ﻛﻪ ﺍﻋﺪﺍﺩﻱ ﮐﻪ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺗﻮﻟﻴﺪ‬4‐24 ‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻣﺎﻧﻨﺪ ﻣﺜﺎﻝ‬
:‫ﻣﻲﻛﻨﺪ ﺩﺭ ﻳﮏ ﻧﺎﺣﻲۀ ﻣﺸﺨﺺ ﻣﺤﺪﻭﺩ ﺷﺪﻩ‬
#include <cstdlib>
#include <ctime> // defines the time() function
#include <iostream>
//#include <time.h> // use this if <ctime> is not recognized
int main()
{ // prints pseudo-random numbers:
unsigned seed = time(NULL); // uses the system clock
cout << "seed = " << seed << endl;
srand(seed); // initializes the seed
int min, max;
cout << "Enter minimum and maximum: ";
cin >> min >> max; // lowest and highest numbers
int range = max - min + 1; // number of numbers in rsnge
for (int i = 0; i < 20; i++)
{ int r = rand()/100%range + min;
cout << r << " ";
}
cout << endl;
}
seed = 808237677
Enter minimum and maximum: 1 100
85 57 1 10 5 73 81 43 46 42 17 44 48 9 3 74 41 4 30 68

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‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫ﺍﻟﻒ – ﺍﺻﻼ ﺗﮑﺮﺍﺭ ﻧﻤﻲﺷﻮﺩ‬


‫ﺏ – ﺗﺎ ﺑﻲﻧﻬﺎﻳﺖ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‬
‫ﺝ – ﻓﻘﻂ ﻳﮏ ﺑﺎﺭ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ‬
‫ﺩ – ﺍﮔﺮ ﺩﺭ ﺑﺪﻥۀ ﺣﻠﻘﻪ‪ ،‬ﺩﺳﺘﻮﺭ ﺧﺎﺗﻢۀ ﺣﻠﻘﻪ ﻭﺟﻮﺩ ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺗﺎ ﺑﻲﻧﻬﺎﻳﺖ ﺍﺩﺍﻣﻪ‬
‫ﻣﻲﻳﺎﺑﺪ‪.‬‬
‫‪ – 8‬ﺩﺭ ﭘﺎﻳﺎﻥ ﺣﻠﻘﻪﻫﺎﻱ ﻣﻘﺎﺑﻞ ﻣﻘﺪﺍﺭ ‪ k‬ﭼﻘﺪﺭ ﺍﺳﺖ؟‬
‫;‪k = 0‬‬
‫)‪for (i=0; i<5; i++‬‬
‫)‪for (j=0; j<5; j++‬‬
‫;‪k++‬‬
‫ﺩ – ‪50‬‬ ‫ﺝ – ‪25‬‬ ‫ﺏ – ‪10‬‬ ‫ﺍﻟﻒ – ‪5‬‬
‫‪ – 9‬ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ – ﺣﻠﻖۀ ‪ do..while‬ﺩﺳﺖ ﮐﻢ ﻳﮏ ﺑﺎﺭ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺏ – ﺣﻠﻖۀ ‪ while‬ﺩﺳﺖ ﮐﻢ ﻳﮏ ﺑﺎﺭ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺝ – ﺣﻠﻖۀ ‪ for‬ﺩﺳﺖ ﮐﻢ ﻳﮏ ﺑﺎﺭ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‬
‫ﺩ – ﺣﻠﻖۀ ‪ while‬ﻭ ﺣﻠﻖۀ ‪ for‬ﺩﺳﺖ ﮐﻢ ﻳﮏ ﺑﺎﺭ ﺍﺟﺮﺍ ﻣﻲﺷﻮﻧﺪ‪.‬‬
‫‪ – 10‬ﺩﺭ ﮐﺪﺍﻡ ﺣﻠﻘﻪ‪ ،‬ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﻫﺮ ﺗﮑﺮﺍﺭ ﺑﺮﺭﺳﻲ ﻣﻲﺷﻮﺩ؟‬
‫ﺩ – ﻫﻴﭻﮐﺪﺍﻡ‬ ‫‪for‬‬ ‫ﺝ – ﺣﻠﻖۀ‬ ‫‪do..while‬‬ ‫ﺏ ‐ ﺣﻠﻖۀ‬ ‫‪while‬‬ ‫ﺍﻟﻒ – ﺣﻠﻖۀ‬
‫‪ – 11‬ﮐﺪﺍﻡ ﺣﻠﻘﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺗﺎ ﺑﻲﻧﻬﺎﻳﺖ ﺍﺩﺍﻣﻪ ﻳﺎﺑﺪ؟‬
‫ﺩ – ﻫﻴﭻﮐﺪﺍﻡ‬ ‫‪for‬‬ ‫ﺝ – ﺣﻠﻖۀ‬ ‫‪do..while‬‬ ‫ﺏ – ﺣﻠﻖۀ‬ ‫‪while‬‬ ‫ﺍﻟﻒ – ﺣﻠﻖۀ‬
‫‪ – 12‬ﺩﺭ ﻣﻮﺭﺩ ﺣﻠﻘﻪﻫﺎﻱ ﺗﻮﺩﺭﺗﻮ ﮐﺪﺍﻡ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ – ﺩﺳﺘﻮﺭ ‪ break‬ﻓﻘﻂ ﺩﺭﻭﻧﻲﺗﺮﻳﻦ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‬
‫ﺏ – ﺩﺳﺘﻮﺭ ‪ break‬ﻓﻘﻂ ﺑﻴﺮﻭﻧﻲﺗﺮﻳﻦ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‬
‫ﺝ – ﺩﺳﺘﻮﺭ ‪ break‬ﻓﻘﻂ ﺣﻠﻘﻪﺍﻱ ﮐﻪ ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺩﺭ ﺑﺪﻥۀ ﺁﻥ ﻗﺮﺍﺭ ﺩﺍﺭﺩ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‬
‫ﺩ – ﺩﺳﺘﻮﺭ ‪ break‬ﺣﻠﻘﻪﻫﺎﻱ ﺩﺭﻭﻧﻲ ﻭ ﺑﻴﺮﻭﻧﻲ ﺭﺍ ﻳﮏﺟﺎ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‪.‬‬
‫‪ – 13‬ﮐﺪﺍﻡ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ – ﺣﻠﻖۀ ‪ for‬ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺣﻠﻖۀ ‪ while‬ﻳﺎ ﺣﻠﻖۀ ‪ do..while‬ﺗﺒﺪﻳﻞ ﮐﺮﺩ‪.‬‬
‫ﺏ – ﺣﻠﻖۀ ‪ for‬ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﺣﻠﻖۀ ‪ while‬ﻳﺎ ﺣﻠﻖۀ ‪ do..while‬ﺗﺒﺪﻳﻞ ﮐﺮﺩ‪.‬‬
‫ﺝ – ﺣﻠﻖۀ ‪ for‬ﺭﺍ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺣﻠﻖۀ ‪ while‬ﺗﺒﺪﻳﻞ ﮐﺮﺩ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪126‬‬

‫ﺩ – ﺣﻠﻖۀ ‪ for‬ﺭﺍ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺣﻠﻖۀ ‪ do..while‬ﺗﺒﺪﻳﻞ ﮐﺮﺩ‪.‬‬


‫‪ – 14‬ﺍﮔﺮ ﺑﻪ ﺟﺎﻱ ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺍﺟﺮﺍﻱ ﻳﮏ ﺣﻠﻘﻪ‪ ،‬ﻋﺒﺎﺭﺕ ‪ true‬ﻗﺮﺍﺭ ﺩﻫﻴﻢ ﺁﻧﮕﺎﻩ‪:‬‬
‫ﺍﻟﻒ – ﺣﻠﻘﻪ ﺍﺻﻼ ﺍﺟﺮﺍ ﻧﻤﻲﺷﻮﺩ‬
‫ﺏ – ﺣﻠﻘﻪ ﺣﺘﻤﺎ ﺗﺎ ﺑﻲﻧﻬﺎﻳﺖ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‬
‫ﺝ – ﺗﻌﺪﺍﺩ ﺗﮑﺮﺍﺭﻫﺎ ﺑﺴﺘﮕﻲ ﺑﻪ ﺩﺳﺘﻮﺭﺍﺕ ﺑﺪﻧﻪ ﺩﺍﺭﺩ‬
‫ﺩ – ﮐﺎﻣﭙﺎﻳﻠﺮ ﺧﻄﺎ ﻣﻲﮔﻴﺮﺩ‬
‫‪ – 15‬ﺍﮔﺮ ‪ i‬ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ ‪ bool‬ﺑﺎ ﻣﻘﺪﺍﺭ ‪ false‬ﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ ﺣﻠﻖۀ ﻣﻘﺎﺑﻞ ﭼﻨﺪ ﺑﺎﺭ‬
‫;‪while (!i) i=true‬‬ ‫ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ؟‬
‫ﺏ – ﻳﮏ ﺑﺎﺭ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‬ ‫ﺍﻟﻒ – ﺍﺻﻼ ﺍﺟﺮﺍ ﻧﻤﻲﺷﻮﺩ‬
‫ﺩ – ﺗﺎ ﻭﻗﺘﻲ ﺣﺎﻓﻈﻪ ﺳﺮﺭﻳﺰ ﺷﻮﺩ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‬ ‫ﺝ – ﺗﺎ ﺑﻲﻧﻬﺎﻳﺖ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‬
‫‪ – 16‬ﺩﺳﺘﻮﺭ ‪ continue‬ﺩﺭ ﺣﻠﻘﻪﻫﺎ ﭼﻪ ﮐﺎﺭﻱ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ؟‬
‫ﺍﻟﻒ – ﺣﻠﻘﻪ ﺭﺍ ﺩﺭ ﻫﻤﺎﻥ ﻣﺤﻞ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‬
‫ﺏ – ﻣﺎﺑﻘﻲ ﺩﺳﺘﻮﺭﺍﺕ ﺑﺪﻥۀ ﺣﻠﻘﻪ ﺭﺍ ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻭ ﺗﮑﺮﺍﺭ ﺑﻌﺪﻱ ﺣﻠﻘﻪ ﺭﺍ ﺁﻏﺎﺯ ﻣﻲﮐﻨﺪ‬
‫ﺝ – ﻣﺎﺑﻘﻲ ﺩﺳﺘﻮﺭﺍﺕ ﺑﺪﻥۀ ﺣﻠﻘﻪ ﺭﺍ ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻭ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‬
‫ﺩ – ﺗﻤﺎﻡ ﺩﺳﺘﻮﺭﺍﺕ ﺗﮑﺮﺍﺭ ﻓﻌﻠﻲ ﺭﺍ ﺍﺟﺮﺍ ﻧﻤﻮﺩﻩ ﻭ ﺳﭙﺲ ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‬
‫‪ – 17‬ﺩﺭ ﺭﺍﺑﻄﻪ ﺑﺎ ﺑﺨﺶ ‪ initializing‬ﻳﺎ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺩﺭ ﺣﻠﻖۀ ‪ for‬ﮐﺪﺍﻡ‬
‫ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟‬
‫ﺍﻟﻒ – ﺍﻳﻦ ﺑﺨﺶ ﻓﻘﻂ ﻳﮏ ﺑﺎﺭ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ‬
‫ﺏ – ﺍﻳﻦ ﺑﺨﺶ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺗﮑﺮﺍﺭﻫﺎ ﺁﻏﺎﺯ ﺷﻮﻧﺪ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ‬
‫ﺝ – ﺍﻳﻦ ﺑﺨﺶ ﻣﻲﺗﻮﺍﻧﺪ ﺩﺭ ﺣﻠﻖۀ ‪ for‬ﻗﻴﺪ ﻧﺸﻮﺩ‬
‫ﺩ – ﺩﺭ ﺣﻠﻘﻪﻫﺎﻱ ‪ for‬ﺗﻮﺩﺭﺗﻮ ﺍﻳﻦ ﺑﺨﺶ ﺣﺬﻑ ﻣﻲﺷﻮﺩ‬
‫‪127‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪ ‐1‬ﺩﺭ ﻳﻚ ﺣﻠﻖۀ ‪ while‬ﺍﮔﺮ ﺷﺮﻁ ﻛﻨﺘﺮﻝ ﺩﺭ ﺍﺑﺘﺪﺍ ﺑﺎ ﻣﻘﺪﺍﺭ ‪) false‬ﻳﻌﻨﻲ ﺻﻔﺮ(‬
‫ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﻮﺩ‪ ،‬ﭼﻪ ﺍﺗﻔﺎﻗﻲ ﻣﻲﺍﻓﺘﺪ؟‬
‫‪ ‐2‬ﭼﻪ ﻭﻗﺖ ﺑﺎﻳﺪ ﻣﺘﻐﻴﺮ ﻛﻨﺘﺮﻝ ﺩﺭ ﺣﻠﻖۀ ‪ for‬ﻗﺒﻞ ﺍﺯ ﺣﻠﻘﻪ ﺍﻋﻼﻥ ﮔﺮﺩﺩ )ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﻛﻪ‬
‫ﺩﺍﺧﻞ ﺑﺨﺶ ﻛﻨﺘﺮﻟﻲ ﺁﻥ ﺍﻋﻼﻥ ﮔﺮﺩﺩ(؟‬
‫‪ ‐3‬ﺩﺳﺘﻮﺭ ‪ break‬ﭼﮕﻮﻧﻪ ﺑﺎﻋﺚ ﻛﻨﺘﺮﻝ ﺑﻬﺘﺮ ﺭﻭﻱ ﺣﻠﻘﻪﻫﺎ ﻣﻲﺷﻮﺩ؟‬
‫‪ ‐4‬ﺣﺪﺍﻗﻞ ﺗﻜﺮﺍﺭ ﺩﺭ‪:‬‬
‫ﺍﻟﻒ ‐ ﻳﻚ ﺣﻠﻖۀ ‪ while‬ﭼﻘﺪﺭ ﺍﺳﺖ؟‬
‫ﺏ ‐ ﻳﻚ ﺣﻠﻖۀ ‪ do..while‬ﭼﻘﺪﺭ ﺍﺳﺖ؟‬
‫‪ ‐5‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﺣﻠﻖۀ ﺯﻳﺮ ﺍﺳﺖ؟‬
‫)‪while (n <= 100‬‬
‫;‪sum += n*n‬‬

‫‪ ‐6‬ﭼﻪ ﺧﻄﺎﻳﻲ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺍﺳﺖ؟‬


‫)(‪int main‬‬
‫;‪{ const double PI‬‬
‫;‪int n‬‬
‫‪PI = 3.14159265358979‬‬
‫;‪n = 22‬‬
‫}‬

‫‪» ‐7‬ﺣﻠﻖۀ ﺑﻲﭘﺎﻳﺎﻥ« ﭼﻴﺴﺖ ﻭ ﭼﻪ ﻓﺎﻳﺪﻩﺍﻱ ﺩﺍﺭﺩ؟‬


‫‪ ‐8‬ﭼﻄﻮﺭ ﻣﻲﺗﻮﺍﻥ ﺣﻠﻘﻪﺍﻱ ﺳﺎﺧﺖ ﻛﻪ ﺑﺎ ﻳﻚ ﺩﺳﺘﻮﺭ ﺩﺭ ﻭﺳﻂ ﺑﻠﻮﻛﺶ ﭘﺎﻳﺎﻥ ﻳﺎﺑﺪ؟‬
‫‪ ‐9‬ﭼﺮﺍ ﺍﺯ ﺑﻪﻛﺎﺭﮔﻴﺮﻱ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺩﺭ ﻣﻘﺎﻳﺴﻪﻫﺎﻱ ﺑﺮﺍﺑﺮﻱ ﺑﺎﻳﺪ ﺍﺟﺘﻨﺎﺏ ﺷﻮﺩ؟‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪128‬‬

‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪ ‐1‬ﻗﻄﻌﻪ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺭﺍ ﺩﻧﺒﺎﻝ ﻧﻤﺎﻳﻴﺪ ﻭ ﻣﻘﺪﺍﺭ ﻫﺮ ﻣﺘﻐﻴﺮ ﺭﺍ ﺩﺭ ﻫﺮ ﮔﺎﻡ ﻣﺸﺨﺺ ﮐﻨﻴﺪ‪:‬‬
‫;‪float x = 4.15‬‬
‫)‪for (int i=0; i < 3; i++‬‬
‫;‪x *= 2‬‬

‫‪ ‐2‬ﺣﻠﻖۀ ‪ for‬ﺯﻳﺮ ﺭﺍ ﺑﻪ ﺣﻠﻖۀ ‪ while‬ﺗﺒﺪﻳﻞ ﻛﻨﻴﺪ‪:‬‬


‫)‪for (int i=1; i <= n; i++‬‬
‫;" " << ‪cout << i*i‬‬

‫‪ ‐3‬ﺧﺮﻭﺟﻲ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ‪:‬‬


‫)(‪int main‬‬
‫)‪{ for (int i = 0; i < 8; i++‬‬
‫;"‪if ( i%2 == 0) cout << i + 1 << "\t‬‬
‫;"‪else if (i%3 == 0) cout << i*i << "\t‬‬
‫;"‪else if (i%5 == 0) cout << 2*i - 1 << "\t‬‬
‫;"‪else cout << i << "\t‬‬
‫}‬

‫‪ ‐4‬ﺧﺮﻭﺟﻲ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺭﺍ ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ‪:‬‬


‫)(‪int main‬‬
‫)‪{ for (int i=0; i < 8; i++‬‬
‫;‪{ if (i%2 == 0) cout << i + 1 << endl‬‬
‫;‪else if (i%3 == 0) continue‬‬
‫;‪else if (i%5 == 0) break‬‬
‫;"‪cout << "End of program.\n‬‬
‫}‬
‫;"‪cout << "End of program.\n‬‬
‫}‬

‫‪ ‐5‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﮐﻨﻴﺪ ﻛﻪ ﻋﺪﺩﻱ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ ﮔﺮﻓﺘﻪ ﻭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻳﻚ ﺣﻠﻖۀ‬


‫‪ while‬ﻣﺠﻤﻮﻉ ﻣﺮﺑﻌﺎﺕ ﺍﻋﺪﺍﺩ ﻣﺘﻮﺍﻟﻲ ﺗﺎ ﺁﻥ ﻋﺪﺩ ﺭﺍ ﭘﻴﺪﺍ ﮐﻨﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ ‪ 5‬ﻭﺍﺭﺩ‬
‫ﺷﻮﺩ‪ ،‬ﺑﺮﻧﺎﻣﻪ ﻣﺬﮐﻮﺭ ﻋﺪﺩ ‪ 55‬ﺭﺍ ﭼﺎﭖ ﻛﻨﺪ ﻛﻪ ﻣﻌﺎﺩﻝ ‪ 52+42+32+22+12‬ﺍﺳﺖ‪.‬‬
‫‪ ‐6‬ﭘﺎﺳﺦ ﺳﻮﺍﻝ ‪ 5‬ﺭﺍ ﺑﺎ ﻳﻚ ﺣﻠﻖۀ ‪ for‬ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ‪.‬‬
‫‪129‬‬ ‫ﻓﺼﻞ ﭼﻬﺎرم ‪ /‬ﺗﮑﺮار‬

‫‪ ‐7‬ﭘﺎﺳﺦ ﺳﻮﺍﻝ ‪ 5‬ﺭﺍ ﺑﺎ ﻳﻚ ﺣﻠﻖۀ ‪ do..while‬ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﻛﻨﻴﺪ‪.‬‬


‫‪ ‐8‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﮐﻨﻴﺪ ﮐﻪ ﺍﻋﻤﺎﻝ ﺗﻘﺴﻴﻢ ﻭ ﺑﺎﻗﻴﻤﺎﻧﺪﻩ ﺭﺍ ﺑﺪﻭﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬
‫ﻋﻤﻠﮕﺮﻫﺎﻱ ‪ /‬ﻭ ‪ %‬ﺑﺮﺍﻱ ﺗﻘﺴﻴﻢ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﻣﺜﺒﺖ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻣﻲﻛﻨﺪ‪.‬‬
‫‪ ‐9‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺍﺟﺮﺍ ﮐﻨﻴﺪ ﻛﻪ ﺍﺭﻗﺎﻡ ﻳﻚ ﻋﺪﺩ ﻣﺜﺒﺖ ﺩﺍﺩﻩ ﺷﺪﻩ ﺭﺍ ﻣﻌﻜﻮﺱ‬
‫ﻣﻲﻛﻨﺪ‪) .‬ﺑﻪ ﺗﻤﺮﻳﻦ ‪ 13‬ﻓﺼﻞ ﺳﻮﻡ ﻧﮕﺎﻩ ﻛﻨﻴﺪ(‬
‫‪ ‐10‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﮐﻪ ﺭﻳﺶۀ ﺻﺤﻴﺢ ﻳﮏ ﻋﺪﺩ ﺩﺍﺩﻩ ﺷﺪﻩ ﺭﺍ ﭘﻴﺪﺍ ﮐﻨﺪ‪ .‬ﺭﻳﺶۀ ﺻﺤﻴﺢ‪،‬‬
‫ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﺪﺩ ﺻﺤﻴﺤﻲ ﺍﺳﺖ ﮐﻪ ﻣﺮﺑﻊ ﺁﻥ ﮐﻮﭼﮏﺗﺮ ﻳﺎ ﻣﺴﺎﻭﻱ ﻋﺪﺩ ﺩﺍﺩﻩ ﺷﺪﻩ ﺑﺎﺷﺪ‪.‬‬
‫‪ – 11‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺍﻗﻠﻴﺪﺱ‪ ،‬ﺑﺰﺭﮒﺗﺮﻳﻦ ﻣﻘﺴﻮﻡﻋﻠﻴﻪ ﻣﺸﺘﺮﮎ ﺩﻭ ﻋﺪﺩ ﺻﺤﻴﺢ‬
‫ﺩﺍﺩﻩ ﺷﺪﻩ ﺭﺍ ﺑﻴﺎﺑﻴﺪ‪ .‬ﺍﻳﻦ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺑﻪ ﻭﺳﻴﻞۀ ﺗﻘﺴﻴﻢﻫﺎﻱ ﻣﺘﻮﺍﻟﻲ‪ ،‬ﺯﻭﺝ )‪ (m,n‬ﺭﺍ ﺑﻪ ﺯﻭﺝ‬
‫)‪ (n,0‬ﺗﺒﺪﻳﻞ ﻣﻲﮐﻨﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﺻﻮﺭﺕ ﮐﻪ ﻋﺪﺩ ﺻﺤﻴﺢ ﺑﺰﺭﮒﺗﺮ ﺭﺍ ﺑﺮ ﻋﺪﺩ ﮐﻮﭼﮏﺗﺮ‬
‫ﺗﻘﺴﻴﻢ ﮐﺮﺩﻩ ﻭ ﺳﭙﺲ ﺑﻪ ﺟﺎﻱ ﻋﺪﺩ ﺑﺰﺭﮒﺗﺮ‪ ،‬ﻋﺪﺩ ﮐﻮﭼﮏﺗﺮ ﺭﺍ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﻭ ﺑﻪ ﺟﺎﻱ‬
‫ﻋﺪﺩ ﮐﻮﭼﮏﺗﺮ‪ ،‬ﺑﺎﻗﻴﻤﺎﻧﺪﻩ ﺗﻘﺴﻴﻢ ﺭﺍ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﻭ ﺩﻭﺑﺎﺭﻩ ﺗﻘﺴﻴﻢ ﺭﺍ ﺭﻭﻱ ﺍﻳﻦ ﺯﻭﺝ ﺟﺪﻳﺪ‬
‫ﺗﮑﺮﺍﺭ ﻣﻲﮐﻨﺪ‪ .‬ﻭﻗﺘﻲ ﺑﺎﻗﻴﻤﺎﻧﺪﻩ ﺑﺮﺍﺑﺮ ﺑﺎ ﺻﻔﺮ ﺷﻮﺩ‪ ،‬ﻋﺪﺩ ﺩﻳﮕﺮ ﺍﺯ ﺁﻥ ﺯﻭﺝ‪ ،‬ﺑﺰﺭﮒﺗﺮﻳﻦ‬
‫ﻣﻘﺴﻮﻡﻋﻠﻴﻪ ﻣﺸﺘﺮﮎ ﺩﻭ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﻭﻟﻴﻪ ﺍﺳﺖ )ﻭ ﻫﻤﭽﻨﻴﻦ ﺑﺰﺭﮒﺗﺮﻳﻦ ﻣﻘﺴﻮﻡﻋﻠﻴﻪ‬
‫ﻣﺸﺘﺮﮎ ﺗﻤﺎﻡ ﺯﻭﺝﻫﺎﻱ ﻣﻴﺎﻧﻲ(‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ ‪ m‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 532‬ﻭ ‪ n‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 112‬ﺑﺎﺷﺪ‪،‬‬
‫ﺍﻟﮕﻮﺭﻳﺘﻢ ﺍﻗﻠﻴﺪﺱ ﺯﻭﺝ )‪ (532,112‬ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﺯﻳﺮ ﺑﻪ ﺯﻭﺝ )‪ (28,0‬ﺗﺒﺪﻳﻞ‬
‫ﻣﻲﮐﻨﺪ‪:‬‬
‫‪(532,112) Ö (112,84) Ö (84,28) Ö (28,0).‬‬
‫ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺍﻗﻠﻴﺪﺱ‪ ،‬ﺑﺰﺭﮒﺗﺮﻳﻦ ﻣﻘﺴﻮﻡﻋﻠﻴﻪ ﻣﺸﺘﺮﮎ ﺩﻭ‬
‫ﻋﺪﺩ ﺻﺤﻴﺢ ﺩﺍﺩﻩ ﺷﺪﻩ ﺭﺍ ﺑﻴﺎﺑﺪ‪.‬‬
‫ﻓﺼﻞ ﭘﻨﺠﻢ‬
‫» ﺗﻮﺍﺑﻊ«‬

‫‪ 5‐1‬ﻣﻘﺪﻣﻪ‬
‫ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻭﺍﻗﻌﻲ ﻭ ﺗﺠﺎﺭﻱ ﺑﺴﻴﺎﺭ ﺑﺰﺭﮒﺗﺮ ﺍﺯ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﻫﺴﺘﻨﺪ ﮐﻪ ﺗﺎﮐﻨﻮﻥ ﺑﺮﺭﺳﻲ‬
‫ﮐﺮﺩﻳﻢ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺑﺰﺭﮒ ﻗﺎﺑﻞ ﻣﺪﻳﺮﻳﺖ ﺑﺎﺷﻨﺪ‪ ،‬ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺭﺍ‬
‫ﺑﻪ ﺯﻳﺮﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﺑﺨﺶﺑﻨﺪﻱ ﻣﻲﮐﻨﻨﺪ‪ .‬ﺍﻳﻦ ﺯﻳﺮﺑﺮﻧﺎﻣﻪﻫﺎ »ﺗﺎﺑﻊ« ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺗﻮﺍﺑﻊ ﺭﺍ‬
‫ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻃﻮﺭ ﺟﺪﺍﮔﺎﻧﻪ ﮐﺎﻣﭙﺎﻳﻞ ﻭ ﺁﺯﻣﺎﻳﺶ ﻧﻤﻮﺩ ﻭ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻣﺨﺘﻠﻒ ﺩﻭﺑﺎﺭﻩ ﺍﺯ ﺁﻥﻫﺎ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪ .‬ﺍﻳﻦ ﺑﺨﺶﺑﻨﺪﻱ ﺩﺭ ﻣﻮﻓﻘﻴﺖ ﻳﮏ ﻧﺮﻡﺍﻓﺰﺍﺭ ﺷﻲﮔﺮﺍ ﺑﺴﻴﺎﺭ ﻣﻮﺛﺮ ﺍﺳﺖ‪.‬‬

‫‪ 5‐2‬ﺗﻮﺍﺑﻊ ﻛﺘﺎﺑﺨﺎﻧﻪﺍﻱ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬


‫»ﻛﺘﺎﺑﺨﺎﻥۀ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ« ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺳﺖ ﮐﻪ ﺷﺎﻣﻞ ﺗﻮﺍﺑﻊ ﺍﺯ ﭘﻴﺶ ﺗﻌﺮﻳﻒ ﺷﺪﻩ‬
‫ﻭ ﺳﺎﻳﺮ ﻋﻨﺎﺻﺮ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﻭ ﻋﻨﺎﺻﺮ ﺍﺯ ﻃﺮﻳﻖ »ﺳﺮﻓﺎﻳﻞﻫﺎ« ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲﺍﻧﺪ‪.‬‬
‫ﻗﺒﻼ ﺑﺮﺧﻲ ﺍﺯ ﺁﻥﻫﺎ ﺭﺍ ﺍﺳﺘﻔﺎﺩﻩ ﻛﺮﺩﻩﺍﻳﻢ‪ :‬ﺛﺎﺑﺖ ‪ INT_MAX‬ﮐﻪ ﺩﺭ >‪ <climits‬ﺗﻌﺮﻳﻒ‬
‫ﺷﺪﻩ )ﻣﺜﺎﻝ ‪ ،(2‐1‬ﺗﺎﺑﻊ )(‪ sqrt‬ﮐﻪ ﺩﺭ >‪ <cmath‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ )ﻣﺜﺎﻝ ‪ ،(2‐15‬ﺗﺎﺑﻊ‬
‫)(‪ rand‬ﮐﻪ ﺩﺭ >‪ <cstdlib‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ )ﻣﺜﺎﻝ ‪ (4‐22‬ﻭ ﺗﺎﺑﻊ )(‪ time‬ﮐﻪ ﺩﺭ‬
‫‪131‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫>‪ <ctime‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ )ﻣﺜﺎﻝ ‪ .(4‐24‬ﺍﻭﻟﻴﻦ ﻣﺜﺎﻝ ﺍﻳﻦ ﺑﺨﺶ‪ ،‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻳﻚ ﺗﺎﺑﻊ‬
‫ﺭﻳﺎﺿﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐1‬ﺗﺎﺑﻊ ﺟﺬﺭ )(‪sqrt‬‬


‫ﺭﻳﺶۀ ﺩﻭﻡ ﻳﻚ ﻋﺪﺩ ﻣﺜﺒﺖ‪ ،‬ﺟﺬﺭ ﺁﻥ ﻋﺪﺩ ﺍﺳﺖ‪ .‬ﺭﻳﺶۀ ﺩﻭﻡ ‪ ،9‬ﻋﺪﺩ ‪ 3‬ﺍﺳﺖ‪.‬‬
‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﺗﺎﺑﻊ ﺟﺬﺭ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺟﻌﺐۀ ﺳﻴﺎﻩ ﺗﺼﻮﺭ ﻛﻨﻴﻢ ﻛﻪ ﻭﻗﺘﻲ ﻋﺪﺩ ‪ 9‬ﺩﺭﻭﻥ ﺁﻥ‬
‫ﻗﺮﺍﺭ ﮔﻴﺮﺩ‪ ،‬ﻋﺪﺩ ‪ 3‬ﺍﺯ ﺁﻥ ﺧﺎﺭﺝ ﻣﻲﺷﻮﺩ ﻭ ﻭﻗﺘﻲ ﻋﺪﺩ ‪ 2‬ﺩﺭ ﺁﻥ ﻗﺮﺍﺭ ﮔﻴﺮﺩ‪ ،‬ﻋﺪﺩ‬
‫‪ 1/41421‬ﺍﺯ ﺁﻥ ﺧﺎﺭﺝ ﻣﻲﺷﻮﺩ‪ .‬ﺗﺎﺑﻊ ﻣﺎﻧﻨﺪ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﮐﺎﻣﻞ‪ ،‬ﺩﺍﺭﺍﻱ ﺭﻭﻧﺪ ﻭﺭﻭﺩﻱ ‐‬
‫ﭘﺮﺩﺍﺯﺵ ‐ ﺧﺮﻭﺟﻲ ﺍﺳﺖ ﻫﺮﭼﻨﺪ ﮐﻪ ﭘﺮﺩﺍﺯﺵ‪ ،‬ﻣﺮﺣﻠﻪﺍﻱ ﭘﻨﻬﺎﻥ ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﻧﻤﻲﺩﺍﻧﻴﻢ ﮐﻪ‬
‫ﺗﺎﺑﻊ ﺭﻭﻱ ﻋﺪﺩ ‪ 2‬ﭼﻪ ﺍﻋﻤﺎﻟﻲ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ ﮐﻪ ‪ 1/41421‬ﺣﺎﺻﻞ ﻣﻲﺷﻮﺩ‪ .‬ﺗﻨﻬﺎ ﭼﻴﺰﻱ‬
‫ﮐﻪ ﻻﺯﻡ ﺍﺳﺖ ﺑﺪﺍﻧﻴﻢ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻋﺪﺩ ‪ 1/41421‬ﺟﺬﺭ ﺍﺳﺖ ﻭ ﻣﺠﺬﻭﺭ ﺁﻥ‪ ،‬ﻋﺪﺩ‬
‫ﻭﺭﻭﺩﻱ ‪ 2‬ﺑﻮﺩﻩ ﺍﺳﺖ‪.‬‬
‫ﺑﺮﻧﺎﻡۀ ﺳﺎﺩۀ ﺯﻳﺮ‪ ،‬ﺗﺎﺑﻊ ﺍﺯ ﭘﻴﺶ ﺗﻌﺮﻳﻒ ﺷﺪۀ ﺟﺬﺭ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﺩ‪:‬‬
‫>‪#include <cmath‬‬ ‫‪// defines the sqrt() function‬‬
‫>‪#include <iostream‬‬ ‫‪// defines the cout object‬‬
‫;‪using namespace std‬‬
‫)(‪int main‬‬
‫‪{ //tests the sqrt() function:‬‬
‫)‪for (int x=0; x < 6; x++‬‬
‫;‪cout << "\t" << x << "\t" << sqrt(x) << endl‬‬
‫}‬
‫‪0‬‬ ‫‪0‬‬
‫‪1‬‬ ‫‪1‬‬
‫‪2‬‬ ‫‪1.41421‬‬
‫‪3‬‬ ‫‪1.73205‬‬
‫‪4‬‬ ‫‪2‬‬
‫‪5‬‬ ‫‪2.23607‬‬

‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺭﻳﺶۀ ﺩﻭﻡ ﺍﻋﺪﺍﺩ ﺻﻔﺮ ﺗﺎ ﭘﻨﺞ ﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ‪ .‬ﻫﺮ ﻭﻗﺖ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ‬
‫ﻋﺒﺎﺭﺕ )‪ 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‬ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﺑﻪ ﺭﻧﮓ ﺗﻴﺮﻩ ﺍﺳﺖ‪ ،‬ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎ ﻛﻪ ﻓﺮﺍﻳﻨﺪ ﺩﺍﺧﻠﻲ ﻭ ﻧﺤﻮۀ ﮐﺎﺭ‬
‫ﺁﻥ ﻗﺎﺑﻞ ﺭﻭﻳﺖ ﻧﻴﺴﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐2‬ﺁﺯﻣﺎﻳﺶ ﻳﻚ ﺭﺍﺑﻂۀ ﻣﺜﻠﺜﺎﺗﻲ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻢ ﺍﺯ ﺳﺮﻓﺎﻳﻞ >‪ <cmath‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻛﻨﺪ‪ .‬ﻫﺪﻑ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺻﺤﺖ‬
‫ﺭﺍﺑﻂۀ ‪ Sin2x=2SinxCosx‬ﺑﻪ ﺷﮑﻞ ﺗﺠﺮﺑﻲ ﺑﺮﺭﺳﻲ ﺷﻮﺩ‪.‬‬
‫)(‪int main‬‬
‫‪{ // tests the identity sin 2x = 2 sin x cos x:‬‬
‫)‪for (float x=0; x < 2; x += 0.2‬‬
‫"‪cout << x << "\t\t" << sin(2*x) << "\t‬‬

‫‪1 – Function call‬‬ ‫‪2 – Argument‬‬ ‫‪3 – Pass by value‬‬


‫‪133‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫;‪<< 2*sin(x)*cos(x) << endl‬‬


‫}‬
‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪0.2‬‬ ‫‪0.389418‬‬ ‫‪0.389418‬‬
‫‪0.4‬‬ ‫‪0.717356‬‬ ‫‪0.717356‬‬
‫‪0.6‬‬ ‫‪0.932039‬‬ ‫‪0.932039‬‬
‫‪0.8‬‬ ‫‪0.999574‬‬ ‫‪0.999574‬‬
‫‪1‬‬ ‫‪0.909297‬‬ ‫‪0.909297‬‬
‫‪1.2‬‬ ‫‪0.675463‬‬ ‫‪0.675463‬‬
‫‪1.4‬‬ ‫‪0.334988‬‬ ‫‪0.334988‬‬
‫‪1.6‬‬ ‫‪-0.0583744‬‬ ‫‪-0.0583744‬‬
‫‪1.8‬‬ ‫‪-0.442521‬‬ ‫‪-0.442521‬‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻣﻘﺪﺍﺭ ‪ x‬ﺭﺍ ﺩﺭ ﺳﺘﻮﻥ ﺍﻭﻝ‪ ،‬ﻣﻘﺪﺍﺭ ‪ Sin2x‬ﺭﺍ ﺩﺭ ﺳﺘﻮﻥ ﺩﻭﻡ ﻭ ﻣﻘﺪﺍﺭ‬
‫‪ 2SinxCosx‬ﺭﺍ ﺩﺭ ﺳﺘﻮﻥ ﺳﻮﻡ ﭼﺎﭖ ﻣﻲﻛﻨﺪ‪ .‬ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺑﺮﺍﻱ ﻫﺮ‬
‫ﻣﻘﺪﺍﺭ ﺁﺯﻣﺎﻳﺸﻲ ‪ ،x‬ﻣﻘﺪﺍﺭ ‪ Sin2x‬ﺑﺎ ﻣﻘﺪﺍﺭ ‪ 2SinxCosx‬ﺑﺮﺍﺑﺮ ﺍﺳﺖ‪ .‬ﺍﻟﺒﺘﻪ ﺍﻳﻦ ﻧﺘﺎﻳﺞ ﺑﻪ‬
‫ﻃﻮﺭ ﮐﻠﻲ ﺍﺛﺒﺎﺕ ﻧﻤﻲﮐﻨﺪ ﮐﻪ ﺭﺍﺑﻂۀ ﻣﺬﮐﻮﺭ ﺻﺤﻴﺢ ﺍﺳﺖ ﺍﻣﺎ ﺑﻪ ﻃﻮﺭ ﺗﺠﺮﺑﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‬
‫ﮐﻪ ﺍﻳﻦ ﺭﺍﺑﻄﻪ ﺩﺭﺳﺖ ﻣﻲﺑﺎﺷﺪ‪ .‬ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ‪ x‬ﺍﺯ ﻧﻮﻉ ‪ float‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺍﻳﻦ‬
‫ﺍﻣﺮ ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ﮐﺪ ‪ x += 0.2‬ﺑﻪ ﺩﺭﺳﺘﻲ ﮐﺎﺭ ﮐﻨﺪ ﻭ ﺧﻄﺎﻱ ﮔﺮﺩﮐﺮﺩﻥ ﺭﺥ ﻧﺪﻫﺪ‪.‬‬
‫ﺣﺎﺻﻞ ﺗﺎﺑﻊ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﺎﻧﻨﺪ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻌﻤﻮﻟﻲ ﺩﺭ ﻫﺮ ﻋﺒﺎﺭﺗﻲ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ‪.‬‬
‫ﻳﻌﻨﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻨﻮﻳﺴﻴﻢ‪:‬‬
‫;)‪y = sqrt(2‬‬
‫;)‪cout << 2*sin(x)*cos(x‬‬

‫ﻫﻤﭽﻨﻴﻦ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺗﻮﺍﺑﻊ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺗﻮﺩﺭﺗﻮ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻛﻨﻴﻢ‪:‬‬


‫)))‪y = sqrt(1 + 2*sqrt(3 + 4*sqrt(5‬‬

‫ﺑﻴﺸﺘﺮ ﺗﻮﺍﺑﻊ ﻣﻌﺮﻭﻑ ﺭﻳﺎﺿﻲ ﻛﻪ ﺩﺭ ﻣﺎﺷﻴﻦﺣﺴﺎﺏﻫﺎ ﻫﻢ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﺩﺭ ﺳﺮﻓﺎﻳﻞ‬


‫>‪ <cmath‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺑﻌﻀﻲ ﺍﺯ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺩﺭ ﺟﺪﻭﻝ ﺯﻳﺮ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ‪:‬‬
‫ﺑﻌﻀﻲ ﺍﺯ ﺗﻮﺍﺑﻊ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪<cmath‬‬
‫ﻣﺜﺎﻝ‬ ‫ﺷﺮﺡ‬ ‫ﺗﺎﺑﻊ‬
‫)‪ acos(0.2‬ﻣﻘﺪﺍﺭ ‪ 1.36944‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﮐﺴﻴﻨﻮﺱ ﻣﻌﮑﻮﺱ ‪) x‬ﺑﻪ ﺭﺍﺩﻳﺎﻥ(‬ ‫)‪acos(x‬‬
‫)‪ asin(0.2‬ﻣﻘﺪﺍﺭ ‪ 0.201358‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﺳﻴﻨﻮﺱ ﻣﻌﮑﻮﺱ ‪) x‬ﺑﻪ ﺭﺍﺩﻳﺎﻥ(‬ ‫)‪asin(x‬‬
‫)‪ atan(0.2‬ﻣﻘﺪﺍﺭ ‪ 0.197396‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﺗﺎﻧﮋﺍﻧﺖ ﻣﻌﮑﻮﺱ ‪) x‬ﺑﻪ ﺭﺍﺩﻳﺎﻥ(‬ ‫)‪atan(x‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪134‬‬

‫)‪ ceil(3.141593‬ﻣﻘﺪﺍﺭ ‪ 4.0‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﻣﻘﺪﺍﺭ ﺳﻘﻒ ‪) x‬ﮔﺮﺩ ﺷﺪﻩ(‬ ‫)‪ceil(x‬‬


‫)‪ cos(2‬ﻣﻘﺪﺍﺭ ‪ -0.416147‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﮐﺴﻴﻨﻮﺱ ‪) x‬ﺑﻪ ﺭﺍﺩﻳﺎﻥ(‬ ‫)‪cos(x‬‬
‫)‪ exp(2‬ﻣﻘﺪﺍﺭ ‪ 7.38906‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﺗﺎﺑﻊ ﻧﻤﺎﻳﻲ ‪) x‬ﺩﺭ ﭘﺎﻳﻪ ‪(e‬‬ ‫)‪exp(x‬‬
‫)‪ fabs(-2‬ﻣﻘﺪﺍﺭ ‪ 2.0‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﻗﺪﺭ ﻣﻄﻠﻖ ‪x‬‬ ‫)‪fabs(x‬‬
‫)‪ floor(3.141593‬ﻣﻘﺪﺍﺭ ‪ 3.0‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﻣﻘﺪﺍﺭ ﮐﻒ ‪) x‬ﮔﺮﺩ ﺷﺪﻩ(‬ ‫)‪floor(x‬‬
‫)‪ log(2‬ﻣﻘﺪﺍﺭ ‪ 0.693147‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﻟﮕﺎﺭﻳﺘﻢ ﻃﺒﻴﻌﻲ ‪) x‬ﺩﺭ ﭘﺎﻳﻪ ‪(e‬‬ ‫)‪log(x‬‬
‫)‪ log10(2‬ﻣﻘﺪﺍﺭ ‪ 0.30103‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﻟﮕﺎﺭﻳﺘﻢ ﻋﻤﻮﻣﻲ ‪) x‬ﺩﺭ ﭘﺎﻳﻪ ‪(10‬‬ ‫)‪log10(x‬‬
‫)‪ pow(2,3‬ﻣﻘﺪﺍﺭ ‪ 8.0‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫‪ x‬ﺑﻪ ﺗﻮﺍﻥ ‪p‬‬ ‫)‪pow(x,p‬‬
‫)‪ sin(2‬ﻣﻘﺪﺍﺭ ‪ 0.909297‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﺳﻴﻨﻮﺱ ‪) x‬ﺑﻪ ﺭﺍﺩﻳﺎﻥ(‬ ‫)‪sin(x‬‬
‫)‪ sqrt(2‬ﻣﻘﺪﺍﺭ ‪ 1.41421‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﺟﺬﺭ ‪x‬‬ ‫)‪sqrt(x‬‬
‫)‪ tan(2‬ﻣﻘﺪﺍﺭ ‪ -2.18504‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬ ‫ﺗﺎﻧﮋﺍﻧﺖ ‪) x‬ﺑﻪ ﺭﺍﺩﻳﺎﻥ(‬ ‫)‪tan(x‬‬

‫ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﻫﺮ ﺗﺎﺑﻊ ﺭﻳﺎﺿﻲ ﻳﮏ ﻣﻘﺪﺍﺭ ﺍﺯ ﻧﻮﻉ ‪ double‬ﺭﺍ‬


‫ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﮔﺮ ﻳﻚ ﻧﻮﻉ ﺻﺤﻴﺢ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﺷﻮﺩ‪ ،‬ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﻛﻪ ﺗﺎﺑﻊ ﺁﻥ ﺭﺍ‬
‫ﭘﺮﺩﺍﺯﺵ ﮐﻨﺪ‪ ،‬ﻣﻘﺪﺍﺭﺵ ﺭﺍ ﺑﻪ ﻧﻮﻉ ‪ double‬ﺍﺭﺗﻘﺎ ﻣﻲﺩﻫﺪ‪.‬‬
‫ﺑﻌﻀﻲ ﺍﺯ ﺳﺮﻓﺎﻳﻞﻫﺎﻱ ﻛﺘﺎﺑﺨﺎﻥۀ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﮐﻪ ﮐﺎﺭﺑﺮﺩ ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﻧﺪ ﺩﺭ‬
‫ﺟﺪﻭﻝ ﺯﻳﺮ ﺁﻣﺪﻩ ﺍﺳﺖ‪:‬‬
‫ﺑﻌﻀﻲ ﺍﺯ ﺳﺮﻓﺎﻳﻞﻫﺎﻱ ﻛﺘﺎﺑﺨﺎﻥۀ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬

‫ﺷﺮﺡ‬ ‫ﺳﺮﻓﺎﻳﻞ‬
‫ﺗﺎﺑﻊ >‪ <assert‬ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‬ ‫>‪<assert‬‬
‫ﺗﻮﺍﺑﻌﻲ ﺭﺍ ﺑﺮﺍﻱ ﺑﺮﺭﺳﻲ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‬ ‫>‪<ctype‬‬
‫ﺛﺎﺑﺖﻫﺎﻱ ﻣﺮﺑﻮﻁ ﺑﻪ ﺍﻋﺪﺍﺩ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‬ ‫>‪<cfloat‬‬
‫ﻣﺤﺪﻭﺩۀ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺭﺍ ﺭﻭﻱ ﺳﻴﺴﺘﻢ ﻣﻮﺟﻮﺩ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‬ ‫>‪<climits‬‬
‫ﺗﻮﺍﺑﻊ ﺭﻳﺎﺿﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‬ ‫>‪<cmath‬‬
‫ﺗﻮﺍﺑﻌﻲ ﺭﺍ ﺑﺮﺍﻱ ﻭﺭﻭﺩﻱ ﻭ ﺧﺮﻭﺟﻲ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‬ ‫>‪<cstdio‬‬
‫ﺗﻮﺍﺑﻊ ﮐﺎﺭﺑﺮﺩﻱ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‬ ‫>‪<cstdlib‬‬
‫ﺗﻮﺍﺑﻌﻲ ﺭﺍ ﺑﺮﺍﻱ ﭘﺮﺩﺍﺯﺵ ﺭﺷﺘﻪﻫﺎ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‬ ‫>‪<cstring‬‬
‫ﺗﻮﺍﺑﻊ ﺗﺎﺭﻳﺦ ﻭ ﺳﺎﻋﺖ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‬ ‫>‪<ctime‬‬

‫ﺍﻳﻦ ﺳﺮﻓﺎﻳﻞﻫﺎ ﺍﺯ ﻛﺘﺎﺑﺨﺎﻥۀ ‪ C‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﮔﺮﻓﺘﻪ ﺷﺪﻩﺍﻧﺪ‪ .‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥﻫﺎ ﺷﺒﻴﻪ‬


‫ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺳﺮﻓﺎﻳﻞﻫﺎﻱ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ )ﻣﺎﻧﻨﺪ >‪ ( <iostream‬ﺍﺳﺖ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ‬
‫‪135‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫ﺑﺨﻮﺍﻫﻴﻢ ﺗﺎﺑﻊ ﺍﻋﺪﺍﺩ ﺗﺼﺎﺩﻓﻲ )(‪ rand‬ﺭﺍ ﺍﺯ ﺳﺮﻓﺎﻳﻞ >‪ <cstdlib‬ﺑﻪ ﻛﺎﺭ ﺑﺒﺮﻳﻢ‪ ،‬ﺑﺎﻳﺪ‬
‫ﺩﺳﺘﻮﺭ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪۀ ﺯﻳﺮ ﺭﺍ ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﻓﺎﻳﻞ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ‪:‬‬
‫>‪#include <cstdlib‬‬

‫‪ 5‐3‬ﺗﻮﺍﺑﻊ ﺳﺎﺧﺖ ﻛﺎﺭﺑﺮ‬


‫ﮔﺮﭼﻪ ﺗﻮﺍﺑﻊ ﺑﺴﻴﺎﺭ ﻣﺘﻨﻮﻋﻲ ﺩﺭ ﮐﺘﺎﺑﺨﺎﻥۀ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﻭﻟﻲ ﺍﻳﻦ ﺗﻮﺍﺑﻊ‬
‫ﺑﺮﺍﻱ ﺑﻴﺸﺘﺮ ﻭﻇﺎﻳﻒ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﻛﺎﻓﻲ ﻧﻴﺴﺘﻨﺪ‪ .‬ﻋﻼﻭﻩ ﺑﺮ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺩﻭﺳﺖ ﺩﺍﺭﻧﺪ‬
‫ﺧﻮﺩﺷﺎﻥ ﺑﺘﻮﺍﻧﻨﺪ ﺗﻮﺍﺑﻌﻲ ﺭﺍ ﺑﺴﺎﺯﻧﺪ ﻭ ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﺎﻳﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐3‬ﺗﺎﺑﻊ )(‪cube‬‬


‫ﻳﻚ ﻣﺜﺎﻝ ﺳﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﺳﺎﺧﺖ ﻛﺎﺭﺑﺮ‪:‬‬
‫)‪int cube(int x‬‬
‫‪{ // returns cube of x:‬‬
‫;‪return x*x*x‬‬
‫}‬

‫ﺍﻳﻦ ﺗﺎﺑﻊ‪ ،‬ﻣﻜﻌﺐ ﻳﻚ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺭﺳﺎﻟﻲ ﺑﻪ ﺁﻥ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﻓﺮﺍﺧﻮﺍﻧﻲ‬


‫)‪ cube(2‬ﻣﻘﺪﺍﺭ ‪ 8‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬
‫ﻳﻚ ﺗﺎﺑﻊ ﺳﺎﺧﺖ ﻛﺎﺭﺑﺮ ﺩﻭ ﻗﺴﻤﺖ ﺩﺍﺭﺩ‪ :‬ﻋﻨﻮﺍﻥ ﻭ ﺑﺪﻧﻪ‪ .‬ﻋﻨﻮﺍﻥ ﻳﻚ ﺗﺎﺑﻊ ﺑﻪ ﺻﻮﺭﺕ‬
‫ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ‬ ‫)ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ( ﻧﺎﻡ‬

‫ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ )(‪ 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‬‬

‫ﺑﻪ ﺟﺎﻱ ‪ expression‬ﻫﺮ ﻋﺒﺎﺭﺗﻲ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﮐﻪ ﺑﺘﻮﺍﻥ ﻣﻘﺪﺍﺭ ﺁﻥ ﺭﺍ ﺑﻪ ﻳﮏ ﻣﺘﻐﻴﺮ‬


‫ﺗﺨﺼﻴﺺ ﺩﺍﺩ‪ .‬ﻧﻮﻉ ﺁﻥ ﻋﺒﺎﺭﺕ ﺑﺎﻳﺪ ﺑﺎ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ ﻳﮑﻲ ﺑﺎﺷﺪ‪.‬‬
‫ﻋﺒﺎﺭﺕ )(‪ int main‬ﮐﻪ ﺩﺭ ﻫﻢۀ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ ﻳﮏ ﺗﺎﺑﻊ ﺑﻪ ﻧﺎﻡ‬
‫»ﺗﺎﺑﻊ ﺍﺻﻠﻲ« ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‪ .‬ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﺯ ﻧﻮﻉ ‪ int‬ﺍﺳﺖ‪ .‬ﻧﺎﻡ ﺁﻥ ‪main‬‬
‫ﺍﺳﺖ ﻭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺁﻥ ﺧﺎﻟﻲ ﺍﺳﺖ؛ ﻳﻌﻨﻲ ﻫﻴﭻ ﭘﺎﺭﺍﻣﺘﺮﻱ ﻧﺪﺍﺭﺩ‪.‬‬

‫‪ 5‐4‬ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ‬
‫ﻭﻗﺘﻲ ﻳﮏ ﺗﺎﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺍﻳﺠﺎﺩ ﮐﺮﺩﻳﺪ‪ ،‬ﻓﻮﺭﺍ ﺑﺎﻳﺪ ﺁﻥ ﺗﺎﺑﻊ ﺭﺍ ﺑﺎ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﺳﺎﺩﻩ‬
‫ﺍﻣﺘﺤﺎﻥ ﮐﻨﻴﺪ‪ .‬ﭼﻨﻴﻦ ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ‪ 1‬ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺗﻨﻬﺎ ﻫﺪﻑ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺍﻣﺘﺤﺎﻥ‬
‫ﮐﺮﺩﻥ ﺗﺎﺑﻊ ﻭ ﺑﺮﺭﺳﻲ ﺻﺤﺖ ﮐﺎﺭ ﺁﻥ ﺍﺳﺖ‪ .‬ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﻣﻮﻗﺘﻲ ﺍﺳﺖ ﮐﻪ ﺑﺎﻳﺪ‬
‫»ﺳﺮﻳﻊ ﻭ ﮐﺜﻴﻒ« ﺑﺎﺷﺪ؛ ﻳﻌﻨﻲ ﻻﺯﻡ ﻧﻴﺴﺖ ﺩﺭ ﺁﻥ ﺗﻤﺎﻡ ﻇﺮﺍﻓﺖﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ – ﻣﺜﻞ‬
‫ﭘﻴﻐﺎﻡﻫﺎﻱ ﺧﺮﻭﺟﻲ‪ ،‬ﺑﺮﭼﺴﺐﻫﺎ ﻭ ﺭﺍﻫﻨﻤﺎﻫﺎﻱ ﺧﻮﺍﻧﺎ – ﺭﺍ ﻟﺤﺎﻅ ﮐﻨﻴﺪ‪ .‬ﻭﻗﺘﻲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬
‫ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ‪ ،‬ﺗﺎﺑﻊ ﺭﺍ ﺁﺯﻣﺎﻳﺶ ﮐﺮﺩﻳﺪ ﺩﻳﮕﺮ ﺑﻪ ﺁﻥ ﺍﺣﺘﻴﺎﺟﻲ ﻧﻴﺴﺖ ﻭ ﻣﻲﺗﻮﺍﻧﻴﺪ ﺑﺮﻧﺎﻡۀ‬
‫ﺁﺯﻣﻮﻥ ﺭﺍ ﺩﻭﺭ ﺑﺮﻳﺰﻳﺪ‪.‬‬

‫‪1 – Testing program‬‬


‫‪137‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫* ﻣﺜﺎﻝ ‪ 5‐4‬ﻳﻚ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺑﺮﺍﻱ ﺗﺎﺑﻊ )(‪cube‬‬


‫ﮐﺪ ﺯﻳﺮ ﺷﺎﻣﻞ ﺗﺎﺑﻊ )(‪ cube‬ﻭ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺁﻥ ﺍﺳﺖ‪:‬‬
‫)‪int cube(int x‬‬
‫‪{ // returns cube of x:‬‬
‫;‪return x*x*x‬‬
‫}‬

‫)(‪int main‬‬
‫‪{ // tests the cube() function:‬‬
‫;‪int n=1‬‬
‫)‪while (n != 0‬‬
‫;‪{ cin >> n‬‬
‫;‪cout << "\tcube(" << n << ") = " << cube(n) << endl‬‬
‫}‬
‫}‬
‫‪5‬‬
‫‪cube(5) = 125‬‬
‫‪-6‬‬
‫‪cube(-6) = -216‬‬
‫‪0‬‬
‫‪cube(0) = 0‬‬

‫ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ ﻣﻲﮔﻴﺮﺩ ﻭ ﻣﻜﻌﺐ ﺁﻥﻫﺎ ﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ ﺗﺎ ﺍﻳﻦ ﻛﻪ‬
‫ﻛﺎﺭﺑﺮ ﻣﻘﺪﺍﺭ ‪ 0‬ﺭﺍ ﻭﺍﺭﺩ ﻛﻨﺪ‪ .‬ﻫﺮ ﻋﺪﺩ ﺻﺤﻴﺤﻲ ﮐﻪ ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ‪ ،‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﮐﺪ‬
‫)‪ cube(n‬ﺑﻪ ﺗﺎﺑﻊ )(‪ cube‬ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ ﺍﺯ ﺗﺎﺑﻊ‪ ،‬ﺟﺎﻳﮕﺰﻳﻦ‬
‫ﻋﺒﺎﺭﺕ )‪ cube(n‬ﮔﺸﺘﻪ ﻭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ‪ cout‬ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‪.‬‬

‫)(‪main‬‬ ‫)(‪cube‬‬ ‫ﻣﻲﺗﻮﺍﻥ ﺭﺍﺑﻂۀ ﺑﻴﻦ ﺗﺎﺑﻊ‬


‫‪n‬‬ ‫‪5‬‬
‫‪5‬‬
‫‪x‬‬ ‫‪5‬‬ ‫)(‪ main‬ﻭ ﺗﺎﺑﻊ )(‪ cube‬ﺭﺍ‬
‫‪int‬‬ ‫‪int‬‬
‫‪125‬‬ ‫ﺷﺒﻴﻪ ﺍﻳﻦ ﺷﮑﻞ ﺗﺼﻮﺭ ﻧﻤﻮﺩ‪:‬‬
‫ﺗﺎﺑﻊ )(‪ main‬ﻣﻘﺪﺍﺭ ‪ 5‬ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ‬
‫)(‪ cube‬ﻣﻲﻓﺮﺳﺘﺪ ﻭ ﺗﺎﺑﻊ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪138‬‬

‫)(‪ cube‬ﻣﻘﺪﺍﺭ ‪ 125‬ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ )(‪ main‬ﺑﺎﺯﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺁﺭﮔﻮﻣﺎﻥ ‪ n‬ﺑﻪ ﻭﺳﻴﻞۀ ﻣﻘﺪﺍﺭ‬
‫ﺑﻪ ﭘﺎﺭﺍﻣﺘﺮ ﺻﻮﺭﻱ ‪ x‬ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺑﻪ ﺑﻴﺎﻥ ﺳﺎﺩﻩﺗﺮ ﻭﻗﺘﻲ ﺗﺎﺑﻊ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ‪x ،‬‬
‫ﻣﻘﺪﺍﺭ ‪ n‬ﺭﺍ ﻣﻲﮔﻴﺮﺩ‪.‬‬
‫ﺩﻗﺖ ﻛﻨﻴﺪ ﻛﻪ ﺗﺎﺑﻊ )(‪ cube‬ﺩﺭ ﺑﺎﻻﻱ ﺗﺎﺑﻊ )(‪ main‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺯﻳﺮﺍ ﻗﺒﻞ ﺍﺯ‬
‫ﺍﻳﻦ ﻛﻪ ﺗﺎﺑﻊ)(‪ cube‬ﺩﺭ ﺗﺎﺑﻊ )(‪ main‬ﺑﻪ ﻛﺎﺭ ﺭﻭﺩ‪ ،‬ﻛﺎﻣﭙﺎﻳﻠﺮ ‪ C++‬ﺑﺎﻳﺪ ﺩﺭ ﺑﺎﺭۀ ﺁﻥ‬
‫ﺍﻃﻼﻉ ﺣﺎﺻﻞ ﻛﻨﺪ‪.‬‬
‫ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻳﻚ ﺗﺎﺑﻊ ﺳﺎﺧﺖ ﻛﺎﺭﺑﺮ ﺑﻪ ﻧﺎﻡ )(‪ max‬ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﺯ‬
‫ﺩﻭ ﻋﺪﺩ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺑﻪ ﺁﻥ‪ ،‬ﻋﺪﺩ ﺑﺰﺭﮒﺗﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺍﺭﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐5‬ﻳﻚ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺑﺮﺍﻱ ﺗﺎﺑﻊ )(‪max‬‬


‫ﺗﺎﺑﻊ ﺯﻳﺮ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺍﺭﺩ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﺯ ﺩﻭ ﻣﻘﺪﺍﺭ ﻓﺮﺳﺘﺎﺩﻩ ﺷﺪﻩ ﺑﻪ ﺁﻥ‪ ،‬ﻣﻘﺪﺍﺭ ﺑﺰﺭﮒﺗﺮ‬
‫ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪:‬‬
‫)‪int max(int x, int y‬‬
‫‪{ // returns larger of the two given integers:‬‬
‫;‪int z‬‬
‫; ‪z = (x > y) ? x : y‬‬
‫;‪return z‬‬
‫}‬

‫)(‪int main‬‬
‫{‬ ‫‪// 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‬ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺗﺎﺑﻊ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪،‬‬
‫ﻣﻲﺗﻮﺍﻥ ﺁﻥ ﺭﺍ ﺩﺭ ﻫﺮ ﻧﻘﻂۀ ﺩﻳﮕﺮﻱ ﺍﺯ ﺗﺎﺑﻊ ﻗﺮﺍﺭ ﺩﺍﺩ‪.‬‬

‫‪ 5‐5‬ﺍﻋﻼﻥﻫﺎ ﻭ ﺗﻌﺎﺭﻳﻒ ﺗﺎﺑﻊ‬


‫ﺩﺭ ﺩﻭ ﻣﺜﺎﻝ ﺁﺧﺮ‪ ،‬ﺗﻌﺮﻳﻒ ﮐﺎﻣﻞ ﺗﺎﺑﻊ ﺩﺭ ﺍﺑﺘﺪﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺁﻣﺪ ﻭ ﺯﻳﺮ ﺁﻥ ﻣﺘﻦ ﺑﺮﻧﺎﻡۀ‬
‫ﺍﺻﻠﻲ ﻗﺮﺍﺭ ﮔﺮﻓﺖ‪ .‬ﺍﻳﻦ ﻳﮏ ﺭﻭﺵ ﺗﻌﺮﻳﻒ ﺗﻮﺍﺑﻊ ﺍﺳﺖ ﮐﻪ ﺍﻏﻠﺐ ﺑﺮﺍﻱ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺁﺯﻣﻮﻥ‬
‫ﺍﺯ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺭﺍﻩ ﺩﻳﮕﺮﻱ ﮐﻪ ﺑﻴﺸﺘﺮ ﺭﻭﺍﺝ ﺩﺍﺭﺩ ﺍﻳﻦ ﮔﻮﻧﻪ ﺍﺳﺖ ﮐﻪ ﺍﺑﺘﺪﺍ ﺗﺎﺑﻊ‬
‫ﺍﻋﻼﻥ‪ 1‬ﺷﻮﺩ‪ ،‬ﺳﭙﺲ ﻣﺘﻦ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﻴﺎﻳﺪ‪ ،‬ﭘﺲ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺗﻌﺮﻳﻒ‪ 2‬ﮐﺎﻣﻞ ﺗﺎﺑﻊ ﻗﺮﺍﺭ‬
‫ﺑﮕﻴﺮﺩ‪ .‬ﺍﻳﻦ ﺭﻭﺵ ﺩﺭ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬
‫ﺍﻋﻼﻥ ﺗﺎﺑﻊ ﺑﺎ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﺗﻔﺎﻭﺕ ﺩﺍﺭﺩ‪ .‬ﺍﻋﻼﻥ ﺗﺎﺑﻊ‪ ،‬ﻓﻘﻂ ﻋﻨﻮﺍﻥ ﺗﺎﺑﻊ ﺍﺳﺖ ﮐﻪ ﻳﮏ‬
‫ﺳﻤﻴﮑﻮﻟﻦ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺁﻥ ﻗﺮﺍﺭ ﺩﺍﺭﺩ ﻭﻟﻲ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ‪ ،‬ﻣﺘﻦ ﮐﺎﻣﻞ ﺗﺎﺑﻊ ﺍﺳﺖ ﮐﻪ ﻫﻢ ﺷﺎﻣﻞ‬
‫ﻋﻨﻮﺍﻥ ﺍﺳﺖ ﻭ ﻫﻢ ﺷﺎﻣﻞ ﺑﺪﻧﻪ‪ .‬ﺍﻋﻼﻥ ﺗﺎﺑﻊ ﺷﺒﻴﻪ ﺍﻋﻼﻥ ﻣﺘﻐﻴﺮﻫﺎﺳﺖ‪ .‬ﻳﮏ ﻣﺘﻐﻴﺮ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ‬

‫‪1 – Declaration‬‬ ‫‪2 - Definition‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪140‬‬

‫ﮐﻪ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﺷﻮﺩ ﺑﺎﻳﺪ ﺍﻋﻼﻥ ﺷﻮﺩ‪ .‬ﺗﺎﺑﻊ ﻫﻢ ﻫﻤﻴﻦ ﻃﻮﺭ ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﻓﺮﻕ ﮐﻪ ﻣﺘﻐﻴﺮ ﺭﺍ‬
‫ﺩﺭ ﻫﺮ ﺟﺎﻳﻲ ﺍﺯ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺗﻮﺍﻥ ﺍﻋﻼﻥ ﮐﺮﺩ ﺍﻣﺎ ﺗﺎﺑﻊ ﺭﺍ ﺑﺎﻳﺪ ﻗﺒﻞ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﻋﻼﻥ ﻧﻤﻮﺩ‪.‬‬
‫ﺩﺭ ﺍﻋﻼﻥ ﺗﺎﺑﻊ ﻓﻘﻂ ﺑﻴﺎﻥ ﻣﻲﺷﻮﺩ ﮐﻪ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ ﭼﻴﺴﺖ‪ ،‬ﻧﺎﻡ ﺗﺎﺑﻊ ﭼﻴﺴﺖ ﻭ ﻧﻮﻉ‬
‫ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﭼﻴﺴﺖ‪ .‬ﻫﻤﻴﻦﻫﺎ ﺑﺮﺍﻱ ﮐﺎﻣﭙﺎﻳﻠﺮ ﮐﺎﻓﻲ ﺍﺳﺖ ﺗﺎ ﺑﺘﻮﺍﻧﺪ ﮐﺎﻣﭙﺎﻳﻞ ﺑﺮﻧﺎﻣﻪ ﺭﺍ‬
‫ﺁﻏﺎﺯ ﮐﻨﺪ‪ .‬ﺑﻌﺪﺍ ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺑﻪ ﺗﻌﺮﻳﻒ ﺑﺪﻥۀ ﺗﺎﺑﻊ ﻧﻴﺰ ﺍﺣﺘﻴﺎﺝ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻳﻦ ﺑﺪﻧﻪ ﺩﺭ‬
‫ﺍﻧﺘﻬﺎﻱ ﺑﺮﻧﺎﻣﻪ ﻭ ﭘﺲ ﺍﺯ ﺗﺎﺑﻊ )(‪ 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‬ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ(‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐6‬ﺗﺎﺑﻊ)(‪ max‬ﺑﺎ ﺍﻋﻼﻥ ﺟﺪﺍ ﺍﺯ ﺗﻌﺮﻳﻒ ﺁﻥ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺗﺎﺑﻊ )(‪ max‬ﺩﺭ ﻣﺜﺎﻝ ‪ 5‐5‬ﺍﺳﺖ‪ .‬ﺍﻣﺎ ﺍﻳﻦﺟﺎ ﺍﻋﻼﻥ‬
‫ﺗﺎﺑﻊ ﺑﺎﻻﻱ ﺗﺎﺑﻊ ﺍﺻﻠﻲ ﻇﺎﻫﺮ ﺷﺪﻩ ﻭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﺑﻌﺪ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺁﻣﺪﻩ ﺍﺳﺖ‪:‬‬
‫;)‪int max(int,int‬‬
‫‪// returns larger of the two given integers:‬‬

‫)(‪int main‬‬

‫‪1 – Argument‬‬ ‫‪2 - Parameter‬‬


‫‪141‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫{‬ ‫‪// tests the max() function:‬‬


‫;‪int m, n‬‬
‫‪do‬‬
‫;‪{ cin >> m >> n‬‬
‫" = )" << ‪cout << "\tmax(" << m << "," << n‬‬
‫;‪<< max(m,n) << endl‬‬
‫}‬
‫;)‪while (m != 0‬‬
‫}‬

‫)‪int max(int x, int y‬‬


‫;‪{ if (x < y) return y‬‬
‫;‪else return x‬‬
‫}‬

‫ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ‪ x‬ﻭ ‪ y‬ﺩﺭ ﺑﺨﺶ ﻋﻨﻮﺍﻥ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﺁﻣﺪﻩﺍﻧﺪ )ﻃﺒﻖ ﻣﻌﻤﻮﻝ(‬
‫ﻭﻟﻲ ﺩﺭ ﺍﻋﻼﻥ ﺗﺎﺑﻊ ﻭﺟﻮﺩ ﻧﺪﺍﺭﻧﺪ‪.‬‬

‫‪ 5‐6‬ﻛﺎﻣﭙﺎﻳﻞ ﺟﺪﺍﮔﺎﻥۀ ﺗﻮﺍﺑﻊ‬


‫ﺍﻏﻠﺐ ﺍﻳﻦ ﻃﻮﺭ ﺍﺳﺖ ﮐﻪ ﺗﻌﺮﻳﻒ ﻭ ﺑﺪﻥۀ ﺗﻮﺍﺑﻊ ﺩﺭ ﻓﺎﻳﻞﻫﺎﻱ ﺟﺪﺍﮔﺎﻧﻪﺍﻱ ﻗﺮﺍﺭ‬
‫ﻣﻲﮔﻴﺮﺩ‪ .‬ﺍﻳﻦ ﻓﺎﻳﻞﻫﺎ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻞ ﮐﺎﻣﭙﺎﻳﻞ‪ 1‬ﻣﻲﺷﻮﻧﺪ ﻭ ﺳﭙﺲ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﮐﻪ ﺁﻥ‬
‫ﺗﻮﺍﺑﻊ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﺩ ﺍﻟﺼﺎﻕ‪ 2‬ﻣﻲﺷﻮﻧﺪ‪ .‬ﺗﻮﺍﺑﻊ ﮐﺘﺎﺑﺨﺎﻥۀ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺑﻪ ﻫﻤﻴﻦ ﺷﮑﻞ‬
‫ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﺷﺪﻩﺍﻧﺪ ﻭ ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﻳﮑﻲ ﺍﺯ ﺁﻥ ﺗﻮﺍﺑﻊ ﺭﺍ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺘﺎﻥ ﺑﻪ ﮐﺎﺭ ﻣﻲﺑﺮﻳﺪ ﺑﺎﻳﺪ‬
‫ﺑﺎ ﺩﺳﺘﻮﺭ ﺭﺍﻫﻨﻤﺎﻱ ﭘﻴﺶﭘﺮﺩﺍﺯﻧﺪﻩ‪ ،‬ﻓﺎﻳﻞ ﺁﻥ ﺗﻮﺍﺑﻊ ﺭﺍ ﺑﻪ ﺑﺮﻧﺎﻣﻪﺗﺎﻥ ﺿﻤﻴﻤﻪ ﮐﻨﻴﺪ‪ .‬ﺍﻳﻦ ﮐﺎﺭ‬
‫ﭼﻨﺪ ﻣﺰﻳﺖ ﺩﺍﺭﺩ‪ .‬ﺍﻭﻟﻴﻦ ﻣﺰﻳﺖ »ﻣﺨﻔﻲﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ« ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﺍﻳﻦ ﮐﻪ ﺗﻮﺍﺑﻊ ﻻﺯﻡ ﺭﺍ‬
‫ﺩﺭ ﻓﺎﻳﻞ ﺟﺪﺍﮔﺎﻧﻪﺍﻱ ﺗﻌﺮﻳﻒ ﻭ ﮐﺎﻣﭙﺎﻳﻞ ﮐﻨﻴﺪ ﻭ ﺳﭙﺲ ﺁﻥ ﻓﺎﻳﻞ ﺭﺍ ﺑﻪ ﻫﻤﺮﺍﻩ ﻣﺸﺨﺼﺎﺕ‬
‫ﺗﻮﺍﺑﻊ ﺑﻪ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺩﻳﮕﺮﻱ ﺑﺪﻫﻴﺪ ﺗﺎ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺭﺍ ﺗﮑﻤﻴﻞ ﮐﻨﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺁﻥ‬
‫ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺍﺯ ﺟﺰﻳﻴﺎﺕ ﺗﻮﺍﺑﻊ ﻭ ﻧﺤﻮۀ ﺍﺟﺮﺍﻱ ﺩﺍﺧﻠﻲ ﺁﻥﻫﺎ ﭼﻴﺰﻱ ﻧﻤﻲﺩﺍﻧﺪ )ﻧﺒﺎﻳﺪ ﻫﻢ‬
‫ﺑﺪﺍﻧﺪ( ﻭ ﻓﻘﻂ ﻣﻲﺩﺍﻧﺪ ﮐﻪ ﭼﻄﻮﺭ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺯ ﺁﻥﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﺪ‪ .‬ﺩﺭ ﻧﺘﻴﺠﻪ ﺍﻃﻼﻋﺎﺗﻲ ﮐﻪ‬
‫ﺩﺍﻧﺴﺘﻦ ﺁﻥﻫﺎ ﺑﺮﺍﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺿﺮﻭﺭﻱ ﻧﻴﺴﺖ ﺍﺯ ﺩﻳﺪ ﺍﻭ ﻣﺨﻔﻲ ﻣﻲﻣﺎﻧﺪ‪ .‬ﺗﺠﺮﺑﻪ ﻧﺸﺎﻥ‬

‫‪1 – Compiling‬‬ ‫‪2 - Linking‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪142‬‬

‫ﺩﺍﺩﻩ ﮐﻪ ﭘﻨﻬﺎﻥﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ‪ ،‬ﻓﻬﻤﻴﺪﻥ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺭﺍ ﺁﺳﺎﻥ ﻣﻲﮐﻨﺪ ﻭ ﭘﺮﻭﮊﻩﻫﺎﻱ ﺑﺰﺭﮒ‬
‫ﺑﺎ ﻣﻮﻓﻘﻴﺖ ﺍﺟﺮﺍ ﻣﻲﺷﻮﻧﺪ‪.‬‬
‫ﻣﺰﻳﺖ ﺩﻳﮕﺮ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺗﻮﺍﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ‬
‫ﻧﻮﺷﺘﻪ ﺷﻮﺩ‪ ،‬ﺟﺪﺍﮔﺎﻧﻪ ﺁﺯﻣﺎﻳﺶ ﻧﻤﻮﺩ‪ .‬ﻭﻗﺘﻲ ﻳﻘﻴﻦ ﮐﺮﺩﻳﺪ ﮐﻪ ﻳﮏ ﺗﺎﺑﻊ ﻣﻔﺮﻭﺽ ﺑﻪ ﺩﺭﺳﺘﻲ‬
‫ﮐﺎﺭ ﻣﻲﮐﻨﺪ‪ ،‬ﺁﻥ ﺭﺍ ﺩﺭ ﻳﮏ ﻓﺎﻳﻞ ﺫﺧﻴﺮﻩ ﮐﻨﻴﺪ ﻭ ﺟﺰﻳﻴﺎﺕ ﺁﻥ ﺗﺎﺑﻊ ﺭﺍ ﻓﺮﺍﻣﻮﺵ ﮐﻨﻴﺪ ﻭ ﻫﺮ‬
‫ﻭﻗﺖ ﮐﻪ ﺑﻪ ﺁﻥ ﺗﺎﺑﻊ ﻧﻴﺎﺯ ﺩﺍﺷﺘﻴﺪ ﺑﺎ ﺧﻴﺎﻟﻲ ﺭﺍﺣﺖ ﺍﺯ ﺁﻥ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﺘﺎﻥ ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﺎﻳﻴﺪ‪.‬‬
‫ﻧﺘﻴﺠﻪ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺗﻮﻟﻴﺪ ﺗﻮﺍﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﻭ ﺗﻮﻟﻴﺪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ‪ ،‬ﻫﻢﺯﻣﺎﻥ ﻭ ﻣﺴﺘﻘﻞ ﺍﺯ ﻫﻢ‬
‫ﭘﻴﺶ ﻣﻲﺭﻭﺩ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﻳﮑﻲ ﻣﻨﺘﻈﺮ ﺩﻳﮕﺮﻱ ﺑﻤﺎﻧﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﺩﻳﺪﮔﺎﻩ »ﺑﺴﺘﻪﺑﻨﺪﻱ ﻧﺮﻡﺍﻓﺰﺍﺭ«‬
‫ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬
‫ﺳﻮﻣﻴﻦ ﻣﺰﻳﺖ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﻫﺮ ﺯﻣﺎﻧﻲ ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻥ ﺗﻌﺮﻳﻒ ﺗﻮﺍﺑﻊ ﺭﺍ‬
‫ﻋﻮﺽ ﮐﺮﺩ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﻻﺯﻡ ﺑﺎﺷﺪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺗﻐﻴﻴﺮ ﻳﺎﺑﺪ‪ .‬ﻓﺮﺽ ﮐﻨﻴﺪ ﺗﺎﺑﻌﻲ ﺑﺮﺍﻱ‬
‫ﻣﺮﺗﺐ ﮐﺮﺩﻥ ﻓﻬﺮﺳﺘﻲ ﺍﺯ ﺍﻋﺪﺍﺩ ﺍﻳﺠﺎﺩ ﮐﺮﺩﻩﺍﻳﺪ ﻭ ﺁﻥ ﺭﺍ ﺟﺪﺍﮔﺎﻧﻪ ﮐﺎﻣﭙﺎﻳﻞ ﻭ ﺫﺧﻴﺮﻩ ﻧﻤﻮﺩﻩﺍﻳﺪ‬
‫ﻭ ﺩﺭ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﮐﺎﺭﺑﺮﺩﻱ ﻫﻢ ﺍﺯ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺑﺮﺩﻩﺍﻳﺪ‪ .‬ﺣﺎﻻ ﻫﺮﮔﺎﻩ ﮐﻪ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺳﺮﻳﻊﺗﺮﻱ‬
‫ﺑﺮﺍﻱ ﻣﺮﺗﺐﺳﺎﺯﻱ ﻳﺎﻓﺘﻴﺪ‪ ،‬ﻓﻘﻂ ﮐﺎﻓﻲ ﺍﺳﺖ ﻓﺎﻳﻞ ﺗﺎﺑﻊ ﺭﺍ ﺍﺻﻼﺡ ﻭ ﮐﺎﻣﭙﺎﻳﻞ ﮐﻨﻴﺪ ﻭ ﺩﻳﮕﺮ‬
‫ﻧﻴﺎﺯﻱ ﻧﻴﺴﺖ ﮐﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﻧﻤﺎﻳﻴﺪ‪.‬‬
‫ﭼﻬﺎﺭﻣﻴﻦ ﻣﺰﻳﺖ ﻫﻢ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻣﻲﺗﻮﺍﻧﻴﺪ ﻳﮏ ﺑﺎﺭ ﻳﮏ ﺗﺎﺑﻊ ﺭﺍ ﮐﺎﻣﭙﺎﻳﻞ ﻭ ﺫﺧﻴﺮﻩ‬
‫ﮐﻨﻴﺪ ﻭ ﺍﺯ ﺁﻥ ﭘﺲ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﻣﺨﺘﻠﻔﻲ ﺍﺯ ﻫﻤﺎﻥ ﺗﺎﺑﻊ ﺍﺳﺘﻔﺎﺩﻩ ﺑﺒﺮﻳﺪ‪ .‬ﻭﻗﺘﻲ ﺷﺮﻭﻉ ﺑﻪ‬
‫ﻧﻮﺷﺘﻦ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﺟﺪﻳﺪ ﻣﻲﮐﻨﻴﺪ‪ ،‬ﺷﺎﻳﺪ ﺑﺮﺧﻲ ﺍﺯ ﺗﻮﺍﺑﻊ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺍﺯ ﻗﺒﻞ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ‪.‬‬
‫ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﻳﮕﺮ ﻻﺯﻡ ﻧﻴﺴﺖ ﮐﻪ ﺁﻥ ﺗﻮﺍﺑﻊ ﺭﺍ ﺩﻭﺑﺎﺭﻩ ﻧﻮﺷﺘﻪ ﻭ ﮐﺎﻣﭙﺎﻳﻞ ﮐﻨﻴﺪ‪ .‬ﺍﻳﻦ ﮐﺎﺭ ﺳﺮﻋﺖ‬
‫ﺗﻮﻟﻴﺪ ﻧﺮﻡ ﺍﻓﺰﺍﺭ ﺭﺍ ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ‪.‬‬
‫ﺗﺎﺑﻊ )(‪ 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++‬ﻣﺮﺍﺟﻌﻪ ﮐﻨﻴﺪ‪.‬‬

‫‪ 5‐6‬ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ‪ ،‬ﺗﻮﺍﺑﻊ ﻣﺤﻠﻲ‬


‫ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ‪ ،2‬ﻣﺘﻐﻴﺮﻱ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﺩﺍﺧﻞ ﻳﮏ ﺑﻠﻮﮎ ﺍﻋﻼﻥ ﮔﺮﺩﺩ‪ .‬ﺍﻳﻦ ﮔﻮﻧﻪ‬
‫ﻣﺘﻐﻴﺮﻫﺎ ﻓﻘﻂ ﺩﺭ ﺩﺍﺧﻞ ﻫﻤﺎﻥ ﺑﻠﻮﮐﻲ ﮐﻪ ﺍﻋﻼﻥ ﻣﻲﺷﻮﻧﺪ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﻫﺴﺘﻨﺪ‪ .‬ﭼﻮﻥ ﺑﺪﻥۀ‬
‫ﺗﺎﺑﻊ‪ ،‬ﺧﻮﺩﺵ ﻳﮏ ﺑﻠﻮﮎ ﺍﺳﺖ ﭘﺲ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﻋﻼﻥ ﺷﺪﻩ ﺩﺭ ﻳﮏ ﺗﺎﺑﻊ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ‬

‫‪1 – Data Link Library‬‬ ‫‪1 – Local variable‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪144‬‬

‫ﺑﺮﺍﻱ ﺁﻥ ﺗﺎﺑﻊ ﻫﺴﺘﻨﺪ‪ .‬ﺍﻳﻦ ﻣﺘﻐﻴﺮﻫﺎ ﻓﻘﻂ ﺗﺎ ﻭﻗﺘﻲ ﮐﻪ ﺗﺎﺑﻊ ﺩﺭ ﺣﺎﻝ ﮐﺎﺭ ﺍﺳﺖ ﻭﺟﻮﺩ ﺩﺍﺭﻧﺪ‪.‬‬
‫ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﻧﻴﺰ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ ﻣﺤﺴﻮﺏ ﻣﻲﺷﻮﻧﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐7‬ﺗﺎﺑﻊ ﻓﺎﻛﺘﻮﺭﻳﻞ‬


‫ﺍﻋﺪﺍﺩ ﻓﺎﻛﺘﻮﺭﻳﻞ ﺭﺍ ﺩﺭ ﻣﺜﺎﻝ ‪ 4‐8‬ﺩﻳﺪﻳﻢ‪ .‬ﻓﺎﻛﺘﻮﺭﻳﻞ ﻋﺪﺩ ﺻﺤﻴﺢ ‪ n‬ﺑﺮﺍﺑﺮ ﺍﺳﺖ ﺑﺎ‪:‬‬
‫)‪n! = n(n-1)(n-2)..(3)(2)(1‬‬

‫ﺗﺎﺑﻊ ﺯﻳﺮ‪ ،‬ﻓﺎﮐﺘﻮﺭﻳﻞ ﻋﺪﺩ ‪ n‬ﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻣﻲﮐﻨﺪ‪:‬‬


‫)‪long fact(int n‬‬
‫)‪{ //returns n! = n*(n-1)*(n-2)*...*(2)*(1‬‬
‫;‪if (n < 0) return 0‬‬
‫;‪int f = 1‬‬
‫)‪while (n > 1‬‬
‫;‪f *= n--‬‬
‫;‪return f‬‬
‫}‬

‫ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﻭ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ﺩﺍﺭﺩ‪ 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‬ﺗﺎﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ﺩﺭﻭﻥ ﻳﮏ ﺗﺎﺑﻊ ﺩﻳﮕﺮ ﺑﻪ ﮐﺎﺭ ﺭﻭﺩ‪ .‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﭼﻨﺪ ﺗﺎﺑﻊ‬
‫ﺳﺎﺩﻩ ﻭ ﺗﺮﮐﻴﺐ ﺁﻥﻫﺎ ﻣﻲﺗﻮﺍﻥ ﺗﻮﺍﺑﻊ ﭘﻴﭽﻴﺪﻩﺗﺮﻱ ﺳﺎﺧﺖ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐8‬ﺗﺎﺑﻊ ﺟﺎﻳﮕﺸﺖ‬


‫ﺩﺭ ﺭﻳﺎﺿﻴﺎﺕ‪ ،‬ﺗﺎﺑﻊ ﺟﺎﻳﮕﺸﺖ ﺭﺍ ﺑﺎ )‪ p(n,k‬ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﻴﺎﻥ ﻣﻲﮐﻨﺪ‬
‫ﮐﻪ ﺑﻪ ﭼﻨﺪ ﻃﺮﻳﻖ ﻣﻲﺗﻮﺍﻥ ‪ k‬ﻋﻨﺼﺮ ﺩﻟﺨﻮﺍﻩ ﺍﺯ ﻳﮏ ﻣﺠﻤﻮﻉۀ ‪ n‬ﻋﻨﺼﺮﻱ ﺭﺍ ﮐﻨﺎﺭ ﻳﮑﺪﻳﮕﺮ‬
‫ﻗﺮﺍﺭ ﺩﺍﺩ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﻣﺤﺎﺳﺒﻪ ﺍﺯ ﺭﺍﺑﻂۀ ﺯﻳﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ‪:‬‬
‫!‪n‬‬
‫= ) ‪P(n, k‬‬
‫!) ‪(n − k‬‬
‫ﺑﺮﺍﻱ ﻣﺜﺎﻝ‪:‬‬
‫!‪4‬‬ ‫‪4! 24‬‬
‫= )‪P(4,2‬‬ ‫= =‬ ‫‪= 12‬‬
‫‪(4 − 2)! 2! 2‬‬
‫ﭘﺲ ﺑﻪ ‪ 12‬ﻃﺮﻳﻖ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺩﻭ ﻋﻨﺼﺮ ﺩﻟﺨﻮﺍﻩ ﺍﺯ ﻳﮏ ﻣﺠﻤﻮﻉۀ ﭼﻬﺎﺭ ﻋﻨﺼﺮﻱ ﺭﺍ ﮐﻨﺎﺭ ﻫﻢ‬
‫ﺑﭽﻴﻨﻴﻢ‪ .‬ﺑﺮﺍﻱ ﺩﻭ ﻋﻨﺼﺮ ﺍﺯ ﻣﺠﻤﻮﻉۀ }‪ {1, 2, 3, 4‬ﺣﺎﻟﺖﻫﺎﻱ ﻣﻤﮑﻦ ﻋﺒﺎﺭﺕ ﺍﺳﺖ‬
‫ﺍﺯ‪:‬‬
‫‪12, 13, 14, 21, 23, 24, 31, 32, 34, 41, 42, 43‬‬

‫ﻛﺪ ﺯﻳﺮ ﺗﺎﺑﻊ ﺟﺎﻳﮕﺸﺖ ﺭﺍ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻣﻲﻛﻨﺪ‪:‬‬


‫)‪long perm(int n, int k‬‬
‫‪{ // returns P(n,k), the number of the permutations of k from n:‬‬
‫;‪if (n < 0) || k < 0 || k > n) return 0‬‬
‫;)‪return fact(n)/fact(n-k‬‬
‫}‬

‫ﺍﻳﻦ ﺗﺎﺑﻊ‪ ،‬ﺧﻮﺩ ﺍﺯ ﺗﺎﺑﻊ ﺩﻳﮕﺮﻱ ﮐﻪ ﻫﻤﺎﻥ ﺗﺎﺑﻊ ﻓﺎﮐﺘﻮﺭﻳﻞ ﺍﺳﺖ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩ‪ .‬ﺷﺮﻁ ﺑﻪ ﮐﺎﺭ‬
‫ﺭﻓﺘﻪ ﺩﺭ ﺩﺳﺘﻮﺭ ‪ if‬ﺑﺮﺍﻱ ﻣﺤﺪﻭﺩ ﮐﺮﺩﻥ ﺣﺎﻟﺖﻫﺎﻱ ﻏﻴﺮ ﻣﻤﮑﻦ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺩﺭ ﺍﻳﻦ‬
‫ﺣﺎﻟﺖﻫﺎ‪ ،‬ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ ‪ 0‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﺗﺎ ﻧﺸﺎﻥ ﺩﻫﺪ ﮐﻪ ﻳﮏ ﻭﺭﻭﺩﻱ ﺍﺷﺘﺒﺎﻩ ﻭﺟﻮﺩ ﺩﺍﺷﺘﻪ‬
‫ﺍﺳﺖ‪ .‬ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺑﺮﺍﻱ ﺗﺎﺑﻊ )(‪ perm‬ﺩﺭ ﺍﺩﺍﻣﻪ ﺁﻣﺪﻩ ﺍﺳﺖ‪:‬‬

‫‪1 – Local function‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 146

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

.‫ ﺩﺭ ﻳﮏ ﻓﺎﻳﻞ ﺑﺎﺷﺪ‬fact() ‫ ﻭ‬perm() ‫ﺍﻟﺒﺘﻪ ﺿﺮﻭﺭﻱ ﺍﺳﺖ ﮐﻪ ﺗﻌﺮﻳﻒ ﺩﻭ ﺗﺎﺑﻊ‬

void ‫ ﺗﺎﺑﻊ‬5‐7

‫ ﺑﺮﺍﻱ ﻣﺸﺨﺺ ﮐﺮﺩﻥ‬C++ ‫ ﺩﺭ‬.‫ﻻﺯﻡ ﻧﻴﺴﺖ ﻳﻚ ﺗﺎﺑﻊ ﺣﺘﻤﺎ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ‬


‫ ﻳﮏ‬.‫ ﺑﻪ ﻋﻨﻮﺍﻥ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻨﺪ‬void ‫ﭼﻨﻴﻦ ﺗﻮﺍﺑﻌﻲ ﺍﺯ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ‬
.‫ ﺗﺎﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ﻫﻴﭻ ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ ﻧﺪﺍﺭﺩ‬void ‫ﺗﺎﺑﻊ‬

‫ ﻧﺎﻡ ﺁﻥﻫﺎ ﺭﺍ ﻣﻲﻧﻮﻳﺴﺪ‬، ‫ ﺗﺎﺑﻌﻲ ﻛﻪ ﺑﻪ ﺟﺎﻱ ﺷﻤﺎﺭۀ ﻣﺎﻩﻫﺎ‬5‐9 ‫* ﻣﺜﺎﻝ‬


void PrintDate(int,int,int);
// prints the given date in literal form:

int main()
{ // tests the PrintDate() function:
int day, month, year;
do
147 ‫ ﺗﻮاﺑﻊ‬/ ‫ﻓﺼﻞ ﭘﻨﺠﻢ‬

{ cin >> day >> month >> year;


PrintDate(day,month,year);
}
while (month > 0);
}

void PrintDate(int d, int m, int y)


{ // prints the given date in literal form:
if (d < 1 || d > 31 || m < 1 || m > 12 || y < 0)
{ cout << "Error: parameter out of range.\n";
return;
}
Cout << d;
switch (m)
{ case 1: cout << "Farvardin "; break;
case 2: cout << "Ordibehesht "; break;
case 3: cout << "Khordad "; break;
case 4: cout << "Tir "; break;
case 5: cout << "Mordad "; break;
case 6: cout << "Shahrivar "; break;
case 7: cout << "Mehr "; break;
case 8: cout << "Aban "; break;
case 9: cout << "Azar "; break;
case 10: cout << "Dey "; break;
case 11: cout << "Bahman "; break;
case 12: cout << "Esfnad "; break;
}
cout << y << endl;
}
7 12 1383
7 Esfand 1383
15 8 1384
15 Aban 1384
000
Error: parameter out of range.
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪148‬‬

‫ﺗﺎﺑﻊ )(‪ PrintDate‬ﻫﻴﭻ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺑﺮﻧﻤﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺗﻨﻬﺎ ﻫﺪﻑ ﺍﻳﻦ ﺗﺎﺑﻊ‪ ،‬ﭼﺎﭖ ﺗﺎﺭﻳﺦ‬
‫ﺍﺳﺖ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺁﻥ ‪ void‬ﺍﺳﺖ‪ .‬ﺍﮔﺮ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﺧﺎﺭﺝ ﺍﺯ ﻣﺤﺪﻭﺩﻩ ﺑﺎﺷﻨﺪ‪،‬‬
‫ﺗﺎﺑﻊ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﮐﻨﺪ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺑﺎ ﺍﻳﻦ ﻭﺟﻮﺩ ﺑﺎﺯ ﻫﻢ ﺍﺣﺘﻤﺎﻝ ﺩﺍﺭﺩ‬
‫ﻣﻘﺎﺩﻳﺮ ﻏﻴﺮﻣﻤﮑﻨﻲ ﻣﺎﻧﻨﺪ ‪ 31 Esfand 1384‬ﭼﺎﭖ ﺷﻮﻧﺪ‪ .‬ﺍﺻﻼﺡ ﺍﻳﻦ ﻧﺎﻫﻨﺠﺎﺭﻱ ﺭﺍ‬
‫ﺑﻪ ﻋﻨﻮﺍﻥ ﺗﻤﺮﻳﻦ ﺑﻪ ﺩﺍﻧﺸﺠﻮ ﻭﺍ ﻣﻲﮔﺬﺍﺭﻳﻢ‪.‬‬
‫ﺍﺯ ﺁﻥﺟﺎ ﻛﻪ ﻳﻚ ﺗﺎﺑﻊ ‪ void‬ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺑﺮﻧﻤﻲﮔﺮﺩﺍﻧﺪ‪ ،‬ﻧﻴﺎﺯﻱ ﺑﻪ ﺩﺳﺘﻮﺭ ‪return‬‬
‫ﻧﻴﺴﺖ ﻭﻟﻲ ﺍﮔﺮ ﻗﺮﺍﺭ ﺑﺎﺷﺪ ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺭﺍ ﺩﺭ ﺗﺎﺑﻊ ‪ void‬ﻗﺮﺍﺭ ﺩﻫﻴﻢ‪ ،‬ﺑﺎﻳﺪ ﺁﻥ ﺭﺍ ﺑﻪ ﺷﮑﻞ‬
‫ﺗﻨﻬﺎ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﺑﻌﺪ ﺍﺯ ﮐﻠﻢۀ ‪ return‬ﻫﻴﭻ ﭼﻴﺰ ﺩﻳﮕﺮﻱ ﺑﻴﺎﻳﺪ‪:‬‬
‫;‪return‬‬

‫ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺩﺳﺘﻮﺭ ‪ return‬ﻓﻘﻂ ﺗﺎﺑﻊ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‪.‬‬


‫ﺗﻮﺍﺑﻊ ‪ void‬ﻣﻌﻤﻮﻻ ﺑﺮﺍﻱ ﺍﻧﺠﺎﻡ ﻳﮏ ﮐﺎﺭ ﻣﺸﺨﺺ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ ﻣﺜﻞ ﺗﺎﺑﻊ ﺑﺎﻻ‬
‫ﮐﻪ ﺗﺎﺭﻳﺦ ﻋﺪﺩﻱ ﺭﺍ ﮔﺮﻓﺘﻪ ﻭ ﺷﮑﻞ ﺣﺮﻓﻲ ﺁﻥ ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ‬
‫ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﻣﻌﻤﻮﻻ ﺍﺳﻢ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﮔﺰﺍﺭۀ ﻓﻌﻠﻲ ﺍﻧﺘﺨﺎﺏ ﻣﻲﮐﻨﻨﺪ‪ .‬ﻣﺜﻼ ﻧﺎﻡ‬
‫ﺗﺎﺑﻊ ﻓﻮﻕ ‪ PrintDate‬ﺍﺳﺖ ﮐﻪ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﺍﻳﻦ ﺗﺎﺑﻊ ﮐﺎﺭ ﭼﺎﭖ ﺗﺎﺭﻳﺦ ﺭﺍ ﺍﻧﺠﺎﻡ‬
‫ﻣﻲﺩﻫﺪ‪ .‬ﺭﻋﺎﻳﺖ ﺍﻳﻦ ﻗﺮﺍﺭﺩﺍﺩ ﺑﻪ ﺧﻮﺍﻧﺎﻳﻲ ﻭ ﺩﺭﮎ ﺑﻬﺘﺮ ﺑﺮﻧﺎﻣﻪﺗﺎﻥ ﮐﻤﮏ ﻣﻲﮐﻨﺪ‪.‬‬

‫‪ 5‐8‬ﺗﻮﺍﺑﻊ ﺑﻮﻟﻲ‬
‫ﺩﺭ ﺑﺴﻴﺎﺭﻱ ﺍﺯ ﺍﻭﻗﺎﺕ ﻻﺯﻡ ﺍﺳﺖ ﺩﺭ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺷﺮﻃﻲ ﺑﺮﺭﺳﻲ ﺷﻮﺩ‪ .‬ﺍﮔﺮ ﺑﺮﺭﺳﻲ ﺍﻳﻦ‬
‫ﺷﺮﻁ ﺑﻪ ﺩﺳﺘﻮﺭﺍﺕ ﺯﻳﺎﺩﻱ ﻧﻴﺎﺯ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ ،‬ﺑﻬﺘﺮ ﺍﺳﺖ ﮐﻪ ﻳﮏ ﺗﺎﺑﻊ ﺍﻳﻦ ﺑﺮﺭﺳﻲ ﺭﺍ ﺍﻧﺠﺎﻡ‬
‫ﺩﻫﺪ‪ .‬ﺍﻳﻦ ﮐﺎﺭ ﻣﺨﺼﻮﺻﺎ ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺍﺯ ﺣﻠﻘﻪﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﺑﺴﻴﺎﺭ ﻣﻔﻴﺪ ﺍﺳﺖ‪ .‬ﺗﻮﺍﺑﻊ‬
‫ﺑﻮﻟﻲ ﻓﻘﻂ ﺩﻭ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﻨﺪ‪ true :‬ﻳﺎ ‪. false‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐10‬ﺗﺎﺑﻌﻲ ﻛﻪ ﺍﻭﻝ ﺑﻮﺩﻥ ﺍﻋﺪﺍﺩ ﺭﺍ ﺑﺮﺭﺳﻲ ﻣﻲﻛﻨﺪ‬


‫ﮐﺪ ﺯﻳﺮ ﻳﻚ ﺗﺎﺑﻊ ﺑﻮﻟﻲ ﺍﺳﺖ ﻛﻪ ﺗﺸﺨﻴﺺ ﻣﻲﺩﻫﺪ ﺁﻳﺎ ﻋﺪﺩ ﺻﺤﻴﺢ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺑﻪ‬
‫ﺁﻥ‪ ،‬ﺍﻭﻝ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ‪:‬‬
‫)‪bool isPrime(int n‬‬
‫‪{ // returns true if n is prime, false otherwise:‬‬
‫‪149‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫;)‪float sqrtn = sqrt(n‬‬


‫;‪if (n < 2) return false‬‬ ‫‪// 0 and 1 are not primes‬‬
‫;‪if (n < 4) return true‬‬ ‫‪// 2 and 3 are the first primes‬‬
‫;‪if (n%2 == 0) return false‬‬ ‫‪// 2 is the only even prime‬‬
‫)‪for (int d=3; d <= sqrtn; d += 2‬‬
‫‪if (n%d == 0) return false; // n has a nontrivial divisor‬‬
‫;‪return true‬‬ ‫‪// n has no nontrivial divisors‬‬
‫}‬

‫ﺗﺎﺑﻊ ﻓﻮﻕ ﺑﺮﺍﻱ ﻋﺪﺩ ‪ 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‬ﺑﻪ ﻫﻤﻴﻦ ﺷﻴﻮﻩ ﻧﺎﻡﮔﺬﺍﺭﻱ ﺷﺪﻩﺍﻧﺪ‪.‬‬

‫‪ 5‐9‬ﺗﻮﺍﺑﻊ ﻭﺭﻭﺩﻱ‪/‬ﺧﺮﻭﺟﻲ‪(I/O) 1‬‬


‫ﺑﺨﺶﻫﺎﻳﻲ ﺍﺯ ﺑﺮﻧﺎﻣﻪ ﮐﻪ ﺑﻪ ﺟﺰﻳﻴﺎﺕ ﺩﺳﺖ ﻭ ﭘﺎ ﮔﻴﺮ ﻣﻲﭘﺮﺩﺍﺯﺩ ﻭ ﺧﻴﻠﻲ ﺑﻪ ﻫﺪﻑ‬
‫ﺍﺻﻠﻲ ﺑﺮﻧﺎﻣﻪ ﻣﺮﺑﻮﻁ ﻧﻴﺴﺖ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺗﻮﺍﺑﻊ ﺳﭙﺮﺩ‪ .‬ﺩﺭ ﭼﻨﻴﻦ ﺷﺮﺍﻳﻄﻲ ﺳﻮﺩﻣﻨﺪﻱ ﺗﻮﺍﺑﻊ‬
‫ﻣﺤﺴﻮﺱﺗﺮ ﻣﻲﺷﻮﺩ‪ .‬ﻓﺮﺽ ﮐﻨﻴﺪ ﻧﺮﻡﺍﻓﺰﺍﺭﻱ ﺑﺮﺍﻱ ﺳﻴﺴﺘﻢ ﺁﻣﻮﺯﺷﻲ ﺩﺍﻧﺸﮕﺎﻩ ﻃﺮﺍﺣﻲ‬
‫ﮐﺮﺩﻩﺍﻳﺪ ﮐﻪ ﺳﻮﺍﺑﻖ ﺗﺤﺼﻴﻠﻲ ﺩﺍﻧﺸﺠﻮﻳﺎﻥ ﺭﺍ ﻧﮕﻪ ﻣﻲﺩﺍﺭﺩ‪ .‬ﺩﺭ ﺍﻳﻦ ﻧﺮﻡﺍﻓﺰﺍﺭ ﻻﺯﻡ ﺍﺳﺖ ﮐﻪ‬
‫ﺳﻦ ﺩﺍﻧﺸﺠﻮ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮑﻲ ﺍﺯ ﺍﻃﻼﻋﺎﺕ ﭘﺮﻭﻧﺪۀ ﺩﺍﻧﺸﺠﻮ ﻭﺍﺭﺩ ﺷﻮﺩ‪ .‬ﺍﮔﺮ ﻭﻇﻴﻒۀ ﺩﺭﻳﺎﻓﺖ‬
‫ﺳﻦ ﺭﺍ ﺑﻪ ﻋﻬﺪۀ ﻳﮏ ﺗﺎﺑﻊ ﺑﮕﺬﺍﺭﻳﺪ‪ ،‬ﻣﻲﺗﻮﺍﻧﻴﺪ ﺟﺰﻳﻴﺎﺗﻲ ﺍﺯ ﻗﺒﻴﻞ ﮐﻨﺘﺮﻝ ﻭﺭﻭﺩﻱ ﻣﻌﺘﺒﺮ‪ ،‬ﻳﺎﻓﺘﻦ‬
‫ﺳﻦ ﺍﺯ ﺭﻭﻱ ﺗﺎﺭﻳﺦ ﺗﻮﻟﺪ ﻭ ‪ ...‬ﺭﺍ ﺩﺭ ﺍﻳﻦ ﺗﺎﺑﻊ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﮐﻨﻴﺪ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﺍﺯ ﻣﺴﻴﺮ ﺑﺮﻧﺎﻡۀ‬
‫ﺍﺻﻠﻲ ﻣﻨﺤﺮﻑ ﺷﻮﻳﺪ‪.‬‬
‫ﻗﺒﻼ ﻧﻤﻮﻧﻪﺍﻱ ﺍﺯ ﺗﻮﺍﺑﻊ ﺧﺮﻭﺟﻲ ﺭﺍ ﺩﻳﺪﻳﻢ‪ .‬ﺗﺎﺑﻊ )(‪ PrintDate‬ﺩﺭ ﻣﺜﺎﻝ ‪5‐9‬‬
‫ﻫﻴﭻ ﭼﻴﺰﻱ ﺑﻪ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﺮﻧﻤﻲﮔﺮﺩﺍﻧﺪ ﻭ ﻓﻘﻂ ﺑﺮﺍﻱ ﭼﺎﭖ ﻧﺘﺎﻳﺞ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‪ .‬ﺍﻳﻦ‬
‫ﺗﺎﺑﻊ ﻧﻤﻮﻧﻪﺍﻱ ﺍﺯ ﺗﻮﺍﺑﻊ ﺧﺮﻭﺟﻲ ﺍﺳﺖ؛ ﻳﻌﻨﻲ ﺗﻮﺍﺑﻌﻲ ﮐﻪ ﻓﻘﻂ ﺑﺮﺍﻱ ﭼﺎﭖ ﻧﺘﺎﻳﺞ ﺑﻪ ﮐﺎﺭ‬
‫ﻣﻲﺭﻭﻧﺪ ﻭ ﻫﻴﭻ ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ ﻧﺪﺍﺭﻧﺪ‪ .‬ﺗﻮﺍﺑﻊ ﻭﺭﻭﺩﻱ ﻧﻴﺰ ﺑﻪ ﻫﻤﻴﻦ ﺭﻭﺵ ﮐﺎﺭ ﻣﻲﮐﻨﻨﺪ ﺍﻣﺎ‬

‫‪1 – Input/Output functions‬‬


‫‪151‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫ﺩﺭ ﺟﻬﺖ ﻣﻌﮑﻮﺱ‪ .‬ﻳﻌﻨﻲ ﺗﻮﺍﺑﻊ ﻭﺭﻭﺩﻱ ﻓﻘﻂ ﺑﺮﺍﻱ ﺩﺭﻳﺎﻓﺖ ﻭﺭﻭﺩﻱ ﻭ ﺍﺭﺳﺎﻝ ﺁﻥ ﺑﻪ ﺑﺮﻧﺎﻡۀ‬
‫ﺍﺻﻠﻲ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ﻭ ﻫﻴﭻ ﭘﺎﺭﺍﻣﺘﺮﻱ ﻧﺪﺍﺭﻧﺪ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪ ﻳﮏ ﺗﺎﺑﻊ ﻭﺭﻭﺩﻱ ﺭﺍ ﻧﺸﺎﻥ‬
‫ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐11‬ﺗﺎﺑﻌﻲ ﺑﺮﺍﻱ ﺩﺭﻳﺎﻓﺖ ﺳﻦ ﻛﺎﺭﺑﺮ‬


‫ﺗﺎﺑﻊ ﺳﺎﺩۀ ﺯﻳﺮ‪ ،‬ﺳﻦ ﮐﺎﺭﺑﺮ ﺭﺍ ﺩﺭﺧﻮﺍﺳﺖ ﻣﻲﮐﻨﺪ ﻭ ﻣﻘﺪﺍﺭ ﺩﺭﻳﺎﻓﺖ ﺷﺪﻩ ﺭﺍ ﺑﻪ ﺑﺮﻧﺎﻡۀ‬
‫ﺍﺻﻠﻲ ﻣﻲﻓﺮﺳﺘﺪ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ ﺗﻘﺮﻳﺒﺎ ﻫﻮﺷﻤﻨﺪ ﺍﺳﺖ ﻭ ﻫﺮ ﻋﺪﺩ ﺻﺤﻴﺢ ﻭﺭﻭﺩﻱ ﻏﻴﺮ ﻣﻨﻄﻘﻲ ﺭﺍ‬
‫ﺭﺩ ﻣﻲﮐﻨﺪ ﻭ ﺑﻪ ﻃﻮﺭ ﻣﮑﺮﺭ ﺩﺭﺧﻮﺍﺳﺖ ﻭﺭﻭﺩﻱ ﻣﻌﺘﺒﺮ ﻣﻲﮐﻨﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ‬
‫ﺩﺭ ﻣﺤﺪﻭﺩۀ ‪ 7‬ﺗﺎ ‪ 120‬ﺩﺭﻳﺎﻓﺖ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int age‬‬
‫‪{ // prompts the user to input his/her age and returns that value:‬‬
‫;‪int n‬‬
‫)‪while (true‬‬
‫;" ‪{ cout << "How old are you:‬‬
‫;‪cin >> n‬‬
‫‪if (n < 0) cout << "\a\tYour age could not‬‬
‫;"‪be negative.‬‬
‫‪else if (n > 120) cout << "\a\tYou could not‬‬
‫;"‪be over 120.‬‬
‫;‪else return n‬‬
‫;"‪cout << "\n\tTry again.\n‬‬
‫}‬
‫}‬

‫ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ‪ 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‬‬

‫‪You are 99 years old.‬‬

‫‪ 5‐14‬ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ‪) 1‬ﺁﺩﺭﺱ(‬


‫ﺗﺎ ﺍﻳﻦ ﻟﺤﻈﻪ ﺗﻤﺎﻡ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻳﻲ ﻛﻪ ﺩﺭ ﺗﻮﺍﺑﻊ ﺩﻳﺪﻳﻢ ﺑﻪ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺍﺭﺳﺎﻝ ﺷﺪﻩﺍﻧﺪ‪.‬‬
‫ﻳﻌﻨﻲ ﺍﺑﺘﺪﺍ ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﺩﺭ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ ﺫﮐﺮ ﺷﺪﻩ ﺑﺮﺁﻭﺭﺩ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﺍﻳﻦ‬
‫ﻣﻘﺪﺍﺭ ﺑﻪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﻣﺤﻠﻲ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﻣﺜﻼ ﺩﺭ ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ cube(x‬ﺍﺑﺘﺪﺍ‬
‫ﻣﻘﺪﺍﺭ ‪ x‬ﺑﺮﺁﻭﺭﺩ ﺷﺪﻩ ﻭ ﺳﭙﺲ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﻪ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ‪ n‬ﺩﺭ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ‬
‫ﭘﺲ ﺍﺯ ﺁﻥ ﺗﺎﺑﻊ ﮐﺎﺭ ﺧﻮﻳﺶ ﺭﺍ ﺁﻏﺎﺯ ﻣﻲﮐﻨﺪ‪ .‬ﺩﺭ ﻃﻲ ﺍﺟﺮﺍﻱ ﺗﺎﺑﻊ ﻣﻤﮑﻦ ﺍﺳﺖ ﻣﻘﺪﺍﺭ ‪n‬‬
‫ﺗﻐﻴﻴﺮ ﮐﻨﺪ ﺍﻣﺎ ﭼﻮﻥ ‪ n‬ﻣﺤﻠﻲ ﺍﺳﺖ ﻫﻴﭻ ﺗﻐﻴﻴﺮﻱ ﺭﻭﻱ ﻣﻘﺪﺍﺭ ‪ x‬ﻧﻤﻲﮔﺬﺍﺭﺩ‪ .‬ﭘﺲ ﺧﻮﺩ ‪ x‬ﺑﻪ‬
‫ﺗﺎﺑﻊ ﻧﻤﻲﺭﻭﺩ ﺑﻠﮑﻪ ﻣﻘﺪﺍﺭ ﺁﻥ ﺩﺭﻭﻥ ﺗﺎﺑﻊ ﮐﭙﻲ ﻣﻲﺷﻮﺩ‪ .‬ﺗﻐﻴﻴﺮ ﺩﺍﺩﻥ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﮐﭙﻲ ﺷﺪﻩ‬
‫ﺩﺭﻭﻥ ﺗﺎﺑﻊ ﻫﻴﭻ ﺗﺎﺛﻴﺮﻱ ﺑﺮ ‪ x‬ﺍﺻﻠﻲ ﻧﺪﺍﺭﺩ‪ .‬ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ‪ x‬ﺭﺍ ﺑﺨﻮﺍﻧﺪ‬

‫‪1 – Reference‬‬
‫‪153‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫ﺍﻣﺎ ﻧﻤﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ‪ x‬ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﺪ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺑﻪ ‪ x‬ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ »ﻓﻘﻂ ﺧﻮﺍﻧﺪﻧﻲ«‬
‫ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﻭﻗﺘﻲ ﺍﺭﺳﺎﻝ ﺑﻪ ﻭﺳﻴﻞۀ ﻣﻘﺪﺍﺭ ﺑﺎﺷﺪ‪ ،‬ﻫﻨﮕﺎﻡ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻋﺒﺎﺭﺍﺕ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪ .‬ﻣﺜﻼ ﺗﺎﺑﻊ )(‪ cube‬ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺻﻮﺭﺕ )‪ cube(2*x-3‬ﻓﺮﺍﺧﻮﺍﻧﻲ‬
‫ﮐﺮﺩ ﻳﺎ ﺑﻪ ﺷﮑﻞ ))‪ cube(2*sqrt(x)-cube(3‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﻮﺩ‪ .‬ﺩﺭ ﻫﺮ ﻳﮏ ﺍﺯ‬
‫ﺍﻳﻦ ﺣﺎﻻﺕ‪ ،‬ﻋﺒﺎﺭﺕ ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻣﻘﺪﺍﺭ ﺗﮑﻲ ﺑﺮﺁﻭﺭﺩ ﺷﺪﻩ ﻭ ﺣﺎﺻﻞ ﺁﻥ‬
‫ﻣﻘﺪﺍﺭ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﺯ ﺗﻐﻴﻴﺮﺍﺕ‬
‫ﻧﺎﺧﻮﺍﺳﺘﻪ ﺩﺭ ﺗﻮﺍﺑﻊ ﻣﺼﻮﻥ ﺑﻤﺎﻧﻨﺪ‪ .‬ﺍﻣﺎ ﮔﺎﻫﻲ ﺍﻭﻗﺎﺕ ﻋﻤﺪﺍ ﻣﻲﺧﻮﺍﻫﻴﻢ ﺍﻳﻦ ﺍﺗﻔﺎﻕ ﺭﺥ ﺩﻫﺪ‪.‬‬
‫ﻳﻌﻨﻲ ﻣﻲﺧﻮﺍﻫﻴﻢ ﮐﻪ ﺗﺎﺑﻊ ﺑﺘﻮﺍﻧﺪ ﻣﺤﺘﻮﻳﺎﺕ ﻣﺘﻐﻴﺮ ﻓﺮﺳﺘﺎﺩﻩ ﺷﺪﻩ ﺑﻪ ﺁﻥ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ‪.‬‬
‫ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺍﺯ ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪.‬‬
‫ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻣﺸﺨﺺ ﮐﻨﻴﻢ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ‪ ،‬ﻋﻼﻣﺖ &‬
‫ﺭﺍ ﺑﻪ ﻧﻮﻉ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﺍﺿﺎﻓﻪ ﻣﻲﮐﻨﻴﻢ‪ .‬ﺍﻳﻦ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺗﺎﺑﻊ‬
‫ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﮐﭙﻲ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥ ﺁﺭﮔﻮﻣﺎﻥ ﺍﻳﺠﺎﺩ ﮐﻨﺪ‪ ،‬ﺧﻮﺩ ﺁﺭﮔﻮﻣﺎﻥ ﻣﺤﻠﻲ ﺭﺍ ﺑﻪ ﮐﺎﺭ‬
‫ﺑﮕﻴﺮﺩ‪ .‬ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺗﺎﺑﻊ ﻫﻢ ﻣﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ﺁﺭﮔﻮﻣﺎﻥ ﻓﺮﺳﺘﺎﺩﻩ ﺷﺪﻩ ﺭﺍ ﺑﺨﻮﺍﻧﺪ ﻭ ﻫﻢ‬
‫ﻣﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ﺁﻥ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﺪ‪ .‬ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺁﻥ ﭘﺎﺭﺍﻣﺘﺮ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ »ﺧﻮﺍﻧﺪﻧﻲ‐ﻧﻮﺷﺘﻨﻲ«‬
‫ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪ .‬ﻫﺮ ﺗﻐﻴﻴﺮﻱ ﮐﻪ ﺭﻭﻱ ﭘﺎﺭﺍﻣﺘﺮ ﺧﻮﺍﻧﺪﻧﻲ‐ﻧﻮﺷﺘﻨﻲ ﺩﺭ ﺗﺎﺑﻊ ﺻﻮﺭﺕ ﮔﻴﺮﺩ ﺑﻪ ﻃﻮﺭ‬
‫ﻣﺴﺘﻘﻴﻢ ﺭﻭﻱ ﻣﺘﻐﻴﺮ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺍﻋﻤﺎﻝ ﻣﻲﺷﻮﺩ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐12‬ﺗﺎﺑﻊ )(‪swap‬‬


‫ﺗﺎﺑﻊ ﻛﻮﭼﻚ ﺯﻳﺮ ﺩﺭ ﻣﺮﺗﺐ ﮐﺮﺩﻥ ﺩﺍﺩﻩﻫﺎ ﮐﺎﺭﺑﺮﺩ ﻓﺮﺍﻭﺍﻥ ﺩﺍﺭﺩ‪:‬‬
‫)‪void swap(float& x, float& y‬‬
‫‪{ // exchanges the values of x and y:‬‬
‫;‪float temp = x‬‬
‫;‪x = y‬‬
‫;‪y = temp‬‬
‫}‬

‫ﻫﺪﻑ ﺍﻳﻦ ﺗﺎﺑﻊ ﺟﺎﺑﺠﺎ ﮐﺮﺩﻥ ﺩﻭ ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺁﻥ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ‬
‫ﻣﻨﻈﻮﺭ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ‪ x‬ﻭ ‪ y‬ﺑﻪ ﺻﻮﺭﺕ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺭﺟﺎﻉ ﺗﻌﺮﻳﻒ ﺷﺪﻩﺍﻧﺪ‪:‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪154‬‬

‫‪float& x, float& y‬‬

‫ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﻣﻮﺟﺐ ﻣﻲﺷﻮﺩ ﻛﻪ ﺑﻪ ﺟﺎﻱ ‪ 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‬‬

‫ﻭﻗﺘﻲ ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ swap(a,b‬ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‪ x ،‬ﺑﻪ ‪ a‬ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ﻭ ‪ y‬ﺑﻪ ‪ .b‬ﺳﭙﺲ‬


‫ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ‪ temp‬ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ ﻭ ﻣﻘﺪﺍﺭ ‪) x‬ﮐﻪ ﻫﻤﺎﻥ ‪ a‬ﺍﺳﺖ( ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ‬
‫هﻨﮕﺎم ﻓﺮاﺧﻮاﻧﯽ ﺗﺎﺑﻊ‬ ‫ﻣﻲﮔﻴﺮﺩ‪ .‬ﭘﺲ ﺍﺯ ﺁﻥ ﻣﻘﺪﺍﺭ ‪y‬‬
‫)‪swap(a b‬‬ ‫)ﮐﻪ ﻫﻤﺎﻥ ‪ b‬ﺍﺳﺖ( ﺩﺭﻭﻥ ‪x‬‬
‫)(‪main‬‬ ‫)(‪swap‬‬

‫‪a‬‬ ‫‪55.5‬‬ ‫‪x‬‬ ‫)ﻳﻌﻨﻲ ‪ (a‬ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﻭ ﺁﻧﮕﺎﻩ‬


‫‪float‬‬ ‫&‪float‬‬
‫ﻣﻘﺪﺍﺭ ‪ temp‬ﺩﺭﻭﻥ ‪) y‬ﻳﻌﻨﻲ‬
‫‪b‬‬ ‫‪88.8‬‬ ‫‪y‬‬
‫‪float‬‬ ‫&‪float‬‬ ‫‪ (b‬ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﻧﺘﻴﺞۀ‬
‫ﻧﻬﺎﻳﻲ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻣﻘﺎﺩﻳﺮ ‪ a‬ﻭ‬
‫ﺑﻌﺪ از‬ ‫‪ b‬ﺑﺎ ﻳﮑﺪﻳﮕﺮ ﺟﺎﺑﺠﺎ ﻣﻲ ﺷﻮﻧﺪ‪.‬‬
‫)(‪main‬‬ ‫ﺑﺎزﮔﺸﺖ‬ ‫)(‪swap‬‬
‫ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ‬
‫‪a‬‬ ‫‪88.8‬‬ ‫‪x‬‬
‫‪float‬‬ ‫&‪float‬‬ ‫ﺭﺥ‬ ‫ﺟﺎﺑﺠﺎﻳﻲ‬ ‫ﺍﻳﻦ‬ ‫ﭼﻄﻮﺭ‬
‫‪b‬‬ ‫‪55.5‬‬ ‫‪y‬‬ ‫ﻣﻲﺩﻫﺪ‪:‬‬
‫‪float‬‬ ‫&‪float‬‬

‫‪temp‬‬ ‫‪55.5‬‬

‫‪float‬‬
‫‪155‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫ﺑﻪ ﺍﻋﻼﻥ ﺗﺎﺑﻊ )(‪ swap‬ﺩﻗﺖ ﮐﻨﻴﺪ‪:‬‬


‫)&‪void swap(float&, float‬‬

‫ﺍﻳﻦ ﺍﻋﻼﻥ ﺷﺎﻣﻞ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﺑﺮﺍﻱ ﻫﺮ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺳﺖ‪ .‬ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ‪ c‬ﻋﺎﺩﺕ ﺩﺍﺭﻧﺪ ﮐﻪ‬
‫ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﭘﻴﺸﻮﻧﺪ ﻧﺎﻡ ﻣﺘﻐﻴﺮ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻨﺪ )ﻣﺜﻞ‪ (float &x‬ﺩﺭ ‪C++‬‬
‫ﻓﺮﺽ ﻣﻲﮐﻨﻴﻢ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﭘﺴﻮﻧﺪ ﻧﻮﻉ ﺍﺳﺖ )ﻣﺜﻞ ‪ (float& x‬ﺑﻪ ﻫﺮ ﺣﺎﻝ‬
‫ﮐﺎﻣﭙﺎﻳﻠﺮ ﻫﻴﭻ ﻓﺮﻗﻲ ﺑﻴﻦ ﺍﻳﻦ ﺩﻭ ﺍﻋﻼﻥ ﻧﻤﻲﮔﺬﺍﺭﺩ ﻭ ﺷﮑﻞ ﻧﻮﺷﺘﻦ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ ﮐﺎﻣﻼ‬
‫ﺍﺧﺘﻴﺎﺭﻱ ﻭ ﺳﻠﻴﻘﻪﺍﻱ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐13‬ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻭ ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺗﻔﺎﻭﺕ ﺑﻴﻦ ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻭ ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺭﺍ ﻧﺸﺎﻥ‬
‫ﻣﻲﺩﻫﺪ‪:‬‬
‫;)&‪void f(int,int‬‬
‫‪// changes reference argument to 99:‬‬

‫)(‪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‬‬
‫}‬

‫)‪void f(int x , int& y‬‬


‫‪{ // changes reference argument to 99:‬‬
‫;‪x = 88‬‬
‫;‪y = 99‬‬
‫}‬
‫‪a = 22, b = 44‬‬
‫‪a = 22, b = 99‬‬
‫‪a = 22, b = 99‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪156‬‬

‫ﺗﺎﺑﻊ )(‪ 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‬‬

‫‪a‬‬ ‫‪22‬‬ ‫‪x‬‬ ‫‪22‬‬


‫‪int‬‬ ‫‪int‬‬

‫‪b‬‬ ‫‪44‬‬ ‫‪y‬‬


‫‪int‬‬ ‫&‪int‬‬

‫ﺑﻌﺪ از‬
‫)(‪f‬‬
‫)(‪main‬‬ ‫ﺑﺎزﮔﺸﺖ‬

‫‪a‬‬ ‫‪22‬‬ ‫‪x‬‬ ‫‪88‬‬


‫‪int‬‬ ‫‪int‬‬

‫‪b‬‬ ‫‪99‬‬ ‫‪y‬‬


‫‪int‬‬ ‫&‪int‬‬

‫ﺩﺭ ﺟﺪﻭﻝ ﺯﻳﺮ ﺧﻼﺹۀ ﺗﻔﺎﻭﺕﻫﺎﻱ ﺑﻴﻦ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻭ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ‬
‫ﺍﺭﺟﺎﻉ ﺁﻣﺪﻩ ﺍﺳﺖ‪.‬‬
‫ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺩﺭ ﻣﻘﺎﻳﺴﻪ ﺑﺎ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ‬
‫ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ‬ ‫ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ‬
‫;‪int& x‬‬ ‫;‪int x‬‬
‫ﭘﺎﺭﺍﻣﺘﺮ ‪ x‬ﻳﮏ ﺍﺭﺟﺎﻉ ﺍﺳﺖ‬ ‫ﭘﺎﺭﺍﻣﺘﺮ ‪ x‬ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﺤﻠﻲ ﺍﺳﺖ‬
‫‪ x‬ﻣﺘﺮﺍﺩﻑ ﺑﺎ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺳﺖ‬ ‫‪ x‬ﻳﮏ ﮐﭙﻲ ﺍﺯ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺳﺖ‬
‫ﻣﻲﺗﻮﺍﻧﺪ ﻣﺤﺘﻮﻳﺎﺕ ﺁﺭﮔﻮﻣﺎﻥ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﺪ‬ ‫ﺗﻐﻴﻴﺮ ﻣﺤﺘﻮﻳﺎﺕ ﺁﺭﮔﻮﻣﺎﻥ ﻣﻤﮑﻦ ﻧﻴﺴﺖ‬
‫‪157‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫ﺁﺭﮔﻮﻣﺎﻥ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﻓﻘﻂ ﺑﺎﻳﺪ‬ ‫ﺁﺭﮔﻮﻣﺎﻥ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻣﻲﺗﻮﺍﻧﺪ‬
‫ﻳﮏ ﻣﺘﻐﻴﺮ ﺑﺎﺷﺪ‬ ‫ﻳﮏ ﺛﺎﺑﺖ‪ ،‬ﻳﮏ ﻣﺘﻐﻴﺮ ﻳﺎ ﻳﮏ ﻋﺒﺎﺭﺕ ﺑﺎﺷﺪ‬
‫ﺁﺭﮔﻮﻣﺎﻥ ﺧﻮﺍﻧﺪﻧﻲ‐ﻧﻮﺷﺘﻨﻲ ﺍﺳﺖ‬ ‫ﺁﺭﮔﻮﻣﺎﻥ ﻓﻘﻂ ﺧﻮﺍﻧﺪﻧﻲ ﺍﺳﺖ‬

‫ﻳﻜﻲ ﺍﺯ ﻣﻮﺍﻗﻌﻲ ﻛﻪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺭﺟﺎﻉ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﻫﺴﺘﻨﺪ ﺟﺎﻳﻲ ﺍﺳﺖ ﻛﻪ ﺗﺎﺑﻊ ﺑﺎﻳﺪ‬
‫ﺑﻴﺶ ﺍﺯ ﻳﻚ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺎﺯﮔﺮﺩﺍﻧﺪ‪ .‬ﺩﺳﺘﻮﺭ ‪ return‬ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﻳﻚ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ‪.‬‬
‫ﺑﻨﺎﺑﺮﺍﻳﻦ ﺍﮔﺮ ﺑﺎﻳﺪ ﺑﻴﺶ ﺍﺯ ﻳﻚ ﻣﻘﺪﺍﺭ ﺑﺮﮔﺸﺖ ﺩﺍﺩﻩ ﺷﻮﺩ‪ ،‬ﺍﻳﻦ ﻛﺎﺭ ﺭﺍ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺍﺭﺟﺎﻉ‬
‫ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐14‬ﺑﺎﺯﮔﺸﺖ ﺑﻴﺸﺘﺮ ﺍﺯ ﻳﻚ ﻣﻘﺪﺍﺭ‬


‫ﺗﺎﺑﻊ ﺯﻳﺮ ﺍﺯ ﻃﺮﻳﻖ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺭﺍﺟﺎﻉ‪ ،‬ﺩﻭ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺎﺯﻣﻲﮔﺮﺩﺍﻧﺪ‪ area :‬ﻭ‬
‫‪) circumference‬ﻣﺤﻴﻂ ﻭ ﻣﺴﺎﺣﺖ( ﺑﺮﺍﻱ ﺩﺍﻳﺮﻩﺍﻱ ﮐﻪ ﺷﻌﺎﻉ ﺁﻥ ﻋﺪﺩ ﻣﻔﺮﻭﺽ ‪r‬‬
‫ﺍﺳﺖ‪:‬‬
‫)‪void ComputeCircle(double& area, double& circumference, double r‬‬
‫{‬ ‫‪// returns the area and circumference of a circle with radius r:‬‬
‫;‪const double PI = 3.141592653589793‬‬
‫;‪area = PI*r*r‬‬
‫;‪circumference = 2*PI*r‬‬
‫}‬

‫ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺗﺎﺑﻊ ﻓﻮﻕ ﻭ ﻳﮏ ﺍﺟﺮﺍﻱ ﺁﺯﻣﺎﻳﺸﻲ ﺁﻥ ﺩﺭ ﺷﮑﻞ ﺯﻳﺮ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪:‬‬
‫;)‪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‬‬

‫‪Enter radius: 100‬‬


‫‪area = 31415.9, circumference = 628.319‬‬

‫ﺩﺭ ﺍﻋﻼﻥ ﻭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﻓﻮﻕ‪ ،‬ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻳﻲ ﮐﻪ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﻧﺪ ﺩﺭ ﺍﺑﺘﺪﺍﻱ‬
‫ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﺷﺪﻩﺍﻧﺪ‪ .‬ﺭﻋﺎﻳﺖ ﺍﻳﻦ ﻗﺎﻋﺪﻩ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﻧﻈﻢ ﺑﺮﻧﺎﻣﻪ‬
‫ﺣﻔﻆ ﺷﻮﺩ ﻭ ﺑﻪ ﺳﺎﺩﮔﻲ ﺑﺘﻮﺍﻧﻴﺪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﺭﺍ ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﺗﻤﻴﺰ ﺩﻫﻴﺪ‪ .‬ﺍﻟﺒﺘﻪ ﺍﻳﻦ ﻓﻘﻂ‬
‫ﻳﮏ ﻗﺮﺍﺭﺩﺍﺩ ﺍﺳﺖ ﻭ ﺭﻋﺎﻳﺖ ﺁﻥ ﺍﺟﺒﺎﺭﻱ ﻧﻴﺴﺖ‪.‬‬

‫‪ 5‐11‬ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ‬


‫ﺍﺭﺳﺎﻝ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺩﻭ ﺧﺎﺻﻴﺖ ﻣﻬﻢ ﺩﺍﺭﺩ‪ :‬ﺍﻭﻝ ﺍﻳﻦ ﮐﻪ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ‬
‫ﺭﻭﻱ ﺁﺭﮔﻮﻣﺎﻥ ﻭﺍﻗﻌﻲ ﺗﻐﻴﻴﺮﺍﺗﻲ ﺑﺪﻫﺪ ﻭ ﺩﻭﻡ ﺍﻳﻦ ﮐﻪ ﺍﺯ ﺍﺷﻐﺎﻝ ﺑﻲﻣﻮﺭﺩ ﺣﺎﻓﻈﻪ ﺟﻠﻮﮔﻴﺮﻱ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﻭﻗﺘﻲ ﻳﮏ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﺷﻮﺩ‪ ،‬ﻳﮏ ﮐﭙﻲ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥ‬
‫ﺁﺭﮔﻮﻣﺎﻥ ﺍﻳﺠﺎﺩ ﺷﺪﻩ ﻭ ﺩﺭ ﺍﺧﺘﻴﺎﺭ ﺗﺎﺑﻊ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺍﻳﻦ ﮐﭙﻲ ﺑﻪ ﺍﻧﺪﺍﺯۀ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺻﻠﻲ‬
‫ﺣﺎﻓﻈﻪ ﺍﺷﻐﺎﻝ ﻣﻲﮐﻨﺪ‪ .‬ﺣﺎﻝ ﺍﮔﺮ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺻﻠﻲ ﺧﻴﻠﻲ ﺣﺠﻴﻢ ﺑﺎﺷﺪ )ﻣﺜﻞ ﻳﮏ ﺗﺼﻮﻳﺮ‬
‫ﮔﺮﺍﻓﻴﮑﻲ( ﺁﻧﮕﺎﻩ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺣﺎﻓﻈﻪ ﺑﻪ ﻣﻴﺰﺍﻥ ﺩﻭﺑﺮﺍﺑﺮ ﻣﺼﺮﻑ‬
‫ﺷﻮﺩ؛ ﺑﺨﺸﻲ ﺑﺮﺍﻱ ﺁﺭﮔﻮﻣﺎﻥ ﺍﺻﻠﻲ ﻭ ﺑﺨﺸﻲ ﺩﻳﮕﺮ ﺑﺮﺍﻱ ﻧﺴﺨﻪ ﻣﺤﻠﻲ ﮐﻪ ﺩﺭ ﺗﺎﺑﻊ ﺑﻪ ﮐﺎﺭ‬
‫ﻣﻲﺭﻭﺩ‪ .‬ﺣﺎﻝ ﺍﮔﺮ ﺍﻳﻦ ﺷﻲﺀ ﺣﺠﻴﻢ ﺭﺍ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﮐﻨﻴﻢ ﺩﻳﮕﺮ ﻧﺴﺦۀ‬
‫ﻣﺤﻠﻲ ﺳﺎﺧﺘﻪ ﻧﻤﻲﺷﻮﺩ ﻭ ﺣﺎﻓﻈﻪﺍﻱ ﻫﻢ ﻫﺪﺭ ﻧﻤﻲﺭﻭﺩ‪ .‬ﺍﻣﺎ ﺍﻳﻦ ﮐﺎﺭ ﻳﮏ ﻋﻴﺐ ﺑﺰﺭﮒ ﺩﺍﺭﺩ‪:‬‬
‫ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺭﺟﺎﻉ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ‪ .‬ﺍﮔﺮ ﺗﺎﺑﻊ ﻧﻤﻲﺑﺎﻳﺴﺖ ﭘﺎﺭﺍﻣﺘﺮ ﻣﺬﮐﻮﺭ‬
‫ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﻣﺨﺎﻃﺮﻩﺁﻣﻴﺰ ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪.‬‬
‫ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻋﻴﺐ ﻣﺬﮐﻮﺭ ﺑﺮﻃﺮﻑ ﺷﻮﺩ ﻭ ﺷﻲﺀ ﺍﺻﻠﻲ ﺍﺯ ﺗﻐﻴﻴﺮﺍﺕ ﻧﺎﺧﻮﺍﺳﺘﻪ ﺩﺭﻭﻥ‬
‫ﺗﺎﺑﻊ ﻣﺼﻮﻥ ﺑﺎﺷﺪ‪ C++ ،‬ﺭﻭﺵ ﺳﻮﻣﻲ ﺭﺍ ﺑﺮﺍﻱ ﺍﺭﺳﺎﻝ ﺁﺭﮔﻮﻣﺎﻥ ﭘﻴﺸﻨﻬﺎﺩ ﻣﻲﮐﻨﺪ‪ :‬ﺍﺭﺳﺎﻝ ﺍﺯ‬
‫ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ‪ .1‬ﺍﻳﻦ ﺭﻭﺵ ﻣﺎﻧﻨﺪ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﻓﺮﻕ ﮐﻪ ﺗﺎﺑﻊ‬
‫ﻧﻤﻲﺗﻮﺍﻧﺪ ﻣﺤﺘﻮﻳﺎﺕ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺭﺟﺎﻉ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﻧﻤﺎﻳﺪ ﻭ ﻓﻘﻂ ﺍﺟﺎﺯۀ ﺧﻮﺍﻧﺪﻥ ﺁﻥ ﺭﺍ ﺩﺍﺭﺩ‪.‬‬
‫ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﭘﺎﺭﺍﻣﺘﺮﻱ ﺭﺍ ﺍﺯ ﻧﻮﻉ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺍﻋﻼﻥ ﮐﻨﻴﻢ ﺑﺎﻳﺪ ﻋﺒﺎﺭﺕ ‪ const‬ﺭﺍ ﺑﻪ‬
‫ﺍﺑﺘﺪﺍﻱ ﺍﻋﻼﻥ ﺁﻥ ﺍﺿﺎﻓﻪ ﻧﻤﺎﻳﻴﻢ‪.‬‬

‫‪1 – Constant reference‬‬


‫‪159‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫* ﻣﺜﺎﻝ ‪ 5‐15‬ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ‬


‫ﺳﻪ ﻃﺮﻳﻘﻪ ﺍﺭﺳﺎﻝ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺭ ﺗﺎﺑﻊ ﺯﻳﺮ ﺑﻪ ﮐﺎﺭ ﺭﻓﺘﻪ ﺍﺳﺖ‪:‬‬
‫)‪void f(int x, int& y, const int& z‬‬
‫;‪{ x += z‬‬
‫;‪y += z‬‬
‫" = ‪cout << "x = " << x << ", y = " << y << ", z‬‬
‫;‪<< z << endl‬‬
‫}‬

‫ﺩﺭ ﺗﺎﺑﻊ ﻓﻮﻕ ﺍﻭﻟﻴﻦ ﭘﺎﺭﺍﻣﺘﺮ ﻳﻌﻨﻲ ‪ 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‬ﺩﺭ ﺍﻋﻼﻥ ﻭ ﺗﻌﺮﻳﻒ ﺁﻥ ﻗﻴﺪ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐16‬ﺗﺎﺑﻊ )(‪ cube‬ﺑﻪ ﺷﮑﻞ ﺑﻲﻭﺍﺳﻄﻪ‬


‫ﺍﻳﻦ ﻫﻤﺎﻥ ﺗﺎﺑﻊ )(‪ cube‬ﻣﺜﺎﻝ ‪ 5‐3‬ﺍﺳﺖ‪:‬‬
‫)‪inline int cube(int x‬‬
‫‪{ // returns cube of x:‬‬
‫;‪return x*x*x‬‬
‫}‬

‫ﺗﻨﻬﺎ ﺗﻔﺎﻭﺕ ﺍﻳﻦ ﺍﺳﺖ ﻛﻪ ﻛﻠﻢۀ ﻛﻠﻴﺪﻱ ‪ 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‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐17‬ﭼﻨﺪﺷﮑﻠﻲ ﺗﺎﺑﻊ )(‪max‬‬


‫ﺩﺭ ﻣﺜﺎﻝ ‪ 5‐3‬ﺗﺎﺑﻊ )(‪ max‬ﺭﺍ ﺗﻌﺮﻳﻒ ﮐﺮﺩﻳﻢ‪ .‬ﺣﺎﻻ ﺗﻮﺍﺑﻊ ﺩﻳﮕﺮﻱ ﺑﺎ ﻫﻤﺎﻥ ﻧﺎﻡ ﻭﻟﻲ‬
‫ﺷﮑﻠﻲ ﻣﺘﻔﺎﻭﺕ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﻴﻢ ﻭ ﻫﻤﻪ ﺭﺍ ﺩﺭ ﻳﮏ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﻳﻢ‪:‬‬
‫;)‪int max(int, int‬‬
‫;)‪int max(int, int, int‬‬
‫;)‪int max(double, double‬‬

‫)(‪int main‬‬
‫<< " " << )‪{ cout << max(99,77) << " " << max(55,66,33‬‬
‫;)‪max(44.4,88.8‬‬
‫}‬

‫)‪int max(int x, int y‬‬


‫‪{ // returns the maximum of the two given integers:‬‬
‫;)‪return (x > y ? x : y‬‬
‫}‬

‫)‪int max(int x, int y, int z‬‬


‫‪{ // returns the maximum of the three given integers:‬‬
‫)‪int m = (x > y ? x : y); // m = max(x , y‬‬
‫;)‪return ( z > m ? z : m‬‬
‫}‬

‫)‪int max(double x, double y‬‬


‫‪{ // return the maximum of the two given doubles:‬‬
‫;)‪return (x>y ? x : y‬‬
‫}‬
‫‪99 66 88.0‬‬

‫ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺳﻪ ﺗﺎﺑﻊ ﺑﺎ ﻧﺎﻡ )(‪ 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‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺑﻪ ﻃﻮﺭ ﻏﻴﺮﻣﻌﻤﻮﻝ ﺧﺎﺗﻤﻪ ﺩﻫﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐18‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ ‪ return‬ﺑﺮﺍﻱ ﭘﺎﻳﺎﻥ ﺩﺍﺩﻥ ﺑﻪ ﻳﻚ ﺑﺮﻧﺎﻣﻪ‬


‫)(‪int main‬‬
‫‪{ // prints the quotient of two input integers:‬‬
‫;‪int n, d‬‬
‫;" ‪cout << "Enter two integers:‬‬
‫;‪cin >> n >> d‬‬
‫;‪if (d = = 0) return 0‬‬
‫;‪cout << n << "/" << d << " = " << n/d << endl‬‬
‫}‬
‫‪Enter two integers: 99 17‬‬
‫‪99/17 = 5‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪164‬‬

‫ﺍﮔﺮ ﻛﺎﺭﺑﺮ ﺑﺮﺍﻱ ﻭﺭﻭﺩﻱ ﺩﻭﻡ ‪ 0‬ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﺪ‪ ،‬ﺑﺮﻧﺎﻣﻪ ﺑﺪﻭﻥ ﭼﺎﭖ ﺧﺮﻭﺟﻲ ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ‪:‬‬
‫‪Enter two integers: 99 0‬‬

‫ﺩﺳﺘﻮﺭ ‪ return‬ﺗﺎﺑﻊ ﻓﻌﻠﻲ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ ﻭ ﮐﻨﺘﺮﻝ ﺭﺍ ﺑﻪ ﻓﺮﺍﺧﻮﺍﻧﻨﺪﻩ‬


‫ﺑﺎﺯﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﺳﺖ ﮐﻪ ﺍﺟﺮﺍﻱ ﺩﺳﺘﻮﺭ ‪ return‬ﺩﺭ ﺗﺎﺑﻊ )(‪ main‬ﮐﻞ‬
‫ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‪.‬‬
‫ﭼﻬﺎﺭ ﺭﻭﺵ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﮐﻪ ﺑﺘﻮﺍﻧﻴﻢ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻏﻴﺮﻣﻌﻤﻮﻝ )ﻳﻌﻨﻲ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ‬
‫ﮐﻪ ﺍﺟﺮﺍ ﺑﻪ ﭘﺎﻳﺎﻥ ﺑﻠﻮﮎ ﺍﺻﻠﻲ ﺑﺮﺳﺪ( ﺧﺎﺗﻤﻪ ﺩﻫﻴﻢ‪:‬‬
‫‪ ‐ 1‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ ‪return‬‬
‫‪ ‐ 2‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ )(‪exit‬‬
‫‪ ‐ 3‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ )(‪abort‬‬
‫‪1‬‬
‫‪ – 4‬ﺍﻳﺠﺎﺩ ﻳﮏ ﺣﺎﻟﺖ ﺍﺳﺘﺜﻨﺎ‬
‫ﻃﺮﻳﻖۀ ﺑﻪﮐﺎﺭﮔﻴﺮﻱ ﺗﺎﺑﻊ )(‪ exit‬ﺩﺭ ﻣﺜﺎﻝ ﺯﻳﺮ ﺷﺮﺡ ﺩﺍﺩﻩ ﺷﺪﻩ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﺭ‬
‫ﺳﺮﻓﺎﻳﻞ >‪ <cstdlib‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺗﺎﺑﻊ )(‪ exit‬ﺑﺮﺍﻱ ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ ﺑﻪ ﮐﻞ‬
‫ﺑﺮﻧﺎﻣﻪ ﺩﺭ ﻫﺮ ﺗﺎﺑﻌﻲ ﻏﻴﺮ ﺍﺯ ﺗﺎﺑﻊ )(‪ main‬ﻣﻔﻴﺪ ﺍﺳﺖ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺗﻮﺟﻪ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐19‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ )(‪ exit‬ﺑﺮﺍﻱ ﭘﺎﻳﺎﻥ ﺩﺍﺩﻥ ﺑﻪ ﺑﺮﻧﺎﻣﻪ‬


‫>‪#include <cstdlib‬‬ ‫‪// defines the exit() function‬‬
‫>‪#include <iostream‬‬ ‫‪// defines thi cin and cout objects‬‬
‫;‪using namespace std‬‬
‫;)‪double reciprocal(double x‬‬

‫)(‪int main‬‬
‫;‪{ double x‬‬
‫;‪cin >> x‬‬
‫;)‪cout << reciprocal(x‬‬
‫}‬

‫)‪double reciprocal(double x‬‬


‫‪{ // returns the reciprocal of x:‬‬

‫‪1 – Exception‬‬
‫‪165‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫;)‪if (x = = 0) exit(1‬‬ ‫‪// terminate the program‬‬


‫;‪return 1.0/x‬‬
‫}‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺍﮔﺮ ﻛﺎﺭﺑﺮ ﻋﺪﺩ ‪ 0‬ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﺪ‪ ،‬ﺗﺎﺑﻊ )(‪ reciprocal‬ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ ﻭ‬
‫ﺑﺮﻧﺎﻣﻪ ﺑﺪﻭﻥ ﻫﻴﭻ ﻣﻘﺪﺍﺭ ﭼﺎﭘﻲ ﺑﻪ ﭘﺎﻳﺎﻥ ﻣﻲﺭﺳﺪ‪.‬‬

‫‪1‬‬
‫‪ 5‐15‬ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﭘﻴﺶﻓﺮﺽ‬
‫ﺩﺭ ‪ C++‬ﻣﻲﺗﻮﺍﻥ ﺗﻌﺪﺍﺩ ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﻳﮏ ﺗﺎﺑﻊ ﺭﺍ ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺑﻪ ﺩﻟﺨﻮﺍﻩ ﺗﻐﻴﻴﺮ‬
‫ﺩﺍﺩ‪ .‬ﺍﻳﻦ ﺍﻣﺮ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﺍﺧﺘﻴﺎﺭﻱ ﻭ ﻣﻘﺎﺩﻳﺮ ﭘﻴﺶﻓﺮﺽ ﺍﻣﮑﺎﻥﭘﺬﻳﺮ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 5‐20‬ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﭘﻴﺶﻓﺮﺽ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺣﺎﺻﻞ ﭼﻨﺪ ﺟﻤﻠﻪﺍﻱ ﺩﺭﺟﻪ ﺳﻮﻡ ‪ a0 + a1 x + a2 x 2 + a3 x3‬ﺭﺍ ﭘﻴﺪﺍ‬
‫ﻣﻲﮐﻨﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺤﺎﺳﺐۀ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺍﺯ ﺍﻟﮕﻮﺭﻳﺘﻢ ﻫﻮﺭﻧﺮ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‪ .‬ﺑﻪ ﺍﻳﻦ ﺷﮑﻞ ﮐﻪ ﺑﺮﺍﻱ‬
‫ﮐﺎﺭﺍﻳﻲ ﺑﻴﺸﺘﺮ‪ ،‬ﻣﺤﺎﺳﺒﻪ ﺑﻪ ﺻﻮﺭﺕ ‪ a0 + (a1 + (a2 + a3 x) x) x‬ﺩﺳﺘﻪﺑﻨﺪﻱ ﻣﻲﺷﻮﺩ‪:‬‬
‫;)‪double p(double, double, double=0, double=0, double=0‬‬

‫)(‪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‬‬

‫ﻫﻤﭽﻨﻴﻦ ﻫﻨﮕﺎﻡ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ‪ ،‬ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﺫﮐﺮ ﺷﺪﻩ ﺑﻪ ﺗﺮﺗﻴﺐ ﺍﺯ ﭼﭗ ﺑﻪ ﺭﺍﺳﺖ‬


‫ﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﻨﺪ ﻭ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺑﻌﺪﻱ ﺑﺎ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﭘﺮ ﻣﻲﺷﻮﻧﺪ‪ .‬ﻣﺜﻼ ﺩﺭ ﺗﺎﺑﻊ‬
‫)(‪ p‬ﮐﻪ ﺩﺭ ﺑﺎﻻ ﻗﻴﺪ ﺷﺪ‪ ،‬ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ p(8.0,7,6‬ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﭘﺎﺭﺍﻣﺘﺮ ‪ x‬ﻣﻘﺪﺍﺭ‬
‫‪ 8.0‬ﺭﺍ ﺑﮕﻴﺮﺩ ﺳﭙﺲ ﭘﺎﺭﺍﻣﺘﺮ ‪ a0‬ﻣﻘﺪﺍﺭ ‪ 7‬ﺭﺍ ﺑﮕﻴﺮﺩ ﻭ ﺳﭙﺲ ﭘﺎﺭﺍﻣﺘﺮ ‪ a1‬ﻣﻘﺪﺍﺭ ‪ 6‬ﺭﺍ‬
‫ﺑﮕﻴﺮﺩ‪ .‬ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ‪ a2‬ﻭ ‪ a3‬ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽﺷﺎﻥ ﺭﺍ ﺧﻮﺍﻫﻨﺪ ﺩﺍﺷﺖ‪ .‬ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺭﺍ‬
‫ﻧﻤﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﻫﻢ ﺑﺰﻧﻴﻢ‪ .‬ﻣﺜﻼ ﻧﻤﻲﺗﻮﺍﻧﻴﻢ ﺗﺎﺑﻊ ﺭﺍ ﻃﻮﺭﻱ ﻓﺮﺍ ﺑﺨﻮﺍﻧﻴﻢ ﮐﻪ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ‪ x‬ﻭ‬
‫‪ a0‬ﻭ ‪ a3‬ﻣﺴﺘﻘﻴﻤﺎ ﻣﻘﺪﺍﺭ ﺑﮕﻴﺮﻧﺪ ﻭﻟﻲ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ‪ a1‬ﻭ ‪ a2‬ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽﺷﺎﻥ ﺭﺍ‬
‫ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ‪.‬‬
‫‪167‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬
‫‪ – 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‬‬

‫‪ – 8‬ﭼﻪ ﺯﻣﺎﻧﻲ ﻳﮏ ﺁﺭﮔﻮﻣﺎﻥ »ﺧﻮﺍﻧﺪﻧﻲ‐ﻧﻮﺷﺘﻨﻲ« ﺍﺳﺖ؟‬


‫ﺍﻟﻒ – ﻭﻗﺘﻲ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺍﺭﺳﺎﻝ ﺷﻮﺩ‬
‫ﺏ – ﻭﻗﺘﻲ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺍﺭﺳﺎﻝ ﺷﻮﺩ‬
‫ﺝ – ﻭﻗﺘﻲ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﺷﻮﺩ‬
‫ﺩ – ﻭﻗﺘﻲ ﺑﺎ ﭘﻴﺸﻮﻧﺪ ‪ const‬ﺍﻋﻼﻥ ﺷﻮﺩ‬
‫‪ – 9‬ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ – ﻓﻘﻂ ﻳﮏ ﻣﻘﺪﺍﺭ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩ ﻭ ﺗﺎﺑﻊ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﻳﮏ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺎﺯﮔﺮﺩﺍﻧﺪ‬
‫ﺏ – ﻓﻘﻂ ﻳﮏ ﻣﻘﺪﺍﺭ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩ ﻭﻟﻲ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺎﺯﮔﺮﺩﺍﻧﺪ‬
‫ﺝ – ﭼﻨﺪ ﻣﻘﺪﺍﺭ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩ ﻭﻟﻲ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﻓﻘﻂ ﻳﮏ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺎﺯﮔﺮﺩﺍﻧﺪ‬
‫ﺩ – ﭼﻨﺪ ﻣﻘﺪﺍﺭ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩ ﻭ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺎﺯﮔﺮﺩﺍﻧﺪ‬
‫‪ – 10‬ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﻳﮏ ﺗﺎﺑﻊ ﺑﻪ ﺷﮑﻞ ﺑﻲﻭﺍﺳﻄﻪ ﺍﺯ ﭼﻪ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ؟‬
‫ﺩ – ‪int‬‬ ‫ﺝ – ‪void‬‬ ‫ﺍﻟﻒ – ‪ const‬ﺏ – ‪inline‬‬
‫‪ – 11‬ﮐﺪﺍﻡ ﻋﺒﺎﺭﺕ ﺩﺭ ﺭﺍﺑﻄﻪ ﺑﺎ ﭼﻨﺪﺷﮑﻠﻲ ﺗﻮﺍﺑﻊ ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ – ﻳﮏ ﺗﺎﺑﻊ ﭼﻨﺪﺷﮑﻠﻲ ﺑﺎﻳﺪ ﻧﺎﻡﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ ﻭﻟﻲ ﺑﺪﻧﻪﻫﺎﻱ ﻳﮑﺴﺎﻥ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‬
‫ﺏ – ﻳﮏ ﺗﺎﺑﻊ ﭼﻨﺪﺷﮑﻠﻲ ﺑﺎﻳﺪ ﻧﺎﻡﻫﺎﻱ ﻳﮑﺴﺎﻥ ﻭﻟﻲ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‬
‫ﺝ – ﻳﮏ ﺗﺎﺑﻊ ﭼﻨﺪﺷﮑﻠﻲ ﺑﺎﻳﺪ ﻧﺎﻡﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ ﻭﻟﻲ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﻳﮑﺴﺎﻥ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‬
‫ﺩ – ﻳﮏ ﺗﺎﺑﻊ ﭼﻨﺪﺷﮑﻠﻲ ﺑﺎﻳﺪ ﻧﺎﻡﻫﺎﻱ ﻳﮑﺴﺎﻥ ﻭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﻳﮑﺴﺎﻥ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‬
‫‪ – 12‬ﺍﮔﺮ ﺗﺎﺑﻊ ‪ f‬ﺑﻪ ﺷﮑﻞ )‪ void f(int k, int x=0, int y=1‬ﺍﻋﻼﻥ‬
‫ﺷﺪﻩ ﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ‪:‬‬
‫ﺍﻟﻒ – ﭘﺎﺭﺍﻣﺘﺮ ‪ k‬ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﻧﻴﺴﺖ‪.‬‬
‫ﺏ – ﭘﺎﺭﺍﻣﺘﺮ ‪ x‬ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ‪ 0‬ﺍﺳﺖ‪.‬‬
‫ﺝ – ﭘﺎﺭﺍﻣﺘﺮ ‪ y‬ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ‪ 1‬ﺍﺳﺖ‪.‬‬
‫ﺩ – ﻫﻤﻪ ﻣﻮﺍﺭﺩ ﻓﻮﻕ ﺻﺤﻴﺢ ﺍﺳﺖ‪.‬‬
‫‪ – 13‬ﭼﺮﺍ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺑﺰﺭﮒ ﺗﻌﺮﻳﻒ ﺗﻮﺍﺑﻊ ﺭﺍ ﺩﺭ ﻓﺎﻳﻞ ﺟﺪﺍﮔﺎﻧﻪﺍﻱ ﻗﺮﺍﺭ ﻣﻲﺩﻫﻨﺪ؟‬
‫ﺍﻟﻒ – ﺑﻪ ﺍﻳﻦ ﺩﻟﻴﻞ ﮐﻪ ﻣﺪﻳﺮﻳﺖ ﺑﺮﻧﺎﻣﻪ ﺁﺳﺎﻥ ﺷﻮﺩ‬
‫ﺏ – ﺑﻪ ﺍﻳﻦ ﺩﻟﻴﻞ ﮐﻪ ﺍﺻﻞ ﭘﻨﻬﺎﻥﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ ﺭﻋﺎﻳﺖ ﺷﻮﺩ‬
‫ﺝ – ﺑﻪ ﺍﻳﻦ ﺩﻟﻴﻞ ﮐﻪ ﺑﺘﻮﺍﻥ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺩﻳﮕﺮ ﻫﻢ ﺍﺯ ﺁﻥ ﺗﻮﺍﺑﻊ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‬
‫‪169‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫ﺩ – ﻫﻤﻪ ﻣﻮﺍﺭﺩ ﻓﻮﻕ‬


‫‪ – 14‬ﺍﮔﺮ ﺗﺎﺑﻊ ‪ g‬ﺑﻪ ﺷﮑﻞ )‪ void g(int m, int& n‬ﺍﻋﻼﻥ ﺷﺪﻩ ﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ‪:‬‬
‫ﺍﻟﻒ – ﭘﺎﺭﺍﻣﺘﺮ ‪ m‬ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﺷﺪﻩ‬
‫ﺏ – ﭘﺎﺭﺍﻣﺘﺮ ‪ n‬ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﺷﺪﻩ‬
‫ﺝ – ﭘﺎﺭﺍﻣﺘﺮ ‪ m‬ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺍﺭﺳﺎﻝ ﺷﺪﻩ‬
‫ﺩ – ﭘﺎﺭﺍﻣﺘﺮ ‪ n‬ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺍﺭﺳﺎﻝ ﺷﺪﻩ‬
‫‪ – 15‬ﺍﮔﺮ ﺗﺎﺑﻊ ﺳﻮﺍﻝ ‪ 14‬ﺑﻪ ﺷﮑﻞ ;)‪ g(x, y‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ ﺁﻧﮕﺎﻩ ﮐﺪﺍﻡ ﻋﺒﺎﺭﺕ‬
‫ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ – ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ ‪ x‬ﺭﺍ ﻣﻲﺗﻮﺍﻧﺪ ﺗﻐﻴﻴﺮ ﺩﻫﺪ‬
‫ﺏ – ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ ‪ y‬ﺭﺍ ﻣﻲﺗﻮﺍﻧﺪ ﺗﻐﻴﻴﺮ ﺩﻫﺪ‬
‫ﺝ – ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ ‪ x‬ﻭ ﻣﻘﺪﺍﺭ ‪ y‬ﺭﺍ ﻣﻲﺗﻮﺍﻧﺪ ﺗﻐﻴﻴﺮ ﺩﻫﺪ‬
‫ﺩ – ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ ﻫﻴﭻ ﮐﺪﺍﻡ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺗﻐﻴﻴﺮ ﺩﻫﺪ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪170‬‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪ ‐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‬‬ ‫‪1‬‬‫‪6‬‬ ‫‪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‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ ‪ /‬ﺗﻮاﺑﻊ‬

‫‪ ‐18‬ﺗﺎﺑﻌﻲ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ ﺑﺰﺭﮒﺗﺮﻳﻦ ﻣﻘﺴﻮﻡﻋﻠﻴﻪ‬


‫ﻣﺸﺘﺮﻙ )ﻣﺴﺄﻝۀ ‪ (17‬ﮐﻮﭼﮏﺗﺮﻳﻦ ﻣﻀﺮﺏ ﻣﺸﺘﺮﮎ ﺩﻭ ﻋﺪﺩ ﺻﺤﻴﺢ ﻣﺜﺒﺖ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ‪.‬‬
‫‪ ‐19‬ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )(‪ power‬ﮐﻪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ‪:‬‬
‫;)‪double power(double x, int p‬‬
‫ﺍﻳﻦ ﺗﺎﺑﻊ ‪ x‬ﺭﺍ ﺑﻪ ﺗﻮﺍﻥ ‪ p‬ﻣﻲﺭﺳﺎﻧﺪ ﮐﻪ ‪ p‬ﻣﻲﺗﻮﺍﻧﺪ ﻫﺮ ﻋﺪﺩ ﺻﺤﻴﺤﻲ ﺑﺎﺷﺪ‪ .‬ﺍﺯ ﺍﻟﮕﻮﺭﻳﺘﻤﻲ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﺪ ﮐﻪ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺐۀ ‪ x 20‬ﻣﻘﺪﺍﺭ ‪ x‬ﺭﺍ ‪ 20‬ﻣﺮﺗﺒﻪ ﺩﺭ ﺧﻮﺩﺵ ﺿﺮﺏ ﻣﻲﮐﻨﺪ‪.‬‬
‫‪ ‐20‬ﻳﻮﻧﺎﻧﻲﻫﺎﻱ ﺑﺎﺳﺘﺎﻥ ﺍﻋﺪﺍﺩ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ﻫﻨﺪﺳﻲ ﻃﺒﻘﻪﺑﻨﺪﻱ ﻣﻲﻛﺮﺩﻧﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺑﻪ‬
‫ﻳﻚ ﻋﺪﺩ ﻣﺜﻠﺜﻲ ﻣﻲﮔﻔﺘﻨﺪ ﺍﮔﺮ ﺁﻥ ﻋﺪﺩ ﻣﻲﺗﻮﺍﻧﺴﺖ‬
‫‪n=1‬‬ ‫‪n=3‬‬ ‫‪n=6‬‬
‫ﺑﺎ ﺭﻳﮓﻫﺎ ﺩﺭ ﻳﻚ ﺗﻘﺎﺭﻥ ﻣﺜﻠﺜﻲ ﭼﻴﺪﻩ ﺷﻮﺩ‪ .‬ﺩﻩ‬
‫ﻋﺪﺩ ﻣﺜﻠﺜﻲ ﺍﻭﻝ ﺍﻋﺪﺍﺩ ‪ 0‬ﻭ ‪ 1‬ﻭ ‪ 3‬ﻭ ‪ 6‬ﻭ ‪10‬‬
‫ﻭ‪ 15‬ﻭ ‪ 21‬ﻭ ‪ 28‬ﻭ ‪ 36‬ﻭ ‪ 45‬ﻫﺴﺘﻨﺪ‪ .‬ﺗﺎﺑﻊ ﺑﻮﻟﻲ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪ .‬ﺍﮔﺮ‬
‫‪ n‬ﻳﮏ ﻋﺪﺩ ﻣﺜﻠﺜﻲ ﺑﺎﺷﺪ ﺍﻳﻦ ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ ‪ 1‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭﮔﺮﻧﻪ ‪ 0‬ﺑﺮﮔﺸﺖ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪:‬‬
‫;)‪int isTriangular(int n‬‬
‫‪ ‐21‬ﺗﺎﺑﻊ )(‪ issquare‬ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ ﺗﺸﺨﻴﺺ ﻣﻲﺩﻫﺪ ﮐﻪ ﺁﻳﺎ‬
‫ﻋﺪﺩ ﺩﺍﺩﻩ ﺷﺪﻩ ﻳﮏ ﻋﺪﺩ ﻣﺮﺑﻌﻲ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ‪:‬‬
‫;)‪int isSquare(int n‬‬
‫‪n=1‬‬ ‫‪n=4‬‬ ‫‪n=9‬‬ ‫ﺍﻭﻟﻴﻦ ﺩﻩ ﻋﺪﺩ ﻣﺮﺑﻌﻲ ﺍﻋﺪﺍﺩ ‪ 0‬ﻭ ‪ 1‬ﻭ ‪ 4‬ﻭ ‪ 9‬ﻭ‬
‫‪ 16‬ﻭ ‪ 25‬ﻭ ‪ 36‬ﻭ ‪ 49‬ﻭ ‪ 64‬ﻭ ‪ 81‬ﻫﺴﺘﻨﺪ‪.‬‬
‫‪ ‐22‬ﺗﺎﺑﻊ )(‪ ComputeCircle‬ﻛﻪ ﻣﺴﺎﺣﺖ ‪ a‬ﻭ ﻣﺤﻴﻂ ‪ c‬ﻳﻚ ﺩﺍﻳﺮﻩ ﺑﺎ ﺷﻌﺎﻉ ﺩﺍﺩﻩ‬
‫ﺷﺪۀ ‪ r‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪ ،‬ﻧﻮﺷﺘﻪ ﻭﺍﻣﺘﺤﺎﻥ ﻛﻨﻴﺪ‪:‬‬
‫;)‪void computeCircle(float& a, float& c, float r‬‬
‫‪ ‐23‬ﺗﺎﺑﻊ )(‪ ComputeTriangle‬ﻛﻪ ﻣﺴﺎﺣﺖ ‪ a‬ﻭ ﻣﺤﻴﻂ ‪ p‬ﺍﺯ ﻳﻚ ﻣﺜﻠﺚ ﺑﺎ‬
‫ﺍﺿﻼﻉ ﺑﻪ ﻃﻮﻝ ‪ a‬ﻭ ‪ b‬ﻭ ‪ c‬ﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻣﻲﻧﻤﺎﻳﺪ‪ ،‬ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪:‬‬
‫;)‪void computeTriangle(float& a, float& p, float a, float b, float c‬‬
‫‪ ‐24‬ﺗﺎﺑﻊ )(‪ computeSphere‬ﻛﻪ ﺣﺠﻢ ‪ v‬ﻭ ﻣﺴﺎﺣﺖ ﺳﻄﺢ ‪ s‬ﺭﺍ ﺑﺮﺍﻱ ﻳﮏ ﻛﺮﻩ‬
‫ﺑﺎ ﺷﻌﺎﻉ ﺩﺍﺩﻩ ﺷﺪۀ ‪ r‬ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪ ،‬ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪:‬‬
‫;)‪void ComputeSphere(float& v, float& s, float r‬‬
‫ﻓﺼﻞ ﺷﺸﻢ‬
‫»ﺁﺭﺍﻳﻪﻫﺎ«‬

‫‪ 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‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐1‬ﺩﺳﺘﻴﺎﺑﻲ ﻣﺴﺘﻘﻴﻢ ﺑﻪ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ‬


‫ﺑﺮﻧﺎﻡۀ ﺳﺎﺩۀ ﺯﻳﺮ ﻳﮏ ﺁﺭﺍﻱۀ ﺳﻪ ﻋﻨﺼﺮﻱ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﻭ ﺳﭙﺲ ﻣﻘﺎﺩﻳﺮﻱ ﺭﺍ ﺩﺭ‬
‫ﺁﻥ ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻭ ﺳﺮﺍﻧﺠﺎﻡ ﺍﻳﻦ ﻣﻘﺎﺩﻳﺮ ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;]‪{ int a[3‬‬
‫;‪a[2] = 55‬‬
‫;‪a[0] = 11‬‬
‫;‪a[1] = 33‬‬
‫;‪cout << "a[0] = " << a[0] << endl‬‬
‫;‪cout << "a[1] = " << a[1] << andl‬‬
‫;‪cout << "a[2] = " << a[2] << endl‬‬
‫}‬
‫‪a[0] = 11‬‬
‫‪a[1] = 33‬‬
‫‪a[2] = 55‬‬

‫ﺧﻂ ﺩﻭﻡ‪ ،‬ﻳﮏ ﺁﺭﺍﻱۀ ﺳﻪ ﻋﻨﺼﺮﻱ ﺍﺯ ﻧﻮﻉ ‪ int‬ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‪ .‬ﺳﻪ ﺧﻂ ﺑﻌﺪﻱ‪ ،‬ﻣﻘﺎﺩﻳﺮﻱ‬
‫ﺭﺍ ﺑﻪ ﺍﻳﻦ ﺳﻪ ﻋﻨﺼﺮ ﺗﺨﺼﻴﺺ ﻣﻲﺩﻫﺪ ﻭ ﺳﻪ ﺧﻂ ﺁﺧﺮ ﻫﻢ ﻣﻘﺪﺍﺭ ﻫﺮ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﭼﺎﭖ‬
‫ﻣﻲﮐﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐2‬ﭼﺎﭖ ﺗﺮﺗﻴﺒﻲ ﻋﻨﺎﺻﺮ ﻳﻚ ﺁﺭﺍﻳﻪ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﭘﻨﺞ ﻋﺪﺩ ﺭﺍ ﻣﻲﺧﻮﺍﻧﺪ ﻭ ﺳﭙﺲ ﺁﻥﻫﺎ ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﻣﻌﻜﻮﺱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ const int SIZE=5; // defines the size N for 5 elements‬‬
‫;]‪double a[SIZE‬‬ ‫‪// declares the array's elements as type‬‬ ‫‪double‬‬
‫;"‪cout << "Enter " << SIZE << " numbers:\t‬‬
‫)‪for (int i=0; i<SIZE; i++‬‬
‫;]‪cin >> a[i‬‬
‫;" ‪cout << "In reverse order:‬‬
‫)‪for (int i=SIZE-1; i>=0; i--‬‬
‫;]‪cout << "\t" << a[i‬‬
‫}‬
‫‪Enter 5 numbers:‬‬ ‫‪11.11‬‬ ‫‪33.33‬‬ ‫‪55.55‬‬ ‫‪77.77‬‬ ‫‪99.99‬‬
‫‪In reverse order:‬‬ ‫‪99.99‬‬ ‫‪77.77‬‬ ‫‪55.55‬‬ ‫‪33.33‬‬ ‫‪11.11‬‬
‫‪177‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫ﺩﻭﻣﻴﻦ ﺧﻂ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺛﺎﺑﺘﻲ ﺑﻪ ﻧﺎﻡ ‪ 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‬ﻭ ﺑﺎ ﺗﻌﺪﺍﺩ ﺳﻪ ﻋﻨﺼﺮ ﺍﻋﻼﻥ ﮐﺮﺩﻩ ﻭ ﻫﺮ ﺳﻪ‬
‫ﻋﻨﺼﺮ ﺭﺍ ﺑﺎ ﻣﻘﺪﺍﺭﻫﺎﻱ ﺩﺭﻭﻥ ﻓﻬﺮﺳﺖ‪ ،‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﮐﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐3‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺁﺭﺍﻳﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪178‬‬

‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﺁﺭﺍﻱۀ ‪ 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‬‬ ‫ﻫﻨﮕﺎﻡ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﺮﺍﻱ ﺍﻋﻼﻥ ﺁﺭﺍﻳﻪ‪،‬‬


‫‪0‬‬ ‫‪55.5‬‬ ‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﻫﻢ ﺑﻪ ﻃﻮﺭ ﺻﺮﻳﺢ ﺫﮐﺮ ﮐﻨﻴﻢ‪ .‬ﺩﺭ ﺍﻳﻦ‬
‫‪1‬‬ ‫‪66.6‬‬
‫‪2‬‬ ‫‪77.7‬‬ ‫ﺻﻮﺭﺕ ﺍﮔﺮ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺫﮐﺮ ﺷﺪﻩ ﺍﺯ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﻣﻮﺟﻮﺩ ﺩﺭ‬
‫‪3‬‬ ‫‪0.0‬‬
‫‪4‬‬ ‫‪0.0‬‬
‫ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﻴﺸﺘﺮ ﺑﺎﺷﺪ‪ ،‬ﺧﺎﻧﻪﻫﺎﻱ ﺑﻌﺪﻱ ﺑﺎ ﻣﻘﺪﺍﺭ ﺻﻔﺮ ﭘﺮ‬
‫‪5‬‬ ‫‪0.0‬‬ ‫ﻣﻲﺷﻮﻧﺪ‪:‬‬
‫‪6‬‬ ‫‪0.0‬‬
‫;} ‪float a[7] = { 55.5, 66.6, 77.7‬‬
‫‪179‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫ﺍﻋﻼﻥ ﺑﺎﻻ ﺁﺭﺍﻱۀ ‪ a‬ﺭﺍ ﺑﺎ ﻫﻔﺖ ﻋﻨﺼﺮ ﺍﺯ ﻧﻮﻉ ‪ float‬ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‪ .‬ﺳﻪ ﻋﻨﺼﺮ ﺍﻭﻝ ﺍﻳﻦ‬
‫ﺁﺭﺍﻳﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻓﻬﺮﺳﺖ ﻣﺬﮐﻮﺭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﺷﻮﻧﺪ ﻭ ﺩﺭ ﭼﻬﺎﺭ ﻋﻨﺼﺮ ﺑﺎﻗﻲﻣﺎﻧﺪﻩ ﻣﻘﺪﺍﺭ‬
‫ﺻﻔﺮ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐4‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﻳﻚ ﺁﺭﺍﻳﻪ ﺑﺎ ﺻﻔﺮﻫﺎﻱ ﻣﺘﻮﺍﻟﻲ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﺁﺭﺍﻳﻪﺍﻱ ﺑﻪ ﻧﺎﻡ ‪ a‬ﺭﺍ ﺍﻋﻼﻥ ﻭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩﻩ ﻭ ﺳﭙﺲ ﻣﻘﺪﺍﺭ ﻋﻨﺎﺻﺮ ﺁﻥ‬
‫ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;} ‪{ float a[6] = { 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[3‬‬ ‫=‬ ‫‪0‬‬
‫]‪a[4‬‬ ‫=‬ ‫‪0‬‬
‫]‪a[5‬‬ ‫=‬ ‫‪0‬‬

‫ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺗﻌﺪﺍﺩ ﻣﻘﺎﺩﻳﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺒﺎﻳﺪ ﺍﺯ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ‬
‫ﺑﻴﺸﺘﺮ ﺑﺎﺷﺪ‪:‬‬
‫;} ‪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‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐5‬ﻳﻚ ﺁﺭﺍﻱۀ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﺁﺭﺍﻱۀ ‪ a‬ﺭﺍ ﺍﻋﻼﻥ ﻣﻲﮐﻨﺪ ﻭﻟﻲ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﻤﻲﻛﻨﺪ‪ .‬ﺑﺎ ﻭﺟﻮﺩ ﺍﻳﻦ‪ ،‬ﻣﻘﺎﺩﻳﺮ‬
‫ﻣﻮﺟﻮﺩ ﺩﺭ ﺁﻥ ﺭﺍ ﭼﺎﭖ ﻣﻲﻛﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫‪{ const int SIZE=4; // defines the size N for 4 elements‬‬
‫;]‪float a[SIZE‬‬ ‫‪// declares the array's elements as float‬‬
‫)‪for (int i=0; i<SIZE; i++‬‬
‫;‪cout << "\ta[" << i << "] = " << a[i] << endl‬‬
‫}‬
‫]‪a[0‬‬ ‫=‬ ‫‪6.01838e-39‬‬
‫]‪a[1‬‬ ‫=‬ ‫‪9.36651e-39‬‬
‫]‪a[2‬‬ ‫=‬ ‫‪6.00363e-39‬‬
‫]‪a[3‬‬ ‫=‬ ‫‪0‬‬

‫ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﻣﻘﺎﺩﻳﺮ ﺩﺭﻭﻥ ﻳﻚ ﺁﺭﺍﻱۀ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ ﻣﻤﻜﻦ ﺍﺳﺖ ﺻﻔﺮ ﺑﺎﺷﺪ ﻳﺎ ﻧﺒﺎﺷﺪ‪،‬‬
‫ﺑﺴﺘﻪ ﺑﻪ ﺍﻳﻦ ﮐﻪ ﺩﺭ ﺁﻥ ﻗﺴﻤﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﻗﺒﻼ ﭼﻪ ﺑﻮﺩﻩ ﺍﺳﺖ‪.‬‬
‫ﺁﺭﺍﻳﻪﻫﺎ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩ ﺍﻣﺎ ﻧﻤﻲﺗﻮﺍﻥ‬
‫ﻣﻘﺪﺍﺭ ﺁﻥﻫﺎ ﺭﺍ ﺑﻪ ﻳﮑﺪﻳﮕﺮ ﺗﺨﺼﻴﺺ ﺩﺍﺩ‪:‬‬
‫;} ‪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‬‬

‫‪ 6‐4‬ﺍﻳﻨﺪﻛﺲ ﺑﻴﺮﻭﻥ ﺍﺯ ﺣﺪﻭﺩ ﺁﺭﺍﻳﻪ‬


‫ﺩﺭ ﺑﻌﻀﻲ ﺍﺯ ﺯﺑﺎﻥﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‪ ،‬ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺍﺯ ﻣﺤﺪﻭﺩۀ ﺗﻌﺮﻳﻒ‬
‫ﺷﺪﻩ ﺑﺮﺍﻱ ﺁﻥ ﺑﻴﺸﺘﺮ ﺑﺎﺷﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺩﺭ ﭘﺎﺳﮑﺎﻝ ﺍﮔﺮ ﺁﺭﺍﻱۀ ‪ a‬ﺑﺎ ﺗﻌﺪﺍﺩ ﭘﻨﺞ ﻋﻨﺼﺮ ﺗﻌﺮﻳﻒ‬
‫ﺷﺪﻩ ﺑﺎﺷﺪ ﻭ ﺁﻧﮕﺎﻩ ]‪ a[7‬ﺩﺳﺘﻴﺎﺑﻲ ﺷﻮﺩ‪ ،‬ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﮐﺎﺭ ﻣﻲﺍﻓﺘﺪ‪ .‬ﺍﻳﻦ ﺳﻴﺴﺘﻢ ﺣﻔﺎﻇﺘﻲ ﺩﺭ‬
‫‪181‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫‪ C++‬ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻳﻨﺪﮐﺲ ﻳﮏ ﺁﺭﺍﻳﻪ ﻫﻨﮕﺎﻡ ﺩﺳﺘﻴﺎﺑﻲ‬
‫ﻣﻲﺗﻮﺍﻧﺪ ﺑﻴﺸﺘﺮ ﺍﺯ ﻋﻨﺎﺻﺮ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺑﺮﺍﻱ ﺁﻥ ﺑﺎﺷﺪ ﻭ ﺑﺎﺯ ﻫﻢ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﺧﻄﺎﻳﻲ‬
‫ﮔﺮﻓﺘﻪ ﺷﻮﺩ‪ ،‬ﺑﺮﻧﺎﻣﻪ ﺍﺩﺍﻣﻪ ﻳﺎﺑﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐6‬ﺗﺠﺎﻭﺯ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﺍﺯ ﻣﺤﺪﻭﺩۀ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺑﺮﺍﻱ ﺁﻥ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﮏ ﺧﻄﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺩﺍﺭﺩ؛ ﺑﻪ ﺑﺨﺸﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺩﺳﺘﻴﺎﺑﻲ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﺯ‬
‫ﻣﺤﺪﻭﺩۀ ﺁﺭﺍﻳﻪ ﺑﻴﺮﻭﻥ ﺍﺳﺖ‪:‬‬
‫)(‪int main‬‬
‫;‪{ const int SIZE=4‬‬
‫;} ‪float a[SIZE} = { 33.3, 44.4, 55.5, 66.6‬‬
‫)‪for (int i=0; i<7; i++‬‬ ‫!‪// ERROR: index is out of bounds‬‬
‫;‪cout << "\ta[" << i << "] = " << a[i] << endl‬‬
‫}‬
‫]‪a[0‬‬ ‫=‬ ‫‪33.3‬‬
‫]‪a[1‬‬ ‫=‬ ‫‪44.4‬‬
‫]‪a[2‬‬ ‫=‬ ‫‪55.5‬‬
‫]‪a[3‬‬ ‫=‬ ‫‪66.6‬‬
‫]‪a[4‬‬ ‫=‬ ‫‪5.60519e-45‬‬
‫]‪a[5‬‬ ‫=‬ ‫‪6.01888e-39‬‬
‫]‪a[6‬‬ ‫=‬ ‫‪6.01889e-39‬‬

‫ﺁﺭﺍﻳﻪﺍﻱ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺗﻌﺮﻳﻒ ﺷﺪﻩ‪ ،‬ﭼﻬﺎﺭ ﻋﻨﺼﺮ ﺩﺍﺭﺩ ﻭﻟﻲ ﺗﻼﺵ ﻣﻲﺷﻮﺩ ﺑﻪ ﻫﻔﺖ‬
‫ﻋﻨﺼﺮ ﺩﺳﺘﻴﺎﺑﻲ ﺷﻮﺩ‪ .‬ﺳﻪ ﻣﻘﺪﺍﺭ ﺁﺧﺮ ﻭﺍﻗﻌﺎ ﺟﺰﻭ ﺁﺭﺍﻳﻪ ﻧﻴﺴﺘﻨﺪ ﻭ ﻓﻘﻂ ﺳﻠﻮﻝﻫﺎﻳﻲ ﺍﺯ‬
‫ﺣﺎﻓﻈﻪﺍﻧﺪ ﮐﻪ ﺩﻗﻴﻘﺎ ﺑﻌﺪ ﺍﺯ ﻋﻨﺼﺮ ﭼﻬﺎﺭﻡ ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪﺍﻧﺪ‪ .‬ﺍﻳﻦ ﺳﻠﻮﻝﻫﺎ ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ‬
‫ﺯﺑﺎﻟﻪ ﻫﺴﺘﻨﺪ‪.‬‬
‫ﺍﮔﺮ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﺍﺯ ﻣﺤﺪﻭﺩۀ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺑﺮﺍﻱ ﺁﻥ ﺗﺠﺎﻭﺯ ﮐﻨﺪ‪ ،‬ﻣﻤﮑﻦ ﺍﺳﺖ‬
‫ﻧﺎﺧﻮﺍﺳﺘﻪ ﻣﻘﺪﺍﺭ ﺳﺎﻳﺮ ﻣﺘﻐﻴﺮﻫﺎ ﺩﺳﺖﮐﺎﺭﻱ ﺷﻮﻧﺪ ﻭ ﺍﻳﻦ ﺑﺎﻋﺚ ﺑﺮﻭﺯ ﻓﺎﺟﻌﻪ ﺷﻮﺩ‪ .‬ﺑﻪ ﻣﺜﺎﻝ‬
‫ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐7‬ﺍﺛﺮ ﻫﻤﺴﺎﻳﮕﻲ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺍﺯ ﺍﻳﻨﺪﮐﺲ ﺧﺎﺭﺝ ﺍﺯ ﻣﺤﺪﻭﺩﻩ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ ﻭ ﺍﻳﻦ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ‬
‫ﻣﻘﺪﺍﺭ ﻳﮏ ﻣﺘﻐﻴﺮ ﺑﻪ ﻃﻮﺭ ﻧﺎﺧﻮﺍﺳﺘﻪ ﺗﻐﻴﻴﺮ ﮐﻨﺪ‪:‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪182‬‬

‫)(‪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‬‬

‫ﻣﺘﻐﻴﺮ ‪ x‬ﺑﻌﺪ ﺍﺯ ﺁﺭﺍﻱۀ ‪ a‬ﺍﻋﻼﻥ ﺷﺪﻩ‪ ،‬ﭘﺲ ﻳﮏ‬


‫‪22.2‬‬ ‫ﺳﻠﻮﻝ ﭼﻬﺎﺭﺑﺎﻳﺘﻲ ﺑﻼﻓﺎﺻﻠﻪ ﺑﻌﺪ ﺍﺯ ﺩﻭﺍﺯﺩﻩ ﺑﺎﻳﺖ‬
‫‪a‬‬
‫‪0‬‬ ‫‪22.2‬‬ ‫ﺁﺭﺍﻳﻪ ﺑﻪ ﺁﻥ ﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﻭﻗﺘﻲ ﺑﺮﻧﺎﻣﻪ‬
‫‪44.4‬‬
‫‪1‬‬ ‫‪44.4‬‬
‫ﺗﻼﺵ ﻣﻲﮐﻨﺪ ﻣﻘﺪﺍﺭ ‪ 88.8‬ﺭﺍ ﺩﺭ ]‪ a[3‬ﻗﺮﺍﺭ‬
‫‪2‬‬ ‫‪66.6‬‬ ‫‪66.6‬‬
‫ﺩﻫﺪ )ﮐﻪ ﺟﺰﻭ ﺁﺭﺍﻳﻪ ﻧﻴﺴﺖ( ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﻪ ﺷﮑﻞ‬
‫‪x‬‬ ‫‪88.8‬‬ ‫‪88.8‬‬ ‫ﻧﺎﺧﻮﺍﺳﺘﻪ ﺩﺭ ‪ x‬ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﻧﺸﺎﻥ‬
‫ﻣﻲﺩﻫﺪ ﭼﻄﻮﺭ ﺍﻳﻦ ﺍﺗﻔﺎﻕ ﺩﺭ ﺣﺎﻓﻈﻪ ﺭﺥ ﻣﻲﺩﻫﺪ‪.‬‬
‫ﺍﻳﻦ ﺧﻄﺎ ﻳﮑﻲ ﺍﺯ ﻭﺣﺸﺖﻧﺎﮎﺗﺮﻳﻦ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍﺳﺖ ﺯﻳﺮﺍ ﻣﻤﮑﻦ ﺍﺳﺖ ﺍﺻﻼ‬
‫ﻧﺘﻮﺍﻧﻴﻢ ﻣﻨﺒﻊ ﺧﻄﺎ ﺭﺍ ﮐﺸﻒ ﮐﻨﻴﻢ‪ .‬ﺣﺘﻲ ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﻪ ﺍﻳﻦ ﺭﻭﺵ ﺩﺍﺩﻩﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻫﺎﻱ‬
‫ﺩﻳﮕﺮﻱ ﮐﻪ ﺩﺭ ﺣﺎﻝ ﮐﺎﺭﻧﺪ ﺭﺍ ﺧﺮﺍﺏ ﮐﻨﻴﻢ ﻭ ﺍﻳﻦ ﺑﺎﻋﺚ ﺍﻳﺠﺎﺩ ﺍﺧﺘﻼﻝ ﺩﺭ ﮐﻞ ﺳﻴﺴﺘﻢ ﺷﻮﺩ‪.‬‬
‫ﺑﻪ ﺍﻳﻦ ﺧﻄﺎ »ﺍﺛﺮ ﻫﻤﺴﺎﻳﮕﻲ« ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺍﻳﻦ ﻭﻇﻴﻒۀ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺍﺳﺖ ﮐﻪ ﺗﻀﻤﻴﻦ ﮐﻨﺪ‬
‫ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﻫﻴﭻﮔﺎﻩ ﺍﺯ ﻣﺤﺪﻭﺩۀ ﺁﻥ ﺧﺎﺭﺝ ﻧﺸﻮﺩ‪.‬‬
‫ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﻮﻉ ﺩﻳﮕﺮﻱ ﺍﺯ ﺧﻄﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪ :‬ﻭﻗﺘﻲ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ‬
‫ﺑﻴﺶ ﺍﺯ ﺣﺪ ﺑﺰﺭﮒ ﺑﺎﺷﺪ‪.‬‬
‫‪1‬‬
‫* ﻣﺜﺎﻝ ‪ 6‐8‬ﺍﻳﺠﺎﺩ ﺍﺳﺘﺜﻨﺎﻱ ﻣﺪﻳﺮﻳﺖ ﻧﺸﺪﻩ‬
‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺍﺯ ﻛﺎﺭ ﻣﻲﺍﻓﺘﺪ ﺯﻳﺮﺍ ﺍﻳﻨﺪﻛﺲ ﺁﺭﺍﻳﻪ ﺧﻴﻠﻲ ﺑﺰﺭﮒ ﺍﺳﺖ‪:‬‬
‫)(‪int main‬‬
‫;‪{ const int SIZE=4‬‬

‫‪1 – Unhandled exception‬‬


‫‪183‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫;} ‪float a[] = { 22.2, 44.4, 66.6‬‬


‫;‪float x=11.1‬‬
‫;‪cout << "x = " << x << endl‬‬
‫;‪a[3333] = 88.8‬‬ ‫!‪// ERROR: index is out of bounds‬‬
‫;‪cout << "x = " << x << endl‬‬
‫}‬

‫ﻭﻗﺘﻲ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺭﻭﻱ ﺭﺍﻳﺎﻧﻪﺍﻱ ﺑﺎ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ‬


‫ﻭﻳﻨﺪﻭﺯ ﺍﺟﺮﺍ ﺷﻮﺩ‪ ،‬ﻳﮏ ﺻﻔﺢۀ ﻫﺸﺪﺍﺭ ﮐﻪ ﺩﺭ‬
‫ﺷﮑﻞ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺭﻭﻱ ﺻﻔﺤﻪ ﻇﺎﻫﺮ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﭘﻨﺠﺮﻩ ﺑﻴﺎﻥ ﻣﻲﮐﻨﺪ ﮐﻪ ﺑﺮﻧﺎﻣﻪ ﺗﻼﺵ‬
‫ﺩﺍﺭﺩ ﺑﻪ ﻧﺸﺎﻧﻲ ‪ 0040108e‬ﺍﺯ ﺣﺎﻓﻈﻪ ﺩﺳﺘﻴﺎﺑﻲ‬
‫ﮐﻨﺪ‪ .‬ﺍﻳﻦ ﻣﮑﺎﻥ ﺧﺎﺭﺝ ﺍﺯ ﺣﺎﻓﻆۀ ﺗﺨﺼﻴﺼﻲ‬
‫ﺍﺳﺖ ﮐﻪ ﺑﺮﺍﻱ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻣﻨﻈﻮﺭ ﺷﺪﻩ‪ ،‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﻣﺘﻮﻗﻒ ﻣﻲﮐﻨﺪ‪.‬‬
‫ﺧﻄﺎﻳﻲ ﮐﻪ ﺩﺭ ﻣﺜﺎﻝ ‪ 6‐8‬ﺑﻴﺎﻥ ﺷﺪﻩ ﻳﮏ »ﺍﺳﺘﺜﻨﺎﻱ ﻣﺪﻳﺮﻳﺖ ﻧﺸﺪﻩ« ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ‬
‫ﺯﻳﺮﺍ ﮐﺪﻱ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ ﮐﻪ ﺑﻪ ﺍﻳﻦ ﺍﺳﺘﺜﻨﺎ ﭘﺎﺳﺦ ﺩﻫﺪ‪ .‬ﺩﺭ ‪ C++‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﮐﺪﻫﺎﻳﻲ ﺑﻪ ﺑﺮﻧﺎﻣﻪ‬
‫ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ ﮐﻪ ﻫﻨﮕﺎﻡ ﺭﺥ ﺩﺍﺩﻥ ﺣﺎﻟﺖﻫﺎﻱ ﺍﺳﺘﺜﻨﺎ‪ ،‬ﺍﺯ ﺗﻮﻗﻒ ﺑﺮﻧﺎﻣﻪ ﺟﻠﻮﮔﻴﺮﻱ ﮐﻨﺪ‪ .‬ﺑﻪ ﺍﻳﻦ‬
‫ﮐﺪﻫﺎ »ﭘﺮﺩﺍﺯﺵﮔﺮ ﺍﺳﺘﺜﻨﺎ‪ «1‬ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬
‫ﺑﺮﺧﻼﻑ ﺑﻌﻀﻲ ﺍﺯ ﺯﺑﺎﻥﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺩﻳﮕﺮ )ﻣﺜﻞ ﭘﺎﺳﮑﺎﻝ ﻭ ﺟﺎﻭﺍ( ﺁﺭﺍﻳﻪﻫﺎ ﺭﺍ‬
‫ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ ﺑﻪ ﻳﮑﺪﻳﮕﺮ ﺗﺨﺼﻴﺺ ﺩﺍﺩ ﻭ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪﻫﺎ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺯ‬
‫ﻣﺤﺪﻭﺩۀ ﺁﺭﺍﻳﻪ ﻓﺮﺍﺗﺮ ﺭﻭﺩ‪ .‬ﺍﻳﻦﻫﺎ ﺑﺎﻋﺚ ﺍﻳﺠﺎﺩ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﮐﺎﻣﭙﺎﻳﻞ ﻭ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ‬
‫ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‪ .‬ﺑﺮﺍﻱ ﺟﻠﻮﮔﻴﺮﻱ ﺍﺯ ﺑﺮﻭﺯ ﺍﻳﻦ ﺧﻄﺎﻫﺎ‪ ،‬ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺑﺎﻳﺪ ﺩﻗﺖ ﻣﻀﺎﻋﻔﻲ ﺭﺍ ﺩﺭ‬
‫ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﮐﺎﺭ ﺑﮕﻴﺮﺩ ﺗﺎ ﺑﺘﻮﺍﻧﺪ ﮐﺪ ﺳﺮﻳﻊﺗﺮ ﻭ ﻣﻄﻤﺌﻦﺗﺮﻱ ﺗﻮﻟﻴﺪ ﮐﻨﺪ‪.‬‬

‫‪ 6‐5‬ﺍﺭﺳﺎﻝ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ‬


‫ﻛﺪ ;][‪ float a‬ﻛﻪ ﺁﺭﺍﻳﻪ ‪ a‬ﺭﺍ ﺍﻋﻼﻥ ﻣﻲﻛﻨﺪ ﺩﻭ ﭼﻴﺰ ﺭﺍ ﺑﻪ ﻛﺎﻣﭙﺎﻳﻠﺮ ﻣﻲﮔﻮﻳﺪ‪:‬‬
‫ﺍﻳﻦ ﮐﻪ ﻧﺎﻡ ﺁﺭﺍﻳﻪ ‪ a‬ﺍﺳﺖ ﻭ ﺍﻳﻦ ﮐﻪ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺍﺯ ﻧﻮﻉ ‪ float‬ﻫﺴﺘﻨﺪ‪ .‬ﺳﻤﺒﻞ ‪ a‬ﻧﺸﺎﻧﻲ‬

‫‪1 – Exception handler‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪184‬‬

‫ﺣﺎﻓﻆۀ ﺁﺭﺍﻳﻪ ﺭﺍ ﺫﺧﻴﺮﻩ ﻣﻲﮐﻨﺪ‪ .‬ﻻﺯﻡ ﻧﻴﺴﺖ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺑﻪ ﮐﺎﻣﭙﺎﻳﻠﺮ ﮔﻔﺘﻪ ﺷﻮﺩ ﺯﻳﺮﺍ‬
‫ﺍﺯ ﺭﻭﻱ ﻧﺸﺎﻧﻲ ﻣﻮﺟﻮﺩ ﺩﺭ ‪ a‬ﻣﻲﺗﻮﺍﻥ ﻋﻨﺎﺻﺮ ﺭﺍ ﺑﺎﺯﻳﺎﺑﻲ ﻧﻤﻮﺩ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﻃﺮﻳﻖ ﻣﻲﺗﻮﺍﻥ ﻳﮏ‬
‫ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﮐﺮﺩ‪ .‬ﻳﻌﻨﻲ ﻓﻘﻂ ﻧﻮﻉ ﺁﺭﺍﻳﻪ ﻭ ﻧﺸﺎﻧﻲ ﺣﺎﻓﻆۀ ﺁﻥ ﺑﻪ ﻋﻨﻮﺍﻥ ﭘﺎﺭﺍﻣﺘﺮ ﺑﻪ‬
‫ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐9‬ﺍﺭﺳﺎﻝ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻌﻲ ﻛﻪ ﻣﺠﻤﻮﻉ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬


‫;)‪int sum(int[],int‬‬
‫)(‪int main‬‬
‫;} ‪{ int a[] = { 11, 33, 55, 77‬‬
‫;)‪int size = sizeof(a)/sizeof(int‬‬
‫;‪cout << "sum(a,size) = " << sum(a,size) << endl‬‬
‫}‬
‫)‪int sum(int a[], int n‬‬
‫;‪{ int sum=0‬‬
‫)‪for (int i=0; i<n; i++‬‬
‫;]‪sum += a[i‬‬
‫;‪return sum‬‬
‫}‬
‫‪sum(a,size) = 176‬‬

‫ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮ ﺗﺎﺑﻊ ﻓﻮﻕ ﺑﻪ ﺷﮑﻞ )‪ (int a[], int n‬ﺍﺳﺖ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻳﻦ‬
‫ﺗﺎﺑﻊ ﻳﮏ ﺁﺭﺍﻳﻪ ﺍﺯ ﻧﻮﻉ ‪ int‬ﻭ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ ‪ int‬ﺩﺭﻳﺎﻓﺖ ﻣﻲﮐﻨﺪ‪ .‬ﺑﻪ ﺍﻋﻼﻥ ﺍﻳﻦ ﺗﺎﺑﻊ‬
‫ﺩﺭ ﺑﺎﻻﻱ ﺗﺎﺑﻊ )(‪ main‬ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪ .‬ﻧﺎﻡ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﺣﺬﻑ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﻫﻨﮕﺎﻡ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ‬
‫ﻧﻴﺰ ﺍﺯ ﻋﺒﺎﺭﺕ )‪ sum(a,size‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﮐﻪ ﻓﻘﻂ ﻧﺎﻡ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﺷﺪﻩ‪ .‬ﻧﺎﻡ‬
‫ﺁﺭﺍﻳﻪ ﺩﺭ ﺣﻘﻴﻘﺖ ﻧﺸﺎﻧﻲ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺍﺳﺖ )ﻳﻌﻨﻲ ]‪ . (a[0‬ﺗﺎﺑﻊ ﺍﺯ ﺍﻳﻦ ﻧﺸﺎﻧﻲ ﺑﺮﺍﻱ‬
‫ﺩﺳﺘﻴﺎﺑﻲ ﺑﻪ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﻧﺸﺎﻧﻲ‪،‬‬
‫ﻣﺤﺘﻮﻳﺎﺕ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ‪ .‬ﭘﺲ ﺍﺭﺳﺎﻝ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﺷﺒﻴﻪ ﺍﺭﺳﺎﻝ ﻣﺘﻐﻴﺮ ﺑﻪ‬
‫ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺍﺳﺖ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺩﻗﺖ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐10‬ﺗﻮﺍﺑﻊ ﻭﺭﻭﺩﻱ ﻭ ﺧﺮﻭﺟﻲ ﺑﺮﺍﻱ ﻳﮏ ﺁﺭﺍﻳﻪ‬


‫ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺗﺎﺑﻊ )(‪ read‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﺗﺎ ﻣﻘﺎﺩﻳﺮﻱ ﺑﻪ ﺩﺍﺧﻞ ﺁﺭﺍﻳﻪ ﻭﺍﺭﺩ‬
‫ﺷﻮﺩ‪ .‬ﺳﭙﺲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ )(‪ print‬ﻣﻘﺎﺩﻳﺮ ﺩﺍﺧﻞ ﺁﺭﺍﻳﻪ ﭼﺎﭖ ﻣﻲﺷﻮﻧﺪ‪:‬‬
185 ‫ ﺁراﻳﻪهﺎ‬/ ‫ﻓﺼﻞ ﺷﺸﻢ‬

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

‫ ﮐﻪ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ‬n ‫ ﻭ ﻫﻤﭽﻨﻴﻦ ﻣﻘﺪﺍﺭ ﭘﺎﺭﺍﻣﺘﺮ‬a ‫ ﻣﻘﺎﺩﻳﺮ ﺁﺭﺍﻱۀ‬read() ‫ﺗﺎﺑﻊ‬


‫ ﺑﺘﻮﺍﻧﺪ‬read() ‫ ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺗﺎﺑﻊ‬،‫ ﻳﻚ ﻣﺘﻐﻴﺮ ﺍﺳﺖ‬n ‫ ﭼﻮﻥ‬.‫ﺍﺳﺖ ﺭﺍ ﺗﻐﻴﻴﺮ ﻣﻲﺩﻫﺪ‬
‫ ﻫﻤﭽﻨﻴﻦ ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ‬.‫ﻣﻘﺪﺍﺭ ﺁﻥ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﺪ ﺍﻳﻦ ﻣﺘﻐﻴﺮ ﺑﺎﻳﺪ ﺑﻪ ﺷﮑﻞ ﺍﺭﺟﺎﻉ ﺍﺭﺳﺎﻝ ﺷﻮﺩ‬
‫ ﺁﺭﺍﻳﻪ ﻧﻴﺰ ﺑﺎﻳﺪ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ‬،‫ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﺪ‬a ‫ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﺑﺘﻮﺍﻧﺪ ﻣﻘﺎﺩﻳﺮ ﺩﺍﺧﻞ ﺁﺭﺍﻳﻪ‬
.‫ ﺍﻣﺎ ﺍﺭﺟﺎﻉ ﺁﺭﺍﻳﻪﻫﺎ ﮐﻤﻲ ﻣﺘﻔﺎﻭﺕ ﺍﺳﺖ‬،‫ﺍﺭﺳﺎﻝ ﺷﻮﺩ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪186‬‬

‫ﺩﺭ ‪ 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‬‬

‫ﺁﺩﺭﺱ ﺧﺎﻥۀ ‪n‬ﺍﻡ ﺑﻪ ﺷﻴﻮۀ ﺑﺎﻻ ﻣﺤﺎﺳﺒﻪ ﻣﻲﺷﻮﺩ ﻭ ﻣﻘﺪﺍﺭ‬


‫‪0x0064fdc8‬‬
‫‪0x0064fdc9‬‬
‫‪0x0064fdca‬‬ ‫]‪a[3‬‬
‫‪0x0064fdcb‬‬
‫‪0x0064fdcc‬‬
‫ﻭﺭﻭﺩﻱ ﺩﺭ ﺁﻥ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﻣﺜﻼ ﺍﮔﺮ ‪ n=3‬ﺑﺎﺷﺪ‪،‬‬
‫]‪ a[3‬ﺳﻪ ﭘﻠﻪ ﺍﺯ ﺧﺎﻥۀ ]‪ a[0‬ﻓﺎﺻﻠﻪ ﺩﺍﺭﺩ‪ .‬ﭼﻮﻥ‬
‫ﺁﺭﺍﻱۀ ‪ a‬ﺍﺯ ﻧﻮﻉ ‪ int‬ﺍﺳﺖ ﻭ ﻧﻮﻉ ‪ int‬ﭼﻬﺎﺭ ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ ﻣﻲﮐﻨﺪ‪ ،‬ﭘﺲ‬
‫ﺁﺩﺭﺱ ]‪ a[3‬ﺑﻪ ﺍﻧﺪﺍﺯۀ ‪ 3*4=12‬ﺑﺎﻳﺖ ﺍﺯ ﺧﺎﻥۀ ]‪ a[0‬ﻓﺎﺻﻠﻪ ﺩﺍﺭﺩ‪ .‬ﻟﺬﺍ ﺑﻪ ﺍﻧﺪﺍﺯﻩ‬
‫ﺩﻭﺍﺯﺩﻩ ﺑﺎﻳﺖ ﺑﻪ ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻧﻪ )ﻳﻌﻨﻲ ]‪ (a[0‬ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ ﺗﺎ ﺑﻪ ﺧﺎﻥۀ ]‪a[3‬‬
‫ﺑﺮﺳﻴﻢ‪ .‬ﺑﻪ ﻣﻘﺪﺍﺭ ‪» 12‬ﺁﻓﺴﺖ‪ «1‬ﻋﻨﺼﺮ ]‪ a[3‬ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺁﻓﺴﺖ ﻳﮏ ﻋﻨﺼﺮ ﺍﺯ ﺁﺭﺍﻳﻪ‪،‬‬

‫‪1 – Offset‬‬
‫‪187‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫ﻋﺪﺩﻱ ﺍﺳﺖ ﮐﻪ ﺑﺎﻳﺪ ﺑﻪ ﻧﺸﺎﻧﻲ ﺧﺎﻥۀ ﺍﻭﻝ ﺍﻓﺰﻭﺩﻩ ﺷﻮﺩ ﺗﺎ ﺑﻪ ﺧﺎﻥۀ ﺁﻥ ﻋﻨﺼﺮ ﺑﺮﺳﻴﻢ‪.‬‬
‫ﺍﺯ ﻫﻢۀ ﮔﻔﺘﻪﻫﺎﻱ ﻓﻮﻕ ﻧﺘﻴﺠﻪ ﻣﻲﺷﻮﺩ ﮐﻪ ﺑﺮﺍﻱ ﺍﺭﺳﺎﻝ ﻳﮏ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﻓﻘﻂ ﮐﺎﻓﻲ‬
‫ﺍﺳﺖ ﻧﺎﻡ ﺁﺭﺍﻳﻪ ﻭ ﺍﻧﺪﺍﺯۀ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﺷﻮﺩ‪ .‬ﺑﺎﺯ ﻫﻢ ﺗﺎﮐﻴﺪ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﻧﺎﻡ ﺁﺭﺍﻳﻪ‪،‬‬
‫ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺭﺍ ﺩﺭ ﺧﻮﺩ ﺩﺍﺭﺩ‪ .‬ﻣﺜﻼ ﺍﮔﺮ ﺁﺭﺍﻱۀ ‪ a‬ﺩﺭ ﺁﺩﺭﺱ ‪0x0064fdbc‬‬
‫ﻭﺍﻗﻊ ﺷﺪﻩ ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺩﺭﻭﻥ ‪ a‬ﻣﻘﺪﺍﺭ ‪ 0x0064fdbc‬ﻗﺮﺍﺭ ﺩﺍﺭﺩ‪ .‬ﻫﻤﭽﻨﻴﻦ ﻧﺎﻡ ﺁﺭﺍﻳﻪ‬
‫ﺷﺒﻴﻪ ﻳﮏ ﺛﺎﺑﺖ ﻋﻤﻞ ﻣﻲﮐﻨﺪ‪ .‬ﻳﻌﻨﻲ ﺁﺩﺭﺱ ﻳﮏ ﺁﺭﺍﻳﻪ ﻫﻤﻴﺸﻪ ﺛﺎﺑﺖ ﺍﺳﺖ ﻭ ﺁﺭﺍﻳﻪ ﻧﻤﻲﺗﻮﺍﻧﺪ‬
‫ﺑﻪ ﻣﮑﺎﻥ ﺩﻳﮕﺮﻱ ﺍﺯ ﺣﺎﻓﻈﻪ ﺗﻐﻴﻴﺮ ﻣﮑﺎﻥ ﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐11‬ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ ﺁﺭﺍﻳﻪ ﻭ ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ ﺁﻥ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﺁﺩﺭﺱ ﺫﺧﻴﺮﻩ ﺷﺪﻩ ﺩﺭ ﻧﺎﻡ ﺁﺭﺍﻳﻪ ﻭ ﻣﻘﺪﺍﺭ ﻣﻮﺟﻮﺩ ﺩﺭ ﺁﻥ ﺧﺎﻧﻪ ﺭﺍ ﭼﺎﭖ‬
‫ﻣﻲﮐﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;} ‪{ int a[] = { 22, 44, 66, 88‬‬
‫;‪cout << "a = " << a << endl‬‬ ‫]‪// the address of a[0‬‬
‫;]‪cout << "a[0] = " << a[0‬‬ ‫]‪// the value of a[0‬‬
‫}‬
‫‪a = 0x0064fdec‬‬
‫‪a[0] = 22‬‬

‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺗﻼﺵ ﻣﻲﮐﻨﺪ ﮐﻪ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ ﻣﻘﺪﺍﺭ ‪ a‬ﺭﺍ ﭼﺎﭖ ﮐﻨﺪ‪ .‬ﻧﺘﻴﺞۀ ﭼﺎﭖ ‪ a‬ﺍﻳﻦ‬
‫ﺍﺳﺖ ﮐﻪ ﻳﮏ ﺁﺩﺭﺱ ﺑﻪ ﺷﮑﻞ ﺷﺎﻧﺰﺩﻩ ﺩﻫﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﻫﻤﺎﻥ ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ‬
‫ﺁﺭﺍﻳﻪ ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﺩﺭﻭﻥ ﻧﺎﻡ ‪ a‬ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ‪ .‬ﺧﺮﻭﺟﻲ ﻧﻴﺰ ﻧﺸﺎﻥ‬
‫ﻣﻲﺩﻫﺪ ﮐﻪ ‪ a‬ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺭﺍ ﺩﺍﺭﺩ ﻭ ]‪ a[0‬ﻣﻘﺪﺍﺭ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺭﺍ‪.‬‬

‫‪1‬‬
‫‪ 6‐6‬ﺍﻟﮕﻮﺭﻳﺘﻢ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ‬
‫ﺁﺭﺍﻳﻪﻫﺎ ﺑﻴﺸﺘﺮ ﺑﺮﺍﻱ ﭘﺮﺩﺍﺯﺵ ﻳﮏ ﺯﻧﺠﻴﺮﻩ ﺍﺯ ﺩﺍﺩﻩﻫﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ‪ .‬ﺍﻏﻠﺐ ﻻﺯﻡ‬
‫ﺍﺳﺖ ﮐﻪ ﺑﺮﺭﺳﻲ ﺷﻮﺩ ﺁﻳﺎ ﻳﮏ ﻣﻘﺪﺍﺭ ﺧﺎﺹ ﺩﺭﻭﻥ ﻳﮏ ﺁﺭﺍﻳﻪ ﻣﻮﺟﻮﺩ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ‪.‬‬
‫ﺳﺎﺩﻩﺗﺮﻳﻦ ﺭﺍﻩ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﺯ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺷﺮﻭﻉ ﮐﻨﻴﻢ ﻭ ﻳﮑﻲ ﻳﮑﻲ ﻫﻢۀ ﻋﻨﺎﺻﺮ‬

‫‪1 – Linear searching‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪188‬‬

‫ﺁﺭﺍﻳﻪ ﺭﺍ ﺟﺴﺘﺠﻮ ﻧﻤﺎﻳﻴﻢ ﺗﺎ ﺑﻔﻬﻤﻴﻢ ﮐﻪ ﻣﻘﺪﺍﺭ ﻣﻮﺭﺩ ﻧﻈﺮ ﺩﺭ ﮐﺪﺍﻡ ﻋﻨﺼﺮ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ‪ .‬ﺑﻪ ﺍﻳﻦ‬
‫ﺭﻭﺵ »ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ« ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐12‬ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺗﺎﺑﻌﻲ ﺭﺍ ﺁﺯﻣﺎﻳﺶ ﻣﻲﮐﻨﺪ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﺯ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ‬
‫ﺑﺮﺍﻱ ﻳﺎﻓﺘﻦ ﻳﮏ ﻣﻘﺪﺍﺭ ﺧﺎﺹ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‪:‬‬
‫;)‪int index(int,int[],int‬‬
‫)(‪int main‬‬
‫;}‪{ int a[] = { 22, 44, 66, 88, 44, 66, 55‬‬
‫;‪cout << "index(44,a,7) = " << index(44,a,7) << endl‬‬
‫;‪cout << "index(50,a,7) = " << index(50,a,7) << endl‬‬
‫}‬
‫)‪int index(int x, int a[], int n‬‬
‫)‪{ for (int i=0; i<n; i++‬‬
‫;‪if (a[i] == x) return i‬‬
‫;‪return n‬‬ ‫‪// x not found‬‬
‫}‬
‫‪index(44,a,7) = 1‬‬
‫‪index(40,a,7) = 7‬‬

‫ﺗﺎﺑﻊ )(‪ 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‬ﻣﺮﺗﺐﺳﺎﺯﻱ ﺣﺒﺎﺑﻲ‬
‫ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺧﻴﻠﻲ ﮐﺎﺭﺁﻣﺪ ﻧﻴﺴﺖ‪ .‬ﻫﻴﭻ ﮐﺲ ﺑﺮﺍﻱ ﻳﺎﻓﺘﻦ ﻣﻌﻨﻲ ﻳﮏ ﮐﻠﻤﻪ ﺩﺭ‬
‫ﻭﺍﮊﻩﻧﺎﻣﻪ‪ ،‬ﻫﻢۀ ﮐﻠﻤﺎﺕ ﺭﺍ ﺍﺯ ﺍﺑﺘﺪﺍ ﺟﺴﺘﺠﻮ ﻧﻤﻲﮐﻨﺪ ﺯﻳﺮﺍ ﮐﻠﻤﺎﺕ ﺩﺭ ﻭﺍﮊﻩﻧﺎﻣﻪ ﺑﻪ ﺗﺮﺗﻴﺐ‬
‫ﺣﺮﻭﻑ ﺍﻟﻔﺒﺎ ﻣﺮﺗﺐ ﺷﺪﻩ ﺍﺳﺖ ﻭ ﺑﺮﺍﻱ ﻳﺎﻓﺘﻦ ﻣﻌﻨﻲ ﻳﮏ ﮐﻠﻤﻪ ﮐﺎﻓﻲ ﺍﺳﺖ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ‬
‫ﺑﻪ ﺑﺨﺸﻲ ﺑﺮﻭﻳﻢ ﮐﻪ ﺣﺮﻑ ﺍﻭﻝ ﮐﻠﻢۀ ﻣﺎ ﺩﺭ ﺁﻥ ﺑﺨﺶ ﻓﻬﺮﺳﺖ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺑﻪ ﺍﻳﻦ ﺻﻮﺭﺕ‬
‫ﺟﺴﺘﺠﻮ ﺑﺴﻴﺎﺭ ﺳﺮﻳﻊﺗﺮ ﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ ﻭ ﭘﺎﺳﺦ ﺩﺭ ﺯﻣﺎﻥ ﮐﻮﺗﺎﻩﺗﺮﻱ ﺣﺎﺻﻞ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻣﺎ‬
‫ﺷﺮﻁ ﺍﻳﻦ ﺟﺴﺘﺠﻮ ﺁﻥ ﺍﺳﺖ ﮐﻪ ﻫﻢۀ ﻋﻨﺎﺻﺮ ﻣﺮﺗﺐ ﺑﺎﺷﻨﺪ‪.‬‬
‫ﺭﻭﺵﻫﺎﻱ ﺯﻳﺎﺩﻱ ﺑﺮﺍﻱ ﻣﺮﺗﺐ ﮐﺮﺩﻥ ﻳﮏ ﺁﺭﺍﻳﻪ ﻭﺟﻮﺩ ﺩﺍﺭﺩ‪» .‬ﻣﺮﺗﺐﺳﺎﺯﻱ ﺣﺒﺎﺑﻲ«‬
‫ﻳﮑﻲ ﺍﺯ ﺳﺎﺩﻩﺗﺮﻳﻦ ﺍﻟﮕﻮﺭﻳﺘﻢﻫﺎﻱ ﻣﺮﺗﺐﺳﺎﺯﻱ ﺍﺳﺖ‪ .‬ﺩﺭ ﺍﻳﻦ ﺭﻭﺵ‪ ،‬ﺁﺭﺍﻳﻪ ﭼﻨﺪﻳﻦ ﻣﺮﺗﺒﻪ‬
‫ﭘﻮﻳﺶ ﻣﻲﺷﻮﺩ ﻭ ﺩﺭ ﻫﺮ ﻣﺮﺗﺒﻪ ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﻨﺼﺮ ﻣﻮﺟﻮﺩ ﺑﻪ ﺳﻤﺖ ﺑﺎﻻ ﻫﺪﺍﻳﺖ ﻣﻲﺷﻮﺩ ﻭ‬
‫ﺳﭙﺲ ﻣﺤﺪﻭﺩۀ ﻣﺮﺗﺐﺳﺎﺯﻱ ﺑﺮﺍﻱ ﻣﺮﺗﺐۀ ﺑﻌﺪﻱ ﻳﮑﻲ ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺩﺭ ﭘﺎﻳﺎﻥ ﻫﻢۀ‬
‫ﭘﻮﻳﺶﻫﺎ‪ ،‬ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﻃﺮﻳﻖۀ ﻳﺎﻓﺘﻦ ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﻨﺼﺮ ﻭ ﺍﻧﺘﻘﺎﻝ ﺁﻥ ﺑﻪ ﺑﺎﻻﻱ‬
‫ﻋﻨﺎﺻﺮ ﺩﻳﮕﺮ ﺑﻪ ﺍﻳﻦ ﺷﮑﻞ ﺍﺳﺖ ﮐﻪ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺑﺎ ﻋﻨﺼﺮ ﺩﻭﻡ ﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺍﮔﺮ‬
‫ﻋﻨﺼﺮ ﺍﻭﻝ ﺑﺰﺭﮒﺗﺮ ﺑﻮﺩ‪ ،‬ﺟﺎﻱ ﺍﻳﻦ ﺩﻭ ﺑﺎ ﻫﻢ ﻋﻮﺽ ﻣﻲﺷﻮﺩ‪ .‬ﺳﭙﺲ ﻋﻨﺼﺮ ﺩﻭﻡ ﺑﺎ ﻋﻨﺼﺮ‬
‫ﺳﻮﻡ ﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺍﮔﺮ ﻋﻨﺼﺮ ﺩﻭﻡ ﺑﺰﺭﮒﺗﺮ ﺑﻮﺩ‪ ،‬ﺟﺎﻱ ﺍﻳﻦ ﺩﻭ ﺑﺎ ﻫﻢ ﻋﻮﺽ ﻣﻲﺷﻮﺩ ﻭ‬
‫ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﻣﻘﺎﻳﺴﻪ ﻭ ﺟﺎﺑﺠﺎﻳﻲ ﺯﻭﺝﻫﺎﻱ ﻫﻤﺴﺎﻳﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﻭﻗﺘﻲ ﺑﻪ ﺍﻧﺘﻬﺎﻱ‬
‫ﺁﺭﺍﻳﻪ ﺭﺳﻴﺪﻳﻢ‪ ،‬ﺑﺰﺭﮒﺗﺮﻳﻦ ﻋﻀﻮ ﺁﺭﺍﻳﻪ ﺩﺭ ﺧﺎﻥۀ ﺍﻧﺘﻬﺎﻳﻲ ﻗﺮﺍﺭ ﺧﻮﺍﻫﺪ ﮔﺮﻓﺖ‪ .‬ﺳﭙﺲ‬
‫ﻣﺤﺪﻭﺩۀ ﺟﺴﺘﺠﻮ ﻳﮑﻲ ﮐﺎﺳﺘﻪ ﻣﻲﺷﻮﺩ ﻭ ﺩﻭﺑﺎﺭﻩ ﺯﻭﺝﻫﺎﻱ ﮐﻨﺎﺭﻱ ﻳﮑﻲ ﻳﮑﻲ ﻣﻘﺎﻳﺴﻪ‬
‫ﻣﻲﺷﻮﻧﺪ ﺗﺎ ﻋﺪﺩ ﺑﺰﺭﮒﺗﺮ ﺑﻌﺪﻱ ﺑﻪ ﻣﮑﺎﻥ ﺑﺎﻻﻱ ﻣﺤﺪﻭﺩﻩ ﻣﻨﺘﻘﻞ ﺷﻮﺩ‪ .‬ﺍﻳﻦ ﭘﻮﻳﺶ ﺍﺩﺍﻣﻪ‬
‫ﻣﻲﻳﺎﺑﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﻭﻗﺘﻲ ﻣﺤﺪﻭﺩﻩ ﺟﺴﺘﺠﻮ ﺑﻪ ﻋﻨﺼﺮ ﺍﻭﻝ ﻣﺤﺪﻭﺩ ﺷﺪ‪ ،‬ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﺷﺪﻩ‬
‫ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐13‬ﻣﺮﺗﺐﺳﺎﺯﻱ ﺣﺒﺎﺑﻲ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺗﺎﺑﻌﻲ ﺭﺍ ﺁﺯﻣﺎﻳﺶ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺮﺗﺐﺳﺎﺯﻱ ﺣﺒﺎﺑﻲ‬
‫ﻳﮏ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﺮﺗﺐ ﻣﻲﻧﻤﺎﻳﺪ‪:‬‬

‫‪1 – Bobble sorting‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪190‬‬

‫;)‪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‬ﺍﻟﮕﻮﺭﻳﺘﻢ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ‬
‫ﺩﺭ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺑﻪ ﻳﮏ ﺁﺭﺍﻱۀ ﻣﺮﺗﺐ ﻧﻴﺎﺯ ﺍﺳﺖ‪ .‬ﻫﻨﮕﺎﻡ ﺟﺴﺘﺠﻮ ﺁﺭﺍﻳﻪ‬
‫ﺍﺯ ﻭﺳﻂ ﺑﻪ ﺩﻭ ﺑﺨﺶ ﺑﺎﻻﻳﻲ ﻭ ﭘﺎﻳﻴﻨﻲ ﺗﻘﺴﻴﻢ ﻣﻲﺷﻮﺩ‪ .‬ﻣﻘﺪﺍﺭ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺑﺎ ﺁﺧﺮﻳﻦ‬
‫ﻋﻨﺼﺮ ﺑﺨﺶ ﭘﺎﻳﻴﻨﻲ ﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺍﮔﺮ ﺍﻳﻦ ﻋﻨﺼﺮ ﮐﻮﭼﮏﺗﺮ ﺍﺯ ﻣﻘﺪﺍﺭ ﺟﺴﺘﺠﻮ ﺑﻮﺩ‪،‬‬
‫ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺩﺭ ﺑﺨﺶ ﭘﺎﻳﻴﻨﻲ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ ﻭ ﺑﺎﻳﺪ ﺩﺭ ﺑﺨﺶ ﺑﺎﻻﻳﻲ ﺑﻪ ﺩﻧﺒﺎﻝ ﺁﻥ ﮔﺸﺖ‪.‬‬

‫‪1 - Binary searching‬‬


‫‪191‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫ﺩﻭﺑﺎﺭﻩ ﺑﺨﺶ ﺑﺎﻻﻳﻲ ﺑﻪ ﺩﻭ ﺑﺨﺶ ﺗﻘﺴﻴﻢ ﻣﻲﮔﺮﺩﺩ ﻭ ﮔﺎﻡﻫﺎﻱ ﺑﺎﻻ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ‪ .‬ﺳﺮﺍﻧﺠﺎﻡ‬
‫ﻣﺤﺪﻭﺩۀ ﺟﺴﺘﺠﻮ ﺑﻪ ﻳﮏ ﻋﻨﺼﺮ ﻣﺤﺪﻭﺩ ﻣﻲﺷﻮﺩ ﮐﻪ ﻳﺎ ﺁﻥ ﻋﻨﺼﺮ ﺑﺎ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺑﺮﺍﺑﺮ‬
‫ﺍﺳﺖ ﻭ ﻋﻨﺼﺮ ﻣﺬﮐﻮﺭ ﻳﺎﻓﺖ ﺷﺪﻩ ﻭ ﻳﺎ ﺍﻳﻦ ﮐﻪ ﺁﻥ ﻋﻨﺼﺮ ﺑﺎ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺑﺮﺍﺑﺮ ﻧﻴﺴﺖ ﻭ‬
‫ﻟﺬﺍ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮ ﺩﺭ ﺁﺭﺍﻳﻪ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ‪ .‬ﺍﻳﻦ ﺭﻭﺵ ﭘﻴﭽﻴﺪﻩﺗﺮ ﺍﺯ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ‬
‫ﺍﺳﺖ ﺍﻣﺎ ﺩﺭ ﻋﻮﺽ ﺑﺴﻴﺎﺭ ﺳﺮﻳﻊﺗﺮ ﺑﻪ ﺟﻮﺍﺏ ﻣﻲﺭﺳﻴﻢ‪ .‬ﺍﻟﺒﺘﻪ ﺑﻪ ﺷﺮﻃﻲ ﺑﻪ ﺟﻮﺍﺏ ﻣﻲﺭﺳﻴﻢ‬
‫ﮐﻪ ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﺷﺪﻩ ﺑﺎﺷﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐14‬ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ‬


‫ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺯﻳﺮ ﺑﺎ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﻣﺜﺎﻝ ‪ 6‐12‬ﻳﮑﻲ ﺍﺳﺖ ﺍﻣﺎ ﺗﺎﺑﻌﻲ ﮐﻪ ﺩﺭ ﺯﻳﺮ‬
‫ﺁﻣﺪﻩ ﺍﺯ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺑﺮﺍﻱ ﻳﺎﻓﺘﻦ ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ ﺁﺭﺍﻳﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﺪ‪:‬‬
‫;)‪int index(int, int[],int‬‬
‫)(‪int main‬‬
‫;} ‪{ int a[] = { 22, 33, 44, 55, 66, 77, 88‬‬
‫;‪cout << "index(44,a,7) = " << index(44,a,7) << endl‬‬
‫;‪cout << "index(60,a,7) = " << index(60,a,7) << endl‬‬
‫}‬

‫)‪int index(int x, int a[], int n‬‬


‫;]‪{ // PRECONDITION: a[0] <= a[1] <= ... <= a[n-1‬‬
‫‪// binary search:‬‬
‫;‪int lo=0, hi=n-1, i‬‬
‫)‪while (lo <= hi‬‬
‫;‪{ i = (lo + hi)/2‬‬ ‫‪// the average of lo and hi‬‬
‫;‪if (a[i] == x) return i‬‬
‫;‪if (a[i] < x) lo = i+1‬‬ ‫]‪// continue search in a[i+1..hi‬‬
‫;‪else hi = i-1‬‬ ‫]‪// continue search in a[0..i-1‬‬
‫}‬
‫;‪return n‬‬ ‫]‪// x was not found in a[0..n-1‬‬
‫}‬
‫‪index(44,a,7) = 2‬‬
‫‪index(60,a,7) = 7‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪192‬‬

‫ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺁﺭﺍﻳﻪ‪ ،‬ﻗﺒﻞ ﺍﺯ ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺑﺎﻳﺪ ﻣﺮﺗﺐ ﺑﺎﺷﺪ‪ .‬ﺍﻳﻦ‬
‫ﭘﻴﺶﺷﺮﻁ ﺑﻪ ﺷﮑﻞ ﺗﻮﺿﻴﺢ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﻗﻴﺪ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬

‫ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺑﻔﻬﻤﻴﻢ ﺗﺎﺑﻊ ﭼﻄﻮﺭ ﮐﺎﺭ ﻣﻲﮐﻨﺪ‪ ،‬ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ index(44,a,7‬ﺭﺍ‬


‫ﺩﻧﺒﺎﻝ ﻣﻲﮐﻨﻴﻢ‪ .‬ﻭﻗﺘﻲ ﺣﻠﻘﻪ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ‪ x=44 ،‬ﻭ ‪ n=7‬ﻭ ‪ lo=0‬ﻭ ‪ hi=6‬ﺍﺳﺖ‪.‬‬
‫ﺍﺑﺘﺪﺍ ‪ i‬ﻣﻘﺪﺍﺭ ‪ (0+6)/2 = 3‬ﺭﺍ ﻣﻲﮔﻴﺮﺩ‪.‬ﭘﺲ ﻋﻨﺼﺮ ]‪ a[i‬ﻋﻨﺼﺮ ﻭﺳﻂ ﺁﺭﺍﻱۀ‬
‫]‪ a[0..6‬ﺍﺳﺖ‪ .‬ﻣﻘﺪﺍﺭ ]‪ a[3‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 55‬ﺍﺳﺖ ﮐﻪ ﺍﺯ ﻣﻘﺪﺍﺭ ‪ x‬ﺑﺰﺭﮒﺗﺮ ﺍﺳﺖ‪ .‬ﭘﺲ ‪x‬‬
‫ﺩﺭ ﻧﻴﻢۀ ﺑﺎﻻﻳﻲ ﻧﻴﺴﺖ ﻭ ﺟﺴﺘﺠﻮ ﺩﺭ ﻧﻴﻢۀ ﭘﺎﻳﻴﻨﻲ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﻟﺬﺍ ‪ hi‬ﺑﺎ ‪ i-1‬ﻳﻌﻨﻲ ‪2‬‬
‫ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﺷﻮﺩ ﻭ ﺣﻠﻘﻪ ﺗﮑﺮﺍﺭ ﻣﻲﮔﺮﺩﺩ‪ .‬ﺣﺎﻻ ‪ hi=2‬ﻭ ‪ lo=0‬ﺍﺳﺖ ﻭ ﺩﻭﺑﺎﺭﻩ ﻋﻨﺼﺮ‬
‫ﻭﺳﻂ ﺁﺭﺍﻱۀ ]‪ a[0..2‬ﻳﻌﻨﻲ ]‪ a[1‬ﺑﺎ ‪ x‬ﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ‪ a[1] .‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 33‬ﺍﺳﺖ ﮐﻪ‬
‫ﮐﻮﭼﮏﺗﺮ ﺍﺯ ‪ x‬ﻣﻲﺑﺎﺷﺪ‪ .‬ﭘﺲ ﺍﻳﻦ ﺩﻓﻌﻪ ‪ lo‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ i+1‬ﻳﻌﻨﻲ ‪ 2‬ﻣﻲﺷﻮﺩ‪ .‬ﺩﺭ ﺳﻮﻣﻴﻦ‬
‫ﺩﻭﺭ ﺣﻠﻘﻪ‪ hi=2 ،‬ﻭ ‪ lo=2‬ﺍﺳﺖ‪ .‬ﭘﺲ ﻋﻨﺼﺮ ﻭﺳﻂ ﺁﺭﺍﻱۀ ]‪ a[2..2‬ﮐﻪ ﻫﻤﺎﻥ‬
‫]‪ a[2‬ﺍﺳﺖ ﺑﺎ ‪ x‬ﻣﻘﺎﻳﺴﻪ ﻣﻲﺷﻮﺩ‪a[2] .‬‬
‫‪lo‬‬ ‫‪hi‬‬ ‫‪i‬‬ ‫]‪a[i‬‬ ‫??‬ ‫‪x‬‬
‫‪0‬‬ ‫‪6‬‬ ‫‪3‬‬ ‫‪55‬‬ ‫>‬ ‫‪44‬‬
‫ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 44‬ﺍﺳﺖ ﮐﻪ ﺑﺎ ‪ x‬ﺑﺮﺍﺑﺮ ﺍﺳﺖ‪ .‬ﭘﺲ‬
‫‪2‬‬ ‫‪1‬‬ ‫‪33‬‬ ‫<‬ ‫‪44‬‬ ‫ﻣﻘﺪﺍﺭ ‪ 2‬ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ؛ ﻳﻌﻨﻲ ‪x‬‬
‫‪2‬‬ ‫‪2‬‬ ‫‪44‬‬ ‫==‬ ‫‪44‬‬ ‫ﻣﻮﺭﺩ ﻧﻈﺮ ﺩﺭ ]‪ a[2‬ﻭﺟﻮﺩ ﺩﺍﺭﺩ‪.‬‬

‫ﺣﺎﻝ ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ index(60,a,7‬ﺭﺍ ﺩﻧﺒﺎﻝ ﻣﻲﮐﻨﻴﻢ‪ .‬ﻭﻗﺘﻲ ﺣﻠﻘﻪ ﺷﺮﻭﻉ‬


‫ﻣﻲﺷﻮﺩ‪ x=60 ،‬ﻭ ‪ n=7‬ﻭ ‪ lo=0‬ﻭ ‪ hi=6‬ﺍﺳﺖ‪ .‬ﻋﻨﺼﺮ ﻭﺳﻂ ﺁﺭﺍﻱۀ ]‪a[0..6‬‬
‫ﻋﻨﺼﺮ ‪ a[3]=55‬ﺍﺳﺖ ﮐﻪ ﺍﺯ ‪ x‬ﮐﻮﭼﮏﺗﺮ ﺍﺳﺖ‪ .‬ﭘﺲ ‪ lo‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ i+1=4‬ﻣﻲﺷﻮﺩ ﻭ‬
‫ﺣﻠﻘﻪ ﺩﻭﺑﺎﺭﻩ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﺩﻓﻌﻪ ‪ hi=6‬ﻭ ‪ lo=4‬ﺍﺳﺖ ‪ .‬ﻋﻨﺼﺮ ﻭﺳﻂ ﺁﺭﺍﻱۀ‬
‫]‪ a[4..6‬ﻋﻨﺼﺮ ‪ a[5]=77‬ﺍﺳﺖ ﮐﻪ ﺑﺰﺭﮒﺗﺮ ﺍﺯ ‪ x‬ﻣﻲﺑﺎﺷﺪ‪ .‬ﭘﺲ ‪ hi‬ﺑﻪ ‪i-1=4‬‬
‫ﺗﻐﻴﻴﺮ ﻣﻲﻳﺎﺑﺪ ﻭ ﺩﻭﺑﺎﺭﻩ ﺣﻠﻘﻪ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﺑﺎﺭ ‪ hi=4‬ﻭ ‪ lo=4‬ﺍﺳﺖ ﻭ ﻋﻨﺼﺮ‬
‫ﻭﺳﻂ ﺁﺭﺍﻱۀ ]‪ a[4..4‬ﻋﻨﺼﺮ ‪ a[4]=66‬ﺍﺳﺖ ﮐﻪ ﺑﺰﺭﮒﺗﺮ ﺍﺯ ‪ x‬ﻣﻲﺑﺎﺷﺪ‪ .‬ﻟﺬﺍ ‪ hi‬ﺑﻪ‬
‫‪ i-1=3‬ﮐﺎﻫﺶ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺍﮐﻨﻮﻥ ﺷﺮﻁ ﺣﻠﻘﻪ‬
‫‪lo‬‬ ‫‪hi‬‬ ‫‪i‬‬ ‫]‪a[i‬‬ ‫??‬ ‫‪x‬‬
‫ﻏﻠﻂ ﻣﻲﺷﻮﺩ ﺯﻳﺮﺍ ‪ hi<lo‬ﺍﺳﺖ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ‬
‫‪0‬‬ ‫‪6‬‬ ‫‪3‬‬ ‫‪55‬‬ ‫<‬ ‫‪60‬‬
‫‪4‬‬ ‫‪5‬‬ ‫‪77‬‬ ‫>‬ ‫‪60‬‬ ‫ﺗﺎﺑﻊ ﻣﻘﺪﺍﺭ ‪ 7‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻳﻌﻨﻲ ﻋﻨﺼﺮ‬
‫‪4‬‬ ‫‪4‬‬ ‫‪66‬‬ ‫>‬ ‫‪60‬‬ ‫ﻣﻮﺭﺩ ﻧﻈﺮ ﺩﺭ ﺁﺭﺍﻳﻪ ﻣﻮﺟﻮﺩ ﻧﻴﺴﺖ‪.‬‬
‫‪193‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫ﺩﺭ ﺗﺎﺑﻊ ﻓﻮﻕ ﻫﺮ ﺑﺎﺭ ﮐﻪ ﺣﻠﻘﻪ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ‪ ،‬ﻣﺤﺪﻭﺩۀ ﺟﺴﺘﺠﻮ ‪ %50‬ﮐﻮﭼﮏﺗﺮ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺩﺭ ﺁﺭﺍﻱۀ ‪ n‬ﻋﻨﺼﺮﻱ‪ ،‬ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺣﺪﺍﮐﺜﺮ ﺑﻪ ‪ log 2 n + 1‬ﻣﻘﺎﻳﺴﻪ‬
‫ﻧﻴﺎﺯ ﺩﺍﺭﺩ ﺗﺎ ﺑﻪ ﭘﺎﺳﺦ ﺑﺮﺳﺪ‪ .‬ﺣﺎﻝ ﺁﻥ ﮐﻪ ﺩﺭ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ ﺑﻪ ‪ n‬ﻣﻘﺎﻳﺴﻪ ﻧﻴﺎﺯ‬
‫ﺍﺳﺖ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺩﺭ ﻳﮏ ﺁﺭﺍﻳﻪ ‪ 100‬ﻋﻨﺼﺮﻱ ﺑﺮﺍﻱ ﻣﺸﺨﺺ ﺷﺪﻥ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ﻣﻮﺭﺩ‬
‫ﻧﻈﺮ ﺩﺭ ﺁﺭﺍﻳﻪ ﻫﺴﺖ ﻳﺎ ﺧﻴﺮ ﺩﺭ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﺑﻪ ‪log 2 100 + 1 = 7.64‬‬
‫ﻣﻘﺎﻳﺴﻪ ﻧﻴﺎﺯ ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﺣﺪﺍﮐﺜﺮ ﺑﺎ ‪ 8‬ﻣﻘﺎﻳﺴﻪ ﺑﻪ ﭘﺎﺳﺦ ﻣﻲﺭﺳﻴﻢ ﻭﻟﻲ ﺩﺭ ﺭﻭﺵ ﺟﺴﺘﺠﻮﻱ‬
‫ﺧﻄﻲ ﺭﻭﻱ ﻫﻤﻴﻦ ﺁﺭﺍﻳﻪ ﺑﻪ ﺣﺪﺍﮐﺜﺮ ‪ 100‬ﻣﻘﺎﻳﺴﻪ ﻧﻴﺎﺯ ﺩﺍﺭﻳﻢ‪ .‬ﭘﺲ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ‬
‫ﺳﺮﻳﻊﺗﺮ ﺍﺯ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ ﺍﺳﺖ‪ .‬ﺩﻭﻣﻴﻦ ﺗﻔﺎﻭﺕ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﮔﺮ ﭼﻨﺪ ﻋﻨﺼﺮ ﺩﺍﺭﺍﻱ‬
‫ﻣﻘﺎﺩﻳﺮ ﻳﮑﺴﺎﻧﻲ ﺑﺎﺷﻨﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ ﻫﻤﻴﺸﻪ ﮐﻮﭼﮏﺗﺮﻳﻦ ﺍﻳﻨﺪﮐﺲ ﺭﺍ‬
‫ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭﻟﻲ ﺩﺭ ﻣﻮﺭﺩ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﻧﻤﻲﺗﻮﺍﻥ ﮔﻔﺖ ﮐﻪ ﮐﺪﺍﻡ ﺍﻳﻨﺪﮐﺲ‬
‫ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺳﻮﻣﻴﻦ ﻓﺮﻕ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﻓﻘﻂ ﺭﻭﻱ‬
‫ﺁﺭﺍﻳﻪﻫﺎﻱ ﻣﺮﺗﺐ ﮐﺎﺭﺍﻳﻲ ﺩﺍﺭﺩ ﻭ ﺍﮔﺮ ﺁﺭﺍﻳﻪﺍﻱ ﻣﺮﺗﺐ ﻧﺒﺎﺷﺪ‪ ،‬ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ ﭘﺎﺳﺦ ﻏﻠﻂ‬
‫ﻣﻲﺩﻫﺪ ﻭﻟﻲ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ ﻫﻤﻴﺸﻪ ﭘﺎﺳﺦ ﺻﺤﻴﺢ ﺧﻮﺍﻫﺪ ﺩﺍﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐15‬ﻣﺸﺨﺺ ﻛﺮﺩﻥ ﺍﻳﻦ ﻛﻪ ﺁﻳﺎ ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﮏ ﺗﺎﺑﻊ ﺑﻮﻟﻲ ﺭﺍ ﺁﺯﻣﺎﻳﺶ ﻣﻲﮐﻨﺪ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ ﻣﺸﺨﺺ ﻣﻲﻧﻤﺎﻳﺪ ﮐﻪ ﺁﻳﺎ‬
‫ﺁﺭﺍﻱۀ ﺩﺍﺩﻩ ﺷﺪﻩ ﻏﻴﺮ ﻧﺰﻭﻟﻲ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ‪:‬‬
‫;)‪bool isNondecreasing(int a[], int n‬‬
‫)(‪int main‬‬
‫;} ‪{ int a[] = { 22, 44, 66, 88, 44, 66, 55‬‬
‫)‪cout << "isNondecreasing(a,4) = " << isNondecreasing(a,4‬‬
‫;‪<< endl‬‬
‫)‪cout << "isNondecreasing(a,7) = " << isNondecreasing(a,7‬‬
‫;‪<< endl‬‬
‫}‬
‫)‪bool isNondecreasing(int a[], int n‬‬
‫‪{ // returns true iff a[0] <= a[1] <= ... <= a[n-1]:‬‬
‫)‪for (int i=1; i<n; i++‬‬
‫;‪if (a[i]<a[i-1]) return false‬‬
‫;‪return true‬‬
‫}‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪194‬‬

‫‪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‬ﺗﻌﺮﻳﻒ‬
‫ﺷﺪﻩ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐16‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ )(‪ assert‬ﺑﺮﺍﻱ ﺭﻋﺎﻳﺖ ﻛﺮﺩﻥ ﻳﻚ ﭘﻴﺶﺷﺮﻁ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻧﺴﺦۀ ﺑﻬﺒﻮﺩﻳﺎﻓﺘﻪﺍﻱ ﺍﺯ ﺗﺎﺑﻊ )(‪ search‬ﻣﺜﺎﻝ ‪ 6‐14‬ﺭﺍ ﺁﺯﻣﺎﻳﺶ‬
‫ﻣﻲﮐﻨﺪ‪ .‬ﺩﺭ ﺍﻳﻦ ﻧﺴﺨﻪ‪ ،‬ﺍﺯ ﺗﺎﺑﻊ )(‪ isNonDecreasing‬ﻣﺜﺎﻝ ‪ 6‐15‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‬
‫ﺗﺎ ﻣﺸﺨﺺ ﺷﻮﺩ ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﺍﺳﺖ ﻳﺎ ﺧﻴﺮ‪ .‬ﻧﺘﻴﺠﻪ ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﻪ ﺗﺎﺑﻊ )(‪ assert‬ﺍﺭﺳﺎﻝ‬
‫ﻣﻲﮔﺮﺩﺩ ﺗﺎ ﺍﮔﺮ ﺁﺭﺍﻳﻪ ﻣﺮﺗﺐ ﻧﺒﺎﺷﺪ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺑﻴﺮﺍﻫﻪ ﻧﺮﻭﺩ‪:‬‬
‫>‪#include <cassert‬‬ ‫‪// defines the assert() function‬‬
‫>‪#include <iostream‬‬ ‫‪// defines the cout object‬‬
‫;‪using namespace std‬‬
‫;)‪int index(int x, int a[], int n‬‬
‫)(‪int main‬‬
‫;} ‪{ int a[] = { 22, 33, 44, 55, 66, 77, 88, 60‬‬
‫;‪cout << "index(44,a,7) = " << index(44,a,7) << endl‬‬
‫;‪cout << "index(44,a,8) = " << index(44,a,8) << endl‬‬

‫‪1 - Precondition‬‬
‫‪195‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫;‪cout << "index(60,a,8) = " << index(60,a,8) << endl‬‬


‫}‬
‫;)‪bool isNondecreasing(int a[], int n‬‬
‫)‪int index(int x, int a[], int n‬‬
‫;]‪{ // PRECONDITION: a[0] <= a[1] <= ... <= a[n-1‬‬
‫‪// binary search:‬‬
‫;))‪assert(isNondecreasing(a,n‬‬
‫;‪int lo=0, hi=n-1, i‬‬
‫)‪while (lo <= hi‬‬
‫;‪{ i = (lo + hi)/2‬‬
‫;‪if (a[i] == x) return i‬‬
‫;‪if (a[i] < x) lo = i+1‬‬ ‫]‪// continue search in a[i+1..hi‬‬
‫;‪else hi = i-1‬‬ ‫]‪// continue search in a[0..n-1‬‬
‫}‬
‫;‪return n‬‬ ‫]‪// x was not found in a[0..n-1‬‬
‫}‬
‫‪index(44,a,7) = 2‬‬

‫ﺁﺭﺍﻱۀ ][‪ a‬ﮐﻪ ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﻛﺎﻣﻼ ﻣﺮﺗﺐ ﻧﻴﺴﺖ ﺍﻣﺎ ﻫﻔﺖ ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﻥ‬
‫ﻣﺮﺗﺐ ﺍﺳﺖ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﺭ ﻓﺮﺍﺧﻮﺍﻧﻲ)‪ index(44,a,7‬ﺗﺎﺑﻊ ﺑﻮﻟﻲ ﻣﻘﺪﺍﺭ ‪ true‬ﺭﺍ ﺑﻪ‬
‫)(‪ assert‬ﺍﺭﺳﺎﻝ ﻣﻲﮐﻨﺪ ﻭ ﺑﺮﻧﺎﻣﻪ ﺍﺩﻣﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺍﻣﺎ ﺩﺭ ﺩﻭﻣﻴﻦ ﻓﺮﺍﺧﻮﺍﻧﻲ‬
‫)‪ index(44,a,8‬ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺗﺎﺑﻊ )(‪ isNondecreasing‬ﻣﻘﺪﺍﺭ‬
‫ﺗﺎﺑﻊ‬ ‫ﺑﻪ‬ ‫ﺭﺍ‬ ‫‪false‬‬
‫)(‪ assert‬ﺍﺭﺳﺎﻝ ﮐﻨﺪ ﻛﻪ‬
‫ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ ﺑﺮﻧﺎﻣﻪ‬
‫ﻣﺘﻮﻗﻒ ﻣﻲﺷﻮﺩ ﻭ ﻭﻳﻨﺪﻭﺯ‬
‫ﭘﻨﺠﺮۀ ﻫﺸﺪﺍﺭ ﻣﻘﺎﺑﻞ ﺭﺍ‬
‫ﻧﻤﺎﻳﺶ ﻣﻲﺩﻫﺪ‪.‬‬

‫‪ 6‐9‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﺩﺭ ﺁﺭﺍﻳﻪ‬


‫ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﺩﺭ ﻓﺼﻞ ﺩﻭﻡ ﺗﻮﺿﻴﺢ ﺩﺍﺩﻩ ﺷﺪﻩﺍﻧﺪ‪ .‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﻧﻴﺰ‬
‫ﻣﻲﺗﻮﺍﻥ ﺁﺭﺍﻳﻪﻫﺎ ﺭﺍ ﭘﺮﺩﺍﺯﺵ ﻧﻤﻮﺩ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪196‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐17‬ﺷﻤﺎﺭﺵ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺭﻭﺯﻫﺎﻱ ﻫﻔﺘﻪ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻳﻚ ﺁﺭﺍﻳﻪ ﺑﻪ ﻧﺎﻡ ][‪ high‬ﺑﺎ ﻫﻔﺖ ﻋﻨﺼﺮ ﺍﺯ ﻧﻮﻉ ‪ float‬ﺗﻌﺮﻳﻒ‬
‫ﻣﻲﻛﻨﺪ ﻛﻪ ﻫﺮ ﻋﻨﺼﺮ ﺣﺪﺍﮐﺜﺮ ﺩﻣﺎ ﺩﺭ ﻳﮏ ﺭﻭﺯ ﻫﻔﺘﻪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪:‬‬
‫)(‪int main‬‬
‫;} ‪{ enum Day { SUN, MON, TUE, WED, THU, FRI, SAT‬‬
‫;}‪float high[SAT+1] = {28.6, 29.1, 29.9, 31.3, 30.4, 32.0, 30.7‬‬
‫)‪for (int day = SUN; day <= SAT; day++‬‬
‫" ‪cout << "The high temperature for day " << day << " was‬‬
‫;‪<< high[day] << endl‬‬
‫}‬
‫‪The‬‬ ‫‪high‬‬ ‫‪temperature‬‬ ‫‪for‬‬ ‫‪day‬‬ ‫‪0‬‬ ‫‪was‬‬ ‫‪28.6‬‬
‫‪The‬‬ ‫‪high‬‬ ‫‪temperature‬‬ ‫‪for‬‬ ‫‪day‬‬ ‫‪1‬‬ ‫‪was‬‬ ‫‪29.1‬‬
‫‪The‬‬ ‫‪high‬‬ ‫‪temperature‬‬ ‫‪for‬‬ ‫‪day‬‬ ‫‪2‬‬ ‫‪was‬‬ ‫‪29.9‬‬
‫‪The‬‬ ‫‪high‬‬ ‫‪temperature‬‬ ‫‪for‬‬ ‫‪day‬‬ ‫‪3‬‬ ‫‪was‬‬ ‫‪31.3‬‬
‫‪The‬‬ ‫‪high‬‬ ‫‪temperature‬‬ ‫‪for‬‬ ‫‪day‬‬ ‫‪4‬‬ ‫‪was‬‬ ‫‪30.4‬‬
‫‪The‬‬ ‫‪high‬‬ ‫‪temperature‬‬ ‫‪for‬‬ ‫‪day‬‬ ‫‪5‬‬ ‫‪was‬‬ ‫‪32.0‬‬
‫‪The‬‬ ‫‪high‬‬ ‫‪temperature‬‬ ‫‪for‬‬ ‫‪day‬‬ ‫‪6‬‬ ‫‪was‬‬ ‫‪30.7‬‬

‫ﺑﻪ ﺧﺎﻃﺮ ﺑﻴﺎﻭﺭﻳﺪ ﮐﻪ ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﺑﻪ ﺷﮑﻞ ﻣﻘﺎﺩﻳﺮ ﻋﺪﺩﻱ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺍﻧﺪﺍﺯۀ‬
‫ﺁﺭﺍﻳﻪ‪ SAT+1 ،‬ﺍﺳﺖ ﺯﻳﺮﺍ ‪ SAT‬ﻣﻘﺪﺍﺭ ﺻﺤﻴﺢ ‪ 6‬ﺭﺍ ﺩﺍﺭﺩ ﻭ ﺁﺭﺍﻳﻪ ﺑﻪ ﻫﻔﺖ ﻋﻨﺼﺮ ﻧﻴﺎﺯﻣﻨﺪ‬
‫ﺍﺳﺖ‪ .‬ﻣﺘﻐﻴﺮ ‪ day‬ﺍﺯ ﻧﻮﻉ ‪ int‬ﺍﺳﺖ ﭘﺲ ﻣﻲﺗﻮﺍﻥ ﻣﻘﺎﺩﻳﺮ ‪ Day‬ﺭﺍ ﺑﻪ ﺁﻥ ﺗﺨﺼﻴﺺ ﺩﺍﺩ‪.‬‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﺩﺭ ﺑﺮﺧﻲ ﺍﺯ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﮐﺪ ﺑﺮﻧﺎﻣﻪ »ﺧﻮﺩ ﺍﺳﺘﻨﺎﺩ«‬
‫ﺷﻮﺩ‪ .‬ﻣﺜﻼ ﺩﺭ ﻣﺜﺎﻝ ‪ 6‐17‬ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺑﻪ ﺷﮑﻞ‬
‫)‪for (int day = SUN; day <= SAT; day++‬‬

‫ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﻫﺮ ﺑﻴﻨﻨﺪﻩﺍﻱ ﺣﻠﻖۀ ‪ for‬ﺑﺎﻻ ﺭﺍ ﺑﻪ ﺧﻮﺑﻲ ﺩﺭﮎ ﮐﻨﺪ‪.‬‬

‫‪ 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‬‬

‫ﺩﺭ ﺍﻳﻦﺟﺎ ‪ shirt‬ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ ‪ Color‬ﺍﺳﺖ ﻭ ﺑﺎ ﻣﻘﺪﺍﺭ ‪ BLUE‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﺪﻩ‪.‬‬


‫‪ car‬ﻳﮏ ﺁﺭﺍﻱۀ ﭼﻬﺎﺭ ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﻭ ﻣﻘﺪﺍﺭ ﻋﻨﺎﺻﺮ ﺁﻥ ﺑﻪ ﺗﺮﺗﻴﺐ ‪ GREEN‬ﻭ ‪ RED‬ﻭ‬
‫‪ BLUE‬ﻭ ‪ RED‬ﻣﻲﺑﺎﺷﺪ‪ .‬ﻫﻤﭽﻨﻴﻦ ‪ wavelength‬ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﻧﻮﻉ ‪ float‬ﺍﺳﺖ ﮐﻪ‬
‫ﺩﺍﺭﺍﻱ ‪ VIOLET+1‬ﻋﻨﺼﺮ ﻳﻌﻨﻲ ‪ 5+1=6‬ﻋﻨﺼﺮ ﺍﺳﺖ‪.‬‬
‫ﺩﺭ ‪ C++‬ﻣﻲﺗﻮﺍﻥ ﻧﺎﻡ ﺍﻧﻮﺍﻉ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﺍﺩ‪ .‬ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ ‪ typedef‬ﻳﮏ‬
‫ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺑﺮﺍﻱ ﻳﮏ ﻧﻮﻉ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻣﻮﺟﻮﺩ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‪ .‬ﻧﺤﻮ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﺑﻪ ﺷﮑﻞ‬
‫ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫;‪typedef type alias‬‬

‫ﻛﻪ ‪ type‬ﻳﮏ ﻧﻮﻉ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻭ ‪ alias‬ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺑﺮﺍﻱ ﺁﻥ ﺍﺳﺖ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﮐﺴﺎﻧﻲ‬
‫ﮐﻪ ﺑﺎ ﭘﺎﺳﮑﺎﻝ ﺑﺮﻧﺎﻣﻪ ﻣﻲﻧﻮﻳﺴﻨﺪ ﺑﻪ ﺟﺎﻱ ﻧﻮﻉ ‪ long‬ﺍﺯ ﻋﺒﺎﺭﺕ ‪ Integer‬ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﻣﻲﮐﻨﻨﺪ ﻭ ﺑﻪ ﺟﺎﻱ ﻧﻮﻉ ‪ double‬ﺍﺯ ﻋﺒﺎﺭﺕ ‪ Real‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﻧﻤﺎﻳﻨﺪ‪ .‬ﺍﻳﻦ ﺍﻓﺮﺍﺩ‬
‫ﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺯ ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻨﺪ‪:‬‬
‫;‪typedef long Integer‬‬
‫;‪typedef double Real‬‬

‫ﻭ ﭘﺲ ﺍﺯ ﺁﻥ ﮐﺪﻫﺎﻱ ﺯﻳﺮ ﻣﻌﺘﺒﺮ ﺧﻮﺍﻫﻨﺪ ﺑﻮﺩ‪:‬‬


‫;‪Integer n = 22‬‬
‫;‪const Real PI = 3.141592653589793‬‬
‫;]‪Integer frequency[64‬‬

‫ﺍﮔﺮ ﺩﺳﺘﻮﺭ ‪ typedef‬ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺑﮑﺎﺭ ﺑﺒﺮﻳﻢ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﺭﺍﻳﻪﻫﺎ ﺭﺍ ﺑﺪﻭﻥ ﻋﻼﻣﺖ‬
‫ﺑﺮﺍﮐﺖ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ‪:‬‬
‫;][‪typedef element-type alias‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪198‬‬

‫ﻣﺜﻞ ﺗﻌﺮﻳﻒ ﺯﻳﺮ ‪:‬‬


‫;][‪typedef float sequence‬‬

‫ﺳﭙﺲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﺭﺍﻱۀ ‪ a‬ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﻋﻼﻥ ﮐﻨﻴﻢ‪:‬‬


‫;}‪sequence a = {55.5, 22.2, 99.9‬‬

‫ﺩﺳﺘﻮﺭ ‪ typedef‬ﻧﻮﻉ ﺟﺪﻳﺪﻱ ﺭﺍ ﺍﻋﻼﻥ ﻧﻤﻲﮐﻨﺪ‪ ،‬ﺑﻠﮑﻪ ﻓﻘﻂ ﺑﻪ ﻳﮏ ﻧﻮﻉ ﻣﻮﺟﻮﺩ‬


‫ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭﻱ ﺭﺍ ﻧﺴﺒﺖ ﻣﻲﺩﻫﺪ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﺤﻮۀ ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ‪ typedef‬ﺭﺍ ﻧﺸﺎﻥ‬
‫ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐18‬ﺩﻭﺑﺎﺭﻩ ﻣﺮﺗﺐﺳﺎﺯﻱ ﺣﺒﺎﺑﻲ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻫﻤﺎﻥ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 6‐13‬ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﻓﺮﻕ ﮐﻪ ﺍﺯ ‪ typedef‬ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﺷﺪﻩ ﺗﺎ ﺑﺘﻮﺍﻥ ﺍﺯ ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ‪ sequrnce‬ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﻧﻮﻉ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪ .‬ﺳﭙﺲ ﺍﻳﻦ ﻧﻮﻉ‬
‫ﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎ ﻭ ﺍﻋﻼﻥ ‪ a‬ﺩﺭ ﺗﺎﺑﻊ )(‪ main‬ﺑﻪ ﮐﺎﺭ ﺭﻓﺘﻪ ﺍﺳﺖ‪:‬‬
‫;][‪typedef float Sequence‬‬
‫;)‪void sort(Sequence,int‬‬
‫;)‪void print(Sequence,int‬‬
‫)(‪int main‬‬
‫{‬ ‫;}‪Sequence 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(Sequence a, int n‬‬
‫)‪{ for (int i=n-1; i>0; i--‬‬
‫)‪for (int j=0; j<i; j++‬‬
‫;)]‪if (a[j] > a[j+1]) swap(a[j],a[j+1‬‬
‫}‬

‫ﺩﻭﺑﺎﺭﻩ ﺑﻪ ﺩﺳﺘﻮﺭ ‪ typedef‬ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪:‬‬


‫;][‪typedef float Seguence‬‬
‫‪199‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫ﻋﻼﻣﺖ ﺑﺮﺍﻛﺖﻫﺎ ][ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ ﮐﻪ ﻫﺮ ﭼﻴﺰﻱ ﮐﻪ ﺍﺯ ﻧﻮﻉ ‪Sequence‬‬


‫ﺗﻌﺮﻳﻒ ﺷﻮﺩ‪ ،‬ﻳﮏ ﺁﺭﺍﻳﻪ ﺍﺳﺖ ﻭ ﻋﺒﺎﺭﺕ ‪ float‬ﻧﻴﺰ ﺑﻴﺎﻥ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺍﺯ ﻧﻮﻉ‬
‫‪ float‬ﺍﺳﺖ‪.‬‬

‫‪ 6‐11‬ﺁﺭﺍﻳﻪﻫﺎﻱ ﭼﻨﺪ ﺑﻌﺪﻱ‬


‫ﻫﻢۀ ﺁﺭﺍﻳﻪﻫﺎﻳﻲ ﻛﻪ ﺗﺎﮐﻨﻮﻥ ﺗﻌﺮﻳﻒ ﮐﺮﺩﻳﻢ‪ ،‬ﻳﮏ ﺑﻌﺪﻱ ﻫﺴﺘﻨﺪ‪ ،‬ﺧﻄﻲ ﻫﺴﺘﻨﺪ‪،‬‬
‫ﺭﺷﺘﻪﺍﻱ ﻫﺴﺘﻨﺪ‪ .‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﺭﺍﻳﻪﺍﻱ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﮐﻪ ﺍﺯ ﻧﻮﻉ ﺁﺭﺍﻳﻪ ﺑﺎﺷﺪ‪ ،‬ﻳﻌﻨﻲ ﻫﺮ ﺧﺎﻧﻪ ﺍﺯ‬
‫ﺁﻥ ﺁﺭﺍﻳﻪ‪ ،‬ﺧﻮﺩ ﻳﮏ ﺁﺭﺍﻳﻪ ﺑﺎﺷﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﻗﺒﻴﻞ ﺁﺭﺍﻳﻪﻫﺎ‪ ،‬ﺁﺭﺍﻳﻪﻫﺎﻱ ﭼﻨﺪﺑﻌﺪﻱ‪ 1‬ﻣﻲﮔﻮﻳﻴﻢ‪ .‬ﻳﮏ‬
‫ﺁﺭﺍﻱۀ ﺩﻭ ﺑﻌﺪﻱ ﺁﺭﺍﻳﻪﺍﻱ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﺧﺎﻧﻪ ﺍﺯ ﺁﻥ‪ ،‬ﺧﻮﺩ ﻳﮏ ﺁﺭﺍﻱۀ ﻳﮏ ﺑﻌﺪﻱ ﺑﺎﺷﺪ‪ .‬ﻳﮏ‬
‫ﺁﺭﺍﻱۀ ﺳﻪ ﺑﻌﺪﻱ ﺁﺭﺍﻳﻪﺍﻱ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﺧﺎﻧﻪ ﺍﺯ ﺁﻥ ﻳﮏ ﺁﺭﺍﻱۀ ﺩﻭ ﺑﻌﺪﻱ ﺑﺎﺷﺪ‪.‬‬
‫ﺩﺳﺘﻮﺭ ;]‪ int a[5‬ﺁﺭﺍﻳﻪﺍﻱ ﺑﺎ ﭘﻨﺞ ﻋﻨﺼﺮ ﺍﺯ ﻧﻮﻉ ‪ int‬ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ‪ .‬ﺍﻳﻦ ﻳﮏ‬
‫ﺁﺭﺍﻱۀ ﻳﮏ ﺑﻌﺪﻱ ﺍﺳﺖ‪ .‬ﺩﺳﺘﻮﺭ ;]‪ int a[3][5‬ﺁﺭﺍﻳﻪﺍﻱ ﺑﺎ ﺳﻪ ﻋﻨﺼﺮ ﺗﻌﺮﻳﻒ‬
‫ﻣﻲﮐﻨﺪ ﮐﻪ ﻫﺮ ﻋﻨﺼﺮ‪ ،‬ﺧﻮﺩ ﻳﮏ ﺁﺭﺍﻱۀ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﺍﺯ ﻧﻮﻉ ‪ int‬ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﻳﮏ ﺁﺭﺍﻱۀ‬
‫ﺩﻭ ﺑﻌﺪﻱ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﻣﺠﻤﻮﻉ ﭘﺎﻧﺰﺩﻩ ﻋﻀﻮ ﺩﺍﺭﺩ‪ .‬ﺩﺳﺘﻮﺭ ;]‪int a[2][3][5‬‬
‫ﺁﺭﺍﻳﻪﺍﻱ ﺑﺎ ﺩﻭ ﻋﻨﺼﺮ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﻫﺮ ﻋﻨﺼﺮ‪ ،‬ﺳﻪ ﺁﺭﺍﻳﻪ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﺁﺭﺍﻳﻪ ﭘﻨﺞ ﻋﻀﻮ‬
‫ﺍﺯ ﻧﻮﻉ ‪ int‬ﺩﺍﺭﺩ‪ .‬ﺍﻳﻦ ﻳﮏ ﺁﺭﺍﻱۀ ﺳﻪ ﺑﻌﺪﻱ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﻣﺠﻤﻮﻉ ﺳﻲ ﻋﻀﻮ ﺩﺍﺭﺩ‪ .‬ﺑﻪ‬
‫ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﻣﻲﺗﻮﺍﻥ ﺁﺭﺍﻳﻪﻫﺎﻱ ﭼﻨﺪ ﺑﻌﺪﻱ ﺗﻌﺮﻳﻒ ﻧﻤﻮﺩ‪.‬‬
‫ﺷﮑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﺑﻪ ﻋﻨﺎﺻﺮ ﺩﺭ ﺁﺭﺍﻳﻪﻫﺎﻱ ﭼﻨﺪ ﺑﻌﺪﻱ ﻣﺎﻧﻨﺪ ﺁﺭﺍﻳﻪﻫﺎﻱ ﻳﮏ ﺑﻌﺪﻱ ﺍﺳﺖ‪.‬‬
‫ﻣﺜﻼ ﺩﺳﺘﻮﺭ‬
‫;‪a[1][2][3] = 99‬‬

‫ﻣﻘﺪﺍﺭ ‪ 99‬ﺭﺍ ﺩﺭ ﻋﻨﺼﺮﻱ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﻳﻨﺪﮐﺲ ﺁﻥ ﻋﻨﺼﺮ)‪ (1,2,3‬ﺍﺳﺖ‪.‬‬


‫ﺁﺭﺍﻳﻪﻫﺎﻱ ﭼﻨﺪ ﺑﻌﺪﻱ ﻣﺜﻞ ﺁﺭﺍﻳﻪﻫﺎﻱ ﻳﮏ ﺑﻌﺪﻱ ﺑﻪ ﺗﻮﺍﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ ﺑﺎ ﺍﻳﻦ‬
‫ﺗﻔﺎﻭﺕ ﮐﻪ ﻫﻨﮕﺎﻡ ﺍﻋﻼﻥ ﻭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﻣﺮﺑﻮﻃﻪ‪ ،‬ﺑﺎﻳﺪ ﺗﻌﺪﺍﺩ ﻋﻨﺎﺻﺮ ﺑﻌﺪ ﺩﻭﻡ ﺗﺎ ﺑﻌﺪ ﺁﺧﺮ‬
‫ﺣﺘﻤﺎ ﺫﮐﺮ ﺷﻮﺩ‪.‬‬

‫‪1 – Multi dimensional arrays‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪200‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐19‬ﻧﻮﺷﺘﻦ ﻭ ﺧﻮﺍﻧﺪﻥ ﻳﻚ ﺁﺭﺍﻱۀ ﺩﻭ ﺑﻌﺪﻱ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻳﮏ ﺁﺭﺍﻱۀ ﺩﻭﺑﻌﺪﻱ ﭼﮕﻮﻧﻪ ﭘﺮﺩﺍﺯﺵ ﻣﻲﺷﻮﺩ‪:‬‬
‫;)]‪void read(int a[][5‬‬
‫;)]‪void print(int a[][5‬‬
‫)(‪int main‬‬
‫;]‪{ int a[3][5‬‬
‫;)‪read(a‬‬
‫;)‪print(a‬‬
‫}‬
‫)]‪void read(int a[][5‬‬
‫;"‪{ cout << "Enter 15 integers, 5 per row:\n‬‬
‫)‪for (int i=0; i<3; i++‬‬
‫;" ‪{ cout << "ROW " << i << ":‬‬
‫)‪for (int j=0; j<5; j++‬‬
‫;]‪cin >> a[i][j‬‬
‫}‬
‫}‬
‫)]‪void print(const int a[][5‬‬
‫)‪{ for (int i=0; i<3; i++‬‬
‫)‪{ for (int j=0; j<5; j++‬‬
‫;]‪cout << " " << a[i][j‬‬
‫;‪cout << endl‬‬
‫}‬
‫}‬
‫‪Enter 15 integers, 5 per row:‬‬
‫‪row‬‬ ‫‪0:‬‬ ‫‪44‬‬ ‫‪77‬‬ ‫‪33 11 44‬‬
‫‪row‬‬ ‫‪1:‬‬ ‫‪60‬‬ ‫‪50‬‬ ‫‪30 90 70‬‬
‫‪row‬‬ ‫‪2:‬‬ ‫‪65‬‬ ‫‪25‬‬ ‫‪45 45 55‬‬
‫‪44‬‬ ‫‪77‬‬ ‫‪33‬‬ ‫‪11‬‬ ‫‪44‬‬
‫‪60‬‬ ‫‪50‬‬ ‫‪30‬‬ ‫‪90‬‬ ‫‪70‬‬
‫‪65‬‬ ‫‪25‬‬ ‫‪45‬‬ ‫‪45‬‬ ‫‪55‬‬

‫ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺩﺭ ﻓﻬﺮﺳﺖ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﻮﺍﺑﻊ ﺑﺎﻻ‪ ،‬ﺑﻌﺪ ﺍﻭﻝ ﻧﺎﻣﺸﺨﺺ ﺍﺳﺖ ﺍﻣﺎ ﺑﻌﺪ ﺩﻭﻡ‬
‫ﻣﺸﺨﺺ ﺷﺪﻩ‪ .‬ﻋﻠﺖ ﻫﻢ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺁﺭﺍﻱۀ ﺩﻭ ﺑﻌﺪﻱ ][][‪ a‬ﺩﺭ ﺣﻘﻴﻘﺖ ﺁﺭﺍﻳﻪﺍﻱ‬
‫ﻳﮏﺑﻌﺪﻱ ﺍﺯ ﺳﻪ ﺁﺭﺍﻱۀ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﺍﺳﺖ‪ .‬ﮐﺎﻣﭙﺎﻳﻠﺮ ﻧﻴﺎﺯ ﻧﺪﺍﺭﺩ ﺑﺪﺍﻧﺪ ﮐﻪ ﭼﻪ ﺗﻌﺪﺍﺩ ﺍﺯ ﺍﻳﻦ‬
‫ﺁﺭﺍﻳﻪﻫﺎﻱ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﻣﻮﺟﻮﺩ ﺍﺳﺖ‪ ،‬ﺍﻣﺎ ﺑﺎﻳﺪ ﺑﺪﺍﻧﺪ ﮐﻪ ﺁﻥﻫﺎ ﭘﻨﺞ ﻋﻨﺼﺮﻱ ﻫﺴﺘﻨﺪ‪.‬‬
201 ‫ ﺁراﻳﻪهﺎ‬/ ‫ﻓﺼﻞ ﺷﺸﻢ‬

‫ ﺑﻌﺪ ﺍﻭﻝ ﻣﺸﺨﺺ ﻧﻴﺴﺖ ﺍﻣﺎ‬،‫ﻭﻗﺘﻲ ﻳﮏ ﺁﺭﺍﻱۀ ﭼﻨﺪ ﺑﻌﺪﻱ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ‬
.‫ﻫﻢۀ ﺍﺑﻌﺎﺩ ﺩﻳﮕﺮ ﺑﺎﻳﺪ ﻣﺸﺨﺺ ﺑﺎﺷﻨﺪ‬

‫ ﭘﺮﺩﺍﺯﺵ ﻳﻚ ﺁﺭﺍﻱۀ ﺩﻭﺑﻌﺪﻱ ﺍﺯ ﻧﻤﺮﺍﺕ ﺍﻣﺘﺤﺎﻧﻲ‬6‐20 ‫* ﻣﺜﺎﻝ‬


const NUM_STUDENTS = 3;
const NUM_QUIZZES = 5;
typedef int Score[NUM_STUDENTS][NUM_QUIZZES];
void read(Score);
void printQuizAverages(Score);
void printClassAverages(Score);
int main()
{ Score score;
cout << "Enter " << NUM_QUIZZES
<< " quiz scores for each student:\n";
read(score);
cout << "The quiz averages are:\n";
printQuizAverages(score);
cout << "The class averages are:\n";
printClassAverages(score);
}
void read(Score score)
{ for (int s=0; s<NUM_STUDENTS; s++)
{ cout << "Student " << s << ": ";
for (int q=0; q<NUM_QUIZZES; q++)
cin >> score[s][q];
}
}
void printQuizAverages(Score score)
{ for (int s=0; s<NUM_STUDENTS; s++)
{ float sum = 0.0;
for (int q=0; q<NUM_QUIZZES; q++)
sum += score[s][q];
cout << "\tStudent " << s << ": " << sum/NUM_QUIZZES
<< endl;
}
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪202‬‬

‫}‬
‫)‪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‬‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻓﻮﻕ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ ‪ typedef‬ﺑﺮﺍﻱ ﺁﺭﺍﻳﻪﻫﺎﻱ ﺩﻭﺑﻌﺪﻱ ‪ 3*5‬ﻧﺎﻡ‬


‫ﻣﺴﺘﻌﺎﺭ ‪ Score‬ﺍﻧﺘﺨﺎﺏ ﺷﺪﻩ‪ .‬ﺍﻳﻦ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺗﻮﺍﺑﻊ ﺧﻮﺍﻧﺎﺗﺮ ﺑﺎﺷﻨﺪ‪ .‬ﻫﺮ ﺗﺎﺑﻊ ﺍﺯ ﺩﻭ‬
‫ﺣﻠﻖۀ ‪ for‬ﺗﻮﺩﺭﺗﻮ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩ ﮐﻪ ﺣﻠﻖۀ ﺑﻴﺮﻭﻧﻲ‪ ،‬ﺑﻌﺪ ﺍﻭﻝ ﺭﺍ ﭘﻴﻤﺎﻳﺶ ﻣﻲﮐﻨﺪ ﻭ ﺣﻠﻖۀ‬
‫ﺩﺭﻭﻧﻲ ﺑﻌﺪ ﺩﻭﻡ ﺭﺍ ﭘﻴﻤﺎﻳﺶ ﻣﻲ ﻧﻤﺎﻳﺪ‪.‬‬
‫ﺗﺎﺑﻊ )(‪ printQuizAverages‬ﻣﻴﺎﻧﮕﻴﻦ ﻫﺮ ﺳﻄﺮ ﺍﺯ ﻧﻤﺮﺍﺕ ﺭﺍ ﻣﺤﺎﺳﺒﻪ ﻭ‬
‫ﭼﺎﭖ ﻣﻲﻧﻤﺎﻳﺪ ﻭ ﺗﺎﺑﻊ )(‪ printClassAverages‬ﻣﻴﺎﻧﮕﻴﻦ ﻫﺮ ﺳﺘﻮﻥ ﺍﺯ ﻧﻤﺮﻩﻫﺎ ﺭﺍ‬
‫ﭼﺎﭖ ﻣﻲﻛﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 6‐21‬ﭘﺮﺩﺍﺯﺵ ﻳﻚ ﺁﺭﺍﻱۀ ﺳﻪ ﺑﻌﺪﻱ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺗﻌﺪﺍﺩ ﺻﻔﺮﻫﺎ ﺭﺍ ﺩﺭ ﻳﻚ ﺁﺭﺍﻱۀ ﺳﻪ ﺑﻌﺪﻱ ﻣﻲﺷﻤﺎﺭﺩ‪:‬‬
‫‪203‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫;)‪int numZeros(int a[][4][3], int n1, int n2, int n3‬‬


‫)(‪int main‬‬
‫‪{ 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‬‬
‫)‪cout << "This array has " << numZeros(a,2,4,3‬‬
‫;"‪<< " zeros:\n‬‬
‫}‬
‫)‪int numZeros(int a[][4][3], int n1, int n2, int n3‬‬
‫;‪{ int count = 0‬‬
‫)‪for (int i = 0; i < n1; i++‬‬
‫)‪for (int j = 0; j < n2; j++‬‬
‫)‪for (int k = 0; k < n3; k++‬‬
‫;‪if (a[i][j][k] == 0) ++count‬‬
‫;‪return count‬‬
‫}‬
‫‪This array has 11 zeros:‬‬

‫ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺁﺭﺍﻳﻪ ﭼﮕﻮﻧﻪ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﻗﺎﻟﺐ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﻪ ﺧﻮﺑﻲ ﻧﻤﺎﻳﺎﻥ‬
‫ﻣﻲﮐﻨﺪ ﮐﻪ ﺁﺭﺍﻱۀ ﻣﺬﮐﻮﺭ ﻳﮏ ﺁﺭﺍﻳﻪ ﺩﻭ ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﻋﻨﺼﺮ‪ ،‬ﺧﻮﺩ ﻳﮏ ﺁﺭﺍﻱۀ‬
‫ﭼﻬﺎﺭ ﻋﻀﻮﻱ ﺍﺳﺖ ﮐﻪ ﻫﺮ ﻋﻀﻮ ﺷﺎﻣﻞ ﺁﺭﺍﻳﻪﺍﻱ ﺳﻪ ﻋﻨﺼﺮﻱ ﻣﻲﺑﺎﺷﺪ‪ .‬ﭘﺲ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺩﺭ‬
‫ﻣﺠﻤﻮﻉ ‪ 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‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫‪ – 6‬ﺍﮔﺮ ﺍﻳﻨﺪﮐﺲ ﺁﺭﺍﻳﻪ ﺍﺯ ﺗﻌﺪﺍﺩ ﺍﻋﻀﺎﻱ ﺁﻥ ﺑﻴﺸﺘﺮ ﺷﻮﺩ ﺁﻧﮕﺎﻩ‪:‬‬


‫ﺍﻟﻒ – ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﺮﻧﺎﻣﻪ ﻣﺘﻮﻗﻒ ﺷﻮﺩ ﺯﻳﺮﺍ ﺍﺛﺮ ﻫﻤﺴﺎﻳﮕﻲ ﺭﺥ ﻣﻲﺩﻫﺪ‬
‫ﺏ – ﮐﺎﻣﭙﺎﻳﻠﺮ ﺧﻄﺎ ﻣﻲﮔﻴﺮﺩ ﻭ ﺑﺮﻧﺎﻣﻪ ﺍﺻﻼ ﺍﺟﺮﺍ ﻧﻤﻲﺷﻮﺩ‬
‫ﺝ – ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﺧﻄﺎ ﻣﻲﮔﻴﺮﺩ ﻭ ﺑﺮﻧﺎﻣﻪ ﻣﺘﻮﻗﻒ ﻣﻲﺷﻮﺩ‬
‫ﺩ – ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺑﻪ ﺗﻌﺪﺍﺩ ﺍﻋﻀﺎﻱ ﺁﺭﺍﻳﻪ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ ﺗﺎ ﺑﻪ ﺍﻧﺪﺍﺯﻩ ﺍﻳﻨﺪﮐﺲ ﺑﺮﺳﺪ‬
‫‪ – 7‬ﺍﮔﺮ ﺁﺭﺍﻱۀ ‪ a‬ﺍﺯ ﻧﻮﻉ ‪ int‬ﻭ ﺑﺎ ﭘﻨﺞ ﻋﻨﺼﺮ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﮐﺪ‬
‫;‪ float b[] = a‬ﭼﻪ ﺍﺛﺮﻱ ﺩﺍﺭﺩ؟‬
‫ﺍﻟﻒ – ﺍﻳﻦ ﮐﺪ ﺍﺷﺘﺒﺎﻩ ﺍﺳﺖ ﺯﻳﺮﺍ ﺁﺭﺍﻳﻪﻫﺎ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﻳﮑﺪﻳﮕﺮ ﺗﺨﺼﻴﺺ ﺩﺍﺩ‬
‫ﺏ – ﻣﻘﺎﺩﻳﺮ ﺁﺭﺍﻱۀ ‪ a‬ﺑﻪ ﻧﻮﻉ ‪ float‬ﺍﺭﺗﻘﺎ ﻳﺎﻓﺘﻪ ﻭ ﺳﭙﺲ ﺩﺭﻭﻥ ﺁﺭﺍﻱۀ ‪ b‬ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‬
‫ﺝ – ﺁﺭﺍﻱۀ ‪ b‬ﺑﺎ ﭘﻨﺞ ﻋﻨﺼﺮ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﺍﻋﻀﺎﻱ ﺁﺭﺍﻱۀ ‪ a‬ﺩﺭ ﺁﻥ ﮐﭙﻲ ﺷﻮﺩ‬
‫ﺩ – ﺁﺭﺍﻱۀ ‪ b‬ﺑﺎ ﭘﻨﺞ ﻋﻨﺼﺮ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﺍﻋﻀﺎﻱ ﺁﺭﺍﻱۀ ‪ a‬ﺩﺭﻭﻥ ﺁﻥ ﮐﭙﻲ ﻣﻲﺷﻮﺩ‬
‫‪ – 8‬ﺩﺳﺘﻮﺭ ;]‪ int a[2][4‬ﭼﻪ ﻋﻤﻠﻲ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ؟‬
‫ﺍﻟﻒ – ﻳﮏ ﺁﺭﺍﻱۀ ﺩﻭ ﺑﻌﺪﻱ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺩﺭ ﮐﻞ ‪ 8‬ﻋﻨﺼﺮ ﺩﺍﺭﺩ‬
‫ﺏ – ﻳﮏ ﺁﺭﺍﻱۀ ﺩﻭ ﺑﻌﺪﻱ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺩﺭ ﮐﻞ ‪ 6‬ﻋﻨﺼﺮ ﺩﺍﺭﺩ‬
‫ﺝ – ﻳﮏ ﺁﺭﺍﻱۀ ﺩﻭ ﺑﻌﺪﻱ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﻋﻨﺎﺻﺮ ﺑﻌﺪ ﺍﻭﻝ‪ ،‬ﻣﻘﺪﺍﺭ ‪2‬‬
‫ﻭ ﻣﻘﺪﺍﺭ ﭘﻴﺶﻓﺮﺽ ﻋﻨﺎﺻﺮ ﺑﻌﺪ ﺩﻭﻡ ‪ ،‬ﻣﻘﺪﺍﺭ ‪ 4‬ﺍﺳﺖ‬
‫ﺩ – ﻳﮏ ﺁﺭﺍﻱۀ ﻳﮏ ﺑﻌﺪﻱ ﺑﺎ ﺩﻭ ﻋﻀﻮ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﻣﻘﺪﺍﺭ ﻋﻀﻮ ﺍﻭﻝ ‪ 2‬ﻭ ﻣﻘﺪﺍﺭ‬
‫ﻋﻀﻮ ﺩﻭﻡ ‪ 4‬ﺍﺳﺖ‬
‫‪ – 9‬ﺍﮔﺮ ‪ a‬ﻳﮏ ﺁﺭﺍﻳﻪ ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺑﺎ ﺍﺟﺮﺍﻱ ﮐﺪ ;‪ cout << a‬ﭼﻪ ﺭﺥ ﻣﻲﺩﻫﺪ؟‬
‫ﺍﻟﻒ – ﻣﻘﺪﺍﺭ ﺍﻋﻀﺎﻱ ﺁﺭﺍﻱۀ ‪ a‬ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫ﺏ – ﺗﻌﺪﺍﺩ ﺍﻋﻀﺎﻱ ﺁﺭﺍﻱۀ ‪ a‬ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫ﺝ – ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺧﺎﻥۀ ﺁﺭﺍﻱۀ ‪ a‬ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫ﺩ – ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﺧﻄﺎ ﻣﻲﮔﻴﺮﺩ ﻭ ﭘﻴﻐﺎﻡ ﺧﻄﺎ ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫‪ – 10‬ﻓﺮﺽ ﮐﻨﻴﺪ ﺗﺎﺑﻊ )(‪ print‬ﻓﻘﻂ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺍﺭﺩ ﻭ ﺁﻥ ﻫﻢ ﺍﺯ ﻧﻮﻉ ﺁﺭﺍﻳﻪ ﺍﺳﺖ‪.‬‬
‫ﺍﮔﺮ ﺁﺭﺍﻳﻪ ‪ a‬ﻳﮏ ﺁﺭﺍﻱۀ ﺳﻪ ﻋﻨﺼﺮﻱ ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﺩﺳﺘﻮﺭﻫﺎﻱ ﺯﻳﺮ ﺁﺭﺍﻱۀ ‪ a‬ﺭﺍ‬
‫ﺑﻪ ﺗﺎﺑﻊ )(‪ print‬ﻣﻲﻓﺮﺳﺘﺪ؟‬
‫ﺏ – ;)][‪print(a‬‬ ‫ﺍﻟﻒ – ;)]‪print(a[3‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪206‬‬

‫ﺩ – ;)(‪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‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫‪ – 16‬ﺑﺮﺍﻱ ﭘﻴﻤﺎﻳﺶ ﺁﺭﺍﻳﻪﺍﻱ ﮐﻪ ‪ n‬ﺑﻌﺪ ﻭ ﺩﺭ ﻫﺮ ﺑﻌﺪ ‪ k‬ﻋﻀﻮ ﺩﺍﺭﺩ ﺑﻪ ﭼﻨﺪ ﺣﻠﻘﻪ‬


‫ﻧﻴﺎﺯﻣﻨﺪﻳﻢ؟‬
‫ﺩ – ‪ n+k‬ﺣﻠﻘﻪ‬ ‫ﺝ – ‪ n-k‬ﺣﻠﻘﻪ‬ ‫ﺍﻟﻒ ‐ ‪ n‬ﺣﻠﻘﻪ ﺏ – ‪ k‬ﺣﻠﻘﻪ‬
‫‪ – 17‬ﺩﺭ ﻣﻮﺭﺩ ﺍﺭﺳﺎﻝ ﺁﺭﺍﻳﻪﻫﺎ ﺑﻪ ﺗﺎﺑﻊ‪ ،‬ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟‬
‫ﺍﻟﻒ – ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ‬
‫ﺏ – ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﺪ ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﻧﻮﻉ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﻭ ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﻥ‪ ،‬ﺑﻪ ﺗﮏ ﺗﮏ‬
‫ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‬
‫ﺝ – ﺩﺭ ﺣﻘﻴﻘﺖ ﺁﺭﺍﻳﻪﻫﺎ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺑﻪ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﻧﺪ‬
‫ﺩ – ﻻﺯﻡ ﻧﻴﺴﺖ ﺗﺎﺑﻊ ﭼﻴﺰﻱ ﺭﺍﺟﻊ ﺑﻪ ﺍﺑﻌﺎﺩ ﺁﺭﺍﻳﻪ ﺑﺪﺍﻧﺪ‬
‫‪ – 18‬ﺑﻪ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺑﺎﻳﺪ ﺑﻪ ﺁﺩﺭﺱ ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻳﻪ ﺍﺿﺎﻓﻪ ﺷﻮﺩ ﺗﺎ ﺑﻪ ﻳﮏ ﻋﻨﺼﺮ‬
‫ﻣﻔﺮﻭﺽ ﺑﺮﺳﻴﻢ ﭼﻪ ﻣﻲﮔﻮﻳﻨﺪ؟‬
‫ﺩ ‐ ﻓﺎﺻﻠﻪ‬ ‫ﺝ – ﺑﻌﺪ‬ ‫ﺏ – ﺍﻳﻨﺪﮐﺲ‬ ‫ﺍﻟﻒ – ﺁﻓﺴﺖ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪208‬‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪ ‐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‬‬

‫‪‐12‬ﺗﺎﺑﻊ ﺯﻳﺮ ﮐﻪ ﻳﮏ ﻣﻘﺪﺍﺭ ﺭﺍ ﺍﺯ ﺁﺭﺍﻳﻪ ﺣﺬﻑ ﻣﻲﮐﻨﺪ‪ ،‬ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ‪:‬‬


‫;)‪void remove(float a[], int& n, int i‬‬
‫ﺗﺎﺑﻊ ﺑﺎﻻ ﺑﻪ ﺍﻳﻦ ﺭﻭﺵ ﻋﻨﺼﺮ ]‪ a[i‬ﺭﺍ ﺣﺬﻑ ﻣﻲﮐﻨﺪ ﮐﻪ ﺗﻤﺎﻡ ﻋﻨﺎﺻﺮ ﺑﻌﺪ ﺍﺯ ﺁﻥ ﺭﺍ ﻳﮏ‬
‫ﭘﻠﻪ ﺑﻪ ﻋﻘﺐ ﻣﻲﮐﺸﺪ ﻭ ‪ 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‬ﻧﮕﺎﻩ ﮐﻨﻴﺪ(‬

‫‪ ‐15‬ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪:‬‬


‫;)‪void rotate(int a[], int n, int k‬‬
‫ﺗﺎﺑﻊ ‪ n‬ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻳﻪ ‪ a‬ﺭﺍ ‪ k،‬ﻣﻮﻗﻌﻴﺖ ﺑﻪ ﺭﺍﺳﺖ )ﻳﺎ ﺍﮔﺮ ‪ k‬ﻣﻨﻔﻲ ﺑﺎﺷﺪ ‪ k‬ﻣﻮﻗﻌﻴﺖ ﺑﻪ‬
‫ﭼﭗ( ﻣﻨﺘﻘﻞ ﻣﻲﮐﻨﺪ‪k .‬ﻋﻨﺼﺮ ﺁﺧﺮ ﺑﻪ ﺷﺮﻭﻉ ﺁﺭﺍﻳﻪ ﻣﻨﺘﻘﻞ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ‪ ،‬ﻓﺮﺍﺧﻮﺍﻧﻲ‬
‫)‪ rotate(a,8,3‬ﺁﺭﺍﻱۀ }‪ {22,33,44,55,66,77,88,99‬ﺭﺍ ﺑﻪ ﺁﺭﺍﻱۀ‬
‫}‪ {77,88,99,22,33,44,55,66‬ﺗﺒﺪﻳﻞ ﻣﻲﻛﻨﺪ‪ .‬ﺑﺪﻳﻬﻲ ﺍﺳﺖ ﮐﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ‬
‫)‪ rotate(a,8,-5‬ﺗﺎﺛﻴﺮ ﻣﺸﺎﺑﻬﻲ ﺧﻮﺍﻫﺪ ﺩﺍﺷﺖ‪.‬‬

‫‪ ‐16‬ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪:‬‬


‫;)‪void append(int a[], int m, int b[], int n‬‬
‫ﺗﺎﺑﻊ ﺑﺎﻻ ‪ n‬ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻱۀ ‪ b‬ﺭﺍ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ‪ m‬ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻱۀ ‪ a‬ﺍﻟﺤﺎﻕ ﻣﻲﻛﻨﺪ‪ .‬ﻓﺮﺽ‬
‫ﺑﺮ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺁﺭﺍﻱۀ ‪ a‬ﺣﺪﺍﻗﻞ ﺑﻪ ﺍﻧﺪﺍﺯۀ ‪ m+n‬ﻋﻨﺼﺮ ﺟﺎ ﺩﺍﺭﺩ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ ﺁﺭﺍﻱۀ ‪a‬‬
‫ﺑﺮﺍﺑﺮ ﺑﺎ }‪ {22,33,44,55,66,77,88,99‬ﻭ ﺁﺭﺍﻱۀ ‪ b‬ﻧﻴﺰ ﺑﺮﺍﺑﺮ ﺑﺎ‬
‫}‪ {20,30,40,50,60,70,80‬ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﻓﺮﺍﺧﻮﺍﻧﻲ )‪append(a,5,b,3‬‬
‫ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺁﺭﺍﻱ ۀ ‪ a‬ﺑﻪ ﺷﮑﻞ }‪ {22,33,44,55,66,20,30,40‬ﺗﻐﻴﻴﺮ‬
‫ﮐﻨﺪ‪ .‬ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﺁﺭﺍﻱۀ ‪ b‬ﺗﻐﻴﻴﺮ ﻧﻤﻲﮐﻨﺪ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪212‬‬

‫‪ ‐17‬ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪:‬‬


‫)‪void insert(float a[], int& n, float x‬‬
‫ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﺭﻭﻥ ﺁﺭﺍﻱۀ ﻣﺮﺗﺐ ‪ a‬ﮐﻪ ‪ n‬ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﻣﻘﺪﺍﺭ ‪ x‬ﺭﺍ ﺩﺭﺝ ﻣﻲﮐﻨﺪ ﻭ ‪ n‬ﺭﺍ‬
‫ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﺪ‪ .‬ﻋﻨﺼﺮ ﺟﺪﻳﺪ ﺩﺭ ﻣﮑﺎﻧﻲ ﺩﺭﺝ ﻣﻲﺷﻮﺩ ﮐﻪ ﺗﺮﺗﻴﺐ ﺁﺭﺍﻳﻪ ﺣﻔﻆ ﺷﻮﺩ‪ .‬ﺑﻪ ﺍﻳﻦ‬
‫ﻣﻨﻈﻮﺭ‪ ،‬ﻋﻨﺎﺻﺮ ﺑﺎﻳﺪ ﺑﻪ ﺟﻠﻮ ﻣﻨﺘﻘﻞ ﺷﻮﻧﺪ ﺗﺎ ﺑﺮﺍﻱ ﻋﻀﻮ ﺟﺪﻳﺪ‪ ،‬ﺟﺎ ﺑﺎﺯ ﺷﻮﺩ‪) .‬ﺑﻪ ﻫﻤﻴﻦ‬
‫ﺩﻟﻴﻞ ﺁﺭﺍﻳﻪ ﺑﺎﻳﺪ ﺣﺪﺍﻗﻞ ‪ n+1‬ﻋﻨﺼﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ(‬

‫‪ ‐18‬ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪:‬‬


‫;)‪int frequency(float a[], int n, int x‬‬
‫ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﻓﻌﺎﺗﻲ ﺭﺍ ﻛﻪ ﻋﻨﺼﺮ ‪ x‬ﺩﺭ ﻣﻴﺎﻥ ‪ n‬ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻳﻪ ﻇﺎﻫﺮ ﻣﻲﺷﻮﺩ ﺭﺍ ﺷﻤﺮﺩﻩ ﻭ‬
‫ﻧﺘﻴﺠﻪ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﺗﻌﺪﺍﺩ ﺗﻜﺮﺍﺭ ‪ x‬ﺩﺭ ‪ a‬ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬

‫‪ ‐19‬ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪:‬‬


‫;)‪void reverse(int a[] , int n‬‬
‫ﺗﺎﺑﻊ ﻓﻮﻕ ‪ n‬ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﻌﻜﻮﺱ ﻣﻲﻛﻨﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﻓﺮﺍﺧﻮﺍﻧﻲ‬
‫ﺑﻪ‬ ‫ﺭﺍ‬ ‫}‪{22,33,44,55,66‬‬ ‫ﺁﺭﺍﻱۀ‬ ‫)‪reverse(a,5‬‬
‫}‪ {66,55,44,33,22‬ﺗﺒﺪﻳﻞ ﻣﻲﻛﻨﺪ‪.‬‬

‫‪ ‐20‬ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪:‬‬


‫;)][‪void add(float a[], int n, float b‬‬
‫ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ‪ n‬ﻋﻨﺼﺮ ﺍﻭﻝ ‪ b‬ﺭﺍ ﺑﻪ ‪ n‬ﻋﻨﺼﺮ ﻣﺘﻨﺎﻇﺮ ﺩﺭ ‪ a‬ﺍﺿﺎﻓﻪ ﻣﻲﻛﻨﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﮔﺮ ‪a‬‬
‫ﺑﺮﺍﺑﺮ ﺑﺎ }‪ {2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9‬ﺑﺎﺷﺪ ﻭ ‪ b‬ﻧﻴﺰ ﺑﺮﺍﺑﺮ ﺑﺎ‬
‫}‪ {6.0,5.0,4.0,3.0,2.0,1.0‬ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﻓﺮﺍﺧﻮﺍﻧﻲ ;)‪add(a,5,b‬‬
‫ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺁﺭﺍﻱ ۀ ‪ a‬ﺑﻪ }‪{8.2,8.3,8.4,8.5,8.6,7.7,8.8,9.9‬‬
‫ﺗﺒﺪﻳﻞ ﺷﻮﺩ‪.‬‬

‫‪ ‐21‬ﺗﺎﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﻛﻨﻴﺪ‪:‬‬


‫;)][‪float outerProduct(float p[][3], float a[], float b‬‬
‫‪213‬‬ ‫ﻓﺼﻞ ﺷﺸﻢ ‪ /‬ﺁراﻳﻪهﺎ‬

‫ﺗﺎﺑﻊ ﺑﺎﻻ‪ ،‬ﺣﺎﺻﻞ ﺿﺮﺏ ﺑﻴﺮﻭﻧﻲ ﺳﻪ ﻋﻨﺼﺮ ﺍﻭﻝ ‪ 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‬ﺍﺳﺖ‪.‬‬

‫‪ ‐22‬ﺗﺎﺑﻌﻲ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ ﮐﻪ ﻋﻨﺎﺻﺮ ﻳﮏ ﺁﺭﺍﻱۀ ﺩﻭﺑﻌﺪﻱ ﻣﺮﺑﻌﻲ ﺭﺍ ‪90‬‬


‫ﺩﺭﺟﻪ ﺩﺭ ﺟﻬﺖ ﻋﻘﺮﺑﻪﻫﺎﻱ ﺳﺎﻋﺖ ﺑﭽﺮﺧﺎﻧﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺎﻳﺪ ﺁﺭﺍﻱۀ ‪:‬‬
‫‪11‬‬ ‫‪22‬‬ ‫‪33‬‬
‫‪44‬‬ ‫‪55‬‬ ‫‪66‬‬
‫‪77‬‬ ‫‪88‬‬ ‫‪99‬‬
‫ﺭﺍ ﺑﻪ ﺁﺭﺍﻱۀ‬
‫‪77‬‬ ‫‪44‬‬ ‫‪11‬‬
‫‪88‬‬ ‫‪55‬‬ ‫‪22‬‬
‫‪99‬‬ ‫‪66‬‬ ‫‪33‬‬
‫ﺗﺒﺪﻳﻞ ﻣﻲﻛﻨﺪ‪.‬‬
‫ﻓﺼﻞ ﻫﻔﺘﻢ‬
‫»ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‪ 1‬ﻭ ﺍﺭﺟﺎﻉﻫﺎ‪«2‬‬

‫‪ 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‬ﺭﺍ‬

‫‪1 – Pointers‬‬ ‫‪2 - References‬‬


‫‪215‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫ﻣﺎﻧﻨﺪ ﺷﮑﻞ ﺯﻳﺮ ﻣﺠﺴﻢ ﮐﻨﻴﻢ‪:‬‬

‫‪n‬‬ ‫ﺧﻮﺩ ﻣﺘﻐﻴﺮ ﺑﻪ ﺷﮑﻞ ﺟﻌﺒﻪ ﻧﻤﺎﻳﺶ ﺩﺍﺩﻩ ﺷﺪﻩ‪ .‬ﻧﺎﻡ ﻣﺘﻐﻴﺮ‪،‬‬
‫‪0x0050cdc0‬‬
‫‪ ،n‬ﺩﺭ ﺑﺎﻻﻱ ﺟﻌﺒﻪ ﺍﺳﺖ ﻭ ﺁﺩﺭﺱ ﻣﺘﻐﻴﺮ ﺩﺭ ﺳﻤﺖ ﭼﭗ ﺟﻌﺒﻪ ﻭ‬
‫‪int‬‬
‫ﻧﻮﻉ ﻣﺘﻐﻴﺮ‪ ،int ،‬ﺩﺭ ﺯﻳﺮ ﺟﻌﺒﻪ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ‪ .‬ﺩﺭ ﺑﻴﺸﺘﺮ‬
‫ﺭﺍﻳﺎﻧﻪﻫﺎ ﻧﻮﻉ ‪ int‬ﭼﻬﺎﺭ ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ ﻣﻲﻧﻤﺎﻳﺪ‪.‬‬
‫‪0x0050cdb8‬‬
‫‪0x0050cdb9‬‬
‫‪0x0050cdc0‬‬
‫‪0x0050cdc1‬‬
‫ﺑﻨﺎﺑﺮﺍﻳﻦ ﻫﻤﺎﻥ ﻃﻮﺭ ﮐﻪ ﺩﺭ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪،‬‬
‫‪0x0050cdc2‬‬
‫‪0x0050cdc3‬‬
‫‪0x0050cdc4‬‬
‫ﻣﺘﻐﻴﺮ ‪ n‬ﻳﮏ ﺑﻠﻮﮎ ﭼﻬﺎﺭﺑﺎﻳﺘﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ ﺍﺷﻐﺎﻝ ﻣﻲﮐﻨﺪ ﮐﻪ‬
‫‪0x0050cdc5‬‬

‫ﺷﺎﻣﻞ ﺑﺎﻳﺖﻫﺎﻱ ‪ 0x0050cdc0‬ﺗﺎ ‪ 0x0050cdc3‬ﺍﺳﺖ‪.‬‬


‫ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﺁﺩﺭﺱ ﺷﻲ‪ ،‬ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﺑﺎﻳﺖ ﺍﺯ ﺑﻠﻮﮐﻲ ﺍﺳﺖ ﮐﻪ ﺷﻲ ﺩﺭ ﺁﻥ ﺟﺎ ﺫﺧﻴﺮﻩ‬
‫ﺷﺪﻩ‪ .‬ﺍﮔﺮ ﻣﺘﻐﻴﺮ ﻓﻮﻕ ﺑﻪ ﺷﮑﻞ ;‪ int n=32‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺷﻮﺩ‪ ،‬ﺁﻧﮕﺎﻩ ﺑﻠﻮﮎ ﺣﺎﻓﻈﻪ‬
‫‪0x0050cdb8‬‬
‫ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪ .‬ﻣﻘﺪﺍﺭ‬
‫‪0x0050cdb9‬‬
‫‪n‬‬
‫‪0x0050cdc0‬‬
‫‪ 32‬ﺩﺭ ﭼﻬﺎﺭ ﺑﺎﻳﺘﻲ ﮐﻪ ﺑﺮﺍﻱ ﺁﻥ‬
‫‪0x0050cdc1‬‬
‫‪0x0050cdc2‬‬
‫‪0x0050cdc3‬‬
‫‪32‬‬ ‫‪0x0050cdc0‬‬ ‫‪32‬‬
‫‪0x0050cdc4‬‬
‫‪0x0050cdc5‬‬
‫‪int‬‬ ‫ﻣﺘﻐﻴﺮ ﻣﻨﻈﻮﺭ ﺷﺪﻩ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺩﺭ ﺍﻳﻦ ﻓﺼﻞ ﺑﻪ ﺑﺮﺭﺳﻲ ﻭ ﻧﺤﻮۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﺩﺭﺱﻫﺎ ﺧﻮﺍﻫﻴﻢ ﭘﺮﺩﺍﺧﺖ‪.‬‬

‫‪ 7‐1‬ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ‬
‫ﺩﺭ ‪ C++‬ﺑﺮﺍﻱ ﺑﺪﺳﺖ ﺁﻭﺭﺩﻥ ﺁﺩﺭﺱ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ‪& 1‬‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﻮﺩ‪ .‬ﺑﻪ ﺍﻳﻦ ﻋﻤﻠﮕﺮ »ﻋﻠﻤﮕﺮ ﺁﺩﺭﺱ« ﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﻋﺒﺎﺭﺕ ‪ &n‬ﺁﺩﺭﺱ ﻣﺘﻐﻴﺮ ‪ n‬ﺭﺍ‬
‫ﺑﻪ ﺩﺳﺖ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 7‐1‬ﭼﺎﭖ ﺁﺩﺭﺱ ﻳﮏ ﻣﺘﻐﻴﺮ‬


‫)(‪int main‬‬
‫;‪{ int n=44‬‬
‫;‪cout << " n = " << n << endl‬‬ ‫‪// prints the value of n‬‬
‫;‪cout << "&n = " << &n << endl‬‬ ‫‪// prints the address of n‬‬
‫}‬
‫‪n = 44‬‬
‫‪&n = 0x00c9fdc3‬‬

‫‪1 – Reference operator‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪216‬‬

‫ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﻛﻪ ﺁﺩﺭﺱ ‪ n‬ﺩﺭ ﺍﻳﻦ ﺍﺟﺮﺍ ﺑﺮﺍﺑﺮ ﺑﺎ ‪ 0x00c9fdc3‬ﺍﺳﺖ‪ .‬ﻣﻲﺗﻮﺍﻥ‬
‫ﻓﻬﻤﻴﺪ ﮐﻪ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺑﺎﻳﺪ ﻳﮏ ﺁﺩﺭﺱ ﺑﺎﺷﺪ ﺯﻳﺮﺍ ﺑﻪ ﺷﮑﻞ ﺷﺎﻧﺰﺩﻩﺩﻫﻲ ﻧﻤﺎﻳﺶ ﺩﺍﺩﻩ ﺷﺪﻩ‪.‬‬
‫ﺍﻋﺪﺍﺩ ﺷﺎﻧﺰﺩﻩﺩﻫﻲ ﺭﺍ ﺍﺯ ﺭﻭﻱ ﻋﻼﻣﺖ ‪ 0x‬ﻣﻲﺗﻮﺍﻥ ﺗﺸﺨﻴﺺ ﺩﺍﺩ‪ .‬ﻣﻌﺎﺩﻝ ﺩﻫﺪﻫﻲ ﻋﺪﺩ ﺑﺎﻻ‬
‫ﻣﻘﺪﺍﺭ ‪ 13,237,699‬ﻣﻲﺑﺎﺷﺪ‪.‬‬
‫ﻧﻤﺎﻳﺶ ﺩﺍﺩﻥ ﺁﺩﺭﺱ ﻳﮏ ﻣﺘﻐﻴﺮ ﺑﻪ ﺍﻳﻦ ﺷﻴﻮﻩ ﺧﻴﻠﻲ ﻣﻔﻴﺪ ﻧﻴﺴﺖ‪ .‬ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ &‬
‫ﺍﺳﺘﻔﺎﺩﻩﻫﺎﻱ ﻣﻬﻢﺗﺮﻱ ﺩﺍﺭﺩ‪ .‬ﻳﮏ ﮐﺎﺭﺑﺮﺩ ﺁﻥ ﺭﺍ ﺩﺭ ﻓﺼﻞ ﭘﻨﺠﻢ ﮔﻔﺘﻪﺍﻳﻢ‪ :‬ﺳﺎﺧﺘﻦ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ‬
‫ﺍﺭﺟﺎﻉ ﺩﺭ ﺍﻋﻼﻥ ﺗﺎﺑﻊ‪ .‬ﺍﮐﻨﻮﻥ ﮐﺎﺭﺑﺮﺩ ﺩﻳﮕﺮﻱ ﻣﻌﺮﻓﻲ ﻣﻲﮐﻨﻴﻢ ﮐﻪ ﺧﻴﻠﻲ ﺑﻪ ﮐﺎﺭﺑﺮﺩ ﻗﺒﻠﻲ ﺷﺒﻴﻪ‬
‫ﺍﺳﺖ؛ ﺍﻋﻼﻥ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﺭﺟﺎﻉ‪.‬‬

‫‪ 7‐2‬ﺍﺭﺟﺎﻉﻫﺎ‬
‫ﻳﻚ »ﺍﺭﺟﺎﻉ« ﻳﻚ ﺍﺳﻢ ﻣﺴﺘﻌﺎﺭ ﻳﺎ ﻭﺍﮊۀ ﻣﺘﺮﺍﺩﻑ ﺑﺮﺍﻱ ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮ ﺍﺳﺖ‪ .‬ﻧﺤﻮ ﺍﻋﻼﻥ‬
‫ﻳﮏ ﺍﺭﺟﺎﻉ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫;‪type& ref_name = var_name‬‬

‫‪ type‬ﻧﻮﻉ ﻣﺘﻐﻴﺮ ﺍﺳﺖ‪ ref_name ،‬ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺍﺳﺖ ﻭ ‪ var_name‬ﻧﺎﻡ ﻣﺘﻐﻴﺮﻱ‬


‫ﺍﺳﺖ ﮐﻪ ﻣﻲﺧﻮﺍﻫﻴﻢ ﺑﺮﺍﻱ ﺁﻥ ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺑﺴﺎﺯﻳﻢ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺩﺭ ﺍﻋﻼﻥ ‪:‬‬
‫;‪int& rn=n‬‬ ‫‪// r is a synonym for n‬‬

‫‪ rn‬ﻳﮏ ﺍﺭﺟﺎﻉ ﻳﺎ ﻧﺎﻡ ﻣﺴﺘﻌﺎﺭ ﺑﺮﺍﻱ ‪ n‬ﺍﺳﺖ‪ .‬ﺍﻟﺒﺘﻪ ‪ n‬ﺑﺎﻳﺪ ﻗﺒﻼ ﺍﻋﻼﻥ ﺷﺪﻩ ﺑﺎﺷﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 7‐2‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﺭﺟﺎﻉﻫﺎ‬


‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ‪ rn‬ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﺍﺭﺟﺎﻉ ﺑﻪ ‪ n‬ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n=44‬‬
‫;‪int& rn=n‬‬ ‫‪//‬‬ ‫‪rn is a synonym for n‬‬
‫<< " = ‪cout << "n‬‬ ‫;‪n << ", rn = " << rn << endl‬‬
‫;‪--n‬‬
‫<< " = ‪cout << "n‬‬ ‫;‪n << ", rn = " << rn << endl‬‬
‫;‪rn *= 2‬‬
‫<< " = ‪cout << "n‬‬ ‫;‪n << ", rn = " << rn << endl‬‬
‫}‬
‫‪217‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫‪n = 44, rn = 44‬‬


‫‪n = 43, rn = 43‬‬
‫‪n = 86, rn = 86‬‬

‫‪ n‬ﻭ ‪ rn‬ﻧﺎﻡﻫﺎﻱ ﻣﺘﻔﺎﻭﺗﻲ ﺑﺮﺍﻱ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺩﻭ ﻫﻤﻴﺸﻪ ﻣﻘﺪﺍﺭ ﻳﮑﺴﺎﻧﻲ ﺩﺍﺭﻧﺪ‪ .‬ﺍﮔﺮ‬
‫‪ n‬ﮐﺎﺳﺘﻪ ﺷﻮﺩ‪ rn ،‬ﻧﻴﺰ ﮐﺎﺳﺘﻪ ﺷﺪﻩ ﻭ ﺍﮔﺮ ‪ rn‬ﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ‪ n ،‬ﻧﻴﺰ ﺍﻓﺰﺍﻳﺶ ﻳﺎﻓﺘﻪ ﺍﺳﺖ‪.‬‬
‫ﻫﻤﺎﻧﻨﺪ ﺛﺎﺑﺖﻫﺎ‪ ،‬ﺍﺭﺟﺎﻉﻫﺎ ﺑﺎﻳﺪ ﻫﻨﮕﺎﻡ ﺍﻋﻼﻥ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺷﻮﻧﺪ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ‬
‫ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ ﻳﮏ ﺍﺭﺟﺎﻉ‪ ،‬ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺳﺖ ﻧﻪ ﻳﮏ ﻟﻴﺘﺮﺍﻝ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﮐﺪ ﺯﻳﺮ ﺍﺷﺘﺒﺎﻩ ﺍﺳﺖ‪:‬‬
‫;‪int& rn=44‬‬ ‫;‪// ERROR: 44 is not a variable‬‬

‫ﮔﺮﭼﻪ ﺑﺮﺧﻲ ﺍﺯ ﮐﺎﻣﭙﺎﻳﻠﺮﻫﺎ ﻣﻤﮑﻦ ﺍﺳﺖ ﺩﺳﺘﻮﺭ ﺑﺎﻻ ﺭﺍ ﻣﺠﺎﺯ ﺑﺪﺍﻧﻨﺪ ﻭﻟﻲ ﺑﺎ ﻧﺸﺎﻥ ﺩﺍﺩﻥ ﻳﮏ‬
‫ﻫﺸﺪﺍﺭ ﺍﻋﻼﻡ ﻣﻲﮐﻨﻨﺪ ﮐﻪ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻮﻗﺘﻲ ﺍﻳﺠﺎﺩ ﺷﺪﻩ ﺗﺎ ‪ rn‬ﺑﻪ ﺣﺎﻓﻆۀ ﺁﻥ ﻣﺘﻐﻴﺮ‪ ،‬ﺍﺭﺟﺎﻉ‬
‫ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪.‬‬
‫ﺩﺭﺳﺖ ﺍﺳﺖ ﮐﻪ ﺍﺭﺟﺎﻉ ﺑﺎ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﺷﻮﺩ‪ ،‬ﺍﻣﺎ ﺍﺭﺟﺎﻉ ﺑﻪ ﺧﻮﺩﻱ ﺧﻮﺩ‬
‫ﻳﮏ ﻣﺘﻐﻴﺮ ﻧﻴﺴﺖ‪ .‬ﻳﮏ ﻣﺘﻐﻴﺮ‪ ،‬ﻓﻀﺎﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻭ ﻧﺸﺎﻧﻲ ﻣﺴﺘﻘﻞ ﺩﺍﺭﺩ‪ ،‬ﺣﺎﻝ ﺁﻥ ﮐﻪ‬
‫ﺍﺭﺟﺎﻉ ﺍﺯ ﻓﻀﺎﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻭ ﻧﺸﺎﻧﻲ ﻣﺘﻐﻴﺮ ﺩﻳﮕﺮﻱ ﺑﻬﺮﻩ ﻣﻲﺑﺮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 7‐3‬ﺍﺭﺟﺎﻉﻫﺎ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺴﺘﻘﻞ ﻧﻴﺴﺘﻨﺪ‬


‫)(‪int main‬‬
‫;‪{ int n=44‬‬
‫;‪int& rn=n‬‬ ‫‪// rn is a synonym for n‬‬
‫;‪cout << " &n = " << &n << ", &rn = " << &rn << endl‬‬
‫;‪int& rn2=n‬‬ ‫‪// rn2 is another synonym for n‬‬
‫;‪int& rn3=rn‬‬ ‫‪// rn3 is another synonym for n‬‬
‫;‪cout << "&rn2 = " << &rn2 << ", &rn3 = " << &rn3 << endl‬‬
‫}‬
‫‪& n = 0x0064fde4, &rn = 0x0064fde4‬‬
‫‪&rn2 = 0x0064fde4, &rn3 = 0x0064fde4‬‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻓﻮﻕ ﻓﻘﻂ ﻳﮏ ﺷﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﻭ ﺁﻥ ﻫﻢ ‪ 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‬ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ ‪ int‬ﺑﻪ ﻧﺎﻡ ‪ n‬ﻭ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺍﺯ ﻧﻮﻉ *‪ int‬ﺑﻪ ﻧﺎﻡ‬
‫‪ pn‬ﺭﺍ ﺍﻋﻼﻥ ﻣﻲﮐﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n=44‬‬
‫;‪cout << "n = " << n << ", &n = " << &n << endl‬‬
‫;‪int* pn=&n‬‬ ‫‪// pn holds the address of n‬‬
‫" << ‪cout‬‬ ‫;‪pn = " << pn << endl‬‬
‫;‪cout << "&pn = " << &pn << endl‬‬
‫}‬
‫‪n = 44, &n = 0x0064fddc‬‬
‫‪pn = 0x0064fddc‬‬
‫‪&pn = 0x0064fde0‬‬

‫‪0x0064fddc‬‬ ‫ﻣﺘﻐﻴﺮ ‪ n‬ﺑﺎ ﻣﻘﺪﺍﺭ ‪ 44‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﺪﻩ ﻭ ﺁﺩﺭﺱ ﺁﻥ‬


‫‪n‬‬ ‫‪44‬‬
‫‪int‬‬ ‫‪ 0x0064fddc‬ﻣﻲﺑﺎﺷﺪ‪ .‬ﺍﺷﺎﺭﻩﮔﺮ ‪ pn‬ﺑﺎ ﻣﻘﺪﺍﺭ ‪ &n‬ﻳﻌﻨﻲ ﺁﺩﺭﺱ‬
‫‪0x0064fde0‬‬ ‫‪ n‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﺪﻩ‪ .‬ﭘﺲ ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ ‪ pn‬ﺑﺮﺍﺑﺮ ﺑﺎ‬
‫‪pn‬‬ ‫‪0x0064fddc‬‬
‫*‪int‬‬ ‫‪ 0x0064fddc‬ﺍﺳﺖ )ﺧﻂ ﺩﻭﻡ ﺧﺮﻭﺟﻲ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ ﺗﺎﻳﻴﺪ‬
‫ﻣﻲﮐﻨﺪ( ‪ .‬ﺍﻣﺎ ‪ pn‬ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﺴﺘﻘﻞ ﺍﺳﺖ ﻭ ﺁﺩﺭﺱ ﻣﺴﺘﻘﻠﻲ ﺩﺍﺭﺩ‪ &pn .‬ﺁﺩﺭﺱ ‪ pn‬ﺭﺍ ﺑﻪ‬
‫ﺩﺳﺖ ﻣﻲﺩﻫﺪ‪ .‬ﺧﻂ ﺳﻮﻡ ﺧﺮﻭﺟﻲ ﺛﺎﺑﺖ ﻣﻲﮐﻨﺪ ﮐﻪ ﻣﺘﻐﻴﺮ ‪ pn‬ﻣﺴﺘﻘﻞ ﺍﺯ ﻣﺘﻐﻴﺮ ‪ n‬ﺍﺳﺖ‪.‬‬
‫ﺗﺼﻮﻳﺮ ﺯﻳﺮ ﺑﻪ ﺩﺭﮎ ﺑﻬﺘﺮ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﮐﻤﮏ ﻣﻲﮐﻨﺪ‪ .‬ﺩﺭ ﺍﻳﻦ ﺗﺼﻮﻳﺮ ﻭﻳﮋﮔﻲﻫﺎﻱ ﻣﻬﻢ ‪ n‬ﻭ‬
‫‪ pn‬ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ‪ pn .‬ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ‪ n‬ﺍﺳﺖ ﻭ ‪n‬‬
‫‪n‬‬ ‫‪44‬‬
‫‪int‬‬ ‫ﻣﻘﺪﺍﺭ ‪ 44‬ﺩﺍﺭﺩ‪.‬‬
‫ﻭﻗﺘﻲ ﻣﻲﮔﻮﻳﻴﻢ »‪ pn‬ﺑﻪ ‪ n‬ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ« ﻳﻌﻨﻲ‬
‫‪pn‬‬
‫*‪int‬‬ ‫ﺩﺭﻭﻥ ‪ pn‬ﺁﺩﺭﺱ ‪ n‬ﻗﺮﺍﺭ ﺩﺍﺭﺩ‪.‬‬

‫‪ 7‐4‬ﻣﻘﺪﺍﺭﻳﺎﺑﻲ‬
‫ﻓﺮﺽ ﮐﻨﻴﺪ ‪ n‬ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ‪ 22‬ﺑﺎﺷﺪ ﻭ ‪ pn‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ‪ n‬ﺑﺎﺷﺪ‪ .‬ﺑﺎ ﺍﻳﻦ ﺣﺴﺎﺏ‬
‫ﺑﺎﻳﺪ ﺑﺘﻮﺍﻥ ﺍﺯ ﻃﺮﻳﻖ ‪ pn‬ﺑﻪ ﻣﻘﺪﺍﺭ ‪ 22‬ﺭﺳﻴﺪ‪ .‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ * ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ‬
‫ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﺭﺍ ﺑﻪ ﺩﺳﺖ ﺁﻭﺭﺩ‪ .‬ﺑﻪ ﺍﻳﻦ ﮐﺎﺭ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ ﺍﺷﺎﺭﻩﮔﺮ ﻣﻲﮔﻮﻳﻴﻢ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 220

‫ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ‬7‐5 ‫* ﻣﺜﺎﻝ‬


:‫ ﻓﻘﻂ ﻳﮏ ﺧﻂ ﮐﺪ ﺑﻴﺸﺘﺮ ﺩﺍﺭﺩ‬.‫ ﺍﺳﺖ‬7‐4 ‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻤﺎﻥ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ‬
int main()
{ int n=44;
cout << "n = " << n << ", &n = " << &n << endl;
int* pn=&n; // pn holds the address of n
cout << " pn = " << pn << endl;
cout << "&pn = " << &pn << endl;
cout << "*pn = " << *pn << endl;
}
n = 44, &n = 0x0064fdcc
pn = 0x0064fdcc
&pn = 0x0064fdd0
*pn = 44

.‫ ﺍﺳﺖ ﺯﻳﺮﺍ ﻫﺮ ﺩﻭ ﻳﮏ ﻣﻘﺪﺍﺭ ﺩﺍﺭﻧﺪ‬n ‫* ﻳﮏ ﺍﺳﻢ ﻣﺴﺘﻌﺎﺭ ﺑﺮﺍﻱ‬pn ‫ﻇﺎﻫﺮﺍ‬


‫ ﺑﻪ ﻣﺜﺎﻝ‬.‫ ﺣﺘﻲ ﺑﻪ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺩﻳﮕﺮ‬،‫ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻫﺮ ﭼﻴﺰﻱ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺷﺎﺭﻩ ﮐﻨﺪ‬
.‫ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ‬

‫ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‬7‐6 ‫* ﻣﺜﺎﻝ‬


:‫ ﺍﺳﺖ‬7‐4 ‫ﺍﻳﻦ ﮐﺪ ﺍﺩﺍﻡۀ ﺳﺎﺧﺘﺎﺭ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ‬
int main()
{ int n=44;
cout << " n = " << n << endl;
cout << " &n = " << &n << endl;
int* pn=&n; // pn holds the address of n
cout << " pn = " << pn << endl;
cout << " &pn = " << &pn << endl;
cout << " *pn = " << *pn << endl;
int** ppn=&pn; // ppn holds the address of pn
cout << " ppn = " << ppn << endl;
cout << " &ppn = " << &ppn << endl;
cout << " *ppn = " << *ppn << endl;
cout << "**ppn = " << **ppn << endl;
‫‪221‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫}‬
‫‪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‬ﺁﺩﺭﺱ ﺁﻥ ﻣﺘﻐﻴﺮ ﺭﺍ ﻣﻲﺩﻫﺪ‪.‬‬

‫‪ 7‐6‬ﭼﭗ ﻣﻘﺪﺍﺭﻫﺎ‪ ،‬ﺭﺍﺳﺖ ﻣﻘﺪﺍﺭﻫﺎ‬


‫ﻳﮏ ﺩﺳﺘﻮﺭ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺩﻭ ﺑﺨﺶ ﺩﺍﺭﺩ‪ :‬ﺑﺨﺸﻲ ﮐﻪ ﺩﺭ ﺳﻤﺖ ﭼﭗ ﻋﻼﻣﺖ‬
‫ﺟﺎﻳﮕﺰﻳﻨﻲ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﻭ ﺑﺨﺸﻲ ﮐﻪ ﺩﺭ ﺳﻤﺖ ﺭﺍﺳﺖ ﻋﻼﻣﺖ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪.‬‬
‫ﻣﺜﻼ ﺩﺳﺘﻮﺭ ;‪ n = 55‬ﻣﺘﻐﻴﺮ ‪ n‬ﺩﺭ ﺳﻤﺖ ﭼﭗ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﻭ ﻣﻘﺪﺍﺭ ‪ 55‬ﺩﺭ ﺳﻤﺖ‬
‫ﺭﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺩﺳﺘﻮﺭ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﺷﮑﻞ ;‪ 55 = n‬ﻧﻮﺷﺖ ﺯﻳﺮﺍ ﻣﻘﺪﺍﺭ ‪ 55‬ﻳﮏ ﺛﺎﺑﺖ‬
‫ﺍﺳﺖ ﻭ ﻧﻤﻲﺗﻮﺍﻧﺪ ﻣﻘﺪﺍﺭ ﺑﮕﻴﺮﺩ‪ .‬ﭘﺲ ﻫﻨﮕﺎﻡ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺑﺎﻳﺪ ﺩﻗﺖ ﮐﻨﻴﻢ‬
‫ﮐﻪ ﭼﻪ ﭼﻴﺰﻱ ﺭﺍ ﺩﺭ ﺳﻤﺖ ﭼﭗ ﻗﺮﺍﺭ ﺑﺪﻫﻴﻢ ﻭ ﭼﻪ ﭼﻴﺰﻱ ﺭﺍ ﺩﺭ ﺳﻤﺖ ﺭﺍﺳﺖ‪.‬‬
‫ﭼﻴﺰﻫﺎﻳﻲ ﮐﻪ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺩﺭ ﺳﻤﺖ ﭼﭗ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻗﺮﺍﺭ ﺑﮕﻴﺮﻧﺪ »ﭼﭗﻣﻘﺪﺍﺭ‪«1‬‬
‫ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﻧﺪ ﻭ ﭼﻴﺰﻫﺎﻳﻲ ﮐﻪ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺩﺭ ﺳﻤﺖ ﺭﺍﺳﺖ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻗﺮﺍﺭ ﺑﮕﻴﺮﻧﺪ‬
‫»ﺭﺍﺳﺖﻣﻘﺪﺍﺭ‪ «2‬ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﻧﺪ‪ .‬ﻣﺘﻐﻴﺮﻫﺎ )ﻭ ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ ﺍﺷﻴﺎ( ﭼﭗﻣﻘﺪﺍﺭ ﻫﺴﺘﻨﺪ ﻭ‬
‫ﻟﻴﺘﺮﺍﻝﻫﺎ )ﻣﺜﻞ ‪ 15‬ﻭ "‪ ("ABC‬ﺭﺍﺳﺖ ﻣﻘﺪﺍﺭ ﻫﺴﺘﻨﺪ‪.‬‬
‫ﻳﮏ ﺛﺎﺑﺖ ﺩﺭ ﺍﺑﺘﺪﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﭼﭗﻣﻘﺪﺍﺭ ﻧﻤﺎﻳﺎﻥ ﻣﻲﺷﻮﺩ‪:‬‬
‫;‪const int MAX = 65535‬‬ ‫‪// MAX is an lvalue‬‬

‫ﺍﻣﺎ ﺍﺯ ﺁﻥ ﭘﺲ ﺩﻳﮕﺮ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﻋﻨﻮﺍﻥ ﭼﭗ ﻣﻘﺪﺍﺭ ﺍﺯ ﺁﻥﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪:‬‬


‫;‪MAX = 21024‬‬ ‫‪// ERROR: MAX is constant‬‬

‫ﺑﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﭼﭗﻣﻘﺪﺍﺭﻫﺎ‪ ،‬ﭼﭗﻣﻘﺪﺍﺭﻫﺎﻱ »ﺗﻐﻴﻴﺮ ﻧﺎﭘﺬﻳﺮ« ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ‪ .‬ﻣﺜﻞ ﺁﺭﺍﻳﻪﻫﺎ‪:‬‬
‫;}‪int a[] = {1,2,3‬‬ ‫‪// O.K‬‬
‫;}‪a[] = {1,2,3‬‬ ‫‪// ERROR‬‬

‫‪1 – L_values‬‬ ‫‪2- R_values‬‬


‫‪223‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫ﻣﺎﺑﻘﻲ ﭼﭗﻣﻘﺪﺍﺭﻫﺎ ﮐﻪ ﻣﻲﺗﻮﺍﻥ ﺁﻥﻫﺎ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﺍﺩ‪ ،‬ﭼﭗﻣﻘﺪﺍﺭﻫﺎﻱ »ﺗﻐﻴﻴﺮ ﭘﺬﻳﺮ«‬


‫ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﻧﺪ‪ .‬ﻫﻨﮕﺎﻡ ﺍﻋﻼﻥ ﻳﮏ ﺍﺭﺟﺎﻉ ﺑﻪ ﻳﮏ ﭼﭗﻣﻘﺪﺍﺭ ﻧﻴﺎﺯ ﺩﺍﺭﻳﻢ‪:‬‬
‫;‪int& r = n‬‬ ‫‪// O.K. n is an lvalue‬‬

‫ﺍﻣﺎ ﺍﻋﻼﻥﻫﺎﻱ ﺯﻳﺮ ﻏﻴﺮﻣﻌﺘﺒﺮﻧﺪ ﺯﻳﺮﺍ ﻫﻴﭻ ﮐﺪﺍﻡ ﭼﭗﻣﻘﺪﺍﺭ ﻧﻴﺴﺘﻨﺪ‪:‬‬


‫;‪int& r = 44‬‬ ‫‪// ERROR: 44 is not an lvalue‬‬
‫;‪int& r = n++‬‬ ‫‪// ERROR: n++ is not an lvalue‬‬
‫;)‪int& r = cube(n‬‬ ‫‪// ERROR: cube(n) is not an lvalue‬‬

‫ﻳﮏ ﺗﺎﺑﻊ‪ ،‬ﭼﭗﻣﻘﺪﺍﺭ ﻧﻴﺴﺖ ﺍﻣﺎ ﺍﮔﺮ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺁﻥ ﻳﮏ ﺍﺭﺟﺎﻉ ﺑﺎﺷﺪ‪ ،‬ﻣﻲﺗﻮﺍﻥ‬
‫ﺗﺎﺑﻊ ﺭﺍ ﺑﻪ ﻳﮏ ﭼﭗﻣﻘﺪﺍﺭ ﺗﺒﺪﻳﻞ ﮐﺮﺩ‪.‬‬

‫‪ 7‐7‬ﺑﺎﺯﮔﺸﺖ ﺍﺯ ﻧﻮﻉ ﺍﺭﺟﺎﻉ‬


‫ﺩﺭ ﺑﺤﺚ ﺗﻮﺍﺑﻊ‪ ،‬ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻭ ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺭﺍ ﺩﻳﺪﻳﻢ‪ .‬ﺍﻳﻦ ﺩﻭ‬
‫ﺷﻴﻮۀ ﺗﺒﺎﺩﻝ ﺩﺭ ﻣﻮﺭﺩ ﺑﺎﺯﮔﺸﺖ ﺍﺯ ﺗﺎﺑﻊ ﻧﻴﺰ ﺻﺪﻕ ﻣﻲﮐﻨﺪ‪ :‬ﺑﺎﺯﮔﺸﺖ ﺍﺯ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﻭ‬
‫ﺑﺎﺯﮔﺸﺖ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ‪ .‬ﺗﻮﺍﺑﻌﻲ ﮐﻪ ﺗﺎﮐﻨﻮﻥ ﺩﻳﺪﻳﻢ ﺑﺎﺯﮔﺸﺖ ﺑﻪ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺩﺍﺷﺘﻨﺪ‪.‬‬
‫ﻳﻌﻨﻲ ﻫﻤﻴﺸﻪ ﻳﮏ ﻣﻘﺪﺍﺭ ﺑﻪ ﻓﺮﺍﺧﻮﺍﻧﻨﺪﻩ ﺑﺮﻣﻲﮔﺸﺖ‪ .‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺗﺎﺑﻊ ﺭﺍ ﻃﻮﺭﻱ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ‬
‫ﮐﻪ ﺑﻪ ﺟﺎﻱ ﻣﻘﺪﺍﺭ‪ ،‬ﻳﮏ ﺍﺭﺟﺎﻉ ﺭﺍ ﺑﺎﺯﮔﺸﺖ ﺩﻫﺪ‪ .‬ﻣﺜﻼ ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﮐﻪ ﻣﻘﺪﺍﺭ ‪ m‬ﺭﺍ‬
‫ﺑﺎﺯﮔﺸﺖ ﺩﻫﺪ‪ ،‬ﻳﮏ ﺍﺭﺟﺎﻉ ﺑﻪ ‪ m‬ﺭﺍ ﺑﺎﺯﮔﺸﺖ ﺩﻫﺪ‪.‬‬
‫ﻭﻗﺘﻲ ﺑﺎﺯﮔﺸﺖ ﺑﻪ ﻃﺮﻳﻖ ﻣﻘﺪﺍﺭ ﺑﺎﺷﺪ‪ ،‬ﺗﺎﺑﻊ ﻳﮏ ﺭﺍﺳﺖﻣﻘﺪﺍﺭ ﺧﻮﺍﻫﺪ ﺑﻮﺩ ﺯﻳﺮﺍ‬
‫ﻣﻘﺪﺍﺭﻫﺎ ﻟﻴﺘﺮﺍﻝ ﻫﺴﺘﻨﺪ ﻭ ﻟﻴﺘﺮﺍﻝﻫﺎ ﺭﺍﺳﺖﻣﻘﺪﺍﺭﻧﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺗﺎﺑﻊ ﺭﺍ ﻓﻘﻂ ﺩﺭ ﺳﻤﺖ‬
‫ﺭﺍﺳﺖ ﻳﮏ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﮐﺎﺭ ﺑﺮﺩ ﻣﺜﻞ‪m = f(); :‬‬

‫ﻭﻗﺘﻲ ﺑﺎﺯﮔﺸﺖ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺑﺎﺷﺪ‪ ،‬ﺗﺎﺑﻊ ﻳﮏ ﭼﭗﻣﻘﺪﺍﺭ ﺧﻮﺍﻫﺪ ﺑﻮﺩ ﺯﻳﺮﺍ‬
‫ﺍﺭﺟﺎﻉﻫﺎ ﭼﭗﻣﻘﺪﺍﺭ ﻫﺴﺘﻨﺪ‪ .‬ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺗﺎﺑﻊ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﺳﻤﺖ ﭼﭗ ﻳﮏ ﺟﺎﻳﮕﺰﻳﻨﻲ‬
‫;‪f() = m‬‬ ‫ﻗﺮﺍﺭ ﺩﺍﺩ ﻣﺜﻞ ‪:‬‬
‫ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﺎﺑﻊ ﺭﺍ ﺑﻪ ﺍﺭﺟﺎﻉ ﺗﺒﺪﻳﻞ ﮐﻨﻴﻢ ﮐﺎﻓﻲ ﺍﺳﺖ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ‬
‫ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﭘﺴﻮﻧﺪ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺩﺭﺝ ﮐﻨﻴﻢ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪224‬‬

‫* ﻣﺜﺎﻝ ‪ 7‐8‬ﺑﺎﺯﮔﺸﺖ ﺍﺯ ﻧﻮﻉ ﺍﺭﺟﺎﻉ‬


‫)‪int& max(int& m, int& n‬‬ ‫‪// return type is reference to int‬‬
‫;)‪{ return (m > n ? m : n‬‬ ‫‪// m and n are non-local references‬‬
‫}‬
‫)(‪int main‬‬
‫;‪{ int m = 44, n = 22‬‬
‫;‪cout << m << ", " << n << ", " << max(m,n) << endl‬‬
‫;‪max(m,n) = 55‬‬ ‫‪// changes the vale of m from 44 to 55‬‬
‫;‪cout << m << ", " << n << ", " << max(m,n) << endl‬‬
‫}‬
‫‪44, 22, 44‬‬
‫‪55, 22, 55‬‬

‫ﺗﺎﺑﻊ )(‪ 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‬‬

‫ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺁﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ & ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺍﺭﺟﺎﻉ ﺩﺭﺁﻣﺪﻩ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 7‐9‬ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ﻳﻚ ﺗﺎﺑﻊ ﺑﻪ ﻋﻨﻮﺍﻥ ﻋﻤﻠﮕﺮ ﺯﻳﺮﻧﻮﻳﺲ ﺁﺭﺍﻳﻪ‬


‫)‪float& component(float* v, int k‬‬
‫‪225‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫{‬ ‫;]‪return v[k-1‬‬


‫}‬

‫)(‪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‬ﺁﺭﺍﻳﻪﻫﺎ ﻭ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‬
‫ﮔﺮﭼﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺍﺯ ﺍﻧﻮﺍﻉ ﻋﺪﺩﻱ ﺻﺤﻴﺢ ﻧﻴﺴﺘﻨﺪ ﺍﻣﺎ ﺑﻌﻀﻲ ﺍﺯ ﺍﻋﻤﺎﻝ ﺣﺴﺎﺑﻲ ﺭﺍ‬
‫ﻣﻲﺗﻮﺍﻥ ﺭﻭﻱ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺍﻧﺠﺎﻡ ﺩﺍﺩ‪ .‬ﺣﺎﺻﻞ ﺍﻳﻦ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺧﺎﻥۀ ﺩﻳﮕﺮﻱ ﺍﺯ‬
‫ﺣﺎﻓﻈﻪ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ‪ .‬ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﺜﻞ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺍﻓﺰﺍﻳﺶ ﻭ ﻳﺎ ﮐﺎﻫﺶ ﺩﺍﺩ ﻭ‬
‫ﻣﻲﺗﻮﺍﻥ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﺭﺍ ﺑﻪ ﺁﻥﻫﺎ ﺍﺿﺎﻓﻪ ﻧﻤﻮﺩ ﻳﺎ ﺍﺯ ﺁﻥ ﮐﻢ ﮐﺮﺩ‪ .‬ﺍﻟﺒﺘﻪ ﻣﻴﺰﺍﻥ ﺍﻓﺰﺍﻳﺶ ﻳﺎ‬
‫ﮐﺎﻫﺶ ﺍﺷﺎﺭﻩﮔﺮ ﺑﺴﺘﮕﻲ ﺑﻪ ﻧﻮﻉ ﺩﺍﺩﻩﺍﻱ ﺩﺍﺭﺩ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ .‬ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺭﺍ‬
‫ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻣﺜﺎﻝ ﺯﻳﺮ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 7‐10‬ﭘﻴﻤﺎﻳﺶ ﺁﺭﺍﻳﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ‬


‫ﺍﻳﻦ ﻣﺜﺎﻝ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﻛﻪ ﭼﮕﻮﻧﻪ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ ﺑﺮﺍﻱ ﭘﻴﻤﺎﻳﺶ ﻳﮏ ﺁﺭﺍﻳﻪ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﻧﻤﻮﺩ‪:‬‬
‫)(‪int main‬‬
‫;‪{ const int SIZE = 3‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪226‬‬

‫;}‪short a[SIZE] = {22, 33, 44‬‬


‫;‪cout << "a = " << a << endl‬‬
‫;‪cout << "sizeof(short) = " << sizeof(short) << endl‬‬
‫;‪short* end = a + SIZE‬‬ ‫‪// converts SIZE to offset 6‬‬
‫;‪short sum = 0‬‬
‫)‪for (short* p = a; p < end; p++‬‬
‫;‪{ sum += *p‬‬
‫;‪cout << "\t p = " << p‬‬
‫;‪cout << "\t *p = " << *p‬‬
‫;‪cout << "\t sum = " << sum << endl‬‬
‫}‬
‫;‪cout << "end = " << end << endl‬‬
‫}‬
‫‪a = 0x3fffd1a‬‬
‫‪sizeof(short) = 2‬‬
‫‪p = 0x3fffd1a‬‬ ‫‪*p = 22‬‬ ‫‪sum = 22‬‬
‫‪p = 0x3fffd1c‬‬ ‫‪*p = 33‬‬ ‫‪sum = 55‬‬
‫‪p = 0x3fffd1e‬‬ ‫‪*p = 44‬‬ ‫‪sum = 99‬‬
‫‪end = 0x3fffd20‬‬

‫ﺗﺎﺑﻊ )(‪ sizeof‬ﺗﻌﺪﺍﺩ ﺑﺎﻳﺖﻫﺎﻳﻲ ﮐﻪ ﻳﮏ ﻧﻮﻉ ﺑﻨﻴﺎﺩﻱ ﺍﺷﻐﺎﻝ ﻣﻲﻧﻤﺎﻳﺪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬
‫ﺧﻂ ﺩﻭﻡ ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻧﻮﻉ ‪ short‬ﺩﺭ ﺍﻳﻦ ﺭﺍﻳﺎﻧﻪ ‪ 2‬ﺑﺎﻳﺖ ﺍﺯ ﺣﺎﻓﻈﻪ ﺭﺍ‬
‫ﺍﺷﻐﺎﻝ ﻣﻲﮐﻨﺪ‪ .‬ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﻧﻮﻉ ‪ short‬ﺑﺎ ﺳﻪ ﻋﻨﺼﺮ ﺍﻋﻼﻥ ﺷﺪﻩ‪ .‬ﻫﻤﭽﻨﻴﻦ‬
‫ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻳﻲ ﺑﻪ ﻧﺎﻡ ‪ p‬ﻭ ‪ end‬ﺍﺯ ﻧﻮﻉ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ‪ short‬ﺍﻋﻼﻥ ﺷﺪﻩﺍﻧﺪ‪ .‬ﭼﻮﻥ ‪p‬‬
‫ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ‪ short‬ﺍﺳﺖ‪ ،‬ﻫﺮ ﺯﻣﺎﻥ ﮐﻪ ‪ p‬ﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ‪ ،‬ﺩﻭ ﺑﺎﻳﺖ ﺑﻪ ﺁﺩﺭﺱ‬
‫ﺩﺭﻭﻥ ‪ p‬ﺍﺿﺎﻓﻪ ﻣﻲﮐﻨﺪ ﻭ ‪ p‬ﺩﺭ ﺣﻘﻴﻘﺖ ﺑﻪ ﻋﺪﺩ ‪ short‬ﺑﻌﺪﻱ ﭘﻴﺸﺮﻭﻱ ﻣﻲﻧﻤﺎﻳﺪ )ﻧﻪ ﺑﻪ‬
‫ﺧﺎﻥۀ ﺑﻌﺪﻱ ﺣﺎﻓﻈﻪ(‪ .‬ﺩﺭ ﺣﻠﻖۀ ‪ for‬ﺍﺑﺘﺪﺍ ﺁﺩﺭﺱ ﺁﺭﺍﻱۀ ‪ a‬ﺩﺭﻭﻥ ﺍﺷﺎﺭﻩﮔﺮ ‪ p‬ﻗﺮﺍﺭ‬
‫ﻣﻲﮔﻴﺮﺩ‪ .‬ﭘﺲ ‪ p‬ﺑﻪ ﺍﻭﻟﻴﻦ ﻋﻨﺼﺮ ﺁﺭﺍﻳﻪ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ‪ .‬ﻫﺮ ﺑﺎﺭ ﮐﻪ ﺣﻠﻘﻪ ﺗﮑﺮﺍﺭ ﺷﻮﺩ‪ ،‬ﻳﮏ‬
‫ﻭﺍﺣﺪ ﺑﻪ ‪ p‬ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ ﻭ ‪ p‬ﺑﻪ ﻋﻨﺼﺮ ﺑﻌﺪﻱ ﺁﺭﺍﻳﻪ ﺍﺷﺎﺭﻩ ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﻋﺒﺎﺭﺕ‬
‫;‪ sum += *p‬ﻧﻴﺰ ﻣﻘﺪﺍﺭ ﺁﻥ ﻋﻨﺼﺮ ﺭﺍ ﺩﺭﻳﺎﻓﺖ ﮐﺮﺩﻩ ﻭ ﺑﻪ ﻣﻘﺪﺍﺭ ‪ sum‬ﺍﺿﺎﻓﻪ ﻣﻲﮐﻨﺪ‪.‬‬
‫ﺍﻳﻦ ﻣﺜﺎﻝ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻫﺮ ﮔﺎﻩ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ‪ ،‬ﻣﻘﺪﺍﺭ ﺁﻥ ﺑﻪ ﺍﻧﺪﺍﺯۀ‬
‫ﺗﻌﺪﺍﺩ ﺑﺎﻳﺖﻫﺎﻱ ﺷﻴﺌﻲ ﮐﻪ ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ‪ ،‬ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ‪ .‬ﻣﺜﻼ ﺍﮔﺮ ‪ p‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ‬
‫‪227‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫‪ double‬ﺑﺎﺷﺪ ﻭ )‪ sizeof(double‬ﺑﺮﺍﺑﺮ ﺑﺎ ﻫﺸﺖ ﺑﺎﻳﺖ ﺑﺎﺷﺪ‪ ،‬ﻫﺮ ﮔﺎﻩ ﮐﻪ ‪ p‬ﻳﮏ‬


‫ﻭﺍﺣﺪ ﺍﻓﺰﺍﻳﺶ ﻳﺎﺑﺪ‪ ،‬ﺍﺷﺎﺭﻩﮔﺮ ‪ p‬ﻫﺸﺖ ﺑﺎﻳﺖ ﺑﻪ ﭘﻴﺶ ﻣﻲﺭﻭﺩ‪ .‬ﻣﺜﻼ ﮐﺪ ﺯﻳﺮ ‪:‬‬
‫;]‪float a[8‬‬
‫;‪float* p = a‬‬ ‫]‪// p points to a[0‬‬
‫;‪++p‬‬ ‫)‪// increases the value of p by sizeof(float‬‬

‫ﺍﮔﺮ ‪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‬‬

‫* ﻣﺜﺎﻝ ‪ 7‐11‬ﭘﻴﻤﺎﻳﺶ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺍﺯ ﻃﺮﻳﻖ ﺁﺩﺭﺱ‬


‫)(‪int main‬‬
‫‪{ short a[] = {22, 33, 44, 55,‬‬ ‫;}‪66‬‬
‫‪cout << "a = " << a << ", *a‬‬ ‫;‪= " << *a << endl‬‬
‫;‪for (short* p = a; p < a +5‬‬ ‫)‪p++‬‬
‫‪cout << "p = " << p << ",‬‬ ‫;‪*p = " << *p << endl‬‬
‫}‬
‫‪a‬‬ ‫=‬ ‫‪0x3fffd08,‬‬ ‫‪*a‬‬ ‫=‬ ‫‪22‬‬
‫‪p‬‬ ‫=‬ ‫‪0x3fffd08,‬‬ ‫‪*p‬‬ ‫=‬ ‫‪22‬‬
‫‪p‬‬ ‫=‬ ‫‪0x3fffd0a,‬‬ ‫‪*p‬‬ ‫=‬ ‫‪33‬‬
‫‪p‬‬ ‫=‬ ‫‪0x3fffd0c,‬‬ ‫‪*p‬‬ ‫=‬ ‫‪44‬‬
‫‪p‬‬ ‫=‬ ‫‪0x3fffd0e,‬‬ ‫‪*p‬‬ ‫=‬ ‫‪55‬‬
‫‪p‬‬ ‫=‬ ‫‪0x3fffd10,‬‬ ‫‪*p‬‬ ‫=‬ ‫‪66‬‬
‫‪p‬‬ ‫=‬ ‫‪0x3fffd12,‬‬ ‫‪*p‬‬ ‫=‬ ‫‪77‬‬

‫ﺩﺭ ﻧﮕﺎﻩ ﺍﻭﻝ‪ a ،‬ﻭ ‪ p‬ﻣﺎﻧﻨﺪ ﻫﻢ ﻫﺴﺘﻨﺪ‪ :‬ﻫﺮ ﺩﻭ ﺑﻪ ﻧﻮﻉ ‪ short‬ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﻨﺪ ﻭ ﻫﺮ ﺩﻭ‬
‫ﺩﺍﺭﺍﻱ ﻣﻘﺪﺍﺭ ‪ 0x3fffd08‬ﻫﺴﺘﻨﺪ‪ .‬ﺍﻣﺎ ‪ a‬ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ﺍﺳﺖ ﻭ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺍﻓﺰﺍﻳﺶ‬
‫ﻳﺎﺑﺪ ﺗﺎ ﺁﺭﺍﻳﻪ ﭘﻴﻤﺎﻳﺶ ﺷﻮﺩ‪ .‬ﭘﺲ ﺑﻪ ﺟﺎﻱ ﺁﻥ ‪ p‬ﺭﺍ ﺍﻓﺰﺍﻳﺶ ﻣﻲﺩﻫﻴﻢ ﺗﺎ ﺁﺭﺍﻳﻪ ﺭﺍ ﭘﻴﻤﺎﻳﺶ‬
‫ﮐﻨﻴﻢ‪ .‬ﺷﺮﻁ )‪ (p < a+5‬ﺣﻠﻘﻪ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‪ a+5 .‬ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ‪:‬‬
‫‪0x3fffd08 + 5*sizeof(short) = 0x3fffd08 + 5*2 = 0x3fffd08 + 0xa = 0x3fffd12‬‬

‫ﭘﺲ ﺣﻠﻘﻪ ﺗﺎ ﺯﻣﺎﻧﻲ ﮐﻪ ‪ p < 0x3fffd12‬ﺑﺎﺷﺪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‪.‬‬


‫ﻋﻤﻠﮕﺮ ﺯﻳﺮﻧﻮﻳﺲ ][ ﻣﺜﻞ ﻋﻤﻠﮕﺮ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ * ﺭﻓﺘﺎﺭ ﻣﻲﮐﻨﺪ‪ .‬ﻫﺮ ﺩﻭﻱ ﺍﻳﻦﻫﺎ‬
‫ﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﻪ ﻋﻨﺎﺻﺮ ﺁﺭﺍﻳﻪ ﺩﺳﺘﺮﺳﻲ ﻣﺴﺘﻘﻴﻢ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ‪.‬‬
‫‪a[0] == *a‬‬
‫)‪a[1] == *(a + 1‬‬
‫)‪a[2] == *(a + 2‬‬
‫‪...‬‬
‫‪...‬‬

‫ﭘﺲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﮐﺪ ﺯﻳﺮ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺁﺭﺍﻳﻪ ﺭﺍ ﭘﻴﻤﺎﻳﺶ ﻧﻤﻮﺩ‪:‬‬


‫)‪for (int i = 0; i < 8; i++‬‬
‫;‪cout << *(a + i) << endl‬‬
229 ‫ اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬/ ‫ﻓﺼﻞ هﻔﺘﻢ‬

‫ ﻣﻘﺎﻳﺲۀ ﺍﻟﮕﻮ‬7‐12 ‫* ﻣﺜﺎﻝ‬


‫ ﻋﻨﺼﺮ‬n2 ‫ ﺑﻪ ﺩﻧﺒﺎﻝ‬a1 ‫ ﻋﻨﺼﺮ ﺍﻭﻝ ﺁﺭﺍﻱۀ‬n1 ‫ ﺩﺭ ﻣﻴﺎﻥ‬loc() ‫ ﺗﺎﺑﻊ‬،‫ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ‬
‫ ﺍﺯ‬a2 ‫ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﮐﻪ‬a1 ‫ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺩﺭﻭﻥ‬،‫ ﺍﮔﺮ ﭘﻴﺪﺍ ﺷﺪ‬.‫ ﻣﻲﮔﺮﺩﺩ‬a2 ‫ﺍﻭﻝ ﺁﺭﺍﻱۀ‬
.‫ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬NULL ‫ﺁﻥﺟﺎ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ﻭﮔﺮﻧﻪ ﺍﺷﺎﺭﻩﮔﺮ‬
short* loc(short* a1, short* a2, int n1, int n2)
{ short* end1 = a1 + n1;
for (short* p1 = a1; p1 <end1; p1++)
if (*p1 == *a2)
{ for (int j = 0; j < n2; j++)
if (p1[j] != a2[j]) break;
if (j == n2) return p1;
}
return 0;
}

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‬‬

‫ﻭﻗﺘﻲ ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﺷﺒﻴﻪ ﺍﻳﻦ ﺍﻋﻼﻥ ﺷﻮﺩ‪:‬‬


‫;‪float* p‬‬ ‫‪// p is a pointer to a float‬‬

‫ﻳﮏ ﻓﻀﺎﻱ ﭼﻬﺎﺭﺑﺎﻳﺘﻲ ﺑﻪ ‪ p‬ﺗﺨﺼﻴﺺ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ )ﻣﻌﻤﻮﻻ )‪ sizeof(float‬ﭼﻬﺎﺭ‬


‫ﺑﺎﻳﺖ ﺍﺳﺖ(‪ .‬ﺣﺎﻻ ‪ p‬ﺍﻳﺠﺎﺩ ﺷﺪﻩ ﺍﺳﺖ ﺍﻣﺎ ﺑﻪ ﻫﻴﭻ ﺟﺎﻳﻲ ﺍﺷﺎﺭﻩ ﻧﻤﻲﮐﻨﺪ ﺯﻳﺮﺍ ﻫﻨﻮﺯ ﺁﺩﺭﺳﻲ‬
‫ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﻧﮕﺮﻓﺘﻪ‪ .‬ﺑﻪ ﭼﻨﻴﻦ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺷﺎﺭﻩﮔﺮ ﺳﺮﮔﺮﺩﺍﻥ ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺍﮔﺮ ﺳﻌﻲ ﮐﻨﻴﻢ‬
‫ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺳﺮﮔﺮﺩﺍﻥ ﺭﺍ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ ﻳﺎ ﺍﺭﺟﺎﻉ ﮐﻨﻴﻢ ﺑﺎ ﺧﻄﺎ ﻣﻮﺍﺟﻪ ﻣﻲﺷﻮﻳﻢ‪ .‬ﻣﺜﻼ ﺩﺳﺘﻮﺭ‪:‬‬
‫;‪*p = 3.14159‬‬ ‫‪// ERROR: no storage has been allocated for *P‬‬

‫ﺧﻄﺎﺳﺖ‪ .‬ﺯﻳﺮﺍ ‪ 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‬‬

‫ﻋﻤﻠﮕﺮ ‪ delete‬ﻋﻤﻠﻲ ﺑﺮﺧﻼﻑ ﻋﻤﻠﮕﺮ ‪ new‬ﺩﺍﺭﺩ‪ .‬ﮐﺎﺭﺵ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺣﺎﻓﻆۀ‬


‫ﺍﺷﻐﺎﻝ ﺷﺪﻩ ﺭﺍ ﺁﺯﺍﺩ ﮐﻨﺪ‪ .‬ﻭﻗﺘﻲ ﺣﺎﻓﻈﻪﺍﻱ ﺁﺯﺍﺩ ﺷﻮﺩ‪ ،‬ﺳﻴﺴﺘﻢ ﻋﺎﻣﻞ ﻣﻲﺗﻮﺍﻧﺪ ﺍﺯ ﺁﻥ ﺑﺮﺍﻱ‬
‫ﮐﺎﺭﻫﺎﻱ ﺩﻳﮕﺮ ﻳﺎ ﺣﺘﻲ ﺗﺨﺼﻴﺺﻫﺎﻱ ﺟﺪﻳﺪ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﺪ‪ .‬ﻋﻤﻠﮕﺮ ‪ delete‬ﺭﺍ ﺗﻨﻬﺎ ﺭﻭﻱ‬
‫ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻳﻲ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﮐﺎﺭ ﺑﺮﺩ ﮐﻪ ﺑﺎ ﺩﺳﺘﻮﺭ ‪ new‬ﺍﻳﺠﺎﺩ ﺷﺪﻩﺍﻧﺪ‪ .‬ﻭﻗﺘﻲ ﺣﺎﻓﻆۀ ﻳﮏ‬
‫ﺍﺷﺎﺭﻩﮔﺮ ﺁﺯﺍﺩ ﺷﺪ‪ ،‬ﺩﻳﮕﺮ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﺁﻥ ﺩﺳﺘﻴﺎﺑﻲ ﻧﻤﻮﺩ ﻣﮕﺮ ﺍﻳﻦ ﮐﻪ ﺩﻭﺑﺎﺭﻩ ﺍﻳﻦ ﺣﺎﻓﻈﻪ‬
‫ﺗﺨﺼﻴﺺ ﻳﺎﺑﺪ‪:‬‬
‫;)‪float* p = new float(3.14159‬‬
‫;‪delete p‬‬ ‫‪// deallocates q‬‬
‫;‪*p = 2.71828‬‬ ‫‪// ERROR: q has been deallocated‬‬

‫ﻭﻗﺘﻲ ﺍﺷﺎﺭﻩ ﮔﺮ ‪ p‬ﺩﺭ ﮐﺪ ﺑﺎﻻ ﺁﺯﺍﺩ ﺷﻮﺩ‪ ،‬ﺣﺎﻓﻈﻪﺍﻱ ﮐﻪ ﺗﻮﺳﻂ ‪ new‬ﺑﻪ ﺁﻥ ﺗﺨﺼﻴﺺ ﻳﺎﻓﺘﻪ‬
‫ﺑﻮﺩ‪ ،‬ﺁﺯﺍﺩ ﺷﺪﻩ ﻭ ﺑﻪ ﻣﻴﺰﺍﻥ )‪ sizeof(float‬ﺑﻪ ﺣﺎﻓﻆۀ ﺁﺯﺍﺩ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ‪ .‬ﻭﻗﺘﻲ‬
‫ﺍﺷﺎﺭﻩﮔﺮﻱ ﺁﺯﺍﺩ ﺷﺪ‪ ،‬ﺑﻪ ﻫﻴﭻ ﭼﻴﺰﻱ ﺍﺷﺎﺭﻩ ﻧﻤﻲﮐﻨﺪ؛ ﻣﺜﻞ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ‪ .‬ﺑﻪ‬
‫ﺍﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ‪ ،‬ﺍﺷﺎﺭﻩﮔﺮ ﺳﺮﮔﺮﺩﺍﻥ ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬
‫ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻳﮏ ﺷﻲﺀ ﺛﺎﺑﺖ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺁﺯﺍﺩ ﮐﺮﺩ‪:‬‬
‫;‪const int* p = new int‬‬
‫;‪delete p‬‬ ‫‪// ERROR: cannot delete pointer to const objects‬‬

‫ﻋﻠﺖ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ »ﺛﺎﺑﺖﻫﺎ ﻧﻤﻲﺗﻮﺍﻧﻨﺪ ﺗﻐﻴﻴﺮ ﮐﻨﻨﺪ«‪.‬‬


‫ﺍﮔﺮ ﻣﺘﻐﻴﺮﻱ ﺭﺍ ﺻﺮﻳﺤﺎ ﺍﻋﻼﻥ ﮐﺮﺩﻩﺍﻳﺪ ﻭ ﺳﭙﺲ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺁﻥ ﻧﺴﺒﺖ ﺩﺍﺩﻩﺍﻳﺪ‪ ،‬ﺍﺯ‬
‫ﻋﻤﻠﮕﺮ ‪ delete‬ﺍﺳﺘﻔﺎﺩﻩ ﻧﮑﻨﻴﺪ‪ .‬ﺍﻳﻦ ﮐﺎﺭ ﺑﺎﻋﺚ ﺍﺷﺘﺒﺎﻩ ﻏﻴﺮ ﻋﻤﺪﻱ ﺯﻳﺮ ﻣﻲﺷﻮﺩ‪:‬‬
‫‪233‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫;‪float x = 3.14159‬‬ ‫‪// x contains the value 3.14159‬‬


‫;‪float* p = &x‬‬ ‫‪// p contains the address of x‬‬
‫;‪delete p‬‬ ‫‪// WARNING: this will make x free‬‬

‫ﮐﺪ ﺑﺎﻻ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺣﺎﻓﻆۀ ﺗﺨﺼﻴﺺﻳﺎﻓﺘﻪ ﺑﺮﺍﻱ ‪ x‬ﺁﺯﺍﺩ ﺷﻮﺩ‪ .‬ﺍﻳﻦ ﺍﺷﺘﺒﺎﻩ ﺭﺍ ﺑﻪ‬
‫ﺳﺨﺘﻲ ﻣﻲﺗﻮﺍﻥ ﺗﺸﺨﻴﺺ ﺩﺍﺩ ﻭ ﺍﺷﮑﺎﻝﺯﺩﺍﻳﻲ ﮐﺮﺩ‪.‬‬

‫‪ 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‬‬

‫ﻫﻢ ‪ a‬ﻭ ﻫﻢ ‪ p‬ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﺛﺎﺑﺘﻲ ﻫﺴﺘﻨﺪ ﮐﻪ ﺑﻪ ﺑﻠﻮﮐﻲ ﺣﺎﻭﻱ ‪ 20‬ﻣﺘﻐﻴﺮ ‪ float‬ﺍﺷﺎﺭﻩ‬


‫ﺩﺍﺭﻧﺪ‪ .‬ﺑﻪ ﺍﻋﻼﻥ ‪ a‬ﺑﺴﺘﻪﺑﻨﺪﻱ ﺍﻳﺴﺘﺎ‪ 2‬ﻣﻲﮔﻮﻳﻨﺪ ﺯﻳﺮﺍ ﺍﻳﻦ ﮐﺪ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺣﺎﻓﻆۀ ﻣﻮﺭﺩ‬
‫ﻧﻴﺎﺯ ﺑﺮﺍﻱ ‪ a‬ﺩﺭ ﺯﻣﺎﻥ ﮐﺎﻣﭙﺎﻳﻞ ﺗﺨﺼﻴﺺ ﺩﺍﺩﻩ ﺷﻮﺩ‪ .‬ﻭﻗﻲ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﺷﻮﺩ‪ ،‬ﺑﻪ ﻫﺮ ﺣﺎﻝ‬
‫ﺣﺎﻓﻆۀ ﻣﺮﺑﻮﻃﻪ ﺗﺨﺼﻴﺺ ﺧﻮﺍﻫﺪ ﻳﺎﻓﺖ ﺣﺘﻲ ﺍﮔﺮ ﺍﺯ ﺁﻥ ﻫﻴﭻ ﺍﺳﺘﻔﺎﺩﻩﺍﻱ ﻧﺸﻮﺩ‪ .‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ‪ ،‬ﺁﺭﺍﻱۀ ﻓﻮﻕ ﺭﺍ ﻃﻮﺭﻱ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﮐﻪ ﺣﺎﻓﻈﻪ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺁﻥ ﻓﻘﻂ ﺩﺭ‬
‫ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺗﺨﺼﻴﺺ ﻳﺎﺑﺪ‪:‬‬
‫;]‪float* p = new float[20‬‬

‫ﺩﺳﺘﻮﺭ ﺑﺎﻻ‪ 20 ،‬ﺧﺎﻥۀ ﺧﺎﻟﻲ ﺣﺎﻓﻈﻪ ﺍﺯ ﻧﻮﻉ ‪ float‬ﺭﺍ ﺩﺭ ﺍﺧﺘﻴﺎﺭ ﮔﺬﺍﺷﺘﻪ ﻭ ﺍﺷﺎﺭﻩﮔﺮ ‪p‬‬
‫ﺭﺍ ﺑﻪ ﺧﺎﻥۀ ﺍﻭﻝ ﺁﻥ ﻧﺴﺒﺖ ﻣﻲﺩﻫﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﺁﺭﺍﻳﻪ‪» ،‬ﺁﺭﺍﻱۀ ﭘﻮﻳﺎ‪ «1‬ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﻃﺮﺯ‬
‫ﺍﻳﺠﺎﺩ ﺍﺷﻴﺎ ﺑﺴﺘﻪﺑﻨﺪﻱ ﭘﻮﻳﺎ‪ 3‬ﻳﺎ »ﺑﺴﺘﻪﺑﻨﺪﻱ ﺯﻣﺎﻥ ﺟﺮﺍ« ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬
‫ﺁﺭﺍﻱۀ ﺍﻳﺴﺘﺎﻱ ‪ a‬ﻭ ﺁﺭﺍﻱۀ ﭘﻮﻳﺎﻱ ‪ p‬ﺭﺍ ﺑﺎ ﻳﮑﺪﻳﮕﺮ ﻣﻘﺎﻳﺴﻪ ﮐﻨﻴﺪ‪ .‬ﺁﺭﺍﻱۀ ﺍﻳﺴﺘﺎﻱ ‪ a‬ﺩﺭ‬
‫ﺯﻣﺎﻥ ﮐﺎﻣﭙﺎﻳﻞ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﺗﺎ ﭘﺎﻳﺎﻥ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺣﺎﻓﻆۀ ﺗﺨﺼﻴﺼﻲ ﺑﻪ ﺁﻥ ﻣﺸﻐﻮﻝ‬
‫ﻣﻲﻣﺎﻧﺪ‪ .‬ﻭﻟﻲ ﺁﺭﺍﻱۀ ﭘﻮﻳﺎﻱ ‪ p‬ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﻭ ﻫﺮ ﺟﺎ ﮐﻪ ﻻﺯﻡ ﺷﺪ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﭘﺲ ﺍﺯ‬
‫ﺍﺗﻤﺎﻡ ﮐﺎﺭ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﻋﻤﻠﮕﺮ ‪ delete‬ﺣﺎﻓﻆۀ ﺗﺨﺼﻴﺼﻲ ﺑﻪ ﺁﻥ ﺭﺍ ﺁﺯﺍﺩ ﮐﺮﺩ‪:‬‬
‫;‪delete [] p‬‬

‫‪1 – Dynamic arrays‬‬ ‫‪2 – Static binding‬‬ ‫‪3 – Dynamic binding‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 234

p ‫ ﺑﺎﻳﺪ ﺣﺘﻤﺎ ﻗﻴﺪ ﺷﻮﻧﺪ ﺯﻳﺮﺍ‬p ‫ ﺑﺮﺍﮐﺖﻫﺎ ][ ﻗﺒﻞ ﺍﺯ ﻧﺎﻡ‬p ‫ﺑﺮﺍﻱ ﺁﺯﺍﺩ ﮐﺮﺩﻥ ﺁﺭﺍﻱۀ ﭘﻮﻳﺎﻱ‬
.‫ﺑﻪ ﻳﮏ ﺁﺭﺍﻳﻪ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‬

‫ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﺭﺍﻳﻪﻫﺎﻱ ﭘﻮﻳﺎ‬7‐15 ‫* ﻣﺜﺎﻝ‬


:‫ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﮏ ﺁﺭﺍﻱۀ ﭘﻮﻳﺎ ﺍﻳﺠﺎﺩ ﻣﻲﻛﻨﺪ‬get() ‫ﺗﺎﺑﻊ‬
void get(double*& a, int& n)
{ cout << "Enter number of items: "; cin >> n;
a = new double[n];
cout << "Enter " << n << " items, one per line:\n";
for (int i = 0; i < n; i++)
{ cout << "\t" << i+1 << ": ";
cin >> a[i];
}
}
void print(double* a, int n)
{ for (int i = 0; i < n; i++)
cout << a[i] << " " ;
cout << endl;
}
int main()
{ double* a; // a is simply an unallocated pointer
int n;
get(a,n); // now a is an array of n doubles
print(a,n);
delete [] a; // now a is simply an unallocated pointer again
get(a,n); // now a is an array of n doubles
print(a,n);
}
Enter number of items: 4
Enter 4 items, one per line:
1: 44.4
2: 77.7
3: 22.2
4: 88.8
44.4 77.7 22.2 88.8
Enter number of items: 2
‫‪235‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫‪Enter 2 items, one per line:‬‬


‫‪1: 3.33‬‬
‫‪2: 9.99‬‬
‫‪3.33 9.99‬‬

‫ﻭﻗﺘﻲ ﺑﺮﻧﺎﻣﻪ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ‪ ،‬ﺍﺑﺘﺪﺍ ﺍﺷﺎﺭﻩﮔﺮ ﺗﻬﻲ ‪ 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‬ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ‬
‫»ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻳﮏ ﺛﺎﺑﺖ« ﺑﺎ »ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ« ﺗﻔﺎﻭﺕ ﺩﺍﺭﺩ‪ .‬ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﺩﺭ ﻗﺎﻟﺐ ﻣﺜﺎﻝ‬
‫ﺯﻳﺮ ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 7‐16‬ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﺛﺎﺑﺖ ﻭ ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻳﻲ ﺑﻪ ﺛﺎﺑﺖﻫﺎ‬


‫ﺩﺭ ﺍﻳﻦ ﮐﺪ ﭼﻬﺎﺭ ﺍﺷﺎﺭﻩﮔﺮ ﺍﻋﻼﻥ ﺷﺪﻩ‪ .‬ﺍﺷﺎﺭﻩﮔﺮ ‪ ،p‬ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ‪ ،cp‬ﺍﺷﺎﺭﻩ ﺑﻪ‬
‫ﻳﮏ ﺛﺎﺑﺖ ‪ ،pc‬ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ﺑﻪ ﻳﮏ ﺛﺎﺑﺖ ‪: cpc‬‬
‫;‪int n = 44‬‬ ‫‪// an int‬‬
‫;‪int* p = &n‬‬ ‫‪// a pointer to an int‬‬
‫;)‪++(*p‬‬ ‫‪// OK: increments int *p‬‬
‫;‪++p‬‬ ‫‪// OK: increments pointer p‬‬
‫;‪int* const cp = &n‬‬ ‫‪// a const pointer to an int‬‬
‫;)‪++(*cp‬‬ ‫‪// OK: increments int *cp‬‬
‫;‪++cp‬‬ ‫‪// illegal: pointer cp is const‬‬
‫;‪const int k = 88‬‬ ‫‪// a const int‬‬
‫;‪const int * pc = &k‬‬ ‫‪// a pointer to a const int‬‬
‫;)‪++(*pc‬‬ ‫‪// illegal: int *pc is const‬‬
‫;‪++pc‬‬ ‫‪// OK: increments pointer pc‬‬
‫;‪const int* const cpc = &k‬‬ ‫‪// a const pointer to a const int‬‬
‫;)‪++(*cpc‬‬ ‫‪// illegal: int *pc is const‬‬
‫;‪++cpc‬‬ ‫‪// illegal: pointer cpc is const‬‬

‫ﺍﺷﺎﺭﻩﮔﺮ ‪ p‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﻣﺘﻐﻴﺮ ‪ n‬ﺍﺳﺖ‪ .‬ﻫﻢ ﺧﻮﺩ ‪ p‬ﻗﺎﺑﻞ ﺍﻓﺰﺍﻳﺶ ﺍﺳﺖ )‪ (++p‬ﻭ‬
‫ﻫﻢ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ‪ p‬ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ﻗﺎﺑﻞ ﺍﻓﺰﺍﻳﺶ ﺍﺳﺖ ))‪ .(++(*P‬ﺍﺷﺎﺭﻩ ﮔﺮ ‪ cp‬ﻳﮏ‬
‫ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﺁﺩﺭﺳﻲ ﮐﻪ ﺩﺭ ‪ cp‬ﺍﺳﺖ ﻗﺎﺑﻞ ﺗﻐﻴﻴﺮ ﻧﻴﺴﺖ ﻭﻟﻲ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺩﺭ‬
‫ﺁﻥ ﺁﺩﺭﺱ ﺍﺳﺖ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺩﺳﺖﮐﺎﺭﻱ ﮐﺮﺩ‪ .‬ﺍﺷﺎﺭﻩﮔﺮ ‪ pc‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺁﺩﺭﺱ‬
‫ﻳﮏ ﺛﺎﺑﺖ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ .‬ﺧﻮﺩ ‪ pc‬ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺗﻐﻴﻴﺮ ﺩﺍﺩ ﻭﻟﻲ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ‪ pc‬ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ‬
‫ﺩﺍﺭﺩ ﻗﺎﺑﻞ ﺗﻐﻴﻴﺮ ﻧﻴﺴﺖ‪ .‬ﺩﺭ ﺁﺧﺮ ﻫﻢ ‪ cpc‬ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ ﺑﻪ ﻳﮏ ﺷﻲﺀ ﺛﺎﺑﺖ ﺍﺳﺖ‪ .‬ﻧﻪ‬
‫ﻣﻘﺪﺍﺭ ‪ cpc‬ﻗﺎﺑﻞ ﺗﻐﻴﻴﺮ ﺍﺳﺖ ﻭ ﻧﻪ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺁﺩﺭﺱ ﺁﻥ ﺩﺭ ‪ cpc‬ﺍﺳﺖ‪.‬‬
‫‪237‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫‪ 7‐11‬ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‬
‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﺭﺍﻳﻪﺍﻱ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﮐﻪ ﺍﻋﻀﺎﻱ ﺁﻥ ﺍﺯ ﻧﻮﻉ ﺍﺷﺎﺭﻩﮔﺮ ﺑﺎﺷﻨﺪ‪ .‬ﻣﺜﻼ ﺩﺳﺘﻮﺭ‪:‬‬
‫;]‪float* p[4‬‬

‫ﺁﺭﺍﻱۀ ‪ p‬ﺭﺍ ﺑﺎ ﭼﻬﺎﺭ ﻋﻨﺼﺮ ﺍﺯ ﻧﻮﻉ *‪) float‬ﻳﻌﻨﻲ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ‪ (float‬ﺍﻋﻼﻥ‬


‫ﻣﻲﮐﻨﺪ‪ .‬ﻋﻨﺎﺻﺮ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﺜﻞ ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﻣﻌﻤﻮﻟﻲ ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩ‪:‬‬
‫;)‪p[0] = new float(3.14159‬‬
‫;)‪p[1] = new float(1.19‬‬

‫‪p‬‬
‫ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﺭﺍ ﻣﻲ ﺗﻮﺍﻧﻴﻢ ﺷﺒﻴﻪ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﻣﺠﺴﻢ ﮐﻨﻴﻢ‪:‬‬
‫‪0‬‬ ‫‪3.14159‬‬
‫‪1‬‬ ‫‪double‬‬
‫ﻣﺜﺎﻝ ﺑﻌﺪ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺑﻪ‬
‫‪2‬‬
‫‪3‬‬ ‫‪1.19‬‬ ‫ﭼﻪ ﺩﺭﺩﻱ ﻣﻲﺧﻮﺭﺩ‪ .‬ﺍﺯ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﻣﻲﺗﻮﺍﻥ ﺑﺮﺍﻱ ﻣﺮﺗﺐﮐﺮﺩﻥ‬
‫‪double‬‬
‫ﻳﮏ ﻓﻬﺮﺳﺖ ﻧﺎﻣﺮﺗﺐ ﺑﻪ ﺭﻭﺵ ﺣﺒﺎﺑﻲ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪ .‬ﺑﻪ‬
‫ﺟﺎﻱ ﺍﻳﻦ ﮐﻪ ﺧﻮﺩ ﻋﻨﺎﺻﺮ ﺟﺎﺑﺠﺎ ﺷﻮﻧﺪ‪ ،‬ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﺁﻥﻫﺎ ﺟﺎﺑﺠﺎ ﻣﻲﺷﻮﻧﺪ‪.‬‬

‫*ﻣﺜﺎﻝ ‪ 7‐17‬ﻣﺮﺗﺐﺳﺎﺯﻱ ﺣﺒﺎﺑﻲ ﻏﻴﺮﻣﺴﺘﻘﻴﻢ‬


‫)‪void sort(float* p[], int n‬‬
‫;‪{ float* temp‬‬
‫)‪for (int i = 1; i < n; i++‬‬
‫)‪for (int j = 0; j < n-i; j++‬‬
‫)]‪if (*p[j] > *p[j+1‬‬
‫;]‪{ temp = p[j‬‬
‫;]‪p[j] = p[j+1‬‬
‫;‪p[j+1] = temp‬‬
‫}‬
‫}‬

‫ﺗﺎﺑﻊ )(‪ sort‬ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺳﭙﺲ ﺩﺭﻭﻥ ﺣﻠﻘﻪﻫﺎﻱ ﺗﻮﺩﺭﺗﻮﻱ ‪for‬‬
‫ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﺪ ﮐﻪ ﺁﻳﺎ ﻣﻘﺎﺩﻳﺮﻱ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﻣﺠﺎﻭﺭ ﺑﻪ ﺁﻥﻫﺎ ﺍﺷﺎﺭﻩ ﺩﺍﺭﻧﺪ‪ ،‬ﻣﺮﺗﺐ‬
‫ﻫﺴﺘﻨﺪ ﻳﺎ ﻧﻪ‪ .‬ﺍﮔﺮ ﻣﺮﺗﺐ ﻧﺒﻮﺩﻧﺪ‪ ،‬ﺟﺎﻱ ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﺁﻥﻫﺎ ﺭﺍ ﺑﺎ ﻫﻢ ﻋﻮﺽ ﻣﻲﮐﻨﺪ‪ .‬ﺩﺭ ﭘﺎﻳﺎﻥ‬
‫ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﻓﻬﺮﺳﺖ ﻣﺮﺗﺐ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ‪ ،‬ﺁﺭﺍﻳﻪﺍﻱ ﺩﺍﺭﻳﻢ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎﻱ ﺩﺭﻭﻥ‬
‫ﺁﻥ ﺑﻪ ﺗﺮﺗﻴﺐ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺍﻧﺪ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪238‬‬

‫‪ 7‐12‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺩﻳﮕﺮ‬


‫ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺩﻳﮕﺮﻱ ﺍﺷﺎﺭﻩ ﮐﻨﺪ‪ .‬ﻣﺜﻼ‪:‬‬
‫;'‪char c = 't‬‬
‫;‪char* pc = &c‬‬
‫;‪char** ppc = &pc‬‬
‫;‪char*** pppc = &ppc‬‬
‫;'‪***pppc = 'w‬‬ ‫'‪// changes value of c to 'w‬‬

‫ﺣﺎﻻ ‪ pc‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﻣﺘﻐﻴﺮ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪ c‬ﺍﺳﺖ‪.‬‬


‫‪pppc‬‬ ‫‪ ppc‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ ‪ pc‬ﺍﺳﺖ ﻭ ﺍﺷﺎﺭﻩﮔﺮ‬
‫‪ pppc‬ﻫﻢ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ ‪ ppc‬ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ .‬ﻣﺜﻞ‬
‫‪ppc‬‬
‫ﺷﮑﻞ ﻣﻘﺎﺑﻞ‪:‬‬
‫‪pc‬‬
‫ﺑﺎ ﺍﻳﻦ ﻭﺟﻮﺩ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﺍﺷﺎﺭﻩﮔﺮ ‪ pppc‬ﻣﺴﺘﻘﻴﻤﺎ‬
‫'‪c '\t‬‬ ‫ﺑﻪ ﻣﺘﻐﻴﺮ ‪ c‬ﺭﺳﻴﺪ‪.‬‬

‫‪ 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‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫ﻓﺎﻳﺪۀ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺗﻮﺍﺑﻊ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﺍﻳﻦ‬


‫‪pf‬‬
‫ﻃﺮﻳﻖ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺗﻮﺍﺑﻊ ﻣﺮﮐﺐ ﺑﺴﺎﺯﻳﻢ‪ .‬ﻳﻌﻨﻲ‬
‫‪f‬‬ ‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﻳﮏ ﺗﺎﺑﻊ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﺁﺭﮔﻮﻣﺎﻥ ﺑﻪ ﺗﺎﺑﻊ‬
‫ﺩﻳﮕﺮ ﺍﺭﺳﺎﻝ ﮐﻨﻴﻢ! ﺍﻳﻦ ﮐﺎﺭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ‬
‫)‪int f(int n‬‬
‫{‬ ‫ﺑﻪ ﺗﺎﺑﻊ ﺍﻣﮑﺎﻥ ﭘﺬﻳﺮ ﺍﺳﺖ‪.‬‬
‫‪...‬‬
‫}‬
‫* ﻣﺜﺎﻝ ‪ 7‐18‬ﺗﺎﺑﻊ ﻣﺮﮐﺐ ﺟﻤﻊ‬
‫ﺗﺎﺑﻊ )(‪ sum‬ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺩﺍﺭﺩ‪ :‬ﺍﺷﺎﺭﻩﮔﺮ ﺗﺎﺑﻊ ‪ pf‬ﻭ ﻋﺪﺩ ﺻﺤﻴﺢ ‪: n‬‬
‫;)‪int sum(int (*)(int), int‬‬
‫;)‪int square(int‬‬
‫;)‪int cube(int‬‬

‫)(‪int main‬‬
‫;‪{ cout << sum(square,4) << endl‬‬ ‫‪// 1 + 4 + 9 + 16‬‬
‫;‪cout << sum(cube,4) << endl‬‬ ‫‪// 1 + 8 + 27 + 64‬‬
‫}‬

‫ﺗﺎﺑﻊ )(‪ 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‬‬
‫}‬

‫)‪int square(int k‬‬


‫;‪{ return k*k‬‬
‫}‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪240‬‬

‫)‪int cube(int k‬‬


‫;‪{ return k*k*k‬‬
‫}‬
‫‪30‬‬
‫‪100‬‬

‫‪ 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‬ﺑﻪ‬
‫ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪.‬‬

‫‪ NUL 7‐14‬ﻭ ‪NULL‬‬

‫ﺛﺎﺑﺖ ﺻﻔﺮ )‪ (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‬ﻳﺎ ﺻﻔﺮ ﺩﺭ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﻗﺮﺍﺭ‬


‫ﻣﻲﮔﻴﺮﺩ‪ ،‬ﺁﻥ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺧﺎﻧﻪ ‪ 0x0‬ﺩﺭ ﺣﺎﻓﻈﻪ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ .‬ﺍﻳﻦ ﺧﺎﻥۀ ﺣﺎﻓﻈﻪ‪ ،‬ﻳﮏ ﺧﺎﻥۀ‬
‫ﺍﺳﺘﺜﻨﺎﻳﻲ ﺍﺳﺖ ﮐﻪ ﻗﺎﺑﻞ ﭘﺮﺩﺍﺯﺵ ﻧﻴﺴﺖ‪ .‬ﻧﻪ ﻣﻲﺗﻮﺍﻥ ﺁﻥ ﺧﺎﻧﻪ ﺭﺍ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ ﮐﺮﺩ ﻭ ﻧﻪ‬
‫ﻣﻲﺗﻮﺍﻥ ﻣﻘﺪﺍﺭﻱ ﺭﺍ ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﺩﺍﺩ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺑﻪ ‪» NULL‬ﻫﻴﭻ ﭼﻴﺰ« ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬
‫ﻭﻗﺘﻲ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺭﺍ ﺑﺪﻭﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ‪ new‬ﺍﻋﻼﻥ ﻣﻲﮐﻨﻴﻢ‪ ،‬ﺧﻮﺏ ﺍﺳﺖ ﮐﻪ ﺍﺑﺘﺪﺍ ﺁﻥ‬
‫ﺭﺍ ‪ NULL‬ﮐﻨﻴﻢ ﺗﺎ ﻣﻘﺪﺍﺭ ﺯﺑﺎﻝۀ ﺁﻥ ﭘﺎﮎ ﺷﻮﺩ‪ .‬ﺍﻣﺎ ﻫﻤﻴﺸﻪ ﺑﺎﻳﺪ ﺑﻪ ﺧﺎﻃﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ ﮐﻪ‬
‫ﺍﺷﺎﺭﻩﮔﺮ ‪ NULL‬ﺭﺍ ﻧﺒﺎﻳﺪ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ ﻧﻤﺎﻳﻴﻢ‪:‬‬
‫;‪int* p = 0‬‬ ‫‪// p points to NULL‬‬
‫;‪*p = 22‬‬ ‫‪// ERROR: cannot dereference the NULL pointer‬‬

‫ﭘﺲ ﺧﻮﺏ ﺍﺳﺖ ﻫﻨﮕﺎﻡ ﻣﻘﺪﺍﺭﻳﺎﺑﻲ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‪ ،‬ﺍﺣﺘﻴﺎﻁ ﮐﺮﺩﻩ ﻭ ﺑﺮﺭﺳﻲ ﮐﻨﻴﻢ ﮐﻪ ﺁﻥ‬
‫ﺍﺷﺎﺭﻩﮔﺮ ‪ NULL‬ﻧﺒﺎﺷﺪ‪:‬‬
‫;‪if (p) *p = 22‬‬ ‫‪// O.K.‬‬

‫ﺣﺎﻻ ﺩﺳﺘﻮﺭ ;‪ *p=22‬ﻭﻗﺘﻲ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ﮐﻪ ‪ p‬ﺻﻔﺮ ﻧﺒﺎﺷﺪ‪ .‬ﻣﻲﺩﺍﻧﻴﺪ ﮐﻪ ﺷﺮﻁ ﺑﺎﻻ‬
‫ﻣﻌﺎﺩﻝ ﺷﺮﻁ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫;‪if (p != NULL) *p = 22‬‬

‫ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺖ‪ .‬ﺁﻥﻫﺎ ﺳﺮﻋﺖ ﭘﺮﺩﺍﺯﺵ ﺭﺍ ﺯﻳﺎﺩ ﻣﻲﮐﻨﻨﺪ ﻭ‬


‫ﮐﺪﻧﻮﻳﺴﻲ ﺭﺍ ﮐﻢ‪ .‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺑﻬﺘﺮﻳﻦ ﺷﮑﻞ ﺍﺯ ﺣﺎﻓﻈﻪ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪.‬‬
‫ﺑﺎ ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﻣﻲﺗﻮﺍﻥ ﺍﺷﻴﺎﻳﻲ ﭘﻴﭽﻴﺪﻩﺗﺮ ﻭ ﮐﺎﺭﺁﻣﺪﺗﺮ ﺳﺎﺧﺖ‪ .‬ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺩﺭ‬
‫ﻗﺎﻟﺐ »ﺳﺎﺧﺘﻤﺎﻥ ﺩﺍﺩﻩﻫﺎ« ﺑﺤﺚ ﻣﻲﺷﻮﺩ ﻭ ﻳﮑﻲ ﺍﺯ ﻣﻬﻢﺗﺮﻳﻦ ﻣﺒﺎﺣﺚ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫ﺍﺳﺖ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺳﻄﺢ ﭘﺎﻳﻴﻦ ﻭ ﺑﺮﺍﻱ ﺩﺳﺖﮐﺎﺭﻱ ﻣﻨﺎﺑﻊ‬
‫ﺳﺨﺖﺍﻓﺰﺍﺭﻱ ﻧﻴﺰ ﻓﺮﺍﻭﺍﻥ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ‪ .‬ﺍﻣﺎ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺍﻣﻨﻴﺖ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺑﻪ ﺧﻄﺮ‬
‫ﻣﻲﺍﻧﺪﺍﺯﻧﺪ‪ .‬ﻣﻲﺗﻮﺍﻧﻨﺪ ﺑﻪ ﺭﺍﺣﺘﻲ ﺑﺮﻧﺎﻡۀ ﺣﺎﺿﺮ ﻳﺎ ﺑﺮﻧﺎﻣﻪﻫﺎﻳﻲ ﮐﻪ ﻫﻢﺯﻣﺎﻥ ﺑﺎ ﺑﺮﻧﺎﻡۀ ﻓﻌﻠﻲ ﺩﺭ‬
‫ﺣﺎﻝ ﮐﺎﺭﻧﺪ ﺭﺍ ﺧﺮﺍﺏ ﮐﻨﻨﺪ‪ .‬ﻧﻤﻮﻧﻪﺍﻱ ﺍﺯ ﺍﻳﻦ ﺑﺤﺮﺍﻥ ﺭﺍ ﺩﺭ ﻣﺜﺎﻝﻫﺎﻱ ﺍﻳﻦ ﻓﺼﻞ ﺩﻳﺪﻳﻢ‪ .‬ﺍﮔﺮ‬
‫ﻣﻲﺧﻮﺍﻫﻴﺪ ﺍﺯ ﻣﺰﺍﻳﺎﻱ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺑﻬﺮﻩ ﺑﺒﺮﻳﺪ ﻭ ﮐﺎﺭﺁﻳﻲ ﺑﺮﻧﺎﻣﻪﺗﺎﻥ ﺭﺍ ﺑﻬﺒﻮﺩ ﺑﺒﺨﺸﻴﺪ‪ ،‬ﻫﻤﻴﺸﻪ‬
‫ﺑﺎﻳﺪ ﻣﺤﺘﺎﻃﺎﻧﻪ ﺑﺎ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺑﺮﺧﻮﺭﺩ ﮐﻨﻴﺪ‪ .‬ﺍﻳﻦ ﻓﻘﻂ ﻭﻗﺘﻲ ﻣﻤﮑﻦ ﺍﺳﺖ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ‬
‫ﺧﻮﺏ ﺷﻨﺎﺧﺘﻪ ﺑﺎﺷﻴﺪ ﻭ ﺑﺮﺍﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥﻫﺎ ﺗﺴﻠﻂ ﮐﺎﻓﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪242‬‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬
‫‪ – 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‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫ﺍﻟﻒ( ﻣﻘﺪﺍﺭ ‪ 50‬ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬


‫ﺏ( ﻣﻘﺪﺍﺭ ‪ 0x000cc70‬ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫ﺝ( ﻋﺒﺎﺭﺕ "‪ "&nt‬ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫ﺩ( ﺁﺩﺭﺱ ‪ p‬ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫‪ – 7‬ﺍﮔﺮ ‪ k‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﻧﻮﻉ ‪ float‬ﺑﺎﺷﺪ ﻭ ﺑﺨﻮﺍﻫﻴﻢ ‪ l‬ﺭﺍ ﻃﻮﺭﻱ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ﮐﻪ ﺑﻪ‬
‫‪ k‬ﺍﺷﺎﺭﻩ ﮐﻨﺪ‪ ،‬ﺁﻧﮕﺎﻩ ‪:‬‬
‫ﺍﻟﻒ( ‪ l‬ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ *‪ float‬ﺗﻌﺮﻳﻒ ﺷﻮﺩ‬
‫ﺏ( ‪ l‬ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ **‪ float‬ﺗﻌﺮﻳﻒ ﺷﻮﺩ‬
‫ﺝ( ‪ l‬ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ ‪ float‬ﺗﻌﺮﻳﻒ ﺷﻮﺩ‬
‫ﺩ( ‪ l‬ﺑﺎﻳﺪ ﺍﺯ ﻧﻮﻉ &‪ float‬ﺗﻌﺮﻳﻒ ﺷﻮﺩ‬
‫‪ – 8‬ﺍﮔﺮ ‪ pt‬ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺣﺎﺻﻞ ﻋﺒﺎﺭﺕ ﺯﻳﺮ ﭼﻴﺴﺖ؟‬
‫; ‪cout << pt << endl << *pt << endl << &pt‬‬
‫ﺍﻟﻒ( ﺭﻭﻱ ﺳﻄﺮ ﺍﻭﻝ ﺁﺩﺭﺱ ﺩﺭﻭﻥ ‪ pt‬ﻭ ﺭﻭﻱ ﺳﻄﺮ ﺩﻭﻡ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ‪ pt‬ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ‬
‫ﺩﺍﺭﺩ ﻭ ﺭﻭﻱ ﺳﻄﺮ ﺳﻮﻡ ﺁﺩﺭﺱ ﺧﻮﺩ ‪ pt‬ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫ﺏ( ﺭﻭﻱ ﺳﻄﺮ ﺍﻭﻝ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ‪ pt‬ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ﻭ ﺭﻭﻱ ﺳﻄﺮ ﺩﻭﻡ ﺁﺩﺭﺱ ﺩﺭﻭﻥ‬
‫‪ pt‬ﻭ ﺭﻭﻱ ﺳﻄﺮ ﺳﻮﻡ ﺁﺩﺭﺱ ﺧﻮﺩ ‪ pt‬ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫ﺝ( ﺭﻭﻱ ﺳﻄﺮ ﺍﻭﻝ ﺁﺩﺭﺱ ﺧﻮﺩ ‪ pt‬ﻭ ﺭﻭﻱ ﺳﻄﺮ ﺩﻭﻡ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ‪ pt‬ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ‬
‫ﻣﻲﮐﻨﺪ ﻭ ﺭﻭﻱ ﺳﻄﺮ ﺳﻮﻡ ﺁﺩﺭﺱ ﺩﺭﻭﻥ ‪ pt‬ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫ﺩ( ﺭﻭﻱ ﺳﻄﺮ ﺍﻭﻝ ﺁﺩﺭﺱ ﺩﺭﻭﻥ ‪ pt‬ﻭ ﺭﻭﻱ ﺳﻄﺮ ﺩﻭﻡ ﺁﺩﺭﺱ ﺧﻮﺩ ‪ pt‬ﻭ ﺭﻭﻱ ﺳﻄﺮ‬
‫ﺳﻮﻡ ﻣﻘﺪﺍﺭﻱ ﮐﻪ ‪ pt‬ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‬
‫‪ – 9‬ﺍﮔﺮ ‪ n‬ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﺯ ﻧﻮﻉ ﺑﻨﻴﺎﺩﻱ ﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ ‪:‬‬
‫ﺏ( ‪&(*n)=n‬‬ ‫ﺍﻟﻒ( ‪*(&n)=n‬‬
‫ﺩ( ‪&n=n‬‬ ‫ﺝ( ‪*n=n‬‬
‫‪ – 10‬ﮐﺪﺍﻡ ﻳﮏ ﺍﺯ ﺍﻋﻼﻥﻫﺎﻱ ﺯﻳﺮ‪ ،‬ﺗﺎﺑﻊ )(‪ f‬ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺑﺎﺯﮔﺸﺖ ﺍﺯ ﻧﻮﻉ ﺍﺭﺟﺎﻉ ﺍﻋﻼﻥ‬
‫ﻣﻲﮐﻨﺪ؟‬
‫ﺏ( )‪int* f(int k‬‬ ‫ﺍﻟﻒ( )‪int f(int& k‬‬
‫ﺩ( )‪void f(int& k‬‬ ‫ﺝ( )‪int& f(int k‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪244‬‬

‫‪ – 11‬ﺍﮔﺮ ‪ p‬ﺍﺯ ﻧﻮﻉ *‪ float‬ﺑﺎﺷﺪ ﻭ ‪ sizeof(float)=4‬ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺣﺎﺻﻞ‬


‫ﻋﺒﺎﺭﺕ ;‪ ++p‬ﭼﻴﺴﺖ؟‬
‫ﺍﻟﻒ( ﺁﺩﺭﺱ ﺩﺭﻭﻥ ‪ p‬ﻳﮏ ﺑﺎﻳﺖ ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ‬
‫ﺏ( ﺁﺩﺭﺱ ﺩﺭﻭﻥ ‪ p‬ﭼﻬﺎﺭﺑﺎﻳﺖ ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ‬
‫ﺝ( ﺁﺩﺭﺱ ﺩﺭﻭﻥ ‪ p‬ﺩﻭ ﺑﺎﻳﺖ ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ‬
‫ﺩ( ﮐﺎﻣﭙﺎﻳﻠﺮ ﺧﻄﺎ ﻣﻲﮔﻴﺮﺩ ﺯﻳﺮﺍ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺍﻓﺰﺍﻳﺶ ﺩﺍﺩ‬
‫‪ – 12‬ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟‬
‫ﺍﻟﻒ( ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻳﮏ ﺷﻲﺀ ﺛﺎﺑﺖ )‪ (const‬ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺁﺯﺍﺩ ﮐﺮﺩ‬
‫ﺏ( ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ‪ new‬ﻣﻲﺗﻮﺍﻥ ﻳﮏ ﺁﺩﺭﺱ ﺁﺯﺍﺩ ﺭﺍ ﺑﻪ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺍﺧﺘﺼﺎﺹ ﺩﺍﺩ‬
‫ﺝ( ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ‪ delete‬ﻣﻲﺗﻮﺍﻥ ﺁﺩﺭﺱ ﺗﺨﺼﻴﺺﻳﺎﻓﺘﻪ ﺑﻪ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺭﺍ ﺁﺯﺍﺩ ﮐﺮﺩ‬
‫ﺩ( ﭘﺲ ﺍﺯ ﺁﺯﺍﺩ ﮐﺮﺩﻥ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﻫﻨﻮﺯ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺁﺩﺭﺱ ﺁﻥ ﺩﺳﺘﻴﺎﺑﻲ ﻧﻤﻮﺩ‬
‫‪ – 13‬ﺍﮔﺮ ﻋﻤﻠﮕﺮ ‪ new‬ﻧﺘﻮﺍﻧﺪ ﻳﮏ ﺁﺩﺭﺱ ﺁﺯﺍﺩ ﭘﻴﺪﺍ ﮐﻨﺪ ﺁﻧﮕﺎﻩ‬
‫ﺍﻟﻒ( ﻣﻘﺪﺍﺭ ‪ NULL‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬
‫ﺏ( ﻣﻘﺪﺍﺭ ‪ NUL‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬
‫ﺝ( ﺧﻄﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺭﺥ ﻣﻲﺩﻫﺪ ﻭ ﺑﺮﻧﺎﻣﻪ ﻣﺘﻮﻗﻒ ﻣﻲﺷﻮﺩ‬
‫ﺩ( ﺩﻭﺑﺎﺭﻩ ﺗﻼﺵ ﻣﻲﮐﻨﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﻓﻀﺎﻱ ﺁﺯﺍﺩ ﺑﻴﺎﺑﺪ‬
‫‪ – 14‬ﮐﺪﺍﻡ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ( ﺁﺭﺍﻳﻪ ﭘﻮﻳﺎ ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭﻟﻲ ﺁﺭﺍﻳﻪ ﺍﻳﺴﺘﺎ ﺩﺭ ﺯﻣﺎﻥ ﮐﺎﻣﭙﺎﻳﻞ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ‬
‫ﺏ( ﺁﺭﺍﻳﻪ ﭘﻮﻳﺎ ﺭﺍ ﺩﺭ ﻫﺮ ﺯﻣﺎﻧﻲ ﻣﻲﺗﻮﺍﻥ ﺁﺯﺍﺩ ﮐﺮﺩ ﻭﻟﻲ ﺁﺭﺍﻳﻪ ﺍﻳﺴﺘﺎ ﺗﺎ ﭘﺎﻳﺎﻥ ﺑﺮﻧﺎﻣﻪ ﺑﺎﻗﻲ ﻣﻲﻣﺎﻧﺪ‬
‫ﺝ( ﺍﻧﺪﺍﺯﻩ ﺁﺭﺍﻳﻪ ﭘﻮﻳﺎ ﻣﺘﻐﻴﺮ ﺍﺳﺖ ﻭﻟﻲ ﺍﻧﺪﺍﺯﻩ ﺁﺭﺍﻳﻪ ﺍﻳﺴﺘﺎ ﺛﺎﺑﺖ ﺍﺳﺖ‬
‫ﺩ( ﻫﻤﻪ ﻣﻮﺍﺭﺩ ﻓﻮﻕ ﺻﺤﻴﺢ ﺍﺳﺖ‬
‫ﮐﺪﺍﻡ ﻋﺒﺎﺭﺕ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟‬ ‫;]‪float* t[10‬‬ ‫‪ – 15‬ﺩﺭ ﺭﺍﺑﻄﻪ ﺑﺎ ﻋﺒﺎﺭﺕ‬
‫ﺍﻟﻒ( ﺁﺭﺍﻳﻪ ‪ t‬ﻳﮏ ﺁﺭﺍﻳﻪ ﭘﻮﻳﺎ ﺍﺳﺖ‬
‫ﺏ( ﺁﺭﺍﻳﻪ ‪ t‬ﻳﮏ ﺁﺭﺍﻳﻪ ﺍﻳﺴﺘﺎ ﺍﺳﺖ‬
‫ﺝ( ﺍﻧﺪﺍﺯﻩ ﺁﺭﺍﻳﻪ ‪ t‬ﺩﺭ ﻫﻨﮕﺎﻡ ﺍﺟﺮﺍ ﻗﺎﺑﻞ ﺗﻐﻴﻴﺮ ﺍﺳﺖ‬
‫ﺩ( ﺁﺭﺍﻳﻪ ‪ t‬ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ‬
‫‪245‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪ ‐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‬‬

‫‪ ‐14‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﻛﺪ ﺯﻳﺮ ﺍﺳﺖ؟‬


‫;]‪short a[32‬‬
‫)‪for (int i = 0; i < 32; i++‬‬
‫;‪*a++ = i*i‬‬
‫‪ ‐15‬ﻣﻘﺪﺍﺭ ﻫﺮ ﻳﻚ ﺍﺯ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺯﻳﺮ ﺭﺍ ﺑﻌﺪ ﺍﺯ ﺍﺟﺮﺍ ﺷﺪﻥ ﻛﺪ ﺯﻳﺮ ﻣﺸﺨﺺ ﻛﻨﻴﺪ‪ .‬ﻓﺮﺽ‬
‫ﮐﻨﻴﺪ ﻛﻪ ﻫﺮﻋﺪﺩ ﺻﺤﻴﺢ ‪ 4‬ﺑﺎﻳﺖ ﺭﺍ ﺍﺷﻐﺎﻝ ﻣﻲﻛﻨﺪ ﻭ ‪ m‬ﺩﺭ ﻣﺤﻠﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﺫﺧﻴﺮﻩ ﺷﺪﻩ ﮐﻪ‬
‫ﺍﺯ ﺑﺎﻳﺖ ‪ 0x3fffd00‬ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ‪.‬‬
‫;‪int m = 44‬‬
‫;‪int* p = &m‬‬
‫;‪int& r = m‬‬
‫;)‪int n = (*p++‬‬
‫;‪int* q = p – 1‬‬
‫;‪r = *(--p) + 1‬‬
‫;‪++*q‬‬
‫ﺝ( ‪*q‬‬ ‫ﺙ( ‪r‬‬ ‫ﺕ( ‪*p‬‬ ‫ﭖ( ‪&m‬‬ ‫ﺏ( ‪n‬‬ ‫ﺍﻟﻒ( ‪m‬‬
‫‪ ‐16‬ﻫﺮ ﻳﻚ ﺍﺯ ﻣﻮﺍﺭﺩ ﺯﻳﺮ ﺭﺍ ﺩﺭ ﺩﺳﺘﻪﻫﺎﻱ ﭼﭗﻣﻘﺪﺍﺭ ﺗﻐﻴﻴﺮﭘﺬﻳﺮ‪ ،‬ﭼﭗﻣﻘﺪﺍﺭ ﺗﻐﻴﻴﺮﻧﺎﭘﺬﻳﺮ‬
‫ﻳﺎ ﻏﻴﺮﭼﭗﻣﻘﺪﺍﺭ ﻃﺒﻘﻪ ﺑﻨﺪﻱ ﻛﻨﻴﺪ‪:‬‬
‫ﺍﻟﻒ( ;‪double x = 1.23‬‬
‫ﺏ( ‪4.56*x + 7.89‬‬
‫ﭖ( ;‪const double y = 1.23‬‬
‫ﺕ( ;}‪double a[8] = {0.0‬‬
‫ﺙ( ]‪a[5‬‬
‫ﺝ( ;} ‪double f() { return 1.23‬‬
‫ﭺ( )‪f(1.23‬‬
‫ﺡ( ;‪double& r = x‬‬
‫ﺥ( ;‪double* p = &x‬‬
‫ﺩ( ‪*p‬‬
‫ﺫ( ;‪const double* p = &x‬‬
‫ﺭ( ;‪double* const p = &x‬‬
‫‪ ‐17‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﻛﺪ ﺯﻳﺮ ﺍﺳﺖ؟‬
‫;‪float x = 3.14159‬‬
‫;‪float* p = &x‬‬
‫;‪short d = 44‬‬
‫‪247‬‬ ‫ﻓﺼﻞ هﻔﺘﻢ ‪ /‬اﺷﺎرﻩﮔﺮهﺎ و ارﺟﺎعهﺎ‬

‫;‪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‬‬

‫ﭖ( ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻳﻚ ﺁﺭﺍﻳﻪ ﺍﺯ ﻫﺸﺖ ‪float‬‬


‫ﺕ( ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻳﻚ ﺁﺭﺍﻳﻪ ﺍﺯ ﻫﺸﺖ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ‪float‬‬
‫ﺙ( ﻳﻚ ﺗﺎﺑﻊ ﻛﻪ ﻳﻚ ‪ float‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬
‫ﺝ( ﻳﻚ ﺗﺎﺑﻊ ﻛﻪ ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ‪ float‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬
‫ﭺ( ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺗﺎﺑﻊ ﻛﻪ ﻳﻚ ‪ float‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬
‫ﺡ( ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﻳﻚ ﺗﺎﺑﻊ ﻛﻪ ﻳﻚ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ‪ float‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪ ‐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‬‬

‫‪ p‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺯ ﻧﻮﻉ *‪ int‬ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﺍﺷﺎﺭﻩﮔﺮﻱ ﮐﻪ ﺑﻪ ﻳﮏ ﻣﻘﺪﺍﺭ ‪ int‬ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪.‬‬


‫ﻋﺒﺎﺭﺕ ‪ &n‬ﺁﺩﺭﺱ ﻣﺘﻐﻴﺮ ‪ n‬ﺭﺍ ﺑﻪ ﺩﺳﺖ ﻣﻲﺁﻭﺭﺩ‪ .‬ﺍﻳﻦ ﺁﺩﺭﺱ ﺩﺭﻭﻥ ﺍﺷﺎﺭﻩﮔﺮ ‪ p‬ﻗﺮﺍﺭ‬
‫ﮔﺮﻓﺘﻪ ﺍﺳﺖ‪ .‬ﺣﺎﻻ ﺍﺷﺎﺭﻩﮔﺮ ‪ p‬ﺑﻪ ‪ n‬ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺩﺳﺘﻮﺭ‬
‫;‪*p = 55‬‬

‫ﻣﻘﺪﺍﺭ ‪ n‬ﺭﺍ ﺑﻪ ‪ 55‬ﺗﻐﻴﻴﺮ ﻣﻲﺩﻫﺪ‪.‬‬


‫ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ‪ ،‬ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﺴﺘﻘﻞ ﺍﺳﺖ ﮐﻪ ﻓﻀﺎﻱ ﺫﺧﻴﺮﻩﺳﺎﺯﻱ ﻣﺠﺰﺍﻳﻲ ﺩﺍﺭﺩ‪ .‬ﻣﺜﻼ‬
‫ﺩﺭ ﮐﺪ ﺑﺎﻻ ﺍﮔﺮ ﺁﺩﺭﺱ ‪ n‬ﻫﻨﮕﺎﻡ ﺍﺟﺮﺍ ‪ 64fddc‬ﺑﺎﺷﺪ‪ ،‬ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺩﺭﻭﻥ ﺍﺷﺎﺭﻩﮔﺮ ‪ p‬ﺫﺧﻴﺮﻩ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺧﻮﺩ ‪ p‬ﻣﻲﺗﻮﺍﻧﺪ ﺩﺍﺭﺍﻱ ﺁﺩﺭﺱ ‪ 64ff19‬ﺑﺎﺷﺪ ﮐﻪ ﻣﻘﺪﺍﺭ ‪ 64fddc‬ﺩﺭﻭﻥ ﺁﻥ‬
‫ﺁﺩﺭﺱ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ‪.‬‬
‫ﻳﮏ ﺷﻲ ﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﻣﺜﻼ ﺩﺳﺘﻮﺭ‬
‫;‪float* q = &n‬‬

‫ﺍﺷﺎﺭﻩﮔﺮ ﺩﻳﮕﺮﻱ ﺑﻪ ﻧﺎﻡ ‪ q‬ﺍﻋﻼﻥ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﻫﻢ ﺑﻪ ‪ n‬ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ .‬ﺣﺎﻻ ﻫﻢ ‪ p‬ﻭ ﻫﻢ ‪q‬‬
‫ﺑﻪ ‪ n‬ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﻨﺪ‪ .‬ﺍﻟﺒﺘﻪ ‪ p‬ﻭ ‪ q‬ﺩﻭ ﺍﺷﺎﺭﻩﮔﺮ ﻣﺠﺰﺍ ﻭ ﻣﺴﺘﻘﻞ ﺍﺯ ﻫﻢ ﻫﺴﺘﻨﺪ‪ .‬ﺑﺎ ﺩﺳﺘﻮﺭ‬
‫;‪cout << *p‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪252‬‬

‫ﻣﻘﺪﺍﺭ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ‪ p‬ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ ،‬ﭼﺎﭖ ﻣﻲﺷﻮﺩ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺑﺎ ﺩﺳﺘﻮﺭ‬


‫;‪cout << p‬‬

‫ﺁﺩﺭﺱ ﻣﺘﻐﻴﺮﻱ ﮐﻪ ‪ p‬ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﭼﺎﭖ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻟﺒﺘﻪ ﺍﮐﻨﻮﻥ ﺑﻪ ﻳﮏ ﺍﺳﺘﺜﻨﺎ‬
‫ﺑﺮﻣﻲﺧﻮﺭﻳﻢ‪ .‬ﺍﮔﺮ ‪ p‬ﺍﺯ ﻧﻮﻉ *‪ char‬ﺑﺎﺷﺪ‪ ،‬ﺣﺎﺻﻞ ;‪ cout << p‬ﻃﻮﺭ ﺩﻳﮕﺮﻱ‬
‫ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪.‬‬

‫‪ 8‐3‬ﺭﺷﺘﻪﻫﺎﻱ ﻛﺎﺭﺍﻛﺘﺮﻱ ﺩﺭ ‪C‬‬

‫ﺩﺭ ﺯﺑﺎﻥ ‪ C++‬ﻳﻚ »ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ« ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﺳﺖ ﮐﻪ ﺍﻳﻦ ﺁﺭﺍﻳﻪ‬


‫ﺩﺍﺭﺍﻱ ﻭﻳﮋﮔﻲ ﻣﻬﻢ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫‪ ‐ 1‬ﻳﻚ ﺑﺨﺶ ﺍﺿﺎﻓﻲ ﺩﺭ ﺍﻧﺘﻬﺎﻱ ﺁﺭﺍﻳﻪ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﮐﻪ ﻣﻘﺪﺍﺭ ﺁﻥ‪ ،‬ﮐﺎﺭﺍﮐﺘﺮ ‪ NUL‬ﻳﻌﻨﻲ‬
‫'‪ '\0‬ﺍﺳﺖ‪ .‬ﭘﺲ ﺗﻌﺪﺍﺩ ﮐﻞ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺩﺭ ﺁﺭﺍﻳﻪ ﻫﻤﻴﺸﻪ ﻳﮑﻲ ﺑﻴﺸﺘﺮ ﺍﺯ ﻃﻮﻝ ﺭﺷﺘﻪ ﺍﺳﺖ‪.‬‬
‫‪ – 2‬ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﻟﻴﺘﺮﺍﻝ ﺭﺷﺘﻪﺍﻱ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ ﻣﻘﺪﺍﺭﮔﺬﺍﺭﻱ ﮐﺮﺩ‬
‫;"‪char str[] = "string‬‬ ‫ﻣﺜﻞ‪:‬‬
‫ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﺍﻳﻦ ﺁﺭﺍﻳﻪ ﻫﻔﺖ ﻋﻨﺼﺮ ﺩﺍﺭﺩ‪ 's' :‬ﻭ '‪ 't‬ﻭ '‪ 'r‬ﻭ '‪ 'i‬ﻭ '‪ 'n‬ﻭ‬
‫'‪ 'g‬ﻭ '‪.'\0‬‬
‫‪ – 3‬ﮐﻞ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﺜﻞ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻌﻤﻮﻟﻲ ﭼﺎﭖ ﮐﺮﺩ‪ .‬ﻣﺜﻞ‪:‬‬
‫;‪cout << str‬‬

‫ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ‪ ،‬ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺩﺭﻭﻥ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪ str‬ﻳﮑﻲ ﻳﮑﻲ ﺑﻪ ﺧﺮﻭﺟﻲ‬
‫ﻣﻲﺭﻭﻧﺪ ﺗﺎ ﻭﻗﺘﻲ ﮐﻪ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺍﻧﺘﻬﺎﻳﻲ ‪ NUL‬ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ‪.‬‬
‫‪ – 4‬ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﺜﻞ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻌﻤﻮﻟﻲ ﺍﺯ ﻭﺭﻭﺩﻱ ﺩﺭﻳﺎﻓﺖ ﮐﺮﺩ‬
‫;‪cin >> str‬‬ ‫ﻣﺜﻞ‪:‬‬
‫ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ‪ ،‬ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺍﺭﺩ ﺷﺪﻩ ﻳﮑﻲ ﻳﮑﻲ ﺩﺭﻭﻥ ‪ str‬ﺟﺎﻱ ﻣﻲﮔﻴﺮﻧﺪ ﺗﺎ‬
‫ﻭﻗﺘﻲ ﮐﻪ ﺑﻪ ﻳﮏ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﺩﺭ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺭﻭﺩﻱ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ‪ .‬ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ ﺑﺎﻳﺪ‬
‫ﻣﻄﻤﺌﻦ ﺑﺎﺷﺪ ﮐﻪ ﺁﺭﺍﻱۀ ‪ str‬ﺑﺮﺍﻱ ﺩﺭﻳﺎﻓﺖ ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺍﺭﺩ ﺷﺪﻩ ﺟﺎ ﺩﺍﺭﺩ‪.‬‬
‫‪253‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫‪ – 5‬ﺗﻮﺍﺑﻊ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪ <cstring‬ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺮﺍﻱ ﺩﺳﺖﮐﺎﺭﻱ‬


‫ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﻪ ﮐﺎﺭ ﺑﮕﻴﺮﻳﻢ‪ .‬ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﻋﺒﺎﺭﺗﻨﺪ ﺍﺯ‪ :‬ﺗﺎﺑﻊ ﻃﻮﻝ ﺭﺷﺘﻪ )(‪، strlen‬‬
‫ﺗﻮﺍﺑﻊ ﮐﭙﻲ ﺭﺷﺘﻪ )(‪ strcpy‬ﻭ )(‪ ، strncpy‬ﺗﻮﺍﺑﻊ ﺍﻟﺼﺎﻕ ﺭﺷﺘﻪﻫﺎ )(‪ strcat‬ﻭ‬
‫)(‪ ، strncat‬ﺗﻮﺍﺑﻊ ﻣﻘﺎﻳﺲۀ ﺭﺷﺘﻪﻫﺎ )(‪ strcmp‬ﻭ )(‪ strncmp‬ﻭ ﺗﺎﺑﻊ‬
‫ﺍﺳﺘﺨﺮﺍﺝ ﻧﺸﺎﻧﻪ )(‪ . strtok‬ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺩﺭ ﺑﺨﺶ ‪ 8‐8‬ﺗﻮﺿﻴﺢ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐1‬ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﺎ ﻛﺎﺭﺍﻛﺘﺮ ‪ NUL‬ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﻨﺪ‬


‫ﺑﺮﻧﺎﻡۀ ﮐﻮﭼﮏ ﺯﻳﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮ '‪ '\0‬ﺑﻪ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺍﻟﺼﺎﻕ‬
‫ﻣﻲﺷﻮﺩ‪:‬‬
‫)(‪int main‬‬
‫;"‪{ char s[] = "ABCD‬‬
‫)‪for (int i = 0; i < 5; i++‬‬
‫;"‪cout << "s[" << i << "] = '" << s[i] << "'\n‬‬
‫}‬
‫'‪s[0] = 'A‬‬
‫'‪s[1] = 'B‬‬
‫'‪s[2] = 'C‬‬
‫'‪s[3] = 'D‬‬
‫'' = ]‪s[4‬‬

‫‪S‬‬ ‫ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪ s‬ﺩﺍﺭﺍﻱ ﭘﻨﺞ ﻋﻀﻮ ﺍﺳﺖ ﮐﻪ ﻋﻀﻮ ﭘﻨﺠﻢ‪ ،‬ﮐﺎﺭﺍﮐﺘﺮ '‪'\0‬‬
‫‪0‬‬ ‫‪A‬‬ ‫ﻣﻲﺑﺎﺷﺪ‪ .‬ﺗﺼﻮﻳﺮ ﺧﺮﻭﺟﻲ ﺍﻳﻦ ﻣﻄﻠﺐ ﺭﺍ ﺗﺎﻳﻴﺪ ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﻭﻗﺘﻲ ﮐﺎﺭﺍﮐﺘﺮ‬
‫‪1‬‬ ‫‪B‬‬
‫‪2‬‬ ‫‪C‬‬ ‫'‪ '\0‬ﺑﻪ ‪ cout‬ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ‪ ،‬ﻫﻴﭻ ﭼﻴﺰ ﭼﺎﭖ ﻧﻤﻲﺷﻮﺩ‪ .‬ﺣﺘﻲ ﺟﺎﻱ‬
‫‪3‬‬ ‫‪D‬‬
‫‪4‬‬ ‫‪Ø‬‬ ‫ﺧﺎﻟﻲ ﻫﻢ ﭼﺎﭖ ﻧﻤﻲﺷﻮﺩ‪ .‬ﺧﻂ ﺁﺧﺮ ﺧﺮﻭﺟﻲ‪ ،‬ﻋﻀﻮ ﭘﻨﺠﻢ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲ ﺩﻫﺪ‬
‫ﮐﻪ ﻣﻴﺎﻥ ﺩﻭ ﻋﻼﻣﺖ ﺁﭘﺴﺘﺮﻭﻑ ﻫﻴﭻ ﭼﻴﺰﻱ ﭼﺎﭖ ﻧﺸﺪﻩ‪.‬‬

‫‪ 8‐ 4‬ﻭﺭﻭﺩﻱ‪/‬ﺧﺮﻭﺟﻲ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ‬


‫ﺩﺭ ‪ C++‬ﺑﻪ ﭼﻨﺪ ﺭﻭﺵ ﻣﻲﺗﻮﺍﻥ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﺩﺭﻳﺎﻓﺖ ﮐﺮﺩﻩ ﻳﺎ ﻧﻤﺎﻳﺶ‬
‫ﺩﺍﺩ‪ .‬ﻳﮏ ﺭﺍﻩ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ﮐﻼﺱ ‪ string‬ﺍﺳﺖ ﮐﻪ ﺩﺭ ﺑﺨﺶﻫﺎﻱ ﺑﻌﺪﻱ ﺑﻪ ﺁﻥ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪254‬‬

‫ﺧﻮﺍﻫﻴﻢ ﭘﺮﺩﺍﺧﺖ‪ .‬ﺭﻭﺵ ﺩﻳﮕﺮ‪ ،‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﮐﻤﮑﻲ ﺍﺳﺖ ﮐﻪ ﺁﻥ ﺭﺍ ﺩﺭ ﺍﺩﺍﻣﻪ ﺷﺮﺡ‬
‫ﻣﻲﺩﻫﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐2‬ﺭﻭﺵ ﺳﺎﺩۀ ﺩﺭﻳﺎﻓﺖ ﻭ ﻧﻤﺎﻳﺶ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ‬


‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﻪ ﻃﻮﻝ ‪ 79‬ﮐﺎﺭﺍﮐﺘﺮ ﺍﻋﻼﻥ ﺷﺪﻩ ﻭ ﮐﻠﻤﺎﺗﻲ ﮐﻪ‬
‫ﺍﺯ ﻭﺭﻭﺩﻱ ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ ﺩﺭ ﺁﻥ ﺭﺷﺘﻪ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪:‬‬
‫)(‪int main‬‬
‫;]‪{ char word[80‬‬
‫‪do‬‬
‫;‪{ cin >> word‬‬
‫;"‪if (*word) cout << "\t\"" << word << "\"\n‬‬
‫;)‪} while (*word‬‬
‫}‬
‫‪Today's date is April 1, 2005.‬‬
‫"‪"Today's‬‬
‫"‪"date‬‬
‫"‪"is‬‬
‫"‪"April‬‬
‫"‪"1,‬‬
‫"‪"2005.‬‬
‫‪Tomorrow is Saturday.‬‬
‫"‪"Tomorrow‬‬
‫"‪"is‬‬
‫"‪"Saturday.‬‬
‫‪^z‬‬

‫ﻭﻗﺘﻲ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺩﺳﺘﻮﺭ ‪ 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‬‬
‫}‬

‫ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻧﻘﻄﻪﮔﺬﺍﺭﻱ )ﺁﭘﺴﺘﺮﻭﻑ‪ ،‬ﻧﻘﻄﻪ‪ ،‬ﻭﻳﺮﮔﻮﻝ ‪ ،‬ﮐﺎﻣﺎ ﻭ ‪(...‬‬


‫ﻣﻲﺗﻮﺍﻧﻨﺪ ﺩﺭ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻓﻮﻕ ﻭﺟﻮﺩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ ﻭﻟﻲ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻓﻀﺎﻱ ﺳﻔﻴﺪ‬
‫)ﺟﺎﻱ ﺧﺎﻟﻲ‪ ،‬ﭘﺮﺵﻫﺎ‪ ،‬ﺧﻂ ﺟﺪﻳﺪ ﻭ ‪ (...‬ﭼﻨﻴﻦ ﻧﻴﺴﺘﻨﺪ‪.‬‬
‫ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ << ﺑﺎ ﺍﺷﺎﺭﻩﮔﺮ ﻧﻮﻉ *‪ char‬ﺭﻓﺘﺎﺭ ﻣﺘﻔﺎﻭﺗﻲ ﺩﺍﺭﺩ‪ .‬ﺍﻳﻦ‬
‫ﻋﻤﻠﮕﺮ ﻭﻗﺘﻲ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ ﻧﻮﻉ *‪ char‬ﺑﺮﺧﻮﺭﺩ ﮐﻨﺪ ﮐﻞ ﺭﺷﺘﻪﺍﻱ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ‬
‫ﻣﻲﮐﻨﺪ ﺭﺍ ﭼﺎﭖ ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﺩﺭ ﺻﻮﺭﺗﻲ ﮐﻪ ﺑﺎ ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺯ ﻧﻮﻉ ﺩﻳﮕﺮ‪ ،‬ﻓﻘﻂ ﺁﺩﺭﺱ ﺩﺭﻭﻥ‬
‫ﺁﻥ ﺍﺷﺎﺭﻩﮔﺮ ﺭﺍ ﭼﺎﭖ ﻣﻲﻧﻤﺎﻳﺪ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪256‬‬

‫‪ 8‐5‬ﭼﻨﺪ ﺗﺎﺑﻊ ﻋﻀﻮ ‪ cin‬ﻭ ‪cout‬‬

‫ﺑﻪ ‪ cin‬ﺷﻲﺀ ﻓﺮﺁﻳﻨﺪ ﻭﺭﻭﺩﻱ ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺍﻳﻦ ﺷﻲ ﺷﺎﻣﻞ ﺗﻮﺍﺑﻊ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫)(‪cin.getline() , cin.get() , cin.ignore() , cin.putback() , cin.peek‬‬

‫ﻫﻢۀ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺷﺎﻣﻞ ﭘﻴﺸﻮﻧﺪ ‪ cin‬ﻫﺴﺘﻨﺪ ﺯﻳﺮﺍ ﺁﻥﻫﺎ ﻋﻀﻮﻱ ﺍﺯ ‪ cin‬ﻣﻲﺑﺎﺷﻨﺪ‪ .‬ﺑﻪ‬
‫‪ cout‬ﺷﻲﺀ ﻓﺮﺁﻳﻨﺪ ﺧﺮﻭﺟﻲ ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺍﻳﻦ ﺷﻲ ﻧﻴﺰ ﺷﺎﻣﻞ ﺗﺎﺑﻊ )(‪ cout.put‬ﺍﺳﺖ‪.‬‬
‫ﻧﺤﻮۀ ﮐﺎﺭﺑﺮﺩ ﻫﺮ ﻳﮏ ﺍﺯ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺭﺍ ﺩﺭ ﺍﺩﺍﻣﻪ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ‪.‬‬
‫ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ‪ n‬ﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ‬ ‫ﻓﺮﺍﺧﻮﺍﻧﻲ ;)‪cin.getline(str,n‬‬
‫ﺩﺭﻭﻥ ‪ str‬ﺧﻮﺍﻧﺪﻩ ﺷﻮﺩ ﻭ ﻣﺎﺑﻘﻲ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺍﺭﺩ ﺷﺪﻩ ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﻧﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐3‬ﺗﺎﺑﻊ )(‪ cin.getline‬ﺑﺎ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻭﺭﻭﺩﻱ ﺭﺍ ﺧﻂ ﺑﻪ ﺧﻂ ﺑﻪ ﺧﺮﻭﺟﻲ ﻣﻲﻓﺮﺳﺘﺪ‪:‬‬
‫)(‪int main‬‬
‫;]‪{ char line[80‬‬
‫‪do‬‬
‫;)‪{ cin.getline(line,80‬‬
‫;"‪if (*line) cout << "\t[" << line << "]\n‬‬
‫;)‪} while (*line‬‬
‫}‬

‫ﺷﺮﻁ ﮐﻨﺘﺮﻝ ﺣﻠﻘﻪ ﺑﻪ ﺷﮑﻞ )‪ (*line‬ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺷﺮﻁ ﻓﻘﻂ ﻭﻗﺘﻲ ‪ true‬ﺍﺳﺖ ﮐﻪ‬
‫ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪ line‬ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻏﻴﺮ ﺗﻬﻲ ﺑﺎﺷﺪ‪ .‬ﻫﺮ ﺑﺎﺭ ﮐﻪ ﺣﻠﻘﻪ ﺍﺟﺮﺍ‬
‫ﻣﻲﮔﺮﺩﺩ‪ 80 ،‬ﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ ﺩﺭﻭﻥ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪ line‬ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺗﺎﺑﻊ )(‪ getline‬ﻧﺴﺦۀ ﺩﻳﮕﺮﻱ ﻫﻢ ﺩﺍﺭﺩ‪ .‬ﻭﻗﺘﻲ ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺎ ﺳﻪ ﭘﺎﺭﺍﻣﺘﺮ ﺑﻪ ﺷﮑﻞ‬
‫;)‪cin.getline(str, n, ch‬‬

‫ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ‪ ،‬ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺭﻭﺩﻱ ﺑﻪ ﺩﺭﻭﻥ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪ str‬ﻣﻨﺘﻘﻞ‬


‫ﻣﻲﺷﻮﻧﺪ ﺗﺎ ﺍﻳﻦ ﮐﻪ ﺗﻌﺪﺍﺩﺷﺎﻥ ﺑﻪ ‪ n‬ﮐﺎﺭﺍﮐﺘﺮ ﺑﺮﺳﺪ ﻳﺎ ﺍﻳﻦ ﮐﻪ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺧﺎﺹ ‪ ch‬ﺑﺮﺧﻮﺭﺩ‬
‫ﺷﻮﺩ‪ .‬ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ‪ ch‬ﮐﻪ ﺑﺎﻋﺚ ﺗﻔﮑﻴﮏ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺭﻭﺩﻱ ﻣﻲﺷﻮﺩ‪» ،‬ﮐﺎﺭﺍﮐﺘﺮ ﻣﺮﺯﺑﻨﺪﻱ«‬
‫ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﻭﻗﺘﻲ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﻪ ﻋﻨﻮﺍﻥ ﮐﺎﺭﺍﮐﺘﺮ ﻣﺮﺯﺑﻨﺪﻱ ﺩﺭ ﻧﻈﺮ ﮔﺮﻓﺘﻪ ﺷﻮﺩ‪ ،‬ﻧﻴﺎﺯﻱ‬
‫‪257‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫ﻧﻴﺴﺖ ﮐﻪ ﺩﺭ ﺗﺎﺑﻊ )(‪ getline‬ﻗﻴﺪ ﺷﻮﺩ ﻭ ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﻓﻘﻂ ﺑﺎ ﺩﻭ‬
‫ﭘﺎﺭﺍﻣﺘﺮ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺩﺭ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﮐﺎﺭﺍﮐﺘﺮ ﮐﺎﻣﺎ '‪ ',‬ﺑﻪ ﻋﻨﻮﺍﻥ ﮐﺎﺭﺍﮐﺘﺮ ﻣﺮﺯﺑﻨﺪﻱ ﻓﺮﺽ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐4‬ﺗﺎﺑﻊ )(‪ cin.getline‬ﺑﺎ ﺳﻪ ﭘﺎﺭﺍﻣﺘﺮ‬


‫ﺑﺮﻧﺎﻣﻪ ﺯﻳﺮ‪ ،‬ﻣﺘﻦ ﻭﺭﻭﺩﻱ ﺭﺍ ﺟﻤﻠﻪ ﺑﻪ ﺟﻤﻠﻪ ﺗﻔﮑﻴﮏ ﻣﻲﻧﻤﺎﻳﺪ‪:‬‬
‫)(‪int main‬‬
‫;]‪{ char clause[20‬‬
‫‪do‬‬
‫;)'‪{ cin.getline(clause, 20, ',‬‬
‫;"‪if (*clause) cout << "\t[" << clause << "]\n‬‬
‫;)‪} while (*clause‬‬
‫}‬
‫‪Once upon a midnight dreary, while I pondered, weak and weary,‬‬
‫‪Over many a quaint and curious volume of forgotten lore,‬‬
‫]‪^z [Once upon a midnight dreary‬‬
‫]‪[ while I pondered‬‬
‫]‪[ weak and weary‬‬
‫[‬
‫]‪Over many a quaint and curious volume of forgotten lore‬‬
‫[‬
‫]‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﭼﻮﻥ ﮐﺎﺭﺍﮐﺘﺮ ﮐﺎﻣﺎ '‪ ',‬ﺑﻪ ﻋﻨﻮﺍﻥ ﮐﺎﺭﺍﮐﺘﺮ ﻣﺮﺯﺑﻨﺪﻱ ﻣﻨﻈﻮﺭ ﺷﺪﻩ‪ ،‬ﻫﺮ ﮐﺎﺭﺍﮐﺘﺮ‬
‫ﺩﻳﮕﺮﻱ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻣﻌﻤﻮﻟﻲ ﻓﺮﺽ ﻣﻲﺷﻮﺩ‪ .‬ﻣﺜﻼ ﺑﻌﺪ ﺍﺯ ﻋﺒﺎﺭﺕ "‪"weary,‬‬
‫ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﻪ ﺻﻮﺭﺕ ﻣﺨﻔﻲ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﺍﻣﺎ ﭼﻮﻥ ﻓﻘﻂ ﮐﺎﺭﺍﮐﺘﺮ ﮐﺎﻣﺎ ﺑﺮﺍﻱ‬
‫ﻣﺮﺯﺑﻨﺪﻱ ﻣﻨﻈﻮﺭ ﺷﺪﻩ‪ ،‬ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻣﻌﻤﻮﻟﻲ ﺩﺭ ﻭﺭﻭﺩﻱ ﺑﻌﺪﻱ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﻭ ﭘﺮﺩﺍﺯﺵ ﻣﻲﺷﻮﺩ‪ .‬ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﻫﺮ ﺩﻓﻌﻪ ﮐﻪ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﻣﺮﺯﺑﻨﺪﻱ ﺑﺮﺧﻮﺭﺩ‬
‫ﺷﻮﺩ‪ ،‬ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ ﺣﺬﻑ ﻣﻲﺷﻮﺩ ﻭ ﻭﺭﻭﺩﻱ ﺑﻌﺪﻱ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻌﺪ ﺍﺯ ﺁﻥ ﺷﺮﻭﻉ ﻣﻲﮐﻨﺪ‪.‬‬
‫ﺗﺎﺑﻊ )(‪ cin.get‬ﺑﺮﺍﻱ ﺧﻮﺍﻧﺪﻥ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺯ ﻭﺭﻭﺩﻱ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‪.‬‬
‫ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ cin.get(ch‬ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻌﺪﻱ ﺍﺯ ﻭﺭﻭﺩﻱ ‪ cin‬ﺧﻮﺍﻧﺪﻩ‬
‫ﺷﺪﻩ ﻭ ﺑﻪ ﺩﺍﺧﻞ ﻣﺘﻐﻴﺮ ‪ ch‬ﮐﭙﻲ ﺷﻮﺩ‪ .‬ﺍﮔﺮ ﺍﻳﻦ ﮐﺎﺭ ﻣﻮﻓﻘﻴﺖ ﺁﻣﻴﺰ ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ ‪ 1‬ﺑﺎﺯﮔﺸﺖ‬
‫ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺍﮔﺮ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ‪ ،‬ﻣﻘﺪﺍﺭ ‪ 0‬ﺑﺎﺯﮔﺮﺩﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 258

cin.get() ‫ ﺗﺎﺑﻊ‬8‐5 ‫* ﻣﺜﺎﻝ‬


‫ ﺗﺎ ﻭﻗﺘﻲ‬.‫' ﺩﺭ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺭﺍ ﺷﻤﺎﺭﺵ ﻣﻲﻛﻨﺪ‬e' ‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﺗﻌﺪﺍﺩ ﺣﺮﻑ‬
:‫ ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‬،‫ ﻣﻲﺧﻮﺍﻧﺪ‬ch ‫ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﺑﺎ ﻣﻮﻓﻘﻴﺖ ﺑﻪ ﺩﺭﻭﻥ‬cin.get(ch)
int main()
{ char ch;
int count = 0;
while (cin.get(ch))
if (ch = = 'e') ++count;
cout << count << " e's were counted.\n";
}
Once upon a midnight dreary, while I pondered, weak and weary,
Over many a quaint and curious volume of forgotten lore,
^z
11 e's were counted.

cout.put() ‫ ﺗﺎﺑﻊ‬.‫ ﺍﺳﺖ‬put() ‫ ﺗﺎﺑﻊ ﺧﺮﻭﺟﻲ‬get() ‫ﻣﻌﮑﻮﺱ ﺗﺎﺑﻊ ﻭﺭﻭﺩﻱ‬


.‫ ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‬.‫ﺑﺮﺍﻱ ﻧﻮﺷﺘﻦ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺩﺭ ﺧﺮﻭﺟﻲ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‬

cout.put() ‫ ﺗﺎﺑﻊ‬8‐6 ‫* ﻣﺜﺎﻝ‬


‫ ﺍﻭﻟﻴﻦ ﺣﺮﻑ ﺍﺯ ﻫﺮ ﮐﻠﻢۀ ﻭﺭﻭﺩﻱ ﺭﺍ ﺑﻪ ﺣﺮﻑ ﺑﺰﺭﮒ ﺗﺒﺪﻳﻞ ﮐﺮﺩﻩ ﻭ ﺁﻥ‬،‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‬
:‫ﺭﺍ ﻣﺠﺪﺩﺍ ﺩﺭ ﺧﺮﻭﺟﻲ ﭼﺎﭖ ﻣﻲﮐﻨﺪ‬
int main()
{ char ch, pre = '\0';
while (cin.get(ch))
{ if (pre = = ' ' || pre = = '\n')
cout.put(char(toupper(ch)));
else cout.put(ch);
pre = ch;
}
}
Fourscore and seven years ago our fathers
Fourscore And Seven Years Ago Our Fathers
brought forth upon this continent a new nation,
Brought Forth Upon This Continent A New Nation,
^z
‫‪259‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫ﻣﺘﻐﻴﺮ ‪ pre‬ﻛﺎﺭﺍﻛﺘﺮ ﺧﻮﺍﻧﺪﻩ ﺷﺪۀ ﻗﺒﻠﻲ ﺭﺍ ﻧﮕﻪ ﻣﻲﺩﺍﺭﺩ‪ .‬ﻣﻨﻄﻖ ﺑﺮﻧﺎﻣﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﺍﺳﺖ ﮐﻪ‬
‫ﺍﮔﺮ ‪ pre‬ﻳﻚ ﮐﺎﺭﺍﮐﺘﺮ ﺧﺎﻟﻲ ﻳﺎ ﻛﺎﺭﺍﻛﺘﺮ ﺧﻂ ﺟﺪﻳﺪ ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﮐﺎﺭﺍﮐﺘﺮﻱ ﮐﻪ ﺩﺭ ‪ch‬‬
‫ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ ﺍﻭﻟﻴﻦ ﺣﺮﻑ ﺍﺯ ﮐﻠﻢۀ ﺑﻌﺪﻱ ﺍﺳﺖ‪ .‬ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﮐﺎﺭﺍﮐﺘﺮ ﺩﺭﻭﻥ ‪ ch‬ﺑﺎ‬
‫ﺣﺮﻑ ﺑﺰﺭﮒ ﺟﺎﻳﮕﺰﻳﻦ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺗﺎﺑﻊ )‪ toupeer(ch‬ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﮔﺮ ‪ ch‬ﺣﺮﻑ ﮐﻮﭼﮏ ﺑﺎﺷﺪ‪ ،‬ﺁﻥ ﺭﺍ ﺑﻪ‬
‫ﺣﺮﻑ ﺑﺰﺭﮒ ﻣﻌﺎﺩﻟﺶ ﺗﺒﺪﻳﻞ ﮐﻨﺪ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪ <ctype.h‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ‪.‬‬
‫ﺍﻟﺒﺘﻪ ﺑﻪ ﺟﺎﻱ ﺍﻳﻦ ﺗﺎﺑﻊ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻋﺒﺎﺭﺕ ﺯﻳﺮ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ‪:‬‬
‫;'‪ch += 'A' – 'a‬‬

‫ﺗﺎﺑﻊ )(‪ cin.putback‬ﺁﺧﺮﻳﻦ ﮐﺎﺭﺍﮐﺘﺮ ﺧﻮﺍﻧﺪﻩ ﺷﺪﻩ ﺗﻮﺳﻂ )(‪ cin.get‬ﺭﺍ‬


‫ﺑﻪ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺑﺎﺯ ﭘﺲ ﻣﻲﻓﺮﺳﺘﺪ ﻭ ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺩﺳﺘﻮﺭ ‪ cin‬ﺑﻌﺪﻱ ﻣﻲﺗﻮﺍﻧﺪ ﺩﻭﺑﺎﺭﻩ‬
‫ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﺑﺨﻮﺍﻧﺪ‪.‬‬
‫ﺗﺎﺑﻊ )(‪ cin.ignore‬ﻳﮏ ﻳﺎ ﭼﻨﺪ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﺑﺪﻭﻥ ﺁﻥ ﮐﻪ ﺁﻥﻫﺎ ﺭﺍ ﭘﺮﺩﺍﺯﺵ‬
‫ﮐﻨﺪ‪ ،‬ﻧﺎﺩﻳﺪﻩ ﮔﺮﻓﺘﻪ ﻭ ﺍﺯ ﺭﻭﻱ ﺁﻥ ﻫﺎ ﭘﺮﺵ ﻣﻲﮐﻨﺪ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐7‬ﺗﻮﺍﺑﻊ )(‪ cin.ignore‬ﻭ )(‪cin.putback‬‬


‫ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﺗﺎﺑﻌﻲ ﺁﺯﻣﺎﻳﺶ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ ﺭﺍ ﺍﺯ‬
‫ﻭﺭﻭﺩﻱ ﺍﺳﺘﺨﺮﺍﺝ ﻣﻲﮐﻨﺪ‪:‬‬
‫;)(‪int nextInt‬‬
‫)(‪int main‬‬
‫;)(‪{ int m = nextInt(), n = nextInt‬‬
‫;)'‪cin.ignore(80,'\n‬‬ ‫‪// ignore rest of input line‬‬
‫;‪cout << m << " + " << n << " = " << m+n << endl‬‬
‫}‬
‫)(‪int nextInt‬‬
‫;‪{ char ch‬‬
‫;‪int n‬‬
‫))‪while (cin.get(ch‬‬
‫‪if (ch >= '0' && ch <= '9') // next character is a digit‬‬
‫;)‪{ cin.putback(ch‬‬ ‫‪// put it back so it can be‬‬
‫;‪cin >> n‬‬ ‫‪// read as a complite int‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪260‬‬

‫;‪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‬‬ ‫ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﻋﺒﺎﺭﺕ‬
‫ﻣﻲﺧﻮﺍﻧﺪ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﺍﺯ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺣﺬﻑ ﻧﻤﺎﻳﺪ‪ .‬ﻣﺜﺎﻝ ﺯﻳﺮ‪ ،‬ﻃﺮﻳﻖۀ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐8‬ﺗﺎﺑﻊ )(‪cin.peek‬‬


‫ﺍﻳﻦ ﻧﺴﺨﻪ ﺍﺯ ﺗﺎﺑﻊ )(‪ nextInt‬ﻣﻌﺎﺩﻝ ﺁﻥ ﺍﺳﺖ ﻛﻪ ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻠﻲ ﺑﻮﺩ‪:‬‬
‫)(‪int nextInt‬‬
‫;‪{ char ch‬‬
‫;‪int n‬‬
‫))(‪while (ch = cin.peek‬‬
‫)'‪if (ch >= '0' && ch <= '9‬‬
‫;‪{ cin >> n‬‬
‫;‪break‬‬
‫}‬
‫;)‪else cin.get(ch‬‬
‫;‪return n‬‬
‫}‬
‫‪261‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫ﻋﺒﺎﺭﺕ )(‪ ch = cin.peek‬ﻛﺎﺭﺍﻛﺘﺮ ﺑﻌﺪﻱ ﺭﺍ ﺩﺭﻭﻥ ‪ ch‬ﻣﻲﺧﻮﺍﻧﺪ ﻭ ﺩﺭ‬


‫ﺻﻮﺭﺕ ﻣﻮﻓﻘﻴﺖ‪ ،‬ﻣﻘﺪﺍﺭ ‪ 1‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺩﺭ ﺧﻂ ﺑﻌﺪﻱ‪ ،‬ﺍﮔﺮ ‪ ch‬ﻳﮏ ﻋﺪﺩ ﺑﺎﺷﺪ‪ ،‬ﻋﺪﺩ‬
‫ﺻﺤﻴﺢ ﺑﻪ ﻃﻮﺭ ﮐﺎﻣﻞ ﺩﺭﻭﻥ ‪ n‬ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ ﻭﮔﺮﻧﻪ ﺁﻥ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺯ ‪ cin‬ﺣﺬﻑ ﻣﻲﺷﻮﺩ‬
‫ﻭ ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺍﮔﺮ ﺩﺭ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺭﻭﺩﻱ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ‪،‬‬
‫ﻋﺒﺎﺭﺕ ;)(‪ ch = cin.peek‬ﻣﻘﺪﺍﺭ ‪ 0‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭ ﺣﻠﻘﻪ ﻣﺘﻮﻗﻒ ﻣﻲﺷﻮﺩ‪.‬‬

‫‪ 8‐6‬ﺗﻮﺍﺑﻊ ﻛﺎﺭﺍﻛﺘﺮﻱ ‪ C‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬


‫ﺩﺭ ﻣﺜﺎﻝ ‪ 8‐6‬ﺑﻪ ﺗﺎﺑﻊ)(‪ toupper‬ﺍﺷﺎﺭﻩ ﺷﺪ‪ .‬ﺍﻳﻦ ﻓﻘﻂ ﻳﮑﻲ ﺍﺯ ﺗﻮﺍﺑﻌﻲ ﺍﺳﺖ ﮐﻪ‬
‫ﺑﺮﺍﻱ ﺩﺳﺖﮐﺎﺭﻱ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺳﺎﻳﺮ ﺗﻮﺍﺑﻌﻲ ﮐﻪ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪<ctype.h‬‬
‫ﻳﺎ >‪ <cctype‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺑﻪ ﺷﺮﺡ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬

‫ﻧﺎﻡ ﺗﺎﺑﻊ‬ ‫ﺷﺮﺡ‬

‫;)‪int isalnum(int c‬‬


‫)(‪isalnum‬‬
‫ﺍﮔﺮ ‪ c‬ﮐﺎﺭﺍﮐﺘﺮ ﺍﻟﻔﺒﺎﻳﻲ ﻳﺎ ﻋﺪﺩﻱ ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﻭﮔﺮﻧﻪ ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫;)‪int isalpha(int c‬‬


‫)(‪isalpha‬‬
‫ﺍﮔﺮ ‪ c‬ﮐﺎﺭﺍﮐﺘﺮ ﺍﻟﻔﺒﺎﻳﻲ ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﻭ ﺩﺭ ﻏﻴﺮ ﺁﻥ‪ ،‬ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫;)‪int iscntrl(int c‬‬


‫)(‪iscntrl‬‬
‫ﺍﮔﺮ ‪ c‬ﮐﺎﺭﺍﮐﺘﺮ ﮐﻨﺘﺮﻟﻲ ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﻭ ﺩﺭ ﻏﻴﺮ ﺁﻥ‪ ،‬ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫;)‪int isdigit(int c‬‬


‫)(‪isdigit‬‬
‫ﺍﮔﺮ ‪ c‬ﮐﺎﺭﺍﮐﺘﺮ ﻋﺪﺩﻱ ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﻭ ﺩﺭ ﻏﻴﺮ ﺁﻥ‪ ،‬ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫;)‪int isgraph(int c‬‬


‫)(‪isgraph‬‬
‫ﺍﮔﺮ ‪ c‬ﮐﺎﺭﺍﮐﺘﺮ ﭼﺎﭘﻲ ﻭ ﻏﻴﺮﺧﺎﻟﻲ ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﻭﮔﺮﻧﻪ ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫;)‪int islower(int c‬‬


‫)(‪islower‬‬
‫ﺍﮔﺮ ‪ c‬ﺣﺮﻑ ﮐﻮﭼﮏ ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﻭ ﺩﺭ ﻏﻴﺮ ﺁﻥ‪ ،‬ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫;)‪int isprint(int c‬‬


‫)(‪isprint‬‬
‫ﺍﮔﺮ ‪ c‬ﮐﺎﺭﺍﮐﺘﺮ ﻗﺎﺑﻞ ﭼﺎﭖ ﺑﺎﺷﺪ ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﻭ ﺩﺭ ﻏﻴﺮ ﺁﻥ‪ ،‬ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫;)‪int ispunct(int c‬‬


‫)(‪ispunct‬‬ ‫ﺍﮔﺮ ‪ c‬ﮐﺎﺭﺍﮐﺘﺮ ﭼﺎﭘﻲ ﺑﻪ ﻏﻴﺮ ﺍﺯ ﺣﺮﻭﻑ ﻭ ﺍﻋﺪﺍﺩ ﻭ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ‬
‫ﻏﻴﺮﺻﻔﺮ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭﮔﺮﻧﻪ ﻣﻘﺪﺍﺭ ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪262‬‬

‫;)‪int isspace(int c‬‬


‫ﺍﮔﺮ ‪ c‬ﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺷﺎﻣﻞ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ' ' ﻭ ﻋﺒﻮﺭ ﻓﺮﻡ '‪ '\f‬ﻭ‬
‫)(‪isspace‬‬
‫ﺧﻂ ﺟﺪﻳﺪ '‪ '\n‬ﻭ ﺑﺎﺯﮔﺸﺖ ﻧﻮﺭﺩ '‪ '\r‬ﻭ ﭘﺮﺵ ﺍﻓﻘﻲ '‪ '\t‬ﻭ ﭘﺮﺵ‬
‫ﻋﻤﻮﺩﻱ '‪ '\v‬ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭﮔﺮﻧﻪ ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫;)‪int isupper(int c‬‬


‫)(‪isupper‬‬
‫ﺍﮔﺮ ‪ c‬ﺣﺮﻑ ﺑﺰﺭﮒ ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭﮔﺮﻧﻪ ﺻﻔﺮ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬
‫;)‪int isxdigit(int c‬‬
‫ﺍﮔﺮ ‪ c‬ﻳﮑﻲ ﺍﺯ ﺩﻩ ﮐﺎﺭﺍﮐﺘﺮ ﻋﺪﺩﻱ ﻳﺎ ﻳﮑﻲ ﺍﺯ ﺩﻭﺍﺯﺩﻩ ﺣﺮﻑ ﻋﺪﺩ ﺷﺎﻧﺰﺩﻩﺩﻫﻲ ﺷﺎﻣﻞ‬
‫'‪ 'a‬ﻭ '‪ 'b‬ﻭ '‪ 'c‬ﻭ '‪ 'd‬ﻭ '‪ 'e‬ﻭ '‪ 'f‬ﻭ '‪ 'A‬ﻭ '‪ 'B‬ﻭ '‪isxdigit() 'C‬‬
‫ﻭ '‪ 'D‬ﻭ '‪ 'E‬ﻭ '‪ 'F‬ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ ﻏﻴﺮﺻﻔﺮ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭﮔﺮﻧﻪ ﻣﻘﺪﺍﺭ ﺻﻔﺮ‬
‫ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬
‫;)‪int tolower(int c‬‬
‫)(‪tolower‬‬ ‫ﺍﮔﺮ ‪ c‬ﺣﺮﻑ ﺑﺰﺭﮒ ﺑﺎﺷﺪ‪ ،‬ﮐﺎﺭﺍﮐﺘﺮ ﮐﻮﭼﮏ ﻣﻌﺎﺩﻝ ﺁﻥ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭﮔﺮﻧﻪ ﺧﻮﺩ‬
‫‪ c‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫;)‪int toupper(int c‬‬


‫)(‪toupper‬‬ ‫ﺍﮔﺮ ‪ c‬ﺣﺮﻑ ﮐﻮﭼﮏ ﺑﺎﺷﺪ‪ ،‬ﮐﺎﺭﺍﮐﺘﺮ ﺑﺰﺭﮒ ﻣﻌﺎﺩﻝ ﺁﻥ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭﮔﺮﻧﻪ ﺧﻮﺩ‬
‫‪ c‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‬

‫ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﻫﻢۀ ﺗﻮﺍﺑﻊ ﻓﻮﻕ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ ‪ 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‬ﮔﺮﭼﻪ ﺑﻪ ﺻﻮﺭﺕ ﻳﮏ ﺁﺭﺍﻱۀ ﺩﻭﺑﻌﺪﻱ ﺍﻋﻼﻥ ﺷﺪﻩ ﻟﻴﮑﻦ ﺑﻪ ﺻﻮﺭﺕ ﻳﮏ‬
‫ﺁﺭﺍﻱۀ ﻳﮏ ﺑﻌﺪﻱ ﺑﺎ ﺁﻥ ﺭﻓﺘﺎﺭ ﻣﻲﺷﻮﺩ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺩﻗﺖ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐9‬ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﭼﻨﺪ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ ﻣﻲﺧﻮﺍﻧﺪ ﻭ ﺁﻥﻫﺎ ﺭﺍ ﺩﺭ ﻳﮏ ﺁﺭﺍﻳﻪ‬
‫ﺫﺧﻴﺮﻩ ﮐﺮﺩﻩ ﻭ ﺳﭙﺲ ﻣﻘﺎﺩﻳﺮ ﺁﻥ ﺁﺭﺍﻳﻪ ﺭﺍ ﭼﺎﭖ ﻣﻲﮐﻨﺪ‪:‬‬
‫)(‪int main‬‬
‫;]‪{ char name[5][20‬‬
‫;‪int count=0‬‬
‫;"‪cout << "Enter at most 4 names with at most 19 characters:\n‬‬
‫))‪while (cin.getline(name[count++], 20‬‬
‫;‬
‫;‪--count‬‬
‫;"‪cout << "The names are:\n‬‬
‫)‪for (int i=0; i<count; i++‬‬
‫;‪cout << "\t" << i << ". [" << name[i] << "]" << endl‬‬
‫}‬
‫‪Enter at most 4 names with at most 19 characters:‬‬
‫‪Mostafa Chamran‬‬
‫‪Ahmad Motevasselian‬‬
‫‪Ebrahim Hemmat‬‬
‫‪^z‬‬
‫‪The names are:‬‬
‫]‪0: [Mostafa Chamran‬‬
‫]‪1: [Ahmad Motevasselian‬‬
‫]‪2: [Ebrahim Hemmat‬‬
‫‪0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19‬‬ ‫ﺁﺭﺍﻱۀ ‪ name‬ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺷﮑﻞ ﻣﻘﺎﺑﻞ ﺗﺼﻮﺭ‬
‫‪0‬‬ ‫‪Mostafa ChamranØ‬‬
‫‪1‬‬ ‫‪Ahmad MotevasselianØ‬‬ ‫ﻧﻤﻮﺩ‪ .‬ﺗﻤﺎﻡ ﻓﻌﺎﻟﻴﺖﻫﺎﻱ ﺣﻠﻖۀ ‪ while‬ﺩﺭ‬
‫‪2‬‬ ‫‪Ebrahim HemmatØ‬‬
‫‪3‬‬
‫ﻗﺴﻤﺖ ﮐﻨﺘﺮﻟﻲ ﺁﻥ ﺍﻧﺠﺎﻡ ﻣﻲﺷﻮﺩ‪:‬‬
‫‪4‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪264‬‬

‫)‪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‬ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ‪ .‬ﺭﻭﺵ ﻣﺬﮐﻮﺭ ﺑﺴﻴﺎﺭ ﻣﻮﺛﺮﺗﺮ ﺍﺳﺖ ﺯﻳﺮﺍ ﺑﺮﺍﻱ‬
‫ﻧﮕﻬﺪﺍﺭﻱ ﻫﺮ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻓﻘﻂ ﺑﻪ ﺍﻧﺪﺍﺯۀ ﻫﻤﺎﻥ ﺭﺷﺘﻪ ﺣﺎﻓﻈﻪ ﺗﺨﺼﻴﺺ ﻣﻲﻳﺎﺑﺪ ﻧﻪ‬
‫ﺑﻴﺸﺘﺮ‪ .‬ﻫﺰﻳﻨﻪﺍﻱ ﮐﻪ ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﺎﺭﺍﻳﻲ ﺑﺎﻳﺪ ﺑﭙﺮﺩﺍﺯﻳﻢ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺭﻭﺍﻝ ﻭﺭﻭﺩﻱ ﮐﻤﻲ‬
‫ﭘﻴﭽﻴﺪﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺩﺭ ﺍﻳﻦ ﺭﻭﺵ ﺑﻪ ﻳﮏ ﻧﮕﻬﺒﺎﻥ ﻧﻴﺎﺯ ﺩﺍﺭﻳﻢ ﺗﺎ ﻭﻗﺘﻲ ﻭﺭﻭﺩﻱ ﻫﺮ ﺭﺷﺘﻪ ﭘﺎﻳﺎﻥ‬
‫ﻳﺎﻓﺖ‪ ،‬ﺑﻪ ﺁﺭﺍﻳﻪ ﻋﻼﻣﺖ ﺑﺪﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐10‬ﻳﻚ ﺁﺭﺍﻱۀ ﺭﺷﺘﻪﺍﻱ ﭘﻮﻳﺎ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﭼﮕﻮﻧﻪ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮ '‪ '$‬ﺑﻪ ﻋﻨﻮﺍﻥ ﮐﺎﺭﺍﮐﺘﺮ‬
‫ﻧﮕﻬﺒﺎﻥ ﺩﺭ ﺗﺎﺑﻊ )(‪ getline‬ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪ .‬ﻣﺜﺎﻝ ﺯﻳﺮ ﺗﻘﺮﻳﺒﺎ ﻣﻌﺎﺩﻝ ﻣﺜﺎﻝ ‪ 8‐9‬ﺍﺳﺖ‪.‬‬
‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﺍﺳﺎﻣﻲ ﺭﺍ ﻣﻲﺧﻮﺍﻧﺪ‪ ،‬ﻃﻮﺭﻱ ﮐﻪ ﻫﺮ ﺍﺳﻢ ﺭﻭﻱ ﻳﮏ ﺧﻂ ﻧﻮﺷﺘﻪ‬
‫‪265‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫ﻣﻲﺷﻮﺩ ﻭ ﻫﺮ ﺍﺳﻢ ﺑﺎ ﮐﺎﺭﺍﮐﺘﺮ '‪ '\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‬‬

‫ﺩﺭﻭﻥ ‪ buffer‬ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺁﺭﺍﻱۀ ﺭﺷﺘﻪﺍﻱ ‪ name‬ﭼﮕﻮﻧﻪ ﻣﻘﺪﺍﺭﺩﻫﻲ‬


‫ﺧﻮﺍﻫﺪ ﺷﺪ‪ .‬ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺑﺎﻳﺖﻫﺎﻱ ﺍﺿﺎﻓﻲ ﮐﻪ ﺩﺭ ﻣﺜﺎﻝ ‪ 8‐9‬ﻭﺟﻮﺩ ﺩﺍﺷﺘﻨﺪ ‪ ،‬ﺍﻳﻦ ﺟﺎ‬
‫ﻭﺟﻮﺩ ﻧﺪﺍﺭﻧﺪ‪.‬‬
‫ﻣﻤﮑﻦ ﺍﺳﺖ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻣﻮﺭﺩ ﺍﺳﺘﻔﺎﺩﻩ‪ ،‬ﺩﺭ ﺯﻣﺎﻥ ﮐﺎﻣﭙﺎﻳﻞ ﻣﺸﺨﺺ ﺑﺎﺷﻨﺪ‪.‬‬
‫ﺩﺭ ﺍﻳﻦ ﻣﻮﺍﺭﺩ ﺑﻪ ﮐﺎﺭﮔﻴﺮﻱ ﻭ ﻣﺪﻳﺮﻳﺖ ﻳﮏ ﺁﺭﺍﻱۀ ﺍﻳﺴﺘﺎ ﺁﺳﺎﻥﺗﺮ ﺍﺳﺖ)ﻣﺜﻞ ﻣﺜﺎﻝ ‪.(8‐9‬‬
‫ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﻪ ﻳﮏ ﺁﺭﺍﻱۀ ﺭﺷﺘﻪﺍﻱ ﺍﻳﺴﺘﺎ ﭼﻘﺪﺭ ﺁﺳﺎﻥﺗﺮ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐11‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﻳﻚ ﺁﺭﺍﻱۀ ﺭﺷﺘﻪﺍﻱ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ ﻫﻢ ﺁﺭﺍﻱۀ ﺭﺷﺘﻪﺍﻱ ‪ name‬ﺭﺍ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩﻩ ﻭ ﺳﭙﺲ ﻣﻘﺎﺩﻳﺮ ﺁﻥ ﺭﺍ‬
‫ﭼﺎﭖ ﻣﻲﻧﻤﺎﻳﺪ‪:‬‬
‫)(‪int main‬‬
‫][‪{ char* name‬‬
‫;} "‪= { "Mostafa Chamran", "Mehdi Zeinoddin", "Ebrahim Hemmat‬‬
‫;"‪cout << "The names are:\n‬‬
‫)‪for (int i = 0; i < 3; i++‬‬
‫"]" << ]‪cout << "\t" << i << ". [" << name[i‬‬
‫;‪<< endl‬‬
‫}‬

‫‪The names are:‬‬


‫]‪0. [Mostafa Chamran‬‬
‫]‪1. [Mehdi Zeinoddin‬‬
‫]‪2. [Ebrahim Hemmat‬‬

‫‪ 8‐8‬ﺗﻮﺍﺑﻊ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ‬


‫ﺳﺮﻓﺎﻳﻞ >‪ <cstring‬ﮐﻪ ﺑﻪ ﺁﻥ »ﮐﺘﺎﺑﺨﺎﻥۀ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ« ﻫﻢ ﻣﻲﮔﻮﻳﻨﺪ‪،‬‬
‫ﺷﺎﻣﻞ ﺧﺎﻧﻮﺍﺩۀ ﺗﻮﺍﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ﺑﺮﺍﻱ ﺩﺳﺖﮐﺎﺭﻱ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺧﻴﻠﻲ ﻣﻔﻴﺪﻧﺪ‪ .‬ﻣﺜﺎﻝ‬
‫‪267‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫ﺑﻌﺪﻱ ﺳﺎﺩﻩﺗﺮﻳﻦ ﺁﻥﻫﺎ ﻳﻌﻨﻲ ﺗﺎﺑﻊ ﻃﻮﻝ ﺭﺷﺘﻪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ‪ ،‬ﻃﻮﻝ ﻳﮏ ﺭﺷﺖۀ‬
‫ﮐﺎﺭﺍﮐﺘﺮﻱ ﺍﺭﺳﺎﻝ ﺷﺪﻩ ﺑﻪ ﺁﻥ )ﻳﻌﻨﻲ ﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺁﻥ ﺭﺷﺘﻪ( ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐12‬ﺗﺎﺑﻊ )(‪strlen‬‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻳﮏ ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ ﺳﺎﺩﻩ ﺑﺮﺍﻱ ﺗﺎﺑﻊ )(‪ strlen‬ﺍﺳﺖ‪ .‬ﻭﻗﺘﻲ‬
‫)‪ strlen(s‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ‪ ،‬ﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺩﺭﻭﻥ ﺭﺷﺖۀ ‪ s‬ﮐﻪ ﻗﺒﻞ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮ‬
‫‪ NUL‬ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪﺍﻧﺪ‪ ،‬ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪:‬‬
‫>‪#include <cstring‬‬
‫)(‪int main‬‬
‫;"‪{ char s[] = "ABCDEFG‬‬
‫;‪cout << "strlen(" << s << ") = " << strlen(s) << endl‬‬
‫;‪cout << "strlen(\"\") = " << strlen("") << endl‬‬
‫;]‪char buffer[80‬‬
‫;" ‪cout << "Enter string:‬‬ ‫;‪cin >> buffer‬‬
‫)‪cout << "strlen(" << buffer << ") = " << strlen(buffer‬‬
‫;‪<< endl‬‬
‫}‬

‫ﺩﺭ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺳﻪ ﺗﺎﺑﻊ ﺩﻳﮕﺮ ﺭﺍ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﻴﻢ‪ .‬ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺑﺮﺍﻱ »ﻣﮑﺎﻥﻳﺎﺑﻲ« ﻳﮏ‬
‫ﮐﺎﺭﺍﮐﺘﺮ ﻳﺎ ﺯﻳﺮﺭﺷﺘﻪ ﺩﺭ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻣﻔﺮﻭﺽ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐13‬ﺗﻮﺍﺑﻊ )(‪strrchr(), strchr(), strstr‬‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﻣﮑﺎﻥﻳﺎﺑﻲ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻳﺎ ﺯﻳﺮﺭﺷﺖۀ ﺧﺎﺹ ﺭﺍ ﺩﺭ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪s‬‬
‫ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪:‬‬
‫>‪#include <cstring‬‬
‫)(‪int main‬‬
‫;"‪{ char s[] = "The Mississippi is a long river.‬‬
‫;"‪cout << "s = \"" << s << "\"\n‬‬
‫;)' ' ‪char* p = strchr(s,‬‬
‫;"‪cout << "strchr(s, ' ') points to s[" << p - s << "].\n‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪268‬‬

‫;)'‪p = strchr(s, 'e‬‬


‫;"‪cout << "strchr(s, 'e') points to s[" << p - s << "].\n‬‬
‫;)'‪p = strrchr(s, 'e‬‬
‫;"‪cout << "strrchr(s, 'e') points to s[" << p - s << "].\n‬‬
‫;)"‪p = strstr(s, "is‬‬
‫‪cout << "strstr(s, \"is\") points to s[" << p – s‬‬
‫;"‪<< "].\n‬‬
‫;)"‪p = strstr(s, "isi‬‬
‫‪cout << "strstr(s, \"is\") points to s[" << p – s‬‬
‫;"‪<< "].\n‬‬
‫‪if (p == NULL) cout << "strstr(s, \"isi\") returns‬‬
‫;"‪NULL\n‬‬
‫}‬
‫"‪s = "The SOFTWARE MOVEMENT is began.‬‬
‫‪strchr(s, ' ') points to s[3].‬‬
‫‪strchr(s, 'e') points to s[2].‬‬
‫‪strrchr(s, 'e') points to s[26].‬‬
‫‪strstr(s, "is") points to s[22].‬‬
‫‪strstr(s, "isi") returns NULL‬‬

‫ﻭﻗﺘﻲ )' '‪ 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‬ﺭﺍ ﺑﺪﻭﻥ ﺗﻐﻴﻴﺮ ﻣﻲﮔﺬﺍﺭﻧﺪ‪ .‬ﻣﺜﺎﻝﻫﺎﻱ ﺑﻌﺪﻱ ﻃﺮﻳﻖۀ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺩﻭ ﺗﺎﺑﻊ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐14‬ﺗﺎﺑﻊ )(‪strcpy‬‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ strcpy(s1, s2‬ﭼﻪ ﺗﺎﺛﻴﺮﻱ ﺩﺍﺭﺩ‪:‬‬
‫>‪#include <iostream‬‬
‫>‪#include <cstring‬‬
‫)(‪int main‬‬
‫;"‪{ char s1[] = "ABCDEFG‬‬
‫;"‪char s2[] = "XYZ‬‬
‫;"‪cout << "Before strcpy(s1,s2):\n‬‬
‫‪cout << "\ts1 = [" << s1 << "], length‬‬ ‫)‪= " << strlen(s1‬‬
‫;‪<< endl‬‬
‫‪cout << "\ts2 = [" << s2 << "], length‬‬ ‫)‪= " << strlen(s2‬‬
‫;‪<< endl‬‬
‫;)‪strcpy(s1,s2‬‬
‫;"‪cout << "After strcpy(s1,s2):\n‬‬
‫‪cout << "\ts1 = [" << s1 << "], length‬‬ ‫)‪= " << strlen(s1‬‬
‫;‪<< endl‬‬
‫‪cout << "\ts2 = [" << s2 << "], length‬‬ ‫)‪= " << strlen(s2‬‬
‫;‪<< endl‬‬
‫}‬
‫‪Before strcpy(s1,s2):‬‬
‫‪s1 = [ABCDEFG], length = 7‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪270‬‬

‫‪s2 = [XYZ], length = 3‬‬


‫‪After strcpy(s1,s2):‬‬
‫‪s1 = [XYZ], length = 3‬‬
‫‪s2 = [XYZ], length = 3‬‬

‫ﻭﻗﺘﻲ ‪ s2‬ﺑﻪ ﺩﺍﺧﻞ ‪ s1‬ﮐﭙﻲ ﺷﺪ‪ ،‬ﺍﻳﻦ ﺩﻭ ﺩﻳﮕﺮ ﻓﺮﻗﻲ ﺑﺎ ﻫﻢ ﻧﻤﻲﮐﻨﻨﺪ‪ .‬ﻫﺮ ﺩﻭ ﺷﺎﻣﻞ ﺳﻪ‬
‫ﮐﺎﺭﺍﮐﺘﺮ ‪ XYZ‬ﻫﺴﺘﻨﺪ‪ .‬ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ strcpy(s1, s2‬ﭼﻪ‬
‫ﺗﺎﺛﻴﺮﻱ ﺩﺍﺭﺩ‪ .‬ﭼﻮﻥ ‪ s2‬ﺩﺍﺭﺍﻱ ﻃﻮﻝ ‪ 3‬ﺍﺳﺖ‪ ،‬ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ strcpy(s1, s2‬ﺑﺎﻋﺚ‬
‫ﻣﻲﺷﻮﺩ ﮐﻪ ﭼﻬﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ ‪) s2‬ﮐﺎﺭﺍﮐﺘﺮ ‪ NUL‬ﻫﻢ ﺟﺰﺋﻲ ﺍﺯ ‪ s2‬ﺍﺳﺖ( ﺭﻭﻱ ﭼﻬﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ‬
‫ﺍﻭﻝ ‪ s1‬ﺭﻭﻧﻮﻳﺴﻲ ﺷﻮﺩ‪ .‬ﺣﺎﻻ ‪ s1‬ﻭ ‪ s2‬ﺩﺍﺭﺍﻱ ﻃﻮﻝ ‪ 3‬ﻫﺴﺘﻨﺪ‪ .‬ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺍﺿﺎﻓﻲ ‪s1‬‬
‫ﺑﺪﻭﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺭﻫﺎ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺩﺭﺳﺖ ﺍﺳﺖ ﮐﻪ ‪ s1‬ﻭ ‪ S2‬ﻫﻢ ﻣﻘﺪﺍﺭ ﻫﺴﺘﻨﺪ ﻭﻟﻲ ﺟﺪﺍ ﺍﺯ ﻫﻢ‬
‫ﻣﻲﺑﺎﺷﻨﺪ ﻭ ﺍﮔﺮ ﺩﺭ ﺍﺩﺍﻣﻪ ﻳﮑﻲ ﺍﺯ ﺁﻥ ﺩﻭ ﺗﻐﻴﻴﺮ ﮐﻨﺪ‪ ،‬ﺗﺎﺛﻴﺮﻱ ﺑﺮ ﺩﻳﮕﺮﻱ ﻧﺨﻮﺍﻫﺪ ﺩﺍﺷﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐15‬ﺗﺎﺑﻊ )(‪strncpy‬‬


‫‪ strncpy(s1,‬ﭼﻪ ﺍﺛﺮﻱ ﺩﺍﺭﺩ‪:‬‬ ‫ﻓﺮﺍﺧﻮﺍﻧﻲ)‪s2, n‬‬ ‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﺪ ﮐﻪ‬
‫)(‪int main‬‬
‫;"‪{ char s1[] = "ABCDEFG‬‬
‫;"‪char s2[] = "XYZ‬‬
‫;"‪cout << "Before strncpy(s1,s2,2):\n‬‬
‫‪cout << "\ts1 = [" << s1 << "], length‬‬ ‫)‪= " << strlen(s1‬‬
‫;‪<< endl‬‬
‫‪cout << "\ts2 = [" << s2 << "], length‬‬ ‫)‪= " << strlen(s2‬‬
‫;‪<< endl‬‬
‫;)‪strncpy(s1,s2,2‬‬
‫;"‪cout << "After strncpy(s1,s2,2):\n‬‬
‫‪cout << "\ts1 = [" << s1 << "], length‬‬ ‫)‪= " << strlen(s1‬‬
‫;‪<< endl‬‬
‫‪cout << "\ts2 = [" << s2 << "], length‬‬ ‫)‪= " << strlen(s2‬‬
‫;‪<< endl‬‬
‫}‬
‫‪Before strncpy(s1,s2,2):‬‬
‫‪s1 = [ABCDEFG], length = 7‬‬
‫‪s2 = [XYZ], length = 3‬‬
‫‪After strncpy(s1,s2,2):‬‬
‫‪s1 = [XYCDEFG], length = 7‬‬
‫‪s2 = [XYZ], length = 3‬‬
‫‪271‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ strncpy(s1,s2,2‬ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺩﻭ ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ﺭﺷﺖۀ ‪s2‬‬


‫ﺭﻭﻱ ﺩﻭ ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ﺭﺷﺖۀ ‪ s1‬ﮐﭙﻲ ﺷﻮﺩ‪ .‬ﻃﻮﻝ ‪ s2‬ﺗﺎﺛﻴﺮﻱ ﺑﺮ ﻃﻮﻝ ‪ s1‬ﻧﺪﺍﺭﺩ ﻭ ﺍﻧﺪﺍﺯۀ‬
‫‪ s1‬ﺗﻐﻴﻴﺮ ﻧﻤﻲﮐﻨﺪ‪.‬‬
‫ﺩﺭ ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ strncpy(s1,s2,n‬ﺍﮔﺮ ‪ strlen(s1)>n‬ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ‪n‬‬
‫ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ‪ s2‬ﺭﻭﻱ ‪ n‬ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ‪ s1‬ﮐﭙﻲ ﻣﻲﺷﻮﺩ ﻭ ﺍﮔﺮ ‪strlen(s1)<=n‬‬
‫ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺗﺎﺛﻴﺮ ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﺎ ﺗﺎﺑﻊ )(‪ strcpy‬ﻳﮑﻲ ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪.‬‬
‫ﺩﻭ ﺗﺎﺑﻊ )(‪ strcat‬ﻭ )(‪ strncat‬ﻫﻤﺎﻧﻨﺪ ﺗﻮﺍﺑﻊ )(‪ strcpy‬ﻭ‬
‫)(‪ strncpy‬ﺭﻓﺘﺎﺭ ﻣﻲﮐﻨﻨﺪ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﺍﻳﻦ ﺗﻮﺍﺑﻊ‪ ،‬ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺭﺷﺖۀ ‪ s2‬ﺭﺍ ﺑﻪ‬
‫ﺍﻧﺘﻬﺎﻱ ﺭﺷﺖۀ ‪ s1‬ﺍﻟﺼﺎﻕ ﻣﻲﮐﻨﻨﺪ‪ .‬ﻋﺒﺎﺭﺕ "‪ "cat‬ﺍﺯ ﮐﻠﻢۀ "‪ "catenate‬ﺑﻪ ﻣﻌﻨﺎﻱ‬
‫»ﺍﻟﺼﺎﻕ ﻧﻤﻮﺩﻥ« ﮔﺮﻓﺘﻪ ﺷﺪﻩ‪ .‬ﺍﻟﺒﺘﻪ ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺗﻮﺍﺑﻊ ﻣﺬﮐﻮﺭ ‪ s1‬ﻭ ‪ s2‬ﺭﺍ ﺑﻪ ﻳﮏ ﺭﺷﺖۀ‬
‫ﻭﺍﺣﺪ ﺗﺒﺪﻳﻞ ﻧﻤﻲﮐﻨﻨﺪ ﺑﻠﮑﻪ ﻳﮏ ﮐﭙﻲ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ‪ s2‬ﺭﺍ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ‪ s1‬ﭘﻴﻮﻧﺪ ﻣﻲﺯﻧﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐16‬ﺗﺎﺑﻊ ﺍﻟﺼﺎﻕ ﺭﺷﺘﻪ )(‪strcat‬‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﺪ ﮐﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ strcat(s1, s2‬ﭼﻪ ﺗﺎﺛﻴﺮﻱ ﺩﺍﺭﺩ‪:‬‬
‫)(‪int main‬‬
‫;"‪{ char s1[] = "ABCDEFG‬‬
‫;"‪char s2[] = "XYZ‬‬
‫;"‪cout << "Before strcat(s1,s2):\n‬‬
‫‪cout << "\ts1 = [" << s1 << "], length‬‬ ‫)‪= " << strlen(s1‬‬
‫;‪<< endl‬‬
‫‪cout << "\ts2 = [" << s2 << "], length‬‬ ‫)‪= " << strlen(s2‬‬
‫;‪<< endl‬‬
‫;)‪strcat(s1,s2‬‬
‫;"‪cout << "After strcat(s1,s2):\n‬‬
‫‪cout << "\ts1 = [" << s1 << "], length‬‬ ‫)‪= " << strlen(s1‬‬
‫;‪<< endl‬‬
‫‪cout << "\ts2 = [" << s2 << "], length‬‬ ‫)‪= " << strlen(s2‬‬
‫;‪<< endl‬‬
‫}‬
‫‪Before strcat(s1,s2):‬‬
‫‪s1 = [ABCDEFG], length = 7‬‬
‫‪s2 = [XYZ], length = 3‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 272

After strcat(s1,s2):
s1 = [ABCDEFGXYZ], length = 10
s2 = [XYZ], length = 3

‫ ﺭﺍ ﺗﺤﺖ‬s1 ‫ ﭼﮕﻮﻧﻪ‬strcat(s1,s2) ‫ﺗﺼﻮﻳﺮ ﺧﺮﻭﺟﻲ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻓﺮﺍﺧﻮﺍﻧﻲ‬


‫ ﺑﺎﻋﺚ‬strcat(s1, s2) ‫ ﻓﺮﺍﺧﻮﺍﻧﻲ‬،‫ ﺩﺍﺭﺩ‬3 ‫ ﻃﻮﻝ‬s2 ‫ ﭼﻮﻥ‬.‫ﺗﺎﺛﻴﺮ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ‬
‫ ﺑﻪ ﺩﺭﻭﻥ ﺁﻥﻫﺎ‬s2 ‫ ﺍﺿﺎﻓﻪ ﮔﺮﺩﺩ ﻭ ﺳﭙﺲ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ‬s1 ‫ﻣﻲﺷﻮﺩ ﮐﻪ ﺳﻪ ﺑﺎﻳﺖ ﺑﻪ ﺍﻧﺘﻬﺎﻱ‬
‫ ﺗﻮﺟﻪ‬.‫ ﺗﮑﻤﻴﻞ ﺷﻮﺩ‬s1 ‫ ﺑﻪ ﺁﻥﻫﺎ ﺍﺿﺎﻓﻪ ﻣﻲﺷﻮﺩ ﺗﺎ‬NUL ‫ﮐﭙﻲ ﺷﻮﻧﺪ ﻭ ﺩﺭ ﻧﻬﺎﻳﺖ ﮐﺎﺭﺍﮐﺘﺮ‬
.‫ ﻣﺴﺘﻘﻞ ﺍﺯ ﻫﻢ ﺑﺎﻗﻲ ﻣﻲﻣﺎﻧﻨﺪ‬s2 ‫ ﻭ‬s1 ‫ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﺑﺎﺯ ﻫﻢ‬

stancat() ‫ ﺗﺎﺑﻊ ﺍﻟﺼﺎﻕ ﺭﺷﺘﻪ‬8‐17 ‫* ﻣﺜﺎﻝ‬


:‫ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‬strncat(s1,s2,n) ‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺗﺎﺛﻴﺮ ﻓﺮﺍﺧﻮﺍﻧﻲ‬
#include <iostream.h>
#include <cstring.h>
int main()
{ // test-driver for the strncat() function:
char s1[] = "ABCDEFG";
char s2[] = "XYZ";
cout << "Before strncat(s1,s2,2):\n";
cout << "\ts1 = [" << s1 << "], length = " << strlen(s1)
<< endl;
cout << "\ts2 = [" << s2 << "], length = " << strlen(s2)
<< endl;
strncat(s1,s2,2);
cout << "After strncat(s1,s2,2):\n";
cout << "\ts1 = [" << s1 << "], length = " << strlen(s1)
<< endl;
cout << "\ts2 = [" << s2 << "], length = " << strlen(s2)
<< endl;
}
Before strncat(s1,s2,2):
s1 = [ABCDEFG], length = 7
s2 = [XYZ], length = 3
After strncat(s1,s2,2):
s1 = [ABCDEFGXY], length = 9
s2 = [XYZ], length = 3
‫‪273‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫ﻓﺮﺍﺧﻮﺍﻧﻲ )‪ strncat(s1,s2,2‬ﺩﻭ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺑﺘﺪﺍﻱ ‪ s2‬ﺭﺍ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ‪ s1‬ﺍﺿﺎﻓﻪ‬


‫ﻣﻲﮐﻨﺪ ﻭ ﺳﭙﺲ ﮐﺎﺭﺍﮐﺘﺮ ‪ NUL‬ﺭﺍ ﻫﻢ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ‪ s1‬ﻣﻲﺍﻓﺰﺍﻳﺪ‪.‬‬
‫ﻫﺮ ﺩﻭ ﺗﺎﺑﻊ )(‪ strcat‬ﻭ )(‪ strncat‬ﺑﺎﻳﺖﻫﺎﻳﻲ ﺭﺍ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ﺭﺷﺖۀ ‪s1‬‬
‫ﺍﺿﺎﻓﻪ ﻣﻲﮐﻨﻨﺪ‪ .‬ﺍﮔﺮ ﺍﻳﻦ ﺑﺎﻳﺖﻫﺎ ﺩﺭ ﺣﺎﻓﻈﻪ ﻗﺒﻼ ﺍﺷﻐﺎﻝ ﺷﺪﻩ ﺑﺎﺷﻨﺪ ﻭ ﺭﺷﺖۀ ‪ s1‬ﻧﺘﻮﺍﻧﺪ ﺩﺭ‬
‫ﻣﮑﺎﻥ ﻓﻌﻠﻲ ﮔﺴﺘﺮﺵ ﻳﺎﺑﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﮐﻞ ﺍﻳﻦ ﺭﺷﺘﻪ ﺑﻪ ﺑﺨﺸﻲ ﺍﺯ ﺣﺎﻓﻈﻪ ﻣﻨﺘﻘﻞ ﻣﻲﺷﻮﺩ ﮐﻪ‬
‫ﺑﺎﻳﺖﻫﺎﻱ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺩﺭ ﺩﺳﺘﺮﺱ ﺑﺎﺷﻨﺪ ﻭ ﺭﺷﺖۀ ﻣﻮﺭﺩ ﻧﻈﺮ ﺑﺘﻮﺍﻧﺪ ﺁﺯﺍﺩﺍﻧﻪ ﮔﺴﺘﺮﺵ ﻳﺎﺑﺪ‪.‬‬
‫ﺟﺪﻭﻝ ﺯﻳﺮ ﺑﺮﺧﻲ ﺍﺯ ﺗﻮﺍﺑﻊ ﻣﻔﻴﺪﻱ ﮐﻪ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪ <cstring‬ﺗﻌﺮﻳﻒ ﺷﺪﻩﺍﻧﺪ‬
‫ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪ .‬ﻋﺒﺎﺭﺕ ‪ size_t‬ﮐﻪ ﺩﺭ ﺗﻮﺍﺑﻊ ﺟﺪﻭﻝ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﻳﮏ ﻧﻮﻉ ﻋﺪﺩ‬
‫ﺻﺤﻴﺢ ﻭﻳﮋﻩ ﺍﺳﺖ ﮐﻪ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪ <csting‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ‪:‬‬
‫ﺗﻮﺍﺑﻊ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪<cstring‬‬

‫ﻧﺎﻡ ﺗﺎﺑﻊ‬ ‫ﺷﺮﺡ‬

‫;)‪void* memcpy(void* s1, const void* s2, size_t n‬‬


‫)(‪memcpy‬‬
‫‪ n‬ﺑﺎﻳﺖ ﺍﻭﻝ ‪ *S1‬ﺭﺍ ﺑﺎ ‪ n‬ﺑﺎﻳﺖ ﺍﻭﻝ ‪ *S2‬ﺟﺎﻳﮕﺰﻳﻦ ﻣﻲﮐﻨﺪ‪ s .‬ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬

‫;)‪char* strcat(char* s1, const char* s2‬‬


‫)(‪strcat‬‬
‫‪ s2‬ﺭﺍ ﺑﻪ ‪ s1‬ﺍﻟﺤﺎﻕ ﻣﻲﮐﻨﺪ‪ s1 .‬ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ‪.‬‬

‫;)‪char* strchr(const char* s, int c‬‬


‫)(‪strchr‬‬
‫ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﻭﻟﻴﻦ ﻭﻗﻮﻉ ‪ c‬ﺩﺭ ﺭﺷﺖۀ ‪ s‬ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﮔﺮ ‪ c‬ﺩﺭ ‪ s‬ﻧﺒﺎﺷﺪ‪ NULL ،‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬

‫;)‪int strcmp(const char* s1, const char* s2‬‬


‫)(‪strcmp‬‬ ‫‪ s1‬ﺭﺍ ﺑﺎ ﺯﻳﺮﺭﺷﺖۀ ‪ s2‬ﻣﻘﺎﻳﺴﻪ ﻣﻲﮐﻨﺪ‪ .‬ﺍﮔﺮ ‪ s1‬ﺑﻪ ﺗﺮﺗﻴﺐ ﺍﻟﻔﺒﺎﻳﻲ‪ ،‬ﮐﻮﭼﮏﺗﺮ ﻳﺎ ﻣﺴﺎﻭﻱ ﻳﺎ ﺑﺰﺭﮒﺗﺮ ﺍﺯ ‪s2‬‬
‫ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ ﻣﻨﻔﻲ ﻳﺎ ﺻﻔﺮ ﻳﺎ ﻣﻘﺪﺍﺭ ﻣﺜﺒﺖ ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬

‫;)‪char* strcpy(char* s1, const char* s2‬‬


‫)(‪strcpy‬‬
‫‪ s2‬ﺭﺍ ﺩﺭ ‪ s1‬ﮐﭙﻲ ﻣﻲﮐﻨﺪ‪ s1 .‬ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬

‫;)‪size_t strcspn(char* s1, const char* s2‬‬


‫)(‪strcspn‬‬
‫ﻃﻮﻝ ﺑﺰﺭﮒﺗﺮﻳﻦ ﺯﻳﺮﺭﺷﺘﻪ ﺍﻱ ﺍﺯ ‪ s1‬ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ ﮐﻪ ﺑﺎ ]‪ s[0‬ﺷﺮﻭﻉ ﺷﺪﻩ ﻭ ﺷﺎﻣﻞ ﻫﻴﭻﻳﮏ ﺍﺯ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪274‬‬

‫ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻣﻮﺟﻮﺩ ﺩﺭ ‪ s2‬ﻧﻴﺴﺖ‪.‬‬

‫;)‪size_t strlen(const char* s‬‬


‫)(‪strlen‬‬ ‫ﻃﻮﻝ ‪ s‬ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ ﮐﻪ ﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻳﻲ ﺍﺳﺖ ﮐﻪ ﺑﺎ ]‪ s[0‬ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ ﻭ ﺑﺎ ﺍﻭﻟﻴﻦ ﮐﺎﺭﺍﮐﺘﺮ ‪NUL‬‬
‫ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ‪.‬‬

‫;)‪char* strncat(char* s1, const char* s2, size_t n‬‬


‫)(‪strncat‬‬ ‫‪ n‬ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ‪ s2‬ﺭﺍ ﺑﻪ ‪ s1‬ﺍﻟﺼﺎﻕ ﻣﻲﮐﻨﺪ‪ .‬ﺍﮔﺮ )‪ n>=strlen(s2‬ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ‬
‫)‪ strncat(s1,s2,n‬ﺗﺎﺛﻴﺮﻱ ﻣﺸﺎﺑﻪ )‪ strcat(s1,s2‬ﺩﺍﺭﺩ‪.‬‬

‫;)‪int strncmp(const char* s1, const char* s2, size_t n‬‬

‫‪ n‬ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ‪ s1‬ﺭﺍ ﺑﺎ ‪ n‬ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ‪ s2‬ﻣﻘﺎﻳﺴﻪ ﻣﻲﮐﻨﺪ ﻭ ﺍﮔﺮ ﺯﻳﺮﺭﺷﺖۀ ﺍﻭﻝ ﺑﻪ ﺗﺮﺗﻴﺐ ﺍﻟﻔﺒﺎﻳﻲ ﺍﺯ‬
‫)(‪strncmp‬‬ ‫ﺯﻳﺮﺭﺷﺖۀ ﺩﻭﻡ ﺑﺰﺭﮒﺗﺮ‪ ،‬ﻣﺴﺎﻭﻱ ﻳﺎ ﮐﻮﭼﮏﺗﺮ ﺑﺎﺷﺪ‪ ،‬ﻣﻘﺪﺍﺭ ﻣﺜﺒﺖ‪ ،‬ﺻﻔﺮ ﻳﺎ ﻣﻘﺪﺍﺭ ﻣﻨﻔﻲ ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﮔﺮ‬
‫)‪ n>=strlen(s2‬ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ )‪ strncmp(s1, s2, n‬ﺗﺎﺛﻴﺮﻱ ﻣﺸﺎﺑﻪ ﺑﺎ‬
‫)‪ strcmp(s1, s2‬ﺧﻮﺍﻫﺪ ﺩﺍﺷﺖ‪.‬‬

‫;)‪char* strncpy(char* s1, const char* s2, size_t n‬‬


‫‪ n‬ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ‪ s1‬ﺭﺍ ﺑﺎ ‪ n‬ﮐﺎﺭﺍﮐﺘﺮ ﺍﻭﻝ ‪ s2‬ﺟﺎﻳﮕﺰﻳﻦ ﻣﻲﮐﻨﺪ ﻭ ‪ s1‬ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﮔﺮ‬
‫)(‪strncpy‬‬
‫)‪ n<=strlen(s1‬ﺑﺎﺷﺪ‪ ،‬ﻃﻮﻝ ‪ s1‬ﺗﻐﻴﻴﺮ ﻧﻤﻲﮐﻨﺪ ‪ .‬ﺍﮔﺮ )‪ n>=strlen(s2‬ﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ‬
‫)‪ strncpy(s1, s2, n‬ﺗﺎﺛﻴﺮﻱ ﻣﺸﺎﺑﻪ )‪ strcpy(s1, s2‬ﺧﻮﺍﻫﺪ ﺩﺍﺷﺖ‪.‬‬

‫;)‪char* strpbrk(const char* s1, const char* s2‬‬


‫ﻣﺤﻞ ﺍﻭﻟﻴﻦ ﺭﺧﺪﺍﺩ ﻫﺮ ﻳﮏ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ‪ s2‬ﺭﺍ ﺩﺭ ‪ s1‬ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﮔﺮ ﻫﻴﭻﻳﮏ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ‪ s2‬ﺩﺭ )(‪strpbrk‬‬
‫‪ s1‬ﻳﺎﻓﺖ ﻧﺸﺪ‪ NULL ،‬ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬

‫;)‪char* strrchr(const char* s, int c‬‬


‫)(‪strrchr‬‬ ‫ﺁﺧﺮﻳﻦ ﻣﺤﻞ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻦ ﮐﺎﺭﺍﮐﺘﺮ ‪ c‬ﺩﺭ ﺭﺷﺖۀ ‪ s‬ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﮔﺮ ‪ c‬ﺩﺭ ‪ s‬ﻧﺒﺎﺷﺪ‪ NULL ،‬ﺭﺍ‬
‫ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬

‫;)‪size_t strspn(char* s1, const char* s2‬‬


‫ﻃﻮﻝ ﺑﺰﺭﮒﺗﺮﻳﻦ ﺯﻳﺮﺭﺷﺘﻪ ﺍﻱ ﺍﺯ ‪ s1‬ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ ﮐﻪ ﺍﺯ ]‪ s[0‬ﺷﺮﻭﻉ ﺷﺪﻩ ﻭ ﻓﻘﻂ ﺷﺎﻣﻞ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ‬
‫)(‪strspn‬‬
‫ﻣﻮﺟﻮﺩ ﺩﺭ ‪ s2‬ﺍﺳﺖ‪.‬‬
‫‪275‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫;)‪char* strstr(const char* s1, const char* s2‬‬


‫)(‪strstr‬‬ ‫ﺁﺩﺭﺱ ﺍﻭﻟﻴﻦ ﻣﺤﻞ ﻭﻗﻮﻉ ﺯﻳﺮﺭﺷﺖۀ ‪ s2‬ﺩﺭ ﺭﺷﺖۀ ‪ s1‬ﺭﺍ ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﮔﺮ ‪ s2‬ﺩﺭ ‪ s1‬ﻧﺒﺎﺷﺪ‪NULL ،‬‬
‫ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬

‫;)‪char* strtok(char* s1, char* s2‬‬


‫ﺭﺷﺖۀ‪ s1‬ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻣﻮﺟﻮﺩ ﺩﺭ ﺭﺷﺖۀ ‪ s2‬ﻧﺸﺎﻧﻪﮔﺬﺍﺭﻱ ﻣﻲﮐﻨﺪ‪ .‬ﭘﺲ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲ‬
‫)(‪strtok‬‬ ‫ﺁﻏﺎﺯﻳﻦ )‪ strtok(s1, s2‬ﻫﺮ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻮﻓﻘﻴﺖﺁﻣﻴﺰ )‪ strtok(NULL,s2‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ‬
‫ﻧﺸﺎﻥۀ ﻳﺎﻓﺖﺷﺪۀ ﺑﻌﺪﻱ ﺩﺭ ‪ s1‬ﺑﺮ ﻣﻲﮔﺮﺩﺍﻧﺪ‪ .‬ﺍﻳﻦ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻫﺎ ﺭﺷﺖۀ ‪ s1‬ﺭﺍ ﺗﻐﻴﻴﺮ ﻣﻲﺩﻫﺪ ﻭ ﻫﺮ ﮐﺎﺭﺍﮐﺘﺮ‬
‫ﻧﺸﺎﻧﻪ ﺭﺍ ﺑﺎ ﮐﺎﺭﺍﮐﺘﺮ ‪ NUL‬ﺟﺎﻳﮕﺰﻳﻦ ﻣﻲﮐﻨﺪ‪.‬‬

‫‪ 8‐9‬ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺩﺭ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬


‫ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﮐﻪ ﺗﺎﮐﻨﻮﻥ ﺗﺸﺮﻳﺢ ﺷﺪ‪ ،‬ﺩﺭ ﺯﺑﺎﻥ ‪ C‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ ﻭ ﺍﻟﺒﺘﻪ‬
‫ﺑﺨﺶ ﻣﻬﻤﻲ ﺍﺯ ‪ C++‬ﻧﻴﺰ ﻣﺤﺴﻮﺏ ﻣﻲﺷﻮﻧﺪ ﺯﻳﺮﺍ ﻭﺳﻴﻞۀ ﻣﻔﻴﺪﻱ ﺑﺮﺍﻱ ﭘﺮﺩﺍﺯﺵ ﺳﺮﻳﻊ‬
‫ﺩﺍﺩﻩﻫﺎ ﻫﺴﺘﻨﺪ‪ .‬ﺍﻣﺎ ﺍﻳﻦ ﺳﺮﻋﺖ ﭘﺮﺩﺍﺯﺵ‪ ،‬ﻫﺰﻳﻨﻪﺍﻱ ﻫﻢ ﺩﺍﺭﺩ‪ :‬ﺧﻄﺮ ﺧﻄﺎﻫﺎﻱ ﺯﻣﺎﻥ ﺍﺟﺮﺍ‪ .‬ﺍﻳﻦ‬
‫ﺧﻄﺎﻫﺎ ﻣﻌﻤﻮﻻ ﺍﺯ ﺍﻳﻦ ﻧﺎﺷﻲ ﻣﻲﺷﻮﻧﺪ ﮐﻪ ﻓﻘﻂ ﺑﺮ ﮐﺎﺭﺍﮐﺘﺮ ‪ NUL‬ﺑﻪ ﻋﻨﻮﺍﻥ ﭘﺎﻳﺎﻥ ﺭﺷﺘﻪ ﺗﮑﻴﻪ‬
‫ﻣﻲﺷﻮﺩ‪ C++ .‬ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺧﺎﺻﻲ ﻧﻴﺰ ﺩﺍﺭﺩ ﮐﻪ ﺍﻣﻦﺗﺮ ﻭ ﻣﻄﻤﺌﻦﺗﺮ ﻫﺴﺘﻨﺪ‪ .‬ﺩﺭ ﺍﻳﻦ‬
‫ﺭﺷﺘﻪﻫﺎ‪ ،‬ﻃﻮﻝ ﺭﺷﺘﻪ ﻧﻴﺰ ﺩﺭﻭﻥ ﺭﺷﺘﻪ ﺫﺧﻴﺮﻩ ﻣﻲﺷﻮﺩ ﻭ ﻟﺬﺍ ﻓﻘﻂ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ‪ NUL‬ﺑﺮﺍﻱ‬
‫ﻣﺸﺨﺺ ﻧﻤﻮﺩﻥ ﺍﻧﺘﻬﺎﻱ ﺭﺷﺘﻪ ﺍﮐﺘﻔﺎ ﻧﻤﻲﺷﻮﺩ‪.‬‬

‫‪ 8‐10‬ﻧﮕﺎﻫﻲ ﺩﻗﻴﻖﺗﺮ ﺑﻪ ﺗﺒﺎﺩﻝ ﺩﺍﺩﻩﻫﺎ‬


‫ﻭﻗﺘﻲ ﻣﻲﺧﻮﺍﻫﻴﻢ ﺩﺍﺩﻩﻫﺎﻳﻲ ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﻴﻢ‪ ،‬ﺍﻳﻦ ﺩﺍﺩﻩﻫﺎ ﺭﺍ ﺩﺭ ﻗﺎﻟﺐ ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ‬
‫ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺗﺎﻳﭗ ﻣﻲﮐﻨﻴﻢ‪ .‬ﻫﻤﭽﻨﻴﻦ ﻭﻗﺘﻲ ﻣﻲﺧﻮﺍﻫﻴﻢ ﻧﺘﺎﻳﺠﻲ ﺭﺍ ﺑﻪ ﺧﺎﺭﺝ ﺍﺯ ﺑﺮﻧﺎﻣﻪ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪276‬‬

‫ﺑﻔﺮﺳﺘﻴﻢ‪ ،‬ﺍﻳﻦ ﻧﺘﺎﻳﺞ ﺩﺭ ﻗﺎﻟﺐ ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﻧﻤﺎﻳﺶ ﺩﺍﺩﻩ ﻣﻲﺷﻮﻧﺪ‪ .‬ﻻﺯﻡ ﺍﺳﺖ‬
‫ﮐﻪ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺑﻪ ﻧﺤﻮﻱ ﺑﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺗﻔﺴﻴﺮ ﺷﻮﻧﺪ‪ .‬ﻣﺜﻼ ﻭﻗﺘﻲ ﻗﺼﺪ ﺩﺍﺭﻳﻢ ﻳﮏ ﻋﺪﺩ‬
‫ﺻﺤﻴﺢ ﺭﺍ ﻭﺍﺭﺩ ﮐﻨﻴﻢ‪ ،‬ﭼﻨﺪ ﮐﺎﺭﺍﮐﺘﺮ ﻋﺪﺩﻱ ﺗﺎﻳﭗ ﻣﻲﮐﻨﻴﻢ‪ .‬ﺣﺎﻻ ﺳﺎﺯ ﻭ ﮐﺎﺭﻱ ﻻﺯﻡ ﺍﺳﺖ ﮐﻪ‬
‫ﺍﺯ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﻳﮏ ﻣﻘﺪﺍﺭ ﺻﺤﻴﺢ ﺑﺴﺎﺯﺩ ﻭ ﺑﻪ ﺑﺮﻧﺎﻣﻪ ﺗﺤﻮﻳﻞ ﺩﻫﺪ‪ .‬ﻫﻤﭽﻨﻴﻦ ﻭﻗﺘﻲ ﻗﺼﺪ‬
‫ﺩﺍﺭﻳﻢ ﻳﮏ ﻋﺪﺩ ﺍﻋﺸﺎﺭﻱ ﺭﺍ ﺑﻪ ﺧﺮﻭﺟﻲ ﺑﻔﺮﺳﺘﻴﻢ‪ ،‬ﺑﺎﻳﺪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺭﺍﻩﮐﺎﺭﻱ‪ ،‬ﺁﻥ ﻋﺪﺩ‬
‫ﺍﻋﺸﺎﺭﻱ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻳﻲ ﺗﺒﺪﻳﻞ ﺷﻮﺩ ﺗﺎ ﺩﺭ ﺧﺮﻭﺟﻲ ﻧﻤﺎﻳﺶ ﻳﺎﺑﺪ‪ .‬ﺟﺮﻳﺎﻥﻫﺎ‪ 1‬ﺍﻳﻦ ﻭﻇﺎﻳﻒ‬
‫ﺭﺍ ﺩﺭ ‪ C++‬ﺑﺮ ﻋﻬﺪﻩ ﺩﺍﺭﻧﺪ‪ .‬ﺟﺮﻳﺎﻥﻫﺎ ﺷﺒﻴﻪ ﭘﺎﻻﻳﻪﺍﻱ ﻫﺴﺘﻨﺪ ﮐﻪ ﺩﺍﺩﻩﻫﺎ ﺭﺍ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺗﺒﺪﻳﻞ‬
‫ﻣﻲﮐﻨﻨﺪ ﻭ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﺑﻪ ﺩﺍﺩﻩﻫﺎﻳﻲ ﺍﺯ ﻳﮏ ﻧﻮﻉ ﺑﻨﻴﺎﺩﻱ ﺗﺒﺪﻳﻞ ﻣﻲﻧﻤﺎﻳﻨﺪ‪ .‬ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ‪،‬‬
‫ﻭﺭﻭﺩﻱﻫﺎ ﻭ ﺧﺮﻭﺟﻲﻫﺎ ﺭﺍ ﻳﮏ ﮐﻼﺱ ﺟﺮﻳﺎﻥ ﺑﻪ ﻧﺎﻡ ‪ stream‬ﮐﻨﺘﺮﻝ ﻣﻲﮐﻨﺪ‪ .‬ﺍﻳﻦ ﮐﻼﺱ‬
‫ﺧﻮﺩ ﺑﻪ ﺯﻳﺮﮐﻼﺱﻫﺎﻳﻲ ﺗﻘﺴﻴﻢ ﻣﻲﺷﻮﺩ‪ :‬ﺷﻲﺀ ‪ istream‬ﺟﺮﻳﺎﻧﻲ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ‬
‫ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺍﺭﺩ ﺷﺪﻩ ﺍﺯ ﺻﻔﺤﻪ ﮐﻠﻴﺪ‪ ،‬ﻓﺮﺍﻫﻢ ﻣﻲﮐﻨﺪ‪ .‬ﺷﻲﺀ ‪ostream‬‬
‫ﺟﺮﻳﺎﻧﻲ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ ﺣﺎﺻﻞ ﺭﺍ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺧﺮﻭﺟﻲ ﻗﺎﺑﻞ ﻧﻤﺎﻳﺶ ﺭﻭﻱ ﺻﻔﺢۀ‬
‫ﻧﻤﺎﻳﺶﮔﺮ ﺗﺒﺪﻳﻞ ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﺷﻲﺀ ‪ ifstream‬ﺟﺮﻳﺎﻧﻲ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺍﺯ‬
‫ﺩﺍﺩﻩﻫﺎﻱ ﺩﺍﺧﻞ ﻳﮏ ﻓﺎﻳﻞ‪ ،‬ﻓﺮﺍﻫﻢ ﻣﻲﮐﻨﺪ‪ .‬ﺷﻲﺀ ‪ ofstream‬ﺟﺮﻳﺎﻧﻲ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ‬
‫ﺣﺎﺻﻞ ﺭﺍ ﺩﺭﻭﻥ ﻳﮏ ﻓﺎﻳﻞ ﺫﺧﻴﺮﻩ ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﺍﻳﻦ ﺟﺮﻳﺎﻥﻫﺎ ﻭ ﻃﺮﻳﻖۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥﻫﺎ ﺭﺍ ﺩﺭ‬
‫ﺍﺩﺍﻣﻪ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ‪.‬‬
‫ﮐﻼﺱ ‪ istream‬ﻧﺤﻮۀ ﺭﻓﺘﺎﺭ ﺑﺎ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻭﺭﻭﺩﻱ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲﻧﻤﺎﻳﺪ‪.‬‬
‫ﻣﻬﻢﺗﺮﻳﻦ ﭼﻴﺰﻱ ﮐﻪ ﺑﺎﻳﺪ ﺗﻌﺮﻳﻒ ﺷﻮﺩ ﻭ ﺍﺗﻔﺎﻗﺎ ﺑﻴﺸﺘﺮﻳﻦ ﺍﺳﺘﻔﺎﺩﻩ ﺭﺍ ﻫﻢ ﺩﺍﺭﺩ‪ ،‬ﻧﺤﻮۀ ﺭﻓﺘﺎﺭ‬
‫»ﻋﻤﻠﮕﺮ ﺑﺮﻭﻥ ﮐﺸﻲ >> « ﺍﺳﺖ )ﺑﻪ ﺁﻥ ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ ﻧﻴﺰ ﻣﻲﮔﻮﻳﻴﻢ(‪ .‬ﻗﺒﻼ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻫﺎ ﺍﺯ‬
‫ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ‪ .‬ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺩﻭ ﻋﻤﻠﻮﻧﺪ ﺩﺍﺭﺩ‪ :‬ﺷﻲﺀ ‪ istream‬ﮐﻪ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ‬
‫ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺍﺯ ﮐﺠﺎ ﺑﺎﻳﺪ ﺑﻴﺮﻭﻥ ﮐﺸﻴﺪﻩ ﺷﻮﻧﺪ‪ ،‬ﻭ ﺷﻴﺌﻲ ﮐﻪ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ ﻣﻘﺪﺍﺭ‬
‫ﺑﺮﻭﻥﮐﺸﻲﺷﺪﻩ ﺑﺎﻳﺪ ﺍﺯ ﭼﻪ ﻧﻮﻋﻲ ﺑﺎﺷﺪ ﻭ ﮐﺠﺎ ﺑﺎﻳﺪ ﺫﺧﻴﺮﻩ ﺷﻮﺩ‪ .‬ﺑﻪ ﺍﻳﻦ ﭘﺮﺩﺍﺯﺵ ﮐﻪ ﺍﺯ‬
‫ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺧﺎﻡ ﻭﺭﻭﺩﻱ ﻣﻘﺎﺩﻳﺮﻱ ﺑﺎ ﻧﻮﻉ ﻣﺸﺨﺺ ﺗﻮﻟﻴﺪ ﻣﻲﮐﻨﺪ‪ ،‬ﻗﺎﻟﺐﺑﻨﺪﻱ‪ 2‬ﻣﻲﮔﻮﻳﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐18‬ﻋﻤﻠﮕﺮ ﺑﺮﻭﻥ ﻛﺸﻲ >> ﻭﺭﻭﺩﻱ ﺭﺍ ﻗﺎﻟﺐﺑﻨﺪﻱ ﻣﻲﮐﻨﺪ‬


‫" ﻭﺍﺭﺩ ﺷﺪﻩ ﺍﺳﺖ‪:‬‬ ‫ﻓﺮﺽ ﮐﻨﻴﺪ ﻛﺪ ﺯﻳﺮ ﺍﺟﺮﺍ ﺷﺪﻩ ﻭ ﻭﺭﺩﻱ ﺑﻪ ﺷﮑﻞ "‪46‬‬

‫;‪int n‬‬
‫;‪cin >> n‬‬
‫‪277‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫ﻭﺭﻭﺩﻱ ﺑﺎﻻ ﺩﺭ ﺣﻘﻴﻘﺖ ﺷﺎﻣﻞ ﻫﻔﺖ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺳﺖ‪ ' ' :‬ﻭ ' ' ﻭ ' ' ﻭ ' ' ﻭ '‪'4‬‬
‫ﻭ '‪ '6‬ﻭ '‪ '\n‬ﻳﻌﻨﻲ ﭼﻬﺎﺭ ﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﻭ ﺳﭙﺲ '‪ '4‬ﻭ ﺑﻌﺪ ﺍﺯ ﺁﻥ '‪ '6‬ﻭ ﺩﺭ‬

‫‪1 – Streams‬‬ ‫‪2 - Formatting‬‬

‫ﻧﻬﺎﻳﺖ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ '‪ '\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‬ﺩﺍﺭﺩ‪ .‬ﺍﺯ ﺍﻳﻦ ﺣﺎﺻﻞ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﺷﺮﻁ ﻣﻨﻄﻘﻲ ﺩﺭ ﺩﺳﺘﻮﺭﺍﺕ ﺩﻳﮕﺮ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪ .‬ﻣﺜﻼ ﻣﻲﺗﻮﺍﻥ ﺣﻠﻘﻪﻫﺎ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﮐﻨﺘﺮﻝ ﮐﺮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐19‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺑﻴﺮﻭﻥﻛﺸﻲ ﺑﺮﺍﻱ ﻛﻨﺘﺮﻝ ﮐﺮﺩﻥ ﻳﻚ ﺣﻠﻘﻪ‬


‫)(‪int main‬‬
‫;‪{ int n‬‬
‫)‪while (cin >> n‬‬
‫;‪cout << "n = " << n << endl‬‬
‫}‬
‫‪46‬‬
‫=‪n‬‬ ‫‪46‬‬
‫‪22‬‬ ‫‪44‬‬ ‫‪66‬‬ ‫‪88‬‬
‫=‪n‬‬ ‫‪22‬‬
‫=‪n‬‬ ‫‪44‬‬
‫=‪n‬‬ ‫‪66‬‬
‫=‪n‬‬ ‫‪88‬‬
‫‪33,‬‬ ‫‪55, 77, 99‬‬
‫=‪n‬‬ ‫‪33‬‬

‫ﺗﺎ ﺯﻣﺎﻧﻲ ﮐﻪ ﺍﻋﺪﺍﺩ ﻭﺭﻭﺩﻱ ﻓﻘﻂ ﺑﻪ ﻭﺳﻴﻞۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻓﻀﺎﻱ ﺳﻔﻴﺪ )ﻣﺜﻞ ‪ tab‬ﻳﺎ ﻓﺎﺻﻞۀ‬
‫ﺧﺎﻟﻲ ﻳﺎ ﮐﺎﺭﺍﮐﺘﺮ ﺧﻂ ﺟﺪﻳﺪ( ﺍﺯ ﻫﻢ ﺟﺪﺍ ﺷﺪﻩ ﺑﺎﺷﻨﺪ‪ ،‬ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﻫﻤﻴﻦ ﮐﻪ ﺑﻪ‬
‫ﺍﻭﻟﻴﻦ ﮐﺎﺭﺍﮐﺘﺮ ﻏﻴﺮﻓﺎﺻﻠﻪﺍﻱ ﻭ ﻏﻴﺮﻋﺪﺩﻱ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ )ﮐﻪ ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﮐﺎﺭﺍﮐﺘﺮ ﮐﺎﻣﺎ '‪',‬‬
‫ﺍﺳﺖ(‪ ،‬ﻋﻤﻠﮕﺮ ﺑﺮﻭﻥﮐﺸﻲ ﺍﺯ ﮐﺎﺭ ﻣﻲﺍﻳﺴﺘﺪ ﻭ ﺑﻪ ﻫﻤﻴﻦ ﻭﺍﺳﻄﻪ‪ ،‬ﺣﻠﻘﻪ ﻧﻴﺰ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ‪.‬‬

‫‪ 8‐11‬ﻭﺭﻭﺩﻱ ﻗﺎﻟﺐﺑﻨﺪﻱ ﻧﺸﺪﻩ‬


‫ﺳﺮﻓﺎﻳﻞ >‪ <iostream‬ﺗﻮﺍﺑﻊ ﻣﺨﺘﻠﻔﻲ ﺑﺮﺍﻱ ﻭﺭﻭﺩﻱ ﺩﺍﺭﺩ‪ .‬ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺑﺮﺍﻱ ﻭﺍﺭﺩ‬
‫ﮐﺮﺩﻥ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﻭ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ﮐﻪ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺭﺍ‬
‫‪279‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫ﻧﺎﺩﻳﺪﻩ ﻧﻤﻲﮔﻴﺮﻧﺪ‪ .‬ﺭﺍﻳﺞﺗﺮﻳﻦ ﺁﻥﻫﺎ‪ ،‬ﺗﺎﺑﻊ )(‪ cin.get‬ﺑﺮﺍﻱ ﺩﺭﻳﺎﻓﺖ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺗﮑﻲ ﻭ‬
‫ﺗﺎﺑﻊ )(‪ cin.getline‬ﺑﺮﺍﻱ ﺩﺭﻳﺎﻓﺖ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐20‬ﺩﺭﻳﺎﻓﺖ ﻛﺎﺭﺍﻛﺘﺮﻫﺎ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ )(‪cin.get‬‬


‫))‪while (cin.get(c‬‬
‫;'‪{ if (c >= 'a' && c <= 'z') c += 'A' - 'a‬‬ ‫‪// capitalize c‬‬
‫;)‪cout.put(c‬‬
‫;‪if (c = = '\n') break‬‬
‫}‬

‫ﺣﻠﻖۀ ﺑﺎﻻ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﺒﺎﺭﺕ )‪ cin.get(c‬ﮐﻨﺘﺮﻝ ﻣﻲﺷﻮﺩ‪ .‬ﺍﮔﺮ ﺩﺭ ﺟﺮﻳﺎﻥ‬


‫ﻭﺭﻭﺩﻱ‪ ،‬ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ ﺗﺸﺨﻴﺺ ﺩﺍﺩﻩ ﺷﻮﺩ )ﮐﻠﻴﺪﻫﺎﻱ ‪ ،(Ctrl+Z‬ﺗﺎﺑﻊ‬
‫)(‪ cin.get‬ﻣﺘﻮﻗﻒ ﺷﺪﻩ ﻭ ﻣﻘﺪﺍﺭ ‪ false‬ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ ﻭ ﺩﺭ ﻧﺘﻴﺠﻪ ﺣﻠﻘﻪ ﻣﺘﻮﻗﻒ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﻫﻤﭽﻨﻴﻦ ﺍﮔﺮ ﮐﺎﺭﺍﮐﺘﺮ ﻭﺍﺭﺩ ﺷﺪﻩ ﻳﮏ ﮐﺎﺭﮐﺘﺮ ﺧﻂ ﺟﺪﻳﺪ ﺑﺎﺷﺪ‪ ،‬ﺩﺳﺘﻮﺭ ‪break‬‬
‫ﺩﺭﻭﻥ ﺣﻠﻘﻪ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺣﻠﻘﻪ ﻣﺘﻮﻗﻒ ﺷﻮﺩ‪ .‬ﺍﻭﻟﻴﻦ ﺩﺳﺘﻮﺭ ‪ if‬ﮐﺎﺭﺍﮐﺘﺮ ﻭﺍﺭﺩ ﺷﺪﻩ ﺭﺍ‬
‫ﺑﻪ ﺣﺮﻑ ﺑﺰﺭﮒ ﺗﺒﺪﻳﻞ ﻣﻲﮐﻨﺪ ﻭ ﺳﭙﺲ ﮐﺎﺭﺍﮐﺘﺮ ﺣﺎﺻﻞ ﺑﺎ ﺗﺎﺑﻊ )‪ cout.put(c‬ﺑﻪ‬
‫ﺧﺮﻭﺟﻲ ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺷﮑﻞ ﺯﻳﺮ ﻧﻤﻮﻧﻪﺍﻱ ﺍﺯ ﺍﺟﺮﺍﻱ ﺣﻠﻖۀ ﺑﺎﻻﺳﺖ‪:‬‬
‫!‪I like C++ features‬‬
‫!‪I LIKE C++ FEATURES‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐21‬ﻭﺍﺭﺩ ﻛﺮﺩﻥ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﻪ ﻭﺳﻴﻞۀ ﺗﺎﺑﻊ )(‪cin.getline‬‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﭼﻄﻮﺭ ﻣﻲﺗﻮﺍﻥ ﺩﺍﺩﻩﻫﺎﻱ ﻣﺘﻨﻲ ﺭﺍ ﺧﻂ ﺑﻪ ﺧﻂ ﺍﺯ‬
‫ﻭﺭﻭﺩﻱ ﺧﻮﺍﻧﺪﻩ ﻭ ﺩﺭﻭﻥ ﻳﮏ ﺁﺭﺍﻱۀ ﺭﺷﺘﻪﺍﻱ ﻗﺮﺍﺭ ﺩﺍﺩ‪:‬‬
‫;‪const int LEN=32‬‬ ‫‪// maximum word length‬‬
‫;‪const int SIZE=10‬‬ ‫‪// array size‬‬
‫‪typedef char Name[LEN]; // defines Name to be a C_string type‬‬
‫)(‪int main‬‬
‫‪{ Name martyr[SIZE]; // defines martyr to be an array of 10 names‬‬
‫;‪int n=0‬‬
‫)‪while(cin.getline(martyr[n++], LEN) && n<SIZE‬‬
‫;‬
‫;‪--n‬‬
‫)‪for (int i=0; i<n; i++‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪280‬‬

‫;‪cout << '\t' << i+1 << ". " << martyr[i] << endl‬‬
‫}‬

‫ﺷﻲﺀ ‪ martyr‬ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ‪ 10‬ﺷﻲ ﺑﺎ ﻧﻮﻉ ‪ Name‬ﺍﺳﺖ‪ .‬ﻗﺒﻼ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬


‫‪ typedef‬ﻣﺸﺨﺺ ﺷﺪﻩ ﮐﻪ ﻧﻮﻉ ‪ Name‬ﻣﻌﺎﺩﻝ ﻳﮏ ﺁﺭﺍﻱۀ ‪ 32‬ﻋﻨﺼﺮﻱ ﺍﺯ ﻧﻮﻉ ‪char‬‬
‫ﺗﺎﺑﻊ‬ ‫ﻓﺮﺍﺧﻮﺍﻧﻲ‬ ‫‪.(NUL+‬‬ ‫ﮐﺎﺭﺍﮐﺘﺮ‬ ‫‪32‬‬ ‫ﻃﻮﻝ‬ ‫ﺑﻪ‬ ‫ﺭﺷﺘﻪﺍﻱ‬ ‫)ﻳﻌﻨﻲ‬ ‫ﺍﺳﺖ‬
‫)‪ cin.getline(martyr[n++], LEN‬ﻫﻢۀ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﺍﺯ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ‬
‫ﻣﻲﺧﻮﺍﻧﺪ ﺗﺎ ﺯﻣﺎﻧﻲ ﮐﻪ ﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺧﻮﺍﻧﺪﻩ ﺷﺪﻩ ﺑﻪ ‪ LEN-1‬ﺑﺮﺳﺪ ﻳﺎ ﺍﻳﻦ ﮐﻪ ﺑﻪ‬
‫ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﺧﻂ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ‪ .‬ﺳﭙﺲ ﺍﻳﻦ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺧﻮﺍﻧﺪﻩ ﺷﺪﻩ ﺑﻪ ﺩﺭﻭﻥ ﺭﺷﺖۀ‬
‫ﮐﺎﺭﺍﮐﺘﺮﻱ ]‪ martyr[n‬ﮐﭙﻲ ﻣﻲﺷﻮﻧﺪ‪ .‬ﻫﺮﮔﺎﻩ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺧﻂ ﺟﺪﻳﺪ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ‪ ،‬ﺍﻳﻦ‬
‫ﮐﺎﺭﺍﮐﺘﺮ ﺍﺯ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺣﺬﻑ ﻣﻲﺷﻮﺩ‪ .‬ﺩﺭ ﻧﺘﻴﺠﻪ ﻫﻴﭻ ﻭﻗﺖ ﮐﺎﺭﺍﮐﺘﺮ ﺧﻂ ﺟﺪﻳﺪ ﺑﻪ‬
‫ﺩﺭﻭﻥ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻓﺮﺳﺘﺎﺩﻩ ﻧﻤﻲﺷﻮﺩ‪.‬‬
‫ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﺑﺪﻥۀ ﺣﻠﻖۀ ‪ while‬ﺧﺎﻟﻲ ﺍﺳﺖ‪ .‬ﺍﻳﻦ ﺣﻠﻘﻪ ﭘﺎﻳﺎﻥ ﻣﻲﻳﺎﺑﺪ‬
‫ﻭﻗﺘﻲ ﮐﻪ ﺩﺭ ﺟﺮﻳﺎﻥ ﻭﺭﻭﺩﻱ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ ﺑﺮﺧﻮﺭﺩ ﺷﻮﺩ ﻳﺎ ﺍﻳﻦ ﮐﻪ ‪n==size‬‬
‫ﺷﻮﺩ‪ .‬ﭼﻮﻥ ‪ n‬ﺍﺯ ﺻﻔﺮ ﺷﺮﻭﻉ ﺷﺪﻩ ﻭ ﭘﺲ ﺍﺯ ﻫﺮ ﺑﺎﺭ ﺩﺭﻳﺎﻓﺖ ﻧﺎﻡ‪ ،‬ﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﻭﺩﻩ‬
‫ﻣﻲﺷﻮﺩ‪ ،‬ﻫﻤﻴﺸﻪ ﻣﻘﺪﺍﺭ ‪ n‬ﻳﮑﻲ ﺑﻴﺸﺘﺮ ﺍﺯ ﺗﻌﺪﺍﺩ ﺍﺳﺎﻣﻲ ﺧﻮﺍﻧﺪﻩ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ‬
‫ﭘﺲ ﺍﺯ ﺍﺗﻤﺎﻡ ﺣﻠﻘﻪ‪ ،‬ﻣﻘﺪﺍﺭ ‪ n‬ﺑﺎﻳﺪ ﻳﮏ ﻭﺍﺣﺪ ﮐﺎﺳﺘﻪ ﺷﻮﺩ ﺗﺎ ﺗﻌﺪﺍﺩ ﻭﺍﻗﻌﻲ ﺍﺳﺎﻣﻲ ﺧﻮﺍﻧﺪﻩ‬
‫ﺷﺪﻩ ﺭﺍ ﻧﺸﺎﻥ ﺩﻫﺪ‪ .‬ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻳﮏ ﺣﻠﻖۀ ‪ for‬ﻣﻘﺪﺍﺭ ﺭﺷﺘﻪﻫﺎ ﺭﺍ‬
‫ﭼﺎﭖ ﮐﺮﺩ ﻳﺎ ﺭﻭﻱ ﺁﻥﻫﺎ‬
‫‪martyr.dat‬‬
‫ﭘﺮﺩﺍﺯﺵﻫﺎﻱ ﺩﻳﮕﺮﻱ ﺍﻧﺠﺎﻡ‬
‫‪Thamen-al-aemmeh (1360/7/5) - ABADAN‬‬
‫‪Tarigh-al-ghods (1360/9/8) - BOSTAN‬‬ ‫ﺩﺍﺩ‪ .‬ﺍﮔﺮ ﻓﺮﺽ ﮐﻨﻴﻢ ﮐﻪ‬
‫‪Fath-al-mobin (1361/1/1) - DEZFUL‬‬
‫‪Beyt-al-moghaddas(1361/2/10) - KHORAMSHAHR‬‬ ‫ﺍﺳﺎﻣﻲ ﺍﺯ ﻓﺎﻳﻞ ﻣﺘﻨﻲ ﻣﻘﺎﺑﻞ‬
‫‪Ramazan (1361/4/23) - TACTICAL‬‬
‫‪Val-fajr 6 (1362/12/2) - CHAZABEH‬‬ ‫ﺧﻮﺍﻧﺪﻩ ﺷﺪﻩ ﺑﺎﺷﻨﺪ‪ ،‬ﺁﻧﮕﺎﻩ‬
‫‪Val-fajr 8 (1364/11/20) - MAJNOUN‬‬
‫‪Karbala 1 (1365/4/10) - MEHRAN‬‬ ‫ﺧﺮﻭﺟﻲ ﮐﺪ ﺑﺎﻻ ﺑﻪ ﺷﮑﻞ‬
‫ﺯﻳﺮ ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪:‬‬
‫‪1.‬‬ ‫‪Thamen-al-aemmeh (1360/7/5) - ABADAN‬‬
‫‪2.‬‬ ‫‪Tarigh-al-ghods (1360/9/8) - BOSTAN‬‬
‫‪3.‬‬ ‫‪Fath-al-mobin (1361/1/1) - DEZFUL‬‬
‫‪4.‬‬ ‫‪Beyt-al-moghaddas(1361/2/10) - KHORAMSHAHR‬‬
‫‪5.‬‬ ‫‪Ramazan (1361/4/23) - TACTICAL‬‬
‫‪281‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫‪6. Val-fajr 6 (1362/12/2) - CHAZABEH‬‬


‫‪7. Val-fajr 8 (1364/11/20) - MAJNOUN‬‬
‫‪8. Karbala 1 (1365/4/10) - MEHRAN‬‬

‫‪ 8‐12‬ﻧﻮﻉ ‪ string‬ﺩﺭ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬


‫ﺩﺭ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﻧﻮﻉ ﺩﺍﺩﻩﺍﻱ ﺧﺎﺻﻲ ﺑﻪ ﻧﺎﻡ ‪ string‬ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﮐﻪ ﻣﺸﺨﺼﺎﺕ‬
‫ﺍﻳﻦ ﻧﻮﻉ ﺩﺭ ﺳﺮﻓﺎﻳﻞ >‪ <string‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﺑﺮﺍﻱ ﺁﺷﻨﺎﻳﻲ ﺑﺎ ﺍﻳﻦ ﻧﻮﻉ ﺟﺪﻳﺪ‪ ،‬ﺍﺯ‬
‫ﻃﺮﻳﻖۀ ﺍﻋﻼﻥ ﻭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺁﻥ ﺷﺮﻭﻉ ﻣﻲﮐﻨﻴﻢ‪ .‬ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﺍﺯ ﻧﻮﻉ ‪ string‬ﻫﺴﺘﻨﺪ ﺑﻪ‬
‫ﭼﻨﺪ ﻃﺮﻳﻖ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺍﻋﻼﻥ ﻭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺷﻮﻧﺪ‪:‬‬
‫‪string‬‬ ‫;‪s1‬‬ ‫‪// s1 contains 0 characters‬‬
‫‪string‬‬ ‫;"‪s2 = "PNU University‬‬ ‫‪// s2 contains 14 characters‬‬
‫‪string‬‬ ‫;)'*' ‪s3(60,‬‬ ‫‪// s3 contains 60 asterisks‬‬
‫‪string‬‬ ‫;‪s4 = s3‬‬ ‫‪// s4 contains 60 asterisks‬‬
‫‪string‬‬ ‫;)‪s5(s2, 4, 2‬‬ ‫"‪// s5 is the 2-character string "Un‬‬

‫‪string‬ﻫﺎ ﻣﺜﻞ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩ ﮐﺮﺩﻥ ﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ‬


‫ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ‪ s1 .‬ﺩﺭ ﮐﺪ ﺑﺎﻻ ﺍﺯ ﻧﻮﻉ ‪ string‬ﺍﻋﻼﻥ ﺷﺪﻩ‪ .‬ﺍﮔﺮ ﻳﮏ ﺷﻲ ﺍﺯ ﻧﻮﻉ‬
‫‪ string‬ﺍﻋﻼﻥ ﺷﺪﻩ ﻭﻟﻲ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﺸﺪﻩ ﺑﺎﺷﺪ )ﻣﺜﻞ ‪ ،(s1‬ﺁﻧﮕﺎﻩ ﺩﺭﻭﻥ ﺁﻥ ﻳﮏ ﺭﺷﺖۀ‬
‫ﺧﺎﻟﻲ ﺻﻔﺮ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪string .‬ﻫﺎ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﻣﺜﻞ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺑﻪ‬
‫ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩ‪ ،‬ﻣﺜﻞ ‪ .s2‬ﺍﺷﻴﺎﻱ ‪ string‬ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻃﻮﺭﻱ ﻣﻘﺪﺍﺭﺩﻫﻲ‬
‫ﮐﻨﻴﻢ ﮐﻪ ﺑﺎ ﺗﻌﺪﺍﺩ ﻣﺸﺨﺼﻲ ﺍﺯ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﺩﻟﺨﻮﺍﻩ ﭘﺮ ﺷﻮﺩ‪ .‬ﻣﺜﻞ ‪ s3‬ﮐﻪ ﺣﺎﻭﻱ ﺷﺼﺖ‬
‫ﮐﺎﺭﺍﮐﺘﺮ '*' ﺍﺳﺖ‪string .‬ﻫﺎ ﺭﺍ ﺑﺮ ﺧﻼﻑ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﻳﮑﺪﻳﮕﺮ‬
‫ﺗﺨﺼﻴﺺ ﺩﻫﻴﻢ ﻭ ﺁﻥﻫﺎ ﺭﺍ ﺍﺯ ﺭﻭﻱ ﻳﮏ ﺷﻲﺀ ‪ string‬ﻣﻮﺟﻮﺩ ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﻨﻴﻢ‪ .‬ﻣﺜﻞ ‪s4‬‬
‫ﮐﻪ ﻫﻢۀ ﻣﻘﺎﺩﻳﺮ ‪ s3‬ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﺧﻮﺍﻫﺪ ﮔﺮﻓﺖ‪ .‬ﻫﻤﭽﻨﻴﻦ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺷﻴﺎﻱ ‪ string‬ﺭﺍ‬
‫ﺑﺎ ﺯﻳﺮﺭﺷﺘﻪﺍﻱ ﺍﺯ ﻳﮏ ‪ string‬ﻣﻮﺟﻮﺩ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﻤﺎﻳﻴﻢ‪ .‬ﻣﺜﻞ ‪ s5‬ﮐﻪ ﺩﻭ ﮐﺎﺭﺍﮐﺘﺮ ﺍﺯ ‪s2‬‬
‫ﺑﺎ ﺷﺮﻭﻉ ﺍﺯ ﺍﻳﻨﺪﮐﺲ ﭼﻬﺎﺭﻡ ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﺧﻮﺍﻫﺪ ﮔﺮﻓﺖ‪ .‬ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﺳﺎﺯﻧﺪۀ ﺯﻳﺮﺭﺷﺘﻪ‬
‫ﺳﻪ ﻗﺴﻤﺖ ﺩﺍﺭﺩ‪ – 1 :‬ﺭﺷﺖۀ ﻭﺍﻟﺪ ﮐﻪ ﺯﻳﺮﺭﺷﺘﻪ ﺍﺯ ﺩﺭﻭﻥ ﺁﻥ ﺍﺳﺘﺨﺮﺍﺝ ﻣﻲﺷﻮﺩ )ﺩﺭ ﺍﻳﻦ‬
‫ﺟﺎ ‪ s2‬ﺍﺳﺖ( ‪ – 2‬ﮐﺎﺭﺍﮐﺘﺮ ﺁﻏﺎﺯﻳﻦ ﺯﻳﺮﺭﺷﺘﻪ )ﺩﺭ ﺍﻳﻦ ﺟﺎ ]‪ s2[4‬ﺍﺳﺖ( ‪ – 3‬ﻃﻮﻝ‬
‫ﺯﻳﺮﺭﺷﺘﻪ )ﺩﺭ ﺍﻳﻦ ﺟﺎ ‪ 2‬ﺍﺳﺖ(‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪282‬‬

‫ﻭﺭﻭﺩﻱ ﻗﺎﻟﺐﺑﻨﺪﻱ ﺷﺪﻩ ﺑﺎ ‪string‬ﻫﺎ ﻣﺜﻞ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻣﻌﻤﻮﻟﻲ ﺭﻓﺘﺎﺭ‬


‫ﻣﻲﮐﻨﺪ‪ .‬ﻳﻌﻨﻲ ﻫﻨﮕﺎﻡ ﻭﺍﺭﺩ ﮐﺮﺩﻥ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﺩﺭﻳﺎﻓﺘﻲ‪ ،‬ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺭﺍ ﻧﺎﺩﻳﺪﻩ‬
‫ﮔﺮﻓﺘﻪ ﻭ ﺣﺬﻑ ﻣﻲﮐﻨﺪ ﻭ ﻫﻤﻴﻦ ﮐﻪ ﺑﻌﺪ ﺍﺯ ﮐﻠﻢۀ ﺟﺎﺭﻱ ﺑﻪ ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺑﺮﺳﺪ‪،‬‬
‫ﺩﺭﻳﺎﻓﺖ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﺩﻫﺪ‪string .‬ﻫﺎ ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )(‪getline‬‬
‫ﻣﺨﺼﻮﺹ ﺑﻪ ﺧﻮﺩﺷﺎﻥ ﺩﺍﺭﻧﺪ ﮐﻪ ﺑﺴﻴﺎﺭ ﺷﺒﻴﻪ ﺗﺎﺑﻊ )(‪ cin.getline‬ﺭﻓﺘﺎﺭ ﻣﻲﮐﻨﺪ‪:‬‬
‫;"‪string s = "ABCDEFG‬‬
‫;)‪getline(cin, s‬‬ ‫‪// reads the entireline of characters into s‬‬

‫ﻫﻤﭽﻨﻴﻦ ﺩﺭﻭﻥ ‪string‬ﻫﺎ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﻋﻤﻠﮕﺮ ﺯﻳﺮﻧﻮﻳﺲ ﻣﺜﻞ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ‬


‫ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪:‬‬
‫;]‪char c = s[2‬‬ ‫‪// assigns 'C' to c‬‬
‫;'*' = ]‪s[4‬‬ ‫"‪// changes s to "ABCD*FG‬‬

‫ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﺍﻳﻦ ﺟﺎ ﻫﻢ ﺍﻳﻨﺪﮐﺲ ﺍﺯ ﺻﻔﺮ ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ‪.‬‬


‫ﺍﺷﻴﺎﻱ ﻧﻮﻉ ‪ string‬ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ ﺯﻳﺮ ﺑﻪ ﻧﻮﻉ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ‬
‫ﺗﺒﺪﻳﻞ ﮐﻨﻴﻢ‪:‬‬
‫;)(‪const char* cs = s.c_str‬‬ ‫‪// converts s into the C-string cs‬‬

‫ﮐﻼﺱ ‪ string‬ﺩﺭ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‪ ،‬ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )(‪ length‬ﺩﺍﺭﺩ ﮐﻪ ﺑﺎ‬


‫ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺗﻌﺪﺍﺩ ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻣﻮﺟﻮﺩ ﺩﺭ ﻳﮏ ﺷﻲﺀ ‪ string‬ﺭﺍ ﺑﻴﺎﺑﻴﻢ‪ .‬ﺍﻳﻦ‬
‫ﺗﺎﺑﻊ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ‪:‬‬
‫;‪cout << s.length() << endl‬‬
‫"‪// prints 7 for the string s = = "ABCD*FG‬‬

‫ﺩﺭ ‪ C++‬ﻣﻲﺗﻮﺍﻧﻴﻢ ‪string‬ﻫﺎ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﺍﺑﻄﻪﺍﻱ ﺑﺎ ﻫﻢ ﻣﻘﺎﻳﺴﻪ‬


‫ﮐﻨﻴﻢ‪ .‬ﺩﺭﺳﺖ ﺷﺒﻴﻪ ﺍﻧﻮﺍﻉ ﺑﻨﻴﺎﺩﻱ ﺩﻳﮕﺮ‪:‬‬
‫;"‪if (s2 < s5) cout << "s2 lexicographically precedes s5\n‬‬
‫)‪while (s4 = = s3‬‬ ‫‪// ...‬‬

‫ﺑﻪ ﺭﺍﺣﺘﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ‪ +‬ﻭ =‪ +‬ﻣﺤﺘﻮﻳﺎﺕ ‪string‬ﻫﺎ ﺭﺍ ﺑﻪ‬


‫ﻳﮑﺪﻳﮕﺮ ﭘﻴﻮﻧﺪ ﺑﺰﻧﻴﻢ ﻳﺎ ﺑﺎ ﻫﻢ ﺗﺮﮐﻴﺐ ﮐﻨﻴﻢ‪:‬‬
‫‪283‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫;"‪string s6 = s + "HIJK‬‬ ‫"‪// changes s6 to "ABCD*FGHIJK‬‬


‫;‪s2 += s5‬‬ ‫"‪// changes s2 to "PNU UniversityUn‬‬

‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﺎﺑﻊ )(‪ substr‬ﻳﮏ ﺯﻳﺮﺭﺷﺘﻪ ﺭﺍ ﺍﺯ ﺩﺭﻭﻥ ﻳﮏ ‪string‬‬


‫ﺍﺳﺘﺨﺮﺍﺝ ﮐﻨﻴﻢ‪:‬‬
‫;)‪s4 = s6.substr(5,3‬‬ ‫"‪// changes s4 to "FGH‬‬

‫ﺗﻮﺍﺑﻊ )(‪ erase‬ﻭ )(‪ replace‬ﺑﺨﺸﻲ ﺍﺯ ﻣﺤﺘﻮﻳﺎﺕ ﺩﺭﻭﻥ ﻳﮏ ‪ string‬ﺭﺍ‬


‫ﺣﺬﻑ ﮐﺮﺩﻩ ﻳﺎ ﺭﻭﻧﻮﻳﺴﻲ ﻣﻲﮐﻨﻨﺪ‪:‬‬
‫;)‪s6.erase(4, 2‬‬ ‫"‪// changes s6 to "ABCDGHIJK‬‬
‫;)"‪s6.replace(5, 2, "xyz‬‬ ‫"‪// changes s6 to "ABCDGxyzJK‬‬

‫ﺗﺎﺑﻊ )(‪ 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‬‬

‫ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥ ﺑﺎﻳﺪ ﺍﺯ ﻗﻮﺍﻧﻴﻦ ﮐﻼﺱﻫﺎ ﭘﻴﺮﻭﻱ ﮐﻨﻴﻢ‪ .‬ﻣﻮﺿﻮﻉ ﮐﻼﺱﻫﺎ ﺭﺍ ﺩﺭ ﻓﺼﻞﻫﺎﻱ ﺁﺗﻲ‬
‫ﺑﻪ ﺩﻗﺖ ﺑﺮﺭﺳﻲ ﻣﻲﻧﻤﺎﻳﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐22‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻧﻮﻉ ‪string‬‬


‫ﮐﺪ ﺯﻳﺮ ﻳﮏ ﻣﺠﻤﻮﻋﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ ﻣﻲﮔﻴﺮﺩ ﻭ ﺳﭙﺲ ﺑﻌﺪ ﺍﺯ ﻫﺮ ﮐﺎﺭﺍﮐﺘﺮ‬
‫"‪ "E‬ﻳﮏ ﻋﻼﻣﺖ ﻭﻳﺮﮔﻮﻝ '‪ ',‬ﺍﺿﺎﻓﻪ ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﻣﺜﻼ ﺍﮔﺮ ﻋﺒﺎﺭﺕ‬
‫"‪"The SOFTWARE MOVEMENT is began‬‬
‫ﻭﺍﺭﺩ ﺷﻮﺩ‪ ،‬ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﺁﻥ ﺭﺍ ﺑﻪ ﺟﻤﻞۀ ﺯﻳﺮ ﺗﺒﺪﻳﻞ ﻣﻲﮐﻨﺪ‪:‬‬
‫‪The SOFTWARE, MOVE,ME,NT is began‬‬
‫ﻣﺘﻦ ﺑﺮﻧﺎﻣﻪ ﺍﻳﻦ ﭼﻨﻴﻦ ﺍﺳﺖ‪:‬‬
‫;‪string word‬‬
‫;‪int k‬‬
‫)‪while (cin >> word‬‬
‫;‪{ k = word.find("E") + 1‬‬
‫))(‪if (k < word.length‬‬
‫;)"‪word.relace(k, 0, ",‬‬
‫;' ' << ‪cout << word‬‬
‫}‬

‫ﺣﻠﻖۀ ‪ 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‬‬

‫ﻃﺒﻖ ﮐﺪﻫﺎﻱ ﻓﻮﻕ‪ readfile ،‬ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﺩﺍﺩﻩﻫﺎ ﺭﺍ ﺍﺯ ﻓﺎﻳﻠﻲ ﺑﻪ ﻧﺎﻡ‬


‫‪ INPUT.TXT‬ﻣﻲﺧﻮﺍﻧﺪ ﻭ ‪ writefile‬ﻧﻴﺰ ﻋﻨﺼﺮﻱ ﺍﺳﺖ ﮐﻪ ﺍﻃﻼﻋﺎﺗﻲ ﺭﺍ ﺩﺭ ﻓﺎﻳﻠﻲ‬
‫ﺑﻪ ﻧﺎﻡ ‪ OUTPUT.TXT‬ﻣﻲﻧﻮﻳﺴﺪ‪ .‬ﺍﮐﻨﻮﻥ ﻣﻲﺗﻮﺍﻥ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ >> ﺩﺍﺩﻩﻫﺎ ﺭﺍ ﺑﻪ‬
‫ﺩﺭﻭﻥ ‪ readfile‬ﺧﻮﺍﻧﺪ ﻭ ﺑﺎ ﻋﻤﻠﮕﺮ << ﺍﻃﻼﻋﺎﺕ ﺭﺍ ﺩﺭﻭﻥ ‪ writefile‬ﻧﻮﺷﺖ‪.‬‬
‫ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﺗﻮﺟﻪ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐23‬ﻳﮏ ﺩﻓﺘﺮ ﺗﻠﻔﻦ‬


‫ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﭼﻨﺪ ﻧﺎﻡ ﻭ ﺗﻠﻔﻦ ﻣﺮﺑﻮﻁ ﺑﻪ ﻫﺮ ﻳﮏ ﺭﺍ ﺑﻪ ﺗﺮﺗﻴﺐ ﺍﺯ ﮐﺎﺭﺑﺮ ﺩﺭﻳﺎﻓﺖ ﮐﺮﺩﻩ‬
‫ﻭ ﺩﺭ ﻓﺎﻳﻠﻲ ﺑﻪ ﻧﺎﻡ ‪ PHONE.TXT‬ﺫﺧﻴﺮﻩ ﻣﻲﮐﻨﺪ‪ .‬ﮐﺎﺭﺑﺮ ﺑﺮﺍﻱ ﭘﺎﻳﺎﻥ ﺩﺍﺩﻥ ﺑﻪ ﻭﺭﻭﺩﻱ ﺑﺎﻳﺪ‬
‫ﻋﺪﺩ ‪ 0‬ﺭﺍ ﺗﺎﻳﭗ ﮐﻨﺪ‪.‬‬
‫>‪#include <fstream‬‬
‫>‪#include <iostream‬‬
‫;‪using namespace std‬‬
‫)(‪int main‬‬
‫;)"‪{ ofstream phonefile("PHONE.TXT‬‬
‫;‪long number‬‬
‫;‪string name‬‬
‫;" ‪cout << "Enter a number for each name. (0 for quit):‬‬
‫) ; ; ( ‪for‬‬
‫;" ‪{ cout << "Number:‬‬
‫;‪cin >> number‬‬
‫;‪if (number == 0) break‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪286‬‬

‫;' ' << ‪phonefile << number‬‬


‫;" ‪cout << "Name:‬‬
‫;‪cin >> name‬‬
‫;' ' << ‪phonefile << name‬‬
‫;‪cout << endl‬‬
‫}‬
‫}‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ‪ ،‬ﺟﺮﻳﺎﻧﻲ ﺑﻪ ﻧﺎﻡ ‪ phonefile‬ﺍﺯ ﻧﻮﻉ ‪ ofstream‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ‪.‬‬


‫ﺍﻳﻦ ﺟﺮﻳﺎﻥ‪ ،‬ﻓﺎﻳﻞ ‪ PHONE.TXT‬ﺭﺍ ﻣﺪﻳﺮﻳﺖ ﻣﻲﮐﻨﺪ‪ .‬ﭼﻮﻥ ﺟﺮﻳﺎﻥ ﻣﺬﮐﻮﺭ ﺍﺯ ﻧﻮﻉ‬
‫‪ ofstream‬ﺍﺳﺖ‪ ،‬ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﺍﻃﻼﻋﺎﺗﻲ ﺩﺭﻭﻥ ﻓﺎﻳﻞ ‪ PHONE.TXT‬ﺑﻨﻮﻳﺴﺪ‪ .‬ﻳﮏ‬
‫ﻣﺘﻐﻴﺮ ﺻﺤﻴﺢ ﺑﻪ ﻧﺎﻡ ‪ number‬ﻭ ﻳﮏ ﻣﺘﻐﻴﺮ ﺭﺷﺘﻪﺍﻱ ﺑﻪ ﻧﺎﻡ ‪ name‬ﺷﻤﺎﺭﻩ ﺗﻠﻔﻦ ﻭ ﻧﺎﻡ‬
‫ﻣﺮﺑﻮﻃﻪ ﺭﺍ ﺍﺯ ﻭﺭﻭﺩﻱ ﻣﻲﮔﻴﺮﻧﺪ‪ .‬ﻫﻢۀ ﮐﺎﺭﻫﺎ ﺩﺭﻭﻥ ﺣﻠﻖۀ ‪ for‬ﺍﻧﺠﺎﻡ ﻣﻲﺷﻮﺩ‪ .‬ﺳﺎﺧﺘﺎﺭ ﺍﻳﻦ‬
‫ﺣﻠﻘﻪ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺣﻠﻖۀ ﺑﻲﺍﻧﺘﻬﺎ ﺍﺳﺖ ﺯﻳﺮﺍ ﺣﻠﻘﻪ ﺍﺯ ﺩﺭﻭﻥ ﮐﻨﺘﺮﻝ ﻣﻲﺷﻮﺩ ) ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬
‫ﺩﺳﺘﻮﺭ ‪ .(break‬ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﮐﺎﺭﺑﺮ ﻋﺪﺩ ﺻﻔﺮ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﺷﻤﺎﺭﻩ ﺗﻠﻔﻦ ﻭﺍﺭﺩ ﮐﻨﺪ‪ ،‬ﺣﻠﻘﻪ‬
‫ﻓﻮﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺩﺭ ﻏﻴﺮ ﺍﻳﻦ ﺻﻮﺭﺕ‪ ،‬ﺷﻤﺎﺭۀ ﻣﺬﮐﻮﺭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ <<‬
‫ﺑﻪ ﺟﺮﻳﺎﻥ ‪ phonefile‬ﻓﺮﺳﺘﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ﺍﻳﻦ ﺟﺮﻳﺎﻥ‪ ،‬ﺷﻤﺎﺭﻩ ﺭﺍ ﺩﺭﻭﻥ ﻓﺎﻳﻞ ﻣﻲﻧﻮﻳﺴﺪ‪.‬‬
‫ﺳﭙﺲ ﻧﺎﻡ ﺻﺎﺣﺐ ﺷﻤﺎﺭﻩ ﭘﺮﺳﻴﺪﻩ ﻣﻲﺷﻮﺩ ﻭ ﺁﻥ ﻫﻢ ﺑﻪ ﻫﻤﻴﻦ ﺗﺮﺗﻴﺐ ﺑﻪ ﺟﺮﻳﺎﻥ‬
‫‪ phonefile‬ﻓﺮﺳﺘﺎﺩﻩ ﺷﺪﻩ ﻭ ﺩﺭ ﻧﺘﻴﺠﻪ ﺩﺭﻭﻥ ﻓﺎﻳﻞ ﻧﻮﺷﺘﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﻫﺮ‬
‫ﻣﻘﺪﺍﺭﻱ ﮐﻪ ﺩﺭﻭﻥ ﻓﺎﻳﻞ ﻧﻮﺷﺘﻪ ﻣﻲﺷﻮﺩ‪ ،‬ﻳﮏ ﮐﺎﺭﺍﮐﺘﺮ ﻓﻀﺎﻱ ﺧﺎﻟﻲ ﻧﻴﺰ ﭘﺲ ﺍﺯ ﺁﻥ ﺩﺭ ﻓﺎﻳﻞ‬
‫ﺩﺭﺝ ﻣﻲﺷﻮﺩ‪ .‬ﺍﮔﺮ ﺍﻳﻦ ﮐﺎﺭ ﺭﺍ ﻧﮑﻨﻴﻢ‪ ،‬ﻫﻢۀ ﻧﺎﻡﻫﺎ ﻭ ﺷﻤﺎﺭﻩﻫﺎ ﺑﺪﻭﻥ ﻓﺎﺻﻠﻪ ﻭ ﭘﻴﻮﺳﺘﻪ ﻧﻮﺷﺘﻪ‬
‫ﻣﻲﺷﻮﻧﺪ ﻭ ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ ﺧﻮﺍﻧﺪﻥ ﻓﺎﻳﻞ ﺣﺎﺻﻞ ﺑﺴﻴﺎﺭ ﻣﺸﮑﻞﺗﺮ ﺧﻮﺍﻫﺪ ﺑﻮﺩ‪.‬‬
‫ﻣﺜﺎﻝ ﺑﺎﻻ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ << ﺑﺎ ﺟﺮﻳﺎﻥﻫﺎ ﻣﺜﻞ ‪ cout‬ﺭﻓﺘﺎﺭ‬
‫ﻣﻲﮐﻨﺪ‪ .‬ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ >> ﻧﻴﺰ ﻫﻤﻴﻦ ﻃﻮﺭ ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ‬
‫ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺳﺎﺩﮔﻲ ﺍﻃﻼﻋﺎﺕ ﺩﺭﻭﻥ ﻳﮏ ﻓﺎﻳﻞ ﺭﺍ ﺧﻮﺍﻧﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 8‐24‬ﺟﺴﺘﺠﻮﻱ ﻳﮏ ﺷﻤﺎﺭﻩ ﺩﺭ ﺩﻓﺘﺮ ﺗﻠﻔﻦ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﻓﺎﻳﻞ ﺗﻮﻟﻴﺪ ﺷﺪﻩ ﺗﻮﺳﻂ ﺑﺮﻧﺎﻡۀ ﻗﺒﻞ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﺩ ﻭ ﺩﺭﻭﻥ ﺁﻥ ﺑﻪ‬
‫ﺩﻧﺒﺎﻝ ﻳﮏ ﺷﻤﺎﺭﻩ ﺗﻠﻔﻦ ﻣﻲﮔﺮﺩﺩ‪:‬‬
‫>‪#include <fstream‬‬
‫‪287‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫>‪#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‬‬
‫}‬

‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺑﺎﻻ ﻫﻢ ﺟﺮﻳﺎﻥ ‪ phonefile‬ﺑﺮﺍﻱ ﻣﺪﻳﺮﻳﺖ ﻓﺎﻳﻞ ‪ PHONE.TXT‬ﻣﻨﻈﻮﺭ ﺷﺪﻩ‬


‫ﺍﺳﺖ ﻭﻟﻲ ﺍﻳﻦ ﺑﺎﺭ ﺟﺮﻳﺎﻥ ﻣﺬﮐﻮﺭ ﺍﺯ ﻧﻮﻉ ‪ istream‬ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﻓﺎﻳﻞ ﺭﺍ‬
‫ﺑﺨﻮﺍﻧﺪ‪ .‬ﻋﻤﻞ ﺧﻮﺍﻧﺪﻥ ﺍﻃﻼﻋﺎﺕ ﻓﺎﻳﻞ‪ ،‬ﺩﺭﻭﻥ ﺣﻠﻖۀ ‪ while‬ﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺑﺨﺶ‬
‫ﮐﻨﺘﺮﻟﻲ ﺍﻳﻦ ﺣﻠﻘﻪ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﻧﻮﺷﺘﻪ ﺷﺪﻩ‪:‬‬
‫)‪while (phonefile >> number‬‬

‫ﺍﻳﻦ ﮐﺪ ﺩﻭ ﻭﻇﻴﻔﻪ ﺭﺍ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ‪ :‬ﺍﻭﻝ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﻋﺪﺩ ﺭﺍ ﺍﺯ ﺩﺭﻭﻥ ﺟﺮﻳﺎﻥ‬


‫‪ phonefile‬ﻣﻲﺧﻮﺍﻧﺪ ﻭ ﺁﻥ ﺭﺍ ﺩﺭﻭﻥ ﻣﺘﻐﻴﺮ ‪ number‬ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﻭ ﺩﻭﻡ ﺍﻳﻦ ﮐﻪ ﺍﮔﺮ‬
‫ﻋﻤﻞ ﺧﻮﺍﻧﺪﻥ ﻣﻮﻓﻘﻴﺖﺁﻣﻴﺰ ﺑﻮﺩ‪ ،‬ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﻭ ﺩﺭ ﻏﻴﺮ ﺍﻳﻦ ﺻﻮﺭﺕ ﺣﻠﻘﻪ ﺧﺎﺗﻤﻪ‬
‫ﻣﻲﭘﺬﻳﺮﺩ‪ .‬ﻣﺰﻳﺖ ﺍﻳﻦ ﺷﮑﻞ ﺧﻮﺍﻧﺪﻥ ﺩﺭ ﺁﻥ ﺍﺳﺖ ﮐﻪ ﺩﻳﮕﺮ ﻻﺯﻡ ﻧﻴﺴﺖ ﻧﮕﺮﺍﻥ ﺑﺎﺷﻴﻢ ﮐﻪ ﺁﻳﺎ‬
‫ﺑﻪ ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ ﺭﺳﻴﺪﻩﺍﻳﻢ ﻳﺎ ﻧﻪ‪ .‬ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ﻓﺎﻳﻞ ﺑﺮﺳﻴﻢ‪ ،‬ﻋﺒﺎﺭﺕ‬
‫‪ phonefile>>number‬ﺑﻪ ﻋﻨﻮﺍﻥ ﻧﺎﺩﺭﺳﺖ ﺗﻔﺴﻴﺮ ﻣﻲﺷﻮﺩ ﻭ ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺣﻠﻘﻪ‬
‫ﺧﺎﺗﻤﻪ ﻣﻲﻳﺎﺑﺪ‪ .‬ﺍﮔﺮ ﻋﻤﻞ ﺧﻮﺍﻧﺪﻥ ﺑﻪ ﺍﻳﻦ ﻃﺮﻳﻖ ﺑﺮﺭﺳﻲ ﻧﻤﻲﺷﺪ‪ ،‬ﻣﺠﺒﻮﺭ ﻣﻲﺷﺪﻳﻢ ﺩﺭ ﺟﺎﻱ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪288‬‬

‫ﺩﻳﮕﺮ ﻭ ﺑﻪ ﺷﮑﻞ ﺩﻳﮕﺮﻱ ﻣﺮﺍﻗﺒﺖ ﮐﻨﻴﻢ ﮐﻪ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ﻓﺎﻳﻞ ﺭﺳﻴﺪﻩﺍﻳﻢ ﻳﺎ ﺧﻴﺮ‪ .‬ﺍﮔﺮ ﺍﻳﻦ‬
‫ﻣﺮﺍﻗﺒﺖ ﺻﻮﺭﺕ ﻧﮕﻴﺮﺩ ﻭ ﻭﻗﺘﻲ ﺑﻪ ﺍﻧﺘﻬﺎﻱ ﻓﺎﻳﻞ ﻣﻮﺭﺩ ﻧﻈﺮ ﺭﺳﻴﺪﻳﻢ ﺩﻭﺑﺎﺭﻩ ﺗﻼﺵ ﮐﻨﻴﻢ ﮐﻪ‬
‫ﺩﺍﺩﻩﻫﺎﻱ ﺑﻴﺸﺘﺮﻱ ﺭﺍ ﺍﺯ ﻓﺎﻳﻞ ﺑﺨﻮﺍﻧﻴﻢ‪ ،‬ﺑﺎ ﺧﻄﺎ ﻣﻮﺍﺟﻪ ﻣﻲﺷﻮﻳﻢ ﻭ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﺷﮑﻞ ﻧﺎﺧﻮﺍﺳﺘﻪ‬
‫ﭘﺎﻳﺎﻥ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺗﻮﺟﻪ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻠﻲ‪ ،‬ﻫﻨﮕﺎﻡ ﻧﻮﺷﺘﻦ ﻧﺎﻡﻫﺎ ﻭ ﺷﻤﺎﺭﻩﻫﺎ‪ ،‬ﻳﮏ‬
‫ﻓﺎﺻﻞۀ ﺧﺎﻟﻲ ' ' ﻧﻴﺰ ﺑﻴﻦ ﺁﻥ ﻫﺎ ﺩﺭﺝ ﮐﺮﺩﻳﻢ ﺍﻣﺎ ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ ﻫﻨﮕﺎﻡ ﺧﻮﺍﻧﺪﻥ ﺍﻃﻼﻋﺎﺕ‪،‬‬
‫ﺗﻮﺟﻬﻲ ﺑﻪ ﺍﻳﻦ ﻓﺎﺻﻠﻪﻫﺎﻱ ﺍﺿﺎﻓﻲ ﻧﮑﺮﺩﻳﻢ‪ .‬ﺑﻪ ﺍﻳﻦ ﺩﻟﻴﻞ ﮐﻪ ﺑﺮﺍﻱ ﺧﻮﺍﻧﺪﻥ ﺍﻃﻼﻋﺎﺕ ﺍﺯ‬
‫ﻋﻤﻠﮕﺮ >> ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ ﻭ ﻫﻤﺎﻥ ﻃﻮﺭ ﮐﻪ ﺩﺭ ﺍﺑﺘﺪﺍﻱ ﻓﺼﻞ ﮔﻔﺘﻴﻢ‪ ،‬ﺍﻳﻦ ﻋﻤﻠﮕﺮ‬
‫ﮐﺎﺭﺍﮐﺘﺮﻫﺎﻱ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺭﺍ ﻧﺎﺩﻳﺪﻩ ﻣﻲﮔﻴﺮﺩ‪.‬‬
‫ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺍﻃﻼﻋﺎﺗﻲ ﺭﺍ ﺍﺯ ﺩﺭﻭﻥ ﻓﺎﻳﻞ ﺑﻪ ﺻﻮﺭﺕ ﮐﺎﺭﺍﮐﺘﺮ ﺑﻪ ﮐﺎﺭﺍﮐﺘﺮ ﺑﺨﻮﺍﻧﻴﻢ‪،‬‬
‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﺗﺎﺑﻊ )(‪ 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‬‬

‫ﺍﻟﻒ ‐ ﻛﺪﺍﻡ ﻳﻚ ﺍﺯ ﺁﻥﻫﺎ ﻳﻚ ﺍﻋﻼﻥ ﻣﻌﺘﺒﺮ ‪ C++‬ﺑﺮﺍﻱ ﺭﺷﺖۀ ﻛﺎﺭﺍﻛﺘﺮﻱ ﺍﺳﺖ؟‬


‫ﺏ ‐ ﻛﺪﺍﻡ ﻳﻚ ﺍﺯ ﺁﻥﻫﺎ ﻳﻚ ﺍﻋﻼﻥ ﻣﻌﺘﺒﺮ ‪ C++‬ﺑﺮﺍﻱ ﺭﺷﺖۀ ﻛﺎﺭﺍﻛﺘﺮﻱ ﺑﻪ ﻃﻮﻝ ‪ 5‬ﺍﺳﺖ‬
‫ﻛﻪ ﺩﺭ ﺯﻣﺎﻥ ﻛﺎﻣﭙﺎﻳﻞ ﺁﺩﺭﺱﺩﻫﻲ ﺷﺪﻩ ﻭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ "‪ "Hello‬ﺑﻪ ﺁﻥ ﺍﺧﺘﺼﺎﺹ ﻣﻲﻳﺎﺑﺪ؟‬
‫ﺝ ‐ ﻛﺪﺍﻡ ﻳﻚ ﺍﺯ ﺁﻥﻫﺎ ﻳﻚ ﺍﻋﻼﻥ ﻣﻌﺘﺒﺮ ‪ C++‬ﺑﺮﺍﻱ ﺭﺷﺖۀ ﮐﺎﺭﺍﻛﺘﺮﻱ ﺑﻪ ﻃﻮﻝ ‪ 5‬ﺍﺳﺖ‬
‫ﻛﻪ ﺩﺭ ﺯﻣﺎﻥ ﺍﺟﺮﺍ ﺁﺩﺭﺱﺩﻫﻲ ﺷﺪﻩ ﻭ ﻣﻘﺪﺍﺭ ﺍﻭﻟﻲۀ "‪ "Hello‬ﺑﻪ ﺁﻥ ﺍﺧﺘﺼﺎﺹ ﻣﻲﻳﺎﺑﺪ؟‬
‫ﺩ ‐ ﻛﺪﺍﻡ ﻳﻚ ﺍﺯ ﺁﻥﻫﺎ ﻳﻚ ﺍﻋﻼﻥ ﻣﻌﺘﺒﺮ ‪ C++‬ﺑﺮﺍﻱ ﺭﺷﺖۀ ﻛﺎﺭﺍﻛﺘﺮﻱ ﺑﻪ ﻋﻨﻮﺍﻥ ﭘﺎﺭﺍﻣﺘﺮ‬
‫ﻳﮏ ﺗﺎﺑﻊ ﺍﺳﺖ؟‬
‫‪ ‐2‬ﭼﻪ ﺍﺷﺘﺒﺎﻫﻲ ﺩﺭ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺩﺳﺘﻮﺭ ﺯﻳﺮ ﺍﺳﺖ ﺍﮔﺮ ﺑﺨﻮﺍﻫﻴﻢ ﮐﺪ ﺯﻳﺮ‪ ،‬ﻭﺭﻭﺩﻱ‬
‫"‪ "Hello, word‬ﺭﺍ ﺑﻪ ﺩﺭﻭﻥ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪ s‬ﺑﺨﻮﺍﻧﺪ؟‬
‫;‪cin >> s‬‬

‫‪ ‐3‬ﻛﺪ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ؟‬


‫;"‪char s[] = "123 W. 42nd St., NY, NY 10020-1095‬‬
‫;‪int count = 0‬‬
‫)‪for (char* p = s; *p; p++‬‬
‫;‪if (isupper(*p)) ++ count‬‬
‫;‪cout << count << endl‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 294

‫‐ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ؟‬4


char s[] = "123 W. 42nd St., NY, NY 10020-1095";
for (char* p = s; *p; p++)
if (isupper(*p)) *p = tolower(*p);
cout << s << endl;

‫‐ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ؟‬5


char s[] = "123 W. 42nd St., NY, NY 10020-1095";
for (char* p = s; *p; p++)
if (isupper(*p)) (*p)++;
cout << s << endl;

‫‐ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ؟‬6


char s[] = "123 W. 42nd St., NY, NY 10020-1095";
int count = 0;
for (char* p = s; *p; p++)
if (ispunct(*p)) ++ count;
cout << count << endl;

‫‐ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ؟‬7


char s[] = "123 W. 42nd St., NY, NY 10020-1095";
for (char* p = s; *p; p++)
if (ispunct(*p)) *(p-1) = tolower(*p);
cout << s << endl;

‫ ﺑﺎﺷﻨﺪ ﺁﻧﮕﺎﻩ ﺩﻭ ﺩﺳﺘﻮﺭ ﺯﻳﺮ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﻫﻢ ﺩﺍﺭﻧﺪ؟‬char* ‫ ﺍﺯ ﻧﻮﻉ‬s2 ‫ ﻭ‬s1 ‫‐ ﺍﮔﺮ‬8


char* s1 = s2;
strcpy(s1,s2);

"Hayes" ‫ ﺷﺎﻣﻞ ﺭﺷﺖۀ‬last ‫"ﻭ‬Rutherford" ‫ ﺷﺎﻣﻞ ﺭﺷﺖۀ‬first ‫‐ ﺍﮔﺮ‬9


‫ ﺁﻧﮕﺎﻩ ﺗﺎﺛﻴﺮ ﻫﺮ ﻳﻚ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲﻫﺎﻱ ﺯﻳﺮ ﭼﻪ ﺧﻮﺍﻫﺪ ﺑﻮﺩ؟‬،‫ﺑﺎﺷﺪ‬
‫ ‐ ﺍﻟﻒ‬int n = strlen(first);
‫ ‐ ﺏ‬char* s1 = strchr(first, 'r');
‫ ‐ ﭖ‬char* s1 = strrchr(first, 'r');
‫ ‐ ﺕ‬char* s1 = strpbrk(first, "rstuv");
‫ ‐ ﺙ‬strcpy(first, last);
295 ‫ اﺳﺘﺎﻧﺪارد‬C++ ‫ رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در‬/ ‫ﻓﺼﻞ هﺸﺘﻢ‬

‫ ‐ ﺝ‬strncpy(first, last, 3);


‫ ‐ ﭺ‬strcat(first, last);
‫ ‐ ﺡ‬strncat(first, last, 3);
‫ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ؟‬n ‫‐ ﻫﺮ ﻳﮏ ﺍﺯ ﺟﺎﻳﮕﺰﻳﻨﻲﻫﺎﻱ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﺭﺍ ﺩﺭﻭﻥ‬10
‫ ‐ ﺍﻟﻒ‬int n = strspn("abecedarian","abcde");
‫ ‐ ﺏ‬int n = strspn("beefeater","abcdef");
‫ ‐ ﭖ‬int n = strspn("baccalaureate","abc");
‫ ‐ ﺕ‬int n = strcspn("baccalaureate","rstuv");
‫‐ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ؟‬11
char* s1 = "ABCDE";
char* s2 = "ABC";
if (strcmp(s1,s2) < 0) cout << s1 << " < " << s2 << endl;
else cout << s1 << " >= " << s2 << endl;

‫‐ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ؟‬12


char* s1 = "ABCDE";
char* s2 = "ABCE";
if (strcmp(s1,s2) < 0) cout << s1 << " < " << s2 << endl;
else cout << s1 << " >= " << s2 << endl;

‫‐ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ؟‬13


char* s1 = "ABCDE";
char* s2 = "";
if (strcmp(s1,s2) < 0) cout << s1 << " < " << s2 << endl;
else cout << s1 << " >= " << s2 << endl;

‫‐ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﭼﻴﺰﻱ ﭼﺎﭖ ﻣﻲﻛﻨﺪ؟‬14


char* s1 = " ";
char* s2 = "";
if (strcmp(s1,s2) == 0) cout << s1 << " == " << s2 << endl;
else cout << s1 << " != " << s2 << endl;

‫ ﻭ ﻳﻚ ﺭﺷﺘﻪ ﺍﺯ ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺍﺳﺖ؟‬string ‫‐ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﻴﻦ ﻳﻚ ﺭﺷﺘﻪ ﺍﺯ ﻧﻮﻉ‬15


‫‐ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﻴﻦ ﻭﺭﻭﺩﻱ ﻗﺎﻟﺐﺑﻨﺪﻱ ﺷﺪﻩ ﻭ ﻭﺭﻭﺩﻱ ﺑﺪﻭﻥ ﻗﺎﻟﺐﺑﻨﺪﻱ ﺍﺳﺖ؟‬16
‫‐ ﭼﺮﺍ ﻧﻤﻲﺗﻮﺍﻥ ﻓﻀﺎﻱ ﺳﻔﻴﺪ ﺭﺍ ﺑﺎ ﻋﻤﻠﮕﺮ ﺑﺮﻭﻥ ﻛﺸﻲ ﺧﻮﺍﻧﺪ؟‬17
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪296‬‬

‫‪» ‐18‬ﺟﺮﻳﺎﻥ« ﭼﻴﺴﺖ؟‬


‫‪ ‐19‬ﭼﻪ ﭼﻴﺰﻱ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﭘﺮﺩﺍﺯﺵ ﺭﺷﺘﻪﻫﺎ‪ ،‬ﮐﺎﺭ ﺑﺎ ﻓﺎﻳﻞﻫﺎﻱ ﻧﻮﺷﺘﻲ ﻭ ﻓﺎﻳﻞﻫﺎﻱ‬
‫ﺧﻮﺍﻧﺪﻧﻲ ﺩﺭ ‪ C++‬ﺁﺳﺎﻥﺗﺮ ﺍﺯ ‪ C‬ﺑﺎﺷﺪ؟‬

‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪ ‐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‬‬
‫}‬

‫‪ ‐2‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﻳﻚ ﺭﺷﺘﻪ ﺍﺯ ﺍﺳﺎﻣﻲ ﺭﺍ ﺧﻂ ﺑﻪ ﺧﻂ ﺑﺨﻮﺍﻧﺪ ﻭ ﺳﭙﺲ ﺁﻥﻫﺎ ﺭﺍ‬


‫ﭼﺎﭖ ﻛﻨﺪ‪.‬‬
‫‪ ‐3‬ﺗﺎﺑﻌﻲ ﺑﻨﻮﻳﺴﻴﺪ ﮐﻪ ﻳﮏ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺭﺍ ﺑﺪﻭﻥ ﻫﻴﭻ ﮔﻮﻧﻪ ﺭﻭﻧﻮﺷﺘﻲ ﻣﻌﻜﻮﺱ ﻛﻨﺪ‪.‬‬
‫‪ ‐4‬ﻣﺜﺎﻝ ‪ 8‐3‬ﺭﺍ ﻃﻮﺭﻱ ﺗﻐﻴﻴﺮ ﺩﻫﻴﺪ ﻛﻪ ﺍﺯ ﻋﺒﺎﺭﺕ‬
‫)‪while (cin >> word‬‬

‫ﺑﺠﺎﻱ ﻋﺒﺎﺭﺕ‬
‫)‪do..while (*word‬‬

‫ﺍﺳﺘﻔﺎﺩﻩ ﻛﻨﺪ‪.‬‬
‫‪ ‐5‬ﺗﺎﺑﻌﻲ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﺗﻌﺪﺍﺩ ﺗﮑﺮﺍﺭ ﻳﮏ ﻛﺎﺭﺍﻛﺘﺮ ﺩﺍﺩﻩ ﺷﺪﻩ ﺭﺍ ﺩﺭ ﻳﻚ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ‬
‫ﻣﻔﺮﻭﺽ ﺑﺮﮔﺮﺩﺍﻧﺪ‪.‬‬
‫‪ ‐6‬ﮐﺪ ﻫﺮ ﻳﮏ ﺍﺯ ﺗﻮﺍﺑﻊ ﺯﻳﺮ ﺭﺍ ﻧﻮﺷﺘﻪ ﻭ ﺁﺯﻣﺎﻳﺶ ﮐﻨﻴﺪ‪:‬‬
‫)(‪strcpy‬‬ ‫)(‪strncat‬‬ ‫)(‪strchr‬‬
‫‪297‬‬ ‫ﻓﺼﻞ هﺸﺘﻢ ‪ /‬رﺷﺘﻪهﺎی ﮐﺎراﮐﱰی و ﻓﺎﻳﻞهﺎ در ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫)(‪strrchr‬‬ ‫)(‪strstr‬‬ ‫)(‪strncpy‬‬


‫)(‪strcat‬‬ ‫)(‪strcmp‬‬ ‫)(‪strncmp‬‬
‫)(‪strspn‬‬ ‫)(‪strcspn‬‬ ‫)(‪strpbrk‬‬
‫‪ ‐7‬ﺗﺎﺑﻌﻲ ﺑﻨﻮﻳﺴﻴﺪ ﮐﻪ ﺩﺭﻭﻥ ﻳﻚ ﺭﺷﺖۀ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻣﻔﺮﻭﺽ ﺗﻌﺪﺍﺩ ﻛﻠﻤﺎﺗﻲ ﻛﻪ ﺷﺎﻣﻞ ﻳﻚ‬
‫ﻛﺎﺭﺍﻛﺘﺮ ﺧﺎﺹ ﻫﺴﺘﻨﺪ ﺭﺍ ﺑﺮﻣﻲﮔﺮﺩﺍﻧﺪ‪.‬‬
‫‪ ‐8‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﻳﻚ ﺧﻂ ﺍﺯ ﻣﺘﻦ ﺭﺍ ﺧﻮﺍﻧﺪﻩ ﻭ ﺳﭙﺲ ﻫﻢۀ ﺁﻥ ﺧﻂ ﺭﺍ ﺑﺎ ﺣﺮﻭﻑ‬
‫ﻛﻮﭼﻚ ﭼﺎﭖ ﻛﻨﺪ‪.‬‬
‫‪ ‐9‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﻳﻚ ﺧﻂ ﺍﺯ ﻣﺘﻦ ﺭﺍ ﺧﻮﺍﻧﺪﻩ ﻭ ﺳﭙﺲ ﻫﻢۀ ﺁﻥ ﺧﻂ ﺭﺍ ﺑﺎ ﺣﺬﻑ‬
‫ﺟﺎﻫﺎﻱ ﺧﺎﻟﻲ ﺁﻥ ﭼﺎﭖ ﻛﻨﺪ‪.‬‬
‫‪ ‐10‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﻳﻚ ﺧﻂ ﺍﺯ ﻣﺘﻦ ﺭﺍ ﺧﻮﺍﻧﺪﻩ ﻭ ﺳﭙﺲ ﻫﻢۀ ﺁﻥ ﺧﻂ ﺭﺍ ﻫﻤﺮﺍﻩ ﺑﺎ‬
‫ﺗﻌﺪﺍﺩ ﻛﻠﻤﺎﺗﻲ ﻛﻪ ﺩﺭ ﺁﻥ ﺧﻂ ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﭼﺎﭖ ﻛﻨﺪ‪.‬‬
‫‪ ‐11‬ﺑﺮﻧﺎﻣﻪﺍﻱ ﺑﻨﻮﻳﺴﻴﺪ ﻛﻪ ﻳﻚ ﺧﻂ ﺍﺯ ﻣﺘﻦ ﺭﺍ ﺧﻮﺍﻧﺪﻩ ﻭ ﺳﭙﺲ ﺗﺮﺗﻴﺐ ﻛﻠﻤﺎﺕ ﺭﺍ ﺑﻪ ﻃﻮﺭ‬
‫ﻣﻌﻜﻮﺱ ﭼﺎﭖ ﻛﻨﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺑﺮﺍﻱ ﻭﺭﻭﺩﻱ ‪ today is Tuesday‬ﺧﺮﻭﺟﻲ‬
‫‪ Tuesday is today‬ﺭﺍ ﺗﻮﻟﻴﺪ ﻛﻨﺪ‪.‬‬
‫‪ ‐12‬ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ ﻛﻪ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﻋﻤﻠﻲ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ؟‬
‫;"‪char cs1[] = "ABCDEFGHIJ‬‬
‫;"‪vhar cs2[] = "ABCDEFGH‬‬
‫;‪cout << cs2 << endl‬‬
‫;‪cout << strlen(cs2) << endl‬‬
‫;'‪cs2[4] = 'X‬‬
‫<< ‪if (strcmp(cs1, cs2) < 0) cout << cs1 << " < " << cs2‬‬
‫;‪endl‬‬
‫;‪else cout << cs1 << " >= " << cs2 << endl‬‬
‫;]‪char buffer[80‬‬
‫;)‪strcpy(buffer, cs1‬‬
‫;)‪strcat(buffer, cs2‬‬
‫;)'‪char* cs3 = strchr(buffer, 'G‬‬
‫;‪cout << cs3 << endl‬‬

‫‪ ‐13‬ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ ﻛﻪ ﻛﺪ ﺯﻳﺮ ﭼﻪ ﻋﻤﻠﻲ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ؟‬


‫;"‪string s = "ABCDEFGHIJKLMNOP‬‬
‫;‪cout << s << endl‬‬
‫;‪cout << s.length() << endl‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪298‬‬

‫;'!' = ]‪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,‬‬

‫‪ ‐14‬ﺗﻮﺿﻴﺢ ﺩﻫﻴﺪ ﻛﻪ ﻭﻗﺘﻲ ﻛﺪ‪:‬‬


‫;‪string s‬‬
‫;‪int n‬‬
‫;‪float x‬‬
‫;‪cin >> s >> n >> x >> s‬‬

‫ﺭﻭﻱ ﻫﺮ ﻳﻚ ﺍﺯ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎﻱ ﺯﻳﺮ ﺍﺟﺮﺍ ﻣﻲﺷﻮﺩ ﭼﻪ ﺍﺗﻔﺎﻗﻲ ﻣﻲﺍﻓﺘﺪ؟‬


‫ﺏ ‐ ‪ABC 4567 .89 XYZ‬‬ ‫ﺍﻟﻒ ‐ ‪ABC 456 7.89 XYZ‬‬
‫ﺕ ‐ ‪ABC456 7.8 9 XYZ‬‬ ‫ﭖ ‐ ‪ABC 456 7.8 9XYZ‬‬
‫ﺝ ‐ ‪ABC4 56 7.89XY Z‬‬ ‫ﺙ ‐ ‪ABC456 7 .89 XYZ‬‬
‫ﺡ ‐ ‪AB C 456 7.89XYZ‬‬ ‫ﭺ ‐ ‪AB C456 7.89 XYZ‬‬

‫‪ ‐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 – Object orienting‬‬ ‫‪2 – Class‬‬ ‫‪3 – Object‬‬


‫‪4 – Attribute‬‬ ‫‪5 – Method‬‬ ‫‪6 - Encapsulation‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪302‬‬

‫ﮐﺮﺩﻥ ﺑﺮﻧﺎﻣﻪ ﺭﺍﺣﺖﺗﺮ ﺻﻮﺭﺕ ﻣﻲﮔﻴﺮﺩ ﻭ ﺗﻐﻴﻴﺮ ﺩﺭ ﻳﮏ ﺑﺨﺶ ﺍﺯ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺳﺎﻳﺮ ﺑﺨﺶﻫﺎ ﺭﺍ‬
‫ﺩﭼﺎﺭ ﺍﺧﺘﻼﻝ ﻧﻤﻲﮐﻨﺪ‪ .‬ﻣﺨﻔﻲ ﮐﺮﺩﻥ ﺟﺰﻳﻴﺎﺕ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﮐﻪ ﺑﻪ ﺁﻥ »ﺗﺠﺮﻳﺪ‪ «1‬ﻧﻴﺰ ﻣﻲﮔﻮﻳﻨﺪ‬
‫ﺳﺒﺐ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻣﻨﻴﺖ ﮐﺪ ﺣﻔﻆ ﺷﻮﺩ ﻭ ﺑﺨﺶﻫﺎﻱ ﺑﻲﺍﻫﻤﻴﺖ ﻳﮏ ﻓﺮﺍﻳﻨﺪ ﺍﺯ ﺩﻳﺪ‬
‫ﺍﺳﺘﻔﺎﺩﻩﮐﻨﻨﺪۀ ﺁﻥ ﻣﺨﻔﻲ ﺑﺎﺷﺪ‪ .‬ﺑﻪ ﺑﻴﺎﻥ ﺳﺎﺩﻩﺗﺮ‪ ،‬ﻫﺮ ﺑﺨﺶ ﺍﺯ ﺑﺮﻧﺎﻣﻪ ﺗﻨﻬﺎ ﻣﻲﺗﻮﺍﻧﺪ ﺍﻃﻼﻋﺎﺕ‬
‫ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﺑﺒﻴﻨﺪ ﻭ ﻧﻤﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺍﻃﻼﻋﺎﺕ ﻧﺎﻣﺮﺑﻮﻁ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﻭ ﺁﻥﻫﺎ ﺭﺍ‬
‫ﺩﺳﺖﮐﺎﺭﻱ ﮐﻨﺪ‪ .‬ﺩﺭ ﺑﺮﺧﻲ ﺍﺯ ﮐﺘﺎﺏﻫﺎ ﺍﺯ ﻭﺍﮊۀ »ﮐﭙﺴﻮﻟﻪ ﮐﺮﺩﻥ« ﻳﺎ »ﻣﺤﺼﻮﺭﺳﺎﺯﻱ« ﺑﻪ ﺟﺎﻱ‬
‫ﺑﺴﺘﻪﺑﻨﺪﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‪.‬‬
‫ﺏ‪ .‬ﻭﺭﺍﺛﺖ‪ :2‬ﺩﺭ ﺩﻧﻴﺎﻱ ﻭﺍﻗﻌﻲ‪ ،‬ﻭﺭﺍﺛﺖ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﻳﮏ ﺷﻲ ﻭﻗﺘﻲ ﻣﺘﻮﻟﺪ‬
‫ﻣﻲﺷﻮﺩ‪ ،‬ﺧﺼﻮﺻﻴﺎﺕ ﻭ ﻭﻳﮋﮔﻲﻫﺎﻳﻲ ﺭﺍ ﺍﺯ ﻭﺍﻟﺪ ﺧﻮﺩ ﺑﻪ ﻫﻤﺮﺍﻩ ﺩﺍﺭﺩ ﻫﺮﭼﻨﺪ ﮐﻪ ﺍﻳﻦ ﺷﻲﺀ‬
‫ﺟﺪﻳﺪ ﺑﺎ ﻭﺍﻟﺪﺵ ﺩﺭ ﺑﺮﺧﻲ ﺍﺯ ﺟﺰﻳﻴﺎﺕ ﺗﻔﺎﻭﺕ ﺩﺍﺭﺩ‪ .‬ﺩﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﻧﻴﺰ ﻭﺭﺍﺛﺖ ﺑﻪ ﻫﻤﻴﻦ‬
‫ﻣﻌﻨﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‪ .‬ﻳﻌﻨﻲ ﺍﺯ ﺭﻭﻱ ﻳﮏ ﺷﻲﺀ ﻣﻮﺟﻮﺩ‪ ،‬ﺷﻲﺀ ﺟﺪﻳﺪﻱ ﺳﺎﺧﺘﻪ ﺷﻮﺩ ﮐﻪ‬
‫ﺻﻔﺎﺕ ﻭ ﻣﺘﺪﻫﺎﻱ ﺷﻲﺀ ﻭﺍﻟﺪﺵ ﺭﺍ ﺩﺍﺭﺍ ﺑﻮﺩﻩ ﻭﺍﻟﺒﺘﻪ ﺻﻔﺎﺕ ﻭ ﻣﺘﺪﻫﺎﻱ ﺧﺎﺹ ﺧﻮﺩ ﺭﺍ ﻧﻴﺰ‬
‫ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﺍﻣﺘﻴﺎﺯ ﻭﺭﺍﺛﺖ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﺯ ﮐﺪﻫﺎﻱ ﻣﺸﺘﺮﮎ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﺩ ﻭ ﻋﻼﻭﻩ‬
‫ﺑﺮ ﺍﻳﻦ ﮐﻪ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﮐﺪﻫﺎﻱ ﻗﺒﻠﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﺠﺪﺩ ﮐﺮﺩ‪ ،‬ﺩﺭ ﺯﻣﺎﻥ ﻧﻴﺰ ﺻﺮﻓﻪﺟﻮﻳﻲ ﺷﺪﻩ ﻭ‬
‫ﺍﺳﺘﺤﮑﺎﻡ ﻣﻨﻄﻘﻲ ﺑﺮﻧﺎﻣﻪ ﻫﻢ ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ‪.‬‬
‫ﺝ‪ .‬ﭼﻨﺪ ﺭﻳﺨﺘﻲ‪ :3‬ﮐﻪ ﺑﻪ ﺁﻥ ﭼﻨﺪﺷﮑﻠﻲ ﻫﻢ ﻣﻲﮔﻮﻳﻨﺪ ﺑﻪ ﻣﻌﻨﺎﻱ ﻳﮏ ﭼﻴﺰ ﺑﻮﺩﻥ ﻭ‬
‫ﭼﻨﺪ ﺷﮑﻞ ﺩﺍﺷﺘﻦ ﺍﺳﺖ‪ .‬ﭼﻨﺪﺭﻳﺨﺘﻲ ﺑﻴﺸﺘﺮ ﺩﺭ ﻭﺭﺍﺛﺖ ﻣﻌﻨﺎ ﭘﻴﺪﺍ ﻣﻲﮐﻨﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﮔﺮﭼﻪ‬
‫ﻫﺮ ﻓﺮﺯﻧﺪﻱ ﻣﺜﻞ ﻭﺍﻟﺪﺵ ﺍﺛﺮ ﺍﻧﮕﺸﺖ ﺩﺍﺭﺩ‪ ،‬ﻭﻟﻲ ﺍﺛﺮ ﺍﻧﮕﺸﺖ ﻫﺮ ﺷﺨﺺ ﺑﺎ ﻭﺍﻟﺪﺵ ﻳﺎ ﻫﺮ‬
‫ﺷﺨﺺ ﺩﻳﮕﺮ ﻣﺘﻔﺎﻭﺕ ﺍﺳﺖ‪ .‬ﭘﺲ ﺍﺛﺮ ﺍﻧﮕﺸﺖ ﺩﺭ ﺍﻧﺴﺎﻥﻫﺎ ﭼﻨﺪﺷﮑﻠﻲ ﺩﺍﺭﺩ‪.‬‬
‫ﺩﺭ ﺍﺩﺍﻣﻪ ﺑﻪ ﺷﮑﻞ ﻋﻤﻠﻲ ﺧﻮﺍﻫﻴﻢ ﺩﻳﺪ ﮐﻪ ﭼﮕﻮﻧﻪ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﻔﺎﻫﻴﻢ ﻓﻮﻕ ﺭﺍ ﺩﺭ ﻗﺎﻟﺐ‬
‫ﺑﺮﻧﺎﻣﻪ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﮐﻨﻴﻢ‪.‬‬
‫ﺩﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‪ ،‬ﻳﮏ ﮐﻼﺱ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺁﺭﺍﻳﻪﺍﻱ ﺗﺼﻮﺭ ﮐﺮﺩ ﮐﻪ ﺍﻋﻀﺎﻱ ﺁﻥ ﺍﺯ ﺍﻧﻮﻉ‬
‫ﻣﺨﺘﻠﻒ ﻭ ﻣﺘﻔﺎﻭﺗﻲ ﻫﺴﺘﻨﺪ ﻭ ﻫﻤﭽﻨﻴﻦ ﺗﻮﺍﺑﻊ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻧﻨﺪ ﻋﻀﻮﻱ ﺍﺯ ﺁﻥ ﺁﺭﺍﻳﻪ ﺑﺎﺷﻨﺪ‪ .‬ﻳﮏ‬
‫ﺷﻲ ﻧﻴﺰ ﻣﺘﻐﻴﺮﻱ ﺍﺳﺖ ﮐﻪ ﺍﺯ ﻧﻮﻉ ﻳﮏ ﮐﻼﺱ ﺍﺳﺖ‪ .‬ﺑﻪ ﻃﻮﺭ ﮐﻠﻲ ﻳﮏ ﺷﻲ ﺭﺍ ﻣﻲﺗﻮﺍﻥ‬
‫ﻣﻮﺟﻮﺩﻳﺖ ﻣﺴﺘﻘﻠﻲ ﺗﺼﻮﺭ ﮐﺮﺩ ﮐﻪ ﺩﺍﺩﻩﻫﺎﻱ ﺧﺎﺹ ﺧﻮﺩﺵ ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﮐﻨﺪ ﻭ ﺗﻮﺍﺑﻊ‬

‫‪1 – Abstraction‬‬ ‫‪2 – Inheritance‬‬ ‫‪3 – Polymorphism‬‬


‫‪303‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫ﺧﺎﺹ ﺧﻮﺩﺵ ﺭﺍ ﺩﺍﺭﺩ‪ .‬ﺗﻌﺎﺭﻳﻒ ﮐﻼﺱ ﻣﺸﺨﺺ ﻣﻲﮐﻨﺪ ﺷﻴﺌﻲ ﮐﻪ ﺍﺯ ﺭﻭﻱ ﺁﻥ ﮐﻼﺱ‬
‫ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ ﭼﻪ ﺭﻓﺘﺎﺭﻱ ﺩﺍﺭﺩ‪ .‬ﻭﺍﺿﺢ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻣﻨﻈﻮﺭ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺷﻲﮔﺮﺍﻳﻲ‪ ،‬ﺍﺑﺘﺪﺍ‬
‫ﺑﺎﻳﺪ ﮐﻼﺱﻫﺎﻱ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺭﺍ ﻣﺸﺨﺺ ﻭ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ ‪ .‬ﺳﭙﺲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ‪،‬‬
‫ﺍﺷﻴﺎﻳﻲ ﺍﺯ ﻧﻮﻉ ﺍﻳﻦ ﮐﻼﺱﻫﺎ ﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﻢ‪ .‬ﺑﻘﻲۀ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﺍﻳﻦ ﺍﺷﻴﺎ ﭘﻴﺶ ﻣﻲﺑﺮﻧﺪ‪.‬‬

‫‪ 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‬ﻣﺤﺴﻮﺏ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺗﻔﺎﻭﺕ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﺑﺎ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺩﺭ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ‬

‫‪1 – Function member‬‬ ‫‪2 – Data member‬‬


‫‪3 – Public member‬‬ ‫‪4 – Private member‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪304‬‬

‫ﮐﻼﺱ ﺩﺭ ﺧﺎﺭﺝ ﺍﺯ ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﻫﺴﺘﻨﺪ ﺍﻣﺎ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﻓﻘﻂ ﺩﺭ ﺩﺍﺧﻞ‬
‫ﻫﻤﺎﻥ ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﻫﺴﺘﻨﺪ‪ .‬ﺍﻳﻦ ﻫﻤﺎﻥ ﺧﺎﺻﻴﺘﻲ ﺍﺳﺖ ﮐﻪ »ﻣﺨﻔﻲﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ«‬
‫ﺭﺍ ﻣﻤﮑﻦ ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﺩﺭ ﮐﻼﺱ ﻓﻮﻕ‪ ،‬ﺗﻮﺍﺑﻊ ﺑﻪ ﺷﮑﻞ ‪ public‬ﻭ ﻣﺘﻐﻴﺮﻫﺎ ﺑﻪ ﺻﻮﺭﺕ‬
‫‪ private‬ﻣﺸﺨﺺ ﺷﺪﻩﺍﻧﺪ‪.‬‬
‫ﺣﺎﻝ ﺑﺒﻴﻨﻴﻢ ﮐﻪ ﭼﻄﻮﺭ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﮐﻼﺱﻫﺎ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﻭﺍﻗﻌﻲ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪ .‬ﺑﻪ ﻣﺜﺎﻝ‬
‫ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐1‬ﭘﻴﺎﺩﻩ ﺳﺎﺯﻱ ﻛﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫;)‪void assign(int, int‬‬
‫;)(‪void print‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫)(‪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::assign(int numerator, int denumirator‬‬


‫;‪{ num = numerator‬‬
‫;‪den = denumirator‬‬
‫}‬
‫‪305‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫)(‪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‬ﮐﻪ ﺩﺭ ﺑﺎﻻ ﺍﻋﻼﻥ ﺷﺪ‪ ،‬ﮐﺎﺭﺍﻳﻲ ﺯﻳﺎﺩﻱ ﻧﺪﺍﺭﺩ‪ .‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﻓﺰﻭﺩﻥ‬
‫ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺩﻳﮕﺮﻱ‪ ،‬ﮐﺎﺭﺍﻳﻲ ﺍﻳﻦ ﮐﻼﺱ ﺭﺍ ﺑﻬﺒﻮﺩ ﺩﻫﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐2‬ﺍﻓﺰﻭﺩﻥ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺑﻴﺸﺘﺮ ﺑﻪ ﮐﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫;)‪void assign(int, int‬‬
‫;)(‪double convert‬‬
‫;)(‪void invert‬‬
‫;)(‪void print‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫)(‪int main‬‬
‫;‪{ Ratio x‬‬
‫;)‪x.assign(22, 7‬‬
‫;" = ‪cout << "x‬‬
‫;)(‪x.print‬‬
‫‪307‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫;‪cout << " = " << x.convert() << endl‬‬


‫;)(‪x.invert‬‬
‫;)(‪cout << "1/x = "; x.print‬‬
‫;‪cout << endl‬‬
‫}‬

‫)‪void Ratio::assign(int numerator, int denumirator‬‬


‫;‪{ num = numerator‬‬
‫;‪den = denumirator‬‬
‫}‬

‫)(‪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‬‬

‫ﻣﻲﺗﻮﺍﻧﺴﺘﻴﻢ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ‪ num‬ﻭ ‪ den‬ﺭﺍ ﻧﻴﺰ ﺑﻪ ﺻﻮﺭﺕ ‪ public‬ﺗﻌﺮﻳﻒ‬


‫ﮐﻨﻴﻢ ﺗﺎ ﺑﺘﻮﺍﻧﻴﻢ ﺩﺭﻭﻥ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﻪ ﺻﻮﺭﺕ ﻣﺴﺘﻘﻴﻢ ﺑﻪ ﺍﻳﻦ ﺍﻋﻀﺎ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﻴﻢ ﺍﻣﺎ ﺍﺻﻞ‬
‫ﭘﻨﻬﺎﻥﺳﺎﺯﻱ ﺍﻃﻼﻋﺎﺕ ﺍﻳﻦ ﺍﻣﺮ ﺭﺍ ﺗﻮﺻﻴﻪ ﻧﻤﻲﮐﻨﺪ‪ .‬ﺍﻳﻦ ﺍﺻﻞ ﻣﻲﮔﻮﻳﺪ ﮐﻪ ﺗﺎ ﺣﺪ ﺍﻣﮑﺎﻥ‬
‫ﺩﺍﺩﻩﻫﺎﻱ ﻳﮏ ﮐﻼﺱ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ﺧﺼﻮﺻﻲ ﺗﻌﺮﻳﻒ ﮐﻨﻴﺪ ﻭ ﺩﺳﺘﻴﺎﺑﻲ ﺑﻪ ﺁﻥﻫﺎ ﺭﺍ ﺑﻪ ﺗﻮﺍﺑﻊ‬
‫ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﻭﺍﮔﺬﺍﺭ ﻧﻤﺎﻳﻴﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺩﺍﺩﻩﻫﺎﻱ ﺍﺷﻴﺎ ﺍﺯ ﺩﻳﺪ ﺳﺎﻳﺮﻳﻦ ﻣﺨﻔﻲ ﻣﻲﺷﻮﻧﺪ‬
‫ﻭ ﺍﺯ ﺗﻐﻴﻴﺮﺍﺕ ﻧﺎﺧﻮﺍﺳﺘﻪ ﺩﺭ ﺍﻣﺎﻥ ﻣﻲﻣﺎﻧﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐3‬ﺍﻋﻼﻥ ﻛﻼﺱ ‪ Ratio‬ﺑﻪ ﺷﮑﻞ ﺧﻮﺩﮐﻔﺎ‬


‫ﮐﺪ ﺯﻳﺮ‪ ،‬ﺍﻋﻼﻥ ﮐﻼﺱ ‪ Ratio‬ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺗﻌﺮﻳﻒ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﻧﻴﺰ ﺩﺭﻭﻥ‬
‫ﻫﻤﺎﻥ ﮐﻼﺱ ﻗﺮﺍﺭ ﮔﺮﻓﺘﻪ ﺍﺳﺖ‪:‬‬
‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} ;‪void assign(int n, int d) { num = n; den = d‬‬
‫} ;‪double convert() { return double(num)/den‬‬
‫};‪void invert() { int temp = num; num = den; den = temp‬‬
‫} ;‪void print() { cout << num << '/' << den‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫ﺍﻋﻼﻥ ﻓﻮﻕ ﺭﺍ ﺑﺎ ﺍﻋﻼﻥ ﮐﻼﺱ ‪ 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‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪ .‬ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻳﮏ ﺗﺎﺑﻊ ﻋﻀﻮ‬
‫ﺍﺳﺖ ﮐﻪ ﺩﺭ ﻫﻨﮕﺎﻡ ﺍﻋﻼﻥ ﻳﮏ ﺷﻲ‪ ،‬ﺧﻮﺩ ﺑﻪ ﺧﻮﺩ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ‪ .‬ﻧﺎﻡ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺑﺎﻳﺪ‬

‫‪1 – Interface‬‬ ‫‪2 - Implementation‬‬ ‫‪3 – Constructor Function‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪310‬‬

‫ﺑﺎ ﻧﺎﻡ ﮐﻼﺱ ﻳﮑﺴﺎﻥ ﺑﺎﺷﺪ ﻭ ﺑﺪﻭﻥ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺗﻌﺮﻳﻒ ﺷﻮﺩ‪ .‬ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ‬
‫ﭼﻄﻮﺭ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺟﺎﻱ ﺗﺎﺑﻊ )(‪ assign‬ﺍﺯ ﻳﮏ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐4‬ﺍﻳﺠﺎﺩ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺑﺮﺍﻱ ﻛﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} ;‪Ratio(int n, int d) { num = n; den = d‬‬
‫} ;‪void print() { cout << num << '/' << den‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫)(‪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‬‬

‫ﺑﺎ ﺧﻄﻮﻁ ﺯﻳﺮ ﺍﺯ ﻣﺜﺎﻝ ‪ 9‐1‬ﻣﻌﺎﺩﻝ ﺍﺳﺖ‪:‬‬


‫;‪Ratio x, y‬‬
‫;)‪x.assign(13,7‬‬
‫;)‪y.assign(19,5‬‬

‫ﻭﻇﻴﻒۀ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺣﺎﻓﻆۀ ﻻﺯﻡ ﺭﺍ ﺑﺮﺍﻱ ﺷﻲﺀ ﺟﺪﻳﺪ ﺗﺨﺼﻴﺺ ﺩﺍﺩﻩ‬
‫ﻭ ﺁﻥ ﺭﺍ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻧﻤﺎﻳﺪ ﻭ ﺑﺎ ﺍﺟﺮﺍﻱ ﻭﻇﺎﻳﻔﻲ ﮐﻪ ﺩﺭ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻣﻨﻈﻮﺭ ﺷﺪﻩ‪ ،‬ﺷﻲﺀ‬
‫ﺟﺪﻳﺪ ﺭﺍ ﺑﺮﺍﻱ ﺍﺳﺘﻔﺎﺩﻩ ﺁﻣﺎﺩﻩ ﮐﻨﺪ‪.‬‬
‫‪311‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫ﻫﺮ ﮐﻼﺱ ﻣﻲﺗﻮﺍﻧﺪ ﭼﻨﺪﻳﻦ ﺳﺎﺯﻧﺪﻩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﺩﺭ ﺣﻘﻴﻘﺖ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻣﻲﺗﻮﺍﻧﺪ‬
‫ﭼﻨﺪﺷﮑﻠﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ )ﺑﺨﺶ ‪ 5‐13‬ﺭﺍ ﺑﺒﻴﻨﻴﺪ(‪ .‬ﺍﻳﻦ ﺳﺎﺯﻧﺪﻩﻫﺎ‪ ،‬ﺍﺯ ﻃﺮﻳﻖ ﻓﻬﺮﺳﺖ‬
‫ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﻣﺘﻔﺎﻭﺕ ﺍﺯ ﻳﮑﺪﻳﮕﺮ ﺗﻔﮑﻴﮏ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐5‬ﺍﻓﺰﻭﺩﻥ ﭼﻨﺪ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﺩﻳﮕﺮ ﺑﻪ ﻛﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} ;‪Ratio() { num = 0; den = 1‬‬
‫} ;‪Ratio(int n) { num = n; den = 1‬‬
‫} ;‪Ratio(int n, int d) { num = n; den = d‬‬
‫} ;‪void print() { cout << num << '/' << den‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫)(‪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‬ﮐﻪ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ﻣﻨﻈﻮﺭ ﻧﮑﺮﺩﻩﺍﻳﻢ‪ ،‬ﻳﮑﻲ ﺑﻪ ﻃﻮﺭ‬
‫ﺧﻮﺩﮐﺎﺭ ﺑﺮﺍﻱ ﺁﻥ ﮐﻼﺱ ﻣﻨﻈﻮﺭ ﺧﻮﺍﻫﺪ ﺷﺪ‪.‬‬

‫‪ 9‐4‬ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺩﺭ ﺳﺎﺯﻧﺪﻩﻫﺎ‬


‫ﺳﺎﺯﻧﺪﻩﻫﺎ ﺍﻏﻠﺐ ﺑﻪ ﻏﻴﺮ ﺍﺯ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺩﺍﺩﻩﻫﺎﻱ ﻋﻀﻮ ﻳﮏ ﺷﻲ‪ ،‬ﮐﺎﺭ ﺩﻳﮕﺮﻱ ﺍﻧﺠﺎﻡ‬
‫ﻧﻤﻲﺩﻫﻨﺪ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺩﺭ ‪ C++‬ﻳﮏ ﻭﺍﺣﺪ ﺩﺳﺘﻮﺭﻱ ﻣﺨﺼﻮﺹ ﭘﻴﺶﺑﻴﻨﻲ ﺷﺪﻩ ﮐﻪ ﺗﻮﻟﻴﺪ‬
‫ﺳﺎﺯﻧﺪﻩ ﺭﺍ ﺗﺴﻬﻴﻞ ﻣﻲﻧﻤﺎﻳﺪ‪ .‬ﺍﻳﻦ ﻭﺍﺣﺪ ﺩﺳﺘﻮﺭﻱ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ‪ 2‬ﻧﺎﻡ ﺩﺍﺭﺩ‪.‬‬
‫ﺑﻪ ﺳﻮﻣﻴﻦ ﺳﺎﺯﻧﺪﻩ ﺩﺭ ﻣﺜﺎﻝ ‪ 9‐5‬ﺩﻗﺖ ﮐﻨﻴﺪ‪ .‬ﺍﻳﻦ ﺳﺎﺯﻧﺪﻩ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬
‫ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺧﻼﺻﻪ ﮐﻨﻴﻢ‪:‬‬
‫} { )‪Ratio(int n, int d) : num(n), den(d‬‬

‫ﺩﺭ ﺩﺳﺘﻮﺭ ﺑﺎﻻ‪ ،‬ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞﻫﺎﻱ ﺟﺎﻳﮕﺰﻳﻨﻲ ﮐﻪ ﻗﺒﻼ ﺩﺭ ﺑﺪﻥۀ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻗﺮﺍﺭ ﺩﺍﺷﺘﻨﺪ‪،‬‬
‫ﺍﮐﻨﻮﻥ ﺩﺭﻭﻥ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺟﺎﻱ ﺩﺍﺩﻩ ﺷﺪﻩﺍﻧﺪ )ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﺎ ﺣﺮﻭﻑ ﺗﻴﺮﻩﺗﺮ‬
‫ﻧﺸﺎﻥ ﺩﺍﺩﻩ ﺷﺪﻩ(‪ .‬ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺑﺎ ﻳﮏ ﻋﻼﻣﺖ ﮐﻮﻟﻦ ‪ :‬ﺷﺮﻭﻉ ﻣﻲﺷﻮﺩ‪ ،‬ﺑﺪﻥۀ ﺗﺎﺑﻊ‬
‫ﻧﻴﺰ ﺩﺭ ﺍﻧﺘﻬﺎ ﻣﻲﺁﻳﺪ )ﮐﻪ ﺍﮐﻨﻮﻥ ﺧﺎﻟﻲ ﺍﺳﺖ(‪ .‬ﺩﺭ ﻣﺜﺎﻝ ﺑﻌﺪﻱ‪ ،‬ﺳﺎﺯﻧﺪﻩﻫﺎﻱ ﮐﻼﺱ ‪Ratio‬‬
‫ﺭﺍ ﺑﺎ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺧﻼﺻﻪ ﮐﺮﺩﻩﺍﻳﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐6‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺩﺭ ﻛﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} { )‪Ratio() : num(0) , den(1‬‬
‫} { )‪Ratio(int n) : num(n) , den(1‬‬
‫} { )‪Ratio(int n, int d) : num(n), den(d‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫‪1 – Default constructor‬‬ ‫‪2 – Initializing list‬‬


‫‪313‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫ﺳﺎﺯﻧﺪﻩﻫﺎ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺯ ﺍﻳﻦ ﻫﻢ ﺳﺎﺩﻩﺗﺮ ﮐﻨﻴﻢ‪ .‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ‬


‫ﭘﻴﺶﻓﺮﺽ‪ ،‬ﺍﻳﻦ ﺳﻪ ﺳﺎﺯﻧﺪﻩ ﺭﺍ ﺑﺎ ﻫﻢ ﺍﺩﻏﺎﻡ ﮐﻨﻴﻢ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺗﻮﺟﻪ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐7‬ﺑﻪ ﮐﺎﺭ ﮔﻴﺮﻱ ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﭘﻴﺶﻓﺮﺽ ﺩﺭ ﺳﺎﺯﻧﺪۀ ﻛﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} { )‪Ratio(int n=0, int d=1) : num(n), den(d‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫)(‪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‬ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪ .‬ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﻳﮏ ﺗﺎﺑﻊ ﻋﻤﻮﻣﻲ ﻋﻀﻮ ﮐﻼﺱ ﺍﺳﺖ ﻭ ﺑﻪ‬
‫ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﺟﺎﺯۀ ﺩﺳﺘﺮﺳﻲ ﺑﻪ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺧﺼﻮﺻﻲ ﺭﺍ ﺩﺍﺭﺩ‪ .‬ﺍﺯ ﻃﺮﻓﻲ ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ‬
‫ﺭﺍ ﻃﻮﺭﻱ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﻨﺪ ﮐﻪ ﻓﻘﻂ ﻣﻘﺪﺍﺭ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺭﺍ ﺑﺮﮔﺮﺩﺍﻧﺪ ﻭﻟﻲ ﺁﻥﻫﺎ ﺭﺍ ﺗﻐﻴﻴﺮ‬
‫ﻧﺪﻫﺪ‪ .‬ﺑﻪ ﺑﻴﺎﻥ ﺳﺎﺩﻩﺗﺮ‪ ،‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﻓﻘﻂ ﻣﻲﺗﻮﺍﻥ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺧﺼﻮﺻﻲ‬
‫ﺭﺍ ﺧﻮﺍﻧﺪ ﻭﻟﻲ ﻧﻤﻲﺗﻮﺍﻥ ﺁﻥﻫﺎ ﺭﺍ ﺩﺳﺖﮐﺎﺭﻱ ﮐﺮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐8‬ﺍﻓﺰﻭﺩﻥ ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﺑﻪ ﻛﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} { )‪Ratio(int n=0, int d=1) : num(n) , den(d‬‬
‫} ;‪int numerator() { return num‬‬
‫} ;‪int denomerator() { return den‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫)(‪int main‬‬
‫;)‪{ Ratio x(22,7‬‬
‫;‪cout << x.numerator() << '/' << x.denumerator() << endl‬‬
‫}‬

‫ﺩﺭ ﺍﻳﻦﺟﺎ ﺗﻮﺍﺑﻊ )(‪ numerator‬ﻭ )(‪ denumerator‬ﻣﻘﺎﺩﻳﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﺩﺍﺩﻩﻫﺎﻱ‬


‫ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﻨﺪ‪.‬‬

‫‪ 9‐6‬ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺧﺼﻮﺻﻲ‬


‫ﺗﺎﮐﻨﻮﻥ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﮐﻼﺱ ﺍﻋﻼﻥ ﮐﺮﺩﻳﻢ ﺗﺎ ﺑﺘﻮﺍﻧﻴﻢ ﺩﺭ‬
‫ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺁﻥﻫﺎ ﺭﺍ ﻓﺮﺍ ﺑﺨﻮﺍﻧﻴﻢ ﻭ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥﻫﺎ ﻋﻤﻠﻴﺎﺗﻲ ﺭﺍ ﺭﻭﻱ ﺍﺷﻴﺎ ﺍﻧﺠﺎﻡ ﺩﻫﻴﻢ‪.‬‬
‫ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺭﺍ ﮔﺎﻫﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻋﻀﻮ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﻣﻌﺮﻓﻲ ﮐﻨﻴﻢ‪ .‬ﻭﺍﺿﺢ‬
‫ﺍﺳﺖ ﮐﻪ ﭼﻨﻴﻦ ﺗﺎﺑﻌﻲ ﺍﺯ ﺩﺍﺧﻞ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﺑﻪ ﻫﻴﭻ ﻋﻨﻮﺍﻥ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﻧﻴﺴﺖ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ‬

‫‪1 – Access function‬‬


‫‪315‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫ﻓﻘﻂ ﻣﻲﺗﻮﺍﻧﺪ ﺗﻮﺳﻂ ﺳﺎﻳﺮ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﮐﻼﺱ ﺩﺳﺘﻴﺎﺑﻲ ﺷﻮﺩ‪ .‬ﺑﻪ ﭼﻨﻴﻦ ﺗﺎﺑﻌﻲ ﻳﮏ‬
‫ﺗﺎﺑﻊ ﺳﻮﺩﻣﻨﺪ‪ 1‬ﻣﺤﻠﻲ ﻣﻲﮔﻮﻳﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐9‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺧﺼﻮﺻﻲ‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} { )‪Ratio(int n=0, int d=1) : num(n), den(d‬‬
‫} ;‪void print() { cout << num << '/' << den << endl‬‬
‫} ;‪void printconv() { cout << toFloat() << endl‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;)(‪double toFloat‬‬
‫;}‬

‫)(‪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‬‬
‫ﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪.‬‬

‫‪1 – Utility function‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪316‬‬

‫ﺗﻮﺍﺑﻌﻲ ﮐﻪ ﻓﻘﻂ ﺑﻪ ﺍﻧﺠﺎﻡ ﻭﻇﻴﻒۀ ﺳﺎﻳﺮ ﺗﻮﺍﺑﻊ ﮐﻤﮏ ﻣﻲﮐﻨﻨﺪ ﻭ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺍﺻﻠﻲ ﻫﻴﭻ‬
‫ﮐﺎﺭﺑﺮﺩﻱ ﻧﺪﺍﺭﻧﺪ‪ ،‬ﺑﻬﺘﺮ ﺍﺳﺖ ﺑﻪ ﺻﻮﺭﺕ ﺧﺼﻮﺻﻲ ﺍﻋﻼﻥ ﺷﻮﻧﺪ ﺗﺎ ﺍﺯ ﺩﺳﺘﺮﺱ ﺳﺎﻳﺮﻳﻦ ﺩﺭ‬
‫ﺍﻣﺎﻥ ﺑﻤﺎﻧﻨﺪ‪.‬‬

‫‪ 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‬‬

‫ﺍﻭﻟﻲ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ﺍﺳﺖ ﻭ ﺩﻭﻣﻲ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺍﺳﺖ‪ .‬ﺣﺎﻻ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﺎ‬

‫‪1 – Copy constructor‬‬


‫‪317‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻳﻦ ﺗﺎﺑﻊ‪ ،‬ﺍﺯ ﺭﻭﻱ ﻳﮏ ﺷﻲﺀ ﻣﻮﺟﻮﺩ ﻳﮏ ﮐﭙﻲ ﺑﺴﺎﺯﻳﻢ‪:‬‬


‫;)‪Ratio y(x‬‬

‫ﮐﺪ ﺑﺎﻻ ﻳﮏ ﺷﻲ ﺑﻪ ﻧﺎﻡ ‪ y‬ﺍﺯ ﻧﻮﻉ ‪ Ratio‬ﺍﻳﺠﺎﺩ ﻣﻲﮐﻨﺪ ﻭ ﺗﻤﺎﻡ ﻣﺸﺨﺼﺎﺕ ﺷﻲﺀ ‪ x‬ﺭﺍ‬
‫ﺩﺭﻭﻥ ﺁﻥ ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ‪ .‬ﺍﮔﺮ ﺩﺭ ﺗﻌﺮﻳﻒ ﮐﻼﺱ‪ ،‬ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺫﮐﺮ ﻧﺸﻮﺩ )ﻣﺜﻞ ﻫﻢۀ‬
‫ﮐﻼﺱﻫﺎﻱ ﻗﺒﻠﻲ( ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﻳﮏ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﭘﻴﺶﻓﺮﺽ ﺑﻪ ﮐﻼﺱ ﺍﻓﺰﻭﺩﻩ ﺧﻮﺍﻫﺪ‬
‫ﺷﺪ‪ .‬ﺑﺎ ﺍﻳﻦ ﻭﺟﻮﺩ ﺍﮔﺮ ﺧﻮﺩﺗﺎﻥ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﮐﻨﻴﺪ‪ ،‬ﻣﻲﺗﻮﺍﻧﻴﺪ ﮐﻨﺘﺮﻝ ﺑﻴﺸﺘﺮﻱ‬
‫ﺭﻭﻱ ﺑﺮﻧﺎﻣﻪﺗﺎﻥ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐10‬ﺍﻓﺰﻭﺩﻥ ﻳﻚ ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ ﺑﻪ ﻛﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} { )‪Ratio(int n=0, int d=1) : num(n), den(d‬‬
‫} { )‪Ratio(const Ratio& r) : num(r.num), den(r.den‬‬
‫} ;‪void print() { cout << num << '/' << den‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬
‫)(‪int main‬‬
‫;)‪{ Ratio x(100,360‬‬
‫;)‪Ratio y(x‬‬
‫;" = ‪cout << "x‬‬
‫;)(‪x.print‬‬
‫;" = ‪cout << ", y‬‬
‫;)(‪y.print‬‬
‫}‬
‫‪x = 100/360, y = 100/360‬‬

‫ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺩﺭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻧﻴﺰ ﻣﻲﺗﻮﺍﻥ ﺍﺯ ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﭘﻴﺶﻓﺮﺽ‬
‫ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩ‪ .‬ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ‪ ،‬ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻃﻮﺭﻱ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﮐﻪ ﻋﻨﺼﺮﻫﺎﻱ ‪ num‬ﻭ‬
‫‪ den‬ﺍﺯ ﭘﺎﺭﺍﻣﺘﺮ ‪ r‬ﺑﻪ ﺩﺭﻭﻥ ﻋﻨﺼﺮﻫﺎﻱ ﻣﺘﻨﺎﻇﺮ ﺩﺭ ﺷﻲﺀ ﺟﺪﻳﺪ ﮐﭙﻲ ﺷﻮﻧﺪ‪ .‬ﺩﺳﺘﻮﺭ‬
‫;)‪ Ratio y(x‬ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺷﻲﺀ ‪ y‬ﺳﺎﺧﺘﻪ ﺷﺪﻩ ﻭ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻓﺮﺍ ﺧﻮﺍﻧﺪﻩ‬
‫ﺷﻮﺩ ﺗﺎ ﻣﻘﺎﺩﻳﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﺷﻲﺀ ‪ x‬ﺩﺭﻭﻥ ‪ y‬ﮐﭙﻲ ﺷﻮﻧﺪ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪318‬‬

‫ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺩﺭ ﺳﻪ ﻭﺿﻌﻴﺖ ﻓﺮﺍ ﺧﻮﺍﻧﺪﻩ ﻣﻲﺷﻮﺩ‪:‬‬


‫‪ – 1‬ﻭﻗﺘﻲ ﮐﻪ ﻳﮏ ﺷﻲ ﻫﻨﮕﺎﻡ ﺍﻋﻼﻥ ﺍﺯ ﺭﻭﻱ ﺷﻲﺀ ﺩﻳﮕﺮ ﮐﭙﻲ ﺷﻮﺩ‬
‫‪ – 2‬ﻭﻗﺘﻲ ﮐﻪ ﻳﮏ ﺷﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﻣﻘﺪﺍﺭ ﺑﻪ ﻳﮏ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﺷﻮﺩ‬
‫‪ – 3‬ﻭﻗﺘﻲ ﮐﻪ ﻳﮏ ﺷﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﻣﻘﺪﺍﺭ ﺍﺯ ﻳﮏ ﺗﺎﺑﻊ ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﺷﻮﺩ‬
‫ﺑﺮﺍﻱ ﺩﺭﮎ ﺍﻳﻦ ﻭﺿﻌﻴﺖﻫﺎ ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐11‬ﺩﻧﺒﺎﻝ ﻛﺮﺩﻥ ﻓﺮﺍﺧﻮﺍﻧﻲﻫﺎﻱ ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} { )‪Ratio(int n=0, int d=1) : num(n), den(d‬‬
‫)‪Ratio(const Ratio& r) : num(r.num), den(r.den‬‬
‫} ;"‪{ cout << "COPY CONSTRUCTOR CALLED\n‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫‪Ratio test(Ratio r) // calls the copy constructor, copying ? to r‬‬


‫;‪{ Ratio q = r‬‬ ‫‪// calls the copy constructor, copying r to q‬‬
‫;‪return q‬‬ ‫? ‪// calls the copy constructor, copying q to‬‬
‫}‬

‫)(‪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‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫‐ ﻫﻨﮕﺎﻣﻲ ﮐﻪ ‪ y‬ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ‪ ،‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﻭ ‪ x‬ﺭﺍ ﺩﺭﻭﻥ ‪ y‬ﮐﭙﻲ ﻣﻲﮐﻨﺪ‪.‬‬


‫‐ ﻫﻨﮕﺎﻣﻲ ﮐﻪ ‪ y‬ﺑﻪ ﻭﺳﻴﻞۀ ﻣﻘﺪﺍﺭ ﺑﻪ ﺗﺎﺑﻊ )(‪ test‬ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ‪ ،‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﻭ ‪y‬‬
‫ﺭﺍ ﺑﻪ ﺩﺭﻭﻥ ‪ r‬ﮐﭙﻲ ﻣﻲﮐﻨﺪ‪.‬‬
‫‐ ﻫﻨﮕﺎﻣﻲ ﮐﻪ ‪ q‬ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ‪ ،‬ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﻭ ‪ r‬ﺭﺍ ﺑﻪ ﺩﺭﻭﻥ ‪ q‬ﮐﭙﻲ ﻣﻲﮐﻨﺪ‪.‬‬
‫‐ ﻫﻨﮕﺎﻣﻲ ﮐﻪ ‪ q‬ﺑﻪ ﻭﺳﻴﻞۀ ﻣﻘﺪﺍﺭ ﺍﺯ ﺗﺎﺑﻊ )(‪ test‬ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪ ،‬ﻓﺮﺍﺧﻮﺍﻧﻲ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺣﺘﻲ ﺍﮔﺮ ﭼﻴﺰﻱ ﺭﺍ ﺟﺎﻳﻲ ﮐﭙﻲ ﻧﮑﻨﺪ‪.‬‬
‫ﺩﺳﺘﻮﺭ ;‪ Ratio q=r‬ﻇﺎﻫﺮﻱ ﺷﺒﻴﻪ ﻋﻤﻞ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺩﺍﺭﺩ ﺍﻣﺎ ﺍﻳﻦ ﮐﺪ ﺩﺭ ﺣﻘﻴﻘﺖ‬
‫ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺭﺍ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﮐﻨﺪ ﻭ ﺩﺭﺳﺖ ﺷﺒﻴﻪ ﺩﺳﺘﻮﺭ ;)‪ Ratio q(r‬ﺍﺳﺖ‪.‬‬
‫ﺍﮔﺮ ﻳﮏ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺩﺭ ﺗﻌﺮﻳﻒ ﮐﻼﺳﺘﺎﻥ ﻧﮕﻨﺠﺎﻧﻴﺪ‪ ،‬ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﻳﮏ ﺳﺎﺯﻧﺪۀ‬
‫ﮐﭙﻲ ﺑﺮﺍﻱ ﺁﻥ ﻣﻨﻈﻮﺭ ﻣﻲﺷﻮﺩ ﮐﻪ ﺍﻳﻦ ﺳﺎﺯﻧﺪﻩ ﺑﻪ ﺷﮑﻞ ﭘﻴﺶﻓﺮﺽ ﺗﻤﺎﻡ ﺍﻃﻼﻋﺎﺕ ﻣﻮﺟﻮﺩ‬
‫ﺩﺭ ﺷﻲﺀ ﺟﺎﺭﻱ ﺭﺍ ﺑﻪ ﺩﺭﻭﻥ ﺷﻲﺀ ﺗﺎﺯﻩ ﺳﺎﺧﺘﻪ ﺷﺪﻩ ﮐﭙﻲ ﻣﻲﮐﻨﺪ‪ .‬ﺍﻏﻠﺐ ﺍﻭﻗﺎﺕ ﺍﻳﻦ ﻫﻤﺎﻥ‬
‫ﭼﻴﺰﻱ ﺍﺳﺖ ﮐﻪ ﺍﻧﺘﻈﺎﺭ ﺩﺍﺭﻳﻢ‪ .‬ﺍﻣﺎ ﮔﺎﻫﻲ ﻫﻢ ﺍﻳﻦ ﮐﺎﺭ ﮐﺎﻓﻲ ﻧﻴﺴﺖ ﻭ ﺍﻧﺘﻈﺎﺭﺍﺕ ﻣﺎ ﺭﺍ ﺑﺮﺍﻭﺭﺩﻩ‬
‫ﻧﻤﻲﮐﻨﺪ‪ .‬ﻣﺜﻼ ﻓﺮﺽ ﮐﻨﻴﺪ ﮐﻼﺳﻲ ﺩﺍﺭﻳﺪ ﮐﻪ ﻳﮏ ﻋﻀﻮ ﺁﻥ ﺍﺯ ﻧﻮﻉ ﺍﺷﺎﺭﻩﮔﺮ ﺍﺳﺖ‪ .‬ﺩﺭ ﺣﻴﻦ‬
‫ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺍﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ ﺭﺍ ﺑﻪ ﺧﺎﻧﻪﺍﻱ ﺍﺯ ﺣﺎﻓﻈﻪ ﺍﺷﺎﺭﻩ ﻣﻲﺩﻫﻴﺪ‪ .‬ﺣﺎﻝ ﺍﮔﺮ ﺍﺯ ﺍﻳﻦ ﺷﻲ‬
‫ﻳﮏ ﮐﭙﻲ ﺑﺴﺎﺯﻳﺪ ﺑﺪﻭﻥ ﺍﻳﻦ ﮐﻪ ﺍﺯ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻣﻨﺎﺳﺒﻲ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﺪ‪ ،‬ﺷﻲﺀ ﺟﺪﻳﺪ ﻧﻴﺰ ﺑﻪ‬
‫ﻫﻤﺎﻥ ﺧﺎﻧﻪ ﺍﺯ ﺣﺎﻓﻈﻪ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ‪ .‬ﻳﻌﻨﻲ ﻓﻘﻂ ﺁﻥ ﺍﺷﺎﺭﻩﮔﺮ ﮐﭙﻲ ﻣﻲﺷﻮﺩ ﻧﻪ ﭼﻴﺰﻱ ﮐﻪ ﺑﻪ‬
‫ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﺷﻮﺩ‪ .‬ﺩﺭ ﺍﻳﻦ ﮔﻮﻧﻪ ﻣﻮﺍﺭﺩ ﻻﺯﻡ ﺍﺳﺖ ﺧﻮﺩﺗﺎﻥ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺭﺍ ﺑﻨﻮﻳﺴﻴﺪ ﻭ‬
‫ﺩﺳﺘﻮﺭﺍﺕ ﻻﺯﻡ ﺭﺍ ﺩﺭ ﺁﻥ ﺑﮕﻨﺠﺎﻧﻴﺪ ﺗﺎ ﻫﻨﮕﺎﻡ ﮐﭙﻲ ﮐﺮﺩﻥ ﻳﮏ ﺷﻲ‪ ،‬ﻣﻨﻈﻮﺭﺗﺎﻥ ﺑﺮﺁﻭﺭﺩﻩ ﺷﻮﺩ‪.‬‬

‫‪ 9‐8‬ﻧﺎﺑﻮﺩ ﮐﻨﻨﺪﻩ‬
‫ﻭﻗﺘﻲ ﮐﻪ ﻳﮏ ﺷﻲ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ‪ ،‬ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﺑﺮﺍﻱ ﺳﺎﺧﺘﻦ ﺁﻥ‬
‫ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ‪ .‬ﻭﻗﺘﻲ ﮐﻪ ﺷﻲ ﺑﻪ ﭘﺎﻳﺎﻥ ﺯﻧﺪﮔﻲﺍﺵ ﺑﺮﺳﺪ‪ ،‬ﺗﺎﺑﻊ ﻋﻀﻮ ﺩﻳﮕﺮﻱ ﺑﻪ ﻃﻮﺭ‬
‫ﺧﻮﺩﮐﺎﺭ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ﺗﺎ ﻧﺎﺑﻮﺩﮐﺮﺩﻥ ﺁﻥ ﺷﻲ ﺭﺍ ﻣﺪﻳﺮﻳﺖ ﮐﻨﺪ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ ﻋﻀﻮ‪،‬‬
‫ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ‪ 1‬ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ )ﺩﺭ ﺑﺮﺧﻲ ﺍﺯ ﮐﺘﺎﺏﻫﺎ ﺑﻪ ﺁﻥ »ﺗﺨﺮﻳﺐﮔﺮ« ﻳﺎ »ﻣﻨﻬﺪﻡﮐﻨﻨﺪﻩ«‬

‫‪1 – Destructor‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪320‬‬

‫ﮔﻔﺘﻪﺍﻧﺪ(‪ .‬ﺳﺎﺯﻧﺪﻩ ﻭﻇﻴﻔﻪ ﺩﺍﺭﺩ ﺗﺎ ﻣﻨﺎﺑﻊ ﻻﺯﻡ ﺭﺍ ﺑﺮﺍﻱ ﺷﻲ ﺗﺨﺼﻴﺺ ﺩﻫﺪ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ‬
‫ﻭﻇﻴﻔﻪ ﺩﺍﺭﺩ ﺁﻥ ﻣﻨﺎﺑﻊ ﺭﺍ ﺁﺯﺍﺩ ﮐﻨﺪ‪.‬‬
‫ﻫﺮ ﮐﻼﺱ ﻓﻘﻂ ﻳﮏ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺩﺍﺭﺩ‪ .‬ﻧﺎﻡ ﺗﺎﺑﻊ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺑﺎﻳﺪ ﻫﻢ ﻧﺎﻡ ﮐﻼﺱ ﻣﺮﺑﻮﻃﻪ‬
‫ﺑﺎﺷﺪ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﻳﮏ ﻋﻼﻣﺖ ﻧﻘﻴﺾ ~ ﺑﻪ ﺁﻥ ﭘﻴﺸﻮﻧﺪ ﺷﺪﻩ‪ .‬ﻣﺜﻞ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻭ‬
‫ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ‪ ،‬ﺍﮔﺮ ﻧﺎﺑﻮﺩ ﮐﻨﻨﺪﻩ ﺩﺭ ﺗﻌﺮﻳﻒ ﮐﻼﺱ ﺫﮐﺮ ﻧﺸﻮﺩ‪ ،‬ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﻳﮏ‬
‫ﻧﺎﺑﻮﺩﮐﻨﻨﺪۀ ﭘﻴﺶﻓﺮﺽ ﺑﻪ ﮐﻼﺱ ﺍﻓﺰﻭﺩﻩ ﺧﻮﺍﻫﺪ ﺷﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐12‬ﺍﻓﺰﻭﺩﻥ ﻳﻚ ﻧﺎﺑﻮﺩﻛﻨﻨﺪﻩ ﺑﻪ ﻛﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} ;"‪Ratio() { cout << "OBJECT IS BORN.\n‬‬
‫} ;"‪~Ratio() { cout << "OBJECT DIES.\n‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫)(‪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‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫ﺳﺎﺯﻧﺪﻩ ﻳﺎ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﭼﻪ ﺯﻣﺎﻧﻲ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﻭﻗﺘﻲ ﻳﮏ ﺷﻲ ﺑﻪ ﭘﺎﻳﺎﻥ ﺣﻮﺯﻩﺍﺵ‬


‫ﺑﺮﺳﺪ‪ ،‬ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ ﺗﺎ ﺁﻥ ﺷﻲ ﺭﺍ ﻧﺎﺑﻮﺩ ﮐﻨﺪ‪ .‬ﻳﮏ ﺷﻲﺀ ﻣﺤﻠﻲ ﻭﻗﺘﻲ ﺑﻪ‬
‫ﭘﺎﻳﺎﻥ ﺑﻠﻮﮎ ﻣﺤﻠﻲ ﺑﺮﺳﺪ ﻣﻲﻣﻴﺮﺩ‪ .‬ﻳﮏ ﺷﻲﺀ ﺛﺎﺑﺖ ﻭﻗﺘﻲ ﺑﻪ ﭘﺎﻳﺎﻥ ﺗﺎﺑﻊ )(‪ main‬ﺑﺮﺧﻮﺭﺩ‬
‫ﺷﻮﺩ‪ ،‬ﻣﻲﻣﻴﺮﺩ‪ .‬ﺷﻴﺌﻲ ﮐﻪ ﺩﺭﻭﻥ ﻳﮏ ﺗﺎﺑﻊ ﺗﻌﺮﻳﻒ ﺷﺪﻩ‪ ،‬ﺩﺭ ﭘﺎﻳﺎﻥ ﺁﻥ ﺗﺎﺑﻊ ﻣﻲﻣﻴﺮﺩ‪.‬‬
‫ﺳﻌﻲ ﮐﻨﻴﺪ ﺗﺎﺑﻊ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺭﺍ ﺧﻮﺩﺗﺎﻥ ﺑﺮﺍﻱ ﮐﻼﺱ ﺑﻨﻮﻳﺴﻴﺪ‪ .‬ﻳﮏ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺲ‬
‫ﺧﻮﺏ‪ ،‬ﺗﻮﺍﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻭ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺭﺍ ﺧﻮﺩﺵ ﺩﺭ ﺗﻌﺮﻳﻒ ﮐﻼﺱﻫﺎﻳﺶ‬
‫ﻣﻲﮔﻨﺠﺎﻧﺪ ﻭ ﺁﻥﻫﺎ ﺭﺍ ﺑﻪ ﺗﻮﺍﺑﻊ ﭘﻴﺶﻓﺮﺽ ﺳﻴﺴﺘﻢ ﻭﺍﮔﺬﺍﺭ ﻧﻤﻲﮐﻨﺪ‪.‬‬

‫‪ 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‬ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ‬
‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎﻱ ﮐﻼﺱ ﻧﻴﺰ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ‪ .‬ﺍﺯ ﺁﻥﺟﺎ ﮐﻪ ﻳﮏ ﮐﻼﺱ‬
‫ﻣﻲﺗﻮﺍﻧﺪ ﺍﺷﻴﺎﻱ ﺩﺍﺩﻩﺍﻱ ﻣﺘﻨﻮﻉ ﻭ ﻣﺘﻔﺎﻭﺗﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ ،‬ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ ﺑﺴﻴﺎﺭ ﺳﻮﺩﻣﻨﺪ ﻭ‬
‫ﻣﻔﻴﺪ ﺍﺳﺖ‪ .‬ﺑﻬﺘﺮ ﺍﺳﺖ ﻗﺒﻞ ﺍﺯ ﻣﻄﺎﻟﻊۀ ﻣﺜﺎﻝﻫﺎﻱ ﺯﻳﺮ‪ ،‬ﻓﺼﻞ ﻫﻔﺘﻢ ﺭﺍ ﻣﺮﻭﺭ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐13‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ‬


‫‪class X‬‬
‫{‬ ‫‪public:‬‬
‫;‪int data‬‬
‫;}‬
‫)(‪main‬‬
‫{‬ ‫;‪X* p = new X‬‬
‫;‪(*p).data = 22‬‬ ‫;‪// equivalent to: p->data = 22‬‬
‫;‪cout << "(*p).data = " << (*p).data << " = " << p->data << endl‬‬
‫;‪p->data = 44‬‬
‫;‪cout << " p->data = " << (*p).data << " = " << p->data << endl‬‬
‫}‬
‫‪(*p).data = 22 = 22‬‬
‫‪p->data = 44 = 44‬‬

‫ﺩﺭ ﺍﻳﻦ ﻣﺜﺎﻝ‪ p ،‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺷﻲﺀ ‪ x‬ﺍﺳﺖ‪ .‬ﭘﺲ ‪ *p‬ﻳﮏ ﺷﻲﺀ ‪ x‬ﺍﺳﺖ ﻭ‬
‫‪ (*p).data‬ﺩﺍﺩۀ ﻋﻀﻮ ﺁﻥ ﺷﻲ ﺭﺍ ﺩﺳﺘﻴﺎﺑﻲ ﻣﻲﮐﻨﺪ‪ .‬ﺣﺘﻤﺎ ﺑﺎﻳﺪ ﻫﻨﮕﺎﻡ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ‪ *p‬ﺁﻥ‬
‫ﺭﺍ ﺩﺭﻭﻥ ﭘﺮﺍﻧﺘﺰ ﻗﺮﺍﺭ ﺩﻫﻴﺪ ﺯﻳﺮﺍ ﻋﻤﻠﮕﺮ ﺍﻧﺘﺨﺎﺏ ﻋﻀﻮ )‪ (.‬ﺗﻘﺪﻡ ﺑﺎﻻﺗﺮﻱ ﻧﺴﺒﺖ ﺑﻪ ﻋﻤﻠﮕﺮ‬
‫ﻣﻘﺪﺍﺭﻳﺎﺑﻲ )*( ﺩﺍﺭﺩ‪ .‬ﺍﮔﺮ ﭘﺮﺍﻧﺘﺰﻫﺎ ﻗﻴﺪ ﻧﺸﻮﻧﺪ ﻭ ﻓﻘﻂ ‪ *p.data‬ﻧﻮﺷﺘﻪ ﺷﻮﺩ‪ ،‬ﮐﺎﻣﭙﺎﻳﻠﺮ‬
‫ﺍﻳﻦ ﺧﻂ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ )‪ *(p.data‬ﺗﻔﺴﻴﺮ ﺧﻮﺍﻫﺪ ﮐﺮﺩ ﮐﻪ ﺍﻳﻦ ﺑﺎﻋﺚ ﺧﻄﺎ ﻣﻲﺷﻮﺩ‪.‬‬
‫‪323‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫ﺍﻳﻦ ﻣﺜﺎﻝ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺩﻭ ﻋﺒﺎﺭﺕ ‪ (*p).data‬ﻭ ‪ p->data‬ﻫﺮ ﺩﻭ ﺑﻪ‬


‫ﻳﮏ ﻣﻌﻨﺎ ﻫﺴﺘﻨﺪ‪ .‬ﺑﻴﺸﺘﺮ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﺎﻥ ﺗﺮﺟﻴﺢ ﻣﻲﺩﻫﻨﺪ ﺍﺯ ﺗﺮﮐﻴﺐ ‪ p->data‬ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻨﺪ‬
‫ﺯﻳﺮﺍ ﺑﻪ ﻣﻔﻬﻮﻡ »ﭼﻴﺰﻱ ﮐﻪ ‪ p‬ﺑﻪ ﺁﻥ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ« ﻧﺰﺩﻳﮏﺗﺮ ﺍﺳﺖ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺍﻫﻤﻴﺖ‬
‫ﺑﻴﺸﺘﺮﻱ ﺩﺍﺭﺩ ﻭ ﮐﺎﺭﺑﺮﺩ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ ﺭﺍ ﺑﻬﺘﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐14‬ﻓﻬﺮﺳﺖﻫﺎﻱ ﭘﻴﻮﻧﺪﻱ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻛﻼﺱ ‪Node‬‬


‫ﺑﻪ ﮐﻼﺳﻲ ﮐﻪ ﺩﺭ ﺯﻳﺮ ﺍﻋﻼﻥ ﺷﺪﻩ ﺩﻗﺖ ﮐﻨﻴﺪ‪:‬‬
‫‪class Node‬‬
‫‪{ public:‬‬
‫} { )‪Node(int d, Node* p=0) : data(d), next(p‬‬
‫;‪int data‬‬
‫;‪Node* next‬‬
‫;}‬

‫ﻋﺒﺎﺭﺕ ﺑﺎﻻ ﮐﻼﺳﻲ ﺑﻪ ﻧﺎﻡ ‪ Node‬ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﺷﻴﺎﻱ ﺍﻳﻦ ﮐﻼﺱ ﺩﺍﺭﺍﻱ ﺩﻭ ﻋﻀﻮ‬
‫ﺩﺍﺩﻩﺍﻱ ﻫﺴﺘﻨﺪ ﮐﻪ ﻳﮑﻲ ﻣﺘﻐﻴﺮﻱ ﺍﺯ ﻧﻮﻉ ‪ int‬ﺍﺳﺖ ﻭ ﺩﻳﮕﺮﻱ ﻳﮏ ﺍﺷﺎﺭﻩﮔﺮ ﺍﺯ ﻧﻮﻉ ﻫﻤﻴﻦ‬
‫ﮐﻼﺱ‪ .‬ﺷﺎﻳﺪ ﻋﺠﻴﺐ ﺑﺎﺷﺪ ﮐﻪ ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﺑﻪ ﺷﻴﺌﻲ ﺍﺯ ﻧﻮﻉ ﻫﻤﺎﻥ ﮐﻼﺱ ﺍﺷﺎﺭﻩ ﮐﻨﺪ‬
‫ﺍﻣﺎ ﺍﻳﻦ ﮐﺎﺭ ﻭﺍﻗﻌﺎ ﻣﻤﮑﻦ ﺍﺳﺖ ﻭ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﺑﺘﻮﺍﻧﻴﻢ ﻳﮏ ﺷﻲ ﺭﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻫﻤﻴﻦ‬
‫ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺷﻲﺀ ﺩﻳﮕﺮ ﭘﻴﻮﻧﺪ ﺩﻫﻴﻢ ﻭ ﻳﮏ ﺯﻧﺠﻴﺮﻩ ﺑﺴﺎﺯﻳﻢ‪ .‬ﻣﺜﻼ ﺍﮔﺮ ﺍﺷﻴﺎﻱ ‪ q‬ﻭ ‪ r‬ﻭ ‪ s‬ﺍﺯ‬
‫ﻧﻮﻉ ‪ Node‬ﺑﺎﺷﻨﺪ‪ ،‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﭘﻴﻮﻧﺪ ﺍﻳﻦ ﺳﻪ ﺷﻲ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ﺯﻳﺮ ﻣﺠﺴﻢ ﮐﻨﻴﻢ‪:‬‬

‫‪q‬‬ ‫‪r‬‬ ‫‪s‬‬


‫‪int data‬‬ ‫‪int data‬‬ ‫‪int data‬‬

‫‪Node* next‬‬ ‫‪Node* next‬‬ ‫‪Node* next‬‬

‫ﺑﻪ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻧﻴﺰ ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﭼﻄﻮﺭ ﻫﺮ ﺩﻭ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺷﻲﺀ ﺟﺪﻳﺪ ﺭﺍ‬
‫ﻣﻘﺪﺍﺭﺩﻫﻲ ﻣﻲﮐﻨﺪ‪ .‬ﺍﮐﻨﻮﻥ ﺍﻳﻦ ﮐﻼﺱ ﺭﺍ ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺑﻪ ﮐﺎﺭ ﻣﻲﮔﻴﺮﻳﻢ‪:‬‬
‫)(‪int main‬‬
‫;‪{ int n‬‬
‫;‪Node* p‬‬
‫;‪Node* q=0‬‬
‫)‪while (cin >> n‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪324‬‬

‫{‬ ‫;)‪p = new Node(n, q‬‬


‫;‪q = p‬‬
‫}‬
‫)‪for ( ; p->next; p = p->next‬‬
‫;" >‪cout << p->data << " -‬‬
‫;"‪cout << "*\n‬‬
‫}‬
‫‪22 33 44 55 66 77 ^d‬‬
‫* >‪77 -> 66 -> 55 -> 44 -> 33 -‬‬

‫ﺩﺭ ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺍﺑﺘﺪﺍ ﺩﻭ ﺍﺷﺎﺭﻩﮔﺮ ﺍﺯ ﻧﻮﻉ ‪ Node‬ﺑﻪ ﻧﺎﻡ ‪ p‬ﻭ ‪ q‬ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ ﮐﻪ ‪ q‬ﺑﻪ ﻳﮏ‬
‫ﺷﻲﺀ ﺧﺎﻟﻲ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ .‬ﺩﺭ ﺣﻠﻖۀ ‪ while‬ﭘﺲ ﺍﺯ ﺍﻭﻟﻴﻦ ﻭﺭﻭﺩﻱ‪ ،‬ﺣﺎﻓﻆۀ ﺟﺪﻳﺪﻱ ﺑﺮﺍﻱ‬
‫ﺷﻲﺀ ‪ p‬ﻣﻨﻈﻮﺭ ﻣﻲﺷﻮﺩ ﻭ ﻋﺪﺩ ﻭﺍﺭﺩ ﺷﺪﻩ ﺩﺭ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ‪ data‬ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ ‪ p‬ﻗﺮﺍﺭ‬
‫ﻣﻲﮔﻴﺮﺩ ﻭ ﻫﻤﭽﻨﻴﻦ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ‪ next‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ q‬ﻣﻲﺷﻮﺩ‪ .‬ﻳﻌﻨﻲ ﻋﻀﻮ ﺍﺷﺎﺭﻩﮔﺮ ‪ p‬ﺑﻪ‬
‫ﺣﺎﻓﻆۀ ‪ q‬ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ‪ .‬ﺳﭙﺲ ﺁﺩﺭﺱ ﺷﻲﺀ ‪ p‬ﺩﺭ ﺷﻲﺀ ‪ q‬ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺣﺎﻻ ‪ q‬ﺑﻪ ﺷﻲﺀ‬
‫‪ p‬ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﻭ ‪ p‬ﺑﻪ ﻳﮏ ﺷﻲﺀ ﺧﺎﻟﻲ‪.‬‬
‫ﭘﺲ ﺍﺯ ﺩﻭﻣﻴﻦ ﻭﺭﻭﺩﻱ‪ ،‬ﻣﺠﺪﺩﺍ ﺣﺎﻓﻆۀ ﺟﺪﻳﺪﻱ ﺑﺮﺍﻱ ‪ p‬ﻣﻨﻈﻮﺭ ﻣﻲﺷﻮﺩ ﻭ‬
‫ﺍﻧﺘﺴﺎﺏﻫﺎﻱ ﻓﻮﻕ ﺗﮑﺮﺍﺭ ﻣﻲﺷﻮﺩ ﺗﺎ ﺍﻳﻦ ﮐﻪ ‪ p‬ﺑﻪ ﺣﺎﻓﻆۀ ﻣﻮﺟﻮﺩ ﻗﺒﻠﻲ ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ ﻭ ‪ q‬ﺑﻪ‬
‫ﺷﻲﺀ ‪ p‬ﺍﺷﺎﺭﻩ ﻣﻲﮐﻨﺪ‪ .‬ﺷﮑﻞ ﺯﻳﺮ ﺭﻭﻧﺪ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫‪q‬‬ ‫‪q‬‬ ‫‪q‬‬


‫‪0‬‬ ‫‪0‬‬
‫‪0‬‬
‫‪next‬‬ ‫‪next‬‬
‫‪next‬‬
‫‪p‬‬
‫‪data‬‬ ‫‪data‬‬

‫‪next‬‬ ‫‪next‬‬
‫‪p‬‬
‫‪data‬‬

‫‪next‬‬

‫اﻟﻒ ‪ -‬ﻗﺒﻞ از‬ ‫ب ‪ -‬ﭘﺲ از اوﻟﻴﻦ‬ ‫ج ‪ -‬ﭘﺲ از دوﻣﻴﻦ‬


‫ﺷﺮوع ﺣﻠﻘﻪ‬ ‫ﺗﮑﺮار ﺣﻠﻘﻪ‬ ‫ﺗﮑﺮار ﺣﻠﻘﻪ‬
‫‪325‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫ﺗﺎ ﺯﻣﺎﻧﻲ ﮐﻪ ﮐﺎﺭﺑﺮ ﮐﺎﺭﺍﮐﺘﺮ ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ )‪ (Ctrl+Z‬ﺭ ﺍ ﻓﺸﺎﺭ ﻧﺪﻫﺪ‪ ،‬ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ‬
‫ﻳﺎﻓﺘﻪ ﻭ ﻫﺮ ﺩﻓﻌﻪ ﻳﮏ ﻋﺪﺩ ﺍﺯ ﻭﺭﻭﺩﻱ ﮔﺮﻓﺘﻪ ﺷﺪﻩ ﻭ ﻳﮏ ﺑﻨﺪ ﺑﻪ ﺯﻧﺠﻴﺮۀ ﻣﻮﺟﻮﺩ ﺍﺿﺎﻓﻪ‬
‫ﻣﻲﺷﻮﺩ‪ .‬ﺣﻠﻖۀ ‪ for‬ﻭﻇﻴﻒۀ ﭘﻴﻤﺎﻳﺶ ﻓﻬﺮﺳﺖ ﭘﻴﻮﻧﺪﻱ ﺭﺍ ﺩﺍﺭﺩ‪ .‬ﺑﻪ ﺍﻳﻦ ﺻﻮﺭﺕ ﮐﻪ ﺗﺎ‬
‫ﻭﻗﺘﻲ‬
‫‪ p->next‬ﺑﺮﺍﺑﺮ ﺑﺎ ‪ NUL‬ﻧﺒﺎﺷﺪ‪ ،‬ﺣﻠﻘﻪ ﺍﺩﺍﻣﻪ ﻣﻲﻳﺎﺑﺪ ﻭ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﮔﺮﻩ ﻓﻌﻠﻲ ﺭﺍ ﭼﺎﭖ‬
‫ﻣﻲﮐﻨﺪ ﻭ ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﮐﻞ ﻓﻬﺮﺳﺖ ﭘﻴﻤﺎﻳﺶ ﻣﻲﺷﻮﺩ‪ .‬ﻭﺍﺿﺢ ﺍﺳﺖ ﮐﻪ ﺑﺮﺍﻱ ﭘﻴﻤﻮﺩﻥ ﺍﻳﻦ‬
‫ﻓﻬﺮﺳﺖ ﭘﻴﻮﻧﺪﻱ ﺑﺎﻳﺪ ﺁﻥ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﻌﮑﻮﺱ ﭘﻴﻤﻮﺩ‪.‬‬
‫ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ ﺑﺴﻴﺎﺭ ﺳﻮﺩﻣﻨﺪ ﻭ ﻣﻔﻴﺪ ﺍﺳﺖ ﺑﻪ ﺣﺪﻱ ﮐﻪ ﺑﺤﺚ ﺭﺍﺟﻊ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‬
‫ﻭ ﺍﻟﮕﻮﺭﻳﺘﻢﻫﺎ ﻭ ﻣﺰﺍﻳﺎﻱ ﺁﻥ ﺑﻪ ﺷﺎﺥۀ ﻣﺴﺘﻘﻠﻲ ﺩﺭ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺗﺒﺪﻳﻞ ﺷﺪﻩ ﻭ »ﺳﺎﺧﺘﻤﺎﻥ‬
‫ﺩﺍﺩﻩﻫﺎ‪ «1‬ﻧﺎﻡ ﮔﺮﻓﺘﻪ ﺍﺳﺖ‪ .‬ﺑﻪ ﺍﺧﺘﺼﺎﺭ ﻣﻲﮔﻮﻳﻴﻢ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ ﺑﺮﺍﻱ ﺳﺎﺧﺘﻦ‬
‫ﻓﻬﺮﺳﺖﻫﺎﻱ ﭘﻴﻮﻧﺪﻱ ﻭ ﺩﺭﺧﺖﻫﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‪ .‬ﺍﻳﻦﻫﺎ ﺑﻴﺸﺘﺮ ﺑﺮﺍﻱ‬
‫ﭘﺮﺩﺍﺯﺵﻫﺎﻱ ﺳﺮﻳﻊ ﻣﺜﻞ ﺟﺴﺘﺠﻮ ﺩﺭ ﻓﻬﺮﺳﺖﻫﺎﻱ ﻃﻮﻻﻧﻲ )ﻣﺎﻧﻨﺪ ﻓﺮﻫﻨﮓ ﻟﻐﺎﺕ( ﻳﺎ‬
‫ﻣﺮﺗﺐﺳﺎﺯﻱ ﺭﮐﻮﺭﺩﻫﺎﻱ ﺍﻃﻼﻋﺎﺗﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺑﺮﺍﻱ ﻣﻄﺎﻟﻌﻪ ﺩﺭ ﺍﻳﻦ ﺯﻣﻴﻨﻪ ﺑﻪ ﻣﺮﺍﺟﻊ‬
‫ﺳﺎﺧﺘﻤﺎﻥ ﺩﺍﺩﻩﻫﺎ ﻣﺮﺍﺟﻌﻪ ﮐﻨﻴﺪ‪.‬‬

‫‪ 9‐11‬ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺍﻳﺴﺘﺎ‬


‫ﻫﺮ ﻭﻗﺖ ﮐﻪ ﺷﻴﺌﻲ ﺍﺯ ﺭﻭﻱ ﻳﮏ ﮐﻼﺱ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ‪ ،‬ﺁﻥ ﺷﻲ ﻣﺴﺘﻘﻞ ﺍﺯ ﺍﺷﻴﺎﻱ‬
‫ﺩﻳﮕﺮ‪ ،‬ﺩﺍﺩﻩﻫﺎﻱ ﻋﻀﻮ ﺧﺎﺹ ﺧﻮﺩﺵ ﺭﺍ ﺩﺍﺭﺩ‪ .‬ﮔﺎﻫﻲ ﻻﺯﻡ ﺍﺳﺖ ﮐﻪ ﻣﻘﺪﺍﺭ ﻳﮏ ﻋﻀﻮ‬
‫ﺩﺍﺩﻩﺍﻱ ﺩﺭ ﻫﻢۀ ﺍﺷﻴﺎ ﻳﮑﺴﺎﻥ ﺑﺎﺷﺪ‪ .‬ﺍﮔﺮ ﺍﻳﻦ ﻋﻀﻮ ﻣﻔﺮﻭﺽ ﺩﺭ ﻫﻢۀ ﺍﺷﻴﺎ ﺗﮑﺮﺍﺭ ﺷﻮﺩ‪ ،‬ﻫﻢ ﺍﺯ‬
‫ﮐﺎﺭﺍﻳﻲ ﺑﺮﻧﺎﻣﻪ ﻣﻲﮐﺎﻫﺪ ﻭ ﻫﻢ ﺣﺎﻓﻈﻪ ﺭﺍ ﺗﻠﻒ ﻣﻲﮐﻨﺪ‪ .‬ﺩﺭ ﭼﻨﻴﻦ ﻣﻮﺍﻗﻌﻲ ﺑﻬﺘﺮ ﺍﺳﺖ ﺁﻥ‬
‫ﻋﻀﻮ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﻳﮏ ﻋﻀﻮ ﺍﻳﺴﺘﺎ‪ 2‬ﺍﻋﻼﻥ ﮐﻨﻴﻢ‪ .‬ﻋﻀﻮ ﺍﻳﺴﺘﺎ ﻋﻀﻮﻱ ﺍﺳﺖ ﮐﻪ ﻓﻘﻂ ﻳﮏ‬
‫ﻧﻤﻮﻧﻪ ﺍﺯ ﺁﻥ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﻫﻤﻪ ﺍﺷﻴﺎ ﺍﺯ ﻫﻤﺎﻥ ﻧﻤﻮﻥۀ ﻣﺸﺘﺮﮎ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻨﺪ‪ .‬ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ‬
‫ﺍﺯ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ ‪ static‬ﺩﺭ ﺷﺮﻭﻉ ﺍﻋﻼﻥ ﻣﺘﻐﻴﺮ‪ ،‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﻥ ﻣﺘﻐﻴﺮ ﺭﺍ ﺑﻪ ﺻﻮﺭﺕ ﺍﻳﺴﺘﺎ‬
‫ﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﻢ‪ .‬ﻳﮏ ﻣﺘﻐﻴﺮ ﺍﻳﺴﺘﺎ ﺭﺍ ﻓﻘﻂ ﺑﺎﻳﺪ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ ﻭ ﻣﺴﺘﻘﻞ ﺍﺯ ﺍﺷﻴﺎ ﻣﻘﺪﺍﺭﺩﻫﻲ‬
‫ﻧﻤﻮﺩ‪ .‬ﮐﺪ ﺯﻳﺮ ﻧﺤﻮۀ ﺍﻋﻼﻥ ﻭ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺍﻳﺴﺘﺎ ﺭﺍ ﺑﻴﺎﻥ ﻣﻲﮐﻨﺪ‪:‬‬
‫‪class X‬‬
‫‪{ public:‬‬

‫‪1 – Data structure‬‬ ‫‪2 – Static member‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪326‬‬

‫;‪static int n‬‬ ‫‪// declaration of n as a static data member‬‬


‫;}‬
‫;‪int X::n = 0‬‬ ‫‪// definition of n‬‬

‫ﺧﻂ ﺁﺧﺮ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﻳﺴﺘﺎ ﺭﺍ ﺑﺎﻳﺪ ﺑﻪ ﻃﻮﺭ ﻣﺴﺘﻘﻴﻢ ﻭ ﻣﺴﺘﻘﻞ ﺍﺯ ﺍﺷﻴﺎ‬
‫ﻣﻘﺪﺍﺭﺩﻫﻲ ﮐﺮﺩ‪.‬‬
‫ﻣﺘﻐﻴﺮﻫﺎﻱ ﺍﻳﺴﺘﺎ ﺑﻪ ﻃﻮﺭ ﭘﻴﺶﻓﺮﺽ ﺑﺎ ﺻﻔﺮ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ‬
‫ﻣﻘﺪﺍﺭﺩﻫﻲ ﺻﺮﻳﺢ ﺑﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﻣﺘﻐﻴﺮﻫﺎ ﺿﺮﻭﺭﻱ ﻧﻴﺴﺖ ﻣﮕﺮ ﺍﻳﻦ ﮐﻪ ﺑﺨﻮﺍﻫﻴﺪ ﻳﮏ ﻣﻘﺪﺍﺭ‬
‫ﺍﻭﻟﻲۀ ﻏﻴﺮ ﺻﻔﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐15‬ﻳﻚ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺍﻳﺴﺘﺎ‬


‫ﮐﺪ ﺯﻳﺮ‪ ،‬ﮐﻼﺳﻲ ﺑﻪ ﻧﺎﻡ ‪ widget‬ﺍﻋﻼﻥ ﻣﻲﮐﻨﺪ ﮐﻪ ﺍﻳﻦ ﮐﻼﺱ ﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ‬
‫ﺍﻳﺴﺘﺎ ﺑﻪ ﻧﺎﻡ ‪ count‬ﺩﺍﺭﺩ‪ .‬ﺍﻳﻦ ﻋﻀﻮ‪ ،‬ﺗﻌﺪﺍﺩ ﺍﺷﻴﺎﻱ ‪ widget‬ﮐﻪ ﻣﻮﺟﻮﺩ ﻫﺴﺘﻨﺪ ﺭﺍ ﻧﮕﻪ‬
‫ﻣﻲﺩﺍﺭﺩ‪ .‬ﻫﺮ ﻭﻗﺖ ﮐﻪ ﻳﮏ ﺷﻲﺀ ‪ widget‬ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ‪ ،‬ﺍﺯ ﻃﺮﻳﻖ ﺳﺎﺯﻧﺪﻩ ﻣﻘﺪﺍﺭ‬
‫‪ count‬ﻳﮏ ﻭﺍﺣﺪ ﺍﻓﺰﺍﻳﺶ ﻣﻲﻳﺎﺑﺪ ﻭ ﻫﺮ ﺯﻣﺎﻥ ﮐﻪ ﻳﮏ ﺷﻲﺀ ‪ widget‬ﻧﺎﺑﻮﺩ ﻣﻲﺷﻮﺩ‪ ،‬ﺍﺯ‬
‫ﻃﺮﻳﻖ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﻣﻘﺪﺍﺭ ‪ count‬ﻳﮏ ﻭﺍﺣﺪ ﮐﺎﻫﺶ ﻣﻲﻳﺎﺑﺪ‪:‬‬
‫‪class Widget‬‬
‫‪{ public:‬‬
‫} ;‪Widget() { ++count‬‬
‫} ;‪~Widget() { --count‬‬
‫;‪static int count‬‬
‫;}‬

‫;‪int Widget::count = 0‬‬


‫)(‪main‬‬
‫;‪{ Widget w, x‬‬
‫<< " ‪cout << "Now there are‬‬ ‫;"‪w.count << " widgets.\n‬‬
‫;‪{ Widget w, x, y, z‬‬
‫" ‪cout << "Now there are‬‬ ‫;"‪<< w.count << " widgets.\n‬‬
‫}‬
‫<< " ‪cout << "Now there are‬‬ ‫;"‪w.count << " widgets.\n‬‬
‫;‪Widget y‬‬
‫<< " ‪cout << "Now there are‬‬ ‫;"‪w.count << " widgets.\n‬‬
‫}‬
327 ‫ ﺷﯽﮔﺮاﻳﯽ‬/ ‫ﻢ‬ ‫ﻓﺼﻞ‬

Now there are 2 widgets.


Now there are 6 widgets.
Now there are 2 widgets.
Now there are 3 widgets.

.‫ ﺩﺭﻭﻥ ﺑﻠﻮﮎ ﺩﺍﺧﻠﻲ ﺍﻳﺠﺎﺩ ﺷﺪﻩ ﺍﺳﺖ‬widget ‫ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﭼﮕﻮﻧﻪ ﭼﻬﺎﺭ ﺷﻲﺀ‬
‫ ﺍﻳﻦ ﺍﺷﻴﺎ ﻧﺎﺑﻮﺩ ﻣﻲﺷﻮﻧﺪ ﻭ ﻟﺬﺍ ﺗﻌﺪﺍﺩ‬،‫ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺁﻥ ﺑﻠﻮﮎ ﺧﺎﺭﺝ ﻣﻲﺷﻮﺩ‬
.‫ ﺗﻘﻠﻴﻞ ﻣﻲﻳﺎﺑﺪ‬2 ‫ ﺑﻪ‬6 ‫ﻫﺎ ﺍﺯ‬widget ‫ﮐﻞ‬
‫ ﻓﻘﻂ ﻳﮏ ﻧﻤﻮﻧﻪ ﺍﺯ ﺁﻥ‬:‫ﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺍﻳﺴﺘﺎ ﻣﺜﻞ ﻳﮏ ﻣﺘﻐﻴﺮ ﻣﻌﻤﻮﻟﻲ ﺍﺳﺖ‬
‫ ﺍﺯ ﺁﻥﺟﺎ‬.‫ﻣﻮﺟﻮﺩ ﺍﺳﺖ ﺑﺪﻭﻥ ﺗﻮﺟﻪ ﺑﻪ ﺍﻳﻦ ﮐﻪ ﭼﻪ ﺗﻌﺪﺍﺩ ﺷﻲ ﺍﺯ ﺁﻥ ﮐﻼﺱ ﻣﻮﺟﻮﺩ ﺑﺎﺷﺪ‬
‫ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺁﻥ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻋﻀﻮ‬،‫ﮐﻪ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺍﻳﺴﺘﺎ ﻋﻀﻮﻱ ﺍﺯ ﮐﻼﺱ ﺍﺳﺖ‬
.‫ﺧﺼﻮﺻﻲ ﻧﻴﺰ ﺍﻋﻼﻥ ﮐﻨﻴﻢ‬

‫ ﻳﻚ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺍﻳﺴﺘﺎ ﻭ ﺧﺼﻮﺻﻲ‬9‐16 ‫* ﻣﺜﺎﻝ‬


class Widget
{ public:
Widget() { ++count; }
~Widget() { --count; }
int numWidgets() { return count; }
private:
static int count;
};

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‬ﺩﺭﻭﻥ ﺧﻮﺩ ﮐﻼﺱ ﺟﺎﻱ ﮔﺮﻓﺘﻪ ﻧﻪ ﺩﺭﻭﻥ ﺍﺷﻴﺎ‪.‬‬

‫‪ 9‐12‬ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺍﻳﺴﺘﺎ‬


‫ﺑﺎ ﺩﻗﺖ ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻠﻲ ﺑﻪ ﺩﻭ ﺍﻳﺮﺍﺩ ﺑﺮ ﻣﻲﺧﻮﺭﻳﻢ‪ :‬ﺍﻭﻝ ﺍﻳﻦ ﮐﻪ ﮔﺮﭼﻪ ﻣﺘﻐﻴﺮ ‪count‬‬
‫ﻳﮏ ﻋﻀﻮ ﺍﻳﺴﺘﺎ ﺍﺳﺖ ﻭﻟﻲ ﺑﺮﺍﻱ ﺧﻮﺍﻧﺪﻥ ﺁﻥ ﺣﺘﻤﺎ ﺑﺎﻳﺪ ﺍﺯ ﻳﮏ ﺷﻲﺀ ﻣﻮﺟﻮﺩ ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪.‬‬
‫ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻠﻲ ﺍﺯ ﺷﻲﺀ ‪ w‬ﺑﺮﺍﻱ ﺧﻮﺍﻧﺪﻥ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ‪ .‬ﺍﻳﻦ ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﻣﺠﺒﻮﺭ‬
‫ﺷﻮﻳﻢ ﻫﻤﻴﺸﻪ ﻣﻮﺍﻇﺐ ﺑﺎﺷﻴﻢ ﻋﻀﻮ ﺍﻳﺴﺘﺎﻱ ﻣﻔﺮﻭﺽ ﺍﺯ ﻃﺮﻳﻖ ﻳﮏ ﺷﻲ ﮐﻪ ﺍﻻﻥ ﻣﻮﺟﻮﺩ‬
‫ﺍﺳﺖ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺷﻮﺩ‪ .‬ﻣﺜﻼ ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻠﻲ ﺍﮔﺮ ﺩﺭ ﻗﺴﻤﺘﻲ ﺍﺯ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﺩﻭﺭ ﺍﺯ ﭼﺸﻢ ﻣﺎ‪ ،‬ﺷﻲﺀ‬
‫‪ w‬ﻧﺎﺑﻮﺩ ﺷﻮﺩ‪ ،‬ﺁﻧﮕﺎﻩ ﻓﺮﺍﺧﻮﺍﻧﻲ )(‪ w.numWidgets‬ﺍﺯ ﺁﻥ ﺑﻪ ﺑﻌﺪ ﻣﺨﺎﻃﺮﻩﺁﻣﻴﺰ ﺧﻮﺍﻫﺪ‬
‫ﺑﻮﺩ‪ .‬ﺍﻳﺮﺍﺩ ﺩﻭﻡ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺍﮔﺮ ﻫﻴﭻ ﺷﻴﺌﻲ ﻣﻮﺟﻮﺩ ﻧﺒﺎﺷﺪ‪ ،‬ﻧﻤﻲﺗﻮﺍﻧﻴﻢ ﻋﻀﻮ ﺍﻳﺴﺘﺎﻱ‬
‫‪ count‬ﺭﺍ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﻴﻢ‪ .‬ﺑﺮﺍﻱ ﺭﻓﻊ ﺍﻳﻦ ﺩﻭ ﺍﻳﺮﺍﺩ ﮐﺎﻓﻲ ﺍﺳﺖ ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﻨﺪﻩ ﺭﺍ ﻧﻴﺰ ﺑﻪ‬
‫ﺷﮑﻞ ﺍﻳﺴﺘﺎ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 9‐17‬ﻳﻚ ﺗﺎﺑﻊ ﻋﻀﻮ ﺍﻳﺴﺘﺎ‬


‫ﮐﺪ ﺯﻳﺮ ﻫﻤﺎﻥ ﮐﺪ ﻣﺜﺎﻝ ﻗﺒﻠﻲ ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﻓﺮﻕ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﮐﺪ‪ ،‬ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﻨﺪﻩ‬
‫ﻧﻴﺰ ﺑﻪ ﺷﮑﻞ ﺍﻳﺴﺘﺎ ﺍﻋﻼﻥ ﺷﺪﻩ ﺍﺳﺖ‪:‬‬
‫‪class Widget‬‬
‫{‬ ‫‪public:‬‬
‫} ;‪Widget() { ++count‬‬
‫} ;‪~Widget() { --count‬‬
‫} ;‪static int num() { return count‬‬
‫‪329‬‬ ‫ﻓﺼﻞ ‪‬ﻢ ‪ /‬ﺷﯽﮔﺮاﻳﯽ‬

‫‪private:‬‬
‫;‪static int count‬‬
‫;}‬

‫;‪int Widget::count = 0‬‬

‫)(‪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‬‬

‫‪ ‐15‬ﭼﺮﺍ ﺩﺭ ﻋﺒﺎﺭﺕ ‪ (*P).data‬ﻭﺟﻮﺩ ﭘﺮﺍﻧﺘﺰﻫﺎ ﺿﺮﻭﺭﻱ ﺍﺳﺖ؟‬

‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪ ‐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‬ﺭﺍ ﺗﺪﺍﺭﮎ‬
‫ﺩﻳﺪﻩ ﺍﺳﺖ‪ .‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﺑﻪ ﻋﻤﻠﮕﺮﻫﺎ ﺗﻌﺎﺭﻳﻒ ﺟﺪﻳﺪﻱ‬
‫ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ ﺗﺎ ﺑﺘﻮﺍﻧﻨﺪ ﺑﺎ ﺍﺷﻴﺎﻱ ﮐﻼﺱ ﻣﻮﺭﺩ ﻧﻈﺮ ﺑﻪ ﺩﺭﺳﺘﻲ ﮐﺎﺭ ﮐﻨﻨﺪ‪.‬‬

‫‪1 – Overloading operators‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪338‬‬

‫ﺩﺭ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﻣﺤﺪﻭﺩﻳﺘﻲ ﻭﺟﻮﺩ ﻧﺪﺍﺭﺩ‪ .‬ﻳﻌﻨﻲ ﻣﻲﺗﻮﺍﻧﻴﻢ ﭼﻨﺪﻳﻦ ﮐﻼﺱ‬
‫ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ ﮐﻪ ﻫﺮ ﮐﺪﺍﻡ ﺳﺮﺑﺎﺭﻱ ﺭﺍ ﺑﻪ ﻳﮏ ﻋﻤﻠﮕﺮ ﻣﻔﺮﻭﺽ ﻣﻲﺍﻓﺰﺍﻳﺪ‪ .‬ﻫﻴﭻ ﻳﮏ ﺍﺯ ﺍﻳﻦ‬
‫ﺳﺮﺑﺎﺭﻫﺎ ﺩﻳﮕﺮﻱ ﺭﺍ ﻧﻘﺾ ﻧﻤﻲﮐﻨﺪ ﻭ ﻋﻤﻠﮕﺮ ﻣﺮﺑﻮﻃﻪ ﺑﺎ ﺍﺷﻴﺎﻱ ﻫﺮ ﮐﻼﺱ ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺳﺮﺑﺎﺭ‬
‫ﻫﻤﺎﻥ ﮐﻼﺱ ﺭﻓﺘﺎﺭ ﻣﻲﮐﻨﺪ‪ .‬ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺑﻪ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﺑﭙﺮﺩﺍﺯﻳﻢ‪ ،‬ﻳﮏ ﻣﻔﻬﻮﻡ‬
‫ﺟﺪﻳﺪ ﺭﺍ ﺩﺭ ﺷﻲﮔﺮﺍﻳﻲ ﻣﻌﺮﻓﻲ ﻣﻲﮐﻨﻴﻢ‪.‬‬

‫‪ 10‐2‬ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ‬
‫ﺍﻋﻀﺎﻳﻲ ﺍﺯ ﮐﻼﺱ ﮐﻪ ﺑﻪ ﺷﮑﻞ ﺧﺼﻮﺻﻲ )‪ (private‬ﺍﻋﻼﻥ ﻣﻲﺷﻮﻧﺪ ﻓﻘﻂ ﺍﺯ‬
‫ﺩﺍﺧﻞ ﻫﻤﺎﻥ ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲﺍﻧﺪ ﻭ ﺍﺯ ﺑﻴﺮﻭﻥ ﮐﻼﺱ )ﺩﺭﻭﻥ ﺑﺪﻥۀ ﺍﺻﻠﻲ( ﺍﻣﮑﺎﻥ‬
‫ﺩﺳﺘﺮﺳﻲ ﺑﻪ ﺁﻥﻫﺎ ﻧﻴﺴﺖ‪ .‬ﺍﻣﺎ ﻳﮏ ﺍﺳﺘﺜﻨﺎ ﻭﺟﻮﺩ ﺩﺍﺭﺩ‪ .‬ﺗﺎﺑﻊ ﺩﻭﺳﺖ‪ 1‬ﺗﺎﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ﻋﻀﻮ‬
‫ﻳﮏ ﮐﻼﺱ ﻧﻴﺴﺖ ﺍﻣﺎ ﺍﺟﺎﺯﻩ ﺩﺍﺭﺩ ﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺁﻥ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﺑﻪ ﮐﺪ‬
‫ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪:‬‬
‫‪class Ratio‬‬
‫;)‪{ friend int numReturn(Ratio‬‬
‫‪public:‬‬
‫;)(‪Ratio‬‬
‫;)(‪~Ratio‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫}‬

‫)‪int numReturn(Ratio r‬‬


‫;‪{ return r.num‬‬
‫}‬

‫)(‪int main‬‬
‫;)‪{ Ratio x(22, 7‬‬
‫;‪cout << numReturn(x) << endl‬‬
‫}‬

‫‪1 – Friend function‬‬


‫‪339‬‬ ‫ﻓﺼﻞ دهﻢ ‪ /‬ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ‬

‫ﺩﺭ ﮐﺪ ﺑﺎﻻ ﺗﺎﺑﻊ )(‪ numReturn‬ﻋﻀﻮ ﮐﻼﺱ ‪ Ratio‬ﻧﻴﺴﺖ ﺑﻠﮑﻪ ﺩﻭﺳﺖ ﺁﻥ ﺍﺳﺖ‪.‬‬
‫ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﻳﮏ ﺗﺎﺑﻊ ﺭﺍ ﺩﻭﺳﺖ ﻳﮏ ﮐﻼﺱ ﻣﻌﺮﻓﻲ ﮐﻨﻴﻢ‪ ،‬ﺁﻥ ﺗﺎﺑﻊ ﺭﺍ ﺩﺭ ﮐﻼﺱ ﻣﺬﮐﻮﺭ‬
‫ﺍﻋﻼﻥ ﮐﺮﺩﻩ ﻭ ﺍﺯ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ ‪ friend‬ﺩﺭ ﺍﻋﻼﻥ ﺁﻥ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪ .‬ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ ﺑﺎﻳﺪ‬
‫ﻗﺒﻞ ﺍﺯ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﻭ ﺧﺼﻮﺻﻲ ﮐﻼﺱ ﺍﻋﻼﻥ ﺷﻮﻧﺪ ﻭ ﺗﻌﺮﻳﻒ ﺁﻥﻫﺎ ﺑﺎﻳﺪ ﺧﺎﺭﺝ ﺍﺯ‬
‫ﮐﻼﺱ ﻭ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺗﺎﺑﻊ ﻣﻌﻤﻮﻟﻲ ﺑﺎﺷﺪ ﺯﻳﺮﺍ ﺗﺎﺑﻊ ﺩﻭﺳﺖ‪ ،‬ﻋﻀﻮ ﮐﻼﺱ ﻧﻴﺴﺖ‪ .‬ﺗﻮﺍﺑﻊ‬
‫ﺩﻭﺳﺖ ﺑﻴﺸﺘﺮ ﺩﺭ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﻧﺪ‪.‬‬

‫‪ 10‐3‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ )=(‬


‫ﺩﺭ ﺑﻴﻦ ﻋﻤﻠﮕﺮﻫﺎﻱ ﮔﻮﻧﺎﮔﻮﻥ‪ ،‬ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺷﺎﻳﺪ ﺑﻴﺸﺘﺮﻳﻦ ﮐﺎﺭﺑﺮﺩ ﺭﺍ ﺩﺍﺷﺘﻪ‬
‫ﺑﺎﺷﺪ‪ .‬ﻫﺪﻑ ﺍﻳﻦ ﻋﻤﻠﮕﺮ‪ ،‬ﮐﭙﻲ ﮐﺮﺩﻥ ﻳﮏ ﺷﻲ ﺩﺭ ﺷﻲﺀ ﺩﻳﮕﺮ ﺍﺳﺖ‪ .‬ﻣﺎﻧﻨﺪ ﺳﺎﺯﻧﺪۀ‬
‫ﭘﻴﺶﻓﺮﺽ‪ ،‬ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ‪ ،‬ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻧﻴﺰ ﺑﻪ ﻃﻮﺭ ﺧﻮﺩﮐﺎﺭ ﺑﺮﺍﻱ ﻳﮏ‬
‫ﮐﻼﺱ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺷﮑﻞ ﺻﺮﻳﺢ ﺩﺭﻭﻥ ﮐﻼﺱ ﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 10‐1‬ﺍﻓﺰﻭﺩﻥ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺑﻪ ﻛﻼﺱ ‪Ratio‬‬


‫ﮐﺪ ﺯﻳﺮ ﻳﮏ ﺭﺍﺑﻂ ﮐﻼﺱ ﺑﺮﺍﻱ ‪ Ratio‬ﺍﺳﺖ ﮐﻪ ﺷﺎﻣﻞ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ‪،‬‬
‫ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻭ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻣﻲﺑﺎﺷﺪ‪:‬‬
‫‪class Ratio‬‬
‫‪{ public:‬‬
‫;)‪Ratio(int = 0, int = 1‬‬ ‫‪// default constructor‬‬
‫;)&‪Ratio(const Ratio‬‬ ‫‪// copy constructor‬‬
‫;)&‪void operator=(const Ratio‬‬ ‫‪// assignment operator‬‬
‫‪// other declarations go here‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫ﺑﻪ ﻧﺤﻮ ﺍﻋﻼﻥ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺩﻗﺖ ﻧﻤﺎﻳﻴﺪ‪ .‬ﻧﺎﻡ ﺍﻳﻦ ﺗﺎﺑﻊ ﻋﻀﻮ‪ operator= ،‬ﺍﺳﺖ ﻭ‬
‫ﻓﻬﺮﺳﺖ ﺁﺭﮔﻮﻣﺎﻥ ﺁﻥ ﻣﺎﻧﻨﺪ ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﻣﻲﺑﺎﺷﺪ ﻳﻌﻨﻲ ﻳﮏ ﺁﺭﮔﻮﻣﺎﻥ ﻣﻨﻔﺮﺩ ﺩﺍﺭﺩ ﮐﻪ ﺍﺯ ﻧﻮﻉ‬
‫ﻫﻤﺎﻥ ﮐﻼﺱ ﺍﺳﺖ ﮐﻪ ﺑﻪ ﻃﺮﻳﻖۀ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺍﺭﺳﺎﻝ ﻣﻲﺷﻮﺩ‪ .‬ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺭﺍ‬
‫ﻣﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ‪:‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪340‬‬

‫)‪void Ratio::operator=(const Ratio& r‬‬


‫;‪{ num = r.num‬‬
‫;‪den = r.den‬‬
‫}‬

‫ﮐﺪ ﻓﻮﻕ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺷﻲﺀ ‪ 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‬ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 10‐2‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺑﻪ ﺷﮑﻞ ﺻﺤﻴﺢ‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫;)‪Ratio(int =0, int =1‬‬ ‫‪// default constructor‬‬
‫;)&‪Ratio(const Ratio‬‬ ‫‪// copy constructor‬‬
‫;)&‪Ratio& operator=(const Ratio‬‬ ‫‪// assignment operator‬‬
‫‪// other declarations go here‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫‪// other declarations go here‬‬
‫;}‬

‫)‪Ratio& Ratio::operator=(const Ratio& r‬‬


‫;‪{ num = r.num‬‬
‫;‪den = r.den‬‬
‫;‪return *this‬‬
‫}‬

‫ﺣﺎﻻ ﺍﺷﻴﺎﻱ ﮐﻼﺱ ‪ Ratio‬ﻣﻲﺗﻮﺍﻧﻨﺪ ﺩﺭ ﻳﮏ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺯﻧﺠﻴﺮﻩﺍﻱ ﺷﺮﮐﺖ ﮐﻨﻨﺪ‪:‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪342‬‬

‫;)‪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‬‬

‫ﺳﻪ ﺩﺳﺘﻮﺭ ﺍﻭﻝ‪ ،‬ﺩﺳﺘﻮﺭﺍﺕ ﻣﻘﺪﺍﺭﺩﻫﻲ ﻫﺴﺘﻨﺪ ﻭﻟﻲ ﺩﺳﺘﻮﺭ ﺁﺧﺮ ﻳﮏ ﺩﺳﺘﻮﺭ ﺟﺎﻳﮕﺰﻳﻨﻲ‬
‫ﺍﺳﺖ‪ .‬ﺩﺳﺘﻮﺭ ﻣﻘﺪﺍﺭﺩﻫﻲ‪ ،‬ﺳﺎﺯﻧﺪۀ ﮐﭙﻲ ﺭﺍ ﻓﺮﺍ ﻣﻲﺧﻮﺍﻧﺪ ﻭﻟﻲ ﺩﺳﺘﻮﺭ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻋﻤﻠﮕﺮ‬
‫ﺟﺎﻳﮕﺰﻳﻨﻲ ﺭﺍ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﮐﻨﺪ‪.‬‬

‫‪ 10‐5‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ‬


‫ﭼﻬﺎﺭ ﻋﻤﻠﮕﺮ ﺣﺴﺎﺑﻲ ‪ +‬ﻭ – ﻭ * ﻭ ‪ /‬ﺩﺭ ﻫﻢۀ ﺯﺑﺎﻥﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﻭﺟﻮﺩ ﺩﺍﺭﻧﺪ‬
‫ﻭ ﺑﺎ ﻫﻢۀ ﺍﻧﻮﺍﻉ ﺑﻨﻴﺎﺩﻱ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﻧﺪ‪ .‬ﻗﺼﺪ ﺩﺍﺭﻳﻢ ﺳﺮﺑﺎﺭﻱ ﺭﺍ ﺑﻪ ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ‬
‫ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ ﺗﺎ ﺑﺘﻮﺍﻧﻴﻢ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻥﻫﺎ‪ ،‬ﺍﺷﻴﺎﻱ ﺳﺎﺧﺖ ﺧﻮﺩﻣﺎﻥ ﺭﺍ ﺩﺭ ﻣﺤﺎﺳﺒﺎﺕ ﺭﻳﺎﺿﻲ‬
‫ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ‪.‬‬
‫ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ ﺑﻪ ﺩﻭ ﻋﻤﻠﻮﻧﺪ ﻧﻴﺎﺯ ﺩﺍﺭﻧﺪ‪ .‬ﻣﺜﻼ ﻋﻤﻠﮕﺮ ﺿﺮﺏ )*( ﺩﺭ ﺭﺍﺑﻂۀ ﺯﻳﺮ‪:‬‬
‫;‪z = x*y‬‬

‫ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺭﺍﺑﻂۀ ﻓﻮﻕ ﻭ ﺁﻥﭼﻪ ﺩﺭ ﺑﺨﺶ ﻗﺒﻠﻲ ﮔﻔﺘﻴﻢ‪ ،‬ﻋﻤﻠﮕﺮ ﺿﺮﺏ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪﻩ‬
‫ﺑﺎﻳﺪ ﺩﻭ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ ﻳﮏ ﮐﻼﺱ ﻭ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ ﺑﮕﻴﺮﺩ ﻭ ﻳﮏ ﻣﻘﺪﺍﺭ ﺑﺎﺯﮔﺸﺘﻲ‬
‫ﺍﺯ ﻧﻮﻉ ﻫﻤﺎﻥ ﮐﻼﺱ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﭘﺲ ﺍﻧﺘﻈﺎﺭ ﺩﺍﺭﻳﻢ ﻗﺎﻟﺐ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺿﺮﺏ‬
‫ﺑﺮﺍﻱ ﮐﻼﺱ ‪ 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‬‬
‫}‬

‫ﺩﺭ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ ‪ +‬ﻭ – ﻭ ‪ /‬ﻧﻴﺰ ﺍﺯ ﻗﺎﻟﺐﻫﺎﻱ ﮐﻠﻲ ﻓﻮﻕ‬


‫ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﺩﺭ ﻧﺎﻡ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ‪ ،‬ﺑﻪ ﺟﺎﻱ ﻋﻼﻣﺖ ﺿﺮﺏ *‬
‫ﺑﺎﻳﺪ ﻋﻼﻣﺖ ﻋﻤﻠﮕﺮ ﻣﺮﺑﻮﻃﻪ ﺭﺍ ﻗﺮﺍﺭ ﺩﻫﻴﻢ ﻭ ﺩﺳﺘﻮﺭﺍﺕ ﺑﺪﻥۀ ﺗﺎﺑﻊ ﺭﺍ ﻧﻴﺰ ﻃﺒﻖ ﻧﻴﺎﺯ ﺗﻐﻴﻴﺮ‬
‫ﺩﻫﻴﻢ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺿﺮﺏ ﺭﺍ ﺑﺮﺍﻱ ﮐﻼﺱ ‪ Ratio‬ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 10‐3‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺿﺮﺏ ﺑﺮﺍﻱ ﮐﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫{‬ ‫;)&‪friend Ratio operator*(const Ratio&, const Ratio‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪344‬‬

‫‪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‬‬

‫‪ 10‐6‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺣﺴﺎﺑﻲ‬


‫ﺑﻪ ﺧﺎﻃﺮ ﺑﻴﺎﻭﺭﻳﺪ ﮐﻪ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺣﺴﺎﺑﻲ‪ ،‬ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﻭ‬
‫ﻳﮏ ﻋﻤﻠﮕﺮ ﺣﺴﺎﺑﻲ ﺩﻳﮕﺮ ﺍﺳﺖ‪ .‬ﻣﺜﻼ ﻋﻤﻠﮕﺮ =* ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﺩﻭ ﻋﻤﻞ ﺿﺮﺏ * ﻭ ﺳﭙﺲ‬
‫ﺟﺎﻳﮕﺰﻳﻨﻲ = ﺍﺳﺖ‪ .‬ﻧﮑﺖۀ ﻗﺎﺑﻞ ﺗﻮﺟﻪ ﺩﺭ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺣﺴﺎﺑﻲ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ‬
‫ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﺑﺮ ﺧﻼﻑ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ ﺳﺎﺩﻩ‪ ،‬ﻓﻘﻂ ﻳﮏ ﻋﻤﻠﻮﻧﺪ ﺩﺍﺭﻧﺪ‪ .‬ﭘﺲ ﺗﺎﺑﻊ‬
‫ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺣﺴﺎﺑﻲ ﺑﺮ ﺧﻼﻑ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ‪ ،‬ﻣﻲﺗﻮﺍﻧﺪ‬
‫ﻋﻀﻮ ﮐﻼﺱ ﺑﺎﺷﺪ‪ .‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺣﺴﺎﺑﻲ ﺑﺴﻴﺎﺭ ﺷﺒﻴﻪ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ‬
‫ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺍﺳﺖ‪ .‬ﻗﺎﻟﺐ ﮐﻠﻲ ﺑﺮﺍﻱ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ =* ﺑﺮﺍﻱ ﮐﻼﺱ ﻣﻔﺮﻭﺽ‬
‫‪ T‬ﺑﻪ ﺻﻮﺭﺕ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫‪345‬‬ ‫ﻓﺼﻞ دهﻢ ‪ /‬ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ‬

‫‪class T‬‬
‫‪{ public:‬‬
‫;)&‪T& operator*=(const T‬‬
‫‪// other public members‬‬
‫‪private:‬‬
‫‪// private members‬‬
‫;}‬

‫ﺑﺪﻥۀ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺑﻪ ﻗﺎﻟﺐ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬


‫)‪T& T::operator*=(const T& x‬‬
‫‪{ // required operations‬‬
‫;‪return *this‬‬
‫}‬

‫ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ ‪ *this‬ﺑﺎﻋﺚ ﻣﻲﺷﻮﺩ ﮐﻪ ﺑﺘﻮﺍﻧﻴﻢ ﻋﻤﻠﮕﺮ =* ﺭﺍ ﺩﺭ ﻳﮏ ﺭﺍﺑﻂۀ‬


‫ﺯﻧﺠﻴﺮﻩﺍﻱ ﺑﻪ ﮐﺎﺭ ﺑﺒﺮﻳﻢ‪ .‬ﺩﺭ ‪ C++‬ﭼﻬﺎﺭ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺣﺴﺎﺑﻲ =‪ +‬ﻭ =‪ -‬ﻭ =* ﻭ =‪/‬‬
‫ﻭﺟﻮﺩ ﺩﺍﺭﺩ‪ .‬ﻗﺎﻟﺐ ﮐﻠﻲ ﺑﺮﺍﻱ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻫﻢۀ ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﺑﻪ ﺷﮑﻞ ﻗﺎﻟﺐ ﺑﺎﻻ ﺍﺳﺖ‬
‫ﻓﻘﻂ ﺩﺭ ﻧﺎﻡ ﺗﺎﺑﻊ ﺑﻪ ﺟﺎﻱ =* ﺑﺎﻳﺪ ﻋﻼﻣﺖ ﻋﻤﻠﮕﺮ ﻣﺮﺑﻮﻃﻪ ﺭﺍ ﺫﮐﺮ ﮐﺮﺩ ﻭ ﺩﺳﺘﻮﺭﺍﺕ ﺑﺪﻥۀ‬
‫ﺗﺎﺑﻊ ﺭﺍ ﻧﻴﺰ ﺑﻪ ﺗﻨﺎﺳﺐ‪ ،‬ﺗﻐﻴﻴﺮ ﺩﺍﺩ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﻋﻤﻠﮕﺮ =* ﭼﮕﻮﻧﻪ ﺑﺮﺍﻱ‬
‫ﮐﻼﺱ ‪ Ratio‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪﻩ ﺍﺳﺖ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 10‐4‬ﻛﻼﺱ ‪ Ratio‬ﺑﺎ ﻋﻤﻠﮕﺮ =* ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪﻩ‬


‫‪class Ratio‬‬
‫‪{ public:‬‬
‫;)‪Ratio(int = 0, int = 1‬‬
‫;)&‪Ratio& operator=(const Ratio‬‬
‫;)&‪Ratio& operator*=(const Ratio‬‬
‫‪// other declarations go here‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫‪// other declarations go here‬‬
‫;}‬
‫)‪Ratio& Ratio::operator*=(const Ratio& r‬‬
‫;‪{ num = num*r.num‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪346‬‬

‫;‪den = den*r.den‬‬
‫;‪return *this‬‬
‫}‬

‫ﺑﺪﻳﻬﻲ ﺍﺳﺖ ﮐﻪ ﻋﻤﻠﮕﺮ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪۀ ﺟﺎﻳﮕﺰﻳﻨﻲ ﺣﺴﺎﺑﻲ ﺑﺎﻳﺪ ﺑﺎ ﻋﻤﻠﮕﺮ‬


‫ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺷﺪۀ ﺣﺴﺎﺑﻲ ﻣﻌﺎﺩﻟﺶ‪ ،‬ﻧﺘﻴﺞۀ ﻳﮑﺴﺎﻧﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﻣﺜﻼ ﺍﮔﺮ ‪ x‬ﻭ ‪ y‬ﻫﺮ ﺩﻭ ﺍﺯ‬
‫ﮐﻼﺱ ‪ Ratio‬ﺑﺎﺷﻨﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺩﻭ ﺧﻂ ﮐﺪ ﺯﻳﺮ ﺑﺎﻳﺪ ﻧﺘﻴﺞۀ ﻣﺸﺎﺑﻬﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ‪:‬‬
‫;‪x *= y‬‬
‫;‪x = x*y‬‬

‫‪ 10‐7‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﺍﺑﻄﻪﺍﻱ‬


‫ﺷﺶ ﻋﻤﻠﮕﺮ ﺭﺍﺑﻄﻪﺍﻱ ﺩﺭ ‪ C++‬ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﮐﻪ ﻋﺒﺎﺭﺗﻨﺪ ﺍﺯ‪ > :‬ﻭ < ﻭ >= ﻭ =< ﻭ‬
‫== ﻭ =! ‪ .‬ﺍﻳﻦ ﻋﻤﻠﮕﺮﻫﺎ ﺑﻪ ﻫﻤﺎﻥ ﺭﻭﺵ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﺷﻮﻧﺪ‪،‬‬
‫ﻳﻌﻨﻲ ﺑﻪ ﺷﮑﻞ ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ‪ .‬ﺍﻣﺎ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲﺷﺎﻥ ﻓﺮﻕ ﻣﻲﮐﻨﺪ‪ .‬ﺣﺎﺻﻞ ﻋﺒﺎﺭﺗﻲ ﮐﻪ ﺷﺎﻣﻞ‬
‫ﻋﻤﻠﮕﺮ ﺭﺍﺑﻄﻪﺍﻱ ﺑﺎﺷﺪ‪ ،‬ﻫﻤﻮﺍﺭﻩ ﻳﮏ ﻣﻘﺪﺍﺭ ﺑﻮﻟﻴﻦ ﺍﺳﺖ‪ .‬ﻳﻌﻨﻲ ﺍﮔﺮ ﺁﻥ ﻋﺒﺎﺭﺕ ﺩﺭﺳﺖ ﺑﺎﺷﺪ‪،‬‬
‫ﺣﺎﺻﻞ ‪ true‬ﺍﺳﺖ ﻭ ﺍﮔﺮ ﺁﻥ ﻋﺒﺎﺭﺕ ﻧﺎﺩﺭﺳﺖ ﺑﺎﺷﺪ‪ ،‬ﺣﺎﺻﻞ ‪ false‬ﺍﺳﺖ‪ .‬ﭼﻮﻥ ﻧﻮﻉ‬
‫ﺑﻮﻟﻴﻦ ﺩﺭ ﺣﻘﻴﻘﺖ ﻳﮏ ﻧﻮﻉ ﻋﺪﺩﻱ ﺻﺤﻴﺢ ﺍﺳﺖ‪ ،‬ﻣﻲﺗﻮﺍﻥ ﺑﻪ ﺟﺎﻱ ‪ true‬ﻣﻘﺪﺍﺭ ‪ 1‬ﻭ ﺑﻪ‬
‫ﺟﺎﻱ ‪ false‬ﻣﻘﺪﺍﺭ ‪ 0‬ﺭﺍ ﻗﺮﺍﺭ ﺩﺍﺩ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺟﻬﺖ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺭﺍ ﺑﺮﺍﻱ ﺗﻮﺍﺑﻊ‬
‫ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﺍﺑﻄﻪﺍﻱ‪ ،‬ﺍﺯ ﻧﻮﻉ ‪ int‬ﻗﺮﺍﺭ ﺩﺍﺩﻩﺍﻧﺪ‪ .‬ﻗﺎﻟﺐ ﮐﻠﻲ ﺑﺮﺍﻱ‬
‫ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺭﺍﺑﻄﻪﺍﻱ == ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫‪class T‬‬
‫;)&‪{ friend int operator==(const T&, const T‬‬
‫‪public:‬‬
‫‪// public members‬‬
‫‪private:‬‬
‫‪// private members‬‬
‫}‬

‫ﻫﻤﭽﻨﻴﻦ ﻗﺎﻟﺐ ﮐﻠﻲ ﺗﻌﺮﻳﻒ ﺑﺪﻥۀ ﺍﻳﻦ ﺗﺎﺑﻊ ﺑﻪ ﺻﻮﺭﺕ ﺯﻳﺮ ﻣﻲﺑﺎﺷﺪ‪:‬‬
‫)‪int operator==(const T& x, const T& y‬‬
‫‪{ // required operations to finding result‬‬
‫‪347‬‬ ‫ﻓﺼﻞ دهﻢ ‪ /‬ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ‬

‫;‪return result‬‬
‫}‬

‫ﮐﻪ ﺑﻪ ﺟﺎﻱ ‪ result‬ﻳﮏ ﻣﻘﺪﺍﺭ ﺑﻮﻟﻴﻦ ﻳﺎ ﻳﮏ ﻋﺪﺩ ﺻﺤﻴﺢ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪ .‬ﺳﺎﻳﺮ‬
‫ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﺍﺑﻄﻪﺍﻱ ﻧﻴﺰ ﺍﺯ ﻗﺎﻟﺐ ﺑﺎﻻ ﭘﻴﺮﻭﻱ ﻣﻲﮐﻨﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 10‐5‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺗﺴﺎﻭﻱ )==( ﺑﺮﺍﻱ ﻛﻼﺱ ‪Ratio‬‬


‫‪class Ratio‬‬
‫{‬ ‫;)&‪friend int operator==(const Ratio&, const Ratio‬‬
‫;)&‪frined Ratio operator*(const Ratio&, const Ratio‬‬
‫‪// other declarations go here‬‬
‫‪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‬‬
‫;}‬
‫)‪int operator==(const Ratio& x, const Ratio& y‬‬
‫;)‪{ return (x.num * y.den == y.num * x.den‬‬
‫}‬

‫ﻫﺴﺘﻨﺪ‪ ،‬ﺑﺮﺭﺳﻲ ﺗﺴﺎﻭﻱ ‪ x==y‬ﻣﻌﺎﺩﻝ‬ ‫‪a‬‬ ‫ﭼﻮﻥ ﺍﺷﻴﺎﻱ ﮐﻼﺱ ‪ Ratio‬ﺑﻪ ﺻﻮﺭﺕ ﮐﺴﺮ‬
‫‪b‬‬
‫ﺑﺮﺭﺳﻲ ‪ a == c‬ﺍﺳﺖ ﮐﻪ ﺑﺮﺍﻱ ﺑﺮﺭﺳﻲ ﺍﻳﻦ ﺗﺴﺎﻭﻱ ﻣﻲﺗﻮﺍﻧﻴﻢ ﻣﻘﺪﺍﺭ )‪ (a*d==b*c‬ﺭﺍ‬
‫‪b‬‬ ‫‪d‬‬
‫ﺑﺮﺭﺳﻲ ﮐﻨﻴﻢ‪ .‬ﺑﺪﻥۀ ﺗﺎﺑﻊ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺩﺭ ﻣﺜﺎﻝ ﺑﺎﻻ ﻫﻤﻴﻦ ﺭﺍﺑﻄﻪ ﺭﺍ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﺪ‪.‬‬

‫‪ 10‐8‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺍﻓﺰﺍﻳﺸﻲ ﻭ ﻛﺎﻫﺸﻲ‬


‫ﻋﻤﻠﮕﺮ ﺍﻓﺰﺍﻳﺸﻲ ‪ ++‬ﻭ ﮐﺎﻫﺸﻲ ‪ --‬ﻫﺮ ﮐﺪﺍﻡ ﺩﻭ ﺷﮑﻞ ﺩﺍﺭﻧﺪ‪ :‬ﺷﮑﻞ ﭘﻴﺸﻮﻧﺪﻱ ﻭ‬
‫ﺷﮑﻞ ﭘﺴﻮﻧﺪﻱ‪ .‬ﻫﺮ ﮐﺪﺍﻡ ﺍﺯ ﺍﻳﻦ ﺣﺎﻟﺖﻫﺎ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﮐﺮﺩ‪ .‬ﺍﺑﺘﺪﺍ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ‬
‫ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺭﺍ ﺑﺮﺭﺳﻲ ﻣﻲﮐﻨﻴﻢ‪ .‬ﻋﻤﻠﮕﺮ ﭘﻴﺶﮐﺎﻫﺸﻲ ﺑﻪ ﻫﻤﻴﻦ ﺻﻮﺭﺕ‬
‫ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻣﻲﺷﻮﺩ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪348‬‬

‫ﻭﻗﺘﻲ ﮐﻪ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺭﺍ ﻫﻤﺮﺍﻩ ﺑﺎ ﻳﮏ ﺷﻲ ﺑﻪ ﮐﺎﺭ ﻣﻲﺑﺮﻳﻢ‪ ،‬ﻳﮏ ﻭﺍﺣﺪ ﺑﻪ‬


‫ﻣﻘﺪﺍﺭ ﺁﻥ ﺷﻲ ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ ﻭﺳﭙﺲ ﺍﻳﻦ ﻣﻘﺪﺍﺭ ﺟﺪﻳﺪ ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﻣﻲﺷﻮﺩ‪ .‬ﭘﺲ ﺗﺎﺑﻌﻲ‬
‫ﮐﻪ ﻋﻤﻞ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺭﺍ ﺍﻧﺠﺎﻡ ﻣﻲﺩﻫﺪ‪ ،‬ﻣﻘﺪﺍﺭﻱ ﺍﺯ ﻧﻮﻉ ﻫﻤﺎﻥ‬
‫ﮐﻼﺱ ﺭﺍ ﺑﺎﺯﮔﺸﺖ ﻣﻲﺩﻫﺪ ﺍﻣﺎ ﻫﻴﭻ ﭘﺎﺭﺍﻣﺘﺮﻱ ﻧﺪﺍﺭﺩ‪ .‬ﺍﻳﻦ ﺗﺎﺑﻊ‪ ،‬ﻳﮏ ﺗﺎﺑﻊ ﻋﻀﻮ ﮐﻼﺱ‬
‫ﺍﺳﺖ‪ .‬ﻗﺎﻟﺐ ﮐﻠﻲ ﺑﺮﺍﻱ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺑﻪ ﺻﻮﺭﺕ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬
‫‪class T‬‬
‫‪{ public:‬‬
‫;)(‪T operator++‬‬
‫‪// other public members‬‬
‫‪private:‬‬
‫‪// private members‬‬
‫;}‬

‫ﻗﺎﻟﺐ ﮐﻠﻲ ﺑﺮﺍﻱ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺑﻪ ﺷﮑﻞ ﺯﻳﺮ ﺍﺳﺖ‪:‬‬


‫)(‪T T::operator++‬‬
‫‪{ // required operations‬‬
‫;‪return *this‬‬
‫}‬

‫ﻣﻲﺑﻴﻨﻴﺪ ﮐﻪ ﺍﻳﻦﺟﺎ ﻫﻢ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮ ‪ *this‬ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ‪ .‬ﻋﻠﺖ ﻫﻢ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﻣﺸﺨﺺ‬


‫ﻧﻴﺴﺖ ﭼﻪ ﭼﻴﺰﻱ ﺑﺎﻳﺪ ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﺷﻮﺩ‪ .‬ﺑﻪ ﻫﻤﻴﻦ ﺩﻟﻴﻞ ﺍﺷﺎﺭﻩﮔﺮ ‪ *this‬ﺑﻪ ﮐﺎﺭ ﺭﻓﺘﻪ‬
‫ﺗﺎ ﺷﻴﺌﻲ ﮐﻪ ﻋﻤﻞ ﭘﻴﺶﺍﻓﺰﺍﻳﺶ ﺭﻭﻱ ﺁﻥ ﺻﻮﺭﺕ ﮔﺮﻓﺘﻪ‪ ،‬ﺑﺎﺯﮔﺸﺖ ﺩﺍﺩﻩ ﺷﻮﺩ‪ .‬ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ‬
‫ﺗﻌﻴﻴﻦ ﺩﺳﺘﻮﺭﺍﺕ ﺩﺭﻭﻥ ﺑﺪﻧﻪ ﺩﺭ ﺍﺧﺘﻴﺎﺭ ﻣﺎﺳﺖ‪ .‬ﻟﺰﻭﻣﺎ ﺍﻳﻦ ﻃﻮﺭ ﻧﻴﺴﺖ ﮐﻪ ﺣﺘﻤﺎ ﻣﻘﺪﺍﺭ ‪ 1‬ﺑﻪ‬
‫ﻣﻘﺪﺍﺭ ﻓﻌﻠﻲ ﺷﻲ ﺍﻓﺰﻭﺩﻩ ﺷﻮﺩ‪ .‬ﺍﻟﺒﺘﻪ ﻃﺒﻴﻌﺖ ﺍﻳﻦ ﻋﻤﻠﮕﺮ ﺗﻮﺻﻴﻪ ﻣﻲﮐﻨﺪ ﮐﻪ ﺿﺎﺑﻂۀ ﻓﻮﻕ ﺭﺍ‬
‫ﺭﻋﺎﻳﺖ ﮐﻨﻴﻢ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 10‐6‬ﺍﻓﺰﻭﺩﻥ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺑﻪ ﻛﻼﺱ ‪Ratio‬‬


‫ﺍﮔﺮ ‪ y‬ﻳﮏ ﺷﻲ ﺍﺯ ﮐﻼﺱ ‪ Ratio‬ﺑﺎﺷﺪ ﻭ ﻋﺒﺎﺭﺕ ‪ ++y‬ﺍﺭﺯﻳﺎﺑﻲ ﮔﺮﺩﺩ‪ ،‬ﻣﻘﺪﺍﺭ ‪ 1‬ﺑﻪ‬
‫‪ y‬ﺍﻓﺰﻭﺩﻩ ﻣﻲﺷﻮﺩ ﺍﻣﺎ ﭼﻮﻥ ‪ y‬ﻳﮏ ﻋﺪﺩ ﮐﺴﺮﻱ ﺍﺳﺖ‪ ،‬ﺍﻓﺰﻭﺩﻥ ﻣﻘﺪﺍﺭ ‪ 1‬ﺑﻪ ﺍﻳﻦ ﮐﺴﺮ ﺍﺛﺮ‬
‫ﻣﺘﻔﺎﻭﺗﻲ ﺩﺍﺭﺩ‪ .‬ﻓﺮﺽ ﮐﻨﻴﺪ ‪ y=22/7‬ﺑﺎﺷﺪ‪ .‬ﺣﺎﻻ ﺩﺍﺭﻳﻢ‪:‬‬
‫‪22‬‬ ‫‪22 + 7 29‬‬
‫= ‪+ +y‬‬ ‫=‪+1‬‬ ‫=‬
‫‪7‬‬ ‫‪7‬‬ ‫‪7‬‬
‫‪349‬‬ ‫ﻓﺼﻞ دهﻢ ‪ /‬ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ‬

‫ﭘﺲ ﻭﻗﺘﻲ ‪ 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‬‬

‫ﺍﮐﻨﻮﻥ ﺑﻪ ﺑﺮﺭﺳﻲ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﻣﻲﭘﺮﺩﺍﺯﻳﻢ‪ .‬ﻧﺎﻡ ﺗﺎﺑﻊ ﻋﻤﻠﮕﺮ ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﻭ‬


‫ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺷﺒﻴﻪ ﻫﻢ ﺍﺳﺖ‪ .‬ﻫﺮ ﺩﻭ ‪ operator++‬ﻧﺎﻣﻴﺪﻩ ﻣﻲﺷﻮﺩ‪ .‬ﻭﻟﻲ ﻣﻲﺩﺍﻧﻴﻢ ﮐﻪ‬
‫ﺍﻳﻦ ﺩﻭ ﻋﻤﻠﮕﺮ ﻳﮑﻲ ﻧﻴﺴﺘﻨﺪ‪ .‬ﺑﺮﺍﻱ ﺍﻳﻦ ﮐﻪ ﺍﻳﻦ ﺩﻭ ﺗﺎﺑﻊ ﺍﺯ ﻫﻢ ﺗﻤﻴﺰ ﺩﺍﺩﻩ ﺷﻮﻧﺪ‪ ،‬ﻓﻬﺮﺳﺖ‬
‫ﭘﺎﺭﺍﻣﺘﺮﻫﺎﻱ ﺗﺎﺑﻊ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﻋﺠﻴﺐ ﺩﺍﺭﺩ‪ .‬ﺑﻪ ﻗﺎﻟﺐ ﮐﻠﻲ ﺑﺮﺍﻱ ﺗﺎﺑﻊ ﻋﻤﻠﮕﺮ‬
‫ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺗﻮﺟﻪ ﮐﻨﻴﺪ‪:‬‬
‫;)‪T operator++(int‬‬

‫ﺗﺎﺑﻊ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﻳﮏ ﭘﺎﺭﺍﻣﺘﺮ ﺍﺯ ﻧﻮﻉ ‪ int‬ﺩﺍﺭﺩ ﺩﺭ ﺣﺎﻟﻲ ﮐﻪ ﻣﻲﺩﺍﻧﻴﻢ ﻫﻴﭻ ﻣﻘﺪﺍﺭ‬


‫ﺻﺤﻴﺤﻲ ﺑﻪ ﺍﻳﻦ ﺗﺎﺑﻊ ﺍﺭﺳﺎﻝ ﻧﻤﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﭘﺎﺭﺍﻣﺘﺮ ﺭﺍ ﺩﺭ ﺍﺻﻄﻼﺡ »ﭘﺎﺭﺍﻣﺘﺮ ﮔﻨﮓ«‬
‫ﻣﻲﮔﻮﻳﻨﺪ‪ .‬ﺗﻨﻬﺎ ﻫﺪﻑ ﺍﻳﻦ ﭘﺎﺭﺍﻣﺘﺮ‪ ،‬ﺗﻤﻴﺰ ﺩﺍﺩﻥ ﺗﺎﺑﻊ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺍﺯ ﺗﺎﺑﻊ ﻋﻤﻠﮕﺮ‬
‫ﭘﻴﺶﺍﻓﺰﺍﻳﺸﻲ ﺍﺳﺖ‪ .‬ﺗﺎﺑﻊ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﻳﮏ ﺗﻔﺎﻭﺕ ﻣﻬﻢ ﺩﻳﮕﺮ ﻧﻴﺰ ﺩﺍﺭﺩ‪ :‬ﺩﺳﺘﻮﺭﺍﺕ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪350‬‬

‫ﺑﺪﻥۀ ﺁﻥ‪ .‬ﺍﻳﻦ ﺩﺳﺘﻮﺭﺍﺕ ﺑﺎﻳﺪ ﻃﻮﺭﻱ ﺑﺎﺷﻨﺪ ﮐﻪ ﻣﻘﺪﺍﺭ ﻋﻤﻠﻮﻧﺪ ﻣﺮﺑﻮﻃﻪ ﺭﺍ ﭘﺲ ﺍﺯ ﺍﻧﺠﺎﻡ‬
‫ﺳﺎﻳﺮ ﻣﺤﺎﺳﺒﺎﺕ ﺍﻓﺰﺍﻳﺶ ﺩﻫﻨﺪ ﻧﻪ ﭘﻴﺶ ﺍﺯ ﺁﻥ‪ .‬ﺑﺮﺍﻱ ﺩﺭﮎ ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺑﻪ ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺗﻮﺟﻪ‬
‫ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 10‐7‬ﺍﻓﺰﻭﺩﻥ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺑﻪ ﻛﻼﺱ ‪Ratio‬‬


‫ﺩﺭ ﻋﺒﺎﺭﺕ ;‪ y = x++‬ﺍﺯ ﻋﻤﻠﮕﺮ ﭘﺲﺍﻓﺰﺍﻳﺸﻲ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩﺍﻳﻢ‪ .‬ﺗﺎﺑﻊ ﺍﻳﻦ ﻋﻤﻠﮕﺮ‬
‫ﺑﺎﻳﺪ ﻃﻮﺭﻱ ﺗﻌﺮﻳﻒ ﺷﻮﺩ ﮐﻪ ﻣﻘﺪﺍﺭ ‪ x‬ﺭﺍ ﻗﺒﻞ ﺍﺯ ﺍﻳﻦ ﮐﻪ ﺩﺭﻭﻥ ‪ y‬ﻗﺮﺍﺭ ﺑﮕﻴﺮﺩ‪ ،‬ﺗﻐﻴﻴﺮ ﻧﺪﻫﺪ‪.‬‬
‫ﻣﻲﺩﺍﻧﻴﻢ ﮐﻪ ﺍﺷﺎﺭﻩﮔﺮ ‪ *this‬ﺑﻪ ﺷﻲﺀ ﺟﺎﺭﻱ )ﻣﺎﻟﮏ ﻓﺮﺍﺧﻮﺍﻧﻲ( ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ .‬ﮐﺎﻓﻲ ﺍﺳﺖ‬
‫ﻣﻘﺪﺍﺭ ﺍﻳﻦ ﺍﺷﺎﺭﻩﮔﺮ ﺭﺍ ﺩﺭ ﻳﮏ ﻣﺤﻞ ﻣﻮﻗﺘﻲ ﺫﺧﻴﺮﻩ ﮐﻨﻴﻢ ﻭ ﻋﻤﻞ ﺍﻓﺰﺍﻳﺶ ﺭﺍ ﺭﻭﻱ ﺁﻥ ﻣﻘﺪﺍﺭ‬
‫ﻣﻮﻗﺘﻲ ﺍﻧﺠﺎﻡ ﺩﺍﺩﻩ ﻭ ﺣﺎﺻﻞ ﺁﻥ ﺭﺍ ﺑﺎﺯﮔﺸﺖ ﺩﻫﻴﻢ‪ .‬ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﻣﻘﺪﺍﺭ ‪ *this‬ﺗﻐﻴﻴﺮﻱ‬
‫ﻧﻤﻲﮐﻨﺪ ﻭ ﭘﺲ ﺍﺯ ﺷﺮﮐﺖ ﺩﺭ ﻋﻤﻞ ﺟﺎﻳﮕﺰﻳﻨﻲ‪ ،‬ﺩﺭﻭﻥ ‪ y‬ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ‪:‬‬
‫‪class Ratio‬‬
‫‪{ public:‬‬
‫} { )‪Ratio(int n=0, int d=1) : num(n) , den(d‬‬
‫;)(‪Ratio operator++‬‬ ‫‪//pre-increment‬‬
‫;)‪Ratio operator++(int‬‬ ‫‪//post-increment‬‬
‫} ;‪void print() { cout << num << '/' << den << endl‬‬
‫‪private:‬‬
‫;‪int num, den‬‬
‫;}‬

‫)(‪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‬‬ ‫ﻓﺼﻞ دهﻢ ‪ /‬ﺳﺮﺑﺎرﮔﺬاری ﻋﻤﻠﮕﺮهﺎ‬

‫‪y = 22/7 , x = 29/7‬‬

‫ﭘﺎﺭﺍﻣﺘﺮ ﮔﻨﮓ ﺩﺭ ﺗﻌﺮﻳﻒ ﺗﺎﺑﻊ )(‪ 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‬ﺗﺮﻛﻴﺐ‬
‫ﺗﺮﮐﻴﺐ ﮐﻼﺱﻫﺎ )ﻳﺎ ﺗﺠﻤﻴﻊ ﮐﻼﺱﻫﺎ( ﻳﻌﻨﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻳﮏ ﻳﺎ ﭼﻨﺪ ﮐﻼﺱ ﺩﻳﮕﺮ ﺩﺭ‬
‫ﺩﺍﺧﻞ ﺗﻌﺮﻳﻒ ﻳﮏ ﮐﻼﺱ ﺟﺪﻳﺪ‪ .‬ﻫﻨﮕﺎﻣﻲ ﮐﻪ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﮐﻼﺱ ﺟﺪﻳﺪ‪ ،‬ﺷﻴﺌﻲ ﺍﺯ ﮐﻼﺱ‬
‫ﺩﻳﮕﺮ ﺑﺎﺷﺪ‪ ،‬ﻣﻲﮔﻮﻳﻴﻢ ﮐﻪ ﺍﻳﻦ ﮐﻼﺱ ﺟﺪﻳﺪ ﺗﺮﮐﻴﺒﻲ ﺍﺯ ﺳﺎﻳﺮ ﮐﻼﺱﻫﺎﺳﺖ‪ .‬ﺑﻪ ﺗﻌﺮﻳﻒ ﺩﻭ‬
‫ﮐﻼﺱ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪.‬‬

‫‪1 – Composition‬‬ ‫‪2 - Inheritance‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ 358

Date ‫ ﻛﻼﺱ‬11‐1 ‫* ﻣﺜﺎﻝ‬


‫ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﺷﻴﺎﻱ ﺍﻳﻦ ﮐﻼﺱ ﺑﺮﺍﻱ ﻧﮕﻬﺪﺍﺭﻱ‬Date ‫ ﮐﻼﺱ‬،‫ﮐﺪ ﺯﻳﺮ‬
.‫ﺗﺎﺭﻳﺦ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﺷﻮﻧﺪ‬
class Date
{ public:
Date(int y=0, int m=0, int d=0) :
year(y), month(m), day(d) {};
void setDate(int y, int m, int d)
{ year = y; month = m; day = d; }
void getDate()
{ cin >> year >> month >> day ; }
void showDate()
{ cout << year << '/' << month << '/' << day ; }
private:
int year, month, day;
}

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 ‫ ﺗﺮﮐﻴﺐ و وراﺛﺖ‬/ ‫ﻓﺼﻞ ﻳﺎزدهﻢ‬

Book ‫ ﻛﻼﺱ‬11‐2 ‫* ﻣﺜﺎﻝ‬


‫ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺍﺷﻴﺎﻱ ﺍﻳﻦ ﮐﻼﺱ ﺑﺮﺧﻲ ﺍﺯ ﻣﺸﺨﺼﺎﺕ‬Book ‫ ﮐﻼﺱ‬،‫ﮐﺪ ﺯﻳﺮ‬
:‫ﻳﮏ ﮐﺘﺎﺏ ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﻣﻲﮐﻨﻨﺪ‬
class Book
{ public:
Book(char* n = " ", int i = 0, int p = 0) :
name(n), id(i), page(p) { }
void printName() { cout << name; }
void printId() { cout << id; }
void printPage() { cout << page; }
private:
string name, author;
int id, page;
}

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

‫ ﺭﺍ ﺑﻬﺒﻮﺩ ﺩﻫﻴﻢ‬Book ‫ ﺍﻣﮑﺎﻧﺎﺕ ﮐﻼﺱ‬،‫ﺍﮐﻨﻮﻥ ﻣﻲﺧﻮﺍﻫﻴﻢ ﺑﺎ ﺗﺮﮐﻴﺐ ﺍﻳﻦ ﺩﻭ ﮐﻼﺱ‬


.‫ﺗﺎ ﻣﺸﺨﺼﺎﺕ ﻳﮏ ﮐﺘﺎﺏ ﻭ ﺗﺎﺭﻳﺦ ﺍﻧﺘﺸﺎﺭ ﺁﻥ ﺭﺍ ﻧﮕﻬﺪﺍﺭﻱ ﮐﻨﺪ‬

Book ‫ ﺑﻬﺒﻮﺩ ﺩﺍﺩﻥ ﮐﻼﺱ‬11‐3 ‫* ﻣﺜﺎﻝ‬


#include "Date.h"

class Book
{ public:
Book(char* n = " ", int i = 0, int p = 0) :
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪360‬‬

‫} { )‪name(n), id(i), page(p‬‬


‫} ;‪void printName() { cout << name‬‬
‫)(‪void printId‬‬ ‫;‪{ cout << id‬‬ ‫}‬
‫} ;‪void printPage() { cout << page‬‬
‫)‪void setDOP(int y, int m, int d‬‬
‫} ; )‪{ publish.setDate(y, m, d‬‬
‫} ;)(‪void showDOP() { publish.showDate‬‬
‫‪private:‬‬
‫;‪string name, author‬‬
‫;‪int id, page‬‬
‫;‪Date publish‬‬
‫}‬

‫ﺑﺎ ﺩﻗﺖ ﺩﺭ ﺍﻳﻦ ﮐﻼﺱ ﺑﻬﺒﻮﺩ ﻳﺎﻓﺘﻪ‪ ،‬ﻣﻲﺑﻴﻨﻴﻢ ﮐﻪ ﻳﮏ ﻋﻀﻮ ﺩﺍﺩﻩﺍﻱ ﺧﺼﻮﺻﻲ ﺍﺯ ﻧﻮﻉ ﮐﻼﺱ‬
‫‪ 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‬ﻳﺎ »ﮐﻼﺱ ﻣﺸﺘﻖﺷﺪﻩ« ﻣﻲﮔﻮﻳﻴﻢ‪.‬‬

‫‪1 – Base class‬‬ ‫‪2 – Parent class‬‬


‫‪3 – Sub class‬‬ ‫‪4 – Child class‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪362‬‬

‫ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﻣﻲﺗﻮﺍﻧﺪ ﻋﻼﻭﻩ ﺑﺮ ﺍﻋﻀﺎﻱ ﺑﻪ ﺍﺭﺙ ﺑﺮﺩﻩ ﺷﺪﻩ‪ ،‬ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﻭ ﺧﺼﻮﺻﻲ‬
‫ﺧﺎﺹ ﺧﻮﺩ ﺭﺍ ﻧﻴﺰ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ .‬ﺑﻪ ﮐﺪ ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ‪:‬‬
‫‪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‬ﺭﺍ ﻫﻢ ﺩﺍﺭﺩ ﻭﻟﻲ‬
‫ﺍﺟﺎﺯۀ ﺩﺳﺘﺮﺳﻲ ﻣﺴﺘﻘﻴﻢ ﺑﻪ ﺁﻥ ﺭﺍ ﻧﺪﺍﺭﺩ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﺗﻮﺟﻪ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 11‐4‬ﻣﺸﺘﻖ ﻛﺮﺩﻥ ﻛﻼﺱ ‪ Ebook‬ﺍﺯ ﻛﻼﺱ ‪Book‬‬


‫ﻣﻲﺧﻮﺍﻫﻴﻢ ﮐﻼﺳﻲ ﺑﺮﺍﻱ ﻧﮕﻬﺪﺍﺭﻱ ﻣﺸﺨﺼﺎﺕ ﮐﺘﺎﺏﻫﺎﻱ ﺍﻟﮑﺘﺮﻭﻧﻴﮑﻲ ﺑﺴﺎﺯﻳﻢ‪.‬‬
‫ﮐﺘﺎﺏﻫﺎﻱ ﺍﻟﮑﺘﺮﻭﻧﻴﮑﻲ ﺯﻳﺮﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ﮐﺘﺎﺏﻫﺎﻱ ﮐﻠﻲ ﻫﺴﺘﻨﺪ‪ .‬ﭘﺲ ﻣﻨﻄﻘﻲ ﺍﺳﺖ ﺑﻪ‬
‫ﺟﺎﻱ ﺍﻳﻦ ﮐﻪ ﮐﻼﺱ ‪ Ebook‬ﺭﺍ ﺍﺯ ﺍﺑﺘﺪﺍ ﺍﻳﺠﺎﺩ ﮐﻨﻴﻢ‪ ،‬ﺁﻥ ﺭﺍ ﺍﺯ ﮐﻼﺱ ‪ Book‬ﮐﻪ ﻗﺒﻼ ﺍﻳﺠﺎﺩ‬
‫ﮐﺮﺩﻳﻢ‪ ،‬ﻣﺸﺘﻖ ﮐﻨﻴﻢ‪ .‬ﺩﺭ ﺍﻳﻦ ﺻﻮﺭﺕ ﺍﻏﻠﺐ ﺗﻮﺍﺑﻊ ﻭ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﻮﺭﺩ ﻧﻴﺎﺯ ﺍﺯ ﮐﻼﺱ ‪Book‬‬
363 ‫ ﺗﺮﮐﻴﺐ و وراﺛﺖ‬/ ‫ﻓﺼﻞ ﻳﺎزدهﻢ‬

‫ ﻓﻘﻂ ﮐﺎﻓﻲ ﺍﺳﺖ ﺗﻮﺍﺑﻊ ﻭ ﺩﺍﺩﻩﻫﺎﻱ‬.‫ﺑﻪ ﺍﺭﺙ ﮔﺮﻓﺘﻪ ﻣﻲﺷﻮﻧﺪ ﻭ ﻧﻴﺎﺯﻱ ﺑﻪ ﺍﻳﺠﺎﺩ ﺁﻥﻫﺎ ﻧﻴﺴﺖ‬
:‫ ﺭﺍ ﺑﻪ ﮐﻼﺱ ﻣﺸﺘﻖ ﺷﺪﻩ ﺍﺿﺎﻓﻪ ﮐﻨﻴﻢ‬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

‫ ﺩﺭ ﮐﻼﺱ‬printPage() ‫ ﻭ‬printId() ‫ ﻭ‬printName() ‫ﮔﺮﭼﻪ ﺗﻮﺍﺑﻊ‬


،‫ ﻣﺸﺘﻖ ﺷﺪﻩ‬Book ‫ ﺍﻣﺎ ﭼﻮﻥ ﺍﻳﻦ ﮐﻼﺱ ﺍﺯ ﮐﻼﺱ‬،‫ ﺍﻋﻼﻥ ﻭ ﺗﻌﺮﻳﻒ ﻧﺸﺪﻩﺍﻧﺪ‬Ebook
‫ ﺍﻳﻦ ﻣﺜﺎﻝ‬.‫ﻫﻢۀ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﺁﻥ ﺭﺍ ﺑﻪ ﺍﺭﺙ ﻣﻲﮔﻴﺮﺩ ﻭ ﺩﻳﮕﺮ ﻧﻴﺎﺯﻱ ﺑﻪ ﺍﻋﻼﻥ ﺁﻥﻫﺎ ﻧﻴﺴﺖ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪364‬‬

‫ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﺑﻪ ﺍﺭﺙ ﮔﺮﻓﺘﻪ ﺷﺪﻩ ﺍﺯ ﮐﻼﺱ ﻭﺍﻟﺪ‪ ،‬ﻣﻲﺗﻮﺍﻥ‬
‫ﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺁﻥ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ‪ .‬ﺩﻗﺖ ﮐﻨﻴﺪ ﮐﻪ ﭼﮕﻮﻧﻪ ﺩﺭ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ‬
‫‪ Ebook‬ﺍﺯ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪۀ ﮐﻼﺱ ‪ Book‬ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩ ﻭ ﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﮐﻼﺱ‬
‫‪ Book‬ﺩﺳﺘﻴﺎﺑﻲ ﻧﻤﻮﺩﻩﺍﻳﻢ‪.‬‬

‫‪ 11‐4‬ﺍﻋﻀﺎﻱ ﺣﻔﺎﻇﺖ ﺷﺪﻩ‬


‫ﮔﺮﭼﻪ ﮐﻼﺱ ‪ Ebook‬ﺩﺭ ﻣﺜﺎﻝ ﻗﺒﻞ ﻧﻤﻲﺗﻮﺍﻧﺪ ﻣﺴﺘﻘﻴﻤﺎ ﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ‬
‫ﮐﻼﺱ ﻭﺍﻟﺪﺵ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ ،‬ﺍﻣﺎ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﮐﻪ ﺍﺯ ﮐﻼﺱ‬
‫ﻭﺍﻟﺪ ﺑﻪ ﺍﺭﺙ ﺑﺮﺩﻩ‪ ،‬ﻣﻲﺗﻮﺍﻧﺪ ﺑﻪ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺁﻥ ﮐﻼﺱ ﺩﺳﺘﻴﺎﺑﻲ ﮐﻨﺪ‪ .‬ﺍﻳﻦ ﻣﺤﺪﻭﺩﻳﺖ‬
‫ﺑﺰﺭﮔﻲ ﻣﺤﺴﻮﺏ ﻣﻲﺷﻮﺩ‪ .‬ﺍﮔﺮ ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﮐﻼﺱ ﻭﺍﻟﺪ ﺍﻧﺘﻈﺎﺭﺍﺕ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﺭﺍ‬
‫ﺑﺮﺁﻭﺭﺩﻩ ﻧﺴﺎﺯﻧﺪ‪ ،‬ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﻧﺎﮐﺎﺭﺁﻣﺪ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻭﺿﺎﻉ ﺯﻣﺎﻧﻲ ﻭﺧﻴﻢﺗﺮ ﻣﻲﺷﻮﺩ ﮐﻪ ﻫﻴﭻ‬
‫ﺗﺎﺑﻊ ﻋﻤﻮﻣﻲ ﺑﺮﺍﻱ ﺩﺳﺘﺮﺳﻲ ﺑﻪ ﻳﮏ ﺩﺍﺩۀ ﺧﺼﻮﺻﻲ ﺩﺭ ﮐﻼﺱ ﻭﺍﻟﺪ ﻭﺟﻮﺩ ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﺪ‪.‬‬
‫ﺩﺭ ﮐﻼﺱ ‪ Book‬ﻣﺜﺎﻝ ‪ 11‐2‬ﻳﮏ ﺩﺍﺩۀ ﺧﺼﻮﺻﻲ ﺑﻪ ﻧﺎﻡ ‪ author‬ﺩﺍﺭﻳﻢ ﮐﻪ‬
‫ﺑﻴﺎﻥﮔﺮ ﻧﺎﻡ ﻧﻮﻳﺴﻨﺪﻩ ﺍﺳﺖ‪ .‬ﺩﺭ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ‪ Ebook‬ﺑﻪ ﻫﻴﭻ ﺗﺮﺗﻴﺒﻲ ﻧﻤﻲﺗﻮﺍﻧﻴﻢ ﺑﻪ ﺍﻳﻦ‬
‫ﻋﻀﻮ ﺩﺳﺘﺮﺳﻲ ﭘﻴﺪﺍ ﮐﻨﻴﻢ‪ .‬ﻣﻲﺗﻮﺍﻧﻴﻢ ﺍﻳﻦ ﺩﺍﺩۀ ﻋﻀﻮ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺻﺮﻳﺢ ﺩﺭ ﮐﻼﺱ ‪Ebook‬‬
‫ﺑﮕﻨﺠﺎﻧﻴﻢ ﻭﻟﻲ ﺍﻳﻦ ﮐﺎﺭ ﻣﻨﻄﻘﻲ ﻧﻴﺴﺖ ﺯﻳﺮﺍ ‪ Ebook‬ﺯﻳﺮﻣﺠﻤﻮﻋﻪﺍﻱ ﺍﺯ ‪ Book‬ﺍﺳﺖ ﻭ‬
‫ﺑﺎﻳﺪ ﺑﺘﻮﺍﻧﺪ ﺧﻮﺍﺹ ﺁﻥ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺑﮕﻴﺮﺩ‪ .‬ﺩﺭ ﭼﻨﻴﻦ ﻣﻮﺍﻗﻌﻲ ‪ C++‬ﺗﻮﺻﻴﻪ ﻣﻲﮐﻨﺪ ﺑﻪ ﺟﺎﻱ‬
‫ﺍﻳﻦ ﮐﻪ ‪ author‬ﺭﺍ ﺩﺭ ﮐﻼﺱ ﻭﺍﻟﺪ ﺑﻪ ﺻﻮﺭﺕ ﺧﺼﻮﺻﻲ )‪ (private‬ﺍﻋﻼﻥ ﮐﻨﻴﻢ‪ ،‬ﺁﻥ‬
‫ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺣﻔﺎﻇﺖ ﺷﺪﻩ )‪ (protected‬ﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﻢ‪ .‬ﺍﻋﻀﺎﻱ ‪ protected‬ﻳﺎ‬
‫ﺣﻔﺎﻇﺖ ﺷﺪﻩ‪ 1‬ﺍﻋﻀﺎﻳﻲ ﻫﺴﺘﻨﺪ ﮐﻪ ﻣﺜﻞ ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺍﺯ ﺧﺎﺭﺝ ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ‬
‫ﻧﻴﺴﺘﻨﺪ ﻭﻟﻲ ﻣﺜﻞ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﻣﻲﺗﻮﺍﻧﻨﺪ ﺗﻮﺳﻂ ﮐﻼﺱﻫﺎﻱ ﻓﺮﺯﻧﺪ ﻣﺴﺘﻘﻴﻤﺎ ﺩﺳﺘﻴﺎﺑﻲ‬
‫ﺷﻮﻧﺪ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﺗﻮﺟﻪ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 11‐5‬ﻛﻼﺱ ‪ Book‬ﺑﺎ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ‪protected‬‬


‫ﮐﺪﻫﺎﻱ ﺯﻳﺮ ﻫﻤﺎﻥ ﮐﺪﻫﺎﻱ ﻣﺜﺎﻝ ‪ 11‐2‬ﻫﺴﺘﻨﺪ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﺍﻋﻀﺎﻱ‬
‫‪ private‬ﮐﻼﺱ ‪ Book‬ﺑﻪ ﺍﻋﻀﺎﻱ ‪ protected‬ﺗﺒﺪﻳﻞ ﺷﺪﻩﺍﻧﺪ ﻭ ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ‬

‫‪1 – Protected members‬‬


365 ‫ ﺗﺮﮐﻴﺐ و وراﺛﺖ‬/ ‫ﻓﺼﻞ ﻳﺎزدهﻢ‬

:‫ ﺍﻓﺰﻭﺩﻩ ﺷﺪﻩ‬Ebook ‫ ﺑﻪ ﮐﻼﺱ ﻣﺸﺘﻖ ﺷﺪۀ‬printAuthor() ‫ ﻭ‬setAuthor()


class Book
{ public:
Book(char* n = " ", int i = 0, int p = 0) :
name(n), id(i), page(p) { }
void printName() { cout << name; }
void printId() { cout << id; }
void printPage() { cout << page; }
protected:
string name, author;
int id, page;
}
class Ebook : public Book
{ public:
Ebook(char* n, int i=0, int p=0) :
Book(n,i,p), format("PDF"), size(0) {}
void setAuthor(char* a) { author = a; }
void setSize(int s){ size = s; }
void setFormat(char* f) { format = f; }
void printAuthor() { cout << author; }
void printFormat() { cout << format; }
void printSize() { cout << size; }
protected:
string format;
int size;
}

‫ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ‬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‬‬

‫‪cout‬‬ ‫<<‬ ‫‪"\n‬‬ ‫‪pages:‬‬ ‫;"‬ ‫;)(‪reference.printPage‬‬


‫‪cout‬‬ ‫<<‬ ‫‪"\n‬‬ ‫‪format:‬‬ ‫;"‬ ‫;)(‪reference.printFormat‬‬
‫‪cout‬‬ ‫<<‬ ‫‪"\n‬‬ ‫‪size(KB):‬‬ ‫;"‬ ‫;)(‪reference.printSize‬‬
‫‪cout‬‬ ‫<<‬ ‫‪"\n‬‬ ‫‪Author:‬‬ ‫;"‬ ‫;)(‪reference.printAuthor‬‬
‫}‬
‫‪Ebook name:‬‬ ‫‪C++‬‬
‫‪id:‬‬ ‫‪1‬‬
‫‪pages:‬‬ ‫‪450‬‬
‫‪format:‬‬ ‫‪PDF‬‬
‫‪size(KB):‬‬ ‫‪5500‬‬
‫‪Author:‬‬ ‫‪P.N.U‬‬

‫ﺑﻨﺎﺑﺮ ﺁﻥﭼﻪ ﮔﻔﺘﻴﻢ‪ ،‬ﺍﻋﻀﺎﻱ ﻳﮏ ﮐﻼﺱ ﺳﻪ ﮔﺮﻭﻩ ﻫﺴﺘﻨﺪ‪ :‬ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﻳﺎ‬
‫‪ 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‬ﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﺪ‪.‬‬

‫‪ 11‐5‬ﻏﻠﺒﻪ ﮐﺮﺩﻥ ﺑﺮ ﻭﺭﺍﺛﺖ‬


‫ﺍﮔﺮ ‪ Y‬ﺯﻳﺮ ﮐﻼﺳﻲ ﺍﺯ ‪ X‬ﺑﺎﺷﺪ‪ ،‬ﺁﻧﮕﺎﻩ ﺍﺷﻴﺎﻱ ‪ Y‬ﻫﻢۀ ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﻭ ﺣﻔﺎﻇﺖ ﺷﺪۀ‬
‫ﮐﻼﺱ ‪ X‬ﺭﺍ ﺍﺭﺙ ﻣﻲﺑﺮﻧﺪ‪ .‬ﻣﺜﻼ ﺗﻤﺎﻣﻲ ﺍﺷﻴﺎﻱ ‪ Ebook‬ﺗﺎﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ )(‪printName‬‬
‫ﺍﺯ ﮐﻼﺱ ‪ Book‬ﺭﺍ ﺑﻪ ﺍﺭﺙ ﻣﻲﺑﺮﻧﺪ‪ .‬ﺑﻪ ﺗﺎﺑﻊ )(‪ printName‬ﻳﮏ »ﻋﻀﻮ ﻣﻮﺭﻭﺛﻲ«‬
‫ﻣﻲﮔﻮﻳﻴﻢ‪ .‬ﮔﺎﻫﻲ ﻻﺯﻡ ﺍﺳﺖ ﻳﮏ ﻧﺴﺦۀ ﻣﺤﻠﻲ ﺍﺯ ﻋﻀﻮ ﻣﻮﺭﻭﺛﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﻢ‪ .‬ﻳﻌﻨﻲ ﮐﻼﺱ‬
‫ﻓﺮﺯﻧﺪ‪ ،‬ﻋﻀﻮﻱ ﻫﻢ ﻧﺎﻡ ﺑﺎ ﻋﻀﻮ ﻣﻮﺭﻭﺛﻲ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﮐﻪ ﻣﺨﺼﻮﺹ ﺑﻪ ﺧﻮﺩﺵ ﺑﺎﺷﺪ ﻭ‬
‫ﺍﺭﺛﻲ ﻧﺒﺎﺷﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﻓﺮﺽ ﮐﻨﻴﺪ ﮐﻼﺱ ‪ X‬ﻳﮏ ﻋﻀﻮ ﻋﻤﻮﻣﻲ ﺑﻪ ﻧﺎﻡ ‪ p‬ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﻭ‬
‫ﮐﻼﺱ ‪ Y‬ﺯﻳﺮ ﮐﻼﺱ ‪ X‬ﺑﺎﺷﺪ‪ .‬ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ ﺍﺷﻴﺎﻱ ﮐﻼﺱ ‪ Y‬ﻋﻀﻮ ﻣﻮﺭﻭﺛﻲ ‪ p‬ﺭﺍ ﺧﻮﺍﻫﻨﺪ‬
‫ﺩﺍﺷﺖ‪ .‬ﺣﺎﻝ ﺍﮔﺮ ﻳﮏ ﻋﻀﻮ ﺑﻪ ﻫﻤﺎﻥ ﻧﺎﻡ ‪ p‬ﺩﺭ ﺯﻳﺮﮐﻼﺱ ‪ Y‬ﺑﻪ ﺷﮑﻞ ﺻﺮﻳﺢ ﺍﻋﻼﻥ ﮐﻨﻴﻢ‪،‬‬
‫ﺍﻳﻦ ﻋﻀﻮ ﺟﺪﻳﺪ‪ ،‬ﻋﻀﻮ ﻣﻮﺭﻭﺛﻲ ﻫﻢﻧﺎﻣﺶ ﺭﺍ ﻣﻐﻠﻮﺏ ﻣﻲﮐﻨﺪ‪ .‬ﺑﻪ ﺍﻳﻦ ﻋﻀﻮ ﺟﺪﻳﺪ‪» ،‬ﻋﻀﻮ‬
‫ﻏﺎﻟﺐ« ﻣﻲﮔﻮﻳﻴﻢ‪ .‬ﺑﻨﺎﺑﺮﺍﻳﻦ ﺍﮔﺮ ‪ y1‬ﻳﮏ ﺷﻲ ﺍﺯ ﮐﻼﺱ ‪ Y‬ﺑﺎﺷﺪ‪ y1.p ،‬ﺑﻪ ﻋﻀﻮ ‪ p‬ﻏﺎﻟﺐ‬
‫ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ ﻧﻪ ﺑﻪ ‪ p‬ﻣﻮﺭﻭﺛﻲ‪ .‬ﺍﻟﺒﺘﻪ ﻫﻨﻮﺯ ﻫﻢ ﻣﻲﺗﻮﺍﻥ ﺑﻪ ‪ p‬ﻣﻮﺭﻭﺛﻲ ﺩﺳﺘﺮﺳﻲ ﺩﺍﺷﺖ‪.‬‬
‫ﻋﺒﺎﺭﺕ ‪ y1.X::p‬ﺑﻪ ‪ p‬ﻣﻮﺭﻭﺛﻲ ﺩﺳﺘﻴﺎﺑﻲ ﺩﺍﺭﺩ‪.‬‬
‫ﻫﻢ ﻣﻲﺗﻮﺍﻥ ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﻣﻮﺭﻭﺛﻲ ﺭﺍ ﻣﻐﻠﻮﺏ ﮐﺮﺩ ﻭ ﻫﻢ ﺍﻋﻀﺎﻱ ﺗﺎﺑﻌﻲ ﻣﻮﺭﻭﺛﻲ‬
‫ﺭﺍ‪ .‬ﻳﻌﻨﻲ ﺍﮔﺮ ﮐﻼﺱ ‪ X‬ﺩﺍﺭﺍﻱ ﻳﮏ ﻋﻀﻮ ﺗﺎﺑﻌﻲ ﻋﻤﻮﻣﻲ ﺑﻪ ﻧﺎﻡ )(‪ f‬ﺑﺎﺷﺪ ﻭ ﺩﺭ ﺯﻳﺮﮐﻼﺱ‬
‫‪ Y‬ﻧﻴﺰ ﺗﺎﺑﻊ )(‪ f‬ﺭﺍ ﺑﻪ ﺷﮑﻞ ﺻﺮﻳﺢ ﺍﻋﻼﻥ ﮐﻨﻴﻢ‪ ،‬ﺁﻧﮕﺎﻩ )(‪ y1.f‬ﺑﻪ ﺗﺎﺑﻊ ﻏﺎﻟﺐ ﺍﺷﺎﺭﻩ‬
‫ﺩﺍﺭﺩ ﻭ )(‪ y1.X::f‬ﺑﻪ ﺗﺎﺑﻊ ﻣﻮﺭﻭﺛﻲ ﺍﺷﺎﺭﻩ ﺩﺍﺭﺩ‪ .‬ﺩﺭ ﺑﺮﺧﻲ ﺍﺯ ﻣﺮﺍﺟﻊ ﺑﻪ ﺗﻮﺍﺑﻊ ﻏﺎﻟﺐ‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪368‬‬

‫‪ override‬ﻣﻲﮔﻮﻳﻨﺪ ﻭ ﺩﺍﺩﻩﻫﺎﻱ ﻏﺎﻟﺐ ﺭﺍ ‪ dominate‬ﻣﻲﻧﺎﻣﻨﺪ‪ .‬ﻣﺎ ﺩﺭ ﺍﻳﻦ ﮐﺘﺎﺏ ﻫﺮ‬


‫ﺩﻭ ﻣﻔﻬﻮﻡ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﺍﻋﻀﺎﻱ ﻏﺎﻟﺐ ﺑﻪ ﮐﺎﺭ ﻣﻲﺑﺮﻳﻢ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﻧﮕﺎﻩ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 11‐6‬ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﻭ ﺗﺎﺑﻌﻲ ﻏﺎﻟﺐ‬


‫‪class X‬‬
‫‪{ public:‬‬
‫} ;"‪void f() { cout << "Now X::f() is running\n‬‬
‫;‪int a‬‬
‫;}‬

‫‪class Y : public X‬‬


‫‪{ public:‬‬
‫} ;"‪void f() { cout << "Now Y::f() is running\n‬‬
‫)(‪// this f() overrides X::f‬‬
‫;‪int a‬‬
‫‪// this a dominates X::a‬‬
‫;}‬

‫ﺍﻋﻀﺎﻱ ﺯﻳﺮﮐﻼﺱ ‪ 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‬‬

‫* ﻣﺜﺎﻝ ‪ 11‐7‬ﺳﺎﺯﻧﺪﻩﻫﺎ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩﻫﺎﻱ ﻭﺍﻟﺪ‬


‫‪class X‬‬
‫‪{ public:‬‬
‫} ;"‪X() { cout << "X::X() constructor executing\n‬‬
‫} ;"‪~X() { cout << "X::X() destructor executing\n‬‬
‫;}‬

‫‪clas Y : public X‬‬


‫‪{ public:‬‬
‫} ;"‪Y() { cout << "Y::Y() constructor executing\n‬‬
‫} ;"‪~Y() { cout << "Y::Y() destructor executing\n‬‬
‫;}‬
‫‪clas Z : public Y‬‬
‫‪{ public:‬‬
‫};"‪Z(int n) {cout << "Z::Z(int) constructor executing\n‬‬
‫} ;"‪~Z() { cout << "Z::Z() destructor executing\n‬‬
‫;}‬

‫)(‪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‬ﺍﺳﺖ ﻭ ﺗﻮﺍﺑﻊ ﺁﻥ ﺭﺍ ﻣﻲﺷﻨﺎﺳﺪ‪ .‬ﻣﺜﺎﻝ ﺯﻳﺮ ﺍﻳﻦ ﻣﻄﻠﺐ ﺭﺍ ﺗﺎﻳﻴﺪ ﻣﻲﮐﻨﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 11‐8‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺯ ﮐﻼﺱ ﻭﺍﻟﺪ ﺑﻪ ﺷﻴﺌﻲ ﺍﺯ ﮐﻼﺱ ﻓﺮﺯﻧﺪ‬


‫ﺩﺭ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ‪ ،‬ﮐﻼﺱ ‪ Y‬ﺯﻳﺮﮐﻼﺳﻲ ﺍﺯ ‪ X‬ﺍﺳﺖ‪ .‬ﻫﺮ ﺩﻭﻱ ﺍﻳﻦ ﮐﻼﺱﻫﺎ ﺩﺍﺭﺍﻱ ﻳﮏ‬
‫ﻋﻀﻮ ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )(‪ f‬ﻫﺴﺘﻨﺪ ﻭ ‪ p‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺍﺯ ﻧﻮﻉ *‪ X‬ﺗﻌﺮﻳﻒ ﺷﺪﻩ‪:‬‬
‫‪class X‬‬
‫‪{ public:‬‬
‫} ;"‪void f() { cout << "X::f() executing\n‬‬
‫;}‬

‫‪class Y : public X‬‬


‫‪{ public:‬‬
‫} ;"‪void f() { cout << "Y::f() executing\n‬‬
‫}‬

‫)(‪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‬ﻓﺮﺍ ﺧﻮﺍﻧﺪﻩ ﺷﻮﺩ‪ .‬ﺑﺮﺍﻱ ﺑﺮﺁﻭﺭﺩﻥ ﺍﻳﻦ ﺍﻧﺘﻈﺎﺭ‪ ،‬ﺍﺯ »ﺗﻮﺍﺑﻊ‬
‫ﻣﺠﺎﺯﻱ« ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﻢ‪.‬‬

‫‪ 11‐7‬ﺗﻮﺍﺑﻊ ﻣﺠﺎﺯﻱ ﻭ ﭼﻨﺪﺭﻳﺨﺘﻲ‬


‫ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ‪ 1‬ﺗﺎﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ﺑﺎ ﮐﻠﻢۀ ﮐﻠﻴﺪﻱ ‪ virtual‬ﻣﺸﺨﺺ ﻣﻲﺷﻮﺩ‪ .‬ﻭﻗﺘﻲ‬
‫ﻳﮏ ﺗﺎﺑﻊ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺍﻋﻼﻥ ﻣﻲﺷﻮﺩ‪ ،‬ﻳﻌﻨﻲ ﺩﺭ ﺣﺪﺍﻗﻞ ﻳﮑﻲ ﺍﺯ ﮐﻼﺱﻫﺎﻱ ﻓﺮﺯﻧﺪ ﻧﻴﺰ‬
‫ﺗﺎﺑﻌﻲ ﺑﺎ ﻫﻤﻴﻦ ﻧﺎﻡ ﻭﺟﻮﺩ ﺩﺍﺭﺩ‪ .‬ﺗﻮﺍﺑﻊ ﻣﺠﺎﺯﻱ ﺍﻣﮑﺎﻥ ﻣﻲﺩﻫﻨﺪ ﮐﻪ ﻫﻨﮕﺎﻡ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ‬
‫ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‪ ،‬ﺑﺘﻮﺍﻧﻴﻢ ﺑﺪﻭﻥ ﺩﺭ ﻧﻈﺮ ﮔﺮﻓﺘﻦ ﻧﻮﻉ ﺍﺷﺎﺭﻩﮔﺮ‪ ،‬ﺑﻪ ﺗﻮﺍﺑﻊ ﺷﻲﺀ ﺟﺎﺭﻱ ﺩﺳﺘﻴﺎﺑﻲ‬
‫ﮐﻨﻴﻢ‪ .‬ﺑﻪ ﻣﺜﺎﻝ ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 11‐9‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﻣﺠﺎﺯﻱ‬


‫ﺍﻳﻦ ﺑﺮﻧﺎﻣﻪ‪ ،‬ﻫﻤﺎﻥ ﺑﺮﻧﺎﻡۀ ﻣﺜﺎﻝ ‪ 11‐8‬ﺍﺳﺖ ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﮐﻪ ﺗﺎﺑﻊ )(‪ f‬ﺍﺯ ﮐﻼﺱ‬
‫ﻭﺍﻟﺪ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺍﻋﻼﻥ ﺷﺪﻩ ﺍﺳﺖ‪:‬‬
‫‪class X‬‬
‫‪{ public:‬‬
‫} ;"‪virtual void f() { cout << "X::f() executing\n‬‬

‫‪1 – Virtual function‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪374‬‬

‫;}‬

‫‪class Y : public X‬‬


‫‪{ public:‬‬
‫} ;"‪void f() { cout << "Y::f() executing\n‬‬
‫}‬

‫)(‪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‬ﺑﻪ ﭼﻪ ﻧﻮﻉ ﺷﻴﺌﻲ ﺍﺷﺎﺭﻩ ﮐﻨﺪ‪ ،‬ﻧﺘﺎﻳﺞ ﻣﺘﻔﺎﻭﺗﻲ‬
‫ﺗﻮﻟﻴﺪ ﻣﻲﮐﻨﺪ‪ .‬ﺩﻗﺖ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﻓﻘﻂ ﺗﻮﺍﺑﻊ ﮐﻼﺱ ﻭﺍﻟﺪ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ‬
‫ﻣﻲﮐﻨﻨﺪ‪ .‬ﻣﺜﺎﻝ ﺯﻳﺮ‪ ،‬ﻧﻤﻮﻥۀ ﻣﻔﻴﺪﺗﺮﻱ ﺍﺯ ﭼﻨﺪﺭﻳﺨﺘﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 11‐10‬ﭼﻨﺪﺭﻳﺨﺘﻲ ﺍﺯ ﻃﺮﻳﻖ ﺗﻮﺍﺑﻊ ﻣﺠﺎﺯﻱ‬


‫ﺳﻪ ﮐﻼﺱ ﺯﻳﺮ ﺭﺍ ﺩﺭ ﻧﻈﺮ ﺑﮕﻴﺮﻳﺪ‪ .‬ﺑﺪﻭﻥ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊﻣﺠﺎﺯﻱ‪ ،‬ﺑﺮﻧﺎﻣﻪ ﺁﻥ ﻃﻮﺭ ﮐﻪ‬
‫ﻣﻮﺭﺩ ﺍﻧﺘﻈﺎﺭ ﺍﺳﺖ ﮐﺎﺭ ﻧﻤﻲﮐﻨﺪ‪:‬‬
‫‪class Book‬‬
‫‪{ public:‬‬
‫;])‪Book(char* s) { name = new char[strlen(s+1‬‬
‫;)‪strcpy(name, s‬‬
‫}‬
‫" ‪void print() { cout << "Here is a book with name‬‬
375 ‫ ﺗﺮﮐﻴﺐ و وراﺛﺖ‬/ ‫ﻓﺼﻞ ﻳﺎزدهﻢ‬

<< name << ".\n";


}
protected:
char* name;
};
class Ebook : public Book
{ public:
Ebook(char* s, float g) : Book(s), size(g) {}
void print() { cout << "Here is an Ebook with name "
<< name << " and size "
<< size << " MB.\n";
}
private:
float size;
}
class Notebook : public Book
{ public:
Notebook(char* s, int n) : Book(s) , pages(n) {}
void print() { cout << "Here is a Notebook with name "
<< name << " and " << pages
<< " pages.\n";
}
private:
int pages;
};

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.‬‬

‫ﻓﺮﺍﺧﻮﺍﻧﻲ )(‪ b->print‬ﭼﻨﺪﺭﻳﺨﺘﻲ ﺩﺍﺭﺩ ﻭ ﺑﺴﺘﻪ ﺑﻪ ﺍﻳﻦ ﮐﻪ ‪ b‬ﺑﻪ ﭼﻪ ﻧﻮﻋﻲ ﺍﺷﺎﺭﻩ‬


‫ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪ ،‬ﻧﺘﻴﺞۀ ﻣﺘﻔﺎﻭﺗﻲ ﺧﻮﺍﻫﺪ ﺩﺍﺷﺖ‪.‬‬
‫‪377‬‬ ‫ﻓﺼﻞ ﻳﺎزدهﻢ ‪ /‬ﺗﺮﮐﻴﺐ و وراﺛﺖ‬

‫ﺯﻣﺎﻧﻲ ﻳﮏ ﺗﺎﺑﻊ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ ﻣﻲﮐﻨﻨﺪ ﮐﻪ ﺍﺣﺘﻤﺎﻝ ﺑﺪﻫﻨﺪ ﺣﺪﺍﻗﻞ ﻳﮏ‬
‫ﺯﻳﺮﮐﻼﺱ‪ ،‬ﻧﺴﺨﻪﺍﻱ ﻣﺤﻠﻲ ﺍﺯ ﻫﻤﺎﻥ ﺗﺎﺑﻊ ﺭﺍ ﺧﻮﺍﻫﺪ ﺩﺍﺷﺖ‪.‬‬

‫‪ 11‐8‬ﻧﺎﺑﻮﺩﻛﻨﻨﺪۀ ﻣﺠﺎﺯﻱ‬
‫ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺗﻌﺮﻳﻒ ﺗﻮﺍﺑﻊ ﻣﺠﺎﺯﻱ‪ ،‬ﺑﻪ ﻧﻈﺮ ﻣﻲﺭﺳﺪ ﮐﻪ ﻧﻤﻲﺗﻮﺍﻥ ﺗﻮﺍﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻭ‬
‫ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ ﻧﻤﻮﺩ ﺯﻳﺮﺍ ﺳﺎﺯﻧﺪﻩﻫﺎ ﻭ ﻧﺎﺑﻮﺩﮔﺮﻫﺎ ﺩﺭ ﮐﻼﺱﻫﺎﻱ‬
‫ﻭﺍﻟﺪ ﻭ ﻓﺮﺯﻧﺪ‪ ،‬ﻫﻢﻧﺎﻡ ﻧﻴﺴﺘﻨﺪ‪ .‬ﺩﺭ ﺍﺻﻞ‪ ،‬ﺳﺎﺯﻧﺪﻩﻫﺎ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ‬
‫ﮐﺮﺩ ﺍﻣﺎ ﻧﺎﺑﻮﺩﮔﺮﻫﺎ ﻗﺺۀ ﺩﻳﮕﺮﻱ ﺩﺍﺭﻧﺪ‪ .‬ﻣﺜﺎﻝ ﺑﻌﺪﻱ ﺍﻳﺮﺍﺩ ﻣﻬﻠﮑﻲ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﮐﻪ ﺑﺎ‬
‫ﻣﺠﺎﺯﻱ ﮐﺮﺩﻥ ﻧﺎﺑﻮﺩﮔﺮ‪ ،‬ﺑﺮﻃﺮﻑ ﻣﻲﺷﻮﺩ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 11‐11‬ﺣﺎﻓﻆۀ ﮔﻢ ﺷﺪﻩ‬


‫ﺑﻪ ﺑﺮﻧﺎﻡۀ ﺯﻳﺮ ﺩﻗﺖ ﮐﻨﻴﺪ‪:‬‬
‫‪class X‬‬
‫‪{ public:‬‬
‫‪x() { p = new int[2]; cout << "X().‬‬ ‫} ;"‬
‫} "‪~X() { delete [] p; cout << "~X().\n‬‬
‫‪private:‬‬
‫;‪int* p‬‬
‫;}‬

‫‪class Y : public X‬‬


‫‪{ public:‬‬
‫;]‪Y() { q = new int[1023‬‬ ‫‪cout << "Y() : Y::q = " << q‬‬
‫‪<< ".‬‬ ‫} ;"‬
‫;‪~Y() { delete [] q‬‬ ‫‪cout << "~Y().‬‬ ‫} ;"‬
‫‪private:‬‬
‫;‪int* q‬‬
‫;}‬

‫)(‪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‬ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪ .‬ﺩﺭ ﻳﮏ ﻧﺮﻡﺍﻓﺰﺍﺭ ﺑﺰﺭﮒ‪ ،‬ﺍﻳﻦ ﻣﺴﺎﻟﻪ‬
‫ﻣﻲﺗﻮﺍﻧﺪ ﺑﺎﻋﺚ ﺑﺮﻭﺯ ﻓﺎﺟﻌﻪ ﺷﻮﺩ‪ .‬ﻣﺨﺼﻮﺻﺎ ﺍﻳﻦ ﮐﻪ ﭘﻴﺪﺍ ﮐﺮﺩﻥ ﺍﻳﺮﺍﺩ ﻓﻮﻕ ﺑﺴﻴﺎﺭ ﻣﺸﮑﻞ‬
‫ﺍﺳﺖ‪ .‬ﭘﺲ ﺑﺨﺎﻃﺮ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻴﺪ ﮐﻪ ﻫﺮ ﻭﻗﺖ ﺍﺯ ﺍﺷﻴﺎﻱ ﭘﻮﻳﺎ ﺩﺭ ﺑﺮﻧﺎﻣﻪ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲﮐﻨﻴﺪ‪،‬‬
‫ﻧﺎﺑﻮﺩﮔﺮ ﮐﻼﺱ ﻭﺍﻟﺪ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺍﻋﻼﻥ ﻧﻤﺎﻳﻴﺪ‪.‬‬

‫‪ 11‐9‬ﻛﻼﺱﻫﺎﻱ ﭘﺎﻱۀ ﺍﻧﺘﺰﺍﻋﻲ‬


‫ﺩﺭ ﺷﻲﮔﺮﺍﻳﻲ ﺭﺳﻢ ﺑﺮ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺳﺎﺧﺘﺎﺭ ﺑﺮﻧﺎﻣﻪ ﻭ ﮐﻼﺱﻫﺎ ﺭﺍ ﻃﻮﺭﻱ ﻃﺮﺍﺣﻲ‬
‫ﮐﻨﻨﺪ ﮐﻪ ﺑﺘﻮﺍﻥ ﺁﻥﻫﺎ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﻧﻤﻮﺩﺍﺭ ﺩﺭﺧﺘﻲ ﺷﺒﻴﻪ ﺯﻳﺮ ﻧﺸﺎﻥ ﺩﺍﺩ‪:‬‬

‫‪BOOK‬‬

‫‪Paper BOOK‬‬ ‫‪EBOOK‬‬

‫‪REFERENCE‬‬ ‫‪MAGAZINE‬‬ ‫‪COOKBOOK‬‬ ‫‪PDF‬‬ ‫‪CHM‬‬ ‫‪HLP‬‬ ‫‪HTML‬‬

‫ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﻣﻤﮑﻦ ﺍﺳﺖ ﺑﺨﻮﺍﻫﻴﻢ ﺩﺭ ﻳﮏ ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﮐﻼﺱ ‪ Html‬ﺍﺳﺘﻔﺎﺩﻩ ﮐﻨﻴﻢ‪ .‬ﺷﻲﮔﺮﺍﻳﻲ‬
‫ﺗﻮﺻﻴﻪ ﺩﺍﺭﺩ ﮐﻪ ﺍﺑﺘﺪﺍ ﮐﻼﺱ ﭘﺎﻱۀ ‪ Book‬ﺭﺍ ﺍﻋﻼﻥ ﮐﻨﻴﻢ ﻭ ﺍﺯ ﺁﻥ ﮐﻼﺱ‪ Ebook ،‬ﺭﺍ‬
‫ﻣﺸﺘﻖ‪ 2‬ﮐﺮﺩﻩ ﻭ ﺍﺯ ‪ Ebook‬ﻧﻴﺰ ﺯﻳﺮﮐﻼﺱ ‪ Html‬ﺭﺍ ﻣﺸﺘﻖ ﻧﻤﺎﻳﻴﻢ‪ .‬ﮔﺮﭼﻪ ﻣﻤﮑﻦ ﺍﺳﺖ‬
‫ﺍﻳﻦ ﺭﻭﺵ ﺩﺭ ﺍﺑﺘﺪﺍ ﺑﻲﻣﻌﻨﻲ ﻭ ﺣﺘﻲ ﻭﻗﺖﮔﻴﺮ ﻭ ﻏﻴﺮﻣﻨﻄﻘﻲ ﺑﻪ ﻧﻈﺮ ﺑﺮﺳﺪ‪ ،‬ﺍﻣﺎ ﺩﺭ ﺍﺻﻞ‬
‫ﺭﻭﺵ ﻣﺬﮐﻮﺭ ﺳﺒﺐ ﺳﻬﻮﻟﺖ ﺩﺭ ﺍﺻﻼﺡ ﻭ ﭘﺸﺘﻴﺒﺎﻧﻲ ﺑﺮﻧﺎﻣﻪ ﻣﻲﺷﻮﺩ‪ .‬ﺍﻳﻦ ﻣﻮﺿﻮﻉ ﺩﺭ‬
‫ﺑﺮﻧﺎﻣﻪﻫﺎﻱ ﺗﺠﺎﺭﻱ‪ ،‬ﺑﺴﻴﺎﺭ ﻣﻬﻢ ﻭ ﺣﻴﺎﺗﻲ ﺍﺳﺖ‪.‬‬
‫ﻣﻲﺩﺍﻧﻴﻢ ﮐﻪ ﺩﺭ ﺳﺎﺧﺘﺎﺭ ﻓﻮﻕ‪ ،‬ﻫﺮ ﮐﻼﺱ ﺩﺍﺭﺍﻱ ﺗﻮﺍﺑﻊ ﺧﺎﺻﻲ ﺍﺳﺖ ﮐﻪ ﺭﻓﺘﺎﺭﻫﺎﻱ‬
‫ﻭﻳﮋۀ ﺁﻥ ﮐﻼﺱ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ‪ .‬ﻣﻤﮑﻦ ﺍﺳﺖ ﺗﻮﺍﺑﻌﻲ ﻣﺠﺎﺯﻱ ﻫﻢ ﻭﺟﻮﺩ ﺩﺍﺷﺘﻪ ﺑﺎﺷﻨﺪ ﮐﻪ‬
‫ﺩﺭ ﻫﻢۀ ﺯﻳﺮﮐﻼﺱﻫﺎ ﻣﻐﻠﻮﺏ ﺷﻮﻧﺪ ﻭ ﻧﺴﺨﻪﺍﻱ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥﻫﺎ ﺍﻳﺠﺎﺩ ﺷﻮﺩ‪ .‬ﺩﺭ ﺍﻳﻦ ﺣﺎﻟﺖ‬
‫ﺩﻳﮕﺮ ﻧﻴﺎﺯﻱ ﻧﻴﺴﺖ ﮐﻪ ﺗﻮﺍﺑﻊ ﻣﺬﮐﻮﺭ ﺩﺭ ﮐﻼﺱﻫﺎﻱ ﭘﺎﻳﻪ ﺩﺍﺭﺍﻱ ﺑﺪﻧﻪ ﺑﺎﺷﻨﺪ ﺯﻳﺮﺍ ﺍﻳﻦ ﺑﺪﻧﻪ‬

‫‪1 – Memory leak‬‬ ‫‪2 - Derrive‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪380‬‬

‫ﻫﺮﮔﺰ ﺑﻪ ﮐﺎﺭ ﮔﺮﻓﺘﻪ ﻧﻤﻲﺷﻮﺩ‪ .‬ﺩﺭ ﺍﻳﻦ ﮔﻮﻧﻪ ﻣﻮﺍﻗﻊ‪ ،‬ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﺭﺍ ﺑﻪ ﺷﮑﻞ ﻳﮏ ﺗﺎﺑﻊ‬
‫ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ‪ 1‬ﺍﻋﻼﻥ ﻣﻲﮐﻨﻨﺪ‪ .‬ﻳﮏ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ‪ ،‬ﺗﺎﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ﻫﻴﭻ‬
‫ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻧﺪﺍﺭﺩ ﻭ ﻓﺎﻗﺪ ﺑﺪﻧﻪ ﺍﺳﺖ‪ .‬ﺩﺭ ﺍﻳﻦ ﺗﻮﺍﺑﻊ ﺑﻪ ﺟﺎﻱ ﺑﺪﻧﻪ‪ ،‬ﻋﺒﺎﺭﺕ ;‪ =0‬ﺭﺍ ﻗﺮﺍﺭ‬
‫ﻣﻲﺩﻫﻨﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ‪ ،‬ﺩﺭ ﻫﻢۀ ﮐﻼﺱﻫﺎﻱ ﺭﺍﺑﻂۀ ﻓﻮﻕ‪ ،‬ﺗﺎﺑﻌﻲ ﺑﻪ ﻧﺎﻡ )(‪ print‬ﻭﺟﻮﺩ‬
‫ﺩﺍﺭﺩ ﮐﻪ ﻫﺮ ﺯﻳﺮﮐﻼﺱ ﻳﮏ ﻧﺴﺦۀ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥ ﺭﺍ ﺩﺍﺭﺩ‪ .‬ﭘﺲ ﻻﺯﻡ ﻧﻴﺴﺖ ﮐﻪ ﺩﺭ ﮐﻼﺱ‬
‫ﭘﺎﻱۀ ‪ Book‬ﺑﺮﺍﻱ ﺍﻳﻦ ﺗﺎﺑﻊ‪ ،‬ﺑﺪﻧﻪﺍﻱ ﺗﻌﺮﻳﻒ ﮐﻨﻴﻢ‪ .‬ﻓﻘﻂ ﮐﺎﻓﻲ ﺍﺳﺖ ﺩﺳﺘﻮﺭ‬
‫;‪virtual void print()=0‬‬

‫ﺭﺍ ﺩﺭ ﮐﻼﺱ ‪ Book‬ﺑﮕﻨﺠﺎﻧﻴﻢ‪ .‬ﻫﺮ ﻭﻗﺖ ﭼﻨﻴﻦ ﻋﺒﺎﺭﺗﻲ ﺩﺭ ﺑﺪﻥۀ ﻳﮏ ﮐﻼﺱ ﻇﺎﻫﺮ ﺷﻮﺩ‪،‬‬
‫ﺑﻪ ﺍﻳﻦ ﻣﻌﻨﺎﺳﺖ ﮐﻪ ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﺩﺭ ﺍﻳﻦ ﮐﻼﺱ ﻫﺮﮔﺰ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﻲﺷﻮﺩ ﻭ ﺯﻳﺮﮐﻼﺳﻲ‬
‫ﻭﺟﻮﺩ ﺩﺍﺭﺩ ﮐﻪ ﻧﺴﺦۀ ﻣﺤﻠﻲ ﺍﺯ ﺁﻥ ﺗﺎﺑﻊ ﺭﺍ ﺑﻪ ﮐﺎﺭ ﺧﻮﺍﻫﺪ ﮔﺮﻓﺖ‪ .‬ﮐﻼﺳﻲ ﮐﻪ ﻳﮏ ﻳﺎ ﭼﻨﺪ‬
‫ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺭﺍ ﮐﻼﺱ ﭘﺎﻱۀ ﺍﻧﺘﺰﺍﻋﻲ‪ 2‬ﻣﻲﻧﺎﻣﻴﻢ )ﺑﻪ ﺁﻥ ﮐﻼﺱ ﭘﺎﻱۀ‬
‫ﻣﺠﺮﺩ ﻧﻴﺰ ﮔﻔﺘﻪ ﻣﻲﺷﻮﺩ(‪ .‬ﮐﻼﺱﻫﺎﻱ ﭘﺎﻱۀ ﻣﺠﺮﺩ ﻓﻘﻂ ﺑﺮﺍﻱ ﺳﺎﺧﺘﻦ ﻭ ﺍﺷﺘﻘﺎﻕ ﺯﻳﺮﮐﻼﺱﻫﺎ‬
‫ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﻧﺪ ﻭ ﻫﻴﭻ ﺷﻴﺌﻲ ﻣﺴﺘﻘﻴﻤﺎ ﺍﺯ ﺭﻭﻱ ﺁﻥﻫﺎ ﺳﺎﺧﺘﻪ ﻧﻤﻲﺷﻮﺩ‪ .‬ﮐﻼﺳﻲ ﮐﻪ ﻫﻴﭻ ﺗﺎﺑﻊ‬
‫ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﻧﺪﺍﺷﺘﻪ ﺑﺎﺷﺪ ﺭﺍ »ﮐﻼﺱ ﻣﺸﺘﻖﺷﺪۀ ﻭﺍﻗﻌﻲ« ﻣﻲﮔﻮﻳﻴﻢ‪ .‬ﺍﺷﻴﺎﻱ ﺩﺍﺧﻞ ﻳﮏ‬
‫ﺑﺮﻧﺎﻣﻪ ﺍﺯ ﺭﻭﻱ ﮐﻼﺱﻫﺎﻱ ﻣﺸﺘﻖ ﺷﺪۀ ﻭﺍﻗﻌﻲ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﻧﺪ‪.‬‬
‫ﺍﮔﺮ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﺍﺻﻼ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﻲﺷﻮﺩ‪ ،‬ﭘﺲ ﺍﺻﻼ ﭼﺮﺍ ﺁﻥ ﺭﺍ ﺍﻋﻼﻥ ﻣﻲﮐﻨﻴﻢ؟‬
‫ﭘﺎﺳﺦ ﺍﻳﻦ ﺍﺳﺖ ﮐﻪ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﺭﺍ ﺍﻋﻼﻥ ﻣﻲﮐﻨﻴﻢ ﺗﺎ ﺗﺎﮐﻴﺪ ﮐﻨﻴﻢ ﮐﻪ ﺩﺳﺖ ﮐﻢ ﻳﮏ‬
‫ﺯﻳﺮﮐﻼﺱ ﺑﺎﻳﺪ ﻧﺴﺨﻪﺍﻱ ﻣﺤﻠﻲ ﺍﺯ ﺍﻳﻦ ﺗﺎﺑﻊ ﺭﺍ ﺩﺍﺷﺘﻪ ﺑﺎﺷﺪ‪.‬‬

‫* ﻣﺜﺎﻝ ‪ 11‐12‬ﮐﻼﺱ ﭘﺎﻱۀ ﺍﻧﺘﺰﺍﻋﻲ ﻭ ﻳﮏ ﮐﻼﺱ ﻣﺸﺘﻖ ﺷﺪۀ ﻭﺍﻗﻌﻲ‬


‫‪class VCR‬‬
‫‪{ public:‬‬
‫‪virtual‬‬ ‫‪void‬‬ ‫;‪on() =0‬‬
‫‪virtual‬‬ ‫‪void‬‬ ‫;‪off() =0‬‬
‫‪virtual‬‬ ‫‪void‬‬ ‫;‪record() =0‬‬
‫‪virtual‬‬ ‫‪void‬‬ ‫;‪stop() =0‬‬
‫‪virtual‬‬ ‫‪void‬‬ ‫;‪play() =0‬‬
‫;}‬

‫‪1 – Pure virtual function‬‬ ‫‪2 – Abstracted base class‬‬


‫‪381‬‬ ‫ﻓﺼﻞ ﻳﺎزدهﻢ ‪ /‬ﺗﺮﮐﻴﺐ و وراﺛﺖ‬

‫‪class Video : public VCR‬‬


‫‪{ public:‬‬
‫;)(‪void on‬‬
‫;)(‪void off‬‬
‫;)(‪void record‬‬
‫;)(‪void stop‬‬
‫;)(‪void play‬‬
‫;}‬
‫‪class Camera : public VCR‬‬
‫‪{ public:‬‬
‫;)(‪void on‬‬
‫;)(‪void off‬‬
‫;)(‪void record‬‬
‫;)(‪void stop‬‬
‫;)(‪void play‬‬
‫;}‬

‫ﺩﺭ ﮐﺪ ﺑﺎﻻ‪ ،‬ﮐﻼﺱ ‪ 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‬‬ ‫ﻓﺼﻞ ﻳﺎزدهﻢ ‪ /‬ﺗﺮﮐﻴﺐ و وراﺛﺖ‬

‫‪ – 5‬ﻋﻀﻮ ﺣﻔﺎﻇﺖﺷﺪﻩ ﻋﻀﻮﻱ ﺍﺳﺖ ﮐﻪ‪:‬‬


‫ﺍﻟﻒ – ﺍﺯ ﺧﺎﺭﺝ ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﺍﺳﺖ‬
‫ﺏ – ﻓﻘﻂ ﺗﻮﺳﻂ ﺍﻋﻀﺎﻱ ﻫﻤﺎﻥ ﮐﻼﺱ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﺍﺳﺖ‬
‫ﺝ – ﻓﻘﻂ ﺗﻮﺳﻂ ﺍﻋﻀﺎﻱ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﺍﺳﺖ‬
‫ﺩ – ﺗﻮﺳﻂ ﺍﻋﻀﺎﻱ ﻫﻤﺎﻥ ﮐﻼﺱ ﻭ ﺍﻋﻀﺎﻱ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﻗﺎﺑﻞ ﺩﺳﺘﻴﺎﺑﻲ ﺍﺳﺖ‬
‫‪ – 6‬ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺩﺭ ﻭﺭﺍﺛﺖ ﺻﺤﻴﺢ ﻧﻴﺴﺖ؟‬
‫ﺍﻟﻒ – ﻗﺒﻞ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺳﺎﺯﻧﺪۀ ﻭﺍﻟﺪ‪ ،‬ﺳﺎﺯﻧﺪۀ ﻓﺮﺯﻧﺪ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ‬
‫ﺏ – ﺑﻌﺪ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﺎﺑﻮﺩﮐﻨﻨﺪۀ ﻓﺮﺯﻧﺪ‪ ،‬ﻧﺎﺑﻮﺩﮐﻨﻨﺪۀ ﻭﺍﻟﺪ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ‬
‫ﺝ – ﻗﺒﻞ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺳﺎﺯﻧﺪۀ ﻓﺮﺯﻧﺪ‪ ،‬ﺳﺎﺯﻧﺪۀ ﻭﺍﻟﺪ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻣﻲﺷﻮﺩ‬
‫ﺩ – ﻓﺮﺍﺧﻮﺍﻧﻲ ﺳﺎﺯﻧﺪۀ ﻭﺍﻟﺪ ﺭﺑﻄﻲ ﺑﻪ ﺳﺎﺯﻧﺪۀ ﻓﺮﺯﻧﺪ ﻧﺪﺍﺭﺩ‬
‫‪ – 7‬ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺩﺭ ﺑﺎﺭۀ ﭼﻨﺪﺭﻳﺨﺘﻲ ﮐﻼﺱﻫﺎ ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ – ﭼﻨﺪﺭﻳﺨﺘﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﻣﺠﺎﺯﻱ ﺍﻣﮑﺎﻥﭘﺬﻳﺮ ﺍﺳﺖ‬
‫ﺏ – ﭼﻨﺪﺭﻳﺨﺘﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻋﻀﺎﻱ ﺣﻔﺎﻇﺖﺷﺪﻩ ﺍﻣﮑﺎﻥﭘﺬﻳﺮ ﺍﺳﺖ‬
‫ﺝ – ﭼﻨﺪﺭﻳﺨﺘﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﺷﻴﺎﻱ ﺛﺎﺑﺖ ﺍﻣﮑﺎﻥﭘﺬﻳﺮ ﺍﺳﺖ‬
‫ﺩ – ﭼﻨﺪﺭﻳﺨﺘﻲ ﺑﻪ ﻭﺳﻴﻞۀ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ ﺍﻣﮑﺎﻥﭘﺬﻳﺮ ﺍﺳﺖ‬
‫‪ – 8‬ﮐﺪ ;)(‪ p->f‬ﻣﻌﺎﺩﻝ ﮐﺪﺍﻡ ﮐﺪ ﺯﻳﺮ ﺍﺳﺖ؟‬
‫ﺏ – ;)(‪p.f‬‬ ‫ﺍﻟﻒ ‐ ;)(‪*p.f‬‬
‫ﺩ – )()‪p.(*f‬‬ ‫ﺝ – ;)(‪(*p).f‬‬
‫‪ – 9‬ﮐﺪﺍﻡ ﮔﺰﻳﻨﻪ ﺻﺤﻴﺢ ﺍﺳﺖ؟‬
‫ﺍﻟﻒ – ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﮐﻼﺱ ﻭﺍﻟﺪ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ ﮐﺮﺩ ﻭﻟﻲ‬
‫ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ‬
‫ﺏ – ﺗﺎﺑﻊ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﮐﻼﺱ ﻭﺍﻟﺪ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ ﮐﺮﺩ ﻭﻟﻲ‬
‫ﺳﺎﺯﻧﺪﻩ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ‬
‫ﺝ – ﻫﺮ ﺩﻭ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺭﺍ ﻣﻲﺗﻮﺍﻥ ﺩﺭ ﮐﻼﺱ ﻭﺍﻟﺪ ﺑﻪ ﺷﮑﻞ ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ ﮐﺮﺩ‬
‫ﺩ – ﻫﻴﭻ ﻳﮏ ﺍﺯ ﺩﻭ ﺗﺎﺑﻊ ﺳﺎﺯﻧﺪﻩ ﻭ ﻧﺎﺑﻮﺩﮐﻨﻨﺪﻩ ﺭﺍ ﻧﻤﻲﺗﻮﺍﻥ ﺩﺭ ﮐﻼﺱ ﻭﺍﻟﺪ ﺑﻪ ﺷﮑﻞ‬
‫ﻣﺠﺎﺯﻱ ﺗﻌﺮﻳﻒ ﮐﺮﺩ‪.‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪384‬‬

‫‪ – 10‬ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﺗﺎﺑﻌﻲ ﺍﺳﺖ ﮐﻪ ‪:‬‬


‫ﺍﻟﻒ – ﻫﻴﭻ ﭘﻴﺎﺩﻩﺳﺎﺯﻱ ﻧﺪﺍﺭﺩ ﻭ ﺗﻌﺮﻳﻒ ﺁﻥ ﻓﺎﻗﺪ ﺑﺪﻧﻪ ﺍﺳﺖ‬
‫ﺏ – ﻧﻤﻲﺗﻮﺍﻧﺪ ﺗﻮﺳﻂ ﮐﻼﺱ ﻓﺮﺯﻧﺪ ﺑﻪ ﺍﺭﺙ ﮔﺮﻓﺘﻪ ﺷﻮﺩ‬
‫ﺝ – ﻋﻀﻮ ﻫﻴﭻ ﮐﻼﺳﻲ ﻧﻴﺴﺖ‬
‫ﺩ – ﻫﻴﭻ ﭘﺎﺭﺍﻣﺘﺮﻱ ﻧﺪﺍﺭﺩ ﻭ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺁﻥ ‪ void‬ﺍﺳﺖ‬
‫‪ – 11‬ﻭﻗﺘﻲ ﺩﺭ ﺗﻌﺮﻳﻒ ﻳﮏ ﮐﻼﺱ ﺍﺯ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﺍﺳﺘﻔﺎﺩﻩ ﺷﻮﺩ‪ ،‬ﺁﻧﮕﺎﻩ‪:‬‬
‫ﺍﻟﻒ – ﺁﻥ ﮐﻼﺱ ﺣﺪﺍﻗﻞ ﻳﮏ ﻓﺮﺯﻧﺪ ﺩﺍﺭﺩ‬
‫ﺏ – ﺩﺭ ﻳﮏ ﻓﺮﺯﻧﺪ ﺁﻥ ﮐﻼﺱ‪ ،‬ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﻳﮏ ﻧﺴﺦۀ ﻣﺤﻠﻲ ﺩﺍﺭﺩ‬
‫ﺝ – ﺗﺎﺑﻊ ﻣﺬﮐﻮﺭ ﺗﻮﺳﻂ ﺍﺷﻴﺎﻱ ﺁﻥ ﮐﻼﺱ ﻫﺮﮔﺰ ﻓﺮﺍﺧﻮﺍﻧﻲ ﻧﻤﻲﺷﻮﺩ‬
‫ﺩ – ﻫﺮ ﺳﻪ ﻣﻮﺭﺩ‬
‫‪ – 12‬ﺍﮔﺮ ﮐﻼﺳﻲ ﻳﮏ ﮐﻼﺱ ﭘﺎﻱۀ ﻣﺠﺮﺩ ﺑﺎﺷﺪ ﺁﻧﮕﺎﻩ‪:‬‬
‫ﺍﻟﻒ – ﺁﻥ ﮐﻼﺱ ﻫﻴﭻ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﻧﺪﺍﺭﺩ‬
‫ﺏ – ﺁﻥ ﮐﻼﺱ ﻳﮏ ﻳﺎ ﭼﻨﺪ ﺗﺎﺑﻊ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﺩﺍﺭﺩ‬
‫ﺝ – ﺁﻥ ﮐﻼﺱ ﺑﺮﺍﻱ ﺍﺷﺘﻘﺎﻕ ﺯﻳﺮﮐﻼﺱﻫﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲﺭﻭﺩ‬
‫ﺩ – ﮔﺰﻳﻦۀ ﺏ ﻭ ﺝ ﺻﺤﻴﺢ ﺍﺳﺖ‪.‬‬
‫‪385‬‬ ‫ﻓﺼﻞ ﻳﺎزدهﻢ ‪ /‬ﺗﺮﮐﻴﺐ و وراﺛﺖ‬

‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪ ‐1‬ﺗﺮﻛﻴﺐ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﻭﺭﺍﺛﺖ ﺩﺍﺭﺩ؟‬
‫‪ ‐2‬ﺍﻋﻀﺎﻱ ‪ protected‬ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﺍﻋﻀﺎﻱ ‪ private‬ﺩﺍﺭﻧﺪ؟‬
‫‪ ‐3‬ﺭﻓﺘﺎﺭ ﺳﺎﺯﻧﺪۀ ﭘﻴﺶﻓﺮﺽ ﻭ ﻧﺎﺑﻮﺩﻛﻨﻨﺪﻩ ﺩﺭ ﻭﺭﺍﺛﺖ ﭼﮕﻮﻧﻪ ﺍﺳﺖ؟‬
‫‪ ‐4‬ﺗﺎﺑﻊ ﻋﻀﻮ ‪) virtual‬ﻣﺠﺎﺯﻱ( ﭼﻴﺴﺖ؟‬
‫‪ ‐5‬ﺗﺎﺑﻊ ﻋﻀﻮ ﻣﺠﺎﺯﻱ ﺧﺎﻟﺺ ﭼﻴﺴﺖ؟‬
‫‪ ‐6‬ﺷﮑﺎﻑ ﺣﺎﻓﻈﻪ ﭼﮕﻮﻧﻪ ﺍﻳﺠﺎﺩ ﻣﻲﺷﻮﺩ ﻭ ﺑﺮﺍﻱ ﺟﻠﻮﮔﻴﺮﻱ ﺍﺯ ﺁﻥ ﭼﻪ ﺑﺎﻳﺪ ﮐﺮﺩ؟‬
‫‪ ‐8‬ﻛﻼﺱ ﭘﺎﻱۀ ﺍﻧﺘﺰﺍﻋﻲ ﭼﻴﺴﺖ ﻭ ﭼﺮﺍ ﺳﺎﺧﺘﻪ ﻣﻲﺷﻮﺩ؟‬
‫‪ ‐9‬ﻛﻼﺱ ﻣﺸﺘﻖﺷﺪۀ ﻭﺍﻗﻌﻲ ﭼﻴﺴﺖ؟‬
‫‪ ‐10‬ﺑﺴﺘﻪﺑﻨﺪﻱ ﺍﻳﺴﺘﺎ ﻭ ﺑﺴﺘﻪﺑﻨﺪﻱ ﭘﻮﻳﺎ ﭼﻪ ﺗﻔﺎﻭﺗﻲ ﺑﺎ ﻫﻢ ﺩﺍﺭﺩ؟‬
‫‪ ‐12‬ﭼﻨﺪﺭﻳﺨﺘﻲ ﭼﻴﺴﺖ ﻭ ﭼﮕﻮﻧﻪ ﺳﺒﺐ ﺗﻮﺳﻊۀ ﮐﻼﺱ ﻣﻲﺷﻮﺩ؟‬
‫‪ ‐13‬ﭼﻪ ﺧﻄﺎﻳﻲ ﺩﺭ ﺗﻌﺎﺭﻳﻒ ﺯﻳﺮ ﺍﺳﺖ؟‬
‫‪class X‬‬
‫‪{ protected:‬‬
‫;‪int a‬‬
‫;}‬

‫‪class Y : public X‬‬


‫‪{ public:‬‬
‫} ;‪void set(X x, int c) { x.a = c‬‬
‫;}‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪386‬‬

‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪ ‐1‬ﺳﻠﺴﻠﻪ ﻣﺮﺍﺗﺐ ﻛﻼﺱ ﺯﻳﺮ ﺭﺍ ﭘﻴﺎﺩﻩ ﺳﺎﺯﻱ ﻛﻨﻴﺪ‪:‬‬

‫‪shape‬‬

‫‪TwoDimentional‬‬ ‫‪ThreeDimentional‬‬

‫‪Triangle‬‬ ‫‪Rectangle‬‬ ‫‪Circle‬‬ ‫‪Box‬‬ ‫‪Cone‬‬ ‫‪Cylinderr Sphere‬‬

‫‪ ‐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‬‬ ‫‪1‬‬

‫‪2‬‬ ‫‪2‬‬ ‫‪2‬‬

‫‪3‬‬ ‫‪3‬‬ ‫‪3‬‬

‫‪4‬‬ ‫‪4‬‬ ‫‪4‬‬

‫‪5‬‬ ‫‪5‬‬ ‫‪5‬‬

‫‪6‬‬ ‫‪6‬‬ ‫‪6‬‬

‫‪7‬‬ ‫‪7‬‬ ‫‪7‬‬

‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬

‫‪9‬‬ ‫‪9‬‬ ‫‪9‬‬

‫‪10‬‬ ‫‪10‬‬ ‫‪10‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪388‬‬

‫ﻓﺼﻞ ﺷﺸﻢ‬ ‫ﻓﺼﻞ‬ ‫ﻓﺼﻞ‬


‫ﭘﻨﺠﻢ‬ ‫ﭼﻬﺎرم‬
‫ب‬ ‫ج‬ ‫د‬ ‫ب‬ ‫ج‬ ‫د‬ ‫ب‬ ‫ج‬ ‫د‬
‫اﻟﻒ‬ ‫اﻟﻒ‬ ‫اﻟﻒ‬

‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬

‫‪2‬‬ ‫‪2‬‬ ‫‪2‬‬

‫‪3‬‬ ‫‪3‬‬ ‫‪3‬‬

‫‪4‬‬ ‫‪4‬‬ ‫‪4‬‬

‫‪5‬‬ ‫‪5‬‬ ‫‪5‬‬

‫‪6‬‬ ‫‪6‬‬ ‫‪6‬‬

‫‪7‬‬ ‫‪7‬‬ ‫‪7‬‬

‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬

‫‪9‬‬ ‫‪9‬‬ ‫‪9‬‬

‫‪10‬‬ ‫‪10‬‬ ‫‪10‬‬


‫‪389‬‬ ‫ﺿﻤﻴﻢۀ اﻟﻒ ‪ /‬ﭘﺎﺳﺦﻧﺎمۀ ﭘﺮﺳﺶهﺎی ﮔﺰﻳﻨﻪای‬

‫ﻓﺼﻞ ‪‬ﻢ‬ ‫ﻓﺼﻞ هﺸﺘﻢ‬ ‫ﻓﺼﻞ‬


‫هﻔﺘﻢ‬
‫ب‬ ‫ج‬ ‫د‬ ‫ب‬ ‫ج‬ ‫د‬ ‫ب‬ ‫ج‬ ‫د‬
‫اﻟﻒ‬ ‫اﻟﻒ‬ ‫اﻟﻒ‬

‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬

‫‪2‬‬ ‫‪2‬‬ ‫‪2‬‬

‫‪3‬‬ ‫‪3‬‬ ‫‪3‬‬

‫‪4‬‬ ‫‪4‬‬ ‫‪4‬‬

‫‪5‬‬ ‫‪5‬‬ ‫‪5‬‬

‫‪6‬‬ ‫‪6‬‬ ‫‪6‬‬

‫‪7‬‬ ‫‪7‬‬ ‫‪7‬‬

‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬

‫‪9‬‬ ‫‪9‬‬ ‫‪9‬‬

‫‪10‬‬ ‫‪10‬‬ ‫‪10‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪390‬‬

‫ﻓﺼﻞ‬ ‫ﻓﺼﻞ دهﻢ‬


‫ﻳﺎزدهﻢ‬
‫ب‬ ‫ج‬ ‫د‬ ‫ب‬ ‫ج‬ ‫د‬
‫اﻟﻒ‬ ‫اﻟﻒ‬

‫‪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‬ﻧﻮﺷﺘﻪ ﻣﻲﺷﻮﺩ‪.‬‬

‫ﻣﺒﻨﺎﻱ ﺷﺎﻧﺰﺩﻩ‬ ‫ﻣﺒﻨﺎﻱ ﻫﺸﺖ‬ ‫ﻣﺒﻨﺎﻱ ﺩﻩ‬ ‫ﺷﺮﺡ‬ ‫ﮐﺎﺭﺍﮐﺘﺮ‬

‫‪0x0‬‬ ‫‪000‬‬ ‫‪0‬‬ ‫ﺧﺎﻟﻲ – ﭘﺎﻳﺎﻥ ﺭﺷﺘﻪ‬ ‫@‪Ctrl+‬‬

‫‪0x1‬‬ ‫‪001‬‬ ‫‪1‬‬ ‫ﺷﺮﻭﻉ ﺳﺮﺁﻳﻨﺪ‬ ‫‪Ctrl+A‬‬

‫‪0x2‬‬ ‫‪002‬‬ ‫‪2‬‬ ‫ﺷﺮﻭﻉ ﻣﺘﻦ‬ ‫‪Ctrl+B‬‬

‫‪0x3‬‬ ‫‪003‬‬ ‫‪3‬‬ ‫ﭘﺎﻳﺎﻥ ﻣﺘﻦ‬ ‫‪Ctrl+C‬‬

‫‪0x4‬‬ ‫‪004‬‬ ‫‪4‬‬ ‫ﭘﺎﻳﺎﻥ ﺍﻧﺘﻘﺎﻝ – ﭘﺎﻳﺎﻥ ﻓﺎﻳﻞ‬ ‫‪Ctrl+D‬‬

‫‪0x5‬‬ ‫‪005‬‬ ‫‪5‬‬ ‫ﺭﻫﺎﻳﻲ‪ ،‬ﺑﻴﺮﻭﻥ ﺭﻓﺘﻦ‬ ‫‪Ctrl+E‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪392‬‬

‫ﻣﺒﻨﺎﻱ ﺷﺎﻧﺰﺩﻩ‬ ‫ﻣﺒﻨﺎﻱ ﻫﺸﺖ‬ ‫ﻣﺒﻨﺎﻱ ﺩﻩ‬ ‫ﺷﺮﺡ‬ ‫ﮐﺎﺭﺍﮐﺘﺮ‬

‫‪0x6‬‬ ‫‪006‬‬ ‫‪6‬‬ ‫ﺗﺼﺪﻳﻖ‬ ‫‪Ctrl+F‬‬

‫‪0x7‬‬ ‫‪007‬‬ ‫‪7‬‬ ‫ﺯﻧﮓ‪ ،‬ﺑﻮﻕ ﺳﻴﺴﺘﻢ‬ ‫‪\a‬‬

‫‪0x8‬‬ ‫‪010‬‬ ‫‪8‬‬ ‫ﭘﺴﺨﻮﺭ‬ ‫‪\b‬‬

‫‪0x9‬‬ ‫‪011‬‬ ‫‪9‬‬ ‫ﺟﺪﻭﻝ ﺍﻓﻘﻲ‬ ‫‪\t‬‬

‫‪0xa‬‬ ‫‪012‬‬ ‫‪10‬‬ ‫ﺗﻐﺬﻳﻪ ﺧﻂ‪ ،‬ﺧﻂ ﺟﺪﻳﺪ‬ ‫‪\n‬‬

‫‪0xb‬‬ ‫‪013‬‬ ‫‪11‬‬ ‫ﺟﺪﻭﻝ ﻋﻤﻮﺩﻱ‬ ‫‪\v‬‬

‫‪0xc‬‬ ‫‪014‬‬ ‫‪12‬‬ ‫ﺗﻐﺬﻳﻪ ﻓﺮﻡ‪ ،‬ﺻﻔﺤﻪ ﺟﺪﻳﺪ‬ ‫‪\f‬‬

‫‪0xd‬‬ ‫‪015‬‬ ‫‪13‬‬ ‫ﺑﺮﮔﺸﺖ ﻧﻮﺭﺩ‬ ‫‪\r‬‬

‫‪0xe‬‬ ‫‪016‬‬ ‫‪14‬‬ ‫ﺷﻴﻔﺖ)ﺟﺎﺑﺠﺎﻳﻲ( ﺑﻴﺮﻭﻥ‬ ‫‪Ctrl+N‬‬

‫‪0xf‬‬ ‫‪017‬‬ ‫‪15‬‬ ‫ﺷﻴﻔﺖ ﺩﺍﺧﻞ‬ ‫‪Ctrl+O‬‬

‫‪0x10‬‬ ‫‪020‬‬ ‫‪16‬‬ ‫ﭘﻴﻮﻧﺪ ﺩﺍﺩﻩ‬ ‫‪Ctrl+P‬‬

‫‪0x11‬‬ ‫‪021‬‬ ‫‪17‬‬ ‫ﻭﺳﻴﻞۀ ﮐﻨﺘﺮﻟﻲ ‪ ،1‬ﭘﻴﻤﺎﻳﺶ ﻣﺠﺪﺩ‬ ‫‪Ctrl+Q‬‬

‫‪0x12‬‬ ‫‪022‬‬ ‫‪18‬‬ ‫ﻭﺳﻴﻞۀ ﮐﻨﺘﺮﻟﻲ ‪2‬‬ ‫‪Ctrl+R‬‬

‫‪0x13‬‬ ‫‪023‬‬ ‫‪19‬‬ ‫ﻭﺳﻴﻞۀ ﮐﻨﺘﺮﻟﻲ ‪ ،3‬ﺗﻮﻗﻒ ﭘﻴﻤﺎﻳﺶ‬ ‫‪Ctrl+S‬‬

‫‪0x14‬‬ ‫‪024‬‬ ‫‪20‬‬ ‫ﻭﺳﻴﻞۀ ﮐﻨﺘﺮﻟﻲ ‪4‬‬ ‫‪Ctrl+T‬‬

‫‪0x15‬‬ ‫‪025‬‬ ‫‪21‬‬ ‫ﺗﺼﺪﻳﻖ ﻣﻨﻔﻲ‬ ‫‪Ctrl+U‬‬

‫‪0x16‬‬ ‫‪026‬‬ ‫‪22‬‬ ‫ﺑﻲﮐﺎﺭ ﮐﺮﺩﻥ ﺭﺧﺪﺍﺩ ﻫﻢﺯﻣﺎﻥ‬ ‫‪Ctrl+V‬‬

‫‪0x17‬‬ ‫‪027‬‬ ‫‪23‬‬ ‫ﭘﺎﻳﺎﻥ ﺑﻠﻮﮎ ﺍﻧﺘﻘﺎﻝ‬ ‫‪Ctrl+W‬‬

‫‪0x18‬‬ ‫‪030‬‬ ‫‪24‬‬ ‫ﻟﻐﻮ‬ ‫‪Ctrl+X‬‬

‫‪0x19‬‬ ‫‪031‬‬ ‫‪25‬‬ ‫ﭘﺎﻳﺎﻥ ﭘﻴﺎﻡ‪ ،‬ﻭﻗﻔﻪ‬ ‫‪Ctrl+Y‬‬

‫‪0x1a‬‬ ‫‪032‬‬ ‫‪26‬‬ ‫ﺟﺎﻧﺸﻴﻨﻲ‪ ،‬ﺧﺮﻭﺝ‬ ‫‪Ctrl+Z‬‬

‫‪0x1b‬‬ ‫‪033‬‬ ‫‪27‬‬ ‫ﺑﻴﺮﻭﻥ ﺭﻓﺘﻦ‪ ،‬ﺭﻫﺎﻳﻲ‬ ‫[‪Ctrl+‬‬

‫‪0x1c‬‬ ‫‪034‬‬ ‫‪28‬‬ ‫ﺟﺪﺍﺳﺎﺯ ﻓﺎﻳﻞ‬ ‫‪Ctrl+/‬‬

‫‪0x1d‬‬ ‫‪035‬‬ ‫‪29‬‬ ‫ﺟﺪﺍﺳﺎﺯ ﮔﺮﻭﻩ‬ ‫]‪Ctrl+‬‬

‫‪0x1e‬‬ ‫‪036‬‬ ‫‪30‬‬ ‫ﺟﺪﺍﺳﺎﺯ ﺭﮐﻮﺭﺩ‬ ‫^‪Ctrl+‬‬

‫‪0x1f‬‬ ‫‪037‬‬ ‫‪31‬‬ ‫ﺟﺪﺍﺳﺎﺯ ﻭﺍﺣﺪ‬ ‫_‪Ctrl+‬‬


‫‪393‬‬ ‫ﺿﻤﻴﻢۀ ب ‪ /‬ﺟﺪول اﺳﮑﯽ‬

‫ﻣﺒﻨﺎﻱ ﺷﺎﻧﺰﺩﻩ‬ ‫ﻣﺒﻨﺎﻱ ﻫﺸﺖ‬ ‫ﻣﺒﻨﺎﻱ ﺩﻩ‬ ‫ﺷﺮﺡ‬ ‫ﮐﺎﺭﺍﮐﺘﺮ‬

‫‪0x20‬‬ ‫‪040‬‬ ‫‪32‬‬ ‫ﺟﺎﻱ ﺧﺎﻟﻲ‬

‫‪0x21‬‬ ‫‪041‬‬ ‫‪33‬‬ ‫ﻋﻼﻣﺖ ﺗﻌﺠﺐ‬ ‫!‬

‫‪0x22‬‬ ‫‪042‬‬ ‫‪34‬‬ ‫ﻋﻼﻣﺖ ﻧﻘﻞ ﻗﻮﻝ‬ ‫"‬

‫‪0x23‬‬ ‫‪043‬‬ ‫‪35‬‬ ‫ﻋﻼﻣﺖ ﺷﻤﺎﺭﻩ‬ ‫‪#‬‬

‫‪0x24‬‬ ‫‪044‬‬ ‫‪36‬‬ ‫ﻋﻼﻣﺖ ﺩﻻﺭ‬ ‫‪$‬‬

‫‪0x25‬‬ ‫‪045‬‬ ‫‪37‬‬ ‫ﻋﻼﻣﺖ ﺩﺭﺻﺪ‬ ‫‪%‬‬

‫‪0x26‬‬ ‫‪046‬‬ ‫‪38‬‬ ‫ﻋﻼﻣﺖ ‪and‬‬ ‫&‬

‫‪0x27‬‬ ‫‪047‬‬ ‫‪39‬‬ ‫ﻧﻘﻞ ﻗﻮﻝ ﺗﻨﻬﺎ‪ ،‬ﺁﭘﺴﺘﺮﻭﻑ‬ ‫'‬

‫‪0x28‬‬ ‫‪050‬‬ ‫‪40‬‬ ‫ﭘﺮﺍﻧﺘﺰ ﭼﭗ‬ ‫(‬

‫‪0x29‬‬ ‫‪051‬‬ ‫‪41‬‬ ‫ﭘﺮﺍﻧﺘﺰ ﺭﺍﺳﺖ‬ ‫)‬

‫‪0x2a‬‬ ‫‪052‬‬ ‫‪42‬‬ ‫ﺿﺮﺑﺪﺭ‪ ،‬ﺳﺘﺎﺭﻩ‬ ‫*‬

‫‪0x2b‬‬ ‫‪053‬‬ ‫‪43‬‬ ‫ﺑﻌﻼﻭﻩ‬ ‫‪+‬‬

‫‪0x2c‬‬ ‫‪054‬‬ ‫‪44‬‬ ‫ﮐﺎﻣﺎ‪ ،‬ﻭﻳﺮﮔﻮﻝ‬ ‫‪,‬‬

‫‪0x2d‬‬ ‫‪055‬‬ ‫‪45‬‬ ‫ﺗﻔﺮﻳﻖ‬ ‫‪-‬‬

‫‪0x2e‬‬ ‫‪056‬‬ ‫‪46‬‬ ‫ﻧﻘﻄﻪ‪ ،‬ﻧﻘﻄﻪ ﺍﻋﺸﺎﺭ‬ ‫‪.‬‬

‫‪0x2f‬‬ ‫‪057‬‬ ‫‪47‬‬ ‫ﺍﺳﻠﺶ‬ ‫‪/‬‬

‫‪0x30‬‬ ‫‪060‬‬ ‫‪48‬‬ ‫ﺭﻗﻢ ﺻﻔﺮ‬ ‫‪0‬‬

‫‪0x31‬‬ ‫‪061‬‬ ‫‪49‬‬ ‫ﺭﻗﻢ ﻳﮏ‬ ‫‪1‬‬

‫‪0x32‬‬ ‫‪062‬‬ ‫‪50‬‬ ‫ﺭﻗﻢ ﺩﻭ‬ ‫‪2‬‬

‫‪0x33‬‬ ‫‪063‬‬ ‫‪51‬‬ ‫ﺭﻗﻢ ﺳﻪ‬ ‫‪3‬‬

‫‪0x34‬‬ ‫‪064‬‬ ‫‪52‬‬ ‫ﺭﻗﻢ ﭼﻬﺎﺭ‬ ‫‪4‬‬

‫‪0x35‬‬ ‫‪065‬‬ ‫‪53‬‬ ‫ﺭﻗﻢ ﭘﻨﺞ‬ ‫‪5‬‬

‫‪0x36‬‬ ‫‪066‬‬ ‫‪54‬‬ ‫ﺭﻗﻢ ﺷﺶ‬ ‫‪6‬‬

‫‪0x37‬‬ ‫‪067‬‬ ‫‪55‬‬ ‫ﺭﻗﻢ ﻫﻔﺖ‬ ‫‪7‬‬

‫‪0x38‬‬ ‫‪070‬‬ ‫‪56‬‬ ‫ﺭﻗﻢ ﻫﺸﺖ‬ ‫‪8‬‬

‫‪0x39‬‬ ‫‪071‬‬ ‫‪57‬‬ ‫ﺭﻗﻢ ﻧﻪ‬ ‫‪9‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪394‬‬

‫ﻣﺒﻨﺎﻱ ﺷﺎﻧﺰﺩﻩ‬ ‫ﻣﺒﻨﺎﻱ ﻫﺸﺖ‬ ‫ﻣﺒﻨﺎﻱ ﺩﻩ‬ ‫ﺷﺮﺡ‬ ‫ﮐﺎﺭﺍﮐﺘﺮ‬

‫‪0x3a‬‬ ‫‪072‬‬ ‫‪58‬‬ ‫ﮐﻮﻟﻦ‬ ‫‪:‬‬

‫‪0x3b‬‬ ‫‪073‬‬ ‫‪59‬‬ ‫ﺳﻤﻴﮑﻮﻟﻦ‬ ‫;‬

‫‪0x3c‬‬ ‫‪074‬‬ ‫‪60‬‬ ‫ﮐﻮﭼﮏﺗﺮ‬ ‫<‬

‫‪0x3d‬‬ ‫‪075‬‬ ‫‪61‬‬ ‫ﻣﺴﺎﻭﻱ‬ ‫=‬

‫‪0x3e‬‬ ‫‪076‬‬ ‫‪62‬‬ ‫ﺑﺰﺭﮒﺗﺮ‬ ‫>‬

‫‪0x3f‬‬ ‫‪077‬‬ ‫‪63‬‬ ‫ﻋﻼﻣﺖ ﺳﻮﺍﻝ‬ ‫?‬

‫‪0x40‬‬ ‫‪0100‬‬ ‫‪64‬‬ ‫ﻋﻼﻣﺖ ﺗﺠﺎﺭﻱ‬ ‫@‬

‫‪0x41‬‬ ‫‪0101‬‬ ‫‪65‬‬ ‫ﺣﺮﻑ ‪ A‬ﺑﺰﺭﮒ‬ ‫‪A‬‬

‫‪0x42‬‬ ‫‪0102‬‬ ‫‪66‬‬ ‫ﺣﺮﻑ ‪ B‬ﺑﺰﺭﮒ‬ ‫‪B‬‬

‫‪0x43‬‬ ‫‪0103‬‬ ‫‪67‬‬ ‫ﺣﺮﻑ ‪ C‬ﺑﺰﺭﮒ‬ ‫‪C‬‬

‫‪0x44‬‬ ‫‪0104‬‬ ‫‪68‬‬ ‫ﺣﺮﻑ ‪ D‬ﺑﺰﺭﮒ‬ ‫‪D‬‬

‫‪0x45‬‬ ‫‪0105‬‬ ‫‪69‬‬ ‫ﺣﺮﻑ ‪ E‬ﺑﺰﺭﮒ‬ ‫‪E‬‬

‫‪0x46‬‬ ‫‪0106‬‬ ‫‪70‬‬ ‫ﺣﺮﻑ ‪ F‬ﺑﺰﺭﮒ‬ ‫‪F‬‬

‫‪0x47‬‬ ‫‪0107‬‬ ‫‪71‬‬ ‫ﺣﺮﻑ ‪ G‬ﺑﺰﺭﮒ‬ ‫‪G‬‬

‫‪0x48‬‬ ‫‪0110‬‬ ‫‪72‬‬ ‫ﺣﺮﻑ ‪ H‬ﺑﺰﺭﮒ‬ ‫‪H‬‬

‫‪0x49‬‬ ‫‪0111‬‬ ‫‪73‬‬ ‫ﺣﺮﻑ ‪ I‬ﺑﺰﺭﮒ‬ ‫‪I‬‬

‫‪0x4a‬‬ ‫‪0112‬‬ ‫‪74‬‬ ‫ﺣﺮﻑ ‪ J‬ﺑﺰﺭﮒ‬ ‫‪J‬‬

‫‪0x4b‬‬ ‫‪0113‬‬ ‫‪75‬‬ ‫ﺣﺮﻑ ‪ K‬ﺑﺰﺭﮒ‬ ‫‪K‬‬

‫‪0x4c‬‬ ‫‪0114‬‬ ‫‪76‬‬ ‫ﺣﺮﻑ ‪ L‬ﺑﺰﺭﮒ‬ ‫‪L‬‬

‫‪0x4d‬‬ ‫‪0115‬‬ ‫‪77‬‬ ‫ﺣﺮﻑ ‪ M‬ﺑﺰﺭﮒ‬ ‫‪M‬‬

‫‪0x4e‬‬ ‫‪0116‬‬ ‫‪78‬‬ ‫ﺣﺮﻑ ‪ N‬ﺑﺰﺭﮒ‬ ‫‪N‬‬

‫‪0x4f‬‬ ‫‪0117‬‬ ‫‪79‬‬ ‫ﺣﺮﻑ ‪ O‬ﺑﺰﺭﮒ‬ ‫‪O‬‬

‫‪0x50‬‬ ‫‪0120‬‬ ‫‪80‬‬ ‫ﺣﺮﻑ ‪ P‬ﺑﺰﺭﮒ‬ ‫‪P‬‬

‫‪0x51‬‬ ‫‪0121‬‬ ‫‪81‬‬ ‫ﺣﺮﻑ ‪ Q‬ﺑﺰﺭﮒ‬ ‫‪Q‬‬

‫‪0x52‬‬ ‫‪0122‬‬ ‫‪82‬‬ ‫ﺣﺮﻑ ‪ R‬ﺑﺰﺭﮒ‬ ‫‪R‬‬

‫‪0x53‬‬ ‫‪0123‬‬ ‫‪83‬‬ ‫ﺣﺮﻑ ‪ S‬ﺑﺰﺭﮒ‬ ‫‪S‬‬


‫‪395‬‬ ‫ﺿﻤﻴﻢۀ ب ‪ /‬ﺟﺪول اﺳﮑﯽ‬

‫ﻣﺒﻨﺎﻱ ﺷﺎﻧﺰﺩﻩ‬ ‫ﻣﺒﻨﺎﻱ ﻫﺸﺖ‬ ‫ﻣﺒﻨﺎﻱ ﺩﻩ‬ ‫ﺷﺮﺡ‬ ‫ﮐﺎﺭﺍﮐﺘﺮ‬

‫‪0x54‬‬ ‫‪0124‬‬ ‫‪84‬‬ ‫ﺣﺮﻑ ‪ T‬ﺑﺰﺭﮒ‬ ‫‪T‬‬

‫‪0x55‬‬ ‫‪0125‬‬ ‫‪85‬‬ ‫ﺣﺮﻑ ‪ U‬ﺑﺰﺭﮒ‬ ‫‪U‬‬

‫‪0x56‬‬ ‫‪0126‬‬ ‫‪86‬‬ ‫ﺣﺮﻑ ‪ V‬ﺑﺰﺭﮒ‬ ‫‪V‬‬

‫‪0x57‬‬ ‫‪0127‬‬ ‫‪87‬‬ ‫ﺣﺮﻑ ‪ W‬ﺑﺰﺭﮒ‬ ‫‪W‬‬

‫‪0x58‬‬ ‫‪0130‬‬ ‫‪88‬‬ ‫ﺣﺮﻑ ‪ X‬ﺑﺰﺭﮒ‬ ‫‪X‬‬

‫‪0x59‬‬ ‫‪0131‬‬ ‫‪89‬‬ ‫ﺣﺮﻑ ‪ Y‬ﺑﺰﺭﮒ‬ ‫‪Y‬‬

‫‪0x5a‬‬ ‫‪0132‬‬ ‫‪90‬‬ ‫ﺣﺮﻑ ‪ Z‬ﺑﺰﺭﮒ‬ ‫‪Z‬‬

‫‪0x5b‬‬ ‫‪0133‬‬ ‫‪91‬‬ ‫ﺑﺮﺍﮐﺖ ﭼﭗ‬ ‫[‬

‫‪0x5c‬‬ ‫‪0134‬‬ ‫‪92‬‬ ‫ﺑﮏ ﺍﺳﻠﺶ‬ ‫\‬

‫‪0x5d‬‬ ‫‪0135‬‬ ‫‪93‬‬ ‫ﺑﺮﺍﮐﺖ ﺭﺍﺳﺖ‬ ‫]‬

‫‪0x5e‬‬ ‫‪0136‬‬ ‫‪94‬‬ ‫ﺗﻮﺍﻥ‬ ‫^‬

‫‪0x5f‬‬ ‫‪0137‬‬ ‫‪95‬‬ ‫ﺧﻂ ﺯﻳﺮﻳﻦ‬ ‫_‬

‫‪0x60‬‬ ‫‪0140‬‬ ‫‪96‬‬ ‫ﻋﻼﻣﺖ ﺗﺎﮐﻴﺪ ﻫﺠﺎ‬ ‫`‬

‫‪0x61‬‬ ‫‪0141‬‬ ‫‪97‬‬ ‫ﺣﺮﻑ ‪ A‬ﮐﻮﭼﮏ‬ ‫‪a‬‬

‫‪0x62‬‬ ‫‪0142‬‬ ‫‪98‬‬ ‫ﺣﺮﻑ ‪ B‬ﮐﻮﭼﮏ‬ ‫‪b‬‬

‫‪0x63‬‬ ‫‪0143‬‬ ‫‪99‬‬ ‫ﺣﺮﻑ ‪ C‬ﮐﻮﭼﮏ‬ ‫‪c‬‬

‫‪0x64‬‬ ‫‪0144‬‬ ‫‪100‬‬ ‫ﺣﺮﻑ ‪ D‬ﮐﻮﭼﮏ‬ ‫‪d‬‬

‫‪0x65‬‬ ‫‪0145‬‬ ‫‪101‬‬ ‫ﺣﺮﻑ ‪ E‬ﮐﻮﭼﮏ‬ ‫‪e‬‬

‫‪0x66‬‬ ‫‪0146‬‬ ‫‪102‬‬ ‫ﺣﺮﻑ ‪ F‬ﮐﻮﭼﮏ‬ ‫‪f‬‬

‫‪0x67‬‬ ‫‪0147‬‬ ‫‪103‬‬ ‫ﺣﺮﻑ ‪ G‬ﮐﻮﭼﮏ‬ ‫‪g‬‬

‫‪0x68‬‬ ‫‪0150‬‬ ‫‪104‬‬ ‫ﺣﺮﻑ ‪ H‬ﮐﻮﭼﮏ‬ ‫‪h‬‬

‫‪0x69‬‬ ‫‪0151‬‬ ‫‪105‬‬ ‫ﺣﺮﻑ ‪ I‬ﮐﻮﭼﮏ‬ ‫‪i‬‬

‫‪0x6a‬‬ ‫‪0152‬‬ ‫‪106‬‬ ‫ﺣﺮﻑ ‪ J‬ﮐﻮﭼﮏ‬ ‫‪j‬‬

‫‪0x6b‬‬ ‫‪0153‬‬ ‫‪107‬‬ ‫ﺣﺮﻑ ‪ K‬ﮐﻮﭼﮏ‬ ‫‪k‬‬

‫‪0x6c‬‬ ‫‪0154‬‬ ‫‪108‬‬ ‫ﺣﺮﻑ ‪ L‬ﮐﻮﭼﮏ‬ ‫‪l‬‬

‫‪0x6d‬‬ ‫‪0155‬‬ ‫‪109‬‬ ‫ﺣﺮﻑ ‪ M‬ﮐﻮﭼﮏ‬ ‫‪m‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪396‬‬

‫ﻣﺒﻨﺎﻱ ﺷﺎﻧﺰﺩﻩ‬ ‫ﻣﺒﻨﺎﻱ ﻫﺸﺖ‬ ‫ﻣﺒﻨﺎﻱ ﺩﻩ‬ ‫ﺷﺮﺡ‬ ‫ﮐﺎﺭﺍﮐﺘﺮ‬

‫‪0x6e‬‬ ‫‪0156‬‬ ‫‪110‬‬ ‫ﺣﺮﻑ ‪ N‬ﮐﻮﭼﮏ‬ ‫‪n‬‬

‫‪0x6f‬‬ ‫‪0157‬‬ ‫‪111‬‬ ‫ﺣﺮﻑ ‪ O‬ﮐﻮﭼﮏ‬ ‫‪o‬‬

‫‪0x70‬‬ ‫‪0160‬‬ ‫‪112‬‬ ‫ﺣﺮﻑ ‪ P‬ﮐﻮﭼﮏ‬ ‫‪p‬‬

‫‪0x71‬‬ ‫‪0161‬‬ ‫‪113‬‬ ‫ﺣﺮﻑ ‪ Q‬ﮐﻮﭼﮏ‬ ‫‪q‬‬

‫‪0x72‬‬ ‫‪0162‬‬ ‫‪114‬‬ ‫ﺣﺮﻑ ‪ R‬ﮐﻮﭼﮏ‬ ‫‪r‬‬

‫‪0x73‬‬ ‫‪0163‬‬ ‫‪115‬‬ ‫ﺣﺮﻑ ‪ S‬ﮐﻮﭼﮏ‬ ‫‪s‬‬

‫‪0x74‬‬ ‫‪0164‬‬ ‫‪116‬‬ ‫ﺣﺮﻑ ‪ T‬ﮐﻮﭼﮏ‬ ‫‪t‬‬

‫‪0x75‬‬ ‫‪0165‬‬ ‫‪117‬‬ ‫ﺣﺮﻑ ‪ U‬ﮐﻮﭼﮏ‬ ‫‪u‬‬

‫‪0x76‬‬ ‫‪0166‬‬ ‫‪118‬‬ ‫ﺣﺮﻑ ‪ V‬ﮐﻮﭼﮏ‬ ‫‪v‬‬

‫‪0x77‬‬ ‫‪0167‬‬ ‫‪119‬‬ ‫ﺣﺮﻑ ‪ W‬ﮐﻮﭼﮏ‬ ‫‪w‬‬

‫‪0x78‬‬ ‫‪0170‬‬ ‫‪120‬‬ ‫ﺣﺮﻑ ‪ X‬ﮐﻮﭼﮏ‬ ‫‪x‬‬

‫‪0x79‬‬ ‫‪0171‬‬ ‫‪121‬‬ ‫ﺣﺮﻑ ‪ Y‬ﮐﻮﭼﮏ‬ ‫‪y‬‬

‫‪0x7a‬‬ ‫‪0172‬‬ ‫‪122‬‬ ‫ﺣﺮﻑ ‪ Z‬ﮐﻮﭼﮏ‬ ‫‪z‬‬

‫‪0x7b‬‬ ‫‪0173‬‬ ‫‪123‬‬ ‫ﺁﮐﻮﻻﺩ )ﺍﺑﺮﻭ( ﭼﭗ‬ ‫{‬

‫‪0x7c‬‬ ‫‪0174‬‬ ‫‪124‬‬ ‫ﺧﻂ ﻟﻮﻟﻪ‬ ‫|‬

‫‪0x7d‬‬ ‫‪0175‬‬ ‫‪125‬‬ ‫ﺁﮐﻮﻻﺩ )ﺍﺑﺮﻭ( ﺭﺍﺳﺖ‬ ‫}‬

‫‪0x7e‬‬ ‫‪0176‬‬ ‫‪126‬‬ ‫ﻋﻼﻣﺖ ﻧﻘﻴﺾ‬ ‫~‬

‫‪0x7f‬‬ ‫‪0177‬‬ ‫‪127‬‬ ‫ﺣﺬﻑ‪ ،‬ﭘﺎﮎ ﮐﺮﺩﻥ‬ ‫‪Delete‬‬


‫ﻣﺜﺎﻝ‬ ‫ﺷﺮﺡ‬ ‫ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ‬

‫)‪(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‬‬

‫;‪b0 = b1 bitor b2‬‬ ‫ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ‪ OR‬ﺑﻴﺘﻲ ‪| :‬‬ ‫‪bitor‬‬

‫;‪bool flag‬‬ ‫ﻣﻌﺮﻑ ﻧﻮﻉ ﺑﻮﻟﻴﻦ‬ ‫‪bool‬‬

‫;‪break‬‬ ‫ﻳﮏ ﺣﻠﻘﻪ ﻳﺎ ﻋﺒﺎﺭﺕ ‪ switch‬ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲ ﺩﻫﺪ‬ ‫‪break‬‬

‫)‪case (n/10‬‬ ‫ﺩﺭ ﻋﺒﺎﺭﺕ ‪ switch‬ﺷﺮﻁ ﮐﻨﺘﺮﻟﻲ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪case‬‬

‫)‪catch(error‬‬ ‫ﻓﻌﺎﻟﻴﺖ ﻫﺎﻳﻲ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﻭﻗﺘﻲ ﻳﮏ ﺍﺳﺘﺜﻨﺎ ﺭﺥ ﻣﻲ ﺩﻫﺪ ﺑﺎﻳﺪ ﺍﺟﺮﺍ ﺷﻮﻧﺪ‬ ‫‪catch‬‬
‫ﺿﻤﻴﻤﻪ » ﺝ «‬
‫ﮐﻠﻤﺎﺕ ﮐﻠﻴﺪﻱ ‪C++‬‬

‫;‪char c‬‬ ‫ﻣﻌﺮﻑ ﻧﻮﻉ ﺻﺤﻴﺢ‬ ‫‪char‬‬

‫;} … { ‪class X‬‬ ‫ﺗﻌﺮﻳﻒ ﻳﮏ ﮐﻼﺱ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪class‬‬

‫;‪b0 = compl b1‬‬ ‫ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﻣﻨﻄﻘﻲ ‪ NOT‬ﺑﻴﺘﻲ ‪~ :‬‬ ‫‪compl‬‬

‫;‪const int s = 32‬‬ ‫ﺗﻌﺮﻳﻒ ﻳﮏ ﺛﺎﺑﺖ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪const‬‬

‫)‪pp = const_cast<T*>(p‬‬ ‫ﺑﺮﺍﻱ ﺗﻐﻴﻴﺮ ﺩﺍﺩﻥ ﺍﺷﻴﺎ ﺍﺯ ﺩﺭﻭﻥ ﺗﺎﺑﻊ ﻋﻀﻮ ﺗﻐﻴﻴﺮﻧﺎﭘﺬﻳﺮ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﺷﻮﺩ‬ ‫‪const_cast‬‬

‫;‪continue‬‬ ‫ﺩﺭ ﺣﻠﻘﻪ ﺑﻪ ﺍﺑﺘﺪﺍﻱ ﺩﻭﺭ ﺑﻌﺪﻱ ﭘﺮﺵ ﻣﻲ ﮐﻨﺪ‬ ‫‪continue‬‬

‫;‪default: sum = 0‬‬ ‫ﺣﺎﻟﺖ »ﻭﮔﺮ ﻧﻪ« ﺩﺭ ﻋﺒﺎﺭﺕ ‪switch‬‬ ‫‪default‬‬


‫ﻣﺜﺎﻝ‬ ‫ﺷﺮﺡ‬ ‫ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ‬

‫;‪delete a‬‬ ‫ﺣﺎﻓﻈﻪ ﺍﻱ ﺭﺍ ﮐﻪ ﺑﺎ ﻋﺒﺎﺭﺕ ‪ new‬ﺗﺨﺼﻴﺺ ﻳﺎﻓﺘﻪ ﺁﺯﺍﺩ ﻣﻲ ﮐﻨﺪ‬ ‫‪delete‬‬

‫… ‪do {…} while‬‬ ‫ﻳﮏ ﺣﻠﻘﻪ ‪ do..while‬ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪do‬‬

‫;‪double x‬‬ ‫ﻧﻮﻉ ﻋﺪﺩﻱ ﺣﻘﻴﻘﻲ )ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ ﺑﺎ ﺩﻗﺖ ﻣﻀﺎﻋﻒ(‬ ‫‪double‬‬

‫‪pp = dynamic_cast<T*>p‬‬ ‫ﺑﺮﺍﻱ ﺍﺷﺎﺭﻩ ﮔﺮ ﺩﺍﺩﻩ ﺷﺪﻩ‪ ،‬ﺍﺷﺎﺭﻩ ﮔﺮ *‪ T‬ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ‬ ‫‪dynamic_cast‬‬

‫;‪else n=0‬‬ ‫ﺑﺨﺶ ﺩﻳﮕﺮ ﻋﺒﺎﺭﺕ ‪ if‬ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪else‬‬

‫;}…{ ‪enum bool‬‬ ‫ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﺷﻮﺩ‬ ‫‪enum‬‬

‫;)‪explicit X(int n‬‬ ‫ﺑﺎﻋﺚ ﻣﻲ ﺷﻮﺩ ﺗﺎ ﺍﺯ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺿﻤﻨﻲ ﻳﮏ ﺳﺎﺯﻧﺪﻩ ﺟﻠﻮﮔﻴﺮﻱ ﺷﻮﺩ‬ ‫‪explicit‬‬

‫>‪export template<class T‬‬ ‫ﺩﺳﺘﺮﺳﻲ ﺍﺯ ﻭﺍﺣﺪ ﮐﺎﻣﭙﺎﻳﻞ ﺩﻳﮕﺮ ﺭﺍ ﻣﻤﮑﻦ ﻣﻲ ﺳﺎﺯﺩ‬ ‫‪export‬‬

‫;‪extern int max‬‬ ‫ﮐﻼﺱ ﺫﺧﻴﺮﻩ ﺳﺎﺯﻱ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﺑﻴﺮﻭﻥ ﺍﺯ ﺑﻠﻮﮎ ﻣﺤﻠﻲ ﺗﻌﺮﻳﻒ ﺷﺪﻩ ﺍﻧﺪ‬ ‫‪extern‬‬

‫;‪bool flag=false‬‬ ‫ﻳﮑﻲ ﺍﺯ ﺩﻭ ﻣﻘﺪﺍﺭ ﻧﻮﻉ ‪bool‬‬ ‫‪false‬‬

‫;‪float x‬‬ ‫ﻣﻌﺮﻑ ﻧﻮﻉ ﻋﺪﺩﻱ ﺣﻘﻴﻘﻲ )ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ(‬ ‫‪float‬‬

‫… ) ; ; ( ‪for‬‬ ‫ﻳﮏ ﺣﻠﻘﻪ ‪ for‬ﺍﻳﺠﺎﺩ ﻣﻲ ﮐﻨﺪ‬ ‫‪for‬‬

‫;)(‪friend int f‬‬ ‫ﺩﺭ ﻳﮏ ﮐﻼﺱ‪ ،‬ﺗﺎﺑﻊ ﺩﻭﺳﺖ ﺍﻳﺠﺎﺩ ﻣﻲ ﮐﻨﺪ‬ ‫‪friend‬‬

‫;‪goto error‬‬ ‫ﺑﺎﻋﺚ ﻣﻲ ﺷﻮﺩ ﺗﺎ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﺑﻪ ﻳﮏ ﺟﻤﻞۀ ﺑﺮﭼﺴﺐ ﺩﺍﺭ ﭘﺮﺵ ﮐﻨﺪ‬ ‫‪goto‬‬

‫… )‪if (n>0‬‬ ‫ﻳﮏ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ ‪ if‬ﺍﻳﺠﺎﺩ ﻣﻲ ﮐﻨﺪ‬ ‫‪if‬‬


‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬

‫;)(‪inline int f‬‬ ‫ﺗﺎﺑﻌﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﻣﺘﻦ ﺁﻥ ﺗﺎﺑﻊ ﺑﺎﻳﺪ ﺑﻪ ﺟﺎﻱ ﻓﺮﺍﺧﻮﺍﻧﻲ ﺁﻥ ﺩﺭﺝ ﺷﻮﺩ‪.‬‬ ‫‪inline‬‬

‫;‪int n‬‬ ‫ﻣﻌﺮﻑ ﻧﻮﻉ ﻋﺪﺩﻱ ﺻﺤﻴﺢ‬ ‫‪int‬‬


‫‪398‬‬
‫ﻣﺜﺎﻝ‬ ‫ﺷﺮﺡ‬ ‫ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ‬
‫‪399‬‬

‫;‪long double x‬‬ ‫ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﺍﻧﻮﺍﻉ ﮔﺴﺘﺮﺵ ﻳﺎﻓﺘﻪ ﺻﺤﻴﺢ ﻭ ﺣﻘﻴﻘﻲ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﺷﻮﺩ‬ ‫‪long‬‬

‫;‪mutable string ssn‬‬ ‫ﺑﻪ ﺗﻮﺍﺑﻊ ﺗﻐﻴﻴﺮ ﻧﺎﭘﺬﻳﺮ ﺍﺟﺎﺯﻩ ﻣﻲ ﺩﻫﺪ ﺗﺎ ﻓﻴﻠﺪ ﺭﺍ ﺗﻐﻴﻴﺮ ﺩﻫﻨﺪ‬ ‫‪mutable‬‬

‫} ;‪namespace best { int num‬‬ ‫ﺑﻠﻮﮎ ﻫﺎﻱ ﻓﻀﺎﻱ ﻧﺎﻡ )ﻣﻴﺪﺍﻥ( ﺭﺍ ﻣﻲ ﺷﻨﺎﺳﺎﻧﺪ‬ ‫‪namespace‬‬

‫;‪int* p = new int‬‬ ‫ﺣﺎﻓﻈﻪ ﺍﻱ ﺭﺍ ﺗﺨﺼﻴﺺ ﻣﻲ ﺩﻫﺪ‬ ‫‪new‬‬

‫))‪(not(x==0‬‬ ‫ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ‪ NOT‬ﻣﻨﻄﻘﻲ ‪! :‬‬ ‫‪not‬‬

‫)‪(x not_eq 0‬‬ ‫ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﻧﺎﺑﺮﺍﺑﺮﻱ ‪!= :‬‬ ‫‪not_eq‬‬
‫‪ /‬ﮐﻠﻤﺎت ﮐﻠﻴﺪی ‪C++‬‬

‫)(‪x operator++‬‬ ‫ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲ ﺭﻭﺩ‬ ‫‪opereator‬‬

‫)‪(x>0 or x<8‬‬ ‫ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ‪ OR‬ﻣﻨﻄﻘﻲ ‪|| :‬‬ ‫‪or‬‬


‫ﺿﻤﻴﻢۀ ج‬

‫;‪b1 or_eq b2‬‬ ‫ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﺗﺨﺼﻴﺼﻲ ‪ OR‬ﺑﻴﺘﻲ ‪|= :‬‬ ‫‪or_eq‬‬

‫;‪private: int n‬‬ ‫ﺍﻋﻀﺎﻱ ﺧﺼﻮﺻﻲ ﺭﺍ ﺩﺭ ﻳﮏ ﮐﻼﺱ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪private‬‬

‫;‪protected: int n‬‬ ‫ﺍﻋﻀﺎﻱ ﺣﻔﺎﻇﺖ ﺷﺪﻩ ﺭﺍ ﺩﺭ ﻳﮏ ﮐﻼﺱ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪protected‬‬

‫;‪public: int n‬‬ ‫ﺍﻋﻀﺎﻱ ﻋﻤﻮﻣﻲ ﺭﺍ ﺩﺭ ﻳﮏ ﮐﻼﺱ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪public‬‬

‫;‪register int i‬‬ ‫ﻣﺸﺨﺺ ﮐﻨﻨﺪﻩ ﮐﻼﺱ ﺫﺧﻴﺮﻩ ﺳﺎﺯﻱ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﺩﺭ ﺛﺒﺎﺕ ﻫﺎ ﺫﺧﻴﺮﻩ ﻣﻲ ﺷﻮﻧﺪ‬ ‫‪register‬‬

‫)‪pp = reinterpret_cast<T*>(p‬‬ ‫ﻳﮏ ﺷﻲ ﺑﺎ ﻧﻮﻉ ﻭ ﻣﻘﺪﺍﺭ ﺩﺍﺩﻩ ﺷﺪﻩ ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ‬ ‫‪reinterpret_cast‬‬

‫;‪return 0‬‬ ‫ﻋﺒﺎﺭﺗﻲ ﮐﻪ ﺗﺎﺑﻊ ﺭﺍ ﺧﺎﺗﻤﻪ ﻣﻲ ﺩﻫﺪ ﻭ ﻳﮏ ﻣﻘﺪﺍﺭ ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ‬ ‫‪return‬‬

‫;‪short n‬‬ ‫ﻣﻌﺮﻑ ﻧﻮﻉ ﺻﺤﻴﺢ ﻣﺤﺪﻭﺩ‬ ‫‪short‬‬

‫;‪signed char c‬‬ ‫ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﺍﻧﻮﺍﻉ ﺻﺤﻴﺢ ﻋﻼﻣﺖ ﺩﺍﺭ ﺑﻪ ﮐﺎﺭ ﻣﻲ ﺭﻭﺩ‬ ‫‪signed‬‬
‫ﻣﺜﺎﻝ‬ ‫ﺷﺮﺡ‬ ‫ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ‬

‫;)‪n = sizeof(float‬‬ ‫ﺗﻌﺪﺍﺩ ﺑﺎﻳﺖ ﻫﺎﻳﻲ ﮐﻪ ﺑﺮﺍﻱ ﺫﺧﻴﺮﻩ ﺳﺎﺯﻱ ﻳﮏ ﺷﻲ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ‬ ‫‪sizeof‬‬

‫;‪static int n‬‬ ‫ﮐﻼﺱ ﺫﺧﻴﺮﻩ ﺳﺎﺯﻱ ﺑﺮﺍﻱ ﺍﺷﻴﺎﻳﻲ ﮐﻪ ﺩﺭ ﻃﻮﻝ ﺍﺟﺮﺍﻱ ﺑﺮﻧﺎﻣﻪ ﻭﺟﻮﺩ ﺩﺍﺭﻧﺪ‬ ‫‪static‬‬

‫‪pp = static_cast<T*>p‬‬ ‫ﺑﺮﺍﻱ ﺍﺷﺎﺭﻩ ﮔﺮ ﺩﺍﺩﻩ ﺷﺪﻩ ﻳﮏ ﺍﺷﺎﺭﻩ ﮔﺮ *‪ T‬ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ‬ ‫‪static_cast‬‬

‫;}…{ ‪struct X‬‬ ‫ﺗﻌﺮﻳﻒ ﻳﮏ ﺳﺎﺧﺘﺎﺭ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪struct‬‬

‫} … { )‪switch (n‬‬ ‫ﻳﮏ ﻋﺒﺎﺭﺕ ‪ switch‬ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪switch‬‬

‫>‪template <class t‬‬ ‫ﻳﮏ ﮐﻼﺱ ‪ template‬ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ‬ ‫‪template‬‬

‫;‪return *this‬‬ ‫ﺍﺷﺎﺭﻩ ﮔﺮﻱ ﮐﻪ ﺑﻪ ﺷﻲﺀ ﺟﺎﺭﻱ ﺍﺷﺎﺭﻩ ﻣﻲ ﮐﻨﺪ‬ ‫‪this‬‬

‫;)(‪throw x‬‬ ‫ﺑﺮﺍﻱ ﺗﻮﻟﻴﺪ ﻳﮏ ﺍﺳﺘﺜﻨﺎ ﺑﻪ ﮐﺎﺭ ﻣﻲ ﺭﻭﺩ‬ ‫‪throw‬‬

‫;‪bool flag = true‬‬ ‫ﻳﮑﻲ ﺍﺯ ﻣﻘﺎﺩﻳﺮ ﻣﻤﮑﻦ ﺑﺮﺍﻱ ﻣﺘﻐﻴﺮﻫﺎﻱ ﻧﻮﻉ ‪bool‬‬ ‫‪true‬‬

‫} … { ‪try‬‬ ‫ﺑﻠﻮﮐﻲ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﺷﺎﻣﻞ ﻣﺪﻳﺮﻳﺖ ﮐﻨﻨﺪﻩ ﺍﺳﺘﺜﻨﺎ ﺍﺳﺖ‬ ‫‪try‬‬

‫;‪typedef int Num‬‬ ‫ﺑﺮﺍﻱ ﻳﮏ ﻧﻮﻉ ﻣﻮﺟﻮﺩ‪ ،‬ﻣﺘﺮﺍﺩﻓﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲ ﮐﻨﺪ‬ ‫‪typedef‬‬

‫;)(‪cout << typeid(x).name‬‬ ‫ﺷﻴﺌﻲ ﺭﺍ ﺑﺮ ﻣﻲ ﮔﺮﺩﺍﻧﺪ ﮐﻪ ﻧﻮﻉ ﻳﮏ ﻋﺒﺎﺭﺕ ﺭﺍ ﻧﺸﺎﻥ ﻣﻲ ﺩﻫﺪ‬ ‫‪typeid‬‬

‫;} … { ‪typename X‬‬ ‫ﻣﺘﺮﺍﺩﻓﻲ ﺑﺮﺍﻱ ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ ‪class‬‬ ‫‪typename‬‬

‫;‪using namespace std‬‬ ‫ﺩﺳﺘﻮﺭﻱ ﮐﻪ ﺍﺟﺎﺯﻩ ﻣﻲ ﺩﻫﺪ ﺗﺎ ﭘﻴﺸﻮﻧﺪ ﻭ ﻓﻀﺎﻱ ﻧﺎﻡ ﺣﺬﻑ ﺷﻮﺩ‬ ‫‪using‬‬

‫;} … { ‪union z‬‬ ‫ﺳﺎﺧﺘﺎﺭﻱ ﺭﺍ ﻣﺸﺨﺺ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﺍﺟﺰﺍﻱ ﺁﻥ ﺍﺯ ﺣﺎﻓﻈﻪ ﻣﺸﺘﺮﮎ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﮐﻨﻨﺪ‬ ‫‪union‬‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬

‫;‪unsigned int b‬‬ ‫ﺑﺮﺍﻱ ﺗﻌﺮﻳﻒ ﺍﻧﻮﺍﻉ ﺻﺤﻴﺢ ﺑﺪﻭﻥ ﻋﻼﻣﺖ ﺍﺳﺘﻔﺎﺩﻩ ﻣﻲ ﺷﻮﺩ‬ ‫‪unsigned‬‬

‫;)(‪virtual int f‬‬ ‫ﺗﺎﺑﻊ ﻋﻀﻮﻱ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﺩﺭ ﻳﮏ ﺯﻳﺮ ﮐﻼﺱ ﻧﻴﺰ ﺗﻌﺮﻳﻒ ﺷﺪﻩ‬ ‫‪virtual‬‬
‫‪400‬‬
‫‪401‬‬

‫ﻣﺜﺎﻝ‬ ‫ﺷﺮﺡ‬ ‫ﮐﻠﻤﻪ ﮐﻠﻴﺪﻱ‬

‫;)(‪void f‬‬ ‫ﻋﺪﻡ ﻭﺟﻮﺩ ﻧﻮﻉ ﺑﺎﺯﮔﺸﺘﻲ ﺭﺍ ﻣﻌﻴﻦ ﻣﻲ ﮐﻨﺪ‬ ‫‪void‬‬

‫;‪int volatile n‬‬ ‫ﺍﺷﻴﺎﻳﻲ ﺭﺍ ﺗﻌﺮﻳﻒ ﻣﻲ ﮐﻨﺪ ﮐﻪ ﻣﻲ ﺗﻮﺍﻧﻨﺪ ﺧﺎﺭﺝ ﺍﺯ ﮐﻨﺘﺮﻝ ﺑﺮﻧﺎﻣﻪ ﺗﻐﻴﻴﺮ ﺩﺍﺩﻩ ﺷﻮﻧﺪ‬ ‫‪volatile‬‬

‫;‪wchar_t province‬‬ ‫ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻱ ﻋﺮﻳﺾ )‪ 16‬ﺑﻴﺘﻲ( ﺑﺮﺍﻱ ‪unicode‬‬ ‫‪wchar_t‬‬

‫… )‪while (n > 0‬‬ ‫ﻳﮏ ﺣﻠﻘﻪ ‪ while‬ﺍﻳﺠﺎﺩ ﻣﻲ ﮐﻨﺪ‬ ‫‪while‬‬

‫;‪b0 = b1 xor b2‬‬ ‫ﻣﻌﺎﺩﻟﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ‪ OR‬ﺍﻧﺤﺼﺎﺭﻱ ﺑﻴﺘﻲ ‪^ :‬‬ ‫‪xor‬‬
‫‪ /‬ﮐﻠﻤﺎت ﮐﻠﻴﺪی ‪C++‬‬

‫;‪b1 xor_eq b2‬‬ ‫ﻣﻌﺎﺩﻟﻲ ﺑﺮﺍﻱ ﻋﻤﻠﮕﺮ ﺗﺨﺼﻴﺼﻲ ‪ OR‬ﺍﻧﺤﺼﺎﺭﻱ ﺑﻴﺘﻲ ‪^= :‬‬ ‫‪xor_eq‬‬
‫ﺿﻤﻴﻢۀ ج‬
‫ﺿﻤﻴﻤﻪ » ﺩ «‬
‫ﻋﻤﻠﮕﺮﻫﺎﻱ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬

‫ﺩﺭ ﺍﻳﻦ ﺟﺪﻭﻝ ﻫﻢۀ ﻋﻤﻠﮕﺮﻫﺎﻱ ‪ C++‬ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺣﻖ ﺗﻘﺪﻡ ﺁﻥﻫﺎ ﻓﻬﺮﺳﺖ ﺷﺪﻩ ﺍﺳﺖ‪ .‬ﻋﻤﻠﮕﺮﻫﺎﻱ‬
‫ﺑﺎ ﺳﻄﺢ ﺗﻘﺪﻡ ﺑﺎﻻﺗﺮ ﻗﺒﻞ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺑﺎ ﺳﻄﺢ ﺗﻘﺪﻡ ﭘﺎﻳﻴﻦﺗﺮ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﻧﺪ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﺩﺭ ﻋﺒﺎﺭﺕ‬
‫)‪ (a-b*c‬ﻋﻤﻠﮕﺮ * ﺍﺑﺘﺪﺍ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﻭ ﺳﭙﺲ ﻋﻤﻠﮕﺮ ﺩﻭﻡ ﻳﻌﻨﻲ – ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﮔﺮﺩﺩ ﺯﻳﺮﺍ * ﺩﺭ‬
‫ﺗﻘﺪﻡ ﺳﻄﺢ ‪ 13‬ﺍﺳﺖ ﮐﻪ ﺑﺎﻻﺗﺮ ﺍﺯ ﺳﻄﺢ ﺗﻘﺪﻡ – ﮐﻪ ‪ 12‬ﺍﺳﺖ ﻣﻲﺑﺎﺷﺪ‪.‬‬

‫ﺳﺘﻮﻧﻲ ﮐﻪ ﺑﺎ ﻋﺒﺎﺭﺕ »ﻭﺍﺑﺴﺘﮕﻲ« ﻣﺸﺨﺺ ﺷﺪﻩ‪ ،‬ﻣﻲﮔﻮﻳﺪ ﮐﻪ ﺁﻥ ﻋﻤﻠﮕﺮ ﺍﺯ ﭼﭗ ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ‬


‫ﻳﺎ ﺍﺯ ﺭﺍﺳﺖ‪ .‬ﺑﺮﺍﻱ ﻣﺜﺎﻝ ﻋﺒﺎﺭﺕ )‪ (a-b-c‬ﺑﻪ ﺻﻮﺭﺕ )‪ ((a-b)-c‬ﺍﺭﺯﻳﺎﺑﻲ ﻣﻲﺷﻮﺩ ﺯﻳﺮﺍ –‬
‫ﻭﺍﺑﺴﺘﻪ ﺑﻪ ﭼﭗ ﺍﺳﺖ‪.‬‬

‫ﺳﺘﻮﻧﻲ ﮐﻪ ﺑﺎ »ﺟﻤﻌﻴﺖ« ﻣﺸﺨﺺ ﺷﺪﻩ‪ ،‬ﻣﻲﮔﻮﻳﺪ ﮐﻪ ﺁﻥ ﻋﻤﻠﮕﺮ ﺑﺮ ﺭﻭﻱ ﭼﻨﺪ ﻋﻤﻠﮕﺮ ﻋﻤﻞ ﻣﻲﮐﻨﺪ‪.‬‬

‫ﺳﺘﻮﻧﻲ ﮐﻪ ﺑﺎ »ﺳﺮﺑﺎﺭ« ﻣﺸﺨﺺ ﺷﺪﻩ‪ ،‬ﻣﻲﮔﻮﻳﺪ ﮐﻪ ﺁﻳﺎ ﻋﻤﻠﮕﺮ ﻗﺎﺑﻞ ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻫﺴﺖ ﻳﺎ ﺧﻴﺮ‪.‬‬
‫)ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﺭﺍ ﺩﺭ ﻓﺼﻞ ﺩﻫﻢ ﻣﻄﺎﻟﻌﻪ ﮐﻨﻴﺪ(‪.‬‬

‫ﻣﺜﺎﻝ‬ ‫ﻭﺍﺑﺴﺘﮕﻲ ﺟﻤﻌﻴﺖ ﺳﺮﺑﺎﺭ‬ ‫ﺳﻄﺢ‬ ‫ﻧﺎﻡ‬ ‫ﻋﻤﻠﻮﻧﺪ‬


‫‪::x‬‬ ‫ﺧﻴﺮ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪17‬‬ ‫ﺟﺪﺍﺳﺎﺯﻱ ﺣﻮﺯﻩ ﺳﺮﺍﺳﺮﻱ‬ ‫‪::‬‬
‫‪X::x‬‬ ‫ﺧﻴﺮ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪17‬‬ ‫ﺟﺪﺍﺳﺎﺯﻱ ﺣﻮﺯﻩ ﮐﻼﺳﻲ‬ ‫‪::‬‬
‫‪s.len‬‬ ‫ﺧﻴﺮ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪16‬‬ ‫ﺍﻧﺘﺨﺎﺏ ﻋﻀﻮ ﻣﺴﺘﻘﻴﻢ‬ ‫‪.‬‬
‫‪p->len‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪16‬‬ ‫ﺍﻧﺘﺨﺎﺏ ﻋﻀﻮ ﻏﻴﺮ ﻣﺴﺘﻘﻴﻢ‬ ‫>‪-‬‬
‫]‪a[i‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪16‬‬ ‫ﺟﺎﻧﺸﻴﻦ ﻣﻌﺎﺩﻝ‬ ‫][‬
‫)(‪rand‬‬ ‫ﺑﻠﻪ‬ ‫‐‐‬ ‫ﭼﭗ‬ ‫‪16‬‬ ‫ﻓﺮﺍﺧﻮﺍﻧﻲ ﺗﺎﺑﻊ‬ ‫)(‬
‫)‪int(ch‬‬ ‫ﺑﻠﻪ‬ ‫‐‐‬ ‫ﭼﭗ‬ ‫‪16‬‬ ‫ﺳﺎﺧﺘﻦ ﺍﻧﻮﺍﻉ‬ ‫)(‬
‫‪n++‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪16‬‬ ‫ﭘﺲ ﺍﻓﺰﺍﻳﺸﻲ‬ ‫‪++‬‬
‫‪n--‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪16‬‬ ‫ﭘﺲ ﮐﺎﻫﺸﻲ‬ ‫‪--‬‬
‫)‪sizeof(a‬‬ ‫ﺧﻴﺮ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫‪ sizeof‬ﺍﻧﺪﺍﺯﻩ ﺷﻲ ﻳﺎ ﻧﻮﻉ‬
‫‪403‬‬ ‫ﺿﻤﻴﻢۀ د ‪ /‬ﻋﻤﻠﮕﺮهﺎی ‪ C++‬اﺳﺘﺎﻧﺪارد‬

‫‪++n‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫ﭘﻴﺶ ﺍﻓﺰﺍﻳﺸﻲ‬ ‫‪++‬‬


‫‪--n‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫ﭘﻴﺶ ﮐﺎﻫﺸﻲ‬ ‫‪--‬‬
‫ﻣﺜﺎﻝ‬ ‫ﻭﺍﺑﺴﺘﮕﻲ ﺟﻤﻌﻴﺖ ﺳﺮﺑﺎﺭ‬ ‫ﺳﻄﺢ‬ ‫ﻧﺎﻡ‬ ‫ﻋﻤﻠﻮﻧﺪ‬
‫‪~s‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫ﻣﮑﻤﻞ ﻭ ﻣﻨﻔﻲ ﮐﺮﺩﻥ‬ ‫~‬
‫‪!p‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫‪ NOT‬ﻣﻨﻄﻘﻲ‬ ‫!‬
‫‪+n‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫ﺟﻤﻊ ﺑﺪﻭﻥ ﻭﺍﺑﺴﺘﮕﻲ‬ ‫‪+‬‬
‫‪-n‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫ﺗﻔﺮﻳﻖ ﺑﺪﻭﻥ ﻭﺍﺑﺴﺘﮕﻲ‬ ‫‪-‬‬
‫‪*p‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫ﻋﻤﻠﮕﺮ ﺍﺷﺎﺭﻩ‬ ‫*‬
‫‪&x‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫ﺁﺩﺭﺱ‬ ‫&‬
‫‪new p‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫ﺗﺨﺼﻴﺺ ﺣﺎﻓﻈﻪ‬ ‫‪new‬‬
‫‪delete p‬‬ ‫ﺑﻠﻪ‬ ‫ﻳﮏ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫‪ delete‬ﺁﺯﺍﺩ ﺳﺎﺯﻱ ﺣﺎﻓﻈﻪ‬
‫)‪int(ch‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪15‬‬ ‫ﺗﺒﺪﻳﻞ ﻧﻮﻉ‬ ‫)(‬
‫‪x.*q‬‬ ‫ﺧﻴﺮ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪14‬‬ ‫ﺍﻧﺘﺨﺎﺏ ﻋﻀﻮ ﻣﺴﺘﻘﻴﻢ‬ ‫*‪.‬‬
‫‪p->q‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪14‬‬ ‫ﺍﻧﺘﺨﺎﺏ ﻋﻀﻮ ﻏﻴﺮ ﻣﺴﺘﻘﻴﻢ‬ ‫*>‪-‬‬
‫‪m * n‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪13‬‬ ‫ﺿﺮﺏ‬ ‫*‬
‫‪m / n‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪13‬‬ ‫ﺗﻘﺴﻴﻢ‬ ‫‪/‬‬
‫‪m % n‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪13‬‬ ‫ﺑﺎﻗﻴﻤﺎﻧﺪﻩ‬ ‫‪%‬‬
‫‪m + n‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪12‬‬ ‫ﺟﻤﻊ‬ ‫‪+‬‬
‫‪m - n‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪12‬‬ ‫ﺗﻔﺮﻳﻖ‬ ‫‪-‬‬
‫‪cout << n‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪11‬‬ ‫ﺗﻐﻴﻴﺮ ﺟﻬﺖ ﺑﻪ ﭼﭗ‬ ‫<<‬
‫‪cin >> n‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪11‬‬ ‫ﺗﻐﻴﻴﺮ ﺟﻬﺖ ﺑﻪ ﺭﺍﺳﺖ‬ ‫>>‬
‫‪x < y‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪10‬‬ ‫ﮐﻮﭼﮏﺗﺮ‬ ‫<‬
‫‪x <= y‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪10‬‬ ‫ﮐﻮﭼﮏﺗﺮ ﻳﺎ ﻣﺴﺎﻭﻱ‬ ‫=<‬
‫‪x > y‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪10‬‬ ‫ﺑﺰﺭﮒﺗﺮ‬ ‫>‬
‫‪x >= y‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪10‬‬ ‫ﺑﺰﺭﮒﺗﺮ ﻳﺎ ﻣﺴﺎﻭﻱ‬ ‫=>‬
‫‪x == y‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪9‬‬ ‫ﺑﺮﺍﺑﺮﻱ‬ ‫==‬
‫‪x != y‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪9‬‬ ‫ﻧﺎﺑﺮﺍﺑﺮﻱ‬ ‫=!‬
‫‪s & t‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪8‬‬ ‫ﻧﺸﺎﻧﻪ ‪AND‬‬ ‫&‬
‫ﺑﺮﻧﺎﻣﻪﺳﺎزی ﭘﻴﺸﺮﻓﺘﻪ‬ ‫‪404‬‬

‫‪S ^ t‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪7‬‬ ‫ﻧﺸﺎﻧﻪ ‪XOR‬‬ ‫^‬


‫‪s | t‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪6‬‬ ‫ﻧﺸﺎﻧﻪ ‪OR‬‬ ‫|‬
‫‪u && v‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪5‬‬ ‫‪ AND‬ﻣﻨﻄﻘﻲ‬ ‫&&‬
‫‪u || v‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪4‬‬ ‫‪ OR‬ﻣﻨﻄﻘﻲ‬ ‫||‬
‫‪U ? x : y‬‬ ‫ﺧﻴﺮ‬ ‫ﺳﻪ‬ ‫ﭼﭗ‬ ‫‪3‬‬ ‫ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ‬ ‫‪?:‬‬
‫‪n = 22‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪2‬‬ ‫ﺗﺨﺼﻴﺺ‬ ‫=‬
‫‪n += 8‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪2‬‬ ‫ﺟﻤﻊ ﺗﺨﺼﻴﺼﻲ‬ ‫=‪+‬‬
‫ﻣﺜﺎﻝ‬ ‫ﻭﺍﺑﺴﺘﮕﻲ ﺟﻤﻌﻴﺖ ﺳﺮﺑﺎﺭ‬ ‫ﺳﻄﺢ‬ ‫ﻧﺎﻡ‬ ‫ﻋﻤﻠﻮﻧﺪ‬
‫‪n -= 4‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪2‬‬ ‫ﺗﻔﺮﻳﻖ ﺗﺨﺼﻴﺼﻲ‬ ‫=‪-‬‬
‫‪n *= -1‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪2‬‬ ‫ﺿﺮﺏ ﺗﺨﺼﻴﺼﻲ‬ ‫=*‬
‫‪n /= 10‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪2‬‬ ‫ﺗﻘﺴﻴﻢ ﺗﺨﺼﻴﺼﻲ‬ ‫=‪/‬‬
‫‪n %= 10‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪2‬‬ ‫ﺑﺎﻗﻴﻤﺎﻧﺪﻩ ﺗﺨﺼﻴﺼﻲ‬ ‫=‪%‬‬
‫‪s &= mask‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪2‬‬ ‫‪ AND‬ﺗﺨﺼﻴﺼﻲ‬ ‫=&‬
‫‪s ^= mask‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪2‬‬ ‫‪ XOR‬ﺗﺨﺼﻴﺼﻲ‬ ‫=^‬
‫‪s |= mask‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫‪2‬‬ ‫‪ OR‬ﺗﺨﺼﻴﺼﻲ‬ ‫=|‬
‫‪s << 1‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫ﭼﭗ ‪2‬‬ ‫ﺑﻪ‬ ‫ﺟﻬﺖ‬ ‫ﺗﻐﻴﻴﺮ‬ ‫=<<‬
‫ﺗﺨﺼﻴﺼﻲ‬
‫‪s >> 1‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﺭﺍﺳﺖ‬ ‫ﺭﺍﺳﺖ ‪2‬‬ ‫ﺑﻪ‬ ‫ﺟﻬﺖ‬ ‫ﺗﻐﻴﻴﺮ‬ ‫=>>‬
‫ﺗﺨﺼﻴﺼﻲ‬
‫‪++m, --n‬‬ ‫ﺑﻠﻪ‬ ‫ﺩﻭ‬ ‫ﭼﭗ‬ ‫‪0‬‬ ‫ﮐﺎﻣﺎ‬ ‫‪,‬‬
« ‫ﺿﻤﻴﻤﻪ » ﻫـ‬
‫ﻓﻬﺮﺳﺖ ﻣﻨﺎﺑﻊ ﻭ ﻣﺄﺧﺬ‬

[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.
‫ﻓﻬﺮﺳﺖ ﻣﻄﺎﻟﺐ‬

‫‪37‬‬ ‫‪ 2‐10‬ﻧﻮﻉ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪char‬‬ ‫ﻓﺼﻞ ﺍﻭﻝ‬


‫‪39‬‬ ‫‪ 2–11‬ﻧﻮﻉ ﺷﻤﺎﺭﺷﻲ ‪enum‬‬ ‫»ﻣﻘﺪﻣﺎﺕ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ ﺑﺎ ‪«C++‬‬
‫‪42‬‬ ‫‪ 2–12‬ﺗﺒﺪﻳﻞ ﻧﻮﻉ‪ ،‬ﮔﺴﺘﺮﺵ ﻧﻮﻉ‬ ‫‪1‬‬ ‫‪1‐1‬ﭼﺮﺍ ‪ C++‬؟‬
‫‪45‬‬ ‫‪ 2–13‬ﺑﺮﺧﻲ ﺍﺯ ﺧﻄﺎﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬ ‫‪2‬‬ ‫‪ 1–2‬ﺗﺎﺭﻳﺨﭻۀ ‪C++‬‬
‫‪46‬‬ ‫‪ 2–14‬ﺳﺮﺭﻳﺰﻱ ﻋﺪﺩﻱ‬ ‫‪3‬‬ ‫‪ 1–3‬ﺁﻣﺎﺩﻩﺳﺎﺯﻱ ﻣﻘﺪﻣﺎﺕ‬
‫‪48‬‬ ‫‪ 2–5‬ﺧﻄﺎﻱ ﮔﺮﺩ ﮐﺮﺩﻥ‬ ‫‪4‬‬ ‫‪ 1–4‬ﺷﺮﻭﻉ ﮐﺎﺭ ﺑﺎ ‪C++‬‬
‫‪54‬‬ ‫‪ 2–6‬ﺣﻮﺯۀ ﻣﺘﻐﻴﺮﻫﺎ‬ ‫‪10‬‬ ‫‪ 1–5‬ﻋﻤﻠﮕﺮ ﺧﺮﻭﺟﻲ‬
‫‪58‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬ ‫‪11‬‬ ‫‪ 1–6‬ﻟﻴﺘﺮﺍﻝﻫﺎ ﻭ ﮐﺎﺭﺍﮐﺘﺮﻫﺎ‬
‫‪60‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬ ‫‪12‬‬ ‫‪ 1–7‬ﻣﺘﻐﻴﺮﻫﺎ ﻭ ﺗﻌﺮﻳﻒ ﺁﻥﻫﺎ‪:‬‬
‫‪61‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬ ‫‪15‬‬ ‫‪ 1–8‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺍﻭﻟﻴﻪ ﺑﻪ ﻣﺘﻐﻴﺮﻫﺎ‬
‫‪16‬‬ ‫‪ 1–9‬ﺛﺎﺑﺖﻫﺎ‬
‫ﻓﺼﻞ ﺳﻮﻡ‬ ‫‪17‬‬ ‫‪ 1–10‬ﻋﻤﻠﮕﺮ ﻭﺭﻭﺩﻱ‬
‫»ﺍﻧﺘﺨﺎﺏ«‬ ‫‪20‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬
‫‪63‬‬ ‫‪ 3‐1‬ﺩﺳﺘﻮﺭ ‪if‬‬ ‫‪22‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪65‬‬ ‫‪ 3‐2‬ﺩﺳﺘﻮﺭ ‪if..else‬‬ ‫‪23‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪66‬‬ ‫‪ 3‐4‬ﻋﻤﻠﮕﺮﻫﺎﻱ ﻣﻘﺎﻳﺴﻪﺍﻱ‬
‫‪68‬‬ ‫‪ 3‐5‬ﺑﻠﻮﻙﻫﺎﻱ ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ‬ ‫ﻓﺼﻞ ﺩﻭﻡ‬
‫‪71‬‬ ‫‪ 3‐6‬ﺷﺮﻁﻫﺎﻱ ﻣﺮﻛﺐ‬ ‫»ﺍﻧﻮﺍﻉ ﺍﺻﻠﻲ«‬
‫‪73‬‬ ‫‪ 3‐7‬ﺍﺭﺯﻳﺎﺑﻲ ﻣﻴﺎﻧﺒﺮﻱ‬ ‫‪25‬‬ ‫‪ 2–1‬ﺍﻧﻮﺍﻉ ﺩﺍﺩۀ ﻋﺪﺩﻱ‬
‫‪74‬‬ ‫‪ 3‐8‬ﻋﺒﺎﺭﺍﺕ ﻣﻨﻄﻘﻲ‬ ‫‪26‬‬ ‫‪ 2–2‬ﻣﺘﻐﻴﺮ ﻋﺪﺩ ﺻﺤﻴﺢ‬
‫‪75‬‬ ‫‪ 3‐9‬ﺩﺳﺘﻮﺭﻫﺎﻱ ﺍﻧﺘﺨﺎﺏ ﺗﻮﺩﺭﺗﻮ‬ ‫‪28‬‬ ‫‪ 2–3‬ﻣﺤﺎﺳﺒﺎﺕ ﺍﻋﺪﺍﺩ ﺻﺤﻴﺢ‬
‫‪79‬‬ ‫‪ 3‐10‬ﺳﺎﺧﺘﺎﺭ ‪else if‬‬ ‫‪29‬‬ ‫‪ 2–4‬ﻋﻤﻠﮕﺮﻫﺎﻱ ﺍﻓﺰﺍﻳﺸﻲ ﻭ ﮐﺎﻫﺸﻲ‬
‫‪81‬‬ ‫‪ 3‐11‬ﺩﺳﺘﻮﺭﺍﻟﻌﻤﻞ ‪switch‬‬ ‫‪31‬‬ ‫‪ 2–5‬ﻋﻤﻠﮕﺮﻫﺎﻱ ﻣﻘﺪﺍﺭﮔﺬﺍﺭﻱ ﻣﺮﮐﺐ‬
‫‪84‬‬ ‫‪ 3‐12‬ﻋﻤﻠﮕﺮ ﻋﺒﺎﺭﺕ ﺷﺮﻃﻲ‬ ‫‪32‬‬ ‫‪ 2–6‬ﺍﻧﻮﺍﻉ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬
‫‪85‬‬ ‫‪ 3‐13‬ﻛﻠﻤﺎﺕ ﻛﻠﻴﺪﻱ‬ ‫‪33‬‬ ‫‪ 2–7‬ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬
‫‪87‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬ ‫‪35‬‬ ‫‪ 2–8‬ﺷﮑﻞ ﻋﻠﻤﻲ ﻣﻘﺎﺩﻳﺮ ﻣﻤﻴﺰ ﺷﻨﺎﻭﺭ‬
‫‪90‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬ ‫‪36‬‬ ‫‪ 2–9‬ﻧﻮﻉ ﺑﻮﻟﻴﻦ ‪bool‬‬
‫‪93‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪163‬‬ ‫‪ 5‐14‬ﺗﺎﺑﻊ )(‪main‬‬
‫‪165‬‬ ‫‪ 5‐15‬ﺁﺭﮔﻮﻣﺎﻥﻫﺎﻱ ﭘﻴﺶﻓﺮﺽ‬ ‫ﻓﺼﻞ ﭼﻬﺎﺭﻡ‬
‫‪167‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬ ‫»ﺗﻜﺮﺍﺭ«‬
‫‪170‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬ ‫‪95‬‬ ‫ﻣﻘﺪﻣﻪ‬
‫‪170‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬ ‫‪95‬‬ ‫‪ 4‐1‬ﺩﺳﺘﻮﺭ ‪while‬‬
‫‪98‬‬ ‫‪ 4‐2‬ﺧﺎﺗﻤﻪ ﺩﺍﺩﻥ ﺑﻪ ﻳﻚ ﺣﻠﻘﻪ‬
‫ﻓﺼﻞ ﺷﺸﻢ‬ ‫‪102‬‬ ‫‪ 4‐3‬ﺩﺳﺘﻮﺭ ‪do..while‬‬
‫»ﺁﺭﺍﻳﻪﻫﺎ«‬ ‫‪104‬‬ ‫‪ 4‐4‬ﺩﺳﺘﻮﺭ ‪for‬‬
‫‪174‬‬ ‫‪ 6‐1‬ﻣﻘﺪﻣﻪ‬ ‫‪110‬‬ ‫‪ 4‐5‬ﺩﺳﺘﻮﺭ ‪break‬‬
‫‪175‬‬ ‫‪ 6‐2‬ﭘﺮﺩﺍﺯﺵ ﺁﺭﺍﻳﻪﻫﺎ‬ ‫‪112‬‬ ‫‪ 4‐6‬ﺩﺳﺘﻮﺭ ‪continue‬‬
‫‪177‬‬ ‫‪ 6‐3‬ﻣﻘﺪﺍﺭﺩﻫﻲ ﺁﺭﺍﻳﻪﻫﺎ‬ ‫‪114‬‬ ‫‪ 4‐7‬ﺩﺳﺘﻮﺭ ‪goto‬‬
‫‪180‬‬ ‫‪ 6‐4‬ﺍﻳﻨﺪﻛﺲ ﺑﻴﺮﻭﻥ ﺍﺯ ﺣﺪﻭﺩ ﺁﺭﺍﻳﻪ‬ ‫‪116‬‬ ‫‪ 4‐8‬ﺗﻮﻟﻴﺪ ﺍﻋﺪﺍﺩ ﺷﺒﻪ ﺗﺼﺎﺩﻓﻲ‬
‫‪183‬‬ ‫‪ 6‐5‬ﺍﺭﺳﺎﻝ ﺁﺭﺍﻳﻪ ﺑﻪ ﺗﺎﺑﻊ‬ ‫‪124‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬
‫‪187‬‬ ‫‪ 6‐6‬ﺍﻟﮕﻮﺭﻳﺘﻢ ﺟﺴﺘﺠﻮﻱ ﺧﻄﻲ‬ ‫‪127‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪189‬‬ ‫‪ 6‐7‬ﻣﺮﺗﺐﺳﺎﺯﻱ ﺣﺒﺎﺑﻲ‬ ‫‪128‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪190‬‬ ‫‪ 6‐8‬ﺍﻟﮕﻮﺭﻳﺘﻢ ﺟﺴﺘﺠﻮﻱ ﺩﻭﺩﻭﻳﻲ‬
‫‪ 6‐9‬ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺍﻧﻮﺍﻉ ﺷﻤﺎﺭﺷﻲ ﺩﺭ ﺁﺭﺍﻳﻪ ‪195‬‬ ‫ﻓﺼﻞ ﭘﻨﺠﻢ‬
‫‪196‬‬ ‫‪ 6‐10‬ﺗﻌﺮﻳﻒ ﺍﻧﻮﺍﻉ‬ ‫» ﺗﻮﺍﺑﻊ«‬
‫‪199‬‬ ‫‪ 6‐11‬ﺁﺭﺍﻳﻪﻫﺎﻱ ﭼﻨﺪ ﺑﻌﺪﻱ‬ ‫‪130‬‬ ‫‪ 5‐1‬ﻣﻘﺪﻣﻪ‬
‫‪204‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬ ‫‪130‬‬ ‫‪ 5‐2‬ﺗﻮﺍﺑﻊ ﻛﺘﺎﺑﺨﺎﻧﻪﺍﻱ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬
‫‪208‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬ ‫‪135‬‬ ‫‪ 5‐3‬ﺗﻮﺍﺑﻊ ﺳﺎﺧﺖ ﻛﺎﺭﺑﺮ‬
‫‪208‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬ ‫‪136‬‬ ‫‪ 5‐4‬ﺑﺮﻧﺎﻡۀ ﺁﺯﻣﻮﻥ‬
‫‪139‬‬ ‫‪ 5‐5‬ﺍﻋﻼﻥﻫﺎ ﻭ ﺗﻌﺎﺭﻳﻒ ﺗﺎﺑﻊ‬
‫ﻓﺼﻞ ﻫﻔﺘﻢ‬ ‫‪141‬‬ ‫‪ 5‐6‬ﻛﺎﻣﭙﺎﻳﻞ ﺟﺪﺍﮔﺎﻥۀ ﺗﻮﺍﺑﻊ‬
‫»ﺍﺷﺎﺭﻩﮔﺮﻫﺎ ﻭ ﺍﺭﺟﺎﻉﻫﺎ«‬ ‫‪143‬‬ ‫‪ 5‐6‬ﻣﺘﻐﻴﺮﻫﺎﻱ ﻣﺤﻠﻲ‪ ،‬ﺗﻮﺍﺑﻊ ﻣﺤﻠﻲ‬
‫‪214‬‬ ‫‪ 7‐1‬ﻣﻘﺪﻣﻪ‬ ‫‪146‬‬ ‫‪ 5‐7‬ﺗﺎﺑﻊ ‪void‬‬
‫‪215‬‬ ‫‪ 7‐1‬ﻋﻤﻠﮕﺮ ﺍﺭﺟﺎﻉ‬ ‫‪148‬‬ ‫‪ 5‐8‬ﺗﻮﺍﺑﻊ ﺑﻮﻟﻲ‬
‫‪216‬‬ ‫‪ 7‐2‬ﺍﺭﺟﺎﻉﻫﺎ‬ ‫‪150‬‬ ‫‪ 5‐9‬ﺗﻮﺍﺑﻊ ﻭﺭﻭﺩﻱ‪/‬ﺧﺮﻭﺟﻲ )‪(I/O‬‬
‫‪218‬‬ ‫‪ 7‐3‬ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‬ ‫‪152‬‬ ‫‪ 5‐14‬ﺍﺭﺳﺎﻝ ﺑﻪ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ )ﺁﺩﺭﺱ(‬
‫‪219‬‬ ‫‪ 7‐4‬ﻣﻘﺪﺍﺭﻳﺎﺑﻲ‬ ‫‪158‬‬ ‫‪ 5‐11‬ﺍﺭﺳﺎﻝ ﺍﺯ ﻃﺮﻳﻖ ﺍﺭﺟﺎﻉ ﺛﺎﺑﺖ‬
‫‪222‬‬ ‫‪ 7‐6‬ﭼﭗ ﻣﻘﺪﺍﺭﻫﺎ‪ ،‬ﺭﺍﺳﺖ ﻣﻘﺪﺍﺭﻫﺎ‬ ‫‪160‬‬ ‫‪ 5‐12‬ﺗﻮﺍﺑﻊ ﺑﻲﻭﺍﺳﻄﻪ‬
‫‪223‬‬ ‫‪ 7‐7‬ﺑﺎﺯﮔﺸﺖ ﺍﺯ ﻧﻮﻉ ﺍﺭﺟﺎﻉ‬ ‫‪161‬‬ ‫‪ 5‐13‬ﭼﻨﺪﺷﮑﻠﻲ ﺗﻮﺍﺑﻊ‬
‫‪296‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬ ‫‪225‬‬ ‫‪ 7‐8‬ﺁﺭﺍﻳﻪﻫﺎ ﻭ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‬
‫‪230‬‬ ‫‪ 7‐13‬ﻋﻤﻠﮕﺮ ‪new‬‬
‫ﻓﺼﻞ ﻧﻬﻢ‬ ‫‪232‬‬ ‫‪ 7‐14‬ﻋﻤﻠﮕﺮ ‪delete‬‬

‫»ﺷﻲﮔﺮﺍﻳﻲ«‬ ‫‪233‬‬ ‫‪ 7‐9‬ﺁﺭﺍﻳﻪﻫﺎﻱ ﭘﻮﻳﺎ‬


‫‪299‬‬ ‫‪ 9‐1‬ﻣﻘﺪﻣﻪ‬ ‫‪236‬‬ ‫‪ 7‐10‬ﺍﺷﺎﺭﻩﮔﺮ ﺛﺎﺑﺖ‬
‫‪303‬‬ ‫‪ 9‐2‬ﺍﻋﻼﻥ ﻛﻼﺱﻫﺎ‬ ‫‪237‬‬ ‫‪ 7‐11‬ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‬
‫‪309‬‬ ‫‪ 9‐3‬ﺳﺎﺯﻧﺪﻩﻫﺎ‬ ‫‪238‬‬ ‫‪ 7‐12‬ﺍﺷﺎﺭﻩﮔﺮﻱ ﺑﻪ ﺍﺷﺎﺭﻩﮔﺮ ﺩﻳﮕﺮ‬
‫‪312‬‬ ‫‪ 9‐4‬ﻓﻬﺮﺳﺖ ﻣﻘﺪﺍﺭﺩﻫﻲ ﺩﺭ ﺳﺎﺯﻧﺪﻩﻫﺎ‬ ‫‪238‬‬ ‫‪ 7‐13‬ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺗﻮﺍﺑﻊ‬
‫‪313‬‬ ‫‪ 9‐5‬ﺗﻮﺍﺑﻊ ﺩﺳﺘﻴﺎﺑﻲ‬ ‫‪240‬‬ ‫‪ NUL 7‐14‬ﻭ ‪NULL‬‬

‫‪314‬‬ ‫‪ 9‐6‬ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺧﺼﻮﺻﻲ‬ ‫‪242‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬


‫‪316‬‬ ‫‪ 9‐7‬ﺳﺎﺯﻧﺪۀ ﻛﭙﻲ‬ ‫‪245‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪319‬‬ ‫‪ 9‐8‬ﻧﺎﺑﻮﺩ ﮐﻨﻨﺪﻩ‬ ‫‪248‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬
‫‪321‬‬ ‫‪ 9‐9‬ﺍﺷﻴﺎﻱ ﺛﺎﺑﺖ‬
‫‪322‬‬ ‫‪ 9‐10‬ﺍﺷﺎﺭﻩﮔﺮ ﺑﻪ ﺍﺷﻴﺎ‬
‫‪325‬‬ ‫‪ 9‐11‬ﺍﻋﻀﺎﻱ ﺩﺍﺩﻩﺍﻱ ﺍﻳﺴﺘﺎ‬
‫‪328‬‬ ‫‪ 9‐12‬ﺗﻮﺍﺑﻊ ﻋﻀﻮ ﺍﻳﺴﺘﺎ‬ ‫ﻓﺼﻞ ﻫﺸﺘﻢ‬
‫‪330‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬ ‫»ﺭﺷﺘﻪﻫﺎﻱ ﻛﺎﺭﺍﻛﺘﺮﻱ ﻭ ﻓﺎﻳﻞﻫﺎ ﺩﺭ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ«‬
‫‪333‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬ ‫‪250‬‬ ‫‪ 8‐1‬ﻣﻘﺪﻣﻪ‬
‫‪334‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬ ‫‪251‬‬ ‫‪ 8‐2‬ﻣﺮﻭﺭﻱ ﺑﺮ ﺍﺷﺎﺭﻩﮔﺮﻫﺎ‬
‫‪252‬‬ ‫‪ 8‐3‬ﺭﺷﺘﻪﻫﺎﻱ ﻛﺎﺭﺍﻛﺘﺮﻱ ﺩﺭ ‪C‬‬
‫‪ 8‐ 4‬ﻭﺭﻭﺩﻱ‪/‬ﺧﺮﻭﺟﻲ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ‪253‬‬
‫‪256‬‬ ‫‪ 8‐5‬ﭼﻨﺪ ﺗﺎﺑﻊ ﻋﻀﻮ ‪ cin‬ﻭ ‪cout‬‬
‫‪261‬‬ ‫‪ 8‐6‬ﺗﻮﺍﺑﻊ ﻛﺎﺭﺍﻛﺘﺮﻱ ‪ C‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬
‫‪262‬‬ ‫‪ 8‐7‬ﺁﺭﺍﻳﻪﺍﻱ ﺍﺯ ﺭﺷﺘﻪﻫﺎ‬
‫‪ 8‐8‬ﺗﻮﺍﺑﻊ ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ‪266‬‬
‫‪ 8‐9‬ﺭﺷﺘﻪﻫﺎﻱ ﮐﺎﺭﺍﮐﺘﺮﻱ ﺩﺭ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ ‪275‬‬
‫‪275‬‬ ‫‪ 8‐10‬ﻧﮕﺎﻫﻲ ﺩﻗﻴﻖﺗﺮ ﺑﻪ ﺗﺒﺎﺩﻝ ﺩﺍﺩﻩﻫﺎ‬
‫‪278‬‬ ‫‪ 8‐11‬ﻭﺭﻭﺩﻱ ﻗﺎﻟﺐﺑﻨﺪﻱ ﻧﺸﺪﻩ‬
‫‪281‬‬ ‫‪ 8‐12‬ﻧﻮﻉ ‪ string‬ﺩﺭ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬
‫‪284‬‬ ‫‪ 8‐13‬ﻓﺎﻳﻞﻫﺎ‬
‫‪290‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬
‫‪293‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫ﺿﻤﻴﻤﻪ ﺏ ‪ :‬ﺟﺪﻭﻝ ﺍﺳﮑﻲ‬ ‫ﻓﺼﻞ ﺩﻫﻢ‬
‫‪387‬‬ ‫»ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎ«‬
‫‪393‬‬ ‫ﺿﻤﻴﻤﻪ ﺝ ‪ :‬ﮐﻠﻤﺎﺕ ﮐﻠﻴﺪﻱ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬
‫‪337‬‬ ‫‪ 10‐1‬ﻣﻘﺪﻣﻪ‬
‫‪398‬‬ ‫ﺿﻤﻴﻤﻪ ﺩ ‪ :‬ﻋﻤﻠﮕﺮﻫﺎﻱ ‪ C++‬ﺍﺳﺘﺎﻧﺪﺍﺭﺩ‬
‫‪338‬‬ ‫‪ 10‐2‬ﺗﻮﺍﺑﻊ ﺩﻭﺳﺖ‬
‫‪401‬‬ ‫ﺿﻤﻴﻤﻪ ﻫـ ‪ :‬ﻓﻬﺮﺳﺖ ﻣﻨﺎﺑﻊ ﻭ ﻣﺄﺧﺬ‬
‫‪ 10‐3‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮ ﺟﺎﻳﮕﺰﻳﻨﻲ )=(‪339‬‬
‫‪340‬‬ ‫‪ 10‐4‬ﺍﺷﺎﺭﻩﮔﺮ ‪this‬‬
‫‪ 10‐5‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺣﺴﺎﺑﻲ ‪342‬‬
‫‪ 10‐6‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ‬
‫‪344‬‬ ‫ﺟﺎﻳﮕﺰﻳﻨﻲ ﺣﺴﺎﺑﻲ‬
‫‪ 10‐7‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ ﺭﺍﺑﻄﻪﺍﻱ ‪346‬‬
‫‪ 10‐8‬ﺳﺮﺑﺎﺭﮔﺬﺍﺭﻱ ﻋﻤﻠﮕﺮﻫﺎﻱ‬
‫‪347‬‬ ‫ﺍﻓﺰﺍﻳﺸﻲ ﻭ ﻛﺎﻫﺸﻲ‬
‫‪352‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﮔﺰﻳﻨﻪﺍﻱ‬
‫‪354‬‬ ‫ﭘﺮﺳﺶﻫﺎﻱ ﺗﺸﺮﻳﺤﻲ‬
‫‪354‬‬ ‫ﺗﻤﺮﻳﻦﻫﺎﻱ ﺑﺮﻧﺎﻣﻪﻧﻮﻳﺴﻲ‬

‫ﻓﺼﻞ ﻳﺎﺯﺩﻫﻢ‬
‫»ﺗﺮﻛﻴﺐ ﻭ ﻭﺭﺍﺛﺖ«‬
‫‪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‬‬

You might also like