• پایان فعالیت بخشهای انجمن: امکان ایجاد موضوع یا نوشته جدید برای عموم کاربران غیرفعال شده است

آموزش C++ سي پلاس پلاس از پايه

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
//Listing 5.4 -demonstrates passing by value
1:#include <iostream>
2:
3:void swap(int x,int y);
4:
5:int main()
6:{
7:int x =5,y =10;
8:std::cout <<“Main.Before swap,x:“ <<<x
9:<<“ y::“ <<<y <<“\n ”;
10:swap(x,y);
11:std::cout <<“Main.After swap,x:“ <<<x
12:<<“ y::“ <<<y <<“\n ”;
13:return 0;
14:}
15:
16:void swap (int x,int y)
17:{
18:int temp;
19:std::cout <<“Swap.Before swap,x:“ <<<x
20:<<“ y::“ <<<y <<“\n ”;
21:temp =x;
22:x =y;
23:y =temp;
24:std::cout <<“Swap.After swap,x:“ <<<x
25:<<“ y::“ <<<y <<“\n ”;
26:}


Main.Before swap.x:5 y:10
Swap.Before swap.x:5 y:10
Swap.After swap.x:10 y:5
Main.After swap.x:5 y:10
5 OUTPU
احضار يك تابع با مقدار:
قسمت آبي تابع احضار شده است.

روشي كه در بالا مي بينيد براي صدا كردن تابع، همان روشي است كه ما به طور معمول هميشه استفاده مي كنيم. يعني داخل پرانتز ، ورودي تابع را ارسال مي كنيم.
قسمت سبز رنگ

برنامه بالا براي اين نوشته شده كه بگه كه با اين روش مقدار فرستاده شده تغيير نمي كند. منظور همان x است. قبل صدا كردن و بعد صدا كردن تابع مقدار x در main همان عدد 5 است.
قسمتي كه با رنگ قرمز مشخص شده ، نتيجه اجراي برنامه است. فقط داخل تابع احضار شده ، مقدار x تغيير كرده. به نظر من (saalek) اين x اصلا آن x نيست كه بگيم تغيير كرده. قبلا گفتيم كه متغير موضعي چيه و گفتيم كه متغيرهايي كه درون تابع تعريف مي شوند هم محلي و هم موضعي اند. پس x داخل تابع احضار شده فرق داره با x داخل main .
.
T
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
به نقل از mostafa_gm :
خوب واسه کسی که میخواد تازه برنامه نویسی رو شروع کنه سرو کله زدن با کلاسها و متدهای protected و نمیدونم چی چی و سربار گذاری و ارث بری و توابع مجازی و اشاره گر ها و این کثافت کاریهای تو ++C واقعا وحشتناکه. من خودم تو این مدتی که با VB کار میکردم و حالا برای یه کاری دوباره مجبورم برم سراغ ++VC تازه میفهمم که VB چه نعمتی بود. لااقل برای استفاده از یه تابع یا یه متغیر از یه کلاس هیچ وقت لازم نیست فایل هدرشو include کنم و از کلاسش یه شی بسازم و از این کارای بیخود. واقعا ++VC اعصاب خرد کنه با این ادیتور مزخرفش.



البته #C در مقایسه با ++C خیلی قابل تحمل تره. همین که اشاره گر نداره و بادیدن چیزایی مثل LPTSTR...ZTYRLX و کلی * و & و شکلک های دیگه آدم وحشت نمیکنه خودش جای شکر داره.
___

من هم فرموده استاد گرامي را تاييد مي كنم. هر چند كوچكتر از آنم كه نظر بدم ولي در حد تجربه خودم گفتم.


teleport pro
براي دانلود سايت
كرك آن

http://www.cxzmohamad61.blogfa.com
از وبلاگ بالا آدرس دانلودش را بيابيد.
-----------------------
به نقل از balabala :
ولی من خودم هم گاهی با #c کار می کنم. ولی هرچی توش می نویسم مدیون وی بی یم. درواقع #c تلفیقی از وی بی و سی هستش..


برای خوده واردهاش هم سخته چه برسه به یه تازه کار. اصلا سی++ برای پروژه های سنگین و گروهی خوبه. سی شارپ هم در ابتدا چون شباهت زیادی به سی و مفاهیم وراثت و چندشکلی و ... داره خیلی سخته.

