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

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

saalek

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

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

char* str;
 cout<<"Enter string: ";
 cin>>str;
 for(int i=0;[color=red]str[i]!='\0'[/color];i++)
  if(str[i]>=97)
   str[i]=str[i]-32;
 cout<<"Uppercase : "<<str<<endl;


 // ----------- entehaye ghaaleb -----------
    cout<<"x=> exit  anykey=> repeat"<<endl;
	c=getch();if(c != 'x') goto menu;				
}


هدف برنامه: كاربر هر كلمه اي وارد كند(مثلا اسم خودش را ) ، برنامه اگر حروف كوچكي در تايپش باشد ، آنها را تبديل به حروف بزرگ مي كند.
.
در مورد کد های اسکی لازم نیست اون ها را حفظ کنید میتونید از شرط های زیر داخل حلقه استفاده کنید:
کد:
if((str[i]>='a')&&(str[i])<='z')  
  str[i]=str[i]-32;
if((str[i]>='A')&&(str[i])<='Z') 
  str[i]=str[i]+32;
 

لیلی

کاربر تازه وارد
تاریخ عضویت
7 نوامبر 2005
نوشته‌ها
15
لایک‌ها
0
سن
38
محل سکونت
Esf
یه برنامه جالب دیدم .البته خودم نتونستم درست حلش کنم.نمی دونم کجاش اشکال داره.
برنامه ای که نام و نام خانوادگی کاربر رو بگیره ویک پسورد براش بسازه به صورت زیر:
حروف پسورد یکی در میون از حروف نام و نام خانوادگی کاربر درست شده باشه مثلا اگه کاربر masih ahmadi کند پسورد بشه maahsmiahdi .
include<iostream.h>
#include<stdio.h>
int main (){
char name [5];
char fam[5];
char pass [10];
int i,j;
gets(name);
gets(fam);
for(i=0;(name && fam);i++){
pass=name;
pass[i+1]=fam;}
for(j=0;j<10;j++){
cout<<pass[j];}
return 0;
}
 

saalek

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

کد:
#include <conio.h>		
#include <iostream.h>				
#include<stdio.h>				
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
 
char name [20]={0};
char fam[20]={0};
char pass [100]={0};

cout<<"what is your name?"<<endl  ;
gets(name);
cout<<"what is yourfamily?"<<endl    ;
gets(fam);

for(int i=0;(name[i] && fam[i]);i++){
pass[2*i]=name[i];
pass[2*i+1]=fam[i];}

cout<<"name="<<name<<"     family="<<fam<<endl;
cout<<"password=   "<<pass<<endl;

 // ----------- entehaye ghaaleb -----------
    cout<<"x=> exit  anykey=> repeat"<<endl;
	c=getch();if(c != 'x') goto menu;
}



شرح برنامه:
ابتدا از كاربر با تابع gets(..) ، اسم و فاميل را مي گيريم. اين تابع در stdio است. و بايد اين header را بالاي برنامه include كنيم.

قبلا آرايه هايي از نوع char ساخته ايم و اسم و فاميل را 20 كاراكتر اجازه بزرگ شدن داده ايم. و پسورد را هم من فكر كنم بايد 40 تا باشه كه من همين طوري 100 گرفتم.

بعد حلقه اي تشكيل مي دهيم:

شرط حلقه: شرط حلقه اين است كه هيچ يك از آرايه هاي اسم و فاميل به كاراكتر صفر نرسيده باشد. && همان ((و)) منطقي است. يعني هر وقت يكي هم صفر بشود ، شرط برقرار نيست.
نكته: اعداد صحيح ، وقتي از لحاظ منطقي true محسوب مي شود كه غير صفر باشد. راجع به كاراكترها هم وقتي كدشان غير صفر باشد true محسوب مي شود.

چون مي خواهيم يكي درميان از كاراكترهاي اسم و فاميل استفاده كنيم ، من 2*I و 2*I+1 را نوشتم.

نكات جديد برنامه:
ما قبلا يك برنامه نوشتيم ( همان كه hello مي نويسه) كه مثل برنامه فعلي آرايه char داشت. در آنجا اجزاي آرايه را يكي يكي داديم. اينجا از دو string موجود كه كاربر مي دهد بوسيله يك حلقه به طور اتوماتيك اجزاي آرايه (آرايه pass ) مقدار دهي مي شود .

