1 / 36

應用程式

應用程式. 我們學習程式設計就是希望使用電腦,將電腦當成一個有效的工具,當成一個忠實的僕人,能幫我們解決一些問題,您可能會想到底那些問題可請電腦解決呢?一般來講,很難的計算問題,很繁(煩)的問題,需要電腦提醒的問題等等,幾乎您能想到的問題都可請電腦幫您處理。 電腦怎樣處理您的問體呢?因為它是一個僕人,聽命於主人的您,您下達一個指令它就幫您執行這個指令,您再下達另一個指令它就幫您執行另一個指令,您若不下達指令它也就無從執行,而賦閒休息了。.

Download Presentation

應用程式

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 應用程式 • 我們學習程式設計就是希望使用電腦,將電腦當成一個有效的工具,當成一個忠實的僕人,能幫我們解決一些問題,您可能會想到底那些問題可請電腦解決呢?一般來講,很難的計算問題,很繁(煩)的問題,需要電腦提醒的問題等等,幾乎您能想到的問題都可請電腦幫您處理。 • 電腦怎樣處理您的問體呢?因為它是一個僕人,聽命於主人的您,您下達一個指令它就幫您執行這個指令,您再下達另一個指令它就幫您執行另一個指令,您若不下達指令它也就無從執行,而賦閒休息了。 正修科技大學計算機中心

  2. 這些您所下達的指令集合起來就稱為一個程式。您使用 C 語言下達指令的集合稱為 C 語言原始程式(source program),原始程式是人們看得懂的程式,但電腦看不懂,看不懂的指令當然就無法執行了,必須請人翻譯成電腦看得懂的指令才行,負責翻譯的程式稱為編譯器(compiler),電腦看得懂的指令所構成的程式稱為目的程式(object program),所以電腦所執行的是目的程式。 本章就舉幾個日常生活上會碰到的問題,說明如何請電腦幫我們解決。 正修科技大學計算機中心

  3. 13.1 二月平均日溫 • 我們想了解高雄市在西元 2005 年 2 月的每日平均溫度幾度?這個資料我們可以上氣象局的網站查一查就可了解。我們查到的是如下的一張圖: • 紅色的曲線表示「日均溫」,左邊的垂直軸表示攝氏溫度刻度,水平向右的軸線表示「日數」,我們用目視法製成如下的資料表: 正修科技大學計算機中心

  4. 表 13.1 高雄站二月日均溫 日數 日均溫(攝氏溫度) ------ -------------------------- 1 16.5 3 18.0 5 22.5 7 24.0 9 22.5 11 20.5 13 19.0 15 21.0 17 26.0 19 17.0 21 13.0 23 22.0 25 23.0 27 21.0 28 18.0 正修科技大學計算機中心

  5. 現在我們要利用這些資料,設計一個查詢程式,您從鍵盤輸入一個日數,電腦就回應給您一個高雄市 2005 年 2 月當日的平均溫度。 我們可以將上表設計成兩個一維陣列,「日數」設計成一維陣列 days,包含 15 個元素,每個元素均為整數 int,如下: int days[15] = {1,3,5,7,9,11,13,15,17,19,21,23,25,27,28}; 「日均溫(攝氏溫度)」設計成一維陣列 degs,包含 15 個元素,每個元素均為浮點數 float,如下: float degs[15] = {16.5, 18.0, 22.5, 24.0, 22.5, 20.5, 19.0, 21.0, 26.0, 17.0, 13.0, 22.0, 23.0, 21.0, 18.0}; 正修科技大學計算機中心

  6. 當我們從鍵盤輸入一個日數,取名為 day,例如您輸入 13,也就是說變數 day 的值為 13。然後 day 與 days 陣列裡的每一個元素比較,分別比較 days[0]、days[1]、days[2]、...、days[14],結果在 days[6] 找到,那麼在 degs 陣列的相對位置 degs[6] 就是我們要的日均溫 19.0 攝氏度。 但若您從鍵盤輸入一個日數 14 又如何?14 在 days 陣列從頭到尾都找不到,那怎麼辦呢?因為表中只有 13 日及 15 日的日均溫,並沒有 14 日的日均溫,這時可用內插法求出: 14日的日均溫 = (13日的日均溫 + 15日的日均溫) / 2 = (19.0 + 21.0) / 2 = 20.0 因此可得 14 日的日均溫為 20.0 攝氏度。 正修科技大學計算機中心

  7. 二月日均 溫流程圖 正修科技大學計算機中心

  8. 程式 daydeg.c 從鍵盤輸入一個日數 day,必須在 1 至 28 之間才合乎規定,若不在此範圍就必須從新輸入,一直到合乎規定程式才會往下執行的,這是保護您獲得正確答案的一個措施,否則若輸入 31,因為二月份根本沒有 31 日,顯然不合理,萬一您接受此 31 日,您的程式根本無法執行。 您設計的檢查條件可以這樣寫: day<1 || day>28 符合這個條件表示您輸入的日數 day 是錯誤的。 正修科技大學計算機中心

  9. 您設計的檢查條件可以這樣寫: day<1 || day>28 符合這個條件表示您輸入的日數 day 是錯誤的。可是這樣寫就缺乏彈性了,因為只有二月份才有 28 天,若三月四月又如何?這時您可利用陣列的特性,直接指明陣列 days[] 的最後一個元素值,days[] 陣列的元素個數可透過 sizeof(days) 取得,本例題其值為 15,從零算起最後一個就是第十四個,以 sizeof(days)/sizeof(int)-1 表示,因此條件可改寫如下: day<days[0] || day>days[sizeof(days)/sizeof(int)-1] 您所輸入的日數 day 輪番在 days 陣列找尋,找到時就跳出迴圈,輸出答案,找不到時就用內插法計算日均溫後輸出。 正修科技大學計算機中心

  10. 【程式daydeg.c執行結果】 請輸入一個二月份日數(1-28): 13 <Enter> i=0 days[i]= 1 degs[i]=16.5 i=1 days[i]= 3 degs[i]=18.0 i=2 days[i]= 5 degs[i]=22.5 i=3 days[i]= 7 degs[i]=24.0 i=4 days[i]= 9 degs[i]=22.5 i=5 days[i]=11 degs[i]=20.5 i=6 days[i]=13 degs[i]=19.0 二月13日的日均溫為 19.0 攝氏度 【程式daydeg.c執行結果】 請輸入一個二月份日數(1-28): 14 <Enter> i=0 days[i]= 1 degs[i]=16.5 i=1 days[i]= 3 degs[i]=18.0 i=2 days[i]= 5 degs[i]=22.5 i=3 days[i]= 7 degs[i]=24.0 i=4 days[i]= 9 degs[i]=22.5 i=5 days[i]=11 degs[i]=20.5 i=6 days[i]=13 degs[i]=19.0 i=7 days[i]=15 degs[i]=21.0 二月14日的日均溫為 20.0 攝氏度 正修科技大學計算機中心

  11. 13.2 求函數的根 • 二月日均溫的例題 daydeg.c 是在一個表格裡找尋資料,但在商業或工程方面常常要從一條已知的曲線(函數)求出滿足條件的值。例如有一顆球從一百公尺高的地方自由落下,球因為受到地心引力 g 的影響,愈接近地面它的速度愈快,距離 s 與時間 t 以及地球重力加速度 g 的關係如下所示: 時間 t 以秒計,地球重力加速度 g 為 9.8 每秒每秒公尺計算,因此距離 s 的單位就是公尺了。 正修科技大學計算機中心

  12. 我們將此曲線繪製圖形,水平座標為時間 t 座標,垂直座標為距離 s 座標,向下為正方向,時間 t 為 0 時,距離 s 的值為 0,原點座標為 (0,0) 。請問距離為 100 時 t 的值為何? s = 0.5 * g * t * t [註]「*」表示乘法 100 = 0.5 * 9.8 * t * t 相當於如下的函數 f(t): f(t) = 0.5*9.8*t*t - 100 = 0 我們只要求出一個 t 滿足 f(t)=0 就可以了,可以設計如下的函式: double f(double t) { return (0.5*9.8*t*t-100.0); } 已知一個參數 t 值,傳回 (0.5*9.8*t*t-100.0) 函式值。 正修科技大學計算機中心

  13. 我們可設計一個簡單的程式對於 f(t) 函數取幾個點看看,t 從 0 變化至 9 每次增加 1,看看 f(t) 值的變化如何? 從 balldrop.c 執行結果可以看出當 t=4 時 f(t) 函數值為負數 -21.6,但當 t=5 時函數 f(t) 值為正數 22.5,可見 t 在 4 與 5 之間有某一個值可以滿足函數 f(t)=0 的條件,這個 t 就是我們所要的時間。 正修科技大學計算機中心

  14. 【程式balldrop.c】 /******************* balldrop.c ********************/ #include <stdio.h> double f(double t) { return (0.5*9.8*t*t-100.0); } int main() { int i; for (i=0; i<10; i++) printf("t=%d f(t)=%6.1f\n", i, f((double)i)); return 0; } 【執行結果】 t=0 f(t)=-100.0 t=1 f(t)= -95.1 t=2 f(t)= -80.4 t=3 f(t)= -55.9 t=4 f(t)= -21.6 t=5 f(t)= 22.5 t=6 f(t)= 76.4 t=7 f(t)= 140.1 t=8 f(t)= 213.6 t=9 f(t)= 296.9 正修科技大學計算機中心

  15. 計算球落地 秒數流程圖 正修科技大學計算機中心

  16. 既然知道 t 在 4 與 5 之間有某一個值可以滿足函數 f(t)=0 的條件,這個 t 就是我們所要的秒數,問題是您想求到小數幾位呢?就求到小數四位吧,設第一個時間為 t1 其值為 4,第二個時間為 t2,每次增加 dt=0.0001,也就是將 t 在 4 與 5 之間劃分一萬個小格,每一個小格的距離 0.0001,這個值在我們的程式裡稱為 dt,d 是 delta 很小的意思,t 是 time 時間的意思,dt 是很小時間增量的意思,「0.0001」也就是萬分之一秒。 當時間 t1 時,它的函數值為 f1=f(t1),當時間 t2 時,它的函數值為 f2=f(t2),我們只要判斷 f1 的符號是否與 f2 的符號相異(一個負號,另一個正號),若是相異則表示 t 在 t1 與 t2 的中間,計算 (t1+t2)/2 就是我們要的秒數。 正修科技大學計算機中心

  17. 【程式droptime.c】 /******************** droptime.c *****************/ #include <stdio.h> double f(double t) { return (0.5*9.8*t*t-100.0); } int main() { double t1=4, dt=1.0/10000, t2=t1+dt, f1, f2; int step = 1; f1 = f(t1); f2 = f(t2); while (f2*f1>0.0) { t1 = t2; f1 = f2; t2 = t1 + dt; f2 = f(t2); step++; } printf("經 %7.5f 秒後球落地, 共走 %d 步.\n", (t1+t2)/2, step); return 0; } 【執行結果】 經 4.51755 秒後球落地, 共走 5176 步. 正修科技大學計算機中心

  18. 13.3 二分搜尋法 • 前面的例題,動不動都要執行幾千步,甚或執行幾萬步,有沒有更先進的方法只要執行幾步,或幾十步就可找到答案的呢?我們在第七章介紹過一個二分搜尋法,針對陣列搜尋,現在我們要將它應用來找函數的根。 • 現在我們來看另一個題目,求滿足 f(x)=x*x*x-3*x+1=0 的 x 值。我們用目視法可知 f(0)=1,f(1)=-1,f(0)*f(1)<0,也了解 x 在 0 與 1 之間有一個值滿足 f(x)=x*x*x-3*x+1=0 的條件,它就是我們要找的根,左邊的界限稱為 xl,右邊的界線稱為 xr,中間的稱為 xm=(xl+xr)/2 是左右邊的平均值。現在的起步是 xl=0,xr=1,計算出 xm=(0+1)/2=0.5,我們想求到小數六位,為很小的值稱為 eps,它的值為 0.000001。 • 現在我們要來設計一個程式,為了保持彈性將這三個值 xl、xr、eps 從鍵盤輸入。程式的流程圖如下所示。 正修科技大學計算機中心

  19. 流程圖 findroot 求滿足 f(x)=x*x*x-3*x+1=0 的x值 正修科技大學計算機中心

  20. 執行 findroot.c 程式時,已知在 xl=0.0 與 xr=1.0 之間有根,就猜其中點 xm=(xl+xr)/2=0.5。 正修科技大學計算機中心

  21. 這時 f(0.5) 與 f(1.0) 同為負號,我們的目標不在 0.5 與 1.0 之間,遂將新的右邊界移到中點 0.5 之處,也就是新的 xr=0.5,這時 xl 左邊界的值仍為 0.0,如此範圍已經縮小一半了。 正修科技大學計算機中心

  22. 跟據 xl=0.0 與 xr=0.5 計算一個新中點 xm=(0.0+0.5)/2=0,25,這時函數值 f(0.25) 與 f(0) 同為正號,我們的目標不在 0.0 與 0.25 之間。遂將新的左邊界移到中點 0.25 之處,也就是新的 xl=0.25,這時 xr 右邊界的值仍為 0.5,如此範圍又縮小一半了,只剩下原來的四分之一了。 正修科技大學計算機中心

  23. 同樣的步驟繼續進行,不是拋掉右邊一半,就是拋掉左邊一半,範圍成等比級數縮小,速度相當快,求至小數六位只需猜二十次就可得答案了。最後的答案 xm=0.3472967,滿足 f(0.3472967)=0。 正修科技大學計算機中心

  24. /********************* findroot.c ******************/ #include <stdio.h> double f(double x) { return (x*x*x-3.0*x+1.0); } int main() { double xl, xr, xm, eps; int step=0; printf("請輸入 xl,xr,eps (0 1 0.000001) : "); scanf("%lf %lf %lf", &xl,&xr,&eps); do { xm = (xl+xr)/2.0; step++; printf("xm=%8.6f f(xm)=%10.6f\n", xm, f(xm)); if (f(xm)*f(xl)>0) xl=xm; if (f(xm)*f(xr)>0) xr=xm; } while (xr-xl>eps && f(xm)!=0.0); printf("xm=%9.7lf 共執行 %d 次.\n", xm, step); return 0; } 正修科技大學計算機中心

  25. 【執行結果】 請輸入 xl,xr,eps : 0 1 0.000001 <Enter> xm=0.500000 f(xm)= -0.375000 xm=0.250000 f(xm)= 0.265625 xm=0.375000 f(xm)= -0.072266 xm=0.312500 f(xm)= 0.093018 xm=0.343750 f(xm)= 0.009369 xm=0.359375 f(xm)= -0.031712 xm=0.351563 f(xm)= -0.011236 xm=0.347656 f(xm)= -0.000949 xm=0.345703 f(xm)= 0.004206 xm=0.346680 f(xm)= 0.001627 xm=0.347168 f(xm)= 0.000339 xm=0.347412 f(xm)= -0.000305 xm=0.347290 f(xm)= 0.000017 xm=0.347351 f(xm)= -0.000144 xm=0.347321 f(xm)= -0.000064 xm=0.347305 f(xm)= -0.000024 xm=0.347298 f(xm)= -0.000003 xm=0.347294 f(xm)= 0.000007 xm=0.347296 f(xm)= 0.000002 xm=0.347297 f(xm)= -0.000001 xm=0.3472967 共執行 20 次. 正修科技大學計算機中心

  26. 13.4 輸出日期及時間 • 我們在日常生活裡常常會用到日期與時間,電腦輸出的報表也免不了註記日期及時間,因此如何使用函式庫裡有關日期及時間的函式顯得特別重要。因此先要了解有那些工具可以使用。 • 有關日期及時間的型態(type)及函式均存於 include 目錄 time.h 檔案裡,首先讓我們來了解幾個型態。 • 資料型態 time_t 定義於 time.h 表頭檔,它屬於算術型態,用來表示日曆時間,透過 time() 函式取得時間,函式 localtime() 及 gmtime() 也都使用 time_t 型態的變數取得時間的。ctime() 函式更是使用 time_t 型態的變數取得日期與時間的。 正修科技大學計算機中心

  27. 但 localtime() 及 gmtime() 函式傳回來的卻是 tm 的結構,tm 定義於表頭檔 time.h 裡,以 gcc 編譯器為例,tm 結構定義如下: struct tm { int tm_sec; /*秒(0-59)*/ int tm_min; /*分(0-59)*/ int tm_hour; /*時(0-23), 0表午夜*/ int tm_mday; /*日(1-31)*/ int tm_mon; /*月(0-11), 0表一月*/ int tm_year; /*年(目前之年數-1900)*/ int tm_wday; /*星期日數(0-6, 0為星期日)*/ int tm_yday; /*一年中日數(0-365, 元月一日為0)*/ int tm_isdst; /*日光節約時間為非0,否則為0*/ char *__tm_zone; /*時區*/ int __tm_gmtoff; }; 正修科技大學計算機中心

  28. 在 gmtime.c 程式裡我們設計一個 getdatetime() 函式,因為我們想提供給其他的程式使用,設計成函式比較方便使用,dt 必須最少 36 個字元的陣列才行,本例題宣告為八十個字元的陣列,其前冠上 static 關鍵字,是想離開函式後 dt 仍然存在才能構傳回給呼叫者。 char *getdatetime() { static char dt[80]; time_t now; time(&now); strftime(dt,36,"格林威治時間 %Y/%m/%d %H:%M:%S\n", gmtime(&now)); return dt; } 呼叫 time() 函式取得目前時間存入 now 變數,再透過 strftime() 函式將所取得的時間格式化後存入 dt 陣列傳回。 正修科技大學計算機中心

  29. 【程式gmtime.c】 /*********************** gmtime.c ******************/ #include <stdio.h> #include <stdlib.h> #include <time.h> char *getdatetime() { static char dt[80]; time_t now; time(&now); strftime(dt,36,"格林威治時間 %Y/%m/%d %H:%M:%S\n", gmtime(&now)); return dt; } int main(void) { printf(getdatetime()); return 0; } 【執行結果】 格林威治時間 2005/03/18 06:17:58 正修科技大學計算機中心

  30. 程式 gmtime.c 所輸出的時間為英國格林威治時間,是世界上的標準時間,但地球經度每十五度就相差一個小時,以台灣地區而言,台灣在英國的東方,較英國早八個小時看到太陽,因此格林威治時間必需加上八小時才是中原標準時間,執行結果 06:17:58 在台灣應該 14:17:58 才對。您自己去調整時間也未嘗不可,但何不用現成的 localtime() 函數以取代 gmtime() 函式呢? 將 gmtime.c 程式稍做修改,以輸出當地時間,如 localtime.c 所示。 正修科技大學計算機中心

  31. 【程式localtime.c】 /**************** localtime.c *************/ #include <stdio.h> #include <stdlib.h> #include <time.h> char *getdatetime() { static char dt[80]; time_t now; time(&now); strftime(dt,36,"%Y/%m/%d %H:%M:%S\n", localtime(&now)); return dt; } int main(void) { printf(getdatetime()); return 0; } 【執行結果】 2005/03/18 14:42:00 正修科技大學計算機中心

  32. 13.5 解聯立方程式 • 聯立方程式計算起來很費力又費時,最適合借助電腦了,但您要將解法告訴電腦才行,我們先舉一個簡單的例子,一步一步解出來,再寫程式告訴電腦。 • x1 + 2 x2 = 13 ---------- (1) • x1 - 3 x2 = 3 ---------- (2) • 上面是一個二元聯立方程式,兩個變數 x1 及 x2,將其係數命名為 A 矩陣(matrix),是二列二行的矩陣,將變數命名為 X 矩陣,二列一行,將等號右邊的係數命名為 B 矩陣,二列一行,可改寫如下:A 的反矩陣乘上 B 可得 X。 正修科技大學計算機中心

  33. 正修科技大學計算機中心

  34. 正修科技大學計算機中心

  35. 【程式inverse.c執行結果】 x[0]=9.000000 x[1]=2.000000 正修科技大學計算機中心

  36. 您要求解其他的聯立方程式,只需修改三個值,N、a、b,然後重新編譯後再執行就可以了。例如您要解下列的聯立方程式: 8 x1 + 2 x2 + 3 x3 = 30 ----------- (1) x1 - 9 x2 + 2 x3 = 1 ----------- (2) 2 x1 + 3 x2 + 6 x3 = 31 ----------- (3) 您只需修改: #define N 3 double a[N][N]={{8,2,3},{1,-9,2},{2,3,6}}; double b[N]={30,1,31}; 重新編譯後,執行結果如下: x[0]=2.000000 x[1]=1.000000 x[2]=4.000000 正修科技大學計算機中心

More Related