----
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
رجيسترهاي ax و bx و غيره ، دو بايتي هستند.
در اسمبلي مي گوييم: ax=ffff .
هر بايت 256 حالت دارد. كه ff آنرا پوشش مي دهد.
طبيعتا براي ah و al كه نيمكره هاي ax هستند(و يك بايت هستند) داريم. Ah=ff و al=ff يعني ما داريم يك بايت را عدد مي دهيم.

علت اينكه من دارم به سمت اسمبلي متمايل مي شوم ، علتش اينه كه مقدار دادن به رجيسترها در اسمبلي براي خود من راحت تره تا اينكه بخواهم با struct و union (در سي) به رجيسترها مقدار بدهم.

در برنامه زير من مي خواهم محتواي رجيسترها را با اسمبلي بخوانم و به سي منتقل كنم و در آنجا (سي) چاپ كنم.
همان طور كه مي دانيد ، نوع int دو بايتي است. و ax هم كه دو بايتي بود ، پس بر هم ميشه منطبقشان كرد.
ميشه ah و al را روي char منطبق كرد . چون هر دو يك بايتي هستند. ولي چون من از رشته و char فعلا فراري ام ، از int كه عدد صحيح است استفاده مي كنم.

کد:
#include <conio.h>		
#include <iostream.h>				
				
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
 

 int myint ;

    asm {
	MOV ah, 00
	mov al,41
    mov [myint],ax
    }

cout<<"myint="<<myint<<endl;


 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'x') goto menu;				
}

نتيجه اجراي برنامه چاپ myint است كه همان 41 است.
.

143.gif

.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
به برنامه زير كه فقط مقادير ah و al نسبت به برنامه قبلي تفاوت داره توجه كنيد.

کد:
#include <conio.h>		
#include <iostream.h>				
				
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
 

 int myint ;

    asm {
	MOV ah,[color=red]1[/color]
	mov al,[color=red]0[/color]
    mov [myint],ax
    }

cout<<"myint="<<myint<<endl;


 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'x') goto menu;				
}


144.gif


در قسمت اسمبلي ما در مبناي 10 عدد وارد مي كنيم ولي ah در 256 ضرب ميشه بعد به myint اضافه ميشه.
==================
البته بهتره از unsigned int استفاده بشه تا مقادير بزرگتر هم جا بشه.
ولي از long نميشه استفاده كرد چون با ax هم بايت نيست.
براي بازيابي ah از درون myint هم ميشه با تقسيم و عملگر % يعني باقيمانده تقسيم به نتيجه رسيد. من اين كارها را انجام دادم ولي برنامه اش را ننوشتم تا زياد پست نزنم.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
کد:
#include <conio.h>
#include <iostream.h>
[color=red]#include <dos.h>[/color]
void main()
{
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
int a1=1,a2=2,a3=3,a4=4,a5=5;
char c1,c2,c3;
cout<<"[color=blue]&a1[/color]="<<&a1<<endl;
cout<< [color=red]peek(0x8f95,0xfff0)[/color]<<endl;

 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'q') goto menu;
}

به برنامه بالا نگاه كنيد. من از يك تابع استفاده كردم كه با گرفتن آدرس قطعه و شماره حافظه به ما ميگه كه در آن خانه حافظه چه مقداري قرار دارد.اين تابع در dos.h است پس اينكلود كنيد.
اما اينكه من اين آدرسها را از كجا بدست آوردم جوابش اينه كه اول با دستور &a1 فهميدم كه متغيرها در چه شماره قطعه و شماره حافظه اي ذخيره مي شوند و بعد همان اعداد را به تابع peek دادم. عكس اين تابع هم poke است كه بجاي خواندن حافظه ، در آن مي نويسد.

نكاتي كه با ور رفتن من نتيجه گرفتم.

اولا شماره قطعه بسته به كد برنامه فرق مي كند ولي در اجرائات متوالي با يك كد ثابت ، شماره قطعه ثابته. البته نمي توانم بگم هميشه. خودتان برويد امتحان كنيد.

نكته ديگه اين كه به متغيرهاي متوالي كه ما ايجاد مي كنيم كنار هم و به همان ترتيب حافظه تخصيص داده مي شود.
ديگه معلومه ديگه كه char يك خانه مي خواهد و int دو خانه و الي آخر.

به نظر من جايي كه متغيرها را مي نويسد همان ((قطعه داده )) است. البته من اين را در سي نخوانده ام. فقط در اسمبلي يك ((قطعه داده )) داشتيم و احتمالا در سي هم داريم.

