C++程序设计大作业2.docx

上传人:b****7 文档编号:16280361 上传时间:2023-07-12 格式:DOCX 页数:28 大小:24.67KB
下载 相关 举报
C++程序设计大作业2.docx_第1页
第1页 / 共28页
C++程序设计大作业2.docx_第2页
第2页 / 共28页
C++程序设计大作业2.docx_第3页
第3页 / 共28页
C++程序设计大作业2.docx_第4页
第4页 / 共28页
C++程序设计大作业2.docx_第5页
第5页 / 共28页
C++程序设计大作业2.docx_第6页
第6页 / 共28页
C++程序设计大作业2.docx_第7页
第7页 / 共28页
C++程序设计大作业2.docx_第8页
第8页 / 共28页
C++程序设计大作业2.docx_第9页
第9页 / 共28页
C++程序设计大作业2.docx_第10页
第10页 / 共28页
C++程序设计大作业2.docx_第11页
第11页 / 共28页
C++程序设计大作业2.docx_第12页
第12页 / 共28页
C++程序设计大作业2.docx_第13页
第13页 / 共28页
C++程序设计大作业2.docx_第14页
第14页 / 共28页
C++程序设计大作业2.docx_第15页
第15页 / 共28页
C++程序设计大作业2.docx_第16页
第16页 / 共28页
C++程序设计大作业2.docx_第17页
第17页 / 共28页
C++程序设计大作业2.docx_第18页
第18页 / 共28页
C++程序设计大作业2.docx_第19页
第19页 / 共28页
C++程序设计大作业2.docx_第20页
第20页 / 共28页
亲,该文档总共28页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

C++程序设计大作业2.docx

《C++程序设计大作业2.docx》由会员分享,可在线阅读,更多相关《C++程序设计大作业2.docx(28页珍藏版)》请在冰点文库上搜索。

C++程序设计大作业2.docx

C++程序设计大作业2

《程序设计基础》大作业

 

姓名:

学号:

班级:

成绩:

 

信息科学与工程学院

2009年7月5日

程序设计基础大作业

1.矩阵的综合运算

1.1.需求陈述

此程序为设计一套C函数库用于矩阵的计算,实现矩阵的各种计算功能,同时把矩阵的行列和矩阵的元素封装在一起,使关于矩阵的各种信息更加方便被用户运用。

1.2.需求分析

函数功能需求:

项目

功能

子功能

备注

Matrix

初始化

矩阵的初始化initMatrix()

矩阵的具体定义为:

typedefstruct{

size_tline;

size_trow;

intel[MAX_MATRIX][MAX_MATRIX];

}Matrix;

初始化为单位矩阵Identity()

从文件输入readMatrix()和

向文件输出writeMatrix()

矩阵运算

判断矩阵是否为空:

isEmptyMatrix()

矩阵加法addMatrix

矩阵乘法multiMatrix()

求逆矩阵inverseMatrix()

求矩阵的转置transMatrix()

求矩阵行列式的值

数据需求:

为提高计算准确性和节约时间,故提前在文件中录入数据,矩阵计算时大多直接调用。

1.3.程序设计思想

1.3.1数据类型

矩阵采用静态的二维整型数组来表示,将矩阵的行数、列数和二维数组封装在一个结构体中。

矩阵的上限可用符号常量“MAX_MATRIX”来表示,实际的行和列的项数由结构体中表示行和列的数据项控制。

矩阵的具体定义为:

#defineMAX_MATRIX100

typedef{

size_tline;//矩阵的行数

size_trow;//矩阵的行数

intel[MAX_MATRIX][MAX_MATRIX];//矩阵元素

}Matrix;

1.3.2功能分析

a)矩阵的初始化MatrixinitMatrix(int*a,size_tm,size_tn)

功能:

用一个m行n列的二维数组a来初始化一个矩阵,把行列和元素封装在一起,该矩阵的值作为返回值,返回值的类型为一个结构体类型。

实现思路:

矩阵的行数初始化为二维数组的行数,矩阵的列数初始化为二维数组的列数,矩阵的元素初始化为二维数组的元素。

返回初始化后的矩阵。

b)初始化为单位矩阵MatrixIdentity(size_tm);

功能:

创建一个m行m列的单位矩阵,矩阵的值作为返回值,返回值的类型为一个结构体类型。

实现思路:

矩阵的行和列初始化为相同值,矩阵的对角线元素初始化为1,其余元素初始化为0。

返回初始化后的矩阵。

c)判断矩阵是否为空:

size_tisEmptyMatrix(Matrixa);

功能:

判断一个矩阵a是否为空,是指某个matrix型变量内是否有数据,即是否已经存储了矩阵;返回值用来表示矩阵的元素个数:

矩阵为空则返回0,否则返回矩阵元素个数。

实现思路:

若矩阵为空,则行列数为0,否则为非0,故可直接返回矩阵的行和列的乘积a->line*a->row。

d)从文件输入intreadMatrix(Matrix*a,size_tm,size_tn,FILE*fp);和向文件输出intwriteMatrix(Matrix*a,FILE*fp);

功能:

从文件fp中读取一个m行n列的矩阵,存入指针a所指示的存储空间内;向文件fp写入指针a所指示的存储空间内的矩阵;返回值均为实际读出(写入)的矩阵元素数目、若不能读或写则返回0。

实现思路:

从文件读出矩阵时,打开文件,不能读时返回0,否则读出m*n个元素,矩阵的行为m,矩阵的列为n。

向文件写入矩阵时,不能写返回0,否则向文件写入m*n个元素,每n个为一行,共m行。

e)矩阵加法Matrix*addMatrix(Matrix*a,Matrix*b)

矩阵乘法Matrix*multiMatrix(Matrix*a,Matrix*b)

功能:

把指针a所指示的存储空间内的矩阵与指针b所指示的存储空间内的矩阵向加(相乘),结果放入a所指示的存储空间内,返回值为存储结果的地址。

实现思路:

实现矩阵的加法时,若两矩阵为空矩阵或对应行列不相等,则不能相加,返回空指针NULL,否则,对应元素相加,结果放入a中,返回a;实现矩阵的乘法时,若两矩阵为空矩阵或a的列数和b的行数不相等,则不能相乘,返回空指针NULL,否则,a的行数为乘积矩阵的行数,b的列数为乘积矩阵的列数,a的第i行和b的第j列的对应元素的乘积的和为乘积矩阵的i行j列的元素。

乘积放入a中,返回乘积矩阵的地址a。

关键代码:

/*a的第i行和b的第j列的对应元素的乘积的和为乘积矩阵的i行j列的元素*/

for(inti=0;i

for(intj=0;j

c.el[i][j]=0;

for(intk=0;krow;k++)

c.el[i][j]+=a->el[i][k]*b->el[k][j];

}

f)求矩阵的转置MatrixtransMatrix(Matrix*a)

功能:

求矩阵a的转置,返回转置矩阵。

实现思路:

把a的元素关于对角线互换,返回转置矩阵。

g)求行列式的值doubleHANGLIESHI(Matrixa)

功能:

在能求行列式的值时,计算行列式的之值并返回结果。

实现思路:

若矩阵为空矩阵或矩阵不是方阵,则不能求行列式的值,返回0。

若矩阵只有一个元素,行列式的值就是该元素的值。

否则运用递归方法,把行列式按行展开,求每个元素的代数余子式和该元素的积,在求和,即为行列式的值。

关键代码:

/*去掉第1行第j列,求其余子式*/

{if(t

b.el[s][t]=a.el[s+1][t];//去掉第1行元素

else

b.el[s][t]=a.el[s+1][t+1];//去掉第1行第j列}

/*运用递归方法,把行列式按行展开,利用代数代数余子式求行列式的值,b为a[i][j]的余子式*/

result+=pow(-1,(1+j+1))*a.el[0][j]*HANGLIESHI(b);

h)求逆矩阵MatrixinverseMatrix(Matrixa)

功能:

在能求矩阵的逆矩阵时,求矩阵的逆,并返回逆矩阵。

实现思路:

若矩阵为空矩阵或矩阵不是方阵或矩阵的行列式为0,则不能该矩阵的逆矩阵,返回空矩阵。

若矩阵只有一个元素,行列式的值就是该元素的值。

否则运用递归方法,把行列式按行展开,求每个元素的代数余子式和该元素的积,在求和,即为行列式的值。

关键代码:

/*以下用递归求行列式的值*/

if(a.line==1){

b.el[0][0]=1.0/a.el[0][0];//只有一个元素时,逆矩阵为其倒数

returnb;

}

/*递归求逆矩阵,temp为a[i][j]的余子式*/

b.el[j][i]=pow(-1,i+j)*HANGLIESHI(temp)/HANGLIESHI(a);

}

2.字符串操作

2.1.需求陈述:

设计一套C函数库用于字符串的操作,同时把字符串的长度和字符串封装在一起,使字符串操作时不会越界,保证字符串的长度的值随字符串内容的改变而改变,使关于字符串的各种信息更加方便被用户运用。

