第一篇:C++課程設(shè)計報告--矩陣乘法計算
C++課程設(shè)計報告
一、題目名稱:矩陣乘法計算
二、難易等級: A級
三、對題目的分析和注釋:
分析:
依次建立兩個矩陣空間并按照矩陣乘法規(guī)則進行運算。(矩陣的乘法規(guī)則:
1、矩陣的乘法運算必須符合m*n的矩陣與n*s的矩陣相乘。
2、第一個矩陣的第i行的元素依次乘以第二個矩陣的第j列元素后結(jié)果相加組成生成矩陣第i行第j列元素。)
注釋:
(1)設(shè)計一個矩陣類,將相應(yīng)的函數(shù)和數(shù)據(jù)封裝在類中,簡化程序。
(2)修改程序結(jié)構(gòu),使程序可以反復執(zhí)行,直至按鍵選擇退出為止。
(3)本程序用數(shù)組表示5*5矩陣,將其改為根據(jù)輸入矩陣的大小動態(tài)分配空間[m][n]來放置數(shù)據(jù),其中m,n為用戶可輸入的任意整數(shù)。
(4)增加類的構(gòu)造函數(shù)和成員函數(shù),使得矩陣數(shù)據(jù)既可以用在對象初始化時賦值,也可以通過鍵盤賦值,還可以通過讀取數(shù)據(jù)文件輸入。
(5)用模板的形式改寫矩陣數(shù)據(jù)類型,使得矩陣中的數(shù)據(jù)既可以是整型數(shù)據(jù),也可以是浮點型數(shù)據(jù),執(zhí)行程序時,分別定義兩個整型矩陣和兩個浮點型矩陣進行乘法驗證。
(6)完成矩陣的乘法運算,在運算之前判斷這兩個矩陣能否滿足乘法運算的條件,若不滿足,則給出提示信息。
四、所增加功能模塊的設(shè)計
如果要說增加功能的話,自己編的程序里面不多,我只是按照題目要求,設(shè)計了一個矩陣類,同時用模板的形式改寫矩陣數(shù)據(jù)類型和運算符的重載。
1、模板的使用
我使用了大量的模板,以T為模板參數(shù),通過對T的不同類型的選擇實現(xiàn)相應(yīng)的運算處理。其中choose1()函數(shù)本是無參函數(shù),為了方便模板化,給其賦以偽參數(shù)T,在執(zhí)行時通過T的取值生成相應(yīng)的函數(shù)模板。
template
switch(sjlx){
case 1:
{
choose1(1);
}break;
case 2:
{
choose1(0.0);
}break;
case 3:
{
choose1(1e-10);
}break;
default:cout<<“輸入選擇錯誤!!”< 2、矩陣類的構(gòu)造 按照課本要求采用二級指針動態(tài)開辟內(nèi)存空間,節(jié)省內(nèi)存使用; 其中數(shù)據(jù)結(jié)構(gòu)如下: Mat-->Mat[0]----->Mat[0][0] Mat[0][1] ……Mat[0][j] Mat[1]----->Mat[1][0] Mat[1][1] ……Mat[1][j] : : Mat[i]----->Mat[i][0] Mat[i][1] ……Mat[i][j] 實現(xiàn)構(gòu)造的代碼為: template Mat[i]=new T[nCol];} cout<<“請輸入數(shù)據(jù):n”;for(i=0;i for(j=0;j { cout<<“第[”< cin>>Mat[i][j]; } } 3、運算符的重載 要實現(xiàn)矩陣間的乘法運算,有必要對其運算符進行重載。而乘法運算符又要針對不同數(shù)據(jù)類型進行運算,所以我對運算符重載函數(shù)模板化。template mat3.Mat[i][j]=0; for(int k=0;k mat3.Mat[i][j]+=mat1.Mat[i][k]*mat2.Mat[k][j];} return mat3;} 五、設(shè)計中遇到的主要問題及解決辦法 1、無法實現(xiàn)文件輸入 主要原因是輸入之前調(diào)用的是默認構(gòu)造函數(shù),只是簡單賦值,并未開辟內(nèi)存空間,后來調(diào)用帶參構(gòu)造函數(shù)就可以正常輸入數(shù)據(jù); 2、重載乘法運算的函數(shù)無法重載 經(jīng)檢查發(fā)現(xiàn),由于重載的是友元函數(shù),函數(shù)不存在this指針,因此必須顯式地調(diào)用兩個相乘的矩陣類。 六、設(shè)計中尚存的不足 1、功能還不夠強大,只能做簡單的矩陣乘法,我所期望的是能夠做各種混合運算,具有強大處理功能的實用程序,希望在以后的深入學習中可以改進。 2、關(guān)于異常處理這方面,我覺得處理功能也不是很行,覺得還是應(yīng)該建立全面的異常檢測與異常處理機制。 七、對設(shè)計的感想和心得體會 經(jīng)過這幾周的上機編程,我體會頗多,學到了很多東西。我加強了對C++程序設(shè)計這門課程的認識,并且復習了自己上學期學習到的知識。這些都使我對計算機語言的學習有了更深入的認識??傊?,通過這這幾周的上機編程,我收獲頗豐,相信會為自己以后的學習和工作帶來很大的好處。像矩陣乘法計算問題這樣的程序設(shè)計,經(jīng)歷了平時在課堂和考試中不會出現(xiàn)的問題和考驗。而這些問題,這并不是我們平時只靠課本,就可以輕易解決的。所以,鍛煉了我們挑戰(zhàn)難題,學會用已掌握的知識去解決具體問題的能力,進一步培養(yǎng)了獨立思考問題和解決問題的能力。當然,老師的指導和同學的幫助也是不可忽視的,他們給了我許多提示和幫助,教會了我編譯復雜程序的方法。 實踐出真知,做課程設(shè)計前,我的C++知識只是停留在理論水平,而且就算理論水平,也存在很多漏洞。有時,在做課題的時候,理論的漏洞冒了出來,我就只能在看著課本慢慢的再學習一遍,但有些東西還是沒有搞懂,所以現(xiàn)在就又翻出課本,看著課本編程,也算是將舊的東西復習了一遍。同時,有的概念在編程過程中印象更加深刻。 成功=勤奮+合作。在課程設(shè)計這方面自己也花了好多時間,交流與合作在編程過程中給我很大的幫助,我得到了很多,每次看到解問題后大家的愉悅,我想大家應(yīng)該與我一樣收獲很大吧。說真的,我挺喜歡這種討論的氛圍,它也讓編程過程變得趣味橫生,不再只是呆滯的盯著屏幕寫程序。 對凡事都應(yīng)當有毅力,不要中途放棄。在編程過程中,好幾次遇到困難我都想再換一個別的程序或找同學拷一個程序,但我最終還是堅持下來了。永不言棄,你就一定會成功的。 磨刀不誤砍柴工。在剛拿到任務(wù)時,書上的關(guān)鍵代碼我也是看的一頭霧水,后來我將上學期的課本認真研讀一遍之后,感覺收獲真的不少,接著編起程來就順手好多了。 此次程序設(shè)計使我透徹地領(lǐng)悟到面向?qū)ο蟮某绦蛟O(shè)計的優(yōu)點和強大生命力,特別是類和模板的使用,使程序的兼容性和擴展能力都大大加強,比如我們想要再做一個處理其他類型數(shù)據(jù)的矩陣的乘法計算,只需要添加一個相應(yīng)的類型聲明就可以利用模板迅速構(gòu)造出來。 通過課程設(shè)計的訓練,我進一步學習和掌握了對程序的設(shè)計和編寫,從中體會到了面向?qū)ο蟪绦蛟O(shè)計的方便和巧妙。懂得了在進行編寫一個程序之前,要有明確的目標和整體的設(shè)計思想。另外某些具體的細節(jié)內(nèi)容也是相當?shù)闹匾?。這些寶貴的編程思想和從中摸索到的經(jīng)驗都是在編程的過程中獲得的寶貴財富。這些經(jīng)驗對我以后的編程會有很大的幫助的,我要好好利用。 這次矩陣乘法計算問題課程設(shè)計讓我充分認識到了自己的不足,認識到了動手能力的重要性。我會在以后的學習中更加努力鍛煉自己,提高自己,讓自己寫出更好更完善的程序,為以后的編程打好基礎(chǔ)! 數(shù)據(jù)結(jié)構(gòu) 課程設(shè)計報告 設(shè)計題目: n維矩陣乘法:A B-1 專 業(yè) 計算機科學與技術(shù) 班 級 計本 學 生 學 號 指導教師 起止時間 2007.X.3-2007.X.11 學年第I 學期 一、具體任務(wù) 功能: 設(shè)計一個矩陣相乘的程序,首先從鍵盤輸入兩個矩陣a,b的內(nèi)容,并輸出兩個矩陣,輸出ab-1結(jié)果。 分步實施: 1.初步完成總體設(shè)計,搭好框架,確定人機對話的界面,確定函數(shù)個數(shù); 2.完成最低要求:建立一個文件,可完成2維矩陣的情況; 3.進一步要求:通過鍵盤輸入維數(shù)n。有興趣的同學可以自己擴充系統(tǒng)功能。 要求: 1.界面友好,函數(shù)功能要劃分好 2.總體設(shè)計應(yīng)畫一流程圖 3.程序要加必要的注釋 4.要提供程序測試方案 5.程序一定要經(jīng)得起測試,寧可功能少一些,也要能運行起來,不能運行的程序是沒有價值的。 二、軟件環(huán)境 Microsoft Visual C++ 6.0 三、問題的需求分析 程序以二維數(shù)組作為矩陣的存儲結(jié)構(gòu),通過鍵盤輸入矩陣維數(shù)n,動態(tài)分配內(nèi)存空間,創(chuàng)建n維矩陣。矩陣建立后再通過鍵盤輸入矩陣的各個元素值;也可以通過文件讀入矩陣的各項數(shù)據(jù)(維數(shù)及各元素值)。 當要對矩陣作進一步操作(A*B或A*B^(-1))時,先判斷內(nèi)存中是否已經(jīng)有相關(guān)的數(shù)據(jù)存在,若還未有數(shù)據(jù)存在則提示用戶先輸入相關(guān)數(shù)據(jù)。 當要對矩陣進行求逆時,先利用矩陣可逆的充要條件:|A| != 0 判斷矩陣是否可逆,若矩陣的行列式 |A| = = 0 則提示該矩陣為不可逆的;若 |A| !=0 則求其逆矩陣,并在終端顯示其逆矩陣。 四、算法設(shè)計思想及流程圖 1.抽象數(shù)據(jù)類型 ADT MatrixMulti{ 數(shù)據(jù)對象:D = {a(I,j)|i = 1,2,3,…,n;j = 1,2,…,n;a(i,j)∈ElemSet,n為矩陣維數(shù)} 數(shù)據(jù)關(guān)系: R = {Row,Col} Row = {| <= i <= n,1 <= j <= n-1} Col = {| <= i <= n-1,1 <= j <= n} 基本操作: Swap(&a,&b); 初始條件:記錄a,b已存在。 操作結(jié)果:交換記錄a,b的值。 CreateMatrix(n); 操作結(jié)果:創(chuàng)建n維矩陣,返回該矩陣。 Input(&M); 初始條件:矩陣M已存在。 操作結(jié)果:從終端讀入矩陣M的各個元素值。 Print(&M) 初始條件:矩陣M已存在。 操作結(jié)果:在終端顯示矩陣M的各個元素值。 ReadFromFile(); 操作結(jié)果:從文件讀入矩陣的相關(guān)數(shù)據(jù)。 Menu_Select(); 操作結(jié)果:返回菜單選項。 MultMatrix(&M1,&M2,&R); 初始條件:矩陣M1,M2,R已存在。 操作結(jié)果:矩陣M1,M2作乘法運算,結(jié)果放在R中。 DinV(&M,&V); 初始條件:矩陣M,V已存在。 操作結(jié)果:求矩陣M的逆矩陣,結(jié)果放入矩陣V中。 MatrixDeterm(&M,n); 初始條件:矩陣M已存在。 操作結(jié)果:求矩陣M的行列式的值。 } ADT MatrixMulti 2.矩陣求逆算法設(shè)計思想 算法采用高斯-約旦法(全選主元)求逆,主要思想如下: 首先,對于k從0到n-1作如下幾步: ① 從第k行、第k列開始的右下角子陣中選取絕對值最大的元素,并記住此元素所在的行號與列號,再通過行交換和列交換將它交換到主元素位置上。這一步稱為全選主元。 ② 主元求倒:M(k,k) = / M(k,k) ③ M(k,j) = M(k,j) * M(k,k);j = 0,1,…,n-1;j != k ④ M(i,j) = M(i,j) – M(i,k) * M(k,j);i,j = 0,1,…,n-1;i,j!=k ⑤ M(i,k) = M(i,k) * M(k,k),i = 0,1…,n-1;i != k 最后,根據(jù)在全選主元過程中所記錄的行、列交換的信息進行恢復,恢復原則如下: 在全選主元過程中,先交換的行(列)后進行恢復;原來的行(列)交換用列(行)交換來恢復。 3.矩陣行列式求值運算算法設(shè)計思想 利用行列式的性質(zhì):行列式等于它的任一行(列)各元素與其對應(yīng)的代數(shù)余子式乘積,即 D = ∑a(i,k)*A(i,k) ; k = 1,2,…,n; D = ∑a(k,j)*A(k,j) ; k = 1,2,…,n; 再利用函數(shù)的遞歸調(diào)用法實現(xiàn)求其值。 4.各函數(shù)間的調(diào)用關(guān)系 Main() ReadFromFile() DinV() Swap () Print() Menu_Select() MatrixDeterm() CreateMatrix() MultMatrix() Input() 5.流程圖 否 否 是 否 是 是 否 是 否 否 是 開始 switch(Menu_Select()) case 1: case 3: case 2: n 0 ? 是 輸入矩陣維數(shù)n 輸入矩陣A,B 輸出矩陣維數(shù)n system(“pause”); 通過鍵盤輸入需對哪個矩陣求逆,求出相應(yīng)該的逆陣,并顯示求得的逆陣system(“pause”);若矩陣不可逆則返回主菜單 case 4: R=A*B并顯示矩陣R system(“pause”); case 5: 是 否 是 R=A*B^(-1)顯示矩陣R system(“pause”);若B不可逆,則返回主菜單 case 6: 從指定文件中讀入矩陣數(shù)據(jù) case 0: exit(0); 結(jié)果 否 五、源代碼 #include #include #include #include #include #include #define YES #define NO 0 typedef float ElemType; ElemType **A; //矩陣A ElemType **B; //矩陣B ElemType **R; //矩陣R,用于存放運算結(jié)果 ElemType **V; //矩陣V,存放逆矩陣 int n=0; //矩陣維數(shù) int flag=-1; //標記 void swap(ElemType *a,ElemType *b) //交換記錄a,b的值 { ElemType c; c=*a; *a=*b; *b=c; } ElemType **CreateMatrix(int n) //創(chuàng)建n維矩陣,返回該矩陣 { int i,j; ElemType **M; M = (ElemType **)malloc(sizeof(ElemType *)*n); if(M == NULL) exit(1); for(i=0;i { *(M+i) = (ElemType *)malloc(sizeof(ElemType)*n); for(j=0;j *(*(M+i)+j) = 0; } return M; } ElemType MatrixDeterm(ElemType **M,int n) /*遞歸法求n維矩陣行列式的值,返回運算結(jié)果*/ { int i,j,k,l,s; ElemType **T1; ElemType **T2; T1=CreateMatrix(n); T2=CreateMatrix(n); ElemType u; ElemType value=0; //運算結(jié)果 for(i=0;i { for(j=0;j { T1[i][j]=M[i][j]; T2[i][j]=M[i][j]; } } if(n==2) //若為2維矩陣,則直接運算并返回運算結(jié)果 { value=T2[0][0]*T2[1][1]-T2[0][1]*T2[1][0]; return value; } else { for(j=0;j //將矩陣的行列式以第一行展開 { u=T1[0][j]; for(i=1,l=0;i //求矩陣行列式的余子式M(0,j) { for(k=0,s=0;k { if(k==j) continue; else { T2[l][s]=T1[i][k]; s++; } } l++; } value=value+u*((int)pow(-1,j))*MatrixDeterm(T2,n-1); /*行列式等于某一行的各個元素與其代數(shù)余子式的乘積之和*/ } return value; } } int DinV(ElemType **M,ElemType **V) /*全選主元法求矩陣M的逆矩陣,結(jié)果存入矩陣V中*/ { int i,j,k; ElemType d; ElemType u; int *JS,*IS; JS=(int *)malloc(sizeof(int)*n); IS=(int *)malloc(sizeof(int)*n); u=MatrixDeterm(M,n); //返回矩陣A的行列式值 if(u==0) return -1; for(i=0;i for(j=0;j V[i][j]=M[i][j]; for(k=0;k { d=0; for(i=k;i //找出矩陣M從M[k][k]開始絕對值最大的元素 { for(j=k;j { if(fabs(V[i][j])>d) { d=fabs(V[i][j]); //d記錄絕對值最大的元素的值 /*把絕對值最大的元素在數(shù)組中的行、列坐標分別存入IS[K],JS[K]*/ IS[k]=i; JS[k]=j; } } } if(d+1.0 == 1.0) return 0; //所有元素都為0 if(IS[k] != k) /*若絕對值最大的元素不在第k行,則將矩陣IS[K]行的元素與k行的元素相交換*/ for(j=0;j swap(&V[k][j],&V[IS[k]][j]); if(JS[k]!=k) /*若絕對值最大的元素不在第k列,則將矩陣JS[K]列的元素與k列的元素相交換*/ for(i=0;i swap(&V[i][k],&V[i][JS[k]]); V[k][k]=1/V[k][k]; //絕對值最大的元素求倒 for(j=0;j /*矩陣M第k行除元素M[k][k]本身外都乘以M[k][k]*/ if(j!=k) V[k][j]=V[k][j]*V[k][k]; for(i=0;i /*矩陣除第k行的所有元素與第k列的所有元素外,都拿本身減去M[i][k]*M[k][j],其中i,j為元素本身在矩陣的位置坐標*/ if(i!=k) for(j=0;j if(j!=k) V[i][j]=V[i][j]-V[i][k]*V[k][j]; for(i=0;i /*矩陣M第k列除元素M[k][k]本身外都乘以-M[k][k]*/ if(i!=k) V[i][k]=-V[i][k]*V[k][k]; } for(k=n-1;k>=0;k--) /*根據(jù)上面記錄的行IS[k],列JS[k]信息恢復元素*/ { for(j=0;j if(JS[k]!=k) swap(&V[k][j],&V[JS[k]][j]); for(i=0;i if(IS[k]!=k) swap(&V[i][k],&V[i][IS[k]]); } free(IS); free(JS); return 0; } void MultMatrix(ElemType **M1,ElemType **M2,ElemType **R) /*矩陣M1乘M2 結(jié)果存入矩陣R*/ { int i,j,k; for(i=0;i { for(j=0;j { R[i][j]=0; } } for(i=0;i { for(j=0;j { for(k=0;k { R[i][j]=R[i][j]+M1[i][k]*M2[k][j]; } } } } void Input(ElemType **M) //輸入矩陣M的各個元素值 { int i,j; char str[10]; char c='A'; if(flag==1) c='B'; system(“cls“); printf(“\n\n輸入矩陣%c(%d*%d)\n“,c,n,n); for(i=0;i { for(j=0;j { scanf(“%f“,*(M+i)+j); } } flag=1; gets(str); //吸收多余的字符 } void Print(ElemType **M) //顯示矩陣M的各個元素值 { int i,j; printf(“\t“); for(i=0;i { for(j=0;j { printf(“ %.3f“,M[i][j]); } puts(““); printf(“\t\t“); } } int Menu_Select() { char c; do{ system(“cls“); puts(“\t\t*************n維矩陣乘法器*************“); puts(“\t\t| 1.通過鍵盤輸入各項數(shù)據(jù) |“); puts(“\t\t| 2.顯示矩陣A,B |“); puts(“\t\t| 3.矩陣求逆,并顯示逆矩陣 |“); puts(“\t\t| 4.求矩陣運算A*B,并顯示運算結(jié)果 |“); puts(“\t\t| 5.求矩陣運算A*B^(-1),并顯示運算結(jié)果|“); puts(“\t\t| 6.從文件讀入矩陣A,B與維數(shù)n |“); puts(“\t\t| 0.退出 |“); puts(“\t\t***************************************“); printf(“\t\t請選擇(0-6):“); c=getchar(); }while(c<'0'||c>'6'); return (c-'0'); } void ReadFromFile() //從指定文件讀入矩陣的維數(shù)及矩陣各元素的值 { int i,j; FILE *fp; if((fp=fopen(“tx.txt“,“r“))==NULL) { puts(“無法打開文件!!“); system(“pause“); exit(0); } fscanf(fp,“%d“,&n); //讀入矩陣維數(shù) A=CreateMatrix(n); //創(chuàng)建矩陣A B V R B=CreateMatrix(n); V=CreateMatrix(n); R=CreateMatrix(n); for(i=0;i //讀入矩陣A { for(j=0;j { fscanf(fp,“%f“,&A[i][j]); } } for(i=0;i //讀入矩陣A { for(j=0;j { fscanf(fp,“%f“,&B[i][j]); } } puts(“\n\n讀文件成功“); fclose(fp); flag=1; } int main() { int i; char c,h; char str[10]; for(;;) { switch(Menu_Select()) { case 1: flag=-1; for(;;) { system(“cls“); printf(“\n\n\t矩陣維數(shù)n:“); scanf(“%d“,&n); gets(str); if(n>0) break; else { printf(“\n\t輸入有誤,請重新輸入!\n“); puts(““); system(“pause“); } } A=CreateMatrix(n); B=CreateMatrix(n); V=CreateMatrix(n); R=CreateMatrix(n); Input(A); Input(B); break; case 2: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩陣數(shù)據(jù),請先輸入數(shù)據(jù)“); system(“pause“); break; } puts(“\n“); printf(“\tA = “); Print(A); puts(“\n“); printf(“\tB = “); Print(B); puts(““); system(“pause“); break; case 3: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩陣數(shù)據(jù),請先輸入數(shù)據(jù)“); system(“pause“); break; } for(;;) { printf(“\n\n\t輸入需要求逆的矩陣(A/B):“); h=getchar(); c=getchar(); //h=getchar(); if(c=='A'||c=='a') { i=DinV(A,V); if(i==-1) { puts(“\n\n\t矩陣A的行列式等于0,不可逆!“); system(“pause“); break; } printf(“\tA = “); Print(A); puts(“\n“); printf(“A^(-1) = “); Print(V); puts(““); system(“pause“); break; } else if(c=='B'||c=='b') { i=DinV(B,V); if(i==-1) { puts(“\n\n\t矩陣B的行列式等于0,不可逆!“); system(“pause“); break; } printf(“\tB = “); Print(B); puts(“\n“); printf(“B^(-1) = “); Print(V); puts(““); system(“pause“); break; } else puts(“\n\n\t輸入有誤,請重新輸入!\n“); } break; case 4: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩陣數(shù)據(jù),請先輸入數(shù)據(jù)“); system(“pause“); break; } MultMatrix(A,B,R); printf(“\n\n\tA*B = “); Print(R); puts(““); system(“pause“); break; case 5: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩陣數(shù)據(jù),請先輸入數(shù)據(jù)“); system(“pause“); break; } i=DinV(B,V); if(i==-1) { puts(“\n\n\t矩陣B的行列式等于0,不可逆!“); system(“pause“); break; } MultMatrix(A,V,R); printf(“\n\nA*B^(-1) = “); Print(R); puts(““); system(“pause“); break; case 6: system(“cls“); ReadFromFile(); puts(““); system(“pause“); break; case 0: puts(“\t\t正常退出“); exit(0); break; } } return 0; } 六、運行結(jié)果 1.主界面: 2.輸入6,回車,從文本文件tx.txt中讀入矩陣數(shù)據(jù): 3.回車,回到主菜單界面;輸入2回車,顯示從文件讀入的矩陣數(shù)據(jù): 4.回車,回到主菜單界面;輸入3回車,對指定矩陣求逆:(由于這里矩陣A是不可逆的,因此僅以矩陣B為例) 5.回車,回到主菜單界面;輸入4回車,求矩陣運算A*B: 6.回車回到主菜單界面,輸入5回車,求A*B^(-1)的值: 7.回車回到主菜單界面,輸入0回車,退出程序;如果需要自定矩陣維數(shù)及各元素值,請利用主菜單里的1號功能自行輸入數(shù)據(jù),再進行以上幾種運算操作。 七、收獲及體會 通過這次課程設(shè)計,讓我再次復習了線性代數(shù)里矩陣的相關(guān)知識,比如n維矩陣的求逆、矩陣可逆的充分必要條件(|A| != 0)、矩陣與矩陣的乘法運算、行列式求值方法等。同樣的,還讓我復習了大量C語言里有關(guān)數(shù)組的一些重要概念,比如多維數(shù)組的動態(tài)分配問題、數(shù)組與指針的關(guān)系等。 記得在這個學期新開設(shè)的單片機基礎(chǔ)課上,吳濤老師曾多次強調(diào),讓我們一定要經(jīng)常鍛煉自己的編程能力,他常對我們說:“編程是思維的體操?!北M管我在這方面的能力 和實力非常得有限,也遠遠不及班上的其他同學,但我通過這次課程設(shè)計充分體會到了這句話的精華。 電腦程序作為人體大腦思維的延伸,程序的功能也會因為大腦思維的不斷完善而變得更加強大,所以我決定今后要加強在這方面的鍛煉和學習,以此來激勵自己不斷前進! 八、參考文獻 《數(shù)據(jù)結(jié)構(gòu)(C語言版)》 嚴蔚敏,吳偉民 編著 清華大學出版社 《C語言程序設(shè)計》 洪維恩 編著 中國鐵道出版社 《C語言程序設(shè)計教程》 譚浩強 張基溫 唐永炎 編著 高等教育出版社 《工程數(shù)學——線性代數(shù) 第四版》 同濟大學應(yīng)用數(shù)學系 編 高等教育出版社 計本 2007-12 題目:計算表達式的值 1、問題描述 對于給定的一個表達式,表達式中可以包括常數(shù)、算術(shù)運行符(“+”、“-”、“*”、“/”)和括號,編寫程序計算表達式的值。 基本要求:從鍵盤輸入一個正確的中綴表達式,將中綴表達式轉(zhuǎn)換為對應(yīng)的后綴表達式,計算后綴表達式的值。 提高要求:(1)對于表達式中的簡單錯誤,能夠給出提示; (2)不僅提示錯誤,也能給出錯誤信息(3)表達式中可以包括單個字母表示的變量(4)能夠處理多種操作符(5)實現(xiàn)包含簡單運算的計算器 (6)實現(xiàn)一個包含簡單運算和函數(shù)運算的計算器。 2.需求分析 軟件的基本功能:由鍵盤輸入中綴表達式,程序可以將輸入的中綴表達式轉(zhuǎn)換成對應(yīng)的后綴表達式,并計算后綴表達式的值。對于在輸入時發(fā)生的簡單錯誤,程序可以給出提示。本程序支持整數(shù)、小數(shù)、多種操作數(shù)的處理,可以計算含加、減、乘、除、運算符的表達式,并能判斷表達式括號是否匹配。輸入/輸出形式:用戶可以通過控制臺,根據(jù)輸入提示。輸入形式: ①正確的不含字母變量的中綴表達式; ②含有簡單錯誤的中綴表達式。 輸出形式: ①對于正確的中綴表達式,可以輸出其轉(zhuǎn)化后的后綴表達式及表達式的計算結(jié)果; ②對于含有簡單錯誤的中綴表達式,程序?qū)⒆詣虞敵鲥e誤提示,并給出錯誤信息。 測試數(shù)據(jù)要求:用戶可以輸入一個符合要求的中綴表達式,也可以輸入一個包含簡單錯誤的表達式。表達式中可以包括各種類型的常數(shù)以及小數(shù)等,操作符包括(+、-、*、/),同時表達式還可以包括各種括號。 3.概要設(shè)計 (1)抽象數(shù)據(jù)類型: 根據(jù)題目的要求,考慮用棧類型比較適合。ADT SeqStack Data 棧中元素具有相同類型及后進先出特性,相鄰元素具有前驅(qū)和后繼關(guān)系 Operation SeqStack 前置條件:棧不存在 輸入:無 功能:棧的初始化 輸出:無 后置條件:構(gòu)造一個空棧 ~ SeqStack 前置條件:棧已存在輸入:無 功能:銷毀棧 輸出:無 后置條件:釋放棧所占用的存儲空間 Push 前置條件:棧已存在 輸入:元素值x 功能:在棧頂插入一個元素x 輸出:如果插入不成功,拋出異常 后置條件:如果插入成功,棧頂增加了一個元素 Pop 前置條件:棧已存在輸入:無 功能:刪除棧頂元素 輸出:如果刪除成功,返回被刪元素值,否則,拋出異常 后置條件:如果刪除成功,棧頂減少了一個元素 GetTop 前置條件:棧已存在 輸入:無 功能:讀取當前的棧頂元素 輸出:若棧不空,返回當前的棧頂元素值 后置條件:棧不變 Empty 前置條件:棧已存在輸入:無 功能:判斷棧是否為空 輸出:如果棧為空,返回1;否則,返回0 后置條件:棧不變 End ADT 4.詳細設(shè)計 (1)實現(xiàn)概要設(shè)計的數(shù)據(jù)類型: 采用順序棧 const int StackSize = 50;template ~SeqStack();//析構(gòu)函數(shù) void Push(T x);//將元素x入棧 DataType Pop(); //將棧頂元素彈出 DataType GetTop();//取棧頂元素(并不刪除) int Empty();//判斷棧是否為空 private: DataType data[StackSize];//存放棧元素的數(shù)組 int top;//棧頂元素 };(2)主程序以及其它模塊的算法描述: 這個函數(shù)主要調(diào)用了實現(xiàn)功能的各個函數(shù)。其步驟為:在用戶沒有選擇退出時,先調(diào)用輸入函數(shù),輸入中綴表達式;然后調(diào)用判斷表達式,如果中綴表達式錯誤,則根據(jù)返回的值來輸出錯誤提示,不再往下運算;如果中綴表達式正確,則將中綴表達式轉(zhuǎn)換為后綴表達式,然后輸出中綴表達式和轉(zhuǎn)換后的后綴表達式;接著,再調(diào)用計算函數(shù),計算后綴表達式的結(jié)果輸出。最后是清屏函數(shù)。直至用戶選擇退出。 5、編碼與調(diào)試分析 編碼與調(diào)試過程中遇到的問題及解決辦法: 【問題1】程序在判斷表達式輸入形式有誤時,考慮情況不周全。解決辦法:盡可能多的將表達式有誤的情況考慮在內(nèi)。以下為現(xiàn)已考慮到并解決的問題:①表達式中出現(xiàn)非數(shù)字或非運算符的其他字符; ②表達式中括號不匹配。 【問題2】給變量賦值時出現(xiàn)重定義問題。 解決辦法:在定義暫存棧頂元素的變量t時,應(yīng)該在函數(shù)外面定義,在函數(shù)里面給變量賦值時不能定義?!締栴}3】無法處理多位數(shù)和小數(shù)。 解決辦法:在連續(xù)的操作數(shù)結(jié)束之后插入空格到后綴表達式中,以分隔操作數(shù)。 解決此問題的核心代碼: int i,t=0;float sum=0;for(i=0;i if(a[i]=='.'){ } } t=i;break;if(t!=0){ } else { } return sum; 2.待解決問題: for(i=0;i } i++;for(;i } sum=(a[i]-'0')*pow(0.1,i-t)+sum;if(a[i]=='.')break;sum=(a[i]-'0')*pow(10,n-(n-t)-1-i)+sum;for(i=0;i 6、使用說明 進入菜單,根據(jù)提示進行選擇。 7、測試結(jié)果 (1)含小數(shù)、多位數(shù)及括號的表達式顯示結(jié)果: 8、自學知識 在課程設(shè)計過程中,特別是在代碼編寫和調(diào)試的過程中,自學了很多新的知識。例如atof()函數(shù),包含于表頭文件 #include 第二篇:數(shù)據(jù)結(jié)構(gòu)課程設(shè)計報告n維矩陣乘法
第三篇:C++ 數(shù)據(jù)結(jié)構(gòu) 課程設(shè)計報告 計算表達式