و آدرس هاي حافظه به ترتيب پايين رونده در اين قطعه چيده مي شوند. يعني دومي شماره حافظه اش از اولي كمتره. مثلا با دو int دومي 2 تا شماره حافظه اش كمتره.
.
نكته آخر هم اين كه وقتي با
int
ها داريد كار مي كنيد وقتي دوتا دوتا پايين مي بريد شماره را ، جواب درست مي گيريد ولي اگر يكي پايين بريد جواب مبهمه. خودتان امتحان كنيد شايد قانوني براي اين اعداد پيدا كرديد.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
کد:
#include <conio.h>		
#include <iostream.h>				
[color=red]#include <dos.h>[/color]
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
 
[color=red]sound(400);[/color]

 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'q') goto menu;
	[color=red]sound(50000);[/color]
}


تابع sound داخل پرانتز فركانس مي خواهد. در آخر برنامه من فركانس 50000 را دادم تا ساكت بشه موقع خروج. Dos.h هم بايد include بشه.
اولا براي سرگرمي خوبه دوما براي كنترل برنامه هم مي تواند مفيد باشد. سوما يك كاربردهايي شايد داره كه من نمي دونم.
.
========================
ولي كار من اشتباه بود. راه درستش چيز ديگس. با nosound .
تابع delay هم در dos.h است. كه ميلي سكند ورودي اش است.
و كارش ايجاد تاخير در ادامه اجرا است.

کد:
#include <conio.h>		
#include <iostream.h>				
[color=red]#include <dos.h>[/color]				
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
 
[color=red]
 sound(440);
delay(500);
nosound();
[/color]	

 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'q') goto menu;
}
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
برنامه زير را از اين آدرس گرفته ام.

http://www.sourcecodesworld.com/source/show.asp?ScriptID=1075

چيز جديدي نداره ولي چون قشنگ كار كرده بود پست كردم.
به حلقه بي شرط for آن دقت كنيد. البته نمي گم كار خوبيه ولي ابتكاري است.
همچنين نويسنده اعداد را وقتي از كاربر گرفته داخل متغير كاراكتري ريخته نه عددي و بعد با تابعي آن را به عدد تبديل كرده. همان تابع atof .
اين جوري خطاي كمتري رخ مي دهد.
نويسنده از pouse استفاده كرده بود كه من delay را جاش گذاشتم.


کد:
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include <dos.h>
#include <math.h>

void main()
{

        float input1;
        float input2;
        double output;
        char what;
        char num1[34];
	  char num2[34];
	  
  clrscr();
        gotoxy(15,1);
        cout<<"welcome to the calculater program"<<endl;
	delay(4000);


	clrscr();
       [color=red] for(;;)[/color]
        {
        clrscr();
        cout<<"enter the first number:"<<endl;
        [color=red] cin>>num1;
        input1=atof(num1);[/color]
        clrscr();
        cout<<"enter the second number:"<<endl;
        cin>>num2;
        input2=atof(num2);
        clrscr();
	cout<<"enter opearation + -  *  / s for square root e.exitt"<<endl;
        cin>>what;
        switch(what)
        {
                case'+':
                output=input1+input2;
                clrscr();
		cout<<input1<<what<<input2<<"="<<output<<endl;
		delay(4000);
                break;

                case'-':
                output=input1-input2;
                clrscr();
		cout<<input1<<what<<input2<<"="<<output<<endl;
			delay(4000);
                break;

                case'*':
                output=input1*input2;
                clrscr();
                cout<<input1<<what<<input2<<"="<<output<<endl;
			delay(4000);
                break;

                case'/':
                output=input1/input2;
                clrscr();
                cout<<input1<<what<<input2<<"="<<output<<endl;
			delay(4000);
                break;

                [color=blue]case's':
                case'S':[/color]
                output=sqrt(input1);
                clrscr();
		cout<<"the square root of "<<input1<<" is "<<output<<endl;
			delay(4000);
                break;

                default:
		cout<<"bye"<<endl;
			delay(2000);
                exit(0);
        }
        }
	}