دستور جديد: gets كه مي تواند رشته را از كاربر بگيرد و در يك آرايه از نوع char قرار دهد.

من فقط برنامه را دوباره نويسي كردم و gets را نمي شناختم .
خيلي جالب بود.
.

95.gif

.
 

programmer

کاربر تازه وارد
تاریخ عضویت
1 نوامبر 2005
نوشته‌ها
85
لایک‌ها
0
تبدیل اعداد دسیمال(مبنای 10) به هگزادسیمال(مبنای 16)
کد:
/* decimal to hex */
#include<iostream.h>
#include<conio.h>

const int MAX_SIZE=20;

int main()
{
  long int x;
  int i,h[MAX_SIZE];
  clrscr();
  cout<<"Enter a Decimal integer : ";
  cin>>x;
  i=0;
  while (x != 0)
  {
    h[i] = x % 16;
    x = x / 16;
    i++;
  }//end of while
  cout<<"Number in Hex format :  0x";
  for(int j=i-1;j>=0;j--)
  {
   if(h[j]<=9)
    cout<<h[j];
   else
    switch (h[j])
    {
     case 10:cout<<'A';
	     break;
     case 11:cout<<'B';
	     break;
     case 12:cout<<'C';
	     break;
     case 13:cout<<'D';
	     break;
     case 14:cout<<'E';
	     break;
     case 15:cout<<'F';
	     break;
     default:cout<<"<Error>";
     }//end of Switch
  }//end of for
  cout<<"\nPress any key to exit...";
  getch();
  return 0;
}
 

programmer

کاربر تازه وارد
تاریخ عضویت
1 نوامبر 2005
نوشته‌ها
85
لایک‌ها
0
اینم یه روش کوتاهتر و خلاقانه تر بدون استفاده از دستور سوئیچ :
کد:
/* decimal to hex */
#include<iostream.h>
#include<conio.h>

const int MAX_SIZE=20;

int main()
{
  long int x;
  int i,h[MAX_SIZE];
  clrscr();
  cout<<"Enter a Decimal integer : ";
  cin>>x;
  i=0;
  while (x != 0)
  {
    h[i] = x % 16;
    x = x / 16;
    i++;
  }//end of while
  cout<<"Number in Hex format :  0x";
  for(int j=i-1;j>=0;j--)
  {
   if(h[j]<=9)
    cout<<h[j];
   else
    cout<<char(55+h[j]);
  }//end of for
  cout<<"\nPress any key to exit...";
  getch();
  return 0;
}
البته ادعا نمیکنم خلاقم !
گفتم شاید براتون جالب باشه از این راه هم حلش کردم.
 

saalek

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

هدف برنامه : تبديل از 10 به 16
فوايد برنامه: تمرين با دستور switch case و كار با مبناي 16 . استفاده از constant ثوابت.

شرح برنامه: برنامه كاملا واضح و نمايان است. اگر هنوز در switch case مشكل داريد، اين بهترين مثاله براي يادگيري اين دستور. اين دستور مثلا وقتي استفاده ميشه كه براي هر وردي خاص ، ما خروجي خاص داشته باشيم. مثل اينجا كه براي 10 و 11 و 12 و 13 و 14 و 15 ، ما خروجي هاي a و b و c و d و e و f را داريم.

نكته مهم اين برنامه هم كامنت گذاري است. با كامنت گذاري به موقع شما باعث مي شويد كه هم خودتان بعدا بفهميد برنامه چطور كار مي كند و هم فرد ديگر بهتر مي تواند بفهمد . يكي از دوستان عزيز مي گفت (( كامنت ها از خود كدها مهم ترند ، چون اگر كامنت نباشه ، هيچ كس (شامل خودتان) نمي توانيد از برنامه بعدها استفاده كند. ))
دوست خوبمان هم به موقع از كامنت استفاده كرده. كاري كه من تابحال رعايت نمي كردم. و اشتباه بود.


98.gif

.
 

saalek

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

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



int main()
{
  clrscr();
 
    for(int i=27;i<255;i++)
  {  
    cout<<char(i);
  }//end of for
  
  cout<<"\nPress any key to exit...";
  getch();
  return 0;
}


99.gif

.
 

saalek

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

برنامه زير از دو تابع استفاده مي كنه كه در header ئي به نام string.h قرار دارد و بالاي برنامه include شده.

