摘 要: 從實(shí)踐層面上看,關(guān)系模型應(yīng)用極其廣泛;從理論層面上看,關(guān)系模型是眾多計(jì)算機(jī)分支的交匯處,專門的研究和提煉很有必要。針對(duì)關(guān)系模型的基本操作,本文給出了部分底層的算法及代碼,通過對(duì)編程思想方法的解析,強(qiáng)調(diào)教學(xué)中思維訓(xùn)練的重要性,期待對(duì)相關(guān)課程教學(xué)及人才培養(yǎng)有一定的實(shí)用價(jià)值。
關(guān)鍵詞: 關(guān)系模型;? 二維表格;? C語言;? 編程;? 教學(xué)
中圖分類號(hào): TP 311; G 642文獻(xiàn)標(biāo)志碼: A
Basic Programming Analysis of Relational Model
JIAO Hua
(College of Computer and Information Engineering, Guizhou University of Commerce, Guiyang, Guizhou 550014, China)
Abstract: From the practical level, relational model is widely used; from the theoretical level, relational model is the intersection of many branches of computer, so it is necessary to study and refine it. In view of the basic operation of the relational model, this paper gives some bottom-level algorithms and codes. Through the analysis of programming ideas and methods, it emphasizes the importance of thinking training in teaching, and expects to have a certain practical value for the teaching of relevant courses and personnel training.
Key words: relational model; 2-D table; C language; programming; teaching
0 引言
表格管理無時(shí)不在、無處不在,因此可以說世界是表格的世界[1]。使用表格是為了對(duì)數(shù)
據(jù)進(jìn)行直觀有效的管理,任何復(fù)雜的表格都可由標(biāo)準(zhǔn)的二維表格生成。二維表格用數(shù)據(jù)庫語言[2]可表述為:從縱向看由一個(gè)個(gè)字段(域)組成;從橫向看除第一行(表頭)外,由一條條記錄構(gòu)成。在數(shù)據(jù)庫管理系統(tǒng)中要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù)表,步驟是先建立表結(jié)構(gòu)(表頭),再錄入一條條記錄。二維表格是三大數(shù)據(jù)模型之一的關(guān)系模型,這是它應(yīng)用極其廣泛的根源[3]。上個(gè)世紀(jì)七十年代初Edgar Frank Codd開發(fā)了一個(gè)關(guān)系型的數(shù)據(jù)管理模型,被譽(yù)為“關(guān)系模型之父”。根據(jù)他設(shè)計(jì)構(gòu)建的關(guān)系模型數(shù)據(jù)庫成為了眾多行業(yè)、企業(yè)運(yùn)行的基礎(chǔ):銀行使用關(guān)系數(shù)據(jù)庫跟蹤資金的流動(dòng)、零售商依賴它們對(duì)庫存水平進(jìn)行監(jiān)控、人力資源部門應(yīng)用它們對(duì)員工檔案進(jìn)行管理;政府機(jī)構(gòu)、學(xué)校和圖書館在其中存儲(chǔ)千萬上億條記錄;應(yīng)當(dāng)說世界上幾乎所有的企事業(yè)單位都在使用關(guān)系模型數(shù)據(jù)庫[4]。自Codd公布其理論成果之后的30年中,關(guān)系數(shù)據(jù)庫據(jù)統(tǒng)計(jì)已成為年收入達(dá)到130億美元的產(chǎn)業(yè)。在有堅(jiān)實(shí)數(shù)學(xué)基礎(chǔ)的關(guān)系模型提出以后,之前的兩大數(shù)據(jù)模型——層次模型與網(wǎng)狀模型的系列數(shù)據(jù)庫產(chǎn)品迅速走向衰敗、消亡,眾多商業(yè)化關(guān)系數(shù)據(jù)庫管理系統(tǒng)很快被開發(fā)并占領(lǐng)了市場,其除舊布新之徹底、交替速度之快在軟件史上是罕見的。Codd的杰出貢獻(xiàn)使他在1981年獲得了計(jì)算機(jī)界最高獎(jiǎng)——圖靈獎(jiǎng)。
在高等院校計(jì)算機(jī)類課程中,有多門課程與二維表格模型——關(guān)系模型有關(guān):《計(jì)算機(jī)應(yīng)用基礎(chǔ)》中的Excel、Access;《SQL Server數(shù)據(jù)庫》中的數(shù)據(jù)表操作;《C語言程序設(shè)計(jì)》中的數(shù)組、結(jié)構(gòu)體;《數(shù)據(jù)結(jié)構(gòu)》中的三大結(jié)構(gòu)——線性結(jié)構(gòu)、樹型結(jié)構(gòu)、圖及網(wǎng)狀結(jié)構(gòu)其實(shí)就是《數(shù)據(jù)庫原理》中的三大數(shù)據(jù)模型——關(guān)系模型、層次模型、網(wǎng)狀模型[5]。如同眾多河流的交匯處,關(guān)系模型是多門計(jì)算機(jī)課程聚集點(diǎn),專門的研究和提煉很有必要。目前對(duì)計(jì)算機(jī)教育教學(xué)的研究論文很多,但都比較宏觀和中觀,而計(jì)算機(jī)科技方面的論文又很傲慢地不談教育教學(xué),這里折衷以關(guān)系模型作為出發(fā)點(diǎn),剖析其基礎(chǔ)編程的方法和代碼,期待對(duì)相關(guān)課程教學(xué)及人才培養(yǎng)有一定的實(shí)用價(jià)值。
1 關(guān)系模型的基礎(chǔ)算法及代碼解析
二維表格的輸入、輸出、橫向運(yùn)算、縱向運(yùn)算、排序是最基本的操作,這些操作用Excel、Access或其他數(shù)據(jù)庫軟件都很容易實(shí)現(xiàn),但若要了解底層的算法及代碼,則需要用C語言等過程化高級(jí)語言較困難地進(jìn)行綜合程序設(shè)計(jì)[6]。這一點(diǎn)在教學(xué)中要對(duì)學(xué)生講清楚:前者的容易是因?yàn)椤罢驹诰奕思缟稀?后者的困難是因?yàn)橐磺卸家暗陡鸱N”。但從“知其然且知其所以然”的角度講,必須掌握后者,而且后者也是較好的編程思維訓(xùn)練素材。二維表格模型從本質(zhì)上可描述為若干個(gè)結(jié)構(gòu)相同的數(shù)據(jù)元素排列構(gòu)成的有限序列,每個(gè)數(shù)據(jù)元素由若干個(gè)有關(guān)聯(lián)性的數(shù)據(jù)項(xiàng)組成。比如職工工資表中,除表頭外每一行是一個(gè)數(shù)據(jù)元素,反映的是某個(gè)職工相關(guān)聯(lián)的編號(hào)、姓名、基本工資、工齡工資、津貼、資金、應(yīng)發(fā)合計(jì)等。為了將抽象的分析討論具體化,后面將圍繞以下的二維表格實(shí)例展開[7]。如表1所示。
實(shí)例:已知某班有N個(gè)學(xué)生,其學(xué)號(hào)、姓名、各科課程成績?nèi)缦拢〝?shù)據(jù)省略):
要求設(shè)計(jì)一個(gè)C語言的菜單程序,完成以下功能:
① 輸入學(xué)號(hào)、姓名及各科成績(原始成績的錄入);
② 輸出學(xué)號(hào)、姓名、各科成績及總分;
③ 輸出學(xué)號(hào)、姓名、各科成績、總分及名次;
④ 退出程序。
如何設(shè)計(jì)主菜單?在C語言課程的教學(xué)中,教師總是諄諄教導(dǎo)學(xué)生:在程序設(shè)計(jì)中要注意避免死循環(huán),在循環(huán)體中要有改變循環(huán)條件的語句存在,沒有死循環(huán)的C程序運(yùn)行完后將返回到對(duì)應(yīng)的C編譯系統(tǒng)。這種傳統(tǒng)的教導(dǎo)是必須的,但會(huì)使學(xué)生對(duì)死循環(huán)產(chǎn)生恐懼,萬事萬物都有雙面性,死循環(huán)其實(shí)是編程中的大智慧!因?yàn)樽尦绦蛞恢边\(yùn)行的手段就是一邊采用死循環(huán),一邊在循環(huán)體中安排好必備出口。比如電腦開機(jī)后Windows一直在運(yùn)行,而在開始菜單中有關(guān)機(jī)按扭,其功能是關(guān)閉所有打開的程序、關(guān)閉Windows、關(guān)閉電腦。運(yùn)行一個(gè)基于Windows平臺(tái)的應(yīng)用程序?qū)⒋蜷_一個(gè)窗口,如果不選擇窗口中的關(guān)閉按扭或菜單中的退出項(xiàng),它將一直運(yùn)行下去。因此這里是用死循環(huán)設(shè)計(jì)主菜單,其流程圖[8]如圖1所示。
編程過程中除了掌握C語言扎實(shí)的語法知識(shí)外,繪制流程圖是程序員的基本功[9]。程序設(shè)計(jì)的思路用圖的形式來表達(dá),繪圖過程就是思考的過程,由于圖形的直觀性,繪制過程中又啟發(fā)、促進(jìn)了思考。在具體教學(xué)中,針對(duì)上圖讓學(xué)生描述在菜單中依次選擇1、2、3、4的流程執(zhí)行線路,是一種極佳的編程思維訓(xùn)練選擇。因?yàn)楫?dāng)中有順序、有分支、有循環(huán)、有函數(shù)調(diào)用回返這四種基本程序結(jié)構(gòu)[8],把握流程點(diǎn)的狀態(tài)和走向是程序員的基本功。需要指出的是:通常情況下初學(xué)者不能正確描述上面的流程執(zhí)行線路。
完整的程序代碼[10]如下:
#include
#include
#define N 6
struct st
{int xh; char xm[20]; int yy;
int gs; int zydl; int zf; int mc;};
struct st bj[N];
void cjlr(); void cjxs();void cjmc();
int main()
{ char ch;
while(1)
{system("cls");
printf("歡迎使用本系統(tǒng)?。躰");
printf("1:輸入學(xué)號(hào),姓名,英語、高數(shù)及專業(yè)導(dǎo)論成績\n");
printf("2:輸出學(xué)號(hào),姓名,各科成績、總分\n");
printf("3:輸出學(xué)號(hào),姓名,各科成績、總分、名次\n");
printf("4:退出程序\n");
printf("請(qǐng)選擇1——4:");
ch=getchar();
if(ch=='1') cjlr();
if(ch=='2') cjxs();
if(ch=='3') cjmc();
if(ch=='4') {printf("退出本系統(tǒng)!");getch();break;}
}
return 0;
}
void cjlr()
{int i;
printf("*輸入學(xué)號(hào),姓名,英語、高數(shù)及專業(yè)導(dǎo)論成績*\n");
for(i=0;i<=N-1;i++)
scanf("%d%s%d%d%d",&bj[i].xh,bj[i].xm,&bj[i].yy,&bj[i].gs,&bj[i].zydl);
system("pause");
}
void cjxs()
{int i;
for(i=0;i<=N-1;i++)
bj[i].zf=bj[i].yy+bj[i].gs+bj[i].zydl;
printf("*輸出學(xué)號(hào),姓名,各科成績,總分*\n");
for(i=0;i<=N-1;i++)
printf("%d %10s %4d %4d %4d %4d\n",bj[i].xh,bj[i].xm,bj[i].yy,bj[i].gs,bj[i].zydl,bj[i].zf);
system("pause");
}
void cjmc()
{int i,j,k; struct st temp;
for(i=0;i {k=i; for(j=i+1;j<=N-1;j++) if(bj[j].zf>bj[k].zf) k=j; temp=bj[k];bj[k]=bj[i];bj[i]=temp; } bj[0].mc=1; for(i=1;i<=N-1;i++)???? /* 確定名次 */ if(bj[i].zf==bj[i-1].zf) bj[i].mc=bj[i-1].mc; else bj[i].mc=bj[i-1].mc+1; printf("*輸出學(xué)號(hào),姓名,各科成績,總分,名次*\n"); for(i=0;i<=N-1;i++) printf("%d %10s %4d %4d %4d %4d %4d\n",bj[i].xh,bj[i].xm,bj[i].yy,bj[i].gs,bj[i].zydl,bj[i].zf,bj[i].mc); system("pause"); }? [10] 基礎(chǔ)編程中有一個(gè)著名的沃思公式:“算法+數(shù)據(jù)結(jié)構(gòu)=程序”,上面除了流程圖表示的主算法外,還有選擇排序算法等,在數(shù)據(jù)描述方面,一開始就定義了一個(gè)全局的結(jié)構(gòu)體數(shù)組,所有函數(shù)都可以使用,這個(gè)全局量將各函數(shù)的操作結(jié)果聯(lián)系在一起。因此雖然函數(shù)調(diào)用時(shí)沒有參數(shù)傳遞,回返時(shí)不帶回結(jié)果,但全局結(jié)構(gòu)體數(shù)組將這些函數(shù)串起來了。 選擇菜單項(xiàng)1——菜單項(xiàng)4運(yùn)行情況圖如圖2~圖5所示。 注意主函數(shù)中的程序段: if (ch=='1') cjlr(); if(ch=='2') cjxs(); if(ch=='3') cjmc(); if(ch=='4') {printf("退出本系統(tǒng)!");getch();break;} 可用下面的程序段代替 switch(ch) { case '1':cjlr();break; case '2':cjxs();break; case '3':cjmc();break; case '4':printf("退出本系統(tǒng)!");getch();exit(0); } 注意:exit(0)不能用break替代,這里使用break只能退出switch分支結(jié)構(gòu),不能退出while循環(huán)結(jié)構(gòu);而exit(0)則可強(qiáng)行退出主程序。這一點(diǎn)也是編程者易犯的錯(cuò)誤。 程序說明:(1)、成績錄入函數(shù)cjlr()用于得到最原始的二維表格,因此可以合并到主函數(shù)中去。(2)、成績顯示函數(shù)cjxs()在計(jì)算出總分欄的基礎(chǔ)上,可顯示從學(xué)號(hào)欄到總分欄的二維表格。因?yàn)閎j是一開始就設(shè)置為全局變量的結(jié)構(gòu)體數(shù)組,因此可應(yīng)用cjlr()函數(shù)的結(jié)果。(3)、函數(shù)cjmc()用于排序、填入名次、顯示從學(xué)號(hào)欄到名次欄的二維表格,它用到了函數(shù)cjxs()得到的總分。(4)、子程序3依賴于子程序2的結(jié)果,而子程序2依賴于子程序1的結(jié)果,如果主程序中的菜單選擇不分前后,為增強(qiáng)子程序的獨(dú)立性,勢必添加重復(fù)代碼。(5)、函數(shù)cjmc()由于排序、填入名次已將學(xué)號(hào)順序打亂,若要恢復(fù)可對(duì)學(xué)號(hào)按冒泡排序或選擇排序還原。(6)圖4顯示的并列名次驗(yàn)證了名次算法的正確性。(7)為了避免每次運(yùn)行都要輸入原始二維表格數(shù)據(jù),可用C語言中的文件類型將原始數(shù)據(jù)存盤,運(yùn)行需要時(shí)再調(diào)入,這樣的解決方案更完美。 2 總結(jié) 前面提到的二維表格模型——關(guān)系模型應(yīng)用非常廣泛,是高等院校計(jì)算機(jī)課程中多門課程的交匯點(diǎn)[11],按課程開設(shè)的順序,基礎(chǔ)編程的入門課是“C語言程序設(shè)計(jì)”。C/C++被譽(yù)為高級(jí)語言之母,幾乎所有高級(jí)編程語言追根溯源它們的底層都是C/C++,學(xué)好了C/C++,其他都是“小菜一碟”,因此本文的實(shí)例是用C語言來寫代碼的。基礎(chǔ)編程教學(xué)通常圍繞語法和算法兩條線索展開,傳統(tǒng)的教學(xué)內(nèi)容及期末試卷考核最大的弊端是以語法為中心,打破常規(guī)、注重算法、注重編程思想,用綜合程序設(shè)計(jì)驅(qū)動(dòng)基礎(chǔ)編程教學(xué)的改革意義重大[12]!將關(guān)系模型問題的程序設(shè)計(jì)作為期末考核內(nèi)容,既綜合運(yùn)用了C語言各章節(jié)的知識(shí),在課程體系上也能夠承上啟下,最關(guān)鍵是訓(xùn)練了學(xué)生的編程素質(zhì),這是優(yōu)秀程序員的必經(jīng)之路。 參考文獻(xiàn) [1] 劉云翔. 計(jì)算機(jī)應(yīng)用基礎(chǔ)[M]. (第3版). 北京:清華大學(xué)出版社, 2017. [2] 劉麗. Access數(shù)據(jù)庫基礎(chǔ)教程[M]. (2010版).北京:清華大學(xué)出版社, 2014. [3] 胡孔法. 數(shù)據(jù)庫原理及應(yīng)用[M]. 北京:機(jī)械工業(yè)出版社, 2011. [4] 卓廣平. 數(shù)據(jù)挖掘開發(fā)及應(yīng)用研究[J]. 軟件,2015(5):81-83. [5] 嚴(yán)蔚敏. 數(shù)據(jù)結(jié)構(gòu)(C語言版)[M]. 北京:清華大學(xué)出版社, 2018. [6] 石蕓. 微課在《SQL Server數(shù)據(jù)庫》課程教學(xué)中的應(yīng)用[J]. 信息與電腦(理論版), 2017(13):107-108. [7] 許真珍. 編程基礎(chǔ)課程漸進(jìn)式項(xiàng)目驅(qū)動(dòng)教學(xué)法研究[J]. 實(shí)驗(yàn)室科學(xué),2018(4):123-125. [8] 焦華. 基礎(chǔ)編程的思考方法[J]. 軟件,2018(3):57-62. [9] 安光勇. 以數(shù)學(xué)算法為基礎(chǔ)的C程序編程技巧[J]. 電子測試,2017(7):37-40. [10] 譚浩強(qiáng). C程序設(shè)計(jì)[M]. (第5版).北京:清華大學(xué)出版社, 2017. [11] 岳清. SQL Server數(shù)據(jù)庫完整性教學(xué)案例探析[J]. 電腦知識(shí)與技術(shù), 2017(19):61-63. [12] 臺(tái)海江.《C語言程序設(shè)計(jì)》課程教學(xué)改革探討 [J]. 現(xiàn)代計(jì)算機(jī)(專業(yè)版), 2018(32):33-36. (收稿日期: 2019.06.22) 基金項(xiàng)目:貴州省教育廳2016年本科教學(xué)工程項(xiàng)目(SJ-JXGC-KC-003;SJ-JXGC-KC-002) 作者簡介:焦華(1964-),男,碩士,副教授,研究方向:算法與程序。