دستور exit هم همان طور كه آقا سعيد قبلا ذكر كردند در stdlib است. من تابحال باهاش كار نكردم و سورس را در اين مورد دست نخورده گذاشتم.
.
همچنين برنامه بالا براي تمرين ساختار switch مناسبه. به قسمتي كه با رنگ آبي نشان داده شده نگاه كنيد. با دو case مختلف يعني اس كوچك و اس بزرگ يك سري دستورات اجرا مي شوند. اين ابتكارات و تجربيات آسان به دست نيامده. و كار با سورس ديگران باعث انتقال اين تجربيات است.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
من كمي راجع به اسمبلي توضيح مي دهم. چون ممكنه بعضي دوستان كمي بيگانه باشند باهاش. البته نمي خواهم از عنوان تاپيك كه سي است منحرف بشوم ولي چون سي يك زبان مياني است ، پس به ماشين نزديك است و خواه ناخواه بايست كمي از اسمبلي سردربياريم.
مهم ترين قضيه در اسمبلي ، رجيسترها هستند. هر دستور اسمبلي ، درونش اسمي از يك رجيستر وجود دارد.
رجيسترها ، حافظه هايي درون خود cpu هستند. پس درون Ram نيستند و علاوه بر حافظه Ram هستند. البته تعدادشان كمه ولي اهميتشان كم نيست.
يكسري به نامهاي ax و bx و cx و dx هستند كه همگي دو بايتي هستند. و همگي قابل تقسيم به دو قسمت يك بايتي .
مثلا ax را به دو قسمت بايت بالا ah و بايت پايين al تقسيم مي كنيم. هر كدام از اين 4 تا رجيستر ، وظايف خاصي دارند ولي ميشه بعنوان محل هاي همه منظوره هم از آنها استفاده كرد. مثلا cx حرف اولش از counter به معني شمارشگر گرفته شده ولي مي توانيم به عنوان يك فضا ازش استفاده هاي ديگري هم بكنيم.

يكسري رجيستر ديگر داريم به نامهاي ds و cs و es و ss . حرف دوم اينها يعني s از كلمه segment گرفته شده. D از ديتا ، s از استاك يا پشته ، e از كلمه اكسترا يعني اضافه و c از كلمه code . يعني هر كدام از اين 4 رجيستر نشان مي دهند كه قطعه مورد نظر كجاست. مثلا قطعه پشته ، قطعه داده و قطعه كد.
اين 4 رجيستر را به نيمه نميشه تقسيم كرد و يك تكه هستند ، برخلاف 4 رجيستر اول.

چهار تاي بعدي si و di و sp و bp هستند. دو تاشان براي اينه كه بفهميم كدام كد در كجاي ram نوبت اجرايش است و sp يعني استاك پوينتر ، و نشان مي دهد كه پشته چقدر پر شده. بعدا كه پشته را بگيم ، شايد نياز باشه كه اينها را ياد بگيريم.

پس كلا 12 رجيستر شد. و يكسري هم فلاگ داريم كه همه يك بيتي هستند. (بيت نه بايت) كلشان در يكي دو بايت جا مي شوند. فعلا فكر نمي كنم در سي با فلاگها سروكار داشته باشيم. براي اينكه بدانيد چكار مي كنند ، فقط يك مثال مي زنم. فرض كنيد دو عدد را جمع كنيم و نتيجه جمع از محل حافظه اش بزند بيرون. در اين موقع يكي يا چند تا از فلاگها تغيير مي كند و مي توانيم يك فكري براي قضيه بكنيم.

البته در cpu يكسري حافظه ديگر هم هست كه معمولا اسمي از آنها در كتابها برده نمي شود و ما هم باهاشون كاري نداريم.
و يك نوع متغير هم مي توانيم در سي تعريف كنيم كه از نوع رجيستر باشد. اين نوع متغيرها در حافظه هاي cpu لانه مي كنند نه در Ram . و چون اين حافظه هاي cpu كم هستند نميشه زياد از اين نوع متغيرها تعريف كرد. و كامپايلر اگه ببينه جا نيست اتوماتيك مي اندازد بيرون آن را.فايده اين نوع متغير هم سرعت بالاي دسترسي و كار باهاشه. به نظرم در سطحي كه ما داريم كار مي كنيم ، زوده كه بخواهيم طرف ساختن چنين متغيرهايي برويم. كلا سطح پايين يعني سرعت بيشتر و دخالت بيشتر. و حافظه هاي درون cpu هم يعني ((خط مقدم)).