2.2.需求分析:

函数功能需求:

项目

功能

子功能

备注

String

基本功能

字符串的初始化StringInit()

字符串采用如下结构体来表示:

typedefstruct{

size_tlen;

charch*;

}Str;

实现字符串操作时不会越界。

实现功能不会弱于原库函数

字符串的销毁StringDes()

初始化为空串initNullString()

判断是否为空串isNullString()

求字符串长度StringLen()

字符串操作函数的封装

字符串比较StringCmp()

字符串拷贝StringCpy()

字符串连接StringCat()

取字符在串中第一次出现的位置取StringChr()

取字符在串中最后一次出现的位置取StringrChr()

取子串在串中第一次出现的位置取StringStrr()

字符串的前n个字符的比较StringnCmp()

字符串的前n个字符的拷贝StringnCpy()

去字符串中常见的控制符StringTrim()

字符串的文件输入输出

字符串的字符终端界面的标准输入输出

数据需求:

为提高计算准确性和节约时间,故提前在文件中录入字符串,字符串操作时大多直接调用。

2.3.程序设计思想

2.3.1数据类型

字符串采用如下结构体来表示:

typedefstruct{

size_tlen;

charch*;

}Str;

这里的字符指针ch是指向一块动态分配的连续存储空间,即一个C字符串。

所谓C字符串是指C语言中没有特殊的字符串类型,而是用一个结尾为“\0”字符数组来表示字符串。

len表示字符串的实际长度,即用len==strlen(ch),不包括“\0”的内容。

这个数据结构的关键在于保证ch的内容有足够的存储空间(不会越界),保证长度len的值随字符串内容ch的改变而改变。

2.3.2功能分析

a)字符串的初始化StrStringInit(char*s)、

字符串的销毁voidStringDes(Str*s)

功能:

字符串的初始化用一个C字符串来初始化一个Str类型字符串,返回值为初始化后的字符串,在这个函数中调用malloc()函数来申请动态内存空间;字符串的销毁的目的是调用free()函数来释放空间,返回一个Str字符串。

实现思路:

字符串的初始化,用一个字符串来初始化一个结构体类型,长度为字符串的长度。

ch为字符串地址,初始化时需为字符串分配内存空间。

字符串的销毁,释放字符串所占内存,同时把字符串长度值赋值为0。

关键代码:

s1.ch=(char*)malloc(sizeof(char)*(strlen(s)+1));//为字符串分配内存空间

free(s->ch);//释放内存空间

s->len=0;//长度赋值为0

b)初始化为空串StrinitNullString()、

判断是否为空串并求字符串长度size_tisNullString(Str*s)

功能:

初始化为空串,初始化成一个空字符串。

判断是否为空串并求字符串长度,为进行字符串操作,先判断字符串是否为空。

实现思路:

初始化为空串,把Str类型的结构体成员(字符串和长度)都赋值为0。

判断是否为空串并求字符串长度,若结构体成员中字符串长度为0,则字符串为空,否则不为空,返回字符串的长度值。

关键代码:

/*长度和内容都为空*/

empty.len=0;

empty.ch=0;

c)字符串比较intStringCmp(Str*s1,Str*s2)、

字符串拷贝Str*StringCpy(Str*s1,Str*s2)、

字符串连接Str*StringCat(Str*s1,Str*s2)

功能:

字符串比较,实现两个字符串的比较,返回比较大小值;字符串拷贝,把s2的字符串拷贝到s1中,返回拷贝后的字符串地址;字符串连接,把s2的字符串连接到s1的后面,返回连接后的字符串的地址。

实现思路:

字符串比较,用库函数比较;字符串拷贝,弱s1的字符串的长度小于s2,需重新给s1分配内存空间,然后用库函数把s2拷贝到s1中;字符串连接,连接后的字符串的长度大于s1,故需给s1重新分配内存空间,用库函数把s2连接到s1后面。

关键代码:

/*s1的存储空间不够,需重新开辟空间*/

if(s1->lenlen){

StringDes(s1);//释放原来空间

s1->ch=(char*)malloc(sizeof(char)*(s2->len+1));//重新开辟空间

}

/*字符串的连接,s1内存不够,需重新开辟空间*/

StringDes(s1);//释放原来空间

s1->ch=(char*)malloc(sizeof(char)*(s1->len+s2->len+1));//重新开辟

d)取字符在串中第一次出现的位置char*StringChr(Str*s1,charc)

