日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

QT快速入门、三点求圆心实现详解

發(fā)布時(shí)間:2024/9/27 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 QT快速入门、三点求圆心实现详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在編程中,會(huì)經(jīng)常用到數(shù)學(xué)計(jì)算,所以C++將常用的數(shù)學(xué)計(jì)算,例如求正余弦等,封裝成函數(shù)(正是我們?cè)?.2?數(shù)學(xué)計(jì)算中學(xué)習(xí)到的),我們只需要寫(xiě)入簡(jiǎn)單的語(yǔ)句就可以執(zhí)行所需要的功能,這正是函數(shù)的意義。在這一章的學(xué)習(xí),我們會(huì)建立起模塊化的思維,小的功能模塊我們會(huì)封裝成函數(shù),而一些大的功能模塊,則封裝成類。

剛開(kāi)始進(jìn)行函數(shù)的編寫(xiě),會(huì)感覺(jué)有些難度。其實(shí),只要稍稍多做一些函數(shù)編寫(xiě)的訓(xùn)練的時(shí)候,就可以很容易找到其中的規(guī)律。這一章會(huì)有大量的練習(xí)實(shí)踐,勤動(dòng)手是學(xué)好這一章內(nèi)容的關(guān)鍵。

7.1?函數(shù)

寫(xiě)一個(gè)求中點(diǎn)函數(shù),輸入兩個(gè)點(diǎn)坐標(biāo)——Point1,Point2,求出Point1與Point2的中點(diǎn)坐標(biāo)。參考表7-1中的程序。如何來(lái)完成這個(gè)編程要求,先看一下函數(shù)的編寫(xiě)規(guī)范。

#include<iostream> #include<cmath> using namespace std;struct Point{ double x; double y; };Point GetMidpoint(Point P1, Point P2) { Point Midpoint={0,0}; Midpoint.x = (P1.x + P2.x )/2; Midpoint.y = (P1.y + P2.y )/2; return Midpoint; }int main() { Point Point1,Point2; cout<<"請(qǐng)輸入兩個(gè)點(diǎn)的坐標(biāo)"<<endl; cin>>Point1.x>>Point1.y; cin>>Point2.x>>Point2.y;Point Point_MidP1P2; Point_MidP1P2=GetMidpoint(Point1,Point2); cout<<"中點(diǎn)坐標(biāo)為"<<Point_MidP1P2.x<<','<<Point_MidP1P2.y<<endl; system("pause"); return 0; }

表7-1?求中點(diǎn)函數(shù)程序

函數(shù)的代碼應(yīng)該放在主函數(shù)前面(如果想放在后面需要聲明,在7.2三點(diǎn)求圓心會(huì)講到如果將函數(shù)的實(shí)現(xiàn)放在主函數(shù)后面,應(yīng)該如何進(jìn)行聲明),具體如何實(shí)現(xiàn)該函數(shù)請(qǐng)看7.1.1小節(jié)。

第27行代碼對(duì)函數(shù)GetMidPoint進(jìn)行了調(diào)用,并將求得的結(jié)果賦值給了Point_MidP1P2結(jié)構(gòu)體變量,函數(shù)的使用可以回顧3.2數(shù)學(xué)計(jì)算這一節(jié)。區(qū)別只在于3.2數(shù)學(xué)計(jì)算中的函數(shù)是C++提供給我們的,而函數(shù)GetMidPoint是我們自己編寫(xiě)的。

測(cè)試程序,輸入兩個(gè)坐標(biāo)為(3,5),(5,10)的坐標(biāo)點(diǎn),程序自動(dòng)計(jì)算中點(diǎn)坐標(biāo)值并顯示,如圖7-1所示。

?

圖7-1?求中點(diǎn)函數(shù)測(cè)試結(jié)果示意圖

7.1.1?函數(shù)的編寫(xiě)規(guī)范

首先,先看一下函數(shù)的編寫(xiě)規(guī)范,函數(shù)定義的格式為

函數(shù)返回值的類型名?函數(shù)名(參數(shù)1類型 參數(shù)1名稱,?參數(shù)2類型 ?參數(shù)2名稱, ...)

{

函數(shù)體

}

要求中點(diǎn)坐標(biāo),首先回顧上一章將的內(nèi)容——結(jié)構(gòu)體,先定義名為Point的結(jié)構(gòu)體類型,并定義名為Point1,Point2,Point3的結(jié)構(gòu)體變量,結(jié)構(gòu)體類型為Point?:

struct Point{

double x;

double y;

};

然后開(kāi)始進(jìn)行求中點(diǎn)的函數(shù)的編寫(xiě),根據(jù)易懂的命名方式,將該功能的函數(shù)名起名為GetMidpoint,最終求得的結(jié)果為一個(gè)點(diǎn),所以原函數(shù)返回值的類型名為Point,共有兩個(gè)參數(shù),都為Point類型。

Point GetMidPoint(Point P1, Point P2)

第一個(gè)Point為函數(shù)返回值的類型名,即最終我們想要求得結(jié)果的類型,這里我們要求中點(diǎn)坐標(biāo),所以最終的結(jié)果就是一個(gè)Point類型;空格后緊接著是函數(shù)名GetMidPoint;小括號(hào)內(nèi)是求中點(diǎn)函數(shù)的參數(shù),共有兩個(gè)參數(shù),并且都為Point類型,而P1和P2則是參數(shù)1名稱,以及參數(shù)2名稱。

接下里開(kāi)始在大括號(hào)內(nèi)進(jìn)行函數(shù)體的編寫(xiě)。

Point Midpoint={0,0};

Midpoint.x = (P1.x + P2.x )/2;

Midpoint.y = (P1.y + P2.y )/2;

return Midpoint;

先定義了Point類型的名為Midpoint的結(jié)構(gòu)體變量,并賦初值為0,0;然后求得點(diǎn)Midpoint的x坐標(biāo)值以及y坐標(biāo)值;函數(shù)最終的結(jié)果需要使用關(guān)鍵字return進(jìn)行返回。

(當(dāng)然,如果定義函數(shù)返回值的類型名為void的話,即函數(shù)什么都不返回,最后的return語(yǔ)句不需要編寫(xiě);如果某個(gè)函數(shù)只執(zhí)行某項(xiàng)功能,需要返回任何值得時(shí)候,就可以這樣編寫(xiě))

7.1.2?形式參數(shù)與實(shí)在參數(shù)

形式參數(shù)是在定義函數(shù)時(shí)放在函數(shù)名稱之后的括號(hào)中的參數(shù)。在表7-1的程序中11行代碼中的P1,P2為形式參數(shù)。在函數(shù)的實(shí)現(xiàn)部分,該函數(shù)還沒(méi)有被調(diào)用,系統(tǒng)不對(duì)形式參數(shù)分配內(nèi)存;函數(shù)被調(diào)用時(shí)(程序的第27行為調(diào)用函數(shù)的代碼),系統(tǒng)對(duì)形式參數(shù)進(jìn)行內(nèi)存分配,在函數(shù)結(jié)束后,將這部分內(nèi)存釋放掉。形式參數(shù)屬于局部變量,其作用域限定在函數(shù)體內(nèi)。

實(shí)在參數(shù)是一個(gè)具有確定值的參數(shù)。在表7-1的程序中27行代碼中的Point1,Point2為實(shí)在參數(shù)。調(diào)用函數(shù)時(shí),將實(shí)在參數(shù)的值放入形式參數(shù)的內(nèi)存單元當(dāng)中。

需要注意的是,實(shí)在參數(shù)的個(gè)數(shù)以及類型必須和形式參數(shù)一致,并且前后排序也要一一對(duì)應(yīng)。

7.1.3?編程練習(xí):求兩點(diǎn)連線

編寫(xiě)一個(gè)函數(shù),輸入兩點(diǎn)坐標(biāo),能夠自動(dòng)計(jì)算出這兩點(diǎn)連線的斜率和截距。程序如表7-2所示。

#include<iostream> #include<cmath> using namespace std;struct Point{ double x; double y; };struct Line{ double k; double b; };Line GetLineOfTwoPoints(Point P1,Point P2) { Line StraightLine={0,0}; if(P1.x==P2.x) { P1.x=P2.x-0.0000001; } StraightLine.k = (P2.y - P1.y)/ (P2.x -P1.x); StraightLine.b = P1.y - P1.x * StraightLine.k ; return StraightLine; }int main() { Point Point1,Point2; cout<<"請(qǐng)輸入兩個(gè)點(diǎn)的坐標(biāo)"<<endl; cin>>Point1.x>>Point1.y; cin>>Point2.x>>Point2.y; Line Line1_P1P2; Line1_P1P2=GetLineOfTwoPoints(Point1,Point2); cout<<"兩點(diǎn)連線的斜截式方程為y="<<Line1_P1P2.k<<"x+"<<Line1_P1P2.b<<'.' <<endl; system("pause"); return 0; }

表7-2?求兩點(diǎn)連線函數(shù)程序

在初高中的時(shí)候我們通常使用斜截式來(lái)表示直線,也就是說(shuō)區(qū)分不同的直線只需要一個(gè)斜率k和一個(gè)截距b即可;第10至13行定義一個(gè)名為L(zhǎng)ine的結(jié)構(gòu)體類型,成員為double型的斜率k,以及double型的截距b。

15行至25行代碼實(shí)現(xiàn)了兩點(diǎn)求連線的函數(shù),函數(shù)返回值的類型名為L(zhǎng)ine,函數(shù)名為GetLineOfTwoPoints,參數(shù)有兩個(gè),都是Point型,兩個(gè)形式參數(shù)為P1,P2;函數(shù)體內(nèi)部先定義一個(gè)Line型的結(jié)構(gòu)體變量StraightLine,用來(lái)求得直線的斜率和截距。注意第18行至21行有一個(gè)if語(yǔ)句,該語(yǔ)句是為了在求斜率的時(shí)候,防止分母為0;最后將得到的直線結(jié)果返回。

在34行進(jìn)行了函數(shù)的調(diào)用,實(shí)在參數(shù)為Point1和Point2,所得連線結(jié)果賦值給結(jié)構(gòu)體變量Line1_P1P2。

測(cè)試程序,輸入兩點(diǎn)坐標(biāo)分別為(3,6)、(2,9),最終結(jié)果如圖7-2所示。

?

圖7-2?求兩點(diǎn)連線函數(shù)測(cè)試結(jié)果示意圖

7.1.4?編程練習(xí):求中垂線

編寫(xiě)一個(gè)函數(shù),輸入兩點(diǎn)坐標(biāo),能夠自動(dòng)計(jì)算出這兩點(diǎn)連線的中垂線的斜率和截距。根據(jù)兩點(diǎn)求中垂線,回憶初高中的數(shù)學(xué)知識(shí),需要先求兩點(diǎn)的中點(diǎn),然后求得兩點(diǎn)連線的斜率,垂線的斜率與連線的斜率相乘為-1,有了過(guò)中垂線的一個(gè)點(diǎn)以及斜率就可以求出中垂線了。程序如表7-3所示。

