Sie sind auf Seite 1von 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‬‬

Das könnte Ihnen auch gefallen