菜单系统

更新时间:2024-01-07 16:22:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实训一 光标漫游

⒈问题

在25行80列的显示屏内,通过按键“→、←、↑、↓”来改变光标的位置,如按“→”键则光标往右侧走一列,按“↑”键则光标往上走一行的位置,最终通过“Esc”结束程序。 ⒉边界问题

要处理好特殊情况:①光标在第一行,再按“↑”键时;②光标在第一列,再按“←”键时;③光标在第25行,再按“↓”键时;④光标在第80列,再按“→”键时。 ⒊边界问题处理

采用折返的方式:①光标在第1行,再按“↑”键时进到第25行;②光标在第1列,再按“←”键时进到第80行;③光标在第25行,再按“↓”键时进到第1行;④光标在第80列,再按“→”键时时进到第1列。 ⒋实验基础

①注意查看conio.h,conio.c中的函数:

clrscr() 清屏

KeyValueStru kbhit() 读键(返回虚键和字符的Asc码) void gotoxy(int x, int y) 定位光标到相应行和列

②注意查看与conio.c中的结构与常量: //kbhit()返回的读键结构

typedef struct KeyValueStru{ WORD VKey,AscChar; };

⒌实验步骤

运行“光标漫游示例.EXE”了解需求,看源码“读键光标颜色示例.cpp”了解基本编程。

①编一小程序(用kbhit())获得特殊键“→、←、↑、↓”“Esc、回车”等的虚键值和Asc码值,并记录以备后用;

②写出光标漫游的算法(保存,用类自然语言描述,用word,与同学、老师讨论算法的可行性与正确性);

③在②初步正确的基础上,编写C语言源程序; ④如发现算法问题,用调试器调试; ① 完成本实验的实验报告。 6.要点

光标如何根据所按的键跟随?折返如何处理?x=(x+1) %; 7.该实验与大实验的关联性

请大家体会主菜单“实验蓝本.exe”的处理过程。

附件:实验报告内容 ①问题

②设计要点及算法 ③源程序 ④运行结果

⑤使用调试器状况和经验总结 ⑥使用体会和总结

实训二 色彩处理及方框显示

⒈问题

在显示屏显示各种形状的方框(大小不一)。 ┬──┬ ┌───┐ │ │ │ │ └──┘ └───┘等

实验中可用1,2,3,4,…,9,0等来代替(也可复制“实验用蓝本结构代码.cpp”文件中的S_S_Box等数据),如:

122222223 455555556 455555556 455555556 455555556 788888889

由于我们的实验在控制台的环境下仿真(不能正确显示出制表符号),C-Free对图标符号的显示变成了相关汉字。

我们在上述实验的基础上,采用“空格”+“颜色”的方式来实现方框。 ⒉实验基础

①注意查看conio.c中的函数:

void textattr(int _attr) 设置前景和背景颜色 void textcolor(int _color) 设置前景颜色 void textbackground(int _color) 设置背景颜色

②注意查看与conio.c中的结构与常量:

//颜色常量

