# Native Code > برنامه نویسی با C > برنامه نویسی با زبان C و ++C >  دستگاه محتصات و زاویه یک بردار

## farhadamin

من نمی دونم چرا تایپ من پاک شده من برنامه ای را نوشتم که ایراد داره و از دوستان برای رفع مشکل کمک خواستم نه این که کسی برای من بنویسه... دو ما من که ایران زندگی نمی کنم که شما نوشتیتد دانش جویی... بعد هم این برنامه را من باید حدود یک ماه دیگه شروع به کار کنیم که سعی کردم با کمک دوستان توی این بحث آمادگی کامل را داشته باشیم ..

من سوالم را دوباره می پرسم....

وقتی قرار ورودی تابع در چهار حالت مختلف بررسی بشه یعنی اگر مثبت بود یک دستور روش انجام بشه و اگه منفی بود دستور دیگه ای و اگه هر دو منفی بودند و یا فقط یکی از آن ها بهتر است از کدوم تابع استفاده بشه ... یعنی با استفاه از کدام تابع این چهار حالت را نوشت... من از sweach استفاده کردم اما نتونستم بنویسم .... می خواستم از دوستان راهنمایی بخوام.....
ممنون از کمکتون.....

----------


## emad_67

به نظر من شما مقدار از مقداری که میخوای Arc tan بگیری قدرمطلق بگیر و بعد Arc tan اونو حساب کن یعنی به این صورت

float x=fabs((y2-y1)/(x2-x1));
cout<<atan(x);

بعدش که مقدار رو به دست اوردی با یک switch بررسی کن ببین ببین زاویه تو کدوم ناحیه بده و نسبت به اون ناحیه مقدار لازم رو اضافه یا کم کن. به این شکل:

ناحیه 1: خودش
ناحیه 2: +180
ناحیه 3: -180
ناحیه 4: خودش

----------


## farhadamin

> به نظر من شما مقدار از مقداری که میخوای Arc tan بگیری قدرمطلق بگیر و بعد Arc tan اونو حساب کن یعنی به این صورت
> 
> float x=fabs((y2-y1)/(x2-x1));
> cout<<atan(x);
> 
> بعدش که مقدار رو به دست اوردی با یک switch بررسی کن ببین ببین زاویه تو کدوم ناحیه بده و نسبت به اون ناحیه مقدار لازم رو اضافه یا کم کن. به این شکل:
> 
> ناحیه 1: خودش
> ناحیه 2: +180
> ...


سلام ممنون از راهنمایی شما، من کاری رو که گفتید انجام دادم. اما نمی دونم موقع کمپایلر کردن به قسمتcout<<atan(x);
ایراد می گیرد ... من از  dev C++‎ استفاده می کنم ویژوال سی پلاس پلاس هم دارم که نمی دونم چرا موقع ران همه برنامه ها ایراد 
remote executable patch and name
را میگرد و اسم فایل را از من میخواهد...

البته برنامه به زبان سی است نه پلاس پلاس... ممنون....

----------


## emad_67

برای مثال این برنامه رو اجرا کن ببین چی میشه

#include<iostream.h>
#include<math.h>
void  main()
{
 float x=fabs(1/1);
 cout<<atan(x);
}

اگه برنامه رو به c تبدیل میکنی که باید هدر های مورد نیاز اونو وارد کنی.

----------


## farhadamin

> برای مثال این برنامه رو اجرا کن ببین چی میشه
> 
> #include<iostream.h>
> #include<math.h>
> void  main()
> {
>  float x=fabs(1/1);
>  cout<<atan(x);
> }
> ...


ممنون از جوابت من فکر کنم اصلا cout در سی نباشه چون به این عبارت و #include<iostream.h ایراد میگیره... ممنون

----------


## emad_67

درسته cout در c وجود نداره ولی مگه شما نمیگی که از dev C++‎ یا vC++‎ استفاده میکنی؟
توی این محیط ها نباید مشکلی داشته باشه
اگه از c استفاده میکنی باید cout رو printf و iostream رو به stdio.h تبدیل کنی

----------


## farhadamin

> درسته cout در c وجود نداره ولی مگه شما نمیگی که از dev C++‎ یا vC++‎ استفاده میکنی؟
> توی این محیط ها نباید مشکلی داشته باشه
> اگه از c استفاده میکنی باید cout رو printf و iostream رو به stdio.h تبدیل کنی