تابع اول كه strlen است ، طول يك رشته را حساب مي كند. توجه كنيد كه متغير name كه اين تابع داره روي آن كار مي كند ، 50 خانه اي تعريف شده ولي وقتي كاربر اسم خودشو وارد اين متغير مي كنه ، سي يك صفر به آخر اسم اضافه مي كنه و تابع strlen هم قبل ((صفر)) را مي شمارد و با كل كه 50 است كاري ندارد.

تابع بعدي strcat است و كارش اينه كه يك رشته را به اضافه مي كند به رشته ديگر. و اين كار را بعد اولين صفري كه پيدا مي كند انجام مي دهد. در خطيكه رنگ قرمز زديم ، ما مي آئيم اولين خانه متغير fullname را صفر مي كنيم تا تابع strcat از اولين خانه شروع به پر كدن خانه هاي fullname بكند. بعد اول name را سرايز مي كنيم درونش ، بعد يك فاصله را بعد name مي گذاريم و بعد lastname را درون آن مي ريزيم.
بعد چاپ fullname مي بينيد كه حاوي name و lastname (با يك فاصله بين آنها) است.

کد:
#include <conio.h>		
#include <iostream.h>				
#include <string.h>
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
   char name[50];
   char lastname[50];
   char fullname[100]; // Big enough to hold both name and lastname
  
  cout<<"Please enter your name: ";
  cin.getline ( name, 50 );
 
  // Find the length of your name
  cout<<"Your name is "<< strlen ( name ) <<" letters long\n"<<endl;
  cout<<"Enter your last name: ";
  cin.getline ( lastname, 50 );
  [color=red]fullname[0] = '\0';[/color]    // strcat searches for '\0' to cat after
  strcat ( fullname, name );     // Copy name into full name
  strcat ( fullname, " " );      // We want to separate the names by a space
  strcat ( fullname, lastname ); // Copy lastname onto the end of fullname
  cout<<"Your full name is "<< fullname <<"\n";

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



100.gif

 

Electronics Art

کاربر فعال برق و الکترونیک
کاربر فعال
تاریخ عضویت
9 جولای 2005
نوشته‌ها
1,377
لایک‌ها
18
سالك جان ممنون از وقتي كه براي اين تايپيك ميذارين
خسته نباشي عزيز
ادامه بده كه مشتاق يادگيري هستيم :)
 

saalek

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

ممنون. من خيلي به برنامه نويسي علاقه مندم. مخصوصا سي كه خيلي حساب كتابش دقيقه و همچنين سريع و قوي است. كاش مي شد ويژوال سي ياد بگيرم.
.
==================
PHP:
  break (keyword)
 =================
 Passes control

 Syntax:  break ;

The break statement causes control to pass to the statement following the
innermost enclosing while, do, for, or switch statement.

من كنجكاو بودم كه break چه كاري انجام مي دهد. متن بالا را از help توربو سي آوردم. استنباط من از متن بالا اينه كه :

((بلوكهاي for و do و while و switch ،،، با اين دستور شكسته مي شوند و ...))

منظور من از بلوك ، مجموعه كدي است كه با ((كروشه)) {} محصور شده.
.

=====
تذكر اينكه استفاده از اين دستور در سوئيچ كيس ، رايج است. استفاده از آن در بلوكهاي ديگه را تمرين كنيد. من خودم هنوز تمرين نكردم تا نتيجه را بگم.
.
سئوال : سي چند كلمه كليدي دارد؟ اين دستور جزو كلمات كليدي است.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
ما تقريبا در همه برنامه هاي خود clrscr() و getch() را استفاده كرده ايم .
و همواره بخاطر استفاده از اين 2 تابع conio.h را بالاي برنامه include كرده ايم.

حال ، ***** با كامپايلر يا اديتور خود conio.h را باز كنيد.
در زير ، ليست محتويات آن را مي بينيد:



/* conio.h

Direct MSDOS console input/output.

Copyright (c) 1987, 1991 by Borland International
All Rights Reserved.
*/

#if !defined(__CONIO_H)
#define __CONIO_H

#if !defined(__DEFS_H)
#include <_defs.h>
#endif

#define _NOCURSOR 0
#define _SOLIDCURSOR 1
#define _NORMALCURSOR 2

