当前位置:文档之家› 计算机基础与综合编程实验报告word文档

计算机基础与综合编程实验报告word文档

学号《计算机基础与综合编程实验》报告学院计算机科学与技术学院专业计算机类班级姓名指导教师日期1 实验目的通过迭代式开发,深入掌握C语言的文件、链表、结构体、动态内存管理等技术,开发实现一个计费管理软件。

2 系统功能与描述1.添加卡与查询卡的操作(1)添加卡信息。

①介绍添加卡信息时,将添加的卡信息保存到工程目录下的card.ams文件。

②输入a、输入菜单项编号1实现“添加卡”b、添加卡信息时输入的卡信息c、保存卡信息的文件路径③处理a、获取保存卡信息的文件路径。

b、获取添加的卡信息。

卡信息包括:卡号、密码、开卡金额、卡状态、开卡时间、截止时间、最后使用时间、使用次数、累积金额。

c、将每个卡信息组装成一条字符串,一张卡的每个信息间用“##”分隔。

d、将保存的卡信息的字符串写到工程目录下的card.ams文件末尾。

④输出a、保存成功,则显示添加的卡信息。

b、保存失败,则提示添加卡信息失败。

(2)查询卡信息:①介绍从工程目录下的card.ams文件中,读取并解析卡信息,将卡信息显示到界面中。

②输入a、输入菜单项编号2实现“查询卡”b、card.ams文件中的卡信息③处理a、获取保存卡信息的文件路径。

b、逐行读取该文件中的卡信息并解析。

c、将将解析结果保存到内存中,在界面上显示读取出来的卡信息。

④输出a、读取失败,提示没有该卡的信息。

b、读取成功,则在界面输出卡号,状态,余额,累计使用,使用次数,上次使用时间,一共六个信息。

2.上机:①介绍根据用户输入的卡号和密码,判断该卡能否进行上机。

更新可以上机卡的状态。

②输入a、输入菜单项编号3,实现“上机功能”b、输入卡号和密码c、链表和文件中添加过的卡信息③处理a、执行上机操作时,从卡信息文件中获取卡信息,添加到链表中。

b、以卡号和密码为条件,遍历链表中的卡信息,找到与输入条件相符的卡信息。

c、如果找到,以列表方式显示该卡的上机信息,并更新卡信息。

如果未找到,就提示用户。

④输出a、如果找到需要上机的卡的信息,则以列表的方式显示。

分为三列显示卡信息,依次为:卡号,余额,上机时间。

b、如果未找到,则向界面输出“上机失败”,提示用户3.下机:与上机类似,提示用户输入正确格式的下机的卡号及密码,若不存在此卡,则提示卡号不存在,若存在,则判断卡的状态,若为上机状态,更新下机信息,否则提示卡的状态及下机失败。

同时把上下机的时间,和扣除消费金额的余额输出。

4.项目拓展:I. 充值退费①介绍当用户选择“5充值”时,提示用户输入需要充值的卡的卡号、密码和充值金额。

充值完成后,以列表的方式显示该卡的充值信息,包括卡号、充值金额和余额;如果失败,则提示用户。

②输入a、输入菜单项编号“5”或者“6”b、输入需要充值或退费的卡的卡号和密码c、保存卡信息的文件路径data/card.ams,和保存在文件中的卡信息d、保存卡的充值和退费信息的文件路径data\money.ams③处理a、读取卡信息文件中的卡信息,保存到链表中。

b、以卡号和密码为条件,遍历链表,查询与该卡卡号和密码相同的卡信息c、如果找到,判断该卡是符合充值或退费的条件。

d、若充值或退费,以列表的方式显示该卡的充值或退费信息e、若充值或退费失败,则提示用户。

④输出a、若果充值或退费失败,则输出相应的提示信息b、若果充值或退费成功,则以列表的方式显示该卡的充值或退费信息II.充值优惠在充值的基础上判断充值金额在哪个优惠范围,进行相应的优惠。

III. 注销卡①介绍用户选择菜单项“8注销卡”后,提示用户输入需要注销的卡的卡号和密码。

以卡号为条件,遍历卡信息链表,查找符合条件的卡。

如果找到,以列表的方式显示注销的信息;如果未找到,提示用户。

注销的信息包括:卡号,退款金额②输入a、输入菜单项编号“8”b、输入需要注销的卡的卡号和密码c、保存卡信息的文件路径data/card.amsd、保存在文件中的卡信息③处理a、读取卡信息文件中的卡信息,保存到链表中。