يكي از چيزايي كه زياد در اسمبلي استفاده ميشه ، وقفه ها هستند. كه بر دو نوعند. Dos و bios . همان طور كه از اسمشان برمياد يكسري جزو dos هستند و يكسري جزو bios . وقفه ها مثل توابع آماده اي هستند كه در ram پشت سر هم چيده شده اند. همان موقع كه كامپيوتر داره بالا مياد ، اينها load مي شوند به اول ram . من در برنامه هاي قبلي يكي دو بار از وقفه ها استفاده كردم. ولي نياز به يادگيري آنها نيست.
فقط نامه بالا را براي اين نوشتم كه اگر كسي با اين مفاهيم كمي غريبه است ، آشناتر بشه.
.
وقفه ها را در اسمبلي با كلمه int صدا مي كنند. كه از اول كلمه اينتراپت به معني وقفه گرفتند. من از وقفه 21 استفاده كردم. و قبلش ah را 2 گرفتم. اين بخاطر اينه كه هر وقفه كارهاي زيادي انجام مي دهد و با تغيير ah يا رجيستر ديگر ، كار متفاوتي انجام مي دهد. در اينجا ah مثل كليد انتخاب فعاليت وقفه عمل مي كند. البته در اسمبلي ميشه از هيچ وقفه اي استفاده نكرد. و اسمبلي مساوي وقفه نيست. ولي كار رايجي است استفاده از وقفه ها.
فعلا ما با وقفه ها سعي مي كنيم كار نكنيم. چون ما كه اسمبلي كار نمي كنيم. ((سي)) خودش كلي ((تابع)) براي هر كار داره. ولي ((سي)) براحتي مي تواند وقفه ها را هم مثل زبان اسمبلي استفاده كند.


(( توابع سي: ))
من سعي مي كنم در كنار آموزش (( مفاهيم سي )) ، هر بار تعدادي از(( توابع سي)) را هم معرفي كنم. ولي فعلا اين جوري شده كه هر وقت كم ميارم مي روم سراغ گفتن توابع سي.
آخه مفاهيم كمي سخت تره از گفتن و استفاده از تابع. بقولي توابع سي خيلي حاضر آماده است و دم دست است.
.
 

saeedsmk

مدیر بازنشسته
تاریخ عضویت
6 سپتامبر 2003
نوشته‌ها
1,518
لایک‌ها
4
به نقل از saalek :
...
يكي از چيزايي كه زياد در اسمبلي استفاده ميشه ، وقفه ها هستند. كه بر دو نوعند. Dos و bios .
...
.
سلام
مرسي از زحمتي كه ميكشي
فقط خواستم يه توضيح كوتاهي بدم :
عزيز بهتر بگيم كه ما يه سري توابع اوليه داريم كه تمامي كارها توسط اونها انجام ميشه كه بهشون وقفه ميگيم. يعني تمامي برنامه ها چه توي ويندوز چه توي داس از اونها براي انجام كارشون استفاده ميكنن
اين وقفها به دو دسته bios كه توي بايوس تعريف شده و دسته ديگر كه توسط سيستم عامل معرفي ميشن كه شما به عنوان وقفه داس از انها نام برديد، دسته بندي ميشن .در واقعه وقفه هاي داس وقفه هاي هستند كه بر اساس وقفه هاي بايوس طراحي شده واجرا ميشن .
يه مثال ساده از وقفه هاي كه توسط سيستم عامل تعريف ميشه وقفه اي هست در داس( جز گره اينتراپ 21) كه يه استرينگ رو روي خروجي چاپ ميكنه يعني ادرس استرينگ رو ميگيره( كه بايد با كد صفر يا بايت 0 تموم بشه) وبعد اون رو نمايش ميده . اين وقفه خودش از وقفه بايوس كه چاپ يه كاركتر رو بر عهده داره ( اگه اشتباه نكنم جرء گروه وقفه و يا اينتراپت 10) براي نمايش اون استرينگ استفاده ميكنه .


بهر صورت مرسي از توضيحاتي كه ميدين
:lol:
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
سلام.
توضيحات شما خيلي قشنگ و گيرا بود.
براي من هم جا افتاد قضيه.
به خواننده ها هم توضيحات شما خيلي كمك مي كنه.
زحمت كشيديد.

حالا فهميدم كه وقفه هاي داس از وقفه هاي بيوس ساخته مي شوند و همه توابع از وقفه ها ساخته مي شوند.
باز هم ممنون.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها

151.gif


