105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 1 程式設計實驗 08 陣列與向量 研討問題 05 5.1 使用 call by value 和 call by reference 進行函式呼叫有何差異? 請舉例說明, 為何 swap() 函式必須使用 call by reference 可以有效地將傳入參數的內容互換 ; 而 call by value 則無法達成 5.2 使用 rand() 函式來產生任意 30 個亂數, 並觀察其是否在每次主程式重新執行後亂數產生的順序都會一樣? 若是, 你會如何改善這個問題 5.3 在課堂上老師已經講解了有關選擇排序 (selection sort) 的演算過程, 並以微笑曲線代表對兩個陣列元素進行比較後決定是否執行 swap 運算 假設排序的元素個數為 n, 則選擇排序的微笑曲線數為 n(n-1)/2, 亦即進行比較的次數為 n(n-1)/2 已知 time() 函式可以取得系統時間, 你要如何利用 time() 函式來統計當 n 分別為 100 200 300 時, 電腦執行選擇排序所花費的時間關係 程式設計實驗 8.1: 使用亂數產生器模擬擲同時兩個骰子 提示 1: 使用 MIT App Inventor 設計, 參考以下 UI 設計及 Blocks MIT App Inventor 網址 :http://ai2.appinventor.mit.edu/
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 2 提示 2: 使用 Dev C++ 設計, 參考以下 C++ 程式碼及輸出畫面 // dice.cpp #include <ctime> int dice1, dice2; srand(time(0)); dice1=1 + rand()%6; dice2=1 + rand()%6; cout<<dice1<<" "<<dice2<<endl; system("pause"); return 0; 提示 3: 使用 #develop 設計 SharpDevelop 5 下載網址 :http://www.icsharpcode.net/opensource/sd/download/ 程式設計實驗 8.2: 使用亂數產生器模擬同時擲兩個骰子 100 萬次, 並統計點數和為 2 3 以及 12 出 現的機率 提示 : 參考以下 C++ 程式碼及輸出畫面 // dice_statistic.cpp #include <ctime> #include <cstdlib> int dice1, dice2; int fq[13]=0; srand(time(0));
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 3 for (int i=0; i<1000000; i++) dice1=1 + rand()%6; dice2=1 + rand()%6; fq[dice1+dice2]++; for (int i=2;i<13;i++) cout<<i<<": "<<fq[i]/1000000.0<<endl; system("pause"); return 0; 程式設計實驗 8.3: 使用選擇排序法, 自行定義一個可以將一維整數陣列的元素從小排到大的函式 提示 : 參考以下 C++ 程式碼及輸出畫面 // selection_sort.cpp #include <cstdlib> void selection_sort(int x[], int n) for (int i=0; i<n; i++) for (int j=i+1; j<n; j++) if (x[i]>x[j]) swap(x[i], x[j]); int A[]=7, 35, 40, 19, 13; for (int i=0;i<5;i++) cout<<a[i]<< " "; selection_sort(a, 5); cout<<"after calling selection_sort(a, 5):\n"; for (int i=0;i<5;i++) cout<<a[i]<< " "; system("pause"); return 0; 程式設計實驗 8.4: 使用泡沫排序法, 自行定義一個可以將一維整數陣列的元素從大排到小的函式 提示 : 參考以下 C++ 程式碼及輸出畫面 // bubble_sort.cpp #include <cstdlib> void bubble_sort (int x[ ], int n) for (int i=0;i<n-1;i++) for (int j=0;j<n-1-i;j++) if (x[ j+1]<x[j]) swap(x[j], x[ j+1]); int A[]=7, 35, 40, 19, 13; for (int i=0;i<5;i++) cout<<a[i]<< " ";
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 4 bubble_sort(a, 5); cout<<"after calling bubble_sort(a, 5):\n"; for (int i=0;i<5;i++) cout<<a[i]<< " "; system("pause"); return 0; 程式設計實驗 8.5: 自行定義一個可以將 n n 矩陣加以轉置的函式 提示 : 參考以下 C++ 程式碼及輸出畫面 // transpose.cpp void transpose(int x[][3], int n) for (int i=0;i<n;i++) for (int j=i+1;j<n;j++) swap(x[i][j], x[j][i]); int A[][3]= 1,1,1, 0,1,1, 0,0,1 ; for (int i=0;i<3;i++) for (int j=0;j<3;j++) cout<<a[i][j]<< " "; transpose(a, 3); cout<<"after calling transpose(a, 3):\n"; for (int i=0;i<3;i++) for (int j=0;j<3;j++) cout<<a[i][j]<< " "; system("pause"); return 0; 程式設計實驗 8.6: 使用 vector 向量物件, 重新定義程式設計實驗 8.4 的泡沫排序函式 提示 : 參考以下 C++ 程式碼及輸出畫面 // vector.cpp #include <vector> void bubblesort(vector<int>& x) for (int i=0; i < x.size()-1; i++) for (int j=0; j < x.size()-1-i; j++) if ( x[j+1] < x[j] ) swap(x[j], x[j+1]); vector<int> x(5); for(int i=0; i<x.size(); i++) cin>>x[i]; bubblesort(x); for(int i=0; i<x.size(); i++) cout<<x[i]<< " ";
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 5 system("pause"); return 0; 程式設計實驗 8.7: 讀取實驗 06 產生的成績檔, 載入成績物件後, 應用 C++ Vector 物件或 C# 陣列 物件加以排序, 並顯示排名及成績分布情形 提示 1: 使用 Dev C++ 設計, 參考以下 C++ 程式碼及輸出畫面 #include <iomanip> #include <fstream> #include <vector> class Score public: char name[9]; int programming; int economics; int mis; double average; int rank; ; void swap(score &x, Score &y) Score tmp=x; x=y; y=tmp; void selectionsort(vector<score> &, int, bool); void bubblesort(vector<score> &, int, bool); // int dist[10]=0;. vector<score> grade(50); double max=0, min=100; ifstream fin("grade.csv", ios::in); if (!fin) cout<<" 檔案開啟失敗 "<<endl; else char sentence[81]; fin.getline(sentence, 81, '\n'); double sum=0; int n=0; do fin.getline(grade[n].name,9,','); fin>>grade[n].programming; fin.get(); fin>>grade[n].economics; fin.get(); fin>>grade[n].mis; grade[n].average=(grade[n].programming+grade[n].economics+grade[n].mis)/3.0; if (grade[n].average>max) max = grade[n].average;
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 6 if (grade[n].average<min) min = grade[n].average; sum+=grade[n].average; if (grade[n].average>=90) dist[9]++; else if (grade[n].average>=80) dist[8]++; else if (grade[n].average>=70) dist[7]++; else if (grade[n].average>=60) dist[6]++; else if (grade[n].average>=50) dist[5]++; else if (grade[n].average>=40) dist[4]++; else if (grade[n].average>=30) dist[3]++; else if (grade[n].average>=20) dist[2]++; else if (grade[n].average>=10) dist[1]++; else if (grade[n].average>=0) dist[0]++; n++; while(fin.get()!=eof); fin.close(); cout<<endl<<endl; cout<<"n: "<<n<<endl; cout<<"avg: "<<fixed<<setprecision(2)<<(sum/n)<<endl; cout<<"max: "<<max<<" "<<"Min: "<<min<<endl; cout<<endl<<"-------------------"<<endl; for (int i=9;i>=0;i-=1) cout<<i*10<<"-"<<(i*10+9)<<": "<<dist[i]<<endl; cout<<"-------------------"<<endl; for (int i=0;i<n;i++) cout<<grade[i].name<<" "<<grade[i].programming<<" " <<grade[i].economics<<" "<<grade[i].mis<<endl; selectionsort(grade, 2, false); int k=1; grade[0].rank=k; for (int i=1;i<n;i++) if (grade[i].average < grade[i-1].average) k=i+1; grade[i].rank=k; bubblesort(grade, 1, true); char *strptr; strptr=strtok(sentence,","); while(strptr!=null) cout<<" "<<strptr; strptr=strtok(null,","); cout<<" 總平均名次 \n" <<"---------------------------------------------------------"<<endl; for (int i=0;i<n;i++) cout<<grade[i].name<<" "<<grade[i].programming<<" " <<grade[i].economics<<" "<<grade[i].mis <<" "<<fixed<<setprecision(2)<<grade[i].average <<" "<<grade[i].rank<<endl; cout<<"---------------------------------------------------------"<<endl;
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 7 system("pause"); return 0; void selectionsort(vector<score> &x, int field, bool ascending) cout<<"selectionsort()..."<<endl; for (int i=0;i<x.size()-1;i++) for (int j=i+1;j<x.size();j++) switch(field) case 1: if (ascending) if (strcmp(x[i].name, x[j].name)>0) swap(x[i], x[j]); else if (strcmp(x[i].name, x[j].name)<0) swap(x[i], x[j]); break; case 2: if (ascending) if (x[i].average > x[j].average) swap(x[i], x[j]); else if (x[i].average < x[ j].average) swap(x[i], x[j]); break; void bubblesort(vector<score> &x, int field, bool ascending) cout<<"bubblesort()..."<<endl; for (int i=0;i<x.size()-1;i++) for (int j=0;j<x.size()-i-1;j++) switch(field) case 1: if (ascending) if (strcmp(x[j].name, x[j+1].name)>0) swap(x[j], x[j+1]); else if (strcmp(x[j].name, x[j+1].name)<0) swap(x[j], x[j+1]); break; case 2: if (ascending) if (x[j].average > x[j+1].average) swap(x[j], x[j+1]); else if (x[j].average < x[j+1].average) swap(x[j], x[j+1]); break; 使用 Dev-C++ 進行編譯執行後, 觀察結果 :
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 8 創作指引 : 本模擬問題基礎程式尚未提供個人成績查詢功能, 請規劃並分析如何增加個人成績查詢功 能? 提示 2: 使用 #develop 設計, 參考以下 UI 設計 C# 程式碼 及輸出畫面 SharpDevelop 5 下載網址 :http://www.icsharpcode.net/opensource/sd/download/ 應用 C# 陣列物件加以排序, 並利用視窗元件顯示排名及成績分布情形 建立 C# Windows Application 專案 :GradeManagement 新增 Score 類別 :Score.cs // 自行定義 Score 類別 :Score.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GradeManagement class Score public static string title_id set; get; public static string title_name set; get; public static string title_computer set; get; public static string title_programming set; get; public static string title_accounting set; get; public static string title_economics set; get; public static string title_calculus set; get; public static string title_average set; get; public static string title_rank set; get;
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 9 public string id set; get; public string name set; get; public int computer set; get; public int programming set; get; public int accounting set; get; public int economics set; get; public int calculus set; get; public double average set; get; public int rank set; get; public Score(string aid, string aname, int acomputer, int aprogramming, int aaccounting, int aeconomics, int acalculus) id = aid; name = aname; computer = acomputer; programming = aprogramming; accounting = aaccounting; economics = aeconomics; calculus = acalculus; average = (acomputer + aprogramming + aaccounting + aeconomics + acalculus) / 5.0; rank = -1; 設計主表單 Form1 類別 :Form1.cs(SharpDevelop 預設名稱為 MainForm) // C# 表單類別 :Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace GradeManagement public partial class Form1 : Form public Form1() InitializeComponent(); private StreamReader reader; private Score[] grade = new Score[50]; private void showtitle() textbox2.clear(); string title = String.Format("0,-14 1,-8 2,-2 3,-2 4,-2 5,-3 6,-3 7,-3 8,-2\n", Score.title_id, Score.title_name, Score.title_computer, Score.title_programming, Score.title_accounting, Score.title_economics, Score.title_calculus, Score.title_average, Score.title_rank); textbox2.text += title + Environment.NewLine; private void button1_click(object sender, EventArgs e)
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 10 try reader = new StreamReader(File.OpenRead(textBox1.Text), Encoding.Default); // 顯示中文 Encoding.Default textbox2.clear(); string line = reader.readline(); char[] seps = ','; string[] linetokens = line.split(seps); textbox2.text += line + Environment.NewLine; Score.title_id = linetokens[0]; Score.title_name = linetokens[1]; Score.title_computer = linetokens[2]; Score.title_programming = linetokens[3]; Score.title_accounting = linetokens[4]; Score.title_economics = linetokens[5]; Score.title_calculus = linetokens[6]; Score.title_average = " 平均 "; Score.title_rank = " 排名 "; int n=0; while(!reader.endofstream) line = reader.readline(); textbox2.text += line + Environment.NewLine; linetokens = line.split(seps); grade[n] = new Score( linetokens[0], linetokens[1], Int32.Parse(lineTokens[2]), Int32.Parse(lineTokens[3]), Int32.Parse(lineTokens[4]), Int32.Parse(lineTokens[5]), Int32.Parse(lineTokens[6])); n++; reader.close(); catch (Exception ee) textbox2.text = ee.tostring(); private void button2_click(object sender, EventArgs e) if (reader == null) textbox2.text = " 請先讀取成績檔案 "; else showtitle(); for (int i = 0; i < grade.length; i++) string line = String.Format( "0,-8 1,-6 2:### 3:### 4:### 5:### 6:### 7:###.0", grade[i].id, grade[i].name, grade[i].computer, grade[i].programming, grade[i].accounting, grade[i].economics, grade[i].calculus, grade[i].average); textbox2.text += line + Environment.NewLine;
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 11 private void button3_click(object sender, EventArgs e) if (reader == null) textbox2.text = " 請先讀取成績檔案 "; else Array.Sort(grade, delegate(score score1, Score score2) // 由大排到小 (score2.average - score1.average) return score2.average.compareto(score1.average); ); int k = 1; grade[0].rank = k; for (int i = 1; i < grade.length; i++) if (grade[i].average < grade[i - 1].average) k = i + 1; grade[i].rank = k; Array.Sort(grade, delegate(score score1, Score score2) return score1.id.compareto(score2.id); // 由小排到大 (score1.id - score2.id) ); showtitle(); for (int i = 0; i < grade.length; i++) string line = String.Format( "0,-8 1,-6 2:### 3:### 4:### 5:### 6:### 7:###.0 8:###", grade[i].id, grade[i].name, grade[i].computer, grade[i].programming, grade[i].accounting, grade[i].economics, grade[i].calculus, grade[i].average, grade[i].rank); textbox2.text += line + Environment.NewLine; private void button4_click(object sender, EventArgs e) if (reader == null) textbox2.text = " 請先讀取成績檔案 "; else double max = 0, min = 100; double sum = 0, average = 0; int[] dist = new int[10] 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; for (int i = 0; i < grade.length; i++) if (grade[i].average > max) max = grade[i].average; if (grade[i].average < min) min = grade[i].average; sum += grade[i].average; if (grade[i].average >= 90) dist[9]++; else if (grade[i].average >= 80) dist[8]++; else if (grade[i].average >= 70) dist[7]++; else if (grade[i].average >= 60) dist[6]++; else if (grade[i].average >= 50) dist[5]++; average = sum / grade.length; textbox2.clear(); textbox2.text += " 班級平均 :" + average + Environment.NewLine; textbox2.text += " 最高分 :" + max + Environment.NewLine; textbox2.text += " 最低分 :" + min + Environment.NewLine;
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 12 for (int i = 9; i >= 0; i -= 1) textbox2.text += i * 10 + "-" + (i * 10 + 9) + ": " + dist[i] + Environment.NewLine; private void timer1_tick(object sender, EventArgs e) label2.text = DateTime.Now.ToString(); private void Form1_Load(object sender, EventArgs e) timer1.enabled = true; 觀察主程式 Program 類別 :Program.cs // C# 主程式類別 :Program.cs using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace GradeManagement static class Program /// <summary> /// 應用程式的主要進入點 /// </summary> [STAThread] static void Main() Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); 使用 Visual Studio 2012 或 Sharp Develop 進行編譯執行後, 觀察結果 :
105A 資管一程式設計實驗 08 陣列與向量謝明哲老師 hmz@nttu.edu.tw 13 創作指引 : 本模擬問題基礎程式尚未提供個人成績查詢功能, 請規劃並分析如何增加個人成績查詢功能 使用工具箱提供的 OpenFileDialog 元件提高成績檔案名稱輸入的使用性 使用工具箱提供的 ReportViewer 元件顯示成績分布統計圖