取字符在串中最后一次出现的位置char*StringrChr(Str*s1,charc)

取子串在串中第一次出现的位置char*StringStrr(Str*s1,Str*s2)

功能:

查找字符或字符串在另一字符串中出现的位置,返回值为找到的地址。

实现思路:

直接用c语言库函数查找。

e)字符串的前n个字符的比较intStringnCmp(Str*s1,Str*s2,size_tn)、字符串的前n个字符的拷贝char*StringnCpy(Str*s1,Str*s2,size_tn)

功能:

字符串的前n个字符的比较,实现两个字符串钱n个字符之间的比较,返回比较结果。

字符串的前n个字符的拷贝,实现两个字符串前n个字符之间的拷贝,返回拷贝结果的地址。

实现思路:

字符串的前n个字符的比较,直接用c语言库函数比较两字符串的前n个字符,返回比较大小。

字符串的前n个字符的拷贝,若s1中字符串测长度小于s2,需给s1重新分配内存空间,再用c语言库函数实现前n个字符的拷贝,返回拷贝结果的地址。

关键代码:

/*若s1的长度小于n,需重新分配空间*/

if(s1->len

StringDes(s1);//释放原来空间

s1->ch=(char*)malloc(sizeof(char)*n);//重新开辟空间

}

f)去字符串中常见的控制符size_tStringTrim(Str*s)

功能:

把字符串s中常见的文本占位符:

回车(“\n”值13)、换行(“\r”值10、也叫软回车)、走纸符(“\f”值12)、水平制表符(“\t”值9)、垂直制表符(“\v”值9)、空格(“”值32)。

返回值为修改后s的长度。

实现思路:

一次从第一个字符开始查找,若第i个字符为控制符,查找后面的字符,若不为控制符,赋值给第i个字符。

字符串的长度为新字符串的长度,并返回长度值。

关键代码:

for(i=0;ilen+1;i++)

{/*若第i个字符为控制符,查找第i个字符之后第一个不为控制符的字符*/

if(isspace(s->ch[i])!

=0){

for(t=i;tlen+1;t++)

{/*找到后赋值给第i个字符*/

if(isspace(s->ch[t])==0)

s->ch[i++]=s->ch[t];

}

}

}

g)字符串的文件输入输出size_tfgetSring(Str*s,intn,FILE*stream)、size_tfputSring(Str*s,FILE*stream)

功能:

fputSring()把s中的字符串内容输出到文件流stream中,fgetSring从文件流stream中读取长度不超过n的字符,放入字符串s中。

返回值意为实际读取或写入的字符串长度。

实现思路:

打开文件,若不能读或写,返回0,否则,从文件读出字符串初始化为Str型,返回读取的字符串的长度;把字符串写入文件,返回写入的字符串的长度。

h)字符串的字符终端界面的标准输入输出char*getSring(Str*s,intn)、size_tfputSring(Str*s,FILE*stream)

功能:

从屏幕输入字符串和把字符串输出到屏幕,返回字符串的长度值。

3.动态双向链表的操作

3.1.需求陈述:

设计一套C函数库用于动态双向循环链表的操作,同时把链表的结点数和链表的数据内容串封装在一起,使关于链表的各种信息更加方便被用户运用。

3.2.需求分析:

函数功能需求:

项目

功能

子功能

备注

LinkList

基本功能

创建结点creat_node()

/**链表结点中存储的数据的类型:

LNodeT**/

typedefintLNodeT;

/**链表结点的数据类型的预先声明**/

structlinklist;

/*双向链表结点的数据类型,两部分:

data为数据、next指向下一结点的地址,pre指向上一个结点的地址*/

structlinklist{

LNodeTdata;

structlinklist*next;

structlinklist*pre;

};

字符串的销毁erase_node()

头部插入insert_first()

尾部追加insert_tail()

头部删除delete_first()

尾部删除delete_tail()

按数据内容在链表中插入结点insert_by_data()

按顺序在链表中插入结点insert_by_sub()

获取链表的长度linklen()

按数据内容匹配结点travel_bydata()

按下标访问链表trabel_byseq()

数据需求:

为提高计算准确性和节约时间,故提前在主函数中录入,链表操作时大多直接调用。

3.3.程序设计思想

3.3.1数据类型

链表结点中存储的数据的类型为LNodeT,这里先定义为int类型。

typedefintLNodeT;

双向循环链表结点的数据类型包括两部分:

data为数据、next和pre为向前和向后指针、分别用来存储前一结点和后一结点的地址。