enum COLORS {

/* dark colors */ BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, /* light colors */ DARKGRAY, /* \ LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE };

⒊实验步骤

①编写小程序,用textattr(int _attr)函数来设置(_attr是按字节组织,高4位表背景景,低4位表前景色),后用输出字符串语句输出,体验用textattr的作用;

②写出显示方框的算法(注意模块化); ③在②初步正确的基础上,编写C语言源程序;

④如发现算法问题,用调试器调试; ⑤完成本实验的实验报告。

实训三 主菜单的显示与选择

⒈问题

在屏幕上显示下列菜单,并能通过“→、←、↑、↓”来切换菜单项。如初始显示为: File Edit Run Compile Project Options Debug 当按“→”键时,变成: File Edit Run Compile Project Options Debug 再按“→”键时,变成: File Edit Run Compile Project Options Debug ⒉实验基础 本实验是实验一加颜色处理的方法来实现,所以本次实验的基础大家都具备。运行“主菜单演示.exe”体会编程,大家可在“实验用蓝本结构代码.CPP”上来编程。 ⒊实验原理

如何来实现菜单项的切换是本实验的技巧。 File Edit Run Compile Project Options Debug mi,MenuIndex的缩写 假定我们用一变量mi来指向当前选中的菜单,当按“→”键时,我们用“未选中的颜色”来定位重写“File”的串,使菜单变成: File mi,MenuIndex的缩写

Edit Run Compile Project Options Debug

然后是按键处理后,mi修正为1,然后用“选中的颜色”定位重写“Edit”, File

mi Edit Run Compile Project Options Debug 变成上图的效果,实现了菜单项的动态切换。 ⒋实验步骤

①在word上写出算法(其中主菜单的字符串数据放在数组中)。 ②思考…… ③提问

④算法正确后再编写程序。 ⒌完成实验报告

实训四 菜单数据的组织

⒈问题

看实例“实验蓝本.exe”,思考菜单数据如何组织?数据的组织与菜单显示之间怎么关联? ⒉菜单的逻辑结构图

⒊数据的组织结构 //菜单结构体定义

typedef struct MenuItemStru{

ShortInt SubMenuItemCount; //子菜单的数目 ShortInt SubMenuItemWidth; //子菜单的宽度 MenuItemStru * SubMenuItemAddr; //子菜单数据结构地址 ShortInt MenuItemStrWidth; //菜单项字符串长度 char * MenuItemStrAddr; //菜单项的字符串地址 };

⒋菜单数据的组织

看“实验用蓝本结构代码.cpp” ⒌理解菜单数据组织与程序的关系 ⒍改进实训练三

①掌握结构体变量和指针的使用; 如MainMenu[i]. MenuItemStrAddr

②在一循环中用结构体变量或指针来访问相关参数; ③在循环中加入打印字符串语句,显示出主菜单; ④加入颜色等,实现主界面。

实训五 菜单系统的设计

整个菜单系统的设计需要进一步抽象。设计时要考虑扩展性和通用性的问题:菜单数据的改变,如我们的实例中只有3层菜单,如果把菜单数据增加到4、5等层次菜单时,你所编写的程序代码在只允许修改菜单数据,而不允许修改所有的函数的情况下,你的设计是否能达到此目标?

要实现上述目标,必须对处理过程进行抽象。菜单系统总体上应该如此实施:

①显示主菜单;②读键(暂定有效键为“→、←、↑、↓、Esc、Enter”);③处理有效键。④反复执行②③。特别要注意整个程序中只有一处读键的地方。

由于菜单系统选择的层次性,我们必须对菜单选择的(中间)过程进行有效保存,以便回溯。如当我们进入主菜单项的“Options”→“Compiler”→“Compiler”的子菜单,当我们用“Esc”键时可以回退到“Compiler”状态,从“Compiler”还可以回退到“Options”状态。

为有效管理这种选择状态,我们必须对选择状态加以保存。我们采取以下结构体来保存选择的历史信息:

typedef struct MenuSelectStru{

ShortInt MenuIndex,MenuItemTotal; //选择菜单中的哪项

MenuItemStru * pMenu; //对应主菜单/子菜单的数据结构地址 PCHAR_INFO AddrOfSaveText; //备份下拉菜单区域的空间 bool PullDownMenu; //下拉菜单有否显示 ShortInt left,top,right,bottom; };

字段名 以ASCII码方式存放,最大长度是10个字符,若字段名长度少于10个字符则以空字符(0x00)填充

字段类型 以ASCII码方式存放,1个字符,其值为 Field type: C – Character Y – Currency N – Numeric F – Float D – Date T – DateTime B – Double I – Integer L – Logical M – Memo G – General

C – Character (binary) M – Memo (binary) P – Picture

+ – Autoincrement (dBase Level 7) O – Double (dBase Level 7) @ – Timestamp (dBase Level 7)

DBF数据表文件的结构结束标志为\,占1个字节。对于VFP表文件从\所在的字节开始的263B用于描述自由表或数据库表的相关信息(若为自由表则取值全为零)。

其VFP表文件长度 = 32(文件头)+32*字段个数+1(结束标志)+263。然后是数据部分记录1、记录2……记录n

各记录均为定长格式,以ASCII码方式顺序存放。

每个记录的第一个字节是删除标志,若记录被删除,则该字节为0x2A即\;否则为0x20即空格。 各记录间无分隔符

整个文件的结束标志为0x1A,位于最后一个记录之后的一个字节中。

struct dbf_head { /* DBF文件头结构 */

char vers; /* 版本标志*/

unsigned char yy,mm,dd; /* 最后更新年、月、日 */ unsigned long no_recs; /* 文件包含的总记录数 */

unsigned short head_len,rec_len; /* 文件头长度,记录长度 */ char reserved[20]; /* 保留 */ };