struct text_info {
unsigned char winleft;
unsigned char wintop;
unsigned char winright;
unsigned char winbottom;
unsigned char attribute;
unsigned char normattr;
unsigned char currmode;
unsigned char screenheight;
unsigned char screenwidth;
unsigned char curx;
unsigned char cury;
};

enum text_modes { LASTMODE=-1, BW40=0, C40, BW80, C80, MONO=7, C4350=64 };

#if !defined(__COLORS)
#define __COLORS

enum COLORS {
BLACK, /* dark colors */
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY, /* light colors */
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
};
#endif

#define BLINK 128 /* blink bit */

extern int _Cdecl directvideo;
extern int _Cdecl _wscroll;

#ifdef __cplusplus
extern "C" {
#endif

void _Cdecl clreol( void );
void _Cdecl clrscr( void );
void _Cdecl gotoxy( int __x, int __y );
int _Cdecl wherex( void );
int _Cdecl wherey( void );
int _Cdecl getch( void );
int _Cdecl getche( void );
int _Cdecl kbhit( void );
int _Cdecl putch( int __c );

#ifndef _PORT_DEFS
int _Cdecl inp( unsigned __portid );
unsigned _Cdecl inpw( unsigned __portid );
int _Cdecl outp( unsigned __portid, int __value );
unsigned _Cdecl outpw( unsigned __portid, unsigned __value );
unsigned char _Cdecl inportb( int __portid );
void _Cdecl outportb( int __portid, unsigned char __value );
#endif /* !_PORT_DEFS */

int _Cdecl inport( int __portid );
void _Cdecl outport( int __portid, int __value );

void _Cdecl delline( void );
int _Cdecl gettext( int __left, int __top,
int __right, int __bottom,
void *__destin);
void _Cdecl gettextinfo (struct text_info *__r );
void _Cdecl highvideo( void );
void _Cdecl insline( void );
void _Cdecl lowvideo( void );
int _Cdecl movetext( int __left, int __top,
int __right, int __bottom,
int __destleft, int __desttop );
void _Cdecl normvideo( void );
int _Cdecl puttext( int __left, int __top,
int __right, int __bottom,
void *__source );
void _Cdecl textattr( int __newattr );
void _Cdecl textbackground( int __newcolor );
void _Cdecl textcolor( int __newcolor );
void _Cdecl textmode( int __newmode );
void _Cdecl window( int __left, int __top, int __right, int __bottom);

void _Cdecl _setcursortype( int __cur_t );
char * _Cdecl cgets( char *__str );
int _Cdecl cprintf( const char *__format, ... );
int _Cdecl cputs( const char *__str );
int _Cdecl cscanf( const char *__format, ... );
char * _Cdecl getpass( const char *__prompt );
int _Cdecl ungetch( int __ch );

#ifndef _PORT_DEFS
#define _PORT_DEFS

/* These are in-line functions. These prototypes just clean up
some syntax checks and code generation.
*/
unsigned char _Cdecl __inportb__( int __portid );
unsigned int _Cdecl __inportw__( int __portid );
void _Cdecl __outportb__( int __portid, unsigned char __value );
void _Cdecl __outportw__( int __portid, unsigned int __value );

#define inportb __inportb__
#define inportw __inportw__
#define outportb __outportb__
#define outportw __outportw__

#define inp( portid ) __inportb__( portid )
#define outp( portid,v ) (__outportb__( portid,v ), (int)_AL)
#define inpw( portid ) __inportw__( portid )
#define outpw( portid,v ) (__outportw__( portid,v ), (unsigned)_AX)

#endif /* _PORT_DEFS */

#ifdef __cplusplus
}
#endif

#endif /* __CONIO_H */



دو دستور مذكور را من با رنگ قرمز نشان داده ام.
چيزهاي مفيدي از ديدن سينتكس دستورات در header مربوطه مي آموزيم.
مثلا با ديدن void جلوي clrscr() مي فهميم كه خروجي نمي دهد و فقط صفحه را پاك مي كند و مقداري برنمي گرداند. ولي getch() مقداري صحيح برمي گرداند. داخل پرانتز براي هر دو كلمه void را داريم. اين يعني چه؟ يعني ورودي نمي گيرند .

