基于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自带的控件,能够很大程度上简化设计过程,提高科研开发速度。但是在学生修改、插入以及删除的功能上做的不是很智能,不能模糊识别学生信息并进行操作,这给使用人员来说不是很便利。
本文介绍了一款基于LabWindows/CVI开发的学生管理系统,利用链表数据结构实现了学生信息的增删改查功能,并能将信息保存到txt文件。系统界面包含信息显示、添加和保存,具有良好的操作体验。
8176

被折叠的 条评论
为什么被折叠?