struct field_element{ /* 字段描述结构 */ char field_name[11]; /* 字段名称 */ char field_type; /* 字段类型 */ unsigned long offset; /* 偏移量 */ unsigned char field_length; /* 字段长度 */

unsigned char field_decimal; /* 浮点数整数部分长度 */ char reserved1[2]; /* 保留 */

char dbaseiv_id; /* dBASE IV work area id */ char reserved2[10]; /* char production_index; };

/************************************************************************************

COMMENTS:DBF文件的总体格式

a.数据记录部分,紧随结构描述部分,以ASCII码方式顺序存放,结束标志为1AH(即 文件结束标志),每条记录的首字节为删除标志,20H表示有效,2AH表示已被删除, 字段值间无分隔符,记录亦无结束标记.

b.结构描述部分,位于文件首部,以二进制方式存放,结束标志为0DH.长度 为32*(数据库的字段个数+1(即库整体描述))+1(0DH结束标志)

************************************************************************************/ #include #include #include

//DBF 文件头结构//即库整体描述表,共32个字节 typedef struct tagDBFFILEHEADER {

unsigned char dfMark; //0x03h 或 0x80h(有MEMORY字段) 0 unsigned char dfYear,dfMmonth,dfDay; //依次为年月日,二进制 1-3 unsigned long dfRecordCount; //总记录个数,低位字节在前 4-7

unsigned short dfHeaderLength; //文件头长度=第9字节值*256+第8字节值 8-9 unsigned short dfRecordLength; //记录长度=第11字节值*256+第10字节值 10-11 unsigned char dfReserved[20]; //保留 12-31 }DBFFILEHEADER;

//DBF 字段结构//即字段描述表,32个字节/字段 typedef struct tagDBFINFOHEADER

{

unsigned char diFieldName[10]; //字段名称,ASCII码 0-9 unsigned char diReserved1; //保留字节 10

unsigned char diFieldType; //字段类型,CDNL等ASCII码 11 unsigned long diOffset; //本字段在首记录中的位置 12-15 unsigned char diFieldLength; //字段长度 <=256 16 unsigned char diDecimal; //小数点的位数 17 unsigned char diReserved[14]; //保留 18-31 }DBFINFOHEADER;

typedef DBFFILEHEADER *LPDBFFILEHEADER; typedef DBFINFOHEADER *LPDBFINFOHEADER;

/************************************************************************************ CDBFFile class defination.

************************************************************************************/ class CDBFFile { public: CDBFFile();

virtual ~CDBFFile();

long InitDbf(LPCTSTR lpszFilename); //填充FILEHEADER和INFOHEADER int GetFieldCount();

int GetFieldLength(int FieldNum); int GetDecimal(int FieldNum);

unsigned char * GetFieldName(int FieldNum); unsigned char GetFieldType(int FieldNum); long GetRecordCount(); int GetRecordLength();

int GetRecord(int RecordNum,unsigned char *pBuf);

int GetRecordFieldValue(int RecordNum,int FieldNum,unsigned char *pBuf); unsigned long GetFieldColumSize(int fieldnum); public:

unsigned char * m_Buffer; DBFFILEHEADER m_FileHeader; DBFINFOHEADER m_InfoHeader; DWORD m_dwRecordLen; };

/************************************************************************************ COMMENTS:CDBFFile实现文件

************************************************************************************/

int CDBFFile::GetDecimal(int FieldNum) {

if (FieldNum < 1) return -1;

unsigned char * p = &(m_Buffer[FieldNum * 32]); memcpy(&m_InfoHeader, p, sizeof(m_InfoHeader)); return(m_InfoHeader.diDecimal); }

/************************************************************************************ FUNCTION: 获取记录个数 PARAMETER: None RETURN VALUE:获取记录个数

************************************************************************************/ long CDBFFile::GetRecordCount() {

return(m_FileHeader.dfRecordCount); }

/************************************************************************************ FUNCTION: 获取记录长度 PARAMETER: None RETURN VALUE:记录长度

************************************************************************************/ int CDBFFile::GetRecordLength()

{

return(m_FileHeader.dfRecordLength); }

/************************************************************************************ FUNCTION: 获取任一记录内容

PARAMETER: [in] RecordNum (base 1)记录索引 [out] *pBuf 记录内容

RETURN VALUE:参数错误返回0 成功返回1

************************************************************************************/ int CDBFFile::GetRecord(int RecordNum,unsigned char *pBuf) {

if (RecordNum < 1) return 0;

long lPos=m_FileHeader.dfHeaderLength + (RecordNum-1) * m_dwRecordLen; //(DBFFILEHEADER+DBFINFOHEADER+头结束标志)+(RecordNum-1)*(记录长度) unsigned char * p = &(m_Buffer[lPos]); memcpy(pBuf, p, m_dwRecordLen); return 1; }

/************************************************************************************ FUNCTION: 获取任一记录的任一字段值

PARAMETER: [in] RecordNum (base 1)记录索引

[in] iFieldNum (base 1)字段索引 [out] *pBuf 记录内容

RETURN VALUE:参数错误返回0 成功返回1

************************************************************************************/

int CDBFFile::GetRecordFieldValue(int iRecordNum,int iFieldNum,unsigned char *pBuf) {

char szLeft[100]; char szRight[100];

int i, iFieldLen, iBegin, iFieldCount; memset(szLeft, 0, sizeof(szLeft)); memset(szRight, 0, sizeof(szRight)); iFieldCount = GetFieldCount();

if(iRecordNum < 1 || iFieldNum < 1 || iFieldNum> iFieldCount) return 0; iFieldLen=GetFieldLength(iFieldNum); int iOffset=1; //记录的删除标志2AH/20H for (i=1; i

iOffset+=GetFieldLength(i); }

long lPos=iOffset + m_FileHeader.dfHeaderLength+(iRecordNum-1)*GetRecordLength(); unsigned char * p = &(m_Buffer[lPos]);

memcpy(pBuf, p, iFieldLen);

pBuf[iFieldLen]=0x0; //注意参数pBuf必须足够大(指定字段长度+1) strcpy(szLeft, (char *)pBuf); for(i=iFieldLen-1; i> =0; i--) {

if(szLeft[i]= ' ') szLeft[i] = 0; else break; }

if(szLeft[0]==0) {

strcpy((char *)pBuf, szLeft); return 1; }

for(i=0; i

if(szLeft[i]!= ' ') {

iBegin = i; break; } }

memcpy(szRight, szLeft+iBegin, iFieldLen-iBegin); strcpy((char *)pBuf, szRight); return 1; }

/************************************************************************************ FUNCTION: 获取字段宽度

PARAMETER: [in] iFieldNum (base 1)字段索引 RETURN VALUE:参数错误返回0 成功返回字段宽度

************************************************************************************/ unsigned long CDBFFile::GetFieldColumSize(int fieldnum) {

int iFieldCount;

iFieldCount = GetFieldCount();

if (fieldnum < 1 || fieldnum> iFieldCount) return 0; return GetFieldLength(fieldnum) * GetRecordCount(); }

本文来源:https://www.bwwdw.com/article/c36x.html

Top