****************
آزمايش بعدي:
حجم conio.h چقدر است؟
من به پوشه include رفتم و حجم آن را نگاه كردم. 4 مميز 22 كيلو.
مسلما چنين فايل كوچكي حاوي اين همه تابع نيست. پس توابع كجا هستند؟
حجم پوشه lib تقريبا برابر يك فلاپي است يعني يك و 55 است.
من مي خواهم بگويم كه header ها لينكي به كتابخانه ها هستند.
اگر اشتباه گفتم بگيد.
ولي چه لينك باشند يا نباشند ، نكته مهم اينه كه :
يك سري به header ها بزنيد ، شما مدام از توابع آنها استفاده نمي كنيد ، يك نگاه به ليست آنها مي تواند مفيد باشد.
.
بعد اين كه دستوري را انتخاب كرديد ، help توربو سي مي تواند راهنماي خوبي براي نوشتن يك برنامه باشد. چون نمونه برنامه هم گاهي دارد.
.
يك سئوال از حرفه اي تر ها: كتابخانه ها را با چه زباني نوشته اند؟
.

104.gif

 

programmer

کاربر تازه وارد
تاریخ عضویت
1 نوامبر 2005
نوشته‌ها
85
لایک‌ها
0
من كنجكاو بودم كه break چه كاري انجام مي دهد.
استنباط من از متن بالا اينه كه ((بلوكهاي for و do و while و switch ،،، با اين دستور شكسته مي شوند و ...))
درسته برای خروج از حلقه ها و دستور Switch بکار برده میشه و یک کلمه کلیدیه.
این برنامه کاربرد Break رو مشخص میکنه :
کد:
#include<iostream.h>
#include<conio.h>
int main()
{
for(int i=0;;i++)
{
  cout<<i;
  if(i==10)
    break;
}
cout<<"Press any key to exit...";
getch();
return 0;
}
كتابخانه ها را با چه زباني نوشته اند؟
با خود C و ++C مینویسن.در سطح پایین تر با اسمبلی و زبان ماشین.
خودتون هم میتونید یه هدر فایل بنویسد و برای خودتون کتابخانه شخصی بسازید.
 

saalek

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

با تشكر فراوان از مسئولين و مديران محترم

حالا كه راجع به conio.h صحبت شد ، يك نگاهي به dos.h و bios.h مي كنيم.
يكي از آنها struct هايي براي كار اسمبلي در سي است.
من امروز از سايت tebyan سورسهاي خوبي راجع به اسمبلي و سي دانلود كردم.
نكته جالب اين كه اين سايت كارت اينترنت مجاني به بازديد كنندگانش هديه مي كند. البته فقط باهاش مي توانيد داخل اين سايت بچرخيد. مسنجر هم باز نميشه. شماره تلفن 9718733 و يوزر و پسورد هر دو ، ميشه tebyannet . اسم سايت هم www.tebyan.net است.
قسمت سي اين سورسها هم در واقع اسمبلي نويسي در سي است كه رشته خيلي شيريني است. چون در همين محيط سي ، اسمبلي كار مي كنيم.
و اين خيلي خوبه . چون توابع سي خيلي آسانتر است كار باهاشون تا كار در محيط اسمبلي. البته اين نظر من است. ممكنه فردي با كامپايلر و زيربرنامه هاي مجهز اسمبلي ، محيط كارش خيلي راحت و دلچسب باشه.

ولي ممكنه شما اسمبلي كار نكرده باشيد. پس من كمي شرح مي دهم تا بعد بتوانيم برنامه هايي را با هم كار كنيم.
اگر به اسمبلي علاقه نداريد يا نياز نداريد اين پستها را رد كنيد. پستهايي كه برنامه هايش كلمه regs يا register داره را .


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

چيز ديگه اي هم كه بايستي بدانيد اينه كه اسمبلي تعداد زيادي وقفه dos و bios دارد. و اين وقفه ها كه مثل تابع عمل مي كنند ، ورودي اشان را ممكنه از رجيسترها بگيرند و خروجي اشان را هم به يكسري رجيستر بدهند. خيلي كار جالبي است.

بهتره رجيسترها را طبقه بندي اشان را بگوييم. 4 تا از ax تا dx . كه خيلي از توابع ( بهتره بگيم وقفه ها) براي انجام كاراشون به آنها نگاه مي كنند و خروجي اشان را هم خيلي مواقع در آنها منعكس مي كنند. Ax=ffff اين عبارت نشان مي دهد كه ax دو بايت است. Ff اول يك بايت و ff دوم هم يك بايت.
بنابراين اين 4 رجيستر را به شكل ديگري هم استفاده مي كنند . ax تقسيم ميشه به ah و al . كه ميشه بگي high و low . بايت با ارزش بالاتر در ah است.