جدول بالا را چون خيلي كامل بود فرستادم.
يك نكته راجع به int : اگر مي خواهيد برنامه اتان همه جا درست عمل كند ، بايستي از كلمه int درست استفاده كنيد. همين طور كه در جدول بالا مي بينيد ، int وابسته به سيستم است. يعني مي تواند در هر سيستمي اندازه اش متفاوت باشه. قبلا يك دستور گفتيم كه اندازه متغير را در كامپيوتر اندازه مي گرفت. اگر مي خواهيد از كلمه int استفاده كنيد بجاي بقيه بايستي از تابع sizeof اول سيستم مقابل را تحليل كنيد.
البته اين مربوط به حرفه اي هاست. و من در برنامه هاي ساده اي كه مي نويسم هميشه int استفاده مي كنم.
فعلا اين نكته را گفتم تا بعدا حواستان به اين قضيه باشد. فعلا كه من خودم در كامپيوتر خودم همه برنامه هام قرار است اجرا بشه و اگر كامپيوتر دوستم ببرم ، كامپيوتر او هم دقيقا ساختارش مثل مال منه. بيش از اين حرف نمي زنم چون در حد من نيست و اين مقوله اي است كه به حرفه اي ها مربوطه.

در جدول بالا تعداد بايتها را مي بينيد. سعي كنيد با تابع sizeof همه را چك كنيد و ببينيد در كامپيوتر شما اين تابع همين جوابها را مي دهد يا نه. من خودم هنوز چك نكرده ام.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
کد:
#include <conio.h>		
#include <iostream.h>				
[color=red]#include <math.h>	[/color]			
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------

 int a=-20;

cout<<"abs(a)= "<<[color=red]abs(a)[/color]<<endl;


 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'q') goto menu;
}


تابع ابسوليوت ، مقدار مثبت يك عدد را برمي گرداند و در header ئي بنام math است. توابع رياضي يا متمتيكال در اين header هستند.

==================================

کد:
#include <conio.h>		
#include <iostream.h>				
#include <math.h>				
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
 int a=1;
[color=blue]//while (1)[/color]
while ([color=red] abs(a)> abs(a-1)[/color])	// an other way to use this loop
	{

		a++;
		cout<<a<<" ";
	}


cout<<endl<<"a= "<<abs(a-1)<<endl;


 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'q') goto menu;
}


برنامه بالا را من نوشتم تا ببينم تا كجا int مي تواند بزرگ باشد.
علت اين كه از اين تابع استفاده كردم اينه كه اعداد علامت دار وقتي از حدشان خارج مي شوند تبديل به منفي مي شوند. و مي خواستم وقتي اين اتفاق افتاد حلقه متوقف بشه.
جواب همان عدد 32767 بود.
اگر اين شرط را من نمي نوشتم ، برنامه تا ابد ادامه داشت. و سي error نمي دهد. آن خط كه با رنگ آبي نشان داده شده، حلقه دائمي تشكيل مي دهد.
قانون : اعداد صحيح به جز صفر ، true محسوب مي شوند و while نشانه چراغ سبز مي داند براي ادامه دادن حلقه. و اگر صفر بگذاريم بجاي اين يك ، حلقه يك بار هم نمي چرخه و كنترل به بعد حلقه مي رود. من همين الان امتحان كردم. A مساوي يك چاپ شد. يعني اصلا وارد حلقه نشده و رفته حلقه را رد كرده و همان مقدار اوليه a كه يك بوده را چاپ كرده. چون حتي اگر يك بار حلقه مي چرخيد ، مي شد 2 و نه يك .
من عمدا كلمه while را قبل حلقه گذاشتم تا اگر شرط برقرار نبود ، يك بار هم حلقه اجرا نشه.
ولي مي دانيد كه ميشه while را ته حلقه هم داشت. برنامه زير جوابش 2 است . يعني با وجود اينكه شرط برقرار نيست ، ولي يك بار حلقه پيموده شده.

کد:
#include <conio.h>		
#include <iostream.h>				
#include <math.h>				
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
 int a=1;
    do	{

		a++;
		
	}    while (0)   ;


cout<<endl<<"a= "<<a<<endl;
 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'q') goto menu;
}
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
کد:
#include <conio.h>
#include <iostream.h>
#include <math.h>
void main()
{
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
 long  a1=1000;
 // ------------------------------
 while(labs(a1)>labs(a1-100)  ){

a1=a1+100;
}    
cout<<"a1=long= "<<a1-100<<endl;

 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
c=getch();if(c != 'q') goto menu;
}

153.gif



در مورد اعداد long تابعي به نام labs براي قدر مطلق بكار مي رود.
.
======================================