b、以卡号为条件,遍历链表,找到第一个与该卡卡号和密码相同的卡信息c、如果找到,判断该卡是否符合注销条件d、注销失败,则提示用户e、注销成功,以列表的方式显示该卡的注销信息④输出a、如果注销失败,则输出“注销卡失败!”提示用户b、如果注销成功,则分两列来显示注销信息:卡号和退款金额3 典型算法分析(完整源码请见光盘)(1)搭建程序框架在主界面功能的基础上进行迭代开发。

程序按照三层结构进行构建:表示层、逻辑层、存储层。

然后通过分解与重组将程序分为几个模块,方便以后查看,修改,完善以及维护。

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>// 包含输入输出头文件#include<time.h>// 包含时间头文件#include<string.h>// 导入字符串处理函数#include<stdlib.h>// 包含动态内存分配头文件#include"model.h"// 包含数据定义头文件#include"service.h"// 包含业务处理头文件#include"global.h"// 包含全局定义头文件#include"tool.h"// 包含工具头文件go on>>接下来是宏定义部分#ifndef MENU_H#define MENU_Hvoid outputMenu(); // 声明输出菜单函数void add(); // 声明添加卡函数void query(); // 声明查询卡函数void exitApp(); // 声明退出应用程序函数void logon(); // 声明上机函数void settle(); // 声明下机函数void annul(); // 声明注销卡函数void addMoney(); // 声明充值函数void refundMoney(); // 声明退费函数#endif通过使用宏定义,可以有效防止程序过于繁杂,也能够使同一个语句能够在多次使用时不需要重复编写,从而不影响整个程序的运行,减少了工作量,提高了效率。

(2)文件的处理直接到卡文件中查找卡,通过循环读取卡,当卡的卡号正确时返回1,否则返回0int getCard(){int nCount = 0; // 卡信息数int i = 0;Card* pCard = NULL; // 卡信息lpCardNode node = NULL; // 结点信息lpCardNode cur = NULL; // 添加到链表中的结点// 清除链表中已经存在的数据if (cardList != NULL){releaseCardList();}// 初始化链表initCardList();// 获取卡信息个数nCount = getCardCount(CARDPATH);if (nCount == 0){return FALSE;}// 动态分配内存保存卡信息pCard = (Card*)malloc(sizeof(Card)*nCount);if (pCard != NULL){// 如果返回FALSE,表示读取卡信息失败if (0 == readCard(pCard, CARDPATH)){free(pCard);return FALSE;}// 将读取的卡信息,保存到链表中for (i = 0, node = cardList; i < nCount; i++){// 为结点分配内存cur = (lpCardNode)malloc(sizeof(CardNode));// 如果分配内存失败,则返回if (cur == NULL){free(pCard);return FALSE;}// 初始化新的空间,全部赋值为0memset(cur, 0, sizeof(CardNode));// 将卡信息保存到结点中cur->data = pCard[i];cur->next = NULL;// 将结点添加到链表尾部node->next = cur;node = cur;}// 释放内存free(pCard);return TRUE;}return FALSE;}(3)在卡信息链表中,查询卡号相同的卡信息Card* queryCards(const char* pName, int* pIndex){lpCardNode node = NULL;Card* pCard = NULL;// 从文件中,获取卡信息if (getCard() == FALSE){return NULL;}// 首先分配一个Card大小内存空间pCard = (Card*)malloc(sizeof(Card));if (pCard == NULL){return NULL;}// 从链表的头结点指向的下一个结点开始遍历node = cardList->next;// 遍历链表,结点为空表示到达链表尾部while (node != NULL){// 判断在遍历到的结点的学号中,查找是否包含pName字符串if (strstr(node->data.aName, pName) != NULL){// 如果有,则保存结点中的数据pCard[*pIndex] = node->data;(*pIndex)++;// 重新为指针分配内存pCard = (Card*)realloc(pCard, ((*pIndex) + 1) * sizeof(Card));}// 移到链表的下一个结点node = node->next;}return pCard;(4)更新卡信息文件中的一条卡信息int updateCard(const Card* pCard, const char* pPath, int nIndex){FILE* fp = NULL; // 文件指针int nLine = 0; // 文件卡信息数long lPosition = 0; // 文件位置标记Card bBuf;// 以读写模式打开文件,如果失败,返回FALSEif ((fp = fopen(pPath, "rb+")) == NULL){return FALSE;}// 遍历文件while ((!feof(fp)) && (nLine < nIndex)){// 逐行读取文件内容if (fread(&bBuf, sizeof(Card), 1, fp) != 0){// 获取文件标识位置lPosition = ftell(fp);nLine++;}}// 移到文件标识位置fseek(fp, lPosition, 0);fwrite(pCard, sizeof(Card), 1, fp);// 关闭文件fclose(fp);return TRUE;}}4 开发难点与体会这次实验比上学期难的多,并且要求各个方面知识都要学好,例如添加卡和查询卡要用文件和链表的知识。

相关主题