همين مقدمه كافيه تا كارمون را شروع كنيم. البته رجيسترهاي ديگري هست كه وسط برنامه ها شرح مي دهيم.
حالا يك سري به header هاي مذبور بزنيد. Struct هايي مي بينيد كه با اسمهاي reg مشخص مي شوند. قبلا struct را گفتيم. حداقل يكي دو تا مثال حل مي كنيم . بعدش بقيه هم شبيه همونهاست.
.
 

saalek

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

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

main ()
{
    char letter = 'c';

    cout<<"i love  ";

    asm {
        MOV AH, 02h
        MOV DL, [letter]
        INT 21h
    }

    getch() ;
    return 0;
}


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

حالا چون ممكنه كسي اسمبلي بلد نباشه ، قسمت اسمبلي اش را توضيح مي دهم.
داريم int21h ، اول بگم كه h به معناي هگزايي است . يعني در مبناي 16 و بعد اينكه ما داريم از وقفه شماره 21 از Dos استفاده مي كنيم. اين وقفه كه ميشه بگيم تابع ، كارهاي زيادي انجام مي دهد كه خودش يك تاپيك ميشه اگر بخواهيم توضيح بدهيم. و كارهاي مختلف آن باتنظيم ah است. در اينجا چون ah مساوي 2 است ، كارش چاپ است. مثل همون cout در سي++ . حالا چي را چاپ مي كنه؟ عددي كه در dl باشه را كد اسكي مي گيره و كاراكتر مربوط به آن را چاپ مي كنه. مثل همون char . دقت كنيد كه letter در سي مقدار دهي شده و در اسمبلي مورد استفاده قرار مي گيره و اين خيلي كار زيبايي است.
نتيجه نهايي اجراي برنامه اينه كه سي مي نويسه I love و اسمبلي دنبالش مي نويسه c و ميشه كلا I love c .
.
{{{{{{{ccccccccccccc----------sssssssss}}}}}}}}}}}

حالا مي خواهيم هر دو كار را سي انجام بدهد. ولي با تغيير رجيسترها. البته چاپ كار ساده اي است ولي تغيير رجيسترها گاهي خيلي به درد مي خوره و اين برنامه فقط يك مثاله.


107.gif


در شكل بالا ، 3 قسمت را با رنگ زرد مشخص كرده ايم.
قسمت اول تعريف استراكتها و يونيون union است. دقت كنيد كه Dos.h بالاي برنامه به خاطر همين ها include شده. يك نگاهي به Dos.h بكنيد. اگر برويد نگاه كنيد ، مي بينيد كه اين struct ها و union براي تغيير همان رجيسترها است. مثل ax و ah .
يونيون را هنوز نگفته ايم. ولي يك جور استراكت است. بعدا با مثال مي گيم.
فعلا فقط اين را بگم كه يونيون همان استراكت است ولي تمامي اجزاي يونيون برخلاف استراكت ، از يك سري خانه حافظه استفاده مي كنند. فعلا مثالش دم دستم نيست، بعدا مي گذارم.
اما اين استراكتها و يونيون خلاصه كارشان تغيير رجيسترهاست. اين تكه را از Dos.h آوردم ، نگاه كنيد:

کد:
union   REGS    {
    struct  WORDREGS x;
    struct  BYTEREGS h;
};

داخل يونيون 2 تا استراكت تعريف شده. X و h يه جورايي نوبتي از يونيون استفاده مي كنند . باز اگر به اين header نگاه كنيد ، مي بينيد كه :

کد:
struct WORDREGS {
    unsigned int    ax, bx, cx, dx, si, di, cflag, flags;
};

struct BYTEREGS {
    unsigned char   al, ah, bl, bh, cl, ch, dl, dh;
};

يعني x براي تغيير ax و bx و cx و ... است. در اسمبلي به اينها word يا ((كلمه )) مي گويند. ((كلمه )) تشكيل شده از ((دو)) بايت.
و h براي بايتها است. البته مي دانيد كه مثلا ah و al باز خودشان روي هم ax را تشكيل مي دهند و اين تقسيم بندي براي راحتي كار است.

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

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