براي اعداد double هم تابع fabs بكار مي رود ولي مقدور نشد كدش را اجرا كنم چون خيلي محاسبات طولاني شد. ادامه بحث اعداد بزرگتر هم خيلي پيچيده مي شود و براي سطح كار ما مناسب نيست.
.
 

K_2

کاربر تازه وارد
تاریخ عضویت
10 نوامبر 2005
نوشته‌ها
35
لایک‌ها
0
با سلام دوستان من تو کامپایل برنامه ها مشکل دارم وقتی کامپایل میکنم تو تابع ماین یه ارور میده البته تو تمام برنامه ها که کامپایل میکنم متن ارور اینه ممنون میشم کمکم کنید
4:declaration syntax error
و تابع ماین پارانتز هاش رو نشون میده
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
با سلام.
البته اگر برنامه را مي گذاشتيد اينجا سريعتر مي شد بفهميم اشكالش كجاست.
من الان رفتم جلوي main يك كاراكتر اضافه گذاشتم ، همين خطاي شما را داد. سينتكس يعني املايي.
البته ميشه به ليست خطا ها هم مراجعه كرد كه فكر نكنم نياز باشه. چون فكر كنم سريع رفع بشه .و من هم فعلا اين ليست دم دستم نيست.
.
--------------------
يك نكته هم اينكه وقتي در آخر يك خط ، سمي كالن را فراموش كنيم و نگذاريم، خطا به خط بعدي اشاره مي كنه. كلا بي ديدن برنامه شما فقط ميشه حدس زد. اگر هنوز رفع نشده چند خطي كه لازمه را اينجا بنويسيد.
.
 

K_2

کاربر تازه وارد
تاریخ عضویت
10 نوامبر 2005
نوشته‌ها
35
لایک‌ها
0
به نقل از K_2 :
با سلام دوستان من تو کامپایل برنامه ها مشکل دارم وقتی کامپایل میکنم تو تابع ماین یه ارور میده البته تو تمام برنامه ها که کامپایل میکنم متن ارور اینه ممنون میشم کمکم کنید
4:declaration syntax error
و تابع ماین پارانتز هاش رو نشون میده
salam in error ro gabl az ejraye barname mide yani too tabee INT MAIN() vabade in fagat alamate{hastesh na chize dige
 

programmer

کاربر تازه وارد
تاریخ عضویت
1 نوامبر 2005
نوشته‌ها
85
لایک‌ها
0
salam in error ro gabl az ejraye barname mide yani too tabee INT MAIN() vabade in fagat alamate{hastesh na chize dige
دوست گرامی مون به شما گفتن که :
البته اگر برنامه را مي گذاشتيد اينجا سريعتر مي شد بفهميم اشكالش كجاست.

اگه کد دو خط قبل و بعد از تابع main رو هم میزاشتی مسلمآ دوستان زودتر میتونستن کمکتون کنن .
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
به نقل از K_2 :

با سلام.
همان طور كه دوست گرامي هم گفتند ، بهتره برنامه را بگذاريد تا ما بتوانيم بفهميم كدها چيه و چرا خطا ميده.
من الان برنامه زير را اجرا كردم ، خطايي نداد.

کد:
int main()
{

return 0;
}

سي به حروف كوچك و بزرگ حساسه. همه حروف كوچكند در اين مثال.
وقتي برنامه من اجرا ميشه ، برنامه شما قسمتي داره كه با برنامه من فرق مي كنه.
بايد بررسي بشه.
.
به نقل از K_2 :

من امروز وقتي روي برنامه خود كار مي كردم ، به اشكالي برخوردم كه توضيح مي دهم. موقع اجرا ، برنامه خطا داد و در محلي كه در شكل زير با فلش نشان داده شده ، هم سمي كالن مي خواست و هم كروشه بسته.


163a1.gif


مسلما گذاشتن اين علامتها آنجا غلط است و اگر بگذاريم هم مشكلي حل نمي شود.
اما چرا اين خطا بروز كرده؟
بايد بدانيم كه پيامهاي كامپايلر توربو سي آنقدرها هم مورد اعتماد نيست.
اشكال در اينجا به علت اينه كه در تابع هايي كه فراخوانده ايم ، اشكالي وجود داره، نه در شكل برنامه اصلي.
احتمالا برنامه شما دوست گرامي هم چنين مشكلي داشته وگرنه نوشتن كلمه main را همه بلدند. و وقتي به پرانتزهاي main گير داده ، يك پيام اشتباه است و اشتباه اصلي جاي ديگر بوده.
من چون مي خواستم اشكال برنامه خود را رفع كنم ، آمدم به اين ترتيب زير عمل كردم. البته روش من ، ساخته خودمه و نمي گم درسته.
آمدم لينك به تابع را قطع كردم.


163a2.gif


و ديدم كه تابع main من هيچ مشكلي نداره . بعد آن را وصل كردم و لينك بعدي را قطع كردم.


163a3.gif


و همين كار را ادامه دادم تا معلوم بشه كه اشكال كار از كجاست. البته كار وقت گيريه.
يك راه ديگه اينه كه اگر يادمان است كه آخرين كاري كه انجام داديم چيه، برويم آن را اصلاح كنيم.
.
==================
يك ساعت بعد........بالاخره پيداش كردم.
در سه هدر آنطرف تر ، يك سوئيچ استفاده كرده بودم كه كروشه بسته را نگذاشته بودم.
راستش قبلا اين سوئيچ جزو برنامه اصلي بود ، آمدم يك هدر جدا كنم كروشه اش را نبرده بودم موقع كات كردن. بعدا هم ديدم يك كروشه همين جوري آنجا افتاده ها. ولي باز توجه نكرده بودم.
..
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
در فراخواني تابع ،
دو جور ميشه عمل كرد. با مقدار و با آدرس.
قبلا با مقدار را گفتيم. حالا در اين برنامه ، هر دو جورش را كنار هم ميگيم. تا مقايسه كنيد. از هر كدام كه لازم بود در جاي خود استفاده كنيد.
در نوع دوم ، f2 ، مي بينيم كه آن متغير فرستاده شده به تابع ، تغيير مي كند. قرباني خورده شده. ولي در f1 متغير از تابع جان سالم به در مي برد.

در نوع دوم با علامت & كه علامت آدرس است ، تابع به حافظه مي رود و از بيخ و ريشه ، متغير را تغيير مي دهد.

به همين خاطر به اين روش احضار تابع by refrence مي گويند. و قبلي ((با مقدار)) بود. يعني by value .

کد:
#include <conio.h>		
#include <iostream.h>				

[color=red]int f1(int num1);[/color]	// declare our  function s
[color=red]int f2(int &num1);[/color]

				
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
int a=3;
int y;
[color=green]y=f1(a);[/color]
cout<<"bade ehzare f1// a="<<a<<"  y="<<y<<endl;
[color=green]y=f2(a);[/color]
cout<<"bade ehzare f2// a="<<a<<"  y="<<y<<endl;
 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'q') goto menu;
}
[color=blue]
int f1(int num1)		
{
	num1 = num1*num1;
       return num1;
}[size=3]
int f2(int[/color] [color=red]&[/color][color=blue]num1)		
{
	num1 = num1*num1;
      return num1;
}[/color][/size]


