C++课程设计报告.doc
目录一、课程设计目的及要求21.1设计目的21.2设计要求21.2.1封装一个完善的字符串,实现字符串的基本操作21.2.2.利用C+中的类实现线性链表的常见操作21.2.3 编写一个银行ATM自动取款机模拟程序3二、课程设计具体实现32.1封装一个完善的字符串,实现字符串的基本操作32.1.1总体设计(总的任务画出总体设计图,总体设计方案及主要设计原理;(算法的设计)32.1.2详细设计(要求详细写出每个模块的功能实现,关键技术,关键代码解释等。)42.1.3调试及问题解决62.2利用C+中的类实现线性链表的常见操作62.2.1总体设计62.2.2详细设计62.2.3调试及问题解决62.3编写一个银行ATM自动取款机模拟程序62.2.1总体设计62.2.2详细设计62.2.3调试及问题解决6三、结束语(包括感想、致谢、设计总结)6四、源代码(代码要加注释)64.1封装一个完善的字符串,实现字符串的基本操作64.2利用C+中的类实现线性链表的常见操作94.3编写一个银行ATM自动取款机模拟程序194.3.1面向过程的程序设计194.3.2面向对象的程序设计24一、课程设计目的及要求1.1设计目的软件工程专业所开设的C+课程设计是教学实践环节中一项重要内容,进行此课程设计的旨在:1. 提高和加强学生的计算机应用与软件开发能力,使学生由初学者向专业的程序员过渡。2. 培养学生独立分析问题、解决问题、查阅资料以及自学能力,以适应计算机产业日新月异发展的形势。3. 学习和掌握C+程序设计方法以及上机调试技巧,为今后学习其它专业课程打好基础。 本次课程设计是以学生独立思考解决问题为主,教师指导为辅,结合上机操作,完成指定的任务,作出设计报告。1.2设计要求1.2.1封装一个完善的字符串,实现字符串的基本操作要求如下:l 定义一个串类CMyString,建立适当的构造函数l 字符串使用指针保存字符串l 必须实现如下操作,字符串比较、求串的长度、判断串是否为空、将串置空、字符串赋值(包括两个字符串类复制,一个字符串赋值到CmyString对象)、求字符串中的一个字符或改变字符串中的一个字符(采用重载),完成串的赋值与合并(重载+),得到表示字符串的指针地址l 在字符串类的基础上封装彩色字符串类。(学会使用继承和多态)可选1.2.2.利用C+中的类实现线性链表的常见操作 l 带表头结点(存放的是该线性链表的长度),结点存放的是整型数值; l 实现以下操作 :n 置空MakeEmpty()n 求长度Length() n 插入Insert(int x,int i): 将x插入到第i个结点(不含头结点)的之后; n 删除Delete(int x):删除链表中值为x的结点,成功返回1,否则返回0; n 删除 ReMove(int i):删除链表中第i个结点,成功返回1,否则返回0; n 搜索 Find(int x):在链表中查找数值为x的结点,成功返回1,否则返回0;n 显示 Display():显示整个链表各结点的数值。 l 写出类的构造函数、复制构造函数及析构函数 l 编写一个函数,使用户通过选择进行相关链表操作。1.2.3 编写一个银行ATM自动取款机模拟程序实现ATM取款机的基本功能,如给用户提供查询余额、取款、修改密码、吃卡、退出系统等服务,可根据实际情况添加(如缴费、转账等服务)。 l 对于用户要求输入相应的帐号和密码,如果三次出错则将卡吃掉并打印出相应凭条。 l 若输入的取款金额超出账户余额,则提示用户输入有误并提供更正功能 二、课程设计具体实现2.1封装一个完善的字符串,实现字符串的基本操作2.1.1总体设计(总的任务画出总体设计图,总体设计方案及主要设计原理;(算法的设计)CMyString-string: char *-length: int +CMyString():+ CMyString(s :char *):+ CMyString(s : CMyString &):+getlength(): int +getcontents(): void +setcontents(s : char *): void + friend void strcompare(str1:CMyString, str2:CMyString): + strjudge(): void+ operator(n : int) : char &+friend CMyString operator +( CMyString &st1, CMyString &st2):+void operator =(const CMyString &s):图1-1-1字符串类的类图 通过类来实现字符串的封装,用成员函数和友元函数、运算符的重载来实现字符串的基本操作。2.1.2详细设计(要求详细写出每个模块的功能实现,关键技术,关键代码解释等。)操作模式:功能实现:用一个主函数,把许多功能融入集中关键代码:void main()char str2100;for(int i=0;i<2;i+)cout<<"第"<<i+1<<"个字符串:"cin>>stri;CMyString str1(str0),str2(str1);cout<<"第一个字符串的长度:"<<str1.getlength()<<endl;cout<<"第二个字符串的长度:"<<str2.getlength()<<endl;cout<<"两个字符串的比较:"strcompare(str1,str2);cout<<"判断字符串是否为空,并置空:"<<endl;cout<<"第一个字符串"str1.strjudge();cout<<"第二个字符串"str2.strjudge();str1.setcontents("liyushan");str2.setcontents(" studies hard."); CMyString str3("chengjingui");/字符串的赋值(调用带一个参数的构造函数)cout<<"第三个对象的内容:"str3.getcontents();cout<<"输入一个小于等于"<<str3.getlength()<<"的正整数:"int j;cin>>j;cout<<"输出第"<<j<<"个字符是:"<<str3j-1<<endl;str3=str1+str2;cout<<"第三个字符串的长度为:"<<str3.getlength()<<endl;cout<<"第三个字符串的内容是:"str3.getcontents(); str3.getaddress();字符串类:功能:实现字符串的封装,安全关键代码:class CMyString/类的定义char *string;/字符串的内容int length;/字符串的长度public:CMyString()/不带参数的构造函数length=0;string=NULL;CMyString(char *s)/带一个参数的构造函数length=strlen(s);string=new charlength+1;strcpy(string,s); CMyString(CMyString &s)/拷贝构造函数:来实现对象之间的拷贝length=s.length;string=s.string;;字符串的比较:功能:实现字符串的比较代码:void strcompare(CMyString s1,CMyString s2)/字符串的比较的实现(友元函数)int s;s=strcmp(s1.string,s2.string);if(s>0) cout<<s1.string<<"大于"<<s2.string<<endl;else if(s<0) cout<<s1.string<<"小于"<<s2.string<<endl;else cout<<s1.string<<"等于"<<s2.string<<endl;注意:1. 运用到类的成员函数的类外定义2. 运用到string.h 头文件中的strcmp()字符串的长度:代码:void getcontents()/求字符串的内容cout<<string<<endl;判断字符串是否为空:关键代码:friend void strcompare(CMyString str1,CMyString str2);/友元函数实现两个字符串对象的比较的声明void strcompare(CMyString s1,CMyString s2)/字符串的比较的实现(友元函数)int s;s=strcmp(s1.string,s2.string);if(s>0) cout<<s1.string<<"大于"<<s2.string<<endl;else if(s<0) cout<<s1.string<<"小于"<<s2.string<<endl;else cout<<s1.string<<"等于"<<s2.string<<endl;注意:1. 运用友元函数并类外定义:先声明再定义(不要加限定符)2. 要加关键字:friend 函数参数为对象3. 运用函数:strcmp()置空且赋值:功能的实现:是先用delete 来置空,再分配内存进行赋值代码:void setcontents(char *s)/先置空,再重置字符串的内容length=strlen(s);cout<<string<<"被置空"<<endl;delete string;string=new charlength+1;strcpy(string,s);cout<<"重置后:"<<string<<endl;注意:1. 参数为指针2. 指针要先分配内存再运用3. 运用new delede 来分配动态内存4. 要注意内存长度的选择(内存的空间)求字符串中的一个字符: 功能:要用运算符的重载 关键代码:char & operator(int n)/求字符串中的字符用运算符重载static char ch=0;if(n>length-1)cout<<"整数下标越界"<<endl;return ch;else return *(string+n);注意:下标运算符的重载:返回类型是char &完成串的赋值与合并:实现:重载+关键代码:CMyString operator +( CMyString &st1, CMyString &st2)/运算符+重载的实现(友元函数):实现两个字符串的连接CMyString t;t.length=st1.length+st2.length;/连接时:先计算长度,t.string=new chart.length+1;/再重新分配内存strcpy(t.string,st1.string);/先拷贝 再连接strcat(t.string,st2.string);return t;/返回类型是对象t注意:先分配再拷贝链接void operator =(const CMyString &s)/运算符=的重载delete string;string=new charstrlen(s.string+1);strcpy(string,s.string);注意:参数为类的引用得到表示字符串的指针地址:void getaddress()/得到字符串的指针地址cout<<"字符串的指针地址:"<<&string<<endl;2.1.3调试及问题解决问题1:出现乱码,内存为空解决:析构与置空同时运用,使内存出现2次删除,出现错误 运用默认构造函数问题2:拷贝构造函数的深浅拷贝问题解决:定义拷贝构造函数问题3:运算符的重载问题解决:要对=进行重载 解决问题2.2利用C+中的类实现线性链表的常见操作2.2.1总体设计Nodeint Data; Node *next;图2-2-1链表结构体list-Node *head; -int length;+list(); +list(list &l); +void create(); +list()delete head; +void MakeEmpty(); +int Length(); +void Insert(int x,int i);/将x插入到第i个结点(不含头结点)的之后 +int Delete(int x); /删除链表中值为x的结点,成功返回1,否则返回0 +int ReMove(int i); /删除链表中第i个结点,成功返回1,否则返回0 +int Find(int x); /在链表中查找数值为x的结点,成功返回1,否则返回0 +void Display(); /显示整个链表各结点的数值图2-2-2链表类2.2.2详细设计登录模式:功能的实现:用主函数:开始出现功能代码 1、创建一个链表 2、在第i个结点处插入值为x的结点 3、求链表的长度 4、删除值为x的结点 5、删除第i个结点 6.搜索结点 7. 显示所有的结点 8、置空结点 9. 退出函数 分别在其中调用各自的函数关键代码:void main()int a;list b;cout<<"*需要先创建一个链表再操作*"<<endl;while(1)cout<<" 选择你所需要的服务"<<endl;cout<<"1.创建一个链表"<<endl;cout<<"2.在第i个结点后插入值为x的结点"<<endl;cout<<"3.求链表长度"<<endl;cout<<"4.删除值为x结点"<<endl;cout<<"5.删除第i个结点"<<endl;cout<<"6.搜索结点"<<endl;cout<<"7.显示所有结点"<<endl;cout<<"8.置空结点"<<endl;cout<<"9.退出程序"<<endl;cout<<"请输入功能代码:"<<endl;cin>>a;if(a=1)b.create();b.Display();else if(a=2) int x,i;cout<<"分别输入要插入的数、位置i"<<endl;cin>>x>>i;b.Insert(x,i);b.Display();else if(a=3)cout<<"为链表长度:"<<b.Length()<<endl;else if(a=4)cout<<"请键入你所要删除的数字"<<endl;int c;cin>>c;b.Delete(c);b.Display();else if(a=5) cout<<"请键入你所要删除的位置"<<endl;int i;cin>>i;b.ReMove(i);b.Display(); else if(a=6)cout<<"请键入要查询的数"<<endl;int e;cin>>e;b.Find(e); else if(a=7)b.Display();else if(a=8)b.MakeEmpty();b.Display();else if(a=9)cout<<"BYEBYE!谢谢使用!"<<endl;exit(1);else cout<<"你输入有误."<<endl;continue;/结束本次循环,进行下一次的循环(continue 只能用于循环语句中的)cout<<"循环结束了。"<<endl;注意:循环的运用 Break continue return exit()的不同和运用创建一个链表:功能的实现:运用类的成员函数关键代码:void list:create()Node *p,*tail;int data,i;cout<<"输入链表的数据和长度"<<endl;cin>>data>>i;if(i=0)head=NULL;cout<<"创建一个空的链表。"<<endl;cout<<"重新创造个链表"<<endl;create();/递归调用elsewhile(length<i)length+;if(length=1)head=new Node;tail=head;head->Data=data;elsep=new Node;p->Data=data;tail->next=p;tail=p;cout<<"输入下一个结点的值"<<endl;cin>>data; tail->next=NULL;length-;注意:先确定插入的链表数 当是0时:我运用了递归让其建立一个不为空的链表 当不为0时,我先建立一个头文件,再在尾部加入新的结点,从而建立一个链表在第i个结点处插入值为x的结点: 功能的实现:需要找到第i个节点再插入x,不过要注意i的值l length:提示错误,用循环重写l i<=length:插入头文件后或插入中间结尾关键代码:void list:Insert(int x,int i)/将x插入到第i个结点(不含头结点)的之后Node *p,*q,*s,*t=head;s=new Node;/创建新结点:s s->Data=x;while(1)s->Data=x; /新结点的数据是:xif(i>length)cout<<"输入有误,请重新输入:"<<endl;cout<<"输入插入的数据和结点数:"cin>>x>>i;continue;elsefor(int j=1;j<i;t=t->next)/查找第i个结点j+;p=t; /p指向第i个结点,q指向第i+1个结点q=p->next;if(p=NULL)head=s;s->next=NULL;elseif(p->next!=NULL)s->next=q;p->next=s;elsep->next=s;s->next=NULL;break;求链表的长度:功能的实现:通过遍历链表来得到链表的长度 关键代码:int list:Length()/求链表的长度(结点数)Node *p=head;if(p=NULL)cout<<"该链表是空的。"<<endl;return length;elsefor(length=1;p->next!=NULL;p=p->next)length+;/长度return length; 注意:函数类型为int 删除值为x的结点功能的实现:从头往后找值为x的结点,找到后将其删除关键代码: int list:Delete(int x)/删除链表中值为x的结点,成功返回1,否则返回0Node *p=head,*q;/p用于指向结点x,q指向结点x的前一个结点(删除值为x的结点p)if(p=NULL) /若是空表cout<<"这是个空的链表,删除失败!"<<endl;return 0;if(p->Data=x)/若是第一个结点head=p->next;delete p;cout<<"删除第一个结点,值为"<<x<<endl;return 1;elsewhile(p->Data!=x&&p->next!=NULL)/查找值为x的结点p;q=p;p=p->next;if(p->Data=x)/如果有值为x的结点,返回1q->next=p->next;delete p;cout<<"删除了值为"<<x<<"的结点,删除成功。"<<endl;return 1;elsecout<<"没有该结点,删除失败!"<<endl;return 0;/没有,返回0 删除第i个结点功能的实现:找到结点将其删除关键代码:int list:ReMove(int i) /删除链表中第i个结点,成功返回1,否则返回0Node *p,*q,*t=head;for(int j=1;j<i;t=t->next)/查找第i个结点j+;p=t; /p指向第i个结点,q指向第i+1个结点 q=p->next;if(i=1)head=p->next;delete p;cout<<"删除第"<<i<<"个结点,删除成功!"<<endl;return 1;else if(i>1&&i<=length)q->next=p->next;delete p;cout<<"删除第"<<i<<"个结点,删除成功!"<<endl;return 1;else cout<<"链表中无该结点,删除失败!"<<endl;return 0; 搜索结点 :功能的实现:有循环的方法找到结点关键代码:int list:Find(int x)/在链表中查找数值为x的结点,成功返回1,否则返回0Node *p=head;length=1;while(p!=NULL&&p->Data!=x)length+;p=p->next;if(p->Data=x)cout<<"找到第"<<length<<"个结点是:"<<x<<endl;return 1;elsecout<<"没有找到数据是:"<<x<<"的结点"<<endl;return 0;显示所有的结点功能的实现:考虑空链表与非空的两种情况关键代码:void list:Display()/显示整个链表各结点的数值并输出链表的长度Node *p=head;length=0;if(head=NULL)cout<<"这是一个空的链表"<<endl;elsecout<<"该链表是:"while(p!=NULL)cout<<p->Data<<" "p=p->next;length+; cout<<endl;cout<<"该链表的长度为:"<<length<<endl; 置空结点 :功能的实现:从头往后删除,循环时p=p->next; head=p->next; delete p;p=head;关键代码:void list:MakeEmpty()/置空函数Node *p=head;if(p=NULL)cout<<"这个链表是空的。"<<endl;elsefor(;p->next!=NULL;p=p->next)head=p->next;delete p;p=head;delete p;head=NULL;return; 退出函数功能的实现:用exit()函数关键代码:else if(a=9)cout<<"BYEBYE!谢谢使用!"<<endl;exit(1);注意:本操作要退出程序:就需要退出循环,退出主函数,则用exit()或break或return 注意他们的区别!exit()重要2.2.3调试及问题解决问题1:链表的设计怎么吧?答:需要先创建一个非空链表再进行其他的操作。问题2:缺少头函数?答:在用exit()时缺少头文件。需要加上头文件#include<stdlib.h>,从而解决问题。问题3:创建一个链表时,当为空时不能继续进行?答:采用直接递归调用,实现创建一个非空的链表。2.3编写一个银行ATM自动取款机模拟程序2.2.1总体设计开始登陆界面输入选择代码i判断i的值i=ii=2i=3i=4i=5i=6i=7i为其他2.2.2详细设计登陆模块:功能的实现:通过7个代码实现功能之间的选择1.开户 2.存款3.取款 4.查询余额5.转账6.更改密码7.退出关键代码:void main() int i;while(1)cout<<"tt*n"<<endl;cout<<"tt* 欢迎使用自动取款机 *n"<<endl;cout<<"tt-n"<<endl; cout<<"tt请选择您要办理的手续:n"cout<<"tttt1.开户n"cout<<"tttt2.存款n" cout<<"tttt3.取款n" cout<<"tttt4.查询余额n" cout<<"tttt5.转账n"cout<<"tttt6.更改密码n" cout<<"tttt7.退出n" cout<<"tt请输入您要办理的项目的序号:" cin>>i;if(7=6)break;switch(i)case 1:openAccount();/开户break;case 2:saveMoney();/存款break;case 3:takeMoney();/取款break;case 4:check();/查询余额break;case 5:transfer();/转账break;case 6:changepassword();break;default:cout<<"aaatt你的输入有误,请输入1-7之间的数!n"开户:功能的实现:创建一个账号,用于下面的操作关键代码:/开户函数void openAccount()cout<<"tt欢迎开户::n"cout<<"tt请输入您的姓名:"cin>>name;cout<<"tt请输入您的卡号:"cin>>cardID;cout<<"tt请输入您的密码:"cin>>password;cout<<"tt请输入您的预存金额:"cin>>money;cout<<"tt恭喜您,开户成功!n"吃卡:功能的实现:如果密码三次输入错误,就吃卡,退出系统关键代码:void eatcard()long cid;char password120;for( int i=0;i<3;i+)cout<<"tt请输入您的卡号:"cin>>cid;cout<<"tt请输入您的密码:"cin>>password1;if(cid=cardID&&strcmp(password1,password)=0)cout<<"tt输入正确!"<<endl;return;elseswitch(i)case 0:case 1:cout<<"*卡号密码输入有误*ntt请重新输入:"<<endl;break;case 2:cout<<"*吃卡*"<<endl;exit(1);存款:功能的实现:先输入密码,进入存款关键代码:/存款void saveMoney()int money1;cout<<"tt欢迎使用取款业务:n"eatcard();cout<<"tt请输入您的存款金额:"cin>>money1;money=money+money1;cout<<"tt取款成功,卡上余额为:"<<money<<endl;取款:功能的实现:先输入密码,进行存款关键代码:/取款void takeMoney()int money1;cout<<"tt欢迎您使用取款业务n" eatcard();cout<<"tt请输入您取款的金额:"while(1)cin>>money1;if(money1>money)cout<<"取款超过存款金额"<<"("<<money<<")"<<",请重新输入:"elsemoney=money-money1;cout<<"tt取款成功,您卡上余额为:"<<money<<endl;return;查询余额:先输入密码,进行查询余额功能的实现:关键代码:/查询void check() cout<<"tt欢迎进行查询业务n"eatcard();cout<<"tt卡上余额为:"<<money<<endl;转帐:功能的实现:先输入密码,再转帐关键代码:/转账void transfer()long bcid;int money1;cout<<"tt欢迎使用转账业务n"<<endl; eatcard();cout<<"tt请输入您要转账的卡号:"cin>>bcid;cout<<"tt请输入您要转账的金额:"while(1)cin>>money1;if(money1>money)cout<<"转账金额超过存款金额"<<"("<<money<<")"<<",请重新输入:"elsemoney=money-money1;cout<<"tt转账成功,您卡上余额为:"<<money<<endl;return;修改密码:功能的实现:输入密码,再改密码关键代码:void changepassword()char password120,password220;cout<<"tt欢迎修改密码tt"<<endl;eatcard();while(1)cout<<"输入更改密码:"cin>>password1;cout<<"再输入一遍:"