structlinklist{

LNodeTdata;

structlinklist*next;/**向后的指针**/

structlinklist*pre;/**向前的指针**/

};

定义链表的数据类型LinkT,链表里每个结点都采用动态的内存分配。

typedefstructlinklistLinkT;

3.3.2功能分析

a)创建结点LinkT*creat_node(LNodeTa)、

字符串的销毁#defineerase_node(p)(free(p))

功能:

creat_node()用来初始化一个结点,在这个函数里为结点分配内存空间,所以要用一个LNodeT类型的参数把结点数据传进来;返回一个链表结点的指针LinkT*,把访问存储空间的首地址传出去。

erase_node()用来释放一个链表的结点,它需要一个结点的存储位置。

实现思路:

首先为新结点开辟内存空间,然后把数据赋值给新节点,把向前和向后的指针赋值为空,返回该结点的地址。

关键代码:

LinkT*p=(LinkT*)malloc(sizeof(LinkT));//为新节点开辟空间

p->next=NULL;//把向后的指针赋值为空

p->pre=NULL;//把向前的指针赋值为空

b)头部插入LinkT*insert_first(LinkT*head,LinkT*p)

LinkT*insert_first1(LinkT*head,LNodeTa)

尾部追加LinkT*insert_tail(LinkT*head,LinkT*p)

功能:

在链表的头部和尾部分别插入一个结点,返回新链表的头指针。

实现思路:

头部插入:

若原链表为空,新链表只有一个结点,向前和向后的指针指向本身。

否则,新结点的向前的指针指向原链表的尾,向后的指针指向原链表的第一个结点,head指向新结点,插入新结点。

若根据结点的数据内容插入,需先创建结点。

尾部追加:

若原链表为空,新链表只有一个结点,相当于在头部插入,否则,相当于先在头部插入,再把head向后移动一个位置。

关键代码:

1头部插入中

if(!

head)//此时原链表为空链表,插入后只有一个结点

{

p->next=p;

p->pre=p;

head=p;

}

else

{

p->pre=head->pre;//p的前一个结点指向原链表尾

p->next=head;//p的后一个结点指向原链表头

head->pre->next=p;//原链表尾的下一个结点指向p

head->pre=p;//原链表头的上一个结点指向p

head=p;//链表头改变

}

2尾部追加中

if(!

head)//原链表为空,相当于在头部插入一个结点

head=insert_first(head,p);

else

{/*相当于先在头部插入,再把head向后移动一个位置*/

q=insert_first(head,p);

head=q->next;

}

c)头部删除LinkT*delete_first(LinkT*head)、

尾部删除LinkT*delete_tail(LinkT*head)

功能:

在链表的头部和尾部分别删除一个结点,返回新链表的头指针。

实现思路:

头部删除:

链表为空,不用删除,若有一个结点,删除该结点,新链表为空。

否则,head后移一个位置,原来的head结点释放掉。

尾部删除:

链表为空,不用删除,否则,相当于head向前移动一个位置,删除头结点。

关键代码:

1头部删除中

elseif(head->next==head)//只有一个结点,删除该结点{

erase_node(head);//释放结点

head=NULL;//此时新链表为空

}

else

{/*把头结点删除,并释放掉,head向后移动一个位置*/

p=head->next;

head->pre->next=p;

p->pre=head->pre;

erase_node(head);//释放结点

head=p;

}

2尾部删除中

else

{/*相当于head向前移动一个位置,删除头结点*/

head=q;

head->next=p;

p->pre=head;

q->pre->next=head;

returndelete_first(head);//返回删除结点后的头指针

}

d)按数据内容在链表中插入结点LinkT*insert_by_data(LinkT*head,LNodeTnode)

按顺序在链表中插入结点LinkT*insert_by_sub(LinkT*head,LinkT*p,intn)

功能:

实现在链表中插入新结点,返回插入结点后的头指针。

实现思路:

按数据内容在链表中插入结点:

先把数据内容初始化为结点,若链表为空,相当于在头部插入,若第一个结点数据大于node,相当于在头部插入,否则,查找第一个大于node的结点,把新结点插入到该结点前面,没有找到,把新结点插入到尾部。

按顺序在链表中插入结点:

链表为空,相当于在尾部插入,若输入顺序值超过链表长度,不插入。

若n=1相当于在头部插入,否则,遍历链表,找到第n个位置,插入结点。

关键代码:

1按数据内容插入

LinkT*q,*p=creat_node(node);//先

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 人文社科 > 法律资料

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2