در برنامه بالا ، قسمت قرمز رنگ تعريف توابع بالاي main است.
قسمت آبي خود توابع ، كه بيرون main اند.
قسمت سبز ، احضار توابع.
نتيجه اجرا:


164.gif

.
مي بينيد كه عدد a در نوع دوم بعد احضار تابع تغيير كرده.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
برنامه زير ، همان برنامه بالا است با اين تفاوت كه:
متغيرهاي a و y را عمومي تعريف كرده ايم تا تغييرات را دنبال كنيم.
ورودي و خروجي تابع را long گرفتيم تا اعداد بزرگتري جا بشه.

کد:
#include <conio.h>		
#include <iostream.h>				
[color=red]long f2(long &num1);
  long a;
  long y;[/color]
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
[color=green]y=f2(a);[/color]
cout<<"bade ehzare f2// a="<<a<<"  y="<<y<<endl;

 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'q') goto menu;
}
[size=3][color=blue]long f2(long [/color][color=red]&[/color][color=blue]num1)		
{
	 num1=num1+1;
	 num1 = num1*10;

      return num1;
}[/color][/size]



165.gif


تابع ما هر بار به عدد ، يك واحد اضافه مي كند و در 10 ضرب مي كند.
در شروع برنامه چون هيچ مقداري به متغير a نداديم و از نوع عمومي بود ، به طور اتوماتيك صفر خواهد بود. ولي يادتان باشد اين قضيه كه متغير مقدار اوليه مي گيره به طور اتوماتيك براي متغيرهاي عمومي است . در برنامه قبلي ديديم كه متغير a را بلافاصله بعد تعريف ، خودمان مقدار اوليه داديم.
.
 
بالا