نتيجه اجراي برنامه : اول با cout مي نويسه I LOVE ، بعد با تغيير رجيسترها مي نويسه C .
عدد 43 كد حرف C است . البته بزرگش . كدها استاندارده و با فرق نداره. به عدد 02 هم كه به ah داديم ، بهش مي گويند شماره سرويس.
يعني ما داريم از سرويس 2 از وقفه داس به شماره 21 استفاده مي كنيم.
ليست وقفه هاي داس و بيوس را اگر خودتان ببينيد براحتي مي توانيد ازشان با اين ترتيب استفاده بكنيد.
من ديگه نمي خوام بيشتر توضيح بدهم ، چون موضوع تاپيك سي است ه اسمبلي. ولي اگر به تابع ها و كلاس و وراثت رسيديم و فريضه تاپيك انجام شد ، از همين سايت تبيان مثالهاي قشنگي دارم كه با هم كار مي كنيم. من راستش هنوز اطلاعاتم كامل نيست ولي ممكنه با وقفه ها و تغيير رجسترها بشه كاري كرد كه خود سي ازش عاجز باشه. اين را اساتيد بايد بحث كنند.
.

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

void main()
{
clrscr();
cout<<"I LOVE ";
// --------------------------------
  union REGS regs;
  struct BYTEREGS byteregs;
  struct SREGS sregs;

     regs.h.dl = 0x43;
     regs.h.ah = 0x02;

 intdosx( &regs, &regs, &sregs );
// --------------------------------

    getch() ;
 
}
.
 

saalek

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

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

به نظر من نيازي نيست كه خودتان را مجبور كنيد كه همه ساختارها را ياد بگيريد. چون به نظر من همه يك تعريف هستند كه خودتان هم مي توانيد ايجاد كنيد.
به نظر من آدم بعد مدتي برنامه نويسي ، مي فهمه كه يك ابزار اگه بود خيلي خوب بود و سي پيش بيني همه چيز را كرده. يعني براي راحتي برنامه نويس همه نوع ابزاري آماده كرده.
البته اينها نظرات يك مبتدي است بعدا حتما نظرم عوض ميشه. دوستان هم اگر اصلاح كنند حرفهاي من را ، مسلما همين امروز نظرم عوض ميشه.
*****************
يك نكته به نظرم اومد الان ، كه ميگم:
ببينيد در ويژوال بيسيك وقتي به متغيري بيش از گنجايش آن را مي دهيم، error ميده.
مثلا بالاي 32000 اگر به عدد صحيح كوچك بدهيد ، خطا مي دهد.
ولي سي خطا نمي گيره و نتايج را هم اعلام مي كنه ولي شما خودتان مي توانيد برويد ببينيد چطوري اين نتايج گاه عجيب حاصل شده. البته چيز عجيبي در كار نيست اگر به ماهيت بيت ها و بايت ها آگاه باشيم.
خلاصه كلام اين كه : سي دست ما را باز گذاشته پس كمي دقت بيشتر نيازه.
.
 

saalek

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

109.gif


به برنامه بالا نگاه كنيد. يكسري دستورات هستند كه با علامت پاند # شروع مي شوند. به اينها دستورات(( پيش پردازشگر)) مي گويند.
يعني قبل اينكه ((كامپايل)) صورت بگيرد ، اجرا مي شوند. در اينجا ما iii را define (تعريف) كرديم كه آن عبارت جلوش باشه. قبل از كامپايل هر جا iii باشه برداشته مي شود و آن عبارت جانشين ميشه.
كاربردش مي تواند اين باشه كه در تايپ صرفه جويي بشه.
.
کد:
#include <conio.h>		
#include <iostream.h>				

#define iii  int i=0;i<100;i++

void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------
 for (iii)
{
cout<<"i= "<<i<<endl;
}
 // ----------- entehaye ghaaleb -----------
    cout<<"----------------------new run"<<endl;
	c=getch();if(c != 'x') goto menu;				
}
 

لیلی