#include<iostream>#include<cmath>using namespace std;struct Point{double x;double y;};struct Line{double k;double b;};Point GetMidpoint(Point P1, Point P2){Point Midpoint={0,0};Midpoint.x = (P1.x + P2.x )/2;Midpoint.y = (P1.y + P2.y )/2;return Midpoint;}Line GetLineOfTwoPoints(Point P1,Point P2){Line StraightLine={0,0};if(P1.x==P2.x){P1.x=P2.x-0.0000001;}if(P1.y==P2.y){P1.y=P2.y-0.0000001;}StraightLine.k = (P2.y - P1.y)/ (P2.x -P1.x);StraightLine.b = P1.y - P1.x * StraightLine.k ;return StraightLine;}Line GetMidperpendicular(Point P,double k){Line StraightLine={0,0};StraightLine.k = -1/k;StraightLine.b = P.y - StraightLine.k * P.x ;return StraightLine;}int main(){Point Point1,Point2;cout<<"請(qǐng)輸入兩個(gè)點(diǎn)的坐標(biāo)"<<endl;cin>>Point1.x>>Point1.y;cin>>Point2.x>>Point2.y;Point Point_MidP1P2;Point_MidP1P2=GetMidpoint(Point1,Point2);Line Line1_P1P2;Line1_P1P2=GetLineOfTwoPoints(Point1,Point2);cout<<"兩點(diǎn)連線的斜截式方程為y="<<Line1_P1P2.k<<"x+" <<Line1_P1P2.b<<'.'<<endl;Line Line3_P1P2_Vertical;Line3_P1P2_Vertical = GetMidperpendicular(Point_MidP1P2,Line1_P1P2.k);cout<<"兩點(diǎn)的中垂線的斜截式方程為y="<<Line3_P1P2_Vertical.k<<"x+" <<Line3_P1P2_Vertical.b<<'.'<<endl;system("pause");return 0;}
  • 表7-3?求中垂線函數(shù)程序

    由于要求中垂線,所以需要先求中點(diǎn)坐標(biāo)以及兩點(diǎn)連線的斜率,所以將直接將前面的寫(xiě)好的求兩點(diǎn)中點(diǎn)函數(shù)以及求兩點(diǎn)連線函數(shù)拿來(lái)使用。

    需要注意的是求兩點(diǎn)連線的第31至34行防止兩點(diǎn)的y坐標(biāo)相同;如果兩點(diǎn)y坐標(biāo)相同,求得的斜率就為0,在求中垂線的時(shí)候,連線的斜率作為分母,這樣就會(huì)出錯(cuò)。

    40至46行實(shí)現(xiàn)了求中垂線函數(shù),函數(shù)返回值的類型名為L(zhǎng)ine,函數(shù)名為?GetMidperpendicular,參數(shù)有兩個(gè),一個(gè)是Point型,一個(gè)是double型,兩個(gè)形式參數(shù)的名稱為P,k;函數(shù)體內(nèi)部先定義一個(gè)Line型的結(jié)構(gòu)體變量StraightLine,用來(lái)求得直線的斜率和截距。注意兩個(gè)函數(shù)的結(jié)構(gòu)體變量StraightLine都是局部參數(shù),兩者是不同的。

    中垂線函數(shù)實(shí)現(xiàn)后,開(kāi)始在主函數(shù)中進(jìn)行中垂線求取。首先,求得兩點(diǎn)的中點(diǎn)Point_MidP1P2;然后求得兩點(diǎn)連線Line1_P1P2;最后,將中點(diǎn)Point_MidP1P2以及兩點(diǎn)連線Line1_P1P2的斜率Line1_P1P2.k作為實(shí)在參數(shù),調(diào)用求中垂線函數(shù)GetMidperpendicular,將結(jié)果賦值給Line1_P1P2。

    測(cè)試程序,輸入兩個(gè)點(diǎn)坐標(biāo)為(1,1)以及(0,2),最終結(jié)果如圖7-3所示。

    ?

    圖7-3?求中垂線函數(shù)測(cè)試結(jié)果示意圖

    7.2?編程練習(xí):三點(diǎn)求圓心

    兩點(diǎn)確定一條直線,那么幾個(gè)點(diǎn)確定一個(gè)圓呢?回憶下高中的數(shù)學(xué)知識(shí),三個(gè)點(diǎn)(不在同一條直線上)確定一個(gè)圓。這一節(jié)回顧初中的數(shù)學(xué)知識(shí),并結(jié)合學(xué)習(xí)的程序語(yǔ)言,對(duì)如何將給定的不在同一條直線的三點(diǎn)進(jìn)行圓心的求解形成一個(gè)初步的思路。

    7.2.1?三點(diǎn)求圓心思路

    如圖7-4所示,當(dāng)給定三個(gè)坐標(biāo)點(diǎn)(x1,y1),(x2,y2),(x3,y3),我們分別稱這三個(gè)坐標(biāo)點(diǎn)為Point1,Point2,Point3;

    我們連接坐標(biāo)點(diǎn)Point1,Point2以及Point2,Point3,這樣我們有了兩條線段,我們分別稱這兩條線段為L(zhǎng)ine1_P1P2,Line2_P2P3;

    然后我們分別對(duì)這兩條線段Line1_P1P2,Line2_P2P3求中垂線,獲得的中垂線我們稱為L(zhǎng)ine3_P1P2_Vertical,Line4_P2P3_Vertical;

    最后,我們能夠得到這兩條中垂線的交點(diǎn)——Point6_CenterOfCircle。

    需要注意的是,在求三點(diǎn)求圓心前,需要先確定輸入的三個(gè)點(diǎn)都不相同,并且不在一條直線上。判斷不在一條直線上,可以將Line1_P1P2,Line2_P2P3的斜率是否相同,如果相同則意味著三點(diǎn)在一條直線上。

    ?

    圖7-4?三點(diǎn)求圓心坐標(biāo)示意圖

    7.2.2?程序?qū)崿F(xiàn)

    接下來(lái)我們將以上思路通過(guò)程序?qū)崿F(xiàn)出來(lái),如表7-4所示。

    #include<iostream>#include<cmath>using namespace std;struct Point{double x;double y;};struct Line{double k;double b;};bool IsSameSlope(Line Line1,Line Line2);Line GetLineOfTwoPoints(Point P1,Point P2);bool IsSamePoint(Point P1,Point P2);Point GetMidpoint(Point P1, Point P2);Line GetMidperpendicular(Point P,double k);Point GetPointOfIntersection(Line Line1,Line Line2);double GetDistanceOfTwoPoint(Point P1,Point P2);int main(){Point Point1,Point2,Point3;cout<<"請(qǐng)輸入三個(gè)點(diǎn)的坐標(biāo)"<<endl;cin>>Point1.x>>Point1.y;cin>>Point2.x>>Point2.y;cin>>Point3.x>>Point3.y;bool x;x=IsSamePoint(Point1,Point2)||IsSamePoint(Point2,Point3)||IsSamePoint(Point1,Point3);if(x==1){cout<<"錯(cuò)誤,輸入的三個(gè)點(diǎn)有相同點(diǎn)!"<<endl;system("pause");return 0;}Line Line1_P1P2,Line2_P2P3;Line1_P1P2=GetLineOfTwoPoints(Point1,Point2);Line2_P2P3=GetLineOfTwoPoints(Point2,Point3);bool y;y=IsSameSlope(Line1_P1P2,Line2_P2P3);if(y==1){cout<<"錯(cuò)誤,輸入的三個(gè)點(diǎn)共線!"<<endl;system("pause");return 0;}else{cout<<"這三個(gè)點(diǎn)能夠求出圓心!"<<endl;}Point Point4_MidP1P2,Point5_MidP2P3;Point4_MidP1P2 = GetMidpoint(Point1,Point2);Point5_MidP2P3 = GetMidpoint(Point2,Point3);Line Line3_P1P2_Vertical,Line4_P2P3_Vertical;Line3_P1P2_Vertical = GetMidperpendicular(Point4_MidP1P2,Line1_P1P2.k);Line4_P2P3_Vertical = GetMidperpendicular(Point5_MidP2P3,Line2_P2P3.k);Point CenterOfCircle,StartPoint,EndPoint;CenterOfCircle=GetPointOfIntersection(Line3_P1P2_Vertical,Line4_P2P3_Vertical);double Radius;Radius = GetDistanceOfTwoPoint(CenterOfCircle,Point2);cout<<"圓心坐標(biāo)為"<<CenterOfCircle.x<<", "<<CenterOfCircle.y<<endl;cout<<"半徑為"<<Radius<<endl;system("pause");return 0;}bool IsSameSlope(Line Line1,Line Line2){if (Line1.k==Line2.k){return 1;}else{return 0;}}Line GetLineOfTwoPoints(Point P1,Point P2){Line StraightLine={0,0};if(P1.x==P2.x){P1.x=P2.x-0.0000001;}if(P1.y==P2.y){P1.y=P2.y-0.0000001;}StraightLine.k = (P2.y - P1.y)/ (P2.x -P1.x);StraightLine.b = P1.y - P1.x * StraightLine.k ;return StraightLine;}bool IsSamePoint(Point P1,Point P2){if(P1.x==P2.x&&P1.y==P2.y){return 1;}else{return 0;}}Point GetMidpoint(Point P1, Point P2){Point Midpoint={0,0};Midpoint.x = (P1.x + P2.x )/2;Midpoint.y = (P1.y + P2.y )/2;return Midpoint;}Line GetMidperpendicular(Point P,double k){Line StraightLine={0,0};StraightLine.k = -1/k;StraightLine.b = P.y - StraightLine.k * P.x ;return StraightLine;}Point GetPointOfIntersection(Line Line1,Line Line2){Point PointOfIntersection={0,0};PointOfIntersection.x = (Line2.b-Line1.b)/(Line1.k-Line2.k);PointOfIntersection.y = (Line2.k*Line1.b-Line1.k*Line2.b)/(Line2.k-Line1.k);return PointOfIntersection;}double GetDistanceOfTwoPoint(Point P1,Point P2){double DistanceOfTwoPoint=0;DistanceOfTwoPoint=sqrt((P1.x-P2.x)*(P1.x-P2.x)+(P1.y-P2.y)*(P1.y-P2.y));return DistanceOfTwoPoint;}
  • 表7-4?三點(diǎn)求圓心程序

    函數(shù)放在主程序后面,需要在主函數(shù)前面聲明。函數(shù)聲明很簡(jiǎn)單,直接將大括號(hào)前面的

    ?

    函數(shù)返回值的類型名?函數(shù)名(參數(shù)1類型 參數(shù)1名稱,?參數(shù)2類型 ?參數(shù)2名稱, ...)

    ?

    加上分號(hào)“;”即可。

    該程序共實(shí)現(xiàn)了7個(gè)函數(shù):

    bool IsSameSlope(Line Line1,Line Line2):判斷兩條直線的斜率是否相同,兩個(gè)參數(shù)為L(zhǎng)ine型的結(jié)構(gòu)體變量,如果相同返回1,不同返回0;

    Line GetLineOfTwoPoints(Point P1,Point P2):求兩點(diǎn)連線,兩個(gè)參數(shù)為Point型的結(jié)構(gòu)體變量,返回值為L(zhǎng)ine型結(jié)構(gòu)體變量;

    bool IsSamePoint(Point P1,Point P2):判斷兩點(diǎn)是否相同,兩個(gè)參數(shù)為Point型的結(jié)構(gòu)體變量,如果相同返回1,不同返回0;

    Point GetMidpoint(Point P1, Point P2):求兩點(diǎn)中點(diǎn),兩個(gè)參數(shù)為Point型的結(jié)構(gòu)體變量,返回值為Point型結(jié)構(gòu)體變量;

    Line GetMidperpendicular(Point P,double k):求中垂線,兩個(gè)參數(shù)為Point型的結(jié)構(gòu)體變量和double型變量,返回值為L(zhǎng)ine型結(jié)構(gòu)體變量;

    Point GetPointOfIntersection(Line Line1,Line Line2):求兩條直線交點(diǎn),兩個(gè)參數(shù)為L(zhǎng)ine型的結(jié)構(gòu)體變量,返回值為Point型結(jié)構(gòu)體變量;

    double GetDistanceOfTwoPoint(Point P1,Point P2):求兩點(diǎn)間距離(求半徑使用,圓心到三點(diǎn)任意一點(diǎn)的距離即半徑),兩個(gè)參數(shù)為Point型的結(jié)構(gòu)體變量,返回值為double型結(jié)構(gòu)體變量。

    函數(shù)實(shí)現(xiàn)后,在主函數(shù)中參考7.2.1三點(diǎn)求圓心思路對(duì)函數(shù)進(jìn)行調(diào)用來(lái)完成;測(cè)試程序,輸入三個(gè)點(diǎn)——(0,0)、(5,5)、(10,0),運(yùn)行結(jié)果如圖7-5所示。

    ?

    圖7-5?三點(diǎn)求圓心測(cè)試結(jié)果示意圖

    7.3?類

    通過(guò)函數(shù)的編寫(xiě),我們已經(jīng)初步的接觸到模塊化設(shè)計(jì)的思維;在三點(diǎn)求圓心的實(shí)現(xiàn)中,我們一步步定義小模塊(即函數(shù))幫助我們解決三點(diǎn)求圓心這個(gè)問(wèn)題。在程序的設(shè)計(jì)歷史過(guò)程中,需要解決的問(wèn)題越來(lái)越繁雜,這種編程思路會(huì)顯得很適應(yīng)編程需求。這個(gè)時(shí)候另一種以模塊化為切入點(diǎn)的編程思路應(yīng)用開(kāi)來(lái)——面對(duì)對(duì)象編程(OOP,Object Oriented Programming)。

    什么是面向?qū)ο缶幊?#xff1f;面向?qū)ο缶幊?/strong>與面向過(guò)程編程相對(duì),面向過(guò)程編程是如流水線一般,針對(duì)要解決的問(wèn)題,按照邏輯順序一步步進(jìn)行程序的設(shè)計(jì);而面向?qū)ο缶幊倘缜拔乃v,針對(duì)要解決的問(wèn)題,思考可能要用到方法,將一個(gè)個(gè)方法先進(jìn)行實(shí)現(xiàn),然后在進(jìn)行問(wèn)題的解決。

    C++提供了類這一功能,以勝任面對(duì)對(duì)象編程。

    7.3.1 VS2010環(huán)境下類的添加

    這里以三點(diǎn)求圓心類的實(shí)現(xiàn)為例,進(jìn)行類的講解。

    在VS中創(chuàng)建一個(gè)名為CenterOfCircle的項(xiàng)目(名字可以不一樣),然后開(kāi)始添加一個(gè)類,在“解決方案資源管理器”中點(diǎn)擊鼠標(biāo)右鍵,依次點(diǎn)擊“添加”,“類”,如圖7-6所示。

    ?

    圖7-6?添加類示意圖

    出現(xiàn)“添加類”窗口,默認(rèn)為“C++類”,無(wú)需改變,直接點(diǎn)擊右下角的“添加”鍵。如圖7-7所示。

    ?

    圖7-7?添加類確認(rèn)示意圖

    此時(shí)出現(xiàn)新的窗口——“一般C++類向?qū)А?#xff0c;此時(shí)在“類名”這一欄輸入CenterOfCircle,此時(shí),“.h文件”、“.cpp文件”兩欄自動(dòng)填滿相應(yīng)的信息,填寫(xiě)好后,界面如圖7-8所示。

    ?

    圖7-8?“一般C++類向?qū)А苯缑?/p>

    點(diǎn)擊“完成”,完成類文件的添加,然后在“解決方案資源管理”中的“頭文件”以及“源文件”中會(huì)分別出現(xiàn)兩個(gè)文件——“CenterOfCircle.h”、“CenterOfCircle.cpp”。如圖7-9所示。

    ?

    圖7-9?類添加后資源方案管理界面示意圖

    類添加完成后,就可以進(jìn)行類的編寫(xiě),即分別向“CenterOfCircle.h”、“CenterOfCircle.cpp”兩個(gè)文件中寫(xiě)入相應(yīng)的代碼,以完成三點(diǎn)求圓心類。

    簡(jiǎn)單的來(lái)說(shuō)以.h結(jié)尾的文件是類聲明部分——以數(shù)據(jù)成員的方式描述數(shù)據(jù)部分,以成員函數(shù)(被稱為方法)的方式描述公有接口;以.cpp結(jié)尾的文件是類方法定義部分——用來(lái)描述如何實(shí)現(xiàn)類成員函數(shù)。

    7.3.2?編程練習(xí):三點(diǎn)求圓心類

    我們通過(guò)上一節(jié)熟悉了在VS2010中類的添加,這一節(jié)我們將對(duì)三點(diǎn)求圓心功能進(jìn)行類的實(shí)現(xiàn)和使用。

    在數(shù)控機(jī)床等操作中,想要進(jìn)行圓弧插補(bǔ),需要輸入的點(diǎn)的個(gè)數(shù)為三個(gè),通過(guò)三個(gè)點(diǎn)進(jìn)行圓心坐標(biāo)以及圓弧走向的求取后,才能進(jìn)行圓弧插補(bǔ)。所以這一節(jié)的內(nèi)容是第8章逐點(diǎn)比較法圓弧插補(bǔ)的一個(gè)基礎(chǔ),請(qǐng)大家務(wù)必把基礎(chǔ)打好。

    首先,要判斷三點(diǎn)在不在一條直線上。在這一節(jié)當(dāng)中我們將通過(guò)計(jì)算機(jī)對(duì)給定的三個(gè)點(diǎn),求這三個(gè)點(diǎn)所在圓的圓心、半徑以及三個(gè)點(diǎn)行進(jìn)的方向——順時(shí)針還是逆時(shí)針。

    在進(jìn)行程序編寫(xiě)前需要首先了解一些有關(guān)類編寫(xiě)的相關(guān)知識(shí)。

    1.構(gòu)造函數(shù)與解析函數(shù)

    首先,再次對(duì)類這一概念進(jìn)行解釋。編寫(xiě)三點(diǎn)求圓心類,我們不關(guān)心要求取的三個(gè)點(diǎn)到底是(0,0)、(5,5)、(10,0),或者是(1,2)、(4,5)、(11,0)等等,也就是說(shuō)這個(gè)三點(diǎn)求圓心類是抽象的,不是具體只針對(duì)某三個(gè)具體的點(diǎn)能夠求得最終的結(jié)果;即這個(gè)三點(diǎn)求圓心類可以對(duì)任意三個(gè)點(diǎn)都有效,都能夠求得結(jié)果。

    那么,三點(diǎn)求圓心類是如何區(qū)分不同的點(diǎn)的呢?這就是構(gòu)造函數(shù)的作用,構(gòu)造函數(shù)用來(lái)創(chuàng)建對(duì)象,例如(0,0)、(5,5)、(10,0)三個(gè)點(diǎn),共有6個(gè)值,在求取這三個(gè)點(diǎn)的時(shí)候,只需要將這6個(gè)數(shù)字放入構(gòu)造函數(shù)的參數(shù)中即可,構(gòu)造出對(duì)應(yīng)這三個(gè)點(diǎn)的對(duì)象;有了這個(gè)對(duì)應(yīng)(0,0)、(5,5)、(10,0)三個(gè)點(diǎn)的對(duì)象后,就可以使用三點(diǎn)求圓心類下的成員函數(shù)進(jìn)行圓心、半徑等結(jié)果的求取了。

    總而言之,類是抽象的,在使用類的時(shí)候,放入到構(gòu)造函數(shù)中的參數(shù)不同來(lái)創(chuàng)建不同的對(duì)象,然后該對(duì)象調(diào)用類下的成員函數(shù)來(lái)得到不同的結(jié)果。

    構(gòu)造函數(shù)的名稱和類的名稱一致,但是要區(qū)分兩者的區(qū)別,構(gòu)造函數(shù)是類的成員函數(shù),雖然名稱一樣,但構(gòu)造函數(shù)出現(xiàn)在成員函數(shù)應(yīng)該出現(xiàn)的位置上,在程序中很容易分別。后面的程序說(shuō)明中會(huì)對(duì)此進(jìn)行更詳細(xì)的解釋。

    析構(gòu)函數(shù)通常不需要特別關(guān)注,析構(gòu)函數(shù)的作用是完成清理工作,在程序執(zhí)行到創(chuàng)建的對(duì)象作用域以外的時(shí)候,需要釋放內(nèi)存。這個(gè)過(guò)程系統(tǒng)自動(dòng)完成。析構(gòu)函數(shù)的名稱和類名相似,只在類的名稱前面加上了一個(gè)波浪符號(hào)——“~”。

    2.訪問(wèn)控制

    這里介紹下面程序中會(huì)出現(xiàn)的兩個(gè)關(guān)鍵字——public和private,這兩個(gè)關(guān)鍵字描述了對(duì)類成員的訪問(wèn)控制。

    關(guān)鍵字private標(biāo)識(shí)的成員(無(wú)論是數(shù)據(jù)還是成員函數(shù))不能夠通過(guò)外界直接訪問(wèn),只能夠通過(guò)關(guān)鍵字public標(biāo)識(shí)下的公有成員函數(shù)進(jìn)行訪問(wèn);這樣,共有成員函數(shù)成為程序和對(duì)象的私有成員之間的橋梁,提供了對(duì)象和程序之間的接口。

    為了數(shù)據(jù)隱藏,通常數(shù)據(jù)都放在關(guān)鍵字private下,類的對(duì)外接口的成員函數(shù)放在關(guān)鍵字public下面。(C++還提供了一個(gè)關(guān)鍵字——protected,可以自行補(bǔ)充學(xué)習(xí))

    ?

    接下來(lái),以三點(diǎn)求圓心類為例,看一下如何實(shí)現(xiàn)這個(gè)類。

    a.我們先對(duì)CenterOfCirlce.h文件進(jìn)行編寫(xiě)

    ?(程序說(shuō)明在后面)

    #pragma once#include<cmath>struct Point{double x;double y;};struct Line{double k; //斜率double b; //截距};struct Result{bool HasSolution; //是否有解Point StartPoint; //圓弧行進(jìn)起點(diǎn)坐標(biāo)Point EndPoint; //圓弧行進(jìn)終點(diǎn)坐標(biāo)Point CenterOfCircle; //三點(diǎn)確定的圓心坐標(biāo)bool Direction; //圓弧行進(jìn)方向(順時(shí)針還是逆時(shí)針)double Radius; //半徑長(zhǎng)度};class CenterOfCircle{private:Point Point1,Point2,Point3; //給定的三點(diǎn)Point Point4_MidP1P2,Point5_MidP2P3; //兩點(diǎn)的中點(diǎn)Line Line1_P1P2,Line2_P2P3; //兩點(diǎn)的連線Line Line3_P1P2_Vertical,Line4_P2P3_Vertical; //兩點(diǎn)連線的中垂線Point Point6_CenterOfCircle; //圓心坐標(biāo)bool IsSamePoint(Point,Point); //判斷點(diǎn)是否相同Point GetMidpoint(Point,Point); //獲取中點(diǎn)坐標(biāo)Line GetLineOfTwoPoints(Point,Point); //獲取兩點(diǎn)的連線bool IsSameSlope(Line,Line); //判斷斜率是否相同Line GetMidperpendicular(Point,double); //獲取中垂線Point GetPointOfIntersection(Line,Line); //獲取倆線交點(diǎn)double GetDistanceOfTwoPoint(Point,Point); //獲取兩點(diǎn)距離bool GetDirection(Point,Point,Point); //獲取圓弧走向public:CenterOfCircle(double,double,double,double,double,double); //構(gòu)造函數(shù)的6個(gè)參數(shù)分別三個(gè)點(diǎn)在x與y方向的坐標(biāo)~CenterOfCircle(void);Result GetInformationOfCircle(); //獲取最終給定三點(diǎn)的結(jié)果,有無(wú)解,起點(diǎn),終點(diǎn),圓心,走向以及半徑};
  • 第一行代碼#pragma once防止頭文件重復(fù)編譯。

    在頭文件開(kāi)頭,我們先包含一個(gè)頭文件cmath,因?yàn)楹竺嫖覀儠?huì)使用函數(shù)tan()以及求平方函數(shù)sqrt()進(jìn)行相關(guān)的數(shù)學(xué)計(jì)算。

    結(jié)構(gòu)體類型Point表示點(diǎn),成員為x和y;結(jié)構(gòu)體類型Line表示線,成員為斜率k和截距b。

    結(jié)構(gòu)體類型Result是我們最終求得的結(jié)果,其成員分別為圓弧的起點(diǎn)StartPoint,終點(diǎn)EndPoint,三點(diǎn)所確定的圓心坐標(biāo)CenterOfCircle,圓弧走向Direction(順時(shí)針或逆時(shí)針)以及圓的半徑Radius;

    還有一個(gè)bool型變量HasSolution,表示是否有解,因?yàn)橐紤]到三點(diǎn)是否有兩個(gè)相同點(diǎn)以及三點(diǎn)是否在同一條直線上的問(wèn)題,這兩種情況下的三個(gè)點(diǎn)是無(wú)法形成圓弧的。

    然后我們開(kāi)始對(duì)CenterOfCircle類的成員進(jìn)行聲明,class是關(guān)鍵字,表明要?jiǎng)?chuàng)建一個(gè)名為CenterOfCircle的類;其中,要求圓心的三個(gè)點(diǎn)分別為Point1,Point2,Point3

    求圓心需要先對(duì)三點(diǎn)的兩兩連線進(jìn)行中垂線的求取,在這里我們需要用到兩點(diǎn)的中點(diǎn),以及兩點(diǎn)連線,還有兩點(diǎn)連線線段的中垂線;

    所以,我們定義Point1與Point2的中點(diǎn)坐標(biāo)為Point4_MidP1P2,Point2與Point3的中點(diǎn)坐標(biāo)為Point5_MidP2P3,Point1與Point2連線為Line1_P1P2,Point2與Point3連線為Line2_P2P3,求得相應(yīng)的中垂線為Line3_P1P2_VerticalLine4_P2P3_Vertical

    最后,我們求兩條中垂線的交點(diǎn)即我們要求的圓心坐標(biāo)——Point6_CenterOfCircle。

    ?

    在這個(gè)過(guò)程中,我們需要用到一些簡(jiǎn)單的函數(shù),我們把這些函數(shù)實(shí)現(xiàn)在CenterOfCircle類下,作為CenterOfCircle類的私有成員函數(shù)。

    首先,我們要判斷三個(gè)點(diǎn)是否有兩個(gè)點(diǎn)相同,我們定義這個(gè)成員函數(shù)名bool IsSamePoint(Point,Point),其中兩個(gè)參數(shù)是要判斷的兩個(gè)點(diǎn),兩點(diǎn)相同返回值為1,兩點(diǎn)不同返回值為0;

    Point GetMidpoint(Point,Point)用來(lái)獲取中點(diǎn)坐標(biāo);

    Line GetLineOfTwoPoints(Point,Point)用來(lái)獲取兩點(diǎn)連線;

    bool IsSameSlope(Line,Line)判斷斜率是否相同,若兩兩連線的斜率相同即表示三點(diǎn)共線,即無(wú)解;

    Line GetMidperpendicular(Point,double)通過(guò)斜截式來(lái)實(shí)現(xiàn)中垂線的獲取,兩個(gè)參數(shù)分別為點(diǎn)與斜率;

    Point GetPointOfIntersection(Line,Line)獲取倆線交點(diǎn)坐標(biāo);

    double GetDistanceOfTwoPoint(Point,Point)獲取兩點(diǎn)距離;

    通過(guò)兩點(diǎn)的向量的叉乘的正負(fù)來(lái)判斷圓弧走向是順時(shí)針還是逆時(shí)針,我們通過(guò)成果函數(shù)bool GetDirection(Point,Point,Point)來(lái)進(jìn)行判斷,三個(gè)參數(shù)分別為給定的三個(gè)點(diǎn)。

    在關(guān)鍵字public標(biāo)識(shí)下的公有成員函數(shù)中,構(gòu)造函數(shù)中的6個(gè)參數(shù)分別是三個(gè)點(diǎn)在x與y方向的坐標(biāo);

    我們通過(guò)Result GetInformationOfCircle()來(lái)獲取最終給定三點(diǎn)的結(jié)果,結(jié)果中包括有無(wú)解,圓弧起點(diǎn),圓弧終點(diǎn),三點(diǎn)確定圓的圓心,圓弧走向以及三點(diǎn)確定的圓的半徑;在這個(gè)函數(shù)中,我們將用到私有的成員變量與成員函數(shù)。

    b.接下來(lái)我們開(kāi)始對(duì)CenterOfCirlce.cpp文件進(jìn)行編寫(xiě)

    (程序說(shuō)明在后面)

    #include "CenterOfCircle.h"CenterOfCircle::CenterOfCircle(double P1_x,double P1_y,double P2_x,double P2_y,double P3_x,double P3_y){Point1.x=P1_x;Point1.y=P1_y;Point2.x=P2_x;Point2.y=P2_y;Point3.x=P3_x;Point3.y=P3_y;}CenterOfCircle::~CenterOfCircle(void){}Result CenterOfCircle::GetInformationOfCircle(){Result theResult={0,{0,0},{0,0},{0,0},0,0};if(IsSamePoint(Point1,Point2)||IsSamePoint(Point2,Point3)||IsSamePoint(Point1,Point3)){return theResult;}Line1_P1P2 = GetLineOfTwoPoints(Point1,Point2);Line2_P2P3 = GetLineOfTwoPoints(Point2,Point3);if (IsSameSlope(Line1_P1P2,Line2_P2P3)==1){return theResult;}else{theResult.HasSolution=1;}Point4_MidP1P2 = GetMidpoint(Point1,Point2);Point5_MidP2P3 = GetMidpoint(Point2,Point3);Line3_P1P2_Vertical = GetMidperpendicular(Point4_MidP1P2,Line1_P1P2.k);Line4_P2P3_Vertical = GetMidperpendicular(Point5_MidP2P3,Line2_P2P3.k);theResult.CenterOfCircle = GetPointOfIntersection(Line3_P1P2_Vertical,Line4_P2P3_Vertical);theResult.StartPoint = Point1;theResult.EndPoint = Point3;theResult.Radius = GetDistanceOfTwoPoint(theResult.CenterOfCircle,Point2);theResult.Direction = GetDirection(Point1,Point2,Point3);return theResult;}bool CenterOfCircle::IsSamePoint(Point P1,Point P2){if ((P1.x==P2.x)&&(P1.y==P2.y)){return 1;}else{return 0;}}Line CenterOfCircle::GetLineOfTwoPoints(Point P1, Point P2){Line StraightLine={0,0};StraightLine.k = (P2.y - P1.y)/ (P2.x -P1.x);StraightLine.b = P1.y - P1.x * StraightLine.k ;return StraightLine;}bool CenterOfCircle::IsSameSlope(Line Line1,Line Line2){if (Line1.k==Line2.k){return 1;}else{return 0;}}Point CenterOfCircle::GetMidpoint(Point P1, Point P2){Point Midpoint={0,0};Midpoint.x = (P1.x + P2.x )/2;Midpoint.y = (P1.y + P2.y )/2;return Midpoint;}Line CenterOfCircle::GetMidperpendicular(Point P,double k){Line StraightLine={0,0};StraightLine.k = -1/k;StraightLine.b = P.y - StraightLine.k * P.x ;return StraightLine;}Point CenterOfCircle::GetPointOfIntersection(Line Line1,Line Line2){Point PointOfIntersection={0,0};PointOfIntersection.x = (Line2.b-Line1.b)/(Line1.k-Line2.k);PointOfIntersection.y = (Line2.k*Line1.b-Line1.k*Line2.b)/(Line2.k-Line1.k);return PointOfIntersection;}double CenterOfCircle::GetDistanceOfTwoPoint(Point P1,Point P2){double DistanceOfTwoPoint=0;DistanceOfTwoPoint=sqrt((P1.x-P2.x)*(P1.x-P2.x)+(P1.y-P2.y)*(P1.y-P2.y));return DistanceOfTwoPoint;}bool CenterOfCircle::GetDirection(Point P1,Point P2,Point P3){int CrossProduct=0;bool Direction;CrossProduct=(P2.x-P1.x)*(P3.y-P2.y)-(P2.y-P1.y)*(P3.x-P2.x);if(CrossProduct<0){Direction=1; //clockwise}else{Direction=0; //anticlockwise}return Direction;}
  • 在我們創(chuàng)建CenterOfCircle類的時(shí)候,VS2010自動(dòng)給我們生成了一部分代碼,在CenterOfCircle.cpp中,這寫(xiě)代碼分別是#include "CenterOfCircle.h",構(gòu)造函數(shù)及析構(gòu)函數(shù)。

    我們對(duì)構(gòu)造函數(shù)進(jìn)行改動(dòng),如CenterOfCircle.h文件中我們聲明的構(gòu)造函數(shù)一樣,我們對(duì)CenterOfCircle(double P1_x,double P1_y,double P2_x,double P2_y,double P3_x,double P3_y)函數(shù)的參數(shù)設(shè)置為P1_x,P1_y,P2_x,P2_y,P3_x,P3_y,六個(gè)形參依次代表是三個(gè)點(diǎn)。

    在構(gòu)造函數(shù)內(nèi)部我們將形參依次賦值給我們頭文件聲明過(guò)得私有化變量Point1.x,Point1.y,Point2.x,Point2.y,Point3.x,Point3.y,來(lái)完成對(duì)象的創(chuàng)建;如我們前面學(xué)習(xí)的構(gòu)造函數(shù)一樣,構(gòu)造函數(shù)用來(lái)創(chuàng)建對(duì)象,創(chuàng)建后的對(duì)象可以調(diào)用GetInformationOfCircle()函數(shù),獲取該對(duì)象對(duì)應(yīng)的解的信息——有無(wú)解,圓弧起點(diǎn),圓弧終點(diǎn),三點(diǎn)確定圓的圓心,圓弧走向以及三點(diǎn)確定的圓的半徑。

    析構(gòu)函數(shù)我們不需要進(jìn)行改動(dòng)。

    接下來(lái)我們將對(duì)這類最核心的功能進(jìn)行實(shí)現(xiàn),首先我們要實(shí)現(xiàn)這個(gè)函數(shù),按照C++編程規(guī) 范,我們?cè)谙葘?xiě)這個(gè)函數(shù)求得結(jié)果的返回值類型,在頭文件當(dāng)中,我們定義結(jié)構(gòu)體Result,我們求得的結(jié)果就放在這個(gè)結(jié)構(gòu)體當(dāng)中;然空格隔開(kāi),注意寫(xiě)上類名,表示是這個(gè)類下的函數(shù),然后兩個(gè)英文輸入法狀態(tài)下的冒號(hào),最后我們把這個(gè)函數(shù)的名稱寫(xiě)上GetInformationOfCircle(),由于對(duì)象創(chuàng)建由構(gòu)造函數(shù)完成,我們這里可以直接使用構(gòu)造函數(shù)創(chuàng)建對(duì)象對(duì)應(yīng)的三個(gè)點(diǎn)Point1,Point2,Point3進(jìn)行求解即可,所以不需要參數(shù)。

    進(jìn)入到大括號(hào)內(nèi)開(kāi)始對(duì)功能進(jìn)行實(shí)現(xiàn),首先我們先對(duì)所求結(jié)果的Result結(jié)構(gòu)體創(chuàng)建對(duì)象theResult,并且賦初值——{0,{0,0},{0,0},{0,0},0,0};

    參考頭文件對(duì)Result結(jié)構(gòu)體的定義,我們能夠看到bool型變量HasSolution,即是否有解,我們初始化為0,即無(wú)解;第二個(gè)參數(shù)和第三個(gè)參數(shù)分別為圓弧行進(jìn)起點(diǎn)坐標(biāo)與終點(diǎn)坐標(biāo)StartPoint和EndPoint;第四個(gè)參數(shù)CenterOfCircle,即三點(diǎn)確定的圓心坐標(biāo);第五個(gè)參數(shù)是圓弧行進(jìn)的方向,bool型變量Direction,后面我們將順時(shí)針?lè)较蚪o值為1,逆時(shí)針給值為0;最后一個(gè)參數(shù)為三點(diǎn)確定圓弧的半徑長(zhǎng)度Radius;

    在對(duì)三個(gè)點(diǎn)進(jìn)行處理前,我們應(yīng)該首先判斷兩件事情,1.輸入的三個(gè)點(diǎn)是否有相同的點(diǎn);2.這三個(gè)點(diǎn)是否在同一條直線上;以上兩種情況無(wú)法求得相應(yīng)結(jié)果。

    1.判斷兩點(diǎn)是否相同的函數(shù)IsSamePoint的實(shí)現(xiàn)

    判斷點(diǎn)與點(diǎn)是否相同我們通過(guò)一個(gè)函數(shù)IsSamePoint實(shí)現(xiàn),然后通過(guò)調(diào)用這個(gè)函數(shù)來(lái)判斷Point1,Point2,Point3兩兩是否相同。

    以下是IsSamePoint函數(shù)的實(shí)現(xiàn),返回值為bool型,返回值為1代表這兩個(gè)點(diǎn)相同,返回值為0代表這兩個(gè)點(diǎn)不相同。兩個(gè)參數(shù)都是Point結(jié)構(gòu)體類型,該結(jié)構(gòu)在頭文件已定義過(guò)了,可以參考頭文件中Point結(jié)構(gòu)體的定義。

    在函數(shù)內(nèi)部我們通過(guò)if語(yǔ)句判斷實(shí)現(xiàn)了兩點(diǎn)是否相同的判定,相同我們返回值為1,否則將返回0。

    2.判斷三個(gè)點(diǎn)是否在同一條直線上函數(shù)IsSameSlope的實(shí)現(xiàn)

    判斷三點(diǎn)是否共線實(shí)現(xiàn)的思路分為兩步:

    a)我們將Point1與Point2,Point2與Point3連接起來(lái),得到著兩條直線Line1_P1P2和Line2_P2P3;我們通過(guò)斜截式來(lái)表示直線。我們通過(guò)結(jié)構(gòu)體Line來(lái)定義直線,Line結(jié)構(gòu)體的兩個(gè)成員分別為斜率k與截距b。

    ?

    b)然后對(duì)這兩條直線的斜率進(jìn)行判定是否相等來(lái)得出三點(diǎn)是否共線

    與函數(shù)IsSamePoint類似,我們定義一個(gè)返回值為bool型的IsSameSlope函數(shù),參數(shù)為兩個(gè)結(jié)構(gòu)體類型Line,通過(guò)對(duì)兩個(gè)形參的Line1與Line2的斜率k進(jìn)行判斷是否相等,最終得出三點(diǎn)是否共線。

    ?

    回到CenterOfCircle.cpp中來(lái),第22行到第38行代碼判斷了三點(diǎn)中是否有兩點(diǎn)相同以及三點(diǎn)是否共線,如果三點(diǎn)中沒(méi)有兩個(gè)相同的點(diǎn),并且也三點(diǎn)不共線,則有解,我們將theResult的成員HasSolution賦值為1。

    接下來(lái)開(kāi)始對(duì)三點(diǎn)所確定圓的圓心進(jìn)行求解,我們分三步進(jìn)行:

    1.求取Point1與Point2、Point2與Point3的中點(diǎn)坐標(biāo);

    2.求Point1與Point2所在直線Line1_P1P2的中垂線Line3_P1P2_Vertical,以及Point2與Point3所在直線Line_P2P3的中垂線Line4_P2P3_Vertical;

    回憶初高中數(shù)學(xué)知識(shí),求中垂線,我們使用斜截式進(jìn)行求解。在函數(shù)GetMidperpendicular中,參數(shù)定義了兩個(gè),分別為Point結(jié)構(gòu)體變量P,以及double型變量k;這兩個(gè)參數(shù)分別代表所求線段的中點(diǎn)與斜率。

    3.求兩條中垂線的交點(diǎn),即圓心CenterOfCircle坐標(biāo);

    兩條中垂線獲得后我們可以通過(guò)解二元一次方程來(lái)求得交點(diǎn),也就是我們最終要求的CenterOfCircle。

    通過(guò)調(diào)用這些函數(shù),在CenterOfCircle.cpp程序的39至46行實(shí)現(xiàn)了圓心坐標(biāo)的求取;然后將Point1與Point2分別賦值給圓弧行進(jìn)的起始點(diǎn)StartPoint與終點(diǎn)EndPoint。

    半徑的求取我們?cè)俅瓮ㄟ^(guò)一個(gè)函數(shù)GetDistanceOfTwoPoint來(lái)實(shí)現(xiàn),在程序的49行,我通過(guò)計(jì)算兩點(diǎn)theResult.CenterOfCircle與Point2得出了半徑長(zhǎng)度。這里用到了開(kāi)平方的函數(shù)sqrt,這也是為什么我們?cè)陬^文件中要包含cmath的原因。

    最后,還需要確定圓弧的走向。關(guān)于圓弧走向的數(shù)學(xué)證明這里不再累述,具體數(shù)學(xué)計(jì)算方法如下:設(shè)=(x1,y1),=(x2,y2),=(x3,y3),向量與的向量積(x2-x1)*(y3-y2)-(y2-y1)*(x3-x2)為正時(shí),走向?yàn)槟鏁r(shí)針;為負(fù)時(shí),走向?yàn)轫槙r(shí)針;由于三點(diǎn)不在一條直線上,所以兩向量叉乘不會(huì)為0。

    至此,我們所求結(jié)果result結(jié)構(gòu)體對(duì)應(yīng)的所有成員都有了值。我們寫(xiě)一個(gè)main.cpp來(lái)測(cè)試以下我們寫(xiě)的CenterOfCircle類。

    c.通過(guò)main.cpp文件進(jìn)行三點(diǎn)求圓心類的測(cè)試

    #include "CenterOfCircle.h"#include <iostream>using namespace std;int main(){CenterOfCircle COC(0,0,5,5,10,0);Result R1;R1=COC.GetInformationOfCircle();cout<<std::fixed<<R1.CenterOfCircle.x<<endl;cout<<std::fixed<<R1.CenterOfCircle.y<<endl;cout<<R1.Direction<<endl;cout<<R1.Radius<<endl;system("pause");return 0;}
  • 第1行代碼我們將CenterOfCircle.h包含進(jìn)來(lái),相當(dāng)于我們能夠使用CenterOfCircle類的功能;?進(jìn)入主函數(shù)里面,我們使用CenterOfCircle類創(chuàng)建一個(gè)名為COC的對(duì)象,六個(gè)參數(shù)為三個(gè)點(diǎn)的x坐標(biāo)與y坐標(biāo);

    第7行定義一個(gè)名為R1的Result結(jié)構(gòu)體變量,通過(guò)調(diào)用COC對(duì)象下的成員函數(shù)GetInformationOfCircle(),并將所得結(jié)果傳遞給R1,我們得到了點(diǎn)(0,0)、點(diǎn)(5,5)與點(diǎn)(10,0)確定的圓的相應(yīng)信息——有無(wú)解,圓弧起點(diǎn),圓弧終點(diǎn),三點(diǎn)確定圓的圓心,圓弧走向以及三點(diǎn)確定的圓的半徑;

    第9行至12行我們使用cout函數(shù)將相應(yīng)的結(jié)果輸出出來(lái)。通過(guò)使用std::fixed我們禁用科學(xué)計(jì)數(shù)法,大家可以試一試對(duì)比下有無(wú)std::fixed最終結(jié)果顯示的區(qū)別。

    思考:如果細(xì)心的同學(xué)會(huì)發(fā)現(xiàn),我們對(duì)于有些情況沒(méi)有考慮進(jìn)去。例如求解以下三個(gè)點(diǎn)(0,5),(5,5),(5,0)時(shí),最終輸出的結(jié)果并不能輸出正確的結(jié)果。這是由于我們少考慮了兩種情況:1.兩點(diǎn)的連線平行于x軸;2.兩點(diǎn)連線垂直于y軸。如何完善這個(gè)類,將以上兩種情況考慮進(jìn)去,進(jìn)行正確的計(jì)算輸出呢?可參考7.2三點(diǎn)求圓心這一節(jié)的內(nèi)容進(jìn)行程序的完善。

    7.3.3?編程練習(xí):逐點(diǎn)比較法直線插補(bǔ)類

    這一小節(jié)我們對(duì)第五章的逐點(diǎn)比較法直線插補(bǔ)封裝成類,以進(jìn)一步加強(qiáng)對(duì)函數(shù)和類的掌握。創(chuàng)建項(xiàng)目后,添加類名為Interpolator的類,頭文件Interpolator.h程序如表7-5所示。

  • ?

    #pragma once #include <cmath> #include <iostream> using namespace std; class Interpolator { private: int m_xs; int m_ys; int m_xi; int m_yi; int m_xe; int m_ye; int m_Nxy; int m_XieLvChaZhi; int m_i; public: Interpolator(int,int,int,int); ~Interpolator(void); void DoInterpolator(); };
  • 表7-5?頭文件Interpolator.h程序

    將所有的數(shù)據(jù)(變量)放在關(guān)鍵字private下,構(gòu)造函數(shù)設(shè)置了4個(gè)int型參數(shù),分別代表插補(bǔ)的起始點(diǎn)和終點(diǎn)。

    源文件Interpolator.cpp中的程序如表7-6所示。

    #include "Interpolator.h"Interpolator::Interpolator(int xs,int ys,int xe,int ye) {m_xs=xs;m_ys=ys;m_xe=xe;m_ye=ye;cout<<"起點(diǎn)為"<<m_xs<<","<<m_ys<<endl;cout<<"終點(diǎn)為"<<m_xe<<","<<m_ye<<endl; }Interpolator::~Interpolator(void) { }void Interpolator::DoInterpolator() {m_Nxy =abs( (m_xe - m_xs)) + abs((m_ye - m_ys));m_i=1;m_xi = m_xs;m_yi = m_ys;for(int i=0;i<m_Nxy;i++){m_XieLvChaZhi =(m_xe-m_xs)*(m_yi-m_ys)-(m_xi-m_xs)*(m_ye-m_ys);if(m_xe-m_xs==0){if (m_ye-m_ys>0){m_yi++;}else{m_yi--;}cout<<m_xi<<","<<m_yi<<endl;}if(m_ye-m_ys==0){if (m_xe-m_xs>0){m_xi++;}else{m_xi--;}cout<<m_xi<<","<<m_yi<<endl;}if ((m_xe-m_xs>0)&&(m_ye-m_ys>0)){if (m_XieLvChaZhi>=0){m_xi++;} else{m_yi++;}cout<<m_xi<<","<<m_yi<<endl;}if ((m_xe-m_xs<0)&&(m_ye-m_ys>0)){if (m_XieLvChaZhi<=0){m_xi--;} else{m_yi++;}cout<<m_xi<<","<<m_yi<<endl;}if ((m_xe-m_xs<0)&&(m_ye-m_ys<0)){if (m_XieLvChaZhi<=0){m_yi--;} else{m_xi--;}cout<<m_xi<<","<<m_yi<<endl;}if ((m_xe-m_xs>0)&&(m_ye-m_ys<0)){if (m_XieLvChaZhi>=0){m_yi--;} else{m_xi++;}cout<<m_xi<<","<<m_yi<<endl;}}cout<<"********************************************"<<endl; }

    表7-6?源文件Interpolator.cpp程序

    首先編寫(xiě)構(gòu)造函數(shù),通過(guò)構(gòu)造函數(shù)的四個(gè)參數(shù)(即起點(diǎn)坐標(biāo)與中點(diǎn)坐標(biāo))來(lái)構(gòu)造不同的對(duì)象,并且創(chuàng)建對(duì)象時(shí)使用輸出流對(duì)象cout進(jìn)行起始點(diǎn)以及終點(diǎn)的顯示(10行至11行)。

    成員函數(shù)DoInterpolator實(shí)現(xiàn)了過(guò)程點(diǎn)的計(jì)算以及輸出顯示,該部分代碼原理在第5章已經(jīng)有講述,這里不再累述。

    接下來(lái),就可以通過(guò)在“源文件”中添加主函數(shù)文件進(jìn)行類的測(cè)試。程序如表7-7所示。

    #include "Interpolator.h"int main() {Interpolator chabu1(1,1,5,5);chabu1.DoInterpolator();Interpolator chabu2(2,3,-4,2);chabu2.DoInterpolator();system("pause");return 0; }

    表7-7?源文件main.cpp程序

    可以看到測(cè)試程序里面,分別使用Interpolator類創(chuàng)建了兩個(gè)對(duì)象——chabu1(第5行代碼,參數(shù)表示起點(diǎn)坐標(biāo)為1,1點(diǎn),終點(diǎn)為5,5點(diǎn))以及chabu2(第7行代碼,參數(shù)表示起點(diǎn)坐標(biāo)為2,3點(diǎn),終點(diǎn)為-4,2點(diǎn))。

    程序測(cè)試結(jié)果如圖7-10所示。

    ?

    圖7-10?逐點(diǎn)比較法直線插補(bǔ)類測(cè)試結(jié)果示意圖

    7.4?計(jì)算器小軟件

    前面我們學(xué)習(xí)了大量的C++語(yǔ)言的基礎(chǔ)知識(shí),也通過(guò)很多練習(xí)加強(qiáng)了對(duì)該語(yǔ)言應(yīng)用的掌握。但大家似乎會(huì)疑問(wèn),為什么我們最終的程序?qū)崿F(xiàn)結(jié)果是一個(gè)黑乎乎的界面,一點(diǎn)都不美觀,感覺(jué)和我們常用的軟件相差甚遠(yuǎn)。7.4與7.5兩節(jié)我們將開(kāi)始對(duì)Qt進(jìn)行應(yīng)用,做兩個(gè)小軟件。當(dāng)然,我們還是采取由簡(jiǎn)至難的策略。這一節(jié)我們基于Qt先實(shí)現(xiàn)一個(gè)簡(jiǎn)易的計(jì)算器小軟件,該軟件能夠?qū)崿F(xiàn)對(duì)兩個(gè)輸入的數(shù)字進(jìn)行加減乘除運(yùn)算。

    7.4.1 QT APPLICATION項(xiàng)目創(chuàng)建

    接下來(lái)需要我們先創(chuàng)建一個(gè)Qt Application項(xiàng)目。打開(kāi)VS2010,依次點(diǎn)擊“文件”、“新建”、“項(xiàng)目”,然后在“新建項(xiàng)目”界面下,點(diǎn)擊“Qt5 Projects”,并點(diǎn)擊選擇該項(xiàng)目下的“Qt Application”,更改項(xiàng)目名稱為“Calculator”,項(xiàng)目名稱和接下來(lái)系統(tǒng)默認(rèn)創(chuàng)建的程序相關(guān),請(qǐng)不要寫(xiě)錯(cuò)。如圖7-11所示。

    ?

    圖7-11 Qt Application項(xiàng)目創(chuàng)建示意圖

    然后會(huì)自動(dòng)出現(xiàn)Qt5 GUI Project Wizard窗口,該窗口可以設(shè)置項(xiàng)目所需要的組件,我們忽略設(shè)置步驟,直接點(diǎn)擊“Finish”即可,如圖7-12所示。

    ?

    圖7-12 Qt5 GUI Project Wizard窗口

    其后,VS2010將自動(dòng)創(chuàng)建一個(gè)Qt Application項(xiàng)目,并且自帶了一部分文件以及程序。按下F5,編譯并運(yùn)行,顯示一個(gè)什么都沒(méi)有的窗口,完成第一步項(xiàng)目創(chuàng)建工作。

    7.4.2 UI界面設(shè)計(jì)

    前面我們已經(jīng)寫(xiě)了很多的程序,這里我們將接觸一個(gè)全新的編程模式:使用Qt Designer將界面畫(huà)出來(lái),然后自動(dòng)生成對(duì)應(yīng)界面的代碼;當(dāng)然我們可以不用管生成后的代碼是什么樣的,也可以很好的將目標(biāo)軟件實(shí)現(xiàn)出來(lái)。

    雙擊“Calculator”項(xiàng)目下的“calculator.ui”文件,如圖7-13所示。

    ?

    圖7-13 Calculator項(xiàng)目文件示意圖

    系統(tǒng)將自動(dòng)調(diào)用Qt Designer進(jìn)行界面設(shè)計(jì)。Qt Designer能夠快速設(shè)置窗口需要的組件以及組件的相關(guān)屬性,可以說(shuō)是以“畫(huà)圖”的方式來(lái)進(jìn)行軟件設(shè)計(jì)。其界面如圖7-14所示。

    ?

    ?

    圖7-14 Qt Designer界面示意圖

    Qt Designer上方如其他軟件類似是菜單欄和工具欄,需要特別注意的是最左側(cè)的“Widget Box”以及中間部分標(biāo)題為“Calculator - calculator.ui”的窗口,“Widget Box”里面是軟件需要的一些組件,包括我們經(jīng)常接觸到的按鈕、標(biāo)簽、文本框等等。我們直接點(diǎn)擊鼠標(biāo)不松將需要的組件拖入我們的“Calculator - calculator.ui”窗口當(dāng)中。我們需要兩個(gè)能夠輸入數(shù)字并能夠顯示的組件,我用在“Widget Box”中查找,可找到Double Spin Box組件,我們將其拖出,放在我們的“Calculator - calculator.ui”窗口當(dāng)中;然后找到Push Button組件,拖入四個(gè)到“Calculator - calculator.ui”窗口當(dāng)中;如圖7-15所示。

    ?

    圖7-15?包含三個(gè)Double Spin Box以及四個(gè)Push Button的窗口示意圖

    我們將對(duì)最左側(cè)的兩個(gè)Double Spin Box進(jìn)行相應(yīng)數(shù)字的輸入,然后四個(gè)Push Button分別代表對(duì)這兩個(gè)數(shù)字的加、減、乘、除計(jì)算功能執(zhí)行,右側(cè)的Double Spin Box將兩個(gè)數(shù)字對(duì)應(yīng)的計(jì)算結(jié)果顯示出來(lái)。

    那么,我們程序里面怎么識(shí)別我們點(diǎn)擊了哪一個(gè)按鈕呢?

    我們把目光轉(zhuǎn)向圖??的右側(cè)的“屬性編輯器”,當(dāng)點(diǎn)擊組件的時(shí)候,右側(cè)的“屬性編輯器”將出現(xiàn)組件對(duì)應(yīng)的屬性,其中最重要的就是“objectNmae”,這個(gè)是我們寫(xiě)程序時(shí)所需要用到的名稱,以此跟界面連接起來(lái),實(shí)現(xiàn)圖形交互。我們點(diǎn)擊圖??最上面的那個(gè)“PushButton”,將“objectName”由默認(rèn)的名稱改為“ButtonAdd”,如圖7-16所示。

    ?

    圖7-16 UI文件按鈕名稱更改示意圖

    其后分別將其他三個(gè)按鈕的“objectName”屬性改為“ButtonReduce”、“ButtonMutiply”、“ButtonDivide”;將三個(gè)“Double Spin Box”組件的“objectName”屬性改為“DoubleBoxNumber1”、“DoubleBoxNumber2”、“DoubleBoxNumber3”,同時(shí),我們將三個(gè)“Double Spin Box”組件的“decimals”屬性改為“6”,這樣該組件就能顯示小數(shù)點(diǎn)后6位的數(shù)字,同時(shí)將“minimum”和“maximum”分別改為-10000和10000,這樣基本上能夠滿足我們的數(shù)字顯示范圍(這三個(gè)屬性在該組件的屬性編輯器較下面的位置)。

    由于界面顯示了四個(gè)相同Push Button,雙擊Push Button組件,我們將顯示的內(nèi)容改為“+”、“-”、“*”、“/”,如圖7-17所示。

    ?

    圖7-17?已完成的簡(jiǎn)易計(jì)算器界面圖

    我們會(huì)發(fā)現(xiàn)在標(biāo)題多了一個(gè)星號(hào)——“Calculator - calculator.ui*”,這是因?yàn)槲覀兏膭?dòng)了界面但沒(méi)有保存的緣故,我們依次點(diǎn)擊菜單欄的“文件”,“保存”,將完成的界面保存起來(lái)。到此為止,ui界面的設(shè)計(jì)已經(jīng)完成,接下來(lái)我們要編寫(xiě)程序,來(lái)實(shí)現(xiàn)計(jì)算功能。

    7.4.3?計(jì)算功能程序?qū)崿F(xiàn)

    在創(chuàng)建Qt Application項(xiàng)目后,會(huì)自動(dòng)生成一部分文件與相應(yīng)程序。我們可以直接在系統(tǒng)已給定的程序基礎(chǔ)上進(jìn)行程序的編寫(xiě)。我們依舊先對(duì)頭文件進(jìn)行編寫(xiě),如表7-8所示,加下劃線的代碼是添加或修改的。

    #ifndef CALCULATOR_H #define CALCULATOR_H#include <QtWidgets/QMainWindow> #include "ui_calculator.h"class Calculator : public QMainWindow {Q_OBJECTpublic:Calculator(QWidget *parent = 0);~Calculator();private slots:void Add();void Reduce();void Mutiply();void Divide();private:Ui::CalculatorClass ui;double m_Number1;double m_Number2;double m_Number3; };#endif // CALCULATOR_H

    表7-8 calculator.h程序

    首先,我們看1、2、28行的代碼,這三行是一體的,該語(yǔ)句為了防止頭文件重復(fù)編譯,類似于#pragma once,第4、5行包含了兩個(gè)頭文件,第一個(gè)頭文件,聲明我們要使用QMainWindow類,也就是說(shuō)我們創(chuàng)建的Calculator類是一個(gè)能夠?qū)崿F(xiàn)主窗口的類;第二個(gè)頭文件ui_calculator.h?表示我們包含了一個(gè)界面文件,也就是我們上文所說(shuō)的Qt Designer中設(shè)計(jì)的界面文件編譯后的文件。其中,第7行代碼表明創(chuàng)建了類Calculator,并繼承了QMainWindow的功能,類的繼承我們會(huì)在第八章進(jìn)行講解,這里我們先跳過(guò)去;Q_OBJECT為宏,類似于我們學(xué)過(guò)的?using namespace std;?該語(yǔ)句使用后,方便我們后面會(huì)使用connect函數(shù)(后面會(huì)講);接下來(lái)定義了兩個(gè)公共函數(shù),分別是構(gòu)造函數(shù)和析構(gòu)函數(shù)。

    接下來(lái)我們看這一節(jié)最重要的部分——信號(hào)和槽機(jī)制。信號(hào)和槽機(jī)制是?Qt?的核心機(jī)制,可以讓編程人員將互不相關(guān)的對(duì)象綁定在一起,實(shí)現(xiàn)對(duì)象之間的通信。舉例來(lái)說(shuō),當(dāng)用戶點(diǎn)擊我們?cè)O(shè)計(jì)的簡(jiǎn)易計(jì)算器的“+”按鈕時(shí),軟件內(nèi)部將執(zhí)行加法功能,而用戶點(diǎn)擊這一行為發(fā)出的就是一個(gè)信號(hào),該信號(hào)對(duì)應(yīng)的要實(shí)現(xiàn)的功能即為槽。所有的槽函數(shù)需要在頭文件中單獨(dú)在“private slots:”語(yǔ)句下進(jìn)行聲明。四個(gè)函數(shù)分別對(duì)應(yīng)接下來(lái)要編寫(xiě)的源文件中的加減乘除四個(gè)功能。

    我們需要對(duì)兩個(gè)數(shù)進(jìn)行計(jì)算,所有我們聲明兩個(gè)私有變量,以及一個(gè)計(jì)算后的私有變量,對(duì)應(yīng)程序的23至25行。對(duì)于22行代碼,大家可以簡(jiǎn)單理解為我們前面所設(shè)計(jì)的整個(gè)界面,后面使用界面里面的組件的時(shí)候,需要先輸入22行代碼中所命的名字ui。

    接下來(lái)我們進(jìn)行源文件的編寫(xiě),程序如表7-9所示,加粗部分為添加的代碼部分。

    #include "calculator.h"Calculator::Calculator(QWidget *parent) : QMainWindow(parent) {ui.setupUi(this);connect(ui.ButtonAdd,SIGNAL(clicked()),this,SLOT(Add()));connect(ui.ButtonReduce,SIGNAL(clicked()),this,SLOT(Reduce()));connect(ui.ButtonMutiply,SIGNAL(clicked()),this,SLOT(Mutiply()));connect(ui.ButtonDivide,SIGNAL(clicked()),this,SLOT(Divide())); }Calculator::~Calculator() { }void Calculator::Add() {m_Number1=ui.DoubleBoxNumber1->value();m_Number2=ui.DoubleBoxNumber2->value();m_Number3=m_Number1+m_Number2;ui.DoubleBoxNumber3->setValue(m_Number3); }void Calculator::Reduce() {m_Number1=ui.DoubleBoxNumber1->value();m_Number2=ui.DoubleBoxNumber2->value();m_Number3=m_Number1-m_Number2;ui.DoubleBoxNumber3->setValue(m_Number3); }void Calculator::Mutiply() {m_Number1=ui.DoubleBoxNumber1->value();m_Number2=ui.DoubleBoxNumber2->value();m_Number3=m_Number1*m_Number2;ui.DoubleBoxNumber3->setValue(m_Number3); }void Calculator::Divide() {m_Number1=ui.DoubleBoxNumber1->value();m_Number2=ui.DoubleBoxNumber2->value();m_Number3=m_Number1/m_Number2;ui.DoubleBoxNumber3->setValue(m_Number3); }

    表7-9 calculator.cpp程序

    第1行代碼包含相應(yīng)的頭文件,第3、4、6、13行代碼為構(gòu)造函數(shù)以及析構(gòu)函數(shù)的相關(guān)代碼,這部分默認(rèn)給定的代碼我們通常情況下無(wú)需修改。

    我們重點(diǎn)看第7行至第10行,前面我們已經(jīng)提到了信號(hào)和槽機(jī)制,這里我們將兩者相連,實(shí)現(xiàn)該功能的函數(shù)尉connect函數(shù),很容易找到該函數(shù)的使用規(guī)則,該函數(shù)的共有四個(gè)參數(shù),其中第一個(gè)為界面中的組件,第二個(gè)參數(shù)對(duì)應(yīng)于該組件的信號(hào)類型,第三個(gè)為this,第四個(gè)為對(duì)應(yīng)的槽函數(shù)。如果想深入了解Qt、信號(hào)與槽機(jī)制、connect函數(shù)等可以學(xué)習(xí)Qt的幫助文檔,學(xué)會(huì)看幫助文檔是一個(gè)程序員必備的素質(zhì)。

    第17行至第23行我們實(shí)現(xiàn)了加法功能,通過(guò)Double Spin Box組件的成員函數(shù)value()來(lái)獲取DoubleBoxNumber1以及DoubleBoxNumber2值,m_Number1以及m_Number2分別得到到了兩個(gè)組件的值后,相加后賦值給m_Number3,,最后使用函數(shù)setvalue()將變量m_Number3的值賦給組件DoubleBoxNumber3,并顯示出來(lái)。

    我們能夠看到無(wú)論是value()函數(shù)還是setValue()函數(shù)前面都使用了“->”符號(hào),而不是“.”;因?yàn)镼t在編譯界面文件的時(shí)候,自動(dòng)將我們所用的所有組件以指針的形式進(jìn)行創(chuàng)建(大家可以在Calcultor項(xiàng)目下的Generated Files文件夾中ui_calculator.h文件找到),所以u(píng)i.DoubleBoxNumber1、ui.DoubleBoxNumber2、ui.DoubleBoxNumber3都是指向類的指針,后面調(diào)用成員函數(shù)的時(shí)候用“->”符號(hào)。

    其余三個(gè)函數(shù)與加法函數(shù)沒(méi)有太大的區(qū)別,在此不多做解釋。

    最后還是下一個(gè)main.cpp文件,這個(gè)文件中的程序我們無(wú)需改動(dòng),具體的程序意義不再累述,因?yàn)镼t自身就是一個(gè)很龐大的軟件項(xiàng)目,有余力或有興趣的同學(xué)可以自行深入地去學(xué)習(xí),這些年Qt因?yàn)樽陨淼拈_(kāi)源、免費(fèi)、跨平臺(tái)特性越來(lái)越受到開(kāi)發(fā)者的熱愛(ài),并且應(yīng)用也越來(lái)越廣泛。

    到這里我們就可以按下鍵盤(pán)上的F5鍵,我們就可以測(cè)試下自己編寫(xiě)的簡(jiǎn)易計(jì)算器是否能夠如愿工作。如圖7-18所示,我們分別輸入“123”和“456”,然后按下按鈕“/”,得到結(jié)果為“0.269737”。

    ?

    圖7-18?簡(jiǎn)易計(jì)算器測(cè)試結(jié)果圖

    7.5?編程練習(xí):直線插補(bǔ)模擬小軟件

    通過(guò)使用Qt完成一個(gè)簡(jiǎn)易計(jì)算器,讓我們對(duì)軟件的用戶交互界面實(shí)現(xiàn)有一個(gè)初步的認(rèn)識(shí)。這一節(jié)我們完成一個(gè)直線插補(bǔ)模擬小軟件。

    首先,創(chuàng)建一個(gè)名為“Interpolator”的Qt Application項(xiàng)目;雙擊“Interpolator”項(xiàng)目下的“interpolator.ui”文件,開(kāi)始設(shè)計(jì)直線插補(bǔ)模擬小軟件的交互界面,如圖7-19所示,我們這一次學(xué)習(xí)兩個(gè)新的組件——Label、Text Browser。我們拖入兩個(gè)Label組件,并將顯示內(nèi)容改為“Start Point:”和“End Point:”,Label組件的主要功能就是在界面上進(jìn)行提示性顯示,所以對(duì)于“objectName”以及其他屬性都無(wú)需更改;然后分別在兩個(gè)Label組件后面各添加兩個(gè)Spin Box組件,Spin Box組件和Double Spin Box的區(qū)別在于前者所能夠輸入輸出的數(shù)字為整數(shù),后者則為帶小數(shù)的數(shù)字,分別將兩組Spin Box組件改名為“spinBox_xs”。放置一個(gè)Push Button組件,點(diǎn)擊該按鈕將觸發(fā)對(duì)應(yīng)的直線插補(bǔ)功能,并將過(guò)程點(diǎn)輸出在我們Text Browser組件中,我們將Push Button的“objectName”改為“ButtonDoInterpolator”,Text Browser的“objectName”保持“textBrowser”不變。后面我們依舊在程序中使用這些組件的名字來(lái)實(shí)現(xiàn)界面交互功能。

    ?

    圖7-19?直線插補(bǔ)模擬小軟件示意圖

    然后,我們開(kāi)始完成頭文件“interpolator.h”以及源文件“interpolator.cpp”,主程序文件“main.cpp”依舊不需要改動(dòng)。經(jīng)過(guò)了逐點(diǎn)比較法直線插補(bǔ)類以及計(jì)算器小軟件的訓(xùn)練,大家可以自行嘗試寫(xiě)一寫(xiě)程序,然后參考下面給出的程序內(nèi)容進(jìn)行比對(duì)。頭文件“Interpolator.h”程序如表7-10所示。

    #ifndef INTERPOLATOR_H #define INTERPOLATOR_H#include <QtWidgets/QMainWindow> #include "ui_interpolator.h"class Interpolator : public QMainWindow {Q_OBJECTpublic:Interpolator(QWidget *parent = 0);~Interpolator();private slots:void DoInterpolator();private:Ui::InterpolatorClass ui;int m_xs;int m_ys;int m_xe;int m_ye; };#endif // INTERPOLATOR_H

    表7-10 Interpolator.h程序?

    程序中我們只在原有程序的基礎(chǔ)上增加了一個(gè)槽函數(shù)以及四個(gè)int型變量,四個(gè)int型變量代表起點(diǎn)和終點(diǎn)坐標(biāo)。

    然后是源文件Interpolator.cpp,如表7-11所示。在程序中,加入一個(gè)connect函數(shù),將按鈕與為一個(gè)槽函數(shù)DoInterpolator()相連接;第16行代碼比表示清除掉Text Browser中的內(nèi)容,然后接下來(lái)四行將Spin Box組件中的數(shù)值提取出來(lái)賦值給頭文件中聲明的四個(gè)int型變量——m_xs,m_ys,m_xe,m_ye;剩下的大多數(shù)代碼已經(jīng)多次學(xué)習(xí),第39至第42行代碼實(shí)現(xiàn)了過(guò)程點(diǎn)在界面中Text Browser組件中的顯示,Qt的QString類提供了很方便的對(duì)字符串操作的接口,注意QString類與我們前面學(xué)到的輸入輸出流iostream類的區(qū)別;調(diào)用Text Browser組件下的append()函數(shù)即可實(shí)現(xiàn),對(duì)該函數(shù)括號(hào)中參數(shù)(參數(shù)類型為QString型)的顯示。想進(jìn)一步了解Text Browser組件的其他成員函數(shù)以及用法可以查看Qt的幫助文檔。

    #include "interpolator.h"Interpolator::Interpolator(QWidget *parent): QMainWindow(parent) {ui.setupUi(this);connect(ui.ButtonDoInterpolator,SIGNAL(clicked()),this,SLOT(DoInterpolator())); }Interpolator::~Interpolator() { }void Interpolator::DoInterpolator() {ui.textBrowser->clear();m_xs=ui.spinBox_xs->value();m_ys=ui.spinBox_ys->value();m_xe=ui.spinBox_xe->value();m_ye=ui.spinBox_ye->value();int Nxy,xi,yi,FM;xi = m_xs;yi = m_ys;Nxy =abs( (m_xe - m_xs)) + abs((m_ye - m_ys));for(int i=0;i<Nxy;i++){FM =(m_xe-m_xs)*(yi-m_ys)-(xi-m_xs)*(m_ye-m_ys);if(m_xe-m_xs==0){if (m_ye-m_ys>0){yi++;}else{yi--;}QString str1 = QString::number(xi,'g',6);QString str2 = QString::number(yi,'g',6);QString str3 = str1+','+str2;ui.textBrowser->append(str3);}if(m_ye-m_ys==0){if (m_xe-m_xs>0){xi++;}else{xi--;}QString str1 = QString::number(xi,'g',6);QString str2 = QString::number(yi,'g',6);QString str3 = str1+','+str2;ui.textBrowser->append(str3);}if ((m_xe-m_xs>0)&&(m_ye-m_ys>0)){if (FM>=0){xi++;} else{yi++;}QString str1 = QString::number(xi,'g',6);QString str2 = QString::number(yi,'g',6);QString str3 = str1+','+str2;ui.textBrowser->append(str3);}if ((m_xe-m_xs<0)&&(m_ye-m_ys>0)){if (FM<=0){xi--;} else{yi++;}QString str1 = QString::number(xi,'g',6);QString str2 = QString::number(yi,'g',6);QString str3 = str1+','+str2;ui.textBrowser->append(str3);}if ((m_xe-m_xs<0)&(m_ye-m_ys<0)){if (FM<=0){yi--;} else{xi--;}QString str1 = QString::number(xi,'g',6);QString str2 = QString::number(yi,'g',6);QString str3 = str1+','+str2;ui.textBrowser->append(str3);}if ((m_xe-m_xs>0)&(m_ye-m_ys<0)){if (FM>=0){yi--;} else{xi++;}QString str1 = QString::number(xi,'g',6);QString str2 = QString::number(yi,'g',6);QString str3 = str1+','+str2;ui.textBrowser->append(str3);}} }

    表7-11 Interpolator.cpp程序

    主程序文件“main.cpp”依舊無(wú)需改動(dòng),此時(shí)點(diǎn)擊鍵盤(pán)F5編譯并執(zhí)行程序,我們以起始點(diǎn)(12,34)終點(diǎn)(56,78)為例,測(cè)試一下輸出的結(jié)果,如圖7-20所示。

    ?

    圖7-20?直線插補(bǔ)模擬小軟件測(cè)試結(jié)果圖

    版權(quán)聲明:本文為qq_36552550原創(chuàng)文章,遵循?CC 4.0 BY-SA?版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。

    本文鏈接:七、函數(shù)與類——Qt快速入門、三點(diǎn)求圓心實(shí)現(xiàn)詳解_Ce Ma的博客-CSDN博客

    總結(jié)

    以上是生活随笔為你收集整理的QT快速入门、三点求圆心实现详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 美国美女群体交乱 | 日韩avwww| 午夜激情在线视频 | 波多野结衣视频在线 | 毛茸茸亚洲孕妇孕交片 | 欧美一级视频免费 | 国产精品com | 欧美成人一区二区三区片免费 | 不卡av一区 | 欧美日韩一卡 | 亚洲成人精品视频 | 日韩在线视频观看免费 | 久久伊人成人网 | 欧美精品v| 萌白酱喷水视频 | 国产福利精品在线观看 | 91视频精选 | 久久久久国产视频 | 超碰人人草人人干 | 欧美精品一级二级 | 日本黄在线观看 | 国产美女作爱全过程免费视频 | 精品福利电影 | 国产91在线播放九色 | 亚洲精品一区二区三区新线路 | 你懂的在线观看网址 | 无码无遮挡又大又爽又黄的视频 | www成人啪啪18软件 | 亚洲精品视频导航 | 国产露脸150部国语对白 | 极品国产91在线网站 | 一二三区在线视频 | 日韩成人免费观看 | 成人免费毛片入口 | 青草热视频 | 日韩欧美成人一区 | 午夜tv影院 | av色图在线 | 国产精品乱码一区二区视频 | 2019国产在线| 污视频免费在线观看网站 | 日韩精品成人一区二区在线 | 日韩av在线看 | 男女污污软件 | 超碰成人免费 | 国产一二三四五区 | 国产高清av | 北条麻妃久久精品 | 深夜福利免费视频 | 妓院一钑片免看黄大片 | 日韩精品视频网站 | av激情在线 | 欧美色啪 | av在线一区二区三区 | 亚洲三级色 | 女人被狂躁c到高潮 | 天堂网中文在线观看 | 护士的小嫩嫩好紧好爽 | 福利片在线看 | 日本免费一级片 | 成人黄色激情 | 99久久久无码国产精品性色戒 | 蜜臀少妇久久久久久久高潮 | 大地资源二中文在线影视观看 | 成人在线视频免费 | 91免费国产| 天天舔天天插 | 欧美一区二区三区在线播放 | 日本激情小视频 | 免费在线观看污 | 国产99视频在线 | 国产粉嫩呻吟一区二区三区 | 亚洲美女视频在线观看 | av伦理在线 | 国产高清露脸 | 精品人伦一区二区三区蜜桃网站 | а√天堂资源在线 | 在线免费视频你懂的 | 欧美激情久久久久 | 一级黄色片免费播放 | 久久五月激情 | 91九色国产 | 能免费看18视频网站 | av动漫天堂 | 9999精品 | 一区二区三区视频免费在线观看 | 男人av在线| 欧美污视频在线观看 | 福利在线网站 | 成人精品一区二区三区 | 久久精品无码一区二区三区毛片 | 免费播放av| 超碰免费观看 | 欧美少妇xx | 影音先锋伦理片 | 樱井莉亚av | 久草免费资源 | 国产伦精品视频一区二区三区 | 99免费在线视频 |