基於LabWindows/CVI學生管理系統的實現
摘要
LabWindows/CVI是一款集成式的開發環境,集源代碼編輯、32位ANSI C編譯、聯結、調試以及標準ANSI C庫等爲一體,爲用戶提供簡單的拖放式用戶界面編輯器以及自動代碼生成器,是編程人員的好幫手。學生信息管理系統是針對學校學生處的大量工作處理工作而開發的管理軟件,主要用於學校學生信息管理,總體任務是實現學生信息關係的系統化、科學化、規範化和自動化,其主要任務是用手機和計算機對學生各種信息進行日常管理,如查詢、修改、增加、刪除等。基於此以LabWindows/CVI軟件平臺爲基礎,用鏈表的方式設計了簡單的學生管理系統,並生成txt文件用來保存錄入得學生信息。
關鍵詞: LabWindows/CVI、學生管理系統、鏈表
1、系統軟件設計
1.1、總體設計
軟件界面包括信息顯示、信息添加以及信息保存功能,如下圖所示。
1.2、鏈表的功能
鏈表是一種常見的重要的數據結構。它是動態地進行存儲分配的一種結構。鏈表和數組比較,不用事先確定存儲空間,而是根據需要開闢內存單元。下圖是最簡單的一種鏈表(單向鏈表)的結構。
第 0 個結點稱爲頭結點,它存放有第一個結點的首地址,它沒有數據,只是一個指針變量。以下的每個結點都分爲兩個域,一個是數據域,存放各種實際的數據,如學號 number,姓名 name等。另一個域爲指針域,存放下一結點的首地址。鏈表中的每一個結點都是同一種結構類型。
1.3、軟件流程
1.2、功能模塊設計
1.2.1、學生信息的添加
首先建立學生類型的結構體,包括:姓名、學號
struct Student //定義一個學生類型結構體,包括學號,分數
{
char Name[20];
int Number;
TYPE *Next; //next是指針變量,指向結構體變量
};
學生信息鏈表的建立起始就是,將第一個結點的起始地址賦值給頭指針head,將第二個結點的起始地址賦值給第一個結點的next成員,將第二個結點的起始地址賦給第一個結點的next…第三個結點的next賦值爲NULL,這就形成了簡單的鏈表。
/*******************************************************************
函數名稱: Creat
作用: 返回一個指向鏈表頭的指針
********************************************************************/
TYPE* Creat(void)
{
char Name[20] = {0}; //定義保存姓名的數組
int Number = 0; //定義保存姓名的整形
GetCtrlAttribute(panelHandle, PANEL_STRING_Name, ATTR_CTRL_VAL, Name); //得到PANEL_STRING_Name字符框中字符串給Name
GetCtrlAttribute(panelHandle, PANEL_NUM_Student, ATTR_CTRL_VAL, &Number); //得到PANEL_SPANEL_NUM_Student整形框中字符串給Number
if((strlen(Name) < 1) || (Number < 1)) //根據輸入的數據長度來判斷學生數據是否輸入有誤
{
MessagePopup("提示", "請重新輸入..."); //顯示對話消息對話框
}
else
{
PTmp = (struct Student *)malloc(sizeof(struct Student));//開闢新的結點空間
memset(PTmp, 0, sizeof(struct Student)); // 將空間清零
PTmp->Number = Number; //結點中保存學號,姓名
strcat(PTmp->Name, Name);
struct Student *PMov = Head; //每次都返回頭指針
if(Head == NULL)
{
Head = PTmp; //把第一個結點給頭指針
}
else
{
while(PMov->Next) //循環從頭到尾找指針域
{
PMov = PMov->Next;
}
PMov->Next = PTmp; //找到指針域後更新
}
sprintf(buf,"新添加了1個學生:學生:%s 學號:%d號", PTmp->Name, PTmp->Number); //把信息顯示到提示框
InsertTextBoxLine(panelHandle,PANEL_StudentText,count_index,buf);
count_index++;
return (Head); //返回首地址
}
}
1.2.2、學生信息的刪除
學生信息的刪除就是刪除鏈表指定元素,也就是把前節點的指針域越過要刪除的節點指向下下個節點。即:p->next = q->next;然後放出q節點的空間,即free§,如下圖。
/*******************************************************************
函數名稱: delet
作用: 結點刪除函數
********************************************************************/
void delet(TYPE* head)
{
TYPE* p = head;TYPE* in; //定義兩邊指針
int i = 0; //定義記錄值
char Name[20] = {0}; //定義姓名數組
GetCtrlAttribute(panelHandle, PANEL_STRING_Name, ATTR_CTRL_VAL, Name);//得到PANEL_STRING_Name字符框中字符串給Name
while ((strcmp(p->Name, Name) !=0) && p != NULL) //找到對應姓名並且不爲空的結點
{
in = p; //找到左邊的
p = p->Next; //找到右邊的
i++;
}
if (p != NULL)
{
sprintf(buf,"刪除的學生爲:%s 學號:%d號", p->Name, p->Number); //把信息顯示到提示框
InsertTextBoxLine(panelHandle,PANEL_StudentText,count_index,buf);
count_index++;
in->Next = p->Next; //將左右鏈接
free(p); //釋放中間結點
}
else {
MessagePopup("提示", "學生節點不存在..."); //顯示對話消息對話框
}
}
1.2.3、學生信息的插入
如下圖,可以看出來,插入節點就是用插入前節點的指針域鏈接上插入節點的數據域,再把插入節點的指針域鏈接上插入後節點的數據域。插入節點也就是:e->next = head->next; head->next = e,增加鏈表節點用到了兩個結構體指針和一個int數據。
/*******************************************************************
函數名稱: insert
作用: 鏈表的插入函數
********************************************************************/
void insert(TYPE* head) { //定義鏈表的插入函數
TYPE* p = head, * in; //定義首尾指針
int i = 0; //記錄值
int n; //定義插入的地方
char Name[20] = {0}; //定義姓名數組 ,學號
int Number = 0;
GetCtrlAttribute(panelHandle, PANEL_NUM_Student_Insert, ATTR_CTRL_VAL, &n); //得到PANEL_NUM_Student_Insert整形中數據給n
while (i < (n-1) && p != NULL) {
p = p->Next;
i++; //找到相應結點
}
if (p != NULL) {
in = (TYPE*)malloc(sizeof(TYPE)); //開闢新的空間
memset(in, 0, sizeof(struct Student)); //清零
GetCtrlAttribute(panelHandle, PANEL_STRING_Name, ATTR_CTRL_VAL, Name); //得到PANEL_STRING_Name字符中數據給Name
GetCtrlAttribute(panelHandle, PANEL_NUM_Student, ATTR_CTRL_VAL, &Number);//得到PANEL_NUM_Student整形中數據給Number
in->Number = Number;
strcat(in->Name, Name); //複製信息給in->Name
sprintf(buf,"插入學生:%s 學號:%d號", in->Name, in->Number);
InsertTextBoxLine(panelHandle,PANEL_StudentText,count_index,buf);
count_index++;
in->Next = p->Next; //填充in節點的指針域,也就是說把in的指針域指向p的下一個節點
p->Next = in; //填充p節點的指針域,把p的指針域重新指向in
}
else {
MessagePopup("提示", "表中不包含任何學生...");//顯示對話消息對話框
}
}
1.2.4、學生信息的顯示
把全部的學生信息顯示,就是一個調用循環的過程,,然後用TextBox控件顯示信息。
/*******************************************************************
函數名稱: print
作用: 鏈表輸出函數
********************************************************************/
void print(TYPE * head)
{
TYPE * p; //定義指針
p = head; //使p指向第一個結點
int count = 0; //記錄多少哥結點數
ResetTextBox (panelHandle, PANEL_StudentInfText, "");
prinf_index=0;
if(Head == NULL) //判斷是否爲空
{
MessagePopup("提示", "表中不包含任何學生..."); //顯示對話消息對話框
}
else
if(head!=NULL) //輸出第一個結點後的信息
do {
sprintf(buf,"第%d個學生:%s 學號:%d號", ++count, p->Name, p->Number);//把信息顯示到提示框
InsertTextBoxLine(panelHandle,PANEL_StudentInfText,prinf_index,buf);
prinf_index++;
p = p->Next; //指向下個結點C
} while (p != NULL);
}
1.2.5、學生信息的修改
修改學生信息,就是遍歷學生鏈表,找到姓名相對於的元素,然後進行修改即可。
/*******************************************************************
函數名稱: change
作用: 修改指定位置的結點的信息函數
********************************************************************/
void change(TYPE* head)
{
TYPE* p = head; //傳入首地址
int i = 0; //記錄值
char Name[20] = {0}; //定義姓名數組 ,學號
int Number = 0;
GetCtrlAttribute(panelHandle, PANEL_STRING_Name, ATTR_CTRL_VAL, Name); //得到PANEL_STRING_Name字符中數據給Name
while ((strcmp(p->Name, Name) !=0) && p != NULL) { //找到對應姓名並且不爲空的結點
p = p->Next;
i++;
} //找到相應的位置結點
if (p != NULL) {
GetCtrlAttribute(panelHandle, PANEL_STRING_Name, ATTR_CTRL_VAL, Name); //得到PANEL_STRING_Name字符中數據給Name
GetCtrlAttribute(panelHandle, PANEL_NUM_Student, ATTR_CTRL_VAL, &Number);//得到PANEL_NUM_Student整形中數據給Number
p->Number = Number; //保存學號
sprintf(buf,"修改的學生:%s 學號:%d號", p->Name, p->Number);
InsertTextBoxLine(panelHandle,PANEL_StudentText,count_index,buf);
count_index++;
}
else
MessagePopup("提示", "表中不包含該學生"); //顯示對話消息對話框
}
1.3、學生信息的整體保存
首先要在指定文件路勁中建立txt文件,然後把文本框中的信息,逐行保存到文本文件中。
void SaveText(void)
{
int FileName = 0;
char FilePath[128];
char Buf[100][100]; //最好用動態分配內存
int length = 0,i,row;
FileName = OpenFile("C:\\Users\\86188\\Desktop\\text1.txt",VAL_READ_WRITE,VAL_OPEN_AS_IS,VAL_ASCII); //在指定文件夾中新建文件
GetNumTextBoxLines (panelHandle, PANEL_StudentInfText, &row); //獲取文本控件行數
GetTextBoxLineLength (panelHandle, PANEL_StudentInfText, 0, &length); //獲取每一行字符串長度
for(i = 0; i < row; i++)
{
GetTextBoxLine (panelHandle, PANEL_StudentInfText, i, &Buf[i][0]);
GetTextBoxLineLength (panelHandle, PANEL_StudentInfText, i , &length); //獲取每一行字符串長度
WriteLine(FileName,&Buf[i][0],length);
}
CloseFile(FileName);C
}
1.4、回調函數以及主函數
int main (int argc, char *argv[])
{
if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */
if ((panelHandle = LoadPanel (0, "show.uir", PANEL)) < 0)
return -1;
DisplayPanel (panelHandle);
RunUserInterface ();
DiscardPanel (panelHandle);
return 0;
}
int CVICALLBACK MainCallBack (int panel, int event, void *callbackData,
int eventData1, int eventData2)
{
switch (event)
{
case EVENT_GOT_FOCUS:
break;
case EVENT_LOST_FOCUS:
break;
case EVENT_CLOSE:
QuitUserInterface (0);
break;
}
return 0;
}
int CVICALLBACK MainPanelBtnCallback (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
switch(control)
{
char Name[20] = {0};
int Number = 0;
case PANEL_BTN_Add: //增加
Creat();
print (Head);
break;
case PANEL_BTN_Delete: //刪除
delet(Head);
print (Head);
break;
case PANEL_BTN_Show: //顯示
print (Head);
break;
case PANEL_BTN_insert: //插入
insert (Head);
print (Head);
break;
case PANEL_BTN_Change: //更改
change (Head);
print (Head);
break;
case PANEL_BTN_Save: //保存
SaveText();
break;
}
break;
}
return 0;
}
2、測試結果與分析
通過在控件中輸入個人信息,可以在信息提示中看到控件執行的操作,在學生信息中可以顯示總錄入學生的信息,通過保存控件將錄入好的學生信息保存到text1.txt文件中。
3、結論
學生管理系統設計過程中,利用LabWindows/CVI自帶的控件,能夠很大程度上簡化設計過程,提高科研開發速度。但是在學生修改、插入以及刪除的功能上做的不是很智能,不能模糊識別學生信息並進行操作,這給使用人員來說不是很便利。