• توجه: در صورتی که از کاربران قدیمی ایران انجمن هستید و امکان ورود به سایت را ندارید، میتوانید با آیدی altin_admin@ در تلگرام تماس حاصل نمایید.

تاپيك آموزش زبان C

آرایه ای از رشته ها
گاهی ممکن است ، به عنوان مثال بخواهیم تعدادی از نام افراد را در آرایه ای
نگهداری کنیم : ولی با اطلاعاتی که تاکنون از رشته ها داریم شاید نتوانیم چنین
کاری را انجام دهیم . برای این کار باید آرایه ای از رشته ها داشته باشیم . چون
رشته ها خود ازنوع آرایه هستند باید آرایه ای ازآرایه ها را تعریف کنیم ( آرایه ای
از آرایه ها همان آرایه دوبعدی است ). برای توضیح بیشتر به مثال ۱ توجه نمایید.
مثال : برنامه ای که با تعریف آرایه ای از رشته ها ، ۵ نام را در آن قرار
می دهد و سپس با خواندن نامی از ورودی آنرا در آرایه جستجو می کند . main)(
{
int dex/exist ;
int k ;
char name[21] ;
static char list [5][21]=
{ “ali” /
“ahmad” /
“alireza” /
“jalal” /
“mohammad”
} ;
printf(“\nenter one name for”);
printf(” search:”);
gets(name );
for(dex=0 ; dex<5;dex++)
if(strcmp(list[dex]/name)==0)
{
exist=1 ;
break ;
}
if( exist==1)
{
printf(“\nname “);
printf(“<%s> exist in table.”/name);
}
else
{
printf(“\nname “);
printf(“<%s> not exist. “/name);
}
}
دو نمونه از خروجی برنامه مثال بالا :
( الف ) enter one name for search:reza
name not exist.
( ب ) enter one name for search:ali
name exist in table.
ال بالا از تابع ()strcmp استفاده شده که کارش مقایسه دو رشته می باشد
 
بعضی از توابع رشته ای

بعضی از توابع بر روی رشته ها عمل کرده و دستکاری رشته ها را آسان می کنند .
که می توان از مقایسه رشته ها ، تعیین طول رشته ها، الحاق کردن رشته ها به یکدیگر
و … نام برد .

تابع ()strcpy
تابع ()strcpy برای قرار دادن رشته ای در رشته دیگر مورد استفاده قرار گرفته
و بصورت زیر استفاده می شود : ;
(“رشته ” و متغیر رشته ای )strcpy
اهمیت این تابع وقتی مشخص می شود که بدانیم ، مقدار دادن به متغیر رشته ای
بطور مستقیم امکان پذیر نیست بلکه فقط از طریق این تابع صورت پذیرد . مثلا” اگر
داشته باشیم : char name[11];

دستور انتساب زیر غلط خواهد بود : name=”ALI”;

با استفاده از تابع ()strcpy عمل فوق را می توان بصورت زیر انجام داد : strcpy(name/”ALI”);

این مساله بدین علت است : ” همانطور که در C نمی توان دو آرایه را با حکم
انتساب (=) به یکدیگر نسبت داد ، دو رشته نیز نمی توانند با حکم انتساب ، به
یکدیگر نسبت داده شوند .

مثال ۱: برنامه ای که یک رشته و یک عدد( که بیانگر موقعیتی ازاین رشته است )
را از ورودی خوانده و موجب حذف کاراکتر موجود در آن محل می شود . main)(
{
char string[81] ;
int position ;
printf(“\n type a string: ” );
gets(string );
printf(“\n enter position for ” );
printf(“delete character: ” );
scanf(“%d”/&position );
strcpy(&string[position]/
&string[position+1] );
puts(” the result string is :” );
puts(string );
}

نمونه ای از خروجی برنامه مثال ۱: type a string: in thee name of allah.
enter position for delete character:5
the result string is:
in the name of allah.

در مثال ۱ متغیر position به موقعیتی از رشته اشاره میکند که کاراکتر موجود
در آن باید حذف شود . با استفاده از تابع ()strcpy قسمتی از رشته string را با
شروع از position + 1 ، در همین رشته با شروع از موقعیت position کپی کرده ایم .
این عمل موجب حذف کاراکتری که در موقعیت position قرار داشته است می گردد . با
فرض این که رشته ورودی برابر با “cart” و موقعیت کاراکتری که باید حذف شود ۲
فرض گردد خروجی حاصل از اجرای برنامه مثال ۱ بصورت زیر خواهد بود : type a string: cart.
enter position for delete character:2
the result string is:cat

تابع ()strcat
این تابع برای الحاق کردن ( به دنبال هم قرار دادن ) دو رشته استفاده میشود
و بصورت زیر به کار می رود : strcat(s1/s2)
s1
و s2و دو رشته ای هستند که باید با هم الحاق شوند . s2 در انتهای رشته s1
قرار خواهد گرفت .

مثال ۲: main)(
{
char s1[21] / s2[21] ;
puts(“enter string : ” );
gets(s1 );
puts(“enter string : ” );
gets(s2 );
strcat(s1/s2 );
puts(“result string is: ” );
puts(s1 );
}

درپاسخ به درخواست برنامه ، اگر بجای s1 عبارت good وبجای s2 عبارت moorning
را وارد کنیم ، خروجی بدین صورت است : enter string :
good

enter string :
moorning.

result string is:
goodmoorning.

برای تمرین میتوانید برنامه را طوری تغییر دهید که بین دو عبارت ، یک فاصله
(blank) باشد .

تابع ()strlen
تابع ()strlen برای تعیین طول یک رشته مورد استفاده قرار گرفته و بصورت زیر
به کار می رود : strlen(s)
s
رشته ای است که طول آن باید تعیین شود .

مثال ۳: main)(
{
char name[31] ;
puts(” enter a string: ” );
gets(name );
printf(“\n string length is:”);
printf(“%d”/strlen(name ));
}

نمونه ای از خروجی برنامه مثال ۳ : enter a string:
the c language is very quick.

string length is:29

روش دیگر برای پیدا کردن طول یک رشته ، استفاده از تابع ()scanf با پارامتر
کنترلی %n است . با استفاده از تابع ()scanf و پارامتر %n ، مثال ۳ را می توان
بصورت زیر نوشت : main)(
{
char name[31] ;
int count ;
scanf(“%s%n”/name/&count);
printf(“\n string length is:”);
printf(“%d”/count );
}

تابع ()strcmp
تابع ()strcmp برای مقایسه کاراکتری دو رشته مورد استفاده قرار میگیرد و به
این صورت بکار می رود : strcmp(s1/s2)
s2
و s1و دو رشته ای هستند که باید با یکدیگر مقایسه شوند . این تابع نتیجه
مقایسه دو رشته را بصورت صفر ، منفی و یا مثبت مشخص می کند :
نتیجه |(s1/s2()strcmp
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ s1=s2 | 0

منفی | s2 <َs1
مثبت | s2 >َs1

تابع ()strchr
تابع ()strchr برای جستجوی یک کاراکتر در یک رشته بکار می رود و محل وجود
اولین وقوع آن را مشخص می کند. اگر کاراکتر مورد نظر در رشته وجود نداشته باشد
مقداری که توسط این تابع برگردانده می شود برابر با صفر است . این تابع بصورت
زیر استفاده می شود : strchr(s/ ch)
ch
کاراکتری است که باید در رشته s جستجو شود. بعنوان مثال ، بااجرای دستور: if( strchr( “hello”/’e'))printf( “e is in hello”);

چون حرف e در عبارت hello وجود دارد پیام مناسبی چاپ می شود .

تابع ()strstr
تابع ()strstr برای جستجو زیر رشته ای در یک رشته مورد استفاده قرار گرفته و
بصورت زیر بکار می رود : strstr(s1/s2)
s2
رشته ای است که باید در رشته s1 جستجو شود . اگر s2در s1ر پیدا شود محل
اولین وقوع آن توسط تابع برگردانده می شود ولی اگر s2در s1ر وجود نداشته باشد
مقدار صفر برگردانده خواهد شد . بعنوان مثال ، با اجرای دستور : if( strstr( “this is”/”hi”))printf( “hi found”);

بعلت وجود رشته hi در رشته this is ، پیام مناسبی صادر می شود .

مثال ۴: main)(
{
char s1[80] / s2[80] ;
char ch ;
puts(” enter string : ” );
gets(s1 );
puts(” enter string : ” );
gets(s2 );
puts(“enter character for search”);
printf(” in s1: ” );
ch=getche )(;
printf(“\n length of s1 is:”);
printf(“%d”/strlen(s1 ));
printf(“\n length of s2 is:”);
printf(“%d” /strlen(s2 ));
if(!strcmp(s1/s2))
printf(“\n string are equal. “);
if(strstr(s1/s2))
printf(“\n is in . ” );
else
printf(“\n is not in .”);
if(strstr(s1/ch))
printf(“\ncharacter<%c>is in.”);
else
{
printf(“\ncharacter<%c>is”);
printf(” not in .”);
}
}

نمونه ای از خروجی برنامه مثال ۴ : enter string :
this is a sample statement.
enter string :
sample
enter character for search in : m
length of is:28
length of is:6
is in .
character is
 
اشاره گرها

درک صحیح مفهوم اشاره گرها در زبان C بزرگترین موفقیت یک برنامه نویس است .
زیرا استفاده از اشاره گرها ویژگیهای زیر را دارد : ۱
عمل تخصیص حافظه پویا امکان پذیر است . ۲
موجب بهبود کارآیی بسیاری از توابع می شود . ۳
کار با رشته ها و آرایه ها را آسانتر می کند . ۴
فراخوانی با ارجاع در توابع ، از طریق اشاره گرها امکان پذیر است .
کلیه متغیرهایی که در برنامه ها مورداستفاده قرار میگیرند در حافظه کامپیوتر
ذخیره می شوند ( محل هایی از حافظه هستند ) . بنابراین هر متغیر دارای یک آدرس
منحصر بفردی است که توسط آن می توان به متغیر دسترسی پیدا کرد. اشاره گرها حاوی
آدرس متغیرهای حافظه هستند. بعبارت دیگر اگر متغیری آدرس متغیر دیگر را در خود
نگهداری کند به متغیر اول یک اشاره گر گفته می شود . بعنوان مثال ، اگر محتویات
متغیری که در محل ۱۰۰۰ حافظه قرار دارد برابر با ۱۰۰۴ باشد ، این متغیر به محل ۱۰۰۴
حافظه اشاره خواهد کرد ( شکل ۱ ) .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
محتویات حافظه | آدرس حافظه
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
ؤؤؤؤؤؤ ۱۰۰۴ | ۱۰۰۰ |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ۱۰۰۱ | | |
|
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ۱۰۰۲ | | |
|
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ۱۰۰۳ | | |
|
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
<ؤؤؤؤ| | ۱۰۰۴
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ۱۰۰۵ | |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
شکل (۱) . مفهوم اشاره گر

برای تعریف متغیرهای اشاره گر از روش کلی زیر استفاده می شود :
نام متغیر اشاره گر * نوع
نوع ، یکی از انواع معتبر در زبان C است . نوع اشاره گر مشخص می کند که این
اشاره گر باید به چه نوع داده ای اشاره کند ( سر و کارش با چه نوع داده ای است ).
در زبان C برخلاف زبان هایی مثل PL/I اشاره گرها دارای نوع هستند. لذا دراستفاده
از اشاره گرها باید دقت کافی بخرج داد تا نتیجه نادرستی از برنامه حاصل نگردد .
بعنوان مثال ، دستور int *p; متغیر p را از نوع اشاره گر تعریف می کند که فقط
باید به متغیرهای از نوع “صحیح ” اشاره نماید. البته اگر اشاره گرp به متغیرهایی
از انواع دیگر اشاره نماید ، کامپایلر زبان C خطایی را به برنامه نویس اعلام
نمی کند ولی برنامه نویس باید بداند که این امر یقینا” در نتیجه اجرای برنامه
اثر گذاشته و موجب عدم صحت اجرای برنامه گشته و به نتایج حاصل از برنامه
اطمینانی نیست . بعنوان مثال در حین اجرای برنامه زیر از طرف کامپایلر خطایی
گزارش نخواهد شد ولی می دانیم که این برنامه نتیجه مطلوبی نخواهد داشت . main)(
{
float x/y ;
int *p ;
p=&x ;
y=*p ;
}

در برنامه فوق ، چون p به متغیر x اشاره میکند و p از نوع ” صحیح ” است ، x
را بصورت عدد ” صحیح ” در نظر میگیرد و در دستور بعدی که محتویات محلی که p به را به y منتقل می کند، عمل انتقال به درستی انجام نمیشود.
 
عملگرهای اشاره گر

دو عملگر در مورد اشاره گرها مورد استفاده قرار می گیرند که عبارتند از : *
و & . عملگر & یک عملگر یکانی است که آدرس عملوند خود را مشخص می کند . بعنوان
مثال دستور m = &name موجب می شود تا آدرس متغیر name در متغیر m قرار گیرد .
عملگر * همانند عملگر & یک عملگر یکانی است ، محتویات یک آدرس حافظه را مشخص
می کند . بعنوان مثال دستور p = m; موجب می شود تا محتویات محلی که آدرس آن در m
است به p منتقل گردد . بنابراین مجموعه دستورات (۱) و (۲) که در ذیل آمده اند
معادل یکدیگرند .
ؤ m= &name;
(َ۱) ؤ
ؤ p= *m;
p= nam;( 2)
 
اعمال روی اشاره گرها

اعمالی که بر روی اشاره گرها فایل انجام است به وسعت اعمالی که بر روی سایر
متغیرهای حافظه انجام پذیر است ، نیست . اعمالی که بر روی اشاره گرها انجام
پذیرند عبارتند از : ۱
عمل انتساب : همچون سایر انواع متغیرها، میتوان مقداری را به یک اشاره گر
نسبت داد ( مثال ۱ ) . ۲
اعمال محاسباتی : دو نوع اعمال محاسباتی می توان بر روی اشاره گرها انجام
داد که عبارتند از :
الف ) عمل جمع .
ب ) عمل تفریق .

مثال ۱: main)(
{
int x ;
int *p1 / *p2 ;
p1=&x ;
p2=p1 ;
printf(“\n the address of x is: “);
printf(“%p”/p2 );
}

نمونه ای از خروجی برنامه مثال ۱ : the address of x is:692B:0fDC

برای پی بردن به چگونگی عمل جمع و تفریق روی اشاره گرها فرض کنید که p
اشاره گری از نوع ” صحیح ” است و به ملح ۲۰۰۰ حافظه اشاره می کند . اکنون دستور p + +;
را اجرا کنیم محتویات جدید اشاره گر p ، برابر با ۲۰۰۲ خواهد بود . زیرا
طول نوع ” صحیح ” برابر با ۲ بایت است و با افزایش یک واحد به اشاره گر ، به
اندازه طول نوع اشاره گر به آن افزوده خواهد شد و نه به اندازه یک واحد . اگر
دستور ; – p- را صادر کنیم ، اشاره گر P مجددا” به محل ۲۰۰۰ حافظه اشاره خواهد
کرد . اگر باز هم دستور ; – p- را صادر کنیم این بار به محل ۱۹۸۸ اشاره خواهد
کرد ( شکل ۱ ) . char *ch= 2000;
int *i=2000;

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ch | 2000 | i

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ch+1 | 2001 |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ch+2 | 2002 | i+1

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ch+3 | 2003 |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ch+4 | 2004 | i+2

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ch+5 | 2005 |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
حافظه
شکل (۱) . انجام اعمال محاسباتی روی اشاره گر
۳
مقایسه اشاره گرها : بااستفاده از عملگرهای رابطه ای می توان اشاره گرها را
با یکدیگر مقایسه نمود. بعنوان مثال ، اگر pو qو از نوع اشاره گر باشند ، دستور
زیر معتبر است : if(p < q )print f(“p points to lower memory than q”);

مقایسه اشاره گرها معمولا” در مواردی استفاده می شود که دو یا چند اشاره گر به اشاره می کنند .
 
اشاره گر و آرایه

در زبان C بین آرایه ها و اشاره گرها ارتباط نزدیکی وجود دارد ( اشاره گرها
حاوی یک آدرس و اسم آرایه نیز یک آدرس است ). اسم آرایه آدرس اولیه عنصر آرایه
را مشخص می کند . بعبارت دیگر اسم آرایه آدرس اولین محلی را که عناصر آرایه از
آنجا به بعد در حافظه قرار می گیرند در خود نگهداری می کند . بعنوان مثال اگر
آرایه ای بصورت table[8] تعریف کرده باشیم و اولین عنصر آرایه در محل ۴۰۰ حافظه
قرار داشته باشد و اشاره گری بنام ptr بصورت زیر تعریف کرده باشیم ، int * ptr;

دستور ptr = & table[0] آدرس شروع آرایه یعنی ۴۰۰ را در اشاره گر ptr قرار
می دهد ( این دستور معادل دستور ptr = table; است ) و دستور t = * ptr محتویات
اولین محل آرایه ( اولین عنصر آرایه ) یعنی (table[0]) را در متغیرt قرار داده
دستور * ptr = 0 محتویات اولین محل آرایه table را برابر با صفر قرار می دهد .
با مطالبی که تاکنون گفته شد برای دسترسی به عناصر آرایه علاوه بر اندیس ، از
اشاره گرها نیز می توان استفاده کرد :
آدرس آرایه را در اشاره گر ptr قرار می دهد ptr= table;
به دومین عنصر آرایه اشاره می کند (table[1]);(َptr+ 1) *
به i+1 امین عنصر آرایه اشاره می کند ;(ptr+i) *

مثال : برنامه ای که ۵ مقدار را از ورودی خوانده و در آرایه ای قرار می دهد .
سپس آنها را از آخرین مقدار به اولین مقدار به خروجی منتقل می کند . main)(
{
int arr[5] /i ;
printf(“\n enter five value: ” );
for(i=0 ; i<5 ; i++)
scanf(“%d”/&arr );
printf(“\n the reverse output is: “);
for(i=4 ; i>=0 ; i) –
printf(“%4d”/*(arr+i ));
}

نمونه ای از خروجی برنامه مثال بالا : enter five value: 10 20 30 40 50
the reverse output is:50 40 30 20
 
اشاره گرها و رشته ها

چون رشته ها در زبان C بصورت آرایه تعریف می شوند بین آنها و اشاره گرها نیز
ارتباط نزدیکی وجود دارد . بطوری که بسیاری از توابع کتابخانه ای که با رشته ها
سر و کار دارند ، ارتباط نزدیکی با اشاره گرها پیدا می کنند . بعنوان مثال تابع
()strchr که محل اولین وقوع کاراکتری را در رشته ای پیدا می کند بصورت زیر
استفاده می شود :
) <رشته > و <کاراکتر مورد جستجو>(= strchr اشاره گر

مثال ۱: برنامه ای که یک رشته و کاراکتری را از ورودی خوانده و محل اولین
وقوع این کاراکتر را در رشته پیدا می کند . main)(
{
char ch/line[81]/*ptr/*strchr )(;
printf(“\nenter string to search:\n”);
gets(line );
printf(“\n enter a character: ” );
ch=getche )(;
ptr=strchr(line/ch );
printf(“\n the string start at ” );
printf(“address:%u/line” );
printf(“\n first occurence of” );
printf(” <%c> is address:%u”/ch/ptr);
printf(“\n this is position:” );
printf(“%d( start from 0)”/ptr-line);
}

نمونه ای از خروجی برنامه مثال ۱ : enter string to search:
c has no bound checking.
enter a character: k
the string start at address:3984

first occurence of is address:8291
this is position:20(start from 0 );

همانطوریکه ازخروجی برنامه مثال ۱ پیداست تابع strchr با جستجوی یک کاراکتر
در یک رشته ، آدرس این کاراکتر را بعنوان نتیجه عمل مشخص میکند و در یک اشاره گر
قرار می دهد . همانطور که قبلا” گفته شد ، اگر تابعی دارای نوعی غیر از “صحیح ”
باشد باید در تابع فراخواننده ، نوع آن به کامپایلر اعلام گردد . لذا در مثال
(َ۱) نوع تابع ()strchr بصورت اشاره گر به کاراکتر تعریف شده است . البته اگر با
استفاده از دستور پیش پردازنده # include فایل “string” به برنامه معرفی گردد
نیازی به تعریف این تابع بصورت اشاره گر نیست .

مثال ۲: برنامه ای که رشته ای را از ورودی دریافت کرده و کلیه حروف کوچک این
رشته را به حروف بزرگ تبدیل می کند . main)(
{
char s[50] ;
printf(“enter a string in”);
printf(” lowercase:\n”);
gets(s );
upper(s );
printf(“\n uppercase of”);
printf(” string is:\n”);
puts(s );
}

upper(char *string)
{
while(*string)
{
if(*string>=’a’ && *string<=’z')
*string=*string-32 ;
string++ ;
}
}

نمونه ای از خروجی برنامه مثال ۲ : enter a string in lowercase:
in c all keyword are lowercase.
uppercase of string is:
IN C ALL KEYWORD ARE LOWERCASE.

مثال ۳: برنامه ای که رشته ای را از ورودی خوانده و کلیه حروف بزرگ موجود در
رشته را به حروف کوچک تبدیل می کند : main)(
{
char s[50] ;
printf(“enter a string in”);
printf(” uppercase:\n”);
gets(s );
upper(s );
printf(“\n lowercase of string”);
printf(” is:\n”);
puts(s );
}

upper(char *string)
{
while(*string)
{
if(*string>=’A’ && *string<=’Z')
*string+=32 ;
string++ ;
}
}

نمونه ای از خروجی برنامه مثال ۳ : enter a string in uppercase:
THIS IS A TEST FOR CONVERT TO LOWER.
lowercase of string is:
this is a test for convert to lower.

مثال ۴: برنامه ای که یک رشته و کاراکتری را از ورودی خوانده و تعداد دفعات
تکرار این کاراکتر را رشته مشخص می کند . main)(
{
char string[40] / ch ;
int count ;
printf(“enter string for search:\n”);
gets(string );
printf(“\n enter a character:” );
ch=getche )(;
count=char_count(string/ch );
printf(“\n number of occurs of ” );
printf(“char <%c> is:%d”/ch/count );
}

char_count(char *s/char letter)
{
int count=0 ;
while(*s)
if(*s++==letter)
count ++ ;
return(count );
}

نمونه ای از خروجی برنامه مثال ۴ : enter string for search:
this is a simple test.
enter a character:
number of occurs of char is:3

مثال ۵: برنامه ای که رشته عددی را از ورودی خوانده و سپس آن را به مقدار
عددی تبدیل می کند . main)(
{
int number ;
char s[10] ;
printf(“\n string representation”);
printf(” of numeric:” );
gets(s );
ascii_to_int(&number/s );
printf(“\n numeric value of “);
printf(“string is:%d”/number );
}

ascii_to_int(int *value/char *str)
{
int sign=1 ;
*value=0 ;
while(*str==’ ‘ )str++ ;
if(*str==’-’ || *str==’+')
sign=(*str++==’-’ )?- 1:1;
while(*str)
if((*str>=’0′ )&&( *str<=’9′))
*value=(*value*10)+(*str++- 48 );
else
{
printf(“Watning: the<%c> is:”/*str);
printf(” invalid character.” );
exit(0 );
}
*value *=sign ;
}

خروجی های حاصل از ۴ بار اجرای برنامه مثال ۵ : string representation of a numeric-:342( 1)
numeric value of string is-:342

string representation of a numeric:+2341( 2)
numeric value of string is:+2341

string representation of a numeric:543( 3)
numeric value of string is:543

string representation of a numeric:45y4( 4)
Watning: the is invalid character.

مثال ۶: برنامه ای که عددی را از ورودی خوانده و سپس آن را به رشته تبدیل
می کند . main)(
{
int number ;
char s[10] ;
printf(“\n enter a number: ” );
scanf(“%d”/&number );
int_to_ascii(number/s );
printf(“\n the string value is:%s”/s);
}

int_to_ascii(int*value/char *str)
{
int sign=value ;
char temp / *savestr=str ;
if(value<0)
value*=-1 ;
do{
*str++=(value % 10)+48 ;
value=value/10 ;
} while(value>0 );
if( sign<0)
*str++=’-’ ;
*str– =’\0′ ;
while(savestr
{
temp=*str ;
*str–=*savestr ;
*savestr++=temp ;
}
}

نمونه ای از خروجی برنامه مثال ۶ : enter a number:2341
the st
 
ارزش دهی اولیه رشته ها به عنوان اشاره گر

در این قسمت می خواهیم مشخص کنیم که چگونه میتوان رشته ها را بعنوان اشاره گر
مقدار اولیه داد . برای روشن شدن موضوع ، به مثال ۱ توجه نمایید .

مثال ۱: main)(
{
char *text=”your name is:”;
char name[41] ;
printf(“\n enter your name: ” );
gets(name );
printf(“\n\n %s text” );
puts(name );
}

نمونه ای از خروجی برنامه مثال ۱ : enter your name:mohammad
your name is:mohammad

اولین دستور مثال ۱ را بصورت زیر نیز می توان نوشت : static char text[] = “your name is:”;

این دو دستور از نظر اثری که در حافظه می گذارند تفاوتی با یکدیگر ندارند .
ولی چون دستوری که در برنامه آمده است متغیر text را بصورت اشاره گر تعریف کرده
است ، قابلیت انعطاف بیشتری به این متغیر داده است . این امر باعث شده است که
با دستور ساده ;(text++)puts رشته text کاراکتر به کاراکتر به خروجی منتقل گردد
که نتیجه زیر حاصل خواهد شد : your name is:

وقتی که رشته ها به صورت اشاره گر تعریف می شوند ، بخصوص در مواقعی که طول
عناصر مختلف آن ، متفاوت باشند موجب صرفه جویی در میزان حافظه می گردند ( مثال ( . ۲

مثال ۲: برنامه ای که برای ذخیره کردن نام های تعدادی از افراد ، از آرایه ای
از اشاره گرها استفاده می کند. این برنامه با خواندن نام ۵ نفر از ورودی ، آنها
را در آرایه ای قرار داده ، سپس نامی را از ورودی دریافت می کند و تشخیص می دهد
که آیا این نام در لیست وجود دارد یا خیر . main)(
{
int dex / exist=0 /k ;
char name[21] ;
static char *list[5]=
{“ali”/
“ahmad”/
“alireza”/
“jalal”/
“mohammad”
} ;
printf(“enter a name for search:”);
gets(name);
for(dex=0;dex<5;dex++)
{
if(strcmp(list[dex]/name)==0)
{
exist=1 ;
break ;
}
}
if(exist==1)
printf(“\n name <%s> exist.”/name);
else
printf(“\n name ” );
printf(“<%s> not exist.”/name);
}

نمونه ای از خروجی برنامه مثال ۲ : enter a name for search: ali
name exist.

اگر در مثال ۲ فرض شود که اولین عنصر آرایه list ( که حاوی ۵ نام است ) در
محل ۱۰۰۰ حافظه قرار داشته باشد . این آرایه بصورتی که در شکل (۱) آمده است در
حافظه قرار می گیرد .
اگر درمثال ۲ بجای تعریف آرایه ای از اشاره گرها، آرایه ای از رشته ها را تعریف
میکردیم آنگاه می بایست آرایه list بصورت آرایه ای دو بعدی تعریف میشد که تعداد
سطرهای آن برابر با تعداد افراد ( تعداد عناصر آرایه ) و تعداد ستون های آن
برابر با طول طولانی ترین نام موجود بود ( شکل ۲ و مثال ۳ ) .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤ |A |h |m |a |d |\0|
1000ؤؤ > | 1000 List [0]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤ |A |l |i |\0|
1006ؤؤ > | 1006 List [1]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤ |A |m |i |n |\0|
1010ؤؤ > | 1010 List [2]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤ |y |a |f |a |r |n |e |z |h |a |d |\0|
1015ؤؤ > | 1015 List [3]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤ |B |a |h |r |a |m |i |\0|
1027ؤؤ > | 1027 List [4]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤ
شکل (۱) . نحوه قرار گرفتن آرایه ای از اشاره گرها در حافظه ، شامل ۵ نام

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | | | | |
|
|A hh |m |a |d |\0| 1000ؤؤؤؤؤؤؤؤؤ > List [0]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | | | | | | |
|
|A ll |i |\0| 1012ؤؤؤؤؤؤؤؤؤ > List [1]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | | | | | |
|
|A mm |i |n |\0| 1023ؤؤؤؤؤؤؤؤؤ > List [2]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |y aa |f |a |r |n |e |z |h |a |d |\0|
1035ؤؤؤؤؤؤؤؤؤ > List [3]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | | |
|
|B aa |h |r |a |m |i |\0| 1047ؤؤؤؤؤؤؤؤؤ > List [4]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
شکل (۲) . نحوه قرار گرفتن آرایه ای از رشته ها در حافظه ، شامل ۵ نام

با توجه به نحوه ذخیره شدن اطلاعات در اشکال ۱و ۲و ذخیره کردن رشته ها بصورت
آرایه ای از اشاره گرها در صرفه جویی میزان حافظه بسیار موثر است ولی در همه حالات
اینطور نیست . بعنوان مثال اگر طول همه رشته ها ۱۲ باشد ( به اندازه بزرگترین
طول رشته در مثال ۲ )، حافظه تخصیص یافته در روش اول ( آرایه ای از اشاره گرها )
دارای ۵ اشاره گر اضافی خواهدبود که حافظه بیشتری را نسبت به روش دوم ( آرایه ای
از رشته ها ) اشغال می کند . مزیت عمده بیان رشته ها بصورت آرایه ای از اشاره گرها
سرعت بالاتر و سهولت دسترسی به عناصر آنها است . زیرا نیازی به انجام محاسبات
جهت دسترسی به عناصر آرایه نیست .

مثال ۳: برنامه ای که نام تعدادی از افراد را از ورودی خوانده و در یک آرایه
قرار می دهد . سپس با استفاده از آرایه ای از اشاره گرها ، آن را مرتب می کند و
نتیجه را به خروجی می برد . main)(
{
char name[30][81] ;
char *ptr[30]/*temp ;
const int k=30 ;
int in / out / count=0 ;
while(count
{
printf(“\n enter name of number”);
printf(” %d:”/count+1 );
gets(name[count] );
if(strlen(name[count])==0)
break ;
ptr[count++]=name[count] ;
}
for(out=0 ; out
for(in=out+1 ; in
if(strcmp(ptr[out]/ptr[in])>0)
{
temp=ptr[in] ;
ptr[in]=ptr[out] ;
ptr[out]=temp ;
}
printf(“<< the sorted list is:>>”);
for(out=0 ; out
printf(“\n name %d is:”/out+1);
printf(“%s”/ptr[out]);
}

نمونه ای از خروجی برنامه مثال ۳ : enter name of number 1:bahrami
enter name of number 2:amin
enter name of number 3:jafar
enter name of number 4:sadeghi
enter name of number 5:
<< the sorted list is:>>

name 1 is:amin
name 1 is:bahrami
name 1 is:jafar
name 1 is:sadeghi

برای توضیح بیشتر در مورد چگونگی مرتب کردن رشته ها از طریق آرایه ای از
اشاره گرها ، به شکل های ۳و ۴و که بیانگر نحوه قرار گرفتن عناصر آرایه در حافظه
قبل و بعد از مرتب شدن هستند توجه نمایید .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ |B |a |h |r |a |m |i |\0|
ؤؤؤؤؤؤؤؤؤ > | ptr[0]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ | |
|
|A |m |i |n |\0|ؤؤؤؤؤؤؤؤؤ > | ptr[1]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ |
|
|y |a |f |a |r |\0|ؤؤؤؤؤؤؤؤؤ > | ptr[2]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ |s |a |d |e |g |h |i |\0|
ؤؤؤؤؤؤؤؤؤ > | ptr[3]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ
شکل (۳) . وضعیت اشاره گرها قبل از مرتب شدن

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ |B |a |h |r |a |m |i |\0|
ؤؤؤ ؤؤؤؤؤ > | ptr[0]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ |
| | |A |m |i |n |\0|ؤؤؤؤؤؤؤؤؤ > | ptr[1]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ |
| |y |a |f |a |r |\0|ؤؤؤؤؤؤؤؤؤ > | ptr[2]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ |s |a |d |e |g |h |i |\0|
ؤؤؤؤؤؤؤؤؤ > | ptr[3]
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤؤؤؤ
شکل (۴) . وضعیت اشاره گرها بعد از مرتب شدن

نکته ای که در مورد مثال ۳ باید مورد توجه قرار گیرد این است که آرایه name
بصورت دو بعدی تعریف شده است ولی در حین دسترسی به عناصر آن ، بصورت یک بعدی
مورد استفاده قرار گرفته است . این مساله بدین دلیل است که در زبان C قسمتی از
آرایه را می توان بصورت یک آرایه فرض کرد . بعبارت دیگر ، در یک آرایه دو بعدی
هر سطر را می توان بصورت یک آرایه یک بعدی در نظر گرفت . لذا می توان گفت که
آرایه دو بعدی ، آرایه ای از آرایه های یک بعدی است . بعنوان مثال در دستور : static char name[30][81];

آرایه name یک آرایه دو بعدی تعریف شده است که میتوان آن را بصورت یک آرایه
یک بعدی با تعداد ۳۰ عنصر در نظر گرفت که هر عنصر آن نیز یک آرایه یک بعدی به
 
اشاره گر به اشاره گر

اگر متغیری آدرس متغیر دیگر را در خود نگهداری کند ، متغیر اول یک اشاره گر
است . اگر متغیر دوم ، از نوع اشاره گر باشد در اینصورت متغیر اول یک اشاره گر
به اشاره گر است ( شکل ۱ ) . یادآوری می شود که آرایه ای از اشاره گرها ، نوعی
اشاره گر به اشاره گر است .
متغیر اشاره گر
ؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤ |
مقدار |ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ آدرس >|
ؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤ
ؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤ |
مقدار |ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ آدرس >|ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ آدرس >|
ؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤ ؤؤؤؤؤؤؤؤؤ
شکل (۱) . اشاره گر به اشاره گر

برای تعریف متغیرهای اشاره گر به اشاره گر ، از دو علامت * استفاده می شود .

مثال : برنامه ای شامل اشاره گر به اشاره گر . main)(
{
int x / *p /**q ;
x=10 ;
p=&x ;
q=&p ;
printf(“\n the points to value:”);
printf(“%d”/**q );
}

خروجی حاصل از اجرای برنامه مثال بالا : the points to value:1
 
نکاتی در مورد اشاره گرها

علیرغم قدرت زیادی که استفاده از اشاره گرها در زبان به برنامه نویس می دهد
اشکالاتی را نیز می تواند بوجود آورد که برنامه نویس باید آنها را در نظر داشته
باشد .
اشکال اول ) استفاده از اشاره گرهایی که قبلا” مقدار نگرفته اند .

مثال ۱: main)(
{
int x/*p ;
x=10 ;
*p=x ;
}

دربرنامه مثال ۱ عدد ۱۰ به متغیر x نسبت داده میشود و دستور *p=x; به ماشین
می گوید ” محتویات متغیر x را در آدرسی که اشاره گر p به آن اشاره می کند قرار
بده ” . چون اشاره گر p بجایی در حافظه اشاره نمیکند ( قبلا” مقدار نگرفته است )
عمل مورد نظر انجام نخواهد شد. برای رفع این مشکل کافی است در اشاره گر p مقدار
معتبری قرار گیرد .

اشکال دوم ) عدم استفاده صحیح از اشاره گرها

مثال ۲: main)(
{
int x / *p ;
x=10 ;
p=x ;
printf(“\n %d”/*p );
}

هدف برنامه مثال ۲ این بود که مقدار متغیرx را که برابر با ۱۰ است در خروجی
چاپ نماید ولی به دلیل نادرست بودن دستور p=x; ( با توجه به اشاره گر بودن p )
نتیجه مطلوب حاصل نخواهد شد . این دستور موجب می شود تا عدد ۱۰ ، نه بعنوان یک
مقدار بلکه بعنوان یک آدرس به اشاره گر p منتقل گردد . برای رفع این مشکل کافی
است این دستور را بصورت p=&x; نوشت تا آدرس متغیر x به اشاره گر p منتقل شود .

اشکال سوم ) فرض هایی که برنامه نویس در مورد محل قرار گرفتن متغیرها در حافظه
دارد .

وقتی که متغیرها در حافظه قرار می گیرند ، جای آنها برای ما مشخص نیست و در
هر جایی که فضایی کافی وجود داشته باشد این متغیرها در آنجا ذخیره می شوند .
به همین دلیل مقایسه اشاره گرهایی که به عناصری از یک نوع اشاره نمی کنند صحیح
نبوده و با مشکل مواجه می گردد ( مثال های ۳و ۴و ) .

مثال ۳: main)(
{
char s[80]/y[80] ;
char *p1 / *p2 ;
p1=s ;
p2=y ;
if(p1
printf(“p1 points to lower addree.”);
}

در مثال ۳ مقایسه p1و p2و با یکدیگر صحیح نیست ، زیرا محل قرار گرفتن
رشته های sو yو برای ما مشخص نیست .

مثال ۴: main)(
{
int first[10]/second[10] ;
int *p / t ;
p=first ;
for(t=0 ; t<20 ; t++)
*p++=t ;
}

در مثال ۴ سعی شده که به عناصر آرایه های firstو secondو اعداد ۰ تا ۱۹ نسبت
داده شود. اگر چه ممکن است این عمل در بعضی از کامپایلرها به درستی انجام گیرد
ولی در حالت کلی این طور نیست ، زیرا ممکن است عناصر آرایه های firstو secondو
در محل های متوالی حافظه قرار نگیرند .
با اشکالاتی که تاکنون درمورد اشاره گرها گفته شد برنامه نویس باید در استفاده ا دقت کافی بخرج دهد تا با مشکل مواجه نگردد .
 
دسترسی به اجزای ساختمان

همانطورکه مشاهده شد هر ساختمان دارای چند جزئ است که برای دسترسی به هر یک
از اجزای آن از روش کلی زیر استفاده می شود :
<اسم متغیر از نوع ساختمان >.<نام جزئ>
بعنوان مثال ، با فرض این که p1و p2و دو متغیر از نوع ساختمان بوده و دارای ۳
جزئ به اسامی name، person،و salaryو باشند ، دستورات زیر موجب دسترسی به هر
یک از اجزای متغیر p1 می شوند که در مورد p2 نیز میتوان به همین طریق عمل کرد: p1.name
p1.persno
p1.salary

اگر اجزای ساختمان ، از نوع آرایه باشند ، ذکر اندیس آرایه جهت دسترسی به
عناصر آن الزامی است . بعنوان مثال ، دستور زیر را در نظر می گیریم : struct student {
char name [31];
int cours [10];
int unit [10];
int grade [10];
int persno;
} st1.st2;

در دستور فوق بعضی از اجزای ساختمان student بصورت آرایه ای تعریف شده اند .
دستورات زیر موجب دسترسی به اجزای متغیر ساختمان st1 می شوند : st1.cours [1]
st1.cours
st1.name

همانطورکه مشاهده شد اگر اجزای ساختمان رشته ای باشند میتوان به تک تک عناصر
آن نیز دسترسی پیدا کرد (st1.name)
در مورد مقدار دادن به اجزای ساختمان می توان همانند یک متغیر معمولی عمل
کرد . لذا با فرض این که st1 متغیر ساختمانی باشد که قبلا” تعریف شده است
دستورات زیر معتبر می باشند : st1.persno=1243;( 1)
printf(“\n %d”/st1.persno);( 2)
gets(st1.name);( 3)
for( i=0;i<10;i++( )4)
scanf(“%d”/&st1.unit);

مثال : برنامه ای که دو عدد موهومی را از ورودی خوانده و مجموع آنها را
محاسبه می کند و به خروجی می برد . main)(
{
struct complex
{
int real ;
int unreal ;
} comp1 / comp2 /result ;
printf(“\n enter the real part”);
printf(” for number %d:”/1);
scanf(“%d”/&comp1.real );
printf(“\n enter the unreal part”);
printf(” for number %d:”/1 );
scanf(“%d”/&comp1.unreal );
printf(“\n enter the real part “);
printf(” for number %d:”/2 );
scanf(“%d”/&comp2.real );
printf(“\n enter the unreal part”);
printf(” for number %d:”/2 );
scanf(“%d”/&comp2.unreal );
result.real=comp1.real+comp2.real;
result.unreal=
comp1.unreal+comp2.unreal;
printf(“\nthe result of sum is:”);
printf(“\nreal part=” );
printf(“%d”/result.real);
printf(“\n unreal part” );
printf(“=%d”/result.unreal);
}

نمونه ای از خروجی برنامه مثال بالا : enter the real part for number 1:12
enter the unreal part for number 1:25
enter the real part for number 2:5
enter the unreal part for number 2:19

the result of sum is:

real part=17

un
 
بالا