کاربر تازه وارد
تاریخ عضویت
7 نوامبر 2005
نوشته‌ها
15
لایک‌ها
0
سن
38
محل سکونت
Esf
سلام
ببخشید میدونم از مبحث اشاره گر ها گذشتیم ولی از اونجایی که خیلی از اشاره گر ها بدم میاد.(نمی دونم چرا)
خیلی نخوندمش حالا هم خیلی توش اشکال دارم.
یه برنامه میخوام که بزرگترین و کوچکترین عنصر یک ارایه رو مشخص کنه با استفاده از تابع زیر
void SL( double *array , double &largest , double &smallest, int size
ممنون میشم اگه برام توضیح هم بدید
 

saalek

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

مسائل رشته شما را هم دارم فكر مي كنم و دنبال توابعش هستم . اين مسائل را هم دنبال حلش مي گردم.
ولي من خيلي كندم.
خيلي ممنون كه پيام داديد .
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
با سلام.
من اين يكي دو روزه كمي دنبال asp و javascript و php و html و vbscript و اينها بودم.
و يكي هم اين كه دچار يك مشكل در جاي ديگر شدم. اين آموزش در 2 فروم همزمان ارائه مي شود و آنجا من دچار مشكل اديت كل پستها بودم.

ولي با همه اين ها ، خيلي سي تمرين كردم. و به نكات خوبي دست يافتم كه خدمت شما عرض مي كنم.
.
اول اينكه (( تابع )) را خيلي استفاده كردم و خيلي مسلط شدم. و بحث ديگر هم كلاسهاي متغير ها بود كه خيلي ور رفتم.

در شكل زير ، هم يك تابع استفاده شده و هم يك متغير عمومي استفاده شده.



114.gif



سعي كردم ساده ترين تابع ممكن را بنويسم تا يادگيري آن بلافاصله باشد.
نكته: من در نوشتن همين برنامه يك اشتباه كردم كه بلافاصله تصحيح كردم. و آن اين بود كه متغير x را درون main تعريف كردم و تابع f1 به آن دسترسي نداشت و برنامه خطا داد.
بنابراين x را بيرون main تعريف كردم. اين جوري ، هم داخل main ميشه استفاده كرد ، هم بيرون main ، يعني در توابعي كه بيرون main قرار دارند.
دوستان اگر توضيحات تكميل كننده دارند ، بنويسند.

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

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

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

void f1();

    int x;
void main()						
{		
clrscr();char c ;
 menu:
 // ----------- shoroe ghaaleb -------------

   x=5 ;
f1();


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

void f1()
{
int y;
y=x*x;
cout<<y<<endl;
}
 

saalek

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

حالا چه آموختم؟

تجربه اول: مسلما در برنامه هاي بزرگ نمي شه همه برنامه در يك فايل باشد. پس header سازي امري لازم است. چون وقتي يك فايل خيلي طولاني باشد ، خستگي زيادي با بالا و پايين رفتن در درازي برنامه ايجاد مي شود و گاهي اصلا خودمان هم ديگر سردرنمي آوريم چه كار كرده ايم و مجبوريم پروژه را رها كنيم.

تجربه دوم: هميشه اسم هاي مناسب براي متغيرها و توابع بگذاريد. من اول از f1 تا fn استفاده كردم ولي بعد مدتي ديگه نمي دانستم كدوم به كدومه. پس مجبور شدم با صرف وقت ، تمامي توابع و متغيرها را به اسامي با معنا تغيير دهم.

ولي بگم كه 1 ساعت شايد وقت گرفت تغيير نامها ولي بعدا به شدت باعث افزايش سرعت كار شد.

--
تجربه فني اول: وقتي يك متغير در header تعريف بشه ، در برنامه اصلي هم قابل دسترس است . ولي اگر در برنامه اصلي تعريف بشه ، در header غيرقابل دسترس است.

تجربه فني دوم: من براي راحتي خودم تمامي متغيرها را بيرون main تعريف كردم تا در كل فايل قابل دسترس باشه. ( كل فايل ميشه عمومي – كل پروژه را مي گويند جهاني يا گلوبال. البته اين 2 اصطلاح را من از ويژوال بيسيك با خود آورده ام ولي اسم مهم نيست. دوستان اگر مي توانند اسمهاي مناسب را بفرمايند.)

پس اگر بالاي main متغير تعريف بشه در كل همان فايل main در دسترس است. به اين مي گن عمومي.
ولي اگر در يك header ( كه توربوسي بهش ماژول هم ميگه) تعريف بشه جهاني يا گلوبال ميشه ( يعني در كل پروژه) .

من متغيرهايي كه main نياز داشت را در header تعريف كردم و main هم نگفت كه بدون تعريف داري در main از متغيري استفاده مي كني.

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

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