سلام این برنامه ای ست که من نوشتم اما به switch ایراد می گیره.... ممنون می شم نگاه کنی
#include <stdio.h>
#include <math.h>
#define PI 3.14159265

 int main(void)
{
     
	FILE * fP1; int a,b,c,d; double W;
   
	fP1 = fopen("inddata.txt","r");
	fscanf(fP1,"%d%d%d%d",&a,&b,&c,&d);
	 W = (atan((d-b)/(c-a)));
	switch(W){
              case `(0<(c-a)&& 0<(d-b))´:
	    W = (atan((d-b)/(c-a)));
    	FILE * fP2;
     	fP2 = fopen("uddata.txt", "w");
fprintf(fP2,"retningsvector of punkt A og B er  %f",W);
break;

 case`(0>(c-a))`:
  	
    W = (atan((d-b)/(c-a)))+PI;
     FILE * fP2;
 
	fP2 = fopen("uddata.txt", "w");
fprintf(fP2,"retningsvector of punkt A og B er  %f",W);
 
 break;
 case`(0<(c-a)&& 0>(d-b))`: 
  	
    W = (atan((d-b)/(c-a)))+(2*PI);
     FILE * fP2;
 
	fP2 = fopen("uddata.txt", "w");
fprintf(fP2,"retningsvector of punkt A og B er  %f",W);
}
}



[IMG][/IMG]

----------


## emad_67

دوست عزیز من زیاد با systax سی آشنایی ندارم به همین خاطر هم درست متوجه نشدم چیکار کردی ولی به طور خلاصه میشه اینجوری نوشت

#include <iostream.h>
#include <math.h>
#define PI 3.14159265
void main()
{
    int a,b,c,d;
 cout<<"enter point 1:";
 cin>>a>>b;
 cout<<"enter point 2:";
 cin>>c>>d;
 int x=atan((d-b)/(c-a))*180/PI;
 if((c-a)<0 && (d-b)>0)
  x+=180;
 else if((c-a)<0 && (d-b)<0)
  x+=180;
 else if((c-a)>0 && (d-b)<0)
  x+=360;
 cout<<"teta = "<<x<<endl;
}


البته این طبق عکسی هست که گذاشتی یعنی اگه زاویه تو ناحیه 4 ام باشه مقدار اون رو در جهت مثلثاتی میده. یعنی مثلا ببین 45- و 315 در جه مقدار 315 درجه رو میده. در مورد ذخسره سازی در فایل هم خودت تغییراتی که لازمه رو بده چون من با سی زیاد آشنایی ندارم و بیشتر با syntax C++‎ کار کردم

----------


## farhadamin

> دوست عزیز من زیاد با systax سی آشنایی ندارم به همین خاطر هم درست متوجه نشدم چیکار کردی ولی به طور خلاصه میشه اینجوری نوشت
> 
> #include <iostream.h>
> #include <math.h>
> #define PI 3.14159265
> void main()
> {
>     int a,b,c,d;
>  cout<<"enter point 1:";
> ...



من برنامه شما را به صورت زیر در اوردم اما فقط اعداد وقتی مشابه اند جواب null را می دهد در غیر این صورت ارور می دهد.. از دوستان کسی برنامه اولیه که خودم نوشتم را فرصت در مورد نوشتن و اصلاح کردن داره... ممنون می شم.... از شما هم ممنون دوست عزیز

using namespace std;
int main()
{
   double Ax,Ay,Bx,By,x;
   cout<<"Insert Ax  ";
    cin>>Ax;
   cout<<"Insert Ay  ";
    cin>>Ay;
   cout<<"Insert Bx  ";
    cin>>Bx;
   cout<<"Insert By  ";
    cin>>By;
 x = atan((By-Ay)/(Bx-Ax))*180/PI;
  if  ((Bx-Ax)<0 && (Ay-By)>0)
  x+=180;
else 
      if((Bx-Ax)<0 && (By-Ay)<0)
  x+=180;

 else 
      if((Bx-Ax)>0 && (By-Ay)<0)
  x+=360;

 printf("atan = %s",x);
 getch();
 return 0;
}

----------


## emad_67

مشکل ارور به خاطر این خطه

printf("atan = %s",x);

چون من وقتی مینویسم 

cout<<x<<endl;

برنامه درست کار میکنه

----------


## SMRAH1

سلام
این هم برنامه یافتن زاویه بین دو نقطه AوB نسبت به مرکز مختصات(O) یعنی زاویه AOB البته به یاد داشته باشید که این زاویه ممکن است بیش از 180 درجه باشد (زاویه در جهت پادساعتگرد محاسبه میشود).
#include <stdio.h>
#include <conio.h>
#include <math.h>

#define PI 3.14159265
double GetAngleOf_Point_O_AxleX(double Xpoint,double Ypoint);

int main()
{
    float Ax,Ay,Bx,By;
    double DA,DB,D_Radian,D_Degree;
//Get Data
    printf("\n Enter Data of Point of A and B:\n\n");
    printf(" Ax : ");
    scanf("%f",&Ax);
    printf(" Ay : ");
    scanf("%f",&Ay);
    printf("\n Bx : ");
    scanf("%f",&Bx);
    printf(" By : ");
    scanf("%f",&By);

//Calculate Angle
    DA = GetAngleOf_Point_O_AxleX(Ax,Ay);
    DB = GetAngleOf_Point_O_AxleX(Bx,By);

    D_Degree = DB-DA;
    if(D_Degree < 0)
        D_Degree += 360;

    D_Radian = (D_Degree*PI/180);

//Print Resualt
    printf("\n\n A( %g , %g )  ,  B( %g , %g ) : \n Angle AOB  :\n",Ax,Ay,Bx,By);
    printf("  Radian : %g\n  Degree : %g\n\nEND.",D_Radian,D_Degree);

    getch();
    return 0;
 }

double GetAngleOf_Point_O_AxleX(double Xpoint,double Ypoint)
{
    double deg,x;

    if(Xpoint == 0)
    {
        deg = 90;
        if(Ypoint < 0)
            deg *= -1;
    }
    else
    {
        x = atan(Ypoint/Xpoint);

        if(Xpoint<0 && Ypoint>0)
            x += PI;
        else if(Xpoint<0 && Ypoint<0)
            x += PI;
        else if(Xpoint>0 && Ypoint<0)
            x += (2*PI);

        deg = (x*180/PI);
    }

    return deg;
}
در مورد این برنامه تنها نکته ای که برای درک آن به نظرم می رسد این است که تابع GetAngleOf_Point_O_AxleX وظیفه دارد مقدار زاویه بین نقطه مشخص شده توسط آرگومان خود را با قسمت مثبت محود X به مقدار درجه، برگرداند.

البته شما یک برنامه نیز نوشته بودید که قسمت Switch..case آن بسیار ایراد داشت.مثلا وجود کاراکتر کوتیشن (') اصلا لازم نیست به علاوه اینکه در قسمت switch باید یک عبارت یا متغیر قرار بگیرد و در قسمت case هم باید یک عبارت یا عدد قرار گیرد ولی شما یک شرط قرار داده اید!!!!در اینگونه موارد باید از if های تو در تو استفاده کنید (برنامه من هم دارای این وضعیت است).

موفق باشید.

----------


## farhadamin

> سلام
> این هم برنامه یافتن زاویه بین دو نقطه AوB نسبت به مرکز مختصات(O) یعنی زاویه AOB البته به یاد داشته باشید که این زاویه ممکن است بیش از 180 درجه باشد (زاویه در جهت پادساعتگرد محاسبه میشود).
> #include <stdio.h>
> #include <conio.h>
> #include <math.h>
> 
> #define PI 3.14159265
> double GetAngleOf_Point_O_AxleX(double Xpoint,double Ypoint);
> 
> ...



سلام خیلی ممنون از جوابت خیلی حرفه ای نوشته بودید.....البته از نظر من که خیلی تازه کارم.. :تشویق: 

چند تا سوال داشتم ، اگه جواب بدهید ممنون می شوم.

اول این که چرا این خط
double GetAngleOf_Point_O_AxleX(double Xpoint,double Ypoint);
قبل از main آمده یعنی اون جا تعریف می شه و یعنی جزو کتاب خانه های سی است...

این خط شما تایع main  را می بندید چطور می شه بعد از بستن تابع main برنامه نوشت.... مگه معنی اتمام برنامه را نمی هد.....

    getch();
    return 0;
 }

double GetAngleOf_Point_O_AxleX(double Xpoint,double Ypoint) 

هیج جا هم شما نگفتید که Xpoint= Bx-Ax و همین طور Ypoint= By-Ay اما چطور این کار انجام می شه یعنی این عبارت 
GetAngleOf_Point_O_AxleX(double Xpoint,double Ypoint)
این معنی را می دهد.....

این deg هم که شما ازش استفاده کردید، هیج جا در printf ازش استفاده نکردید پس چه چوری نمایش داده میشه..... 
شما D_Radian,D_Degree   را برای چاپ داده اید رابطه این ها را با deg نمی فهمم... یعنی نمی دونم چطور کار میکنه......

در آخر عبارت return deg; یعنی چی ... به تعداد deg تکرار میکنه..... برای چی....

می دونم خیلی سوال کردم.... ممنون از صبرتون......


برنامه کاملا درست به نظر می رسه  ...اما نمی دونم چرا  با ماشین حساب جور در نمی یاد.....ممنون از همه لطفتون...

----------


## SMRAH1

سلام

در مورد سئوالات شما به صورت کلی جواب میدهم.اول اینکه در زبان سی (و همینطور سی ++) تقریبا همه چیز تابع است.تابع یعنی یک زیر برنامه که به شکل زیر تعریف می شود.
retruned NAME (Parameters)
{
}که در آن returned نوع مقدار بازگشتی تابع را مشخص میکند .مثلا int یا ... و اگر چیزی بر نگرداند نیز با کلیدواژه void مشخص می شود.Name هم یک نام برای تابع (بمنظور فراخوانی تابع و استفاده از آن) است. parameters هم معرف پارامتر های ورودی تابع است که به مانند تعریف متغیر است با این تفاوت که هر پارامتر با یک کاما از پارامتر بعدی جدا می شود.اگر پارامتر ورودی هم وجود نداشته باشد نیز از همان کلید واژه void استفاده می شود.برای درک بهتر می توانید به تعریف تابع main یا GetAngleOf_Point_O_AxleX توجه کنید.اما در مورد مقدار بازگشتی تابع هم از  کلید واژه return استفاده می شود.مثلا در مثال بالا، من در تابع GetAngleOf_Point_O_AxleX عبارت
return deg;را دارم که به این مفهوم است که هر گاه برنامه به این خط برسد کار تابع GetAngleOf_Point_O_AxleX اتمام یافته است و باید مقدار درون متغیر deg را به عنوان حاصل تابع (یادتان باشد در تعریف تابع نوشته ایم که تابع مقدار double بر می گرداند)برگرداند.اما در تعریف تابع یک نکته مهم وجود دارد.چون در زبان سی همه چیز تابع است و از طرفی هیچ تابعی برای آن از قبل تعریف شده نیست،باید اول آن را به کامپایلر معرفی کنیم و بعد استفاده کنیم و در نهایت در جای مناسب تعریف کامل تابع را انجام دهیم.خط
double GetAngleOf_Point_O_AxleX(double Xpoint,double Ypoint);وظیفه معرفی تابع را بر عهده دارد تا برنامه بتوانم در تابع main به راحتی از آن استفاده کنم (اگر این خط را حذف کنید کامپایلر در موقع کامپایل در خطوطی که از این تابع استفاده شده یعنی در تابع main،اعلام خطایی مبنی بر عدم معرفی تابع مذکور می کند)،در نهایت بعد از تابع main هم تابع GetAngleOf_Point_O_AxleX تعریف میکنم.در موقع فراخوان تابع هم از نام آن استفاده می کنیم مثلا در خط
DA = GetAngleOf_Point_O_AxleX(Ax,Ay);برنامه مقادیر AxوAy رابه ترتیب به جای XpointوYpoint در تابع GetAngleOf_Point_O_AxleX قرار داده و سپس این تابع را اجرا و در نهایت مقدار بازگشتی آن را در DA قرار می دهد.
در این جا ذکر دو نکته مهم است.اول اینکه شاید سئوال کنید پس printf یا getch و atan و ... چیست که استفاده می کنیم.جواب این است که اینها هم تابع است و در واقع آن سرفایلهایی که اضافه می کنیم (در این مثلا سرفایلهای stdio.h و conio.h و math.h ) وظیفه معرفی همین توابع را بر عهده دارند.برای استفاده از هر تابع باید بدانید که در کدام سرفایل تعریف شده و به چه شکل تعریف شده است مثلا تابع atan که در سرفایل math است به شکل زیر تعریف شده است:
double antan(double);پس این تابع یک مقدار اعشاری می گیرد و یک مقدار اعشاری باز می گرداند.
نکته دوم و مهم، تابع main است.این تابع یک تابع رزرو شده در زبان سی است.به این مفهوم که زبان سی این تابع را به عنوان تابع حاوی برنامه اصلی می شناسد.یعنی با شروع برنامه به ابتدای آن می پرد و تا آخرین خط این تابع را اجرا می کند.دیگر توابع در صورت نیاز در این تابع فراخوانی می شود.با پایان این تابع (رسیدن به عبارت return) کار این تابع و در واقع کار برنامه تمام شده است.هر برنامه یک و فقط یک تابع main دارد.
تا اینجا مباحثی در مورد ساختار زبان سی مطرح کردم که در هر کتاب زبان سی و سی ++ یافت می شود.از اینجا به بعد می خواهم کمی در مورد الگوریتم این برنامه توضیح دهم(البته باید تذکر دهم که الگوریتمی که شما و دوستمان emad_67 برای محاسبه زاویه بردار های A و B به کار برده اید اشتباه بوده است).برای این منظور تصویر زیر را ببینید.در این تصویر ما می خواهیم زاویه بین دو بردار OA و OB را (یعنی زاویه AOB)یا به عبارتی t را محاسبه کنیم.توجه کنید که فرمولهایی که ما داریم که مثلا نقطه A را بگبرد و زاویه آن را برگرداند (مانند آنچا شما در پست های بالاتر تصویرش را گذاشته بودید)،زاویه بین بردار OA با *محور xهای مثبت* را بدست می دهد یعنی زاویه r در شکل.برای محاسبه t کافیست r و s را محاسبه کنیم و داریم :
t = s-rبه همین سادگی.در برنامه نیز تابع GetAngleOf_Point_O_AxleX وظیفه گرفتن مختصات یک نقطه به عنوان پارامتر و برگرداندن زاویه بردار حاصل از آن (بردار مبدا مختصات تا آن نقطه) را با *محور Xهای مثبت* را بر عهده دارد.این مفدار زاویه بر حسب درجه است.مثلا اگر مختصات نقطه B به تابع GetAngleOf_Point_O_AxleX بدهید،مقدار s را باز می گرداند.اصل محاسبات و یافتن مقدار t در همان تابع main انجام می شود و در نهاید مقدار زاویه را بر حسب درجه و رادیان چاپ می کند.
البته من نمی دانم که شما چگونه با ماشین حساب این زوایا را محاسبه می کنید و آیا از همان روشی که در الگوریتم نوشته بودید استفاده می کنید یا نه.در هر حال اگر هنوز هم مشکلی بود جواب های ماشین حساب را (به همراه مقادیر اصل سئوال) بگذارید تا من هم متوجه اشتباه احتمالی برنامه شوم.برای اینکه بتوانید داده ها را هم دستی چک کنید می توانید نقطه A را 1,1 و B را 2,2-  قرار دهید (آن ها رو کاغذ رسم کنید و زاویه را به راحتی ببینید که 90 درجه است)
در ضمن این نکته هم الان به ذهن من رسید که آن الگوریتمی که شما به کار برده اید (یعنی از Bx-Ax و By-Ay استفاده کرده اید) زاویه بین بردار AB را با محور Xهای مثبت بدست می آورد.
در هر حال اگر باز هم نکته نا گفته است بفرمایید.

موفق و سربلند باشید.

----------


## farhadamin

سلام من نوشته شما را همان موقع که نوشتید خواندم ... اما می خواستم برای حواب دادن مطمئن باشم....
دقیقا همون چیزی که شما در آخر نوشتید مورد نظر من بود..... البته خودم یک چیزی نوشتم که درست کار می کنه ... اما می گذارم که اگر شما اگر ایرادی می بینید به من بگید.... در ضمن من برای دو تا نقطه نوشتم... می خواستم ببینم اگر چند تا نقطه بود چی کار باید کرد ...ما برای هر بردار به دو تا نقطه احتیاج داریم..... می خواستم ببینم چه جوری باید از تکرار استفاده کنم که اگر چهار تا نقطه بود دو تای اول را یک بردار و دو تای دوم را یک بردار در نظر بگیره و زاوایه هر کدوم را با محور اکس نشان بدهد.... منظورم همون for  است اما نمی دونم دقیقا چه جوری ازش استفاده می کنند.....

ممنون می شم توضیح بدهید....

در ضمن از توضیحاتتون بی نهایت استفاده کردم... مثل یک کلاس درست بود.......خیلی ممنون.... نمی تونم بگم که همشو کاملا متوجه شدم... اما بالای هشتاد درصدشو فهمیدم....

برنامه ای را که نوشتم اینه

همون طور که نوشتید سعی کردم از if استفاده کنم...... البته من با فایل ورودی نوشتم.. که راحت ذخیره جواب. بازم ممنون از لطفتون
#include <stdio.h>				/* fprintf og fscanf ligger i dette c-bibliotek*/
#include <math.h>				/* diverse matematik begreber ligger i dette c-bibliotek*/

void main(void)
{

FILE *fp1; double Xa,Ya,Xb,Yb,retRadian,deltaX,deltaY,R,retGon; 

		const double Pi=3.14159265;

		fp1 = fopen("inddata.txt","r");

	fscanf(fp1,"%lf%lf%lf%lf",&Xa,&Ya,&Xb,&Yb);
	fclose(fp1);

	deltaX = Xb-Xa;
	deltaY = Yb-Ya;
	R = atan(deltaY/deltaX);


	if (deltaX>0 && deltaY>=0)
	{
		retRadian = R; 
	}
		else if (deltaY<0)
		{
			retRadian = R+400;
	}
		if (deltaX<0)
		{
			retRadian = R+200;
		}
		if (deltaX==0 && deltaY>0)
		{
			retRadian = 100;
		}
			else if (deltaY<0)
			{
				retRadian = 300;
			}
			else if (deltaY==0)
			{
				retRadian = 0;
			}
	retGon = retRadian*400/(2*Pi);
	
	FILE *fp2;
	fp2 = fopen("uddata.txt", "w");

	fprintf(fp2,"A(%5.2lf , %5.2lf)\t B(%5.2lf , %5.2lf)\t vinkel-radian(%5.2lf)\t vinkel-gon(%5.2lf)\t %5.2lf",Xa,Ya,Xb,Yb,retRadian,retGon);

fclose(fp2);
}

----------


## SMRAH1

سلام

برنامه شما را مطالعه کردم و نظرات خودم را (به علاوه توضیحاتی در مورد ایرادات آن) به همراه سورس تصحیح شده را با یک فایل توضیحی کامل (با فرمت pdf) برایتان گداشتم.لطفا دانلود کنید و حتما توضیحات را مطالعه کنید.

موفق و پیروز باشید.

----------


## farhadamin

> سلام
> 
> برنامه شما را مطالعه کردم و نظرات خودم را (به علاوه توضیحاتی در مورد ایرادات آن) به همراه سورس تصحیح شده را با یک فایل توضیحی کامل (با فرمت pdf) برایتان گداشتم.لطفا دانلود کنید و حتما توضیحات را مطالعه کنید.
> 
> موفق و پیروز باشید.



سلام ممنون از لطف زیادتون...
توضیحاتتون خیلی خوب بود و خیلی چیز ها یاد گرفتم.....

چند تا چیز به نظرم می رسه می خواستم با شما مطرح کنم.... 
اول در مورد سوال شما  آن چیزی که متوجه نشده بودید ... یک سیستم وجود داره که دستگاه مختصات را به جای 360 درجه به 400 درجه تقسیم می کنه که در اروپا زیاد استفاده میشه.....و اسمش gon است.

دوما این که فکر کنم بهتر است if یک جور دیگه در while  تعریف شود چون این جوری بازم برنامه محدوده و اگر در ورودی ما اکس و ایگرگ ها مثل هم باشند یا بخواهیم وقتی همه صفر هستند را محاسبه کند، برنامه نمی تواند این کار را انجام بدهد.....
نمی شه طوری تعریف کرد که اگر برنامه به کلمه  End در ورودی رسید تکرار را تمام کند.... یا مثلا به تعداد Xa این کار را انحام بدهد... یا اگر به خطی رسید که اطلاعاتی در آن نبود تکرار متوقف شود......
در ضمن دلتا اکس مساوی صفر سه حالت داره که به این صورته...
اگر دلتا ایگرگ مثبت باشه 90 یا در سیستم گان 100 است.
اگر دلتا ایگرگ منفی باشد 270 یا در گان 300 است
اگر صفر باشد صفر است....

در ضمن عبارت exit(0); نمی دونم چی کار می کنه....

یه ده باری نوشته شما را خواندم و هر بار یه چیزی یاد گرفتم ممنون.... کار هایی که گفتم را سعی کردم خودم انجام بدم نشد.... مخصوصا در مورد  if ممنون از لطفتون....

یه چیز دیگه چرا در این جا 
	if(Xa==Ya && Xa==Ya && Xa==Xb && Xa==Yb ) 
Xa==Ya را دوبار تکرار کرده اید....
ممنون

----------


## SMRAH1

سلام
نکته اول اینکه کد این
if(Xa==Ya && Xa==Ya && Xa==Xb && Xa==Yb )
اشتباه تایپی بوده است.آن را به
if(Xa==Ya && Xa==Xb && Xa==Yb )
تبدیل کنید (با اینکه از نظر الگوریتمی فرقی ندارد.در واقع اگر همه XهاوYها برابر باشند ،شرط برقرار است).
نکته بعد در مورد استفاده از شرط بالاست.اگر همه XهاوYها برابر باشند به این مفهوم است که دو نقطه AوB بر روی یکدیگر قرار دارند.و بردار از یک نقطه به خودش (برای یافتن زاویه این چنین برداری) بی معنی است با این حال می توان کد را تغییر دار به طوری که اولین داده ای که می خواند برابر تعداد بردار های ورودی یاشد.برنامه زیر تصحیح شده به این شکل است.باز هم تاکید می کنم،برنامه را می توان به شکل مناسب برای هر فرمت ورودی تغییر داد مهم تعیین فرمت ورودی داده هاست..در برنامه قبل وجود چهار صفر در پایان فایل معرف پایان بود،در اینجا تعداد بردارها را از اول فایل می خواند و ممکن است فرمت ورودی دیگری را شما پیشنهاد کنید و ...
نکته بعد در مورد تابع exit است.این تابع در سرفایل stdlib تعریف شده و یک ورودی از نوع int می گیرد.این تابع وظیفه دارد برنامه را خاتمه دهد.یادتان باشد که اگر فایل ورودی به هر دلیلی باز نشود،برنامه کاری برای انجام دادن ندارد و باید خاتمه یابد.ورودی تابع exit هم مقداری است که به سیستم عامل فرستاده می شود (توضیح در مورد این مقدار کمی پیچیده است فقط همین را بدانید که بعضی برنامه ها بر اساس کد بازگشتی بعد از اجرای برنامه های دیگر از وضعیت آنها مطلع می شوند).
نکته آخر هم اینکه در خطوط
if(deltaX == 0)
{
    retRadian = PI/2;
    if(deltaY < 0)
        retRadian *= -1;
}
تمام آن حالت هایی که برای دلتا اکس مساوی صفر فرموده اید قرار دارد با این تفاوت که شما زاویه را از 0 تا 360 درجه فرض می کنید و برنامه زاویه را از منفی پی تا مثبت پی (یا 180- تا 180) فرض میکند و محاسبه می کند.در برنامه پایین با اضافه کردن یک شرط در حلقه مقدار gon را به 0 تا 400 به جای 200- تا 200 برده ام.
باز هم اگر نکته ناگفته ای است بفرمایید.
موفق باشید.

----------


## SMRAH1

ببخشید فایل برنامه پست بالا این است.

----------


## farhadamin

> ببخشید فایل برنامه پست بالا این است.


سلام... خیلی ممنون..... اما بازم چند تا سوال دارم با اجازت می پرسم.


از اول برنامه شروع می کنم...
1.
fp2 = fopen("uddata.txt", "w");
	if(fp2 == NULL)
	{
		fclose(fp1);
		printf("\n Error in open file uddata.txt!!!\n");

دلیل وجودی این قسمت را نمی فهمم مگه نه این که فایل خروجی را خود برنامه ایجاد می کنه.... پس این کد برای چیه.

2. 
چه چوری می شه نوشت که اگر فایل ورودی جود داشت اما درونش اطلاعاتی نبود پیغام عدم وحود اطلاعات را بدهد....
3.
فکر کنم به قول شما توی این برنامه نوشتن قسمت تکرار با while بهتره ....
4.
نمی شود برنامه خودش تعداد نقطه ها را بشمارد به جای این که ما خودمون توی فایل ورودی تعداد را بهش بدهیم.....
5. 
چه جوری میشه برنامه وقتی به یک عبارت می رسد تکرار را تمام کند.. مثل عبارت end... خودم سعی کردم با تعریف تابع ()fgets  در درون if  این کار را انجام بدم نشد...خروجی همیشه خالی بود....
6.
در توضیح if ها آخرین را می توان توضیح داد و یا نداد... یعنی اگر توضیح نداد برنامه خودش تشخیص می دهد مثل این جا
	else if(deltaX>0 && deltaY<0)
				retRadian += (2*PI);

که شما حالت مثبت بودن دلتا ایگرگ را بیان نکرده اید ..اما برنامه در صورت نبود حالت های قبل این حالت را محاسبه می کند... در این جور مواقع بهتر است که حالت آخر را هم توضیح داد یا که نه....
7. 
می خواستم اول فایل ورودی یک اطلاعاتی را بنویسم.... در خروجی آن را هم ببینم.... مثل نقاط... به رادیان... به گان.... می خواستم ببینم چه جوری.... از تابع fgots استفاده کردم اما بازم چیزی نشون نمی داد.... منظورم اینه که ورودی به این صورت باشه.
point    radian     gon
14 
123.1 -10.03 45 96
-0.1 89 43 1
50 40 20 -10
2 3 4 6
0 1 5 1
1 1 2 2
1 1 -1 1
-1 1 1 1
1 -1 1 1
آن خط اول را بالای خروجی هم ببینیم.......
ممنون از لطف زیادت... و کمک هات...
راستی چه چوری میشه با هم بیشتر صحبت کنیم.....
ممنون
8.
در آخر این عبارت را هم نفهمیدم برای چی استفاده کردید...
	if(retGon < 0)	//Now -200<= retGon <0
		{
			retRadian += (2*PI);
			retGon += 400;

----------


## farhadamin

برنامه نهایی برای این که شاید به درد دوستان بخوره این جا می گذارم.....
ممنون از دوستانی که کمک  کردند.... مخصوصا SMARH1
در ضمن این برنامه با فایل ورودی نوشته شده که دوستان می توانند تغییر دهند
#include <stdio.h>				
#include <math.h>				
#include <conio.h>
#include <stdlib.h>
 void main(void)
{

	FILE *fp1,*fp2;
	double Xa,Ya,Xb,Yb;
	double deltaX,deltaY;
	double retRadian,retGon;
	const double PI=3.14159265;
	
    fp1 = fopen("inddata.txt","r");
	if(fp1 == NULL)
	{
		printf("\n Error in open file inddata.txt!!!\n");
		getch();
		exit(0);
	}

	fp2 = fopen("uddata.txt", "w");
	if(fp2 == NULL)
	{
		fclose(fp1);
		printf("\n Error in open file uddata.txt!!!\n");
		getch();
		exit(0);
	}
	
   	 while (fscanf(fp1,"%lf%lf%lf%lf",&Xa,&Ya,&Xb,&Yb) !=EOF)
	{
		
		deltaX = Xb-Xa;
		deltaY = Yb-Ya;
		
		if(deltaX == 0 && deltaY > 0)
		{
			retRadian = PI/2;
		  if(deltaY < 0)
		  {
				retRadian = -1;
		}
			 else if (deltaY==0)
			{
				retRadian = 0;
			}
        }
		else
		{
			retRadian = atan(deltaY/deltaX);

			if(deltaX<0)
				retRadian += PI;
		else if(deltaX>0 && deltaY<0)
				{
                  retRadian += (2*PI);
                   if (deltaY>=0)
                    retRadian = retRadian; 
		}	              	
    }
		retGon = retRadian*400/(2*PI);

		if(retGon < 0)	/*Now -200<= retGon <0*/
		{
			retRadian += (2*PI);
			retGon += 400;
		}
		  	fprintf(fp2,"\nA(%05.2lf , %05.2lf)\t B(%05.2lf , %05.2lf)\t vinkel-radian(%05.2lf)\t vinkel-gon(%05.2lf)\n"
			,Xa,Ya,Xb,Yb,retRadian,retGon);
			 
	    }
	 
	fclose(fp1);
	fclose(fp2);
	printf("End of program.");
	getch();
}

----------


## SMRAH1

سلام

از اینکه خیلی دیر جواب می دهم،امیدوارم من را ببخشید.در هر حال ادب حکم می کند حتما جواب سئوال ها را بنویسم.
جواب سئوالاتان را با همان شماره ای که مطرح کرده اید می نویسم:
1. ممکن است به هر دلیل برنامه نتواند فایل خروجی را ایجاد کند.یک دلیل آن می تواند عدم وجود مسیر مناسب و نام فایل مناسب باشد.دلیل دیگر وجود فایل همنام و باز بودن آن توسط برنامه دیگر است.دلایل دیگری هم می تواند وجود داشته باشد.
2. برنامه را می توان طوری تغییر داد که تعداد نقاط خوانده شده را در صفحه نمایش،بنویسد.در این صورت کاربر به راحتی متوجه این اشتباه خواهد شد.
3.با توجه به فرمت فایل ورودی،نوع تکرار بهتر،مشخص می شود.با این حال کمی هم به سلیقه برنامه نویس (در این مثال بیشتر) بستگی داد.
8.برنامه مقدار gon که تولید می کند عددی بین 200- تا 200 است ولی شما عددی بین 0 تا 400 می خواهید.پس باید اعداد بین 0 تا 200- را به 200 تا 400 ببریم.این شرط این وضعیت را تامین می کند.
6.ابتدا سئوال شما را دوباره مطرح می کنم تا اگر برداشت من اشتباه بوده است شما تصحیح بفرمائید.فرض کنیم سه شرط A و B و C تمام حالات موجود را در برگیرند (اصطلاحا به این وضعیت افراز فضای نمونه به سه قسمت A و B و C می گویند).در این صورت کدام نوع کد نویسی توصیه می شود:
الف.if (A)
{
}
else if (B)
{
}
else
{
}
ب.if (A)
{
}
else if (B)
{
}
else if (C)
{
}در جواب باید یاد آورشوم که قسمتی از برنامه نویسی،سلیقه ای است.در این جا هم هر کدام از روش های بالا مزایا و معایبی دارند.روش اول کد کمتری تولید کرده (چون عملا یک شرط کم می شود) و سرعت اجرای بالاتری دارد.ولی روش دوم اعتماد به برنامه را بالاتر می برد.چون اگر توجه کنید باید شروط A و B و C تمام فضای نومونه را بپوشاند (یا افراز کند).اما گاهی اوقات این وضعیت (علیرغم این موضوع که برنامه نویس فکر میکند رخ داده) برقرار نمی شود.اتفاقا حجم زیادی از باگ های برنامه ها ناشی از همین موضوع (عدم در نظر گرفتن تمام حالات ممکن) می باشد.در نتیجه من روش دوم را می پسندم (حتی در برخی اوقات حالت سخت گیرانه زیر را در نسخه بتا یا دیباگ به کار می برم)
if (A)
{
}
else if (B)
{
}
else if (C)
{
}
else
    printf("Error in if!!");در هر حال اختیار این موضوع به سلیقه برنامه نویس (و کمی هم مقدار حجم محاسبات ،حافظه و ...) بر می گردد.
البته یک نکته ضروری را هم مطرح کنم و آن این است که آن قسمت از کدی که شما قرار داده اید اصلا در این مقوله می گنجد (آن if دارای یک حالت دیگر برای deltaX>0 && deltaY>=0 می باشد که برنامه هیچ عکس العملی را نباید نشان می دهد).
4,5,7 : فرض کنید فرمت داده های ورودی به شکل زیر است:
- خط اول داده هایی که عینا در فایل خروجی چاپ شود.
- خط آخر کلمه end به معنی پایان داده ها است.
- بقیه خطوط چهار عدد قرار دارد که هر عدد به صورت اعشاری بوده و اعداد با کاراکتر space از یکدیگر جدا شده اند.
برنامه پایین طبق شرایط بالا نوشته شده است.توجه کنید در این حالت (با توجه به اینکه علاوه بر داده ها به صورت عدد از داده های متنی نیز بهره می بریم) باید داده ها ابتدا به صورت متنی از فایل خوانده شوند و در صورت نیاز اعداد اعشاری از آن استخراج شوند.
در این برنامه از تابع fgets برای خوانده یک خط از داده ها از یک فایل متنی استفاده شده.همچنین از تابع sscanf برای خواندن اعداد از درون یک رشته استفاده شده است.برای درک بهتر برنامه حتما به comment ها توجه کنید.

موفق و سربلند باشید.

----------

