📄 41.cpp
字号:
/*我真诚地保证:
我自己独立地完成了整个程序从分析、设计到编码的所有工作。
如果在上述过程中,我遇到了什么困难而求教于人,那么,我将在程序实习报告中
详细地列举我所遇到的问题,以及别人给我的提示。
在此,我感谢 项光特对我的启发和帮助。下面的报告中,我还会具体地提到
他们在各个方法对我的帮助。
我的程序里中凡是引用到其他程序或文档之处,
例如教材、课堂笔记、网上的源代码以及其他参考书上的代码段,
我都已经在程序的注释里很清楚地注明了引用的出处。
我从未抄袭过别人的程序,也没有盗用别人的程序,
不管是修改式的抄袭还是原封不动的抄袭。
我编写这个程序,从来没有想过要去破坏或妨碍其他计算机系统的正常运转。
<学生姓名>:池信泽
本程序进行稀疏矩阵的加减乘法,只需输入矩阵中的非零元,输入时应输入非零元的位置,例如如果要输入
第一行第一列的元素,请输入"1,1,*(具体的数值)",并且输入的时候请按行列下标从小到大的顺序输入,
依此类推;如果输入的行数,或是列数有一个为0,则表示矩阵输入完成。以矩阵的形式输出,如果
输入的矩阵不能进行相应的运算,则报错*/
#include<stdio.h>
#include<malloc.h>
#include <stdlib.h>
#include <crtdbg.h>
#include <string.h>
#include <stdio.h>
#define MAXSIZE 1000
#define MAXRC 30
#define MAXLINE 20
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif // _DEBUG
#define _CRTDBG_MAP_ALLOC
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif//用于检查内存是否泄露
typedef enum Point{error,ok}Point;
typedef struct Triple{
int i,j;
float e;
}Triple;//元素类型
typedef struct Rls{
Triple data[MAXSIZE+1];
int rpos[MAXRC];
int mu,nu,tu;
}Rls,*PRls;//矩阵类型
int Maxmu=0,Maxnu=0;
//本函数用于打印菜单选项
void Menu_print()
{
printf(
"\n"
"\n"
"\n"
" +--------------MENU--------------+\n" /*定义菜单字符串数组*/
" | |\n"
" | 1.Matrix add(加法) |\n"
" | 2.Matrix sub(减法) |\n"
" | 3.Matrix mul(乘法) |\n"
" | 4.About... |\n"
" | 5.Quit |\n"
" | |\n"
" | |\n"
" +--------------------------------+\n"
" By 池信泽\n"
" 07 11 06\n");
}
//对本程序的一点功能于输入输出的说明
void About()
{
printf(
" 1. 本程序的功能\n"
" 进行稀疏矩阵的加减乘法\n"
" 2. 输入形式\n"
" 只需输入矩阵中的非零元,输入时应输入非零元的位置,例如如果要输入\n"
" 第一行第一列的元素,请输入1,1,*(具体的数值),一次类推;\n"
" 如果输入的行数,或是列数有一个为0,则表示矩阵输入完成。\n"
" 3. 输出的形式\n"
" 以矩阵的形式输出,如果输入的矩阵不能进行相应的运算,则报错!!!\n");
}
//输入函数允许的最大的行列下标
Point Limilit_input()
{
while(true){
printf("请输入行列下标的最大允许值,应<= %d \n行::",MAXLINE);
scanf("%d",&Maxmu);
printf("列::");
scanf("%d",&Maxnu);
if(Maxmu<=20&&Maxnu<=20)
break;
else
printf("你输入的行列最大值过大,请重新输入!!!!!!\n");
}
return ok;
}
//时Q的行列数及非零的数两为0,相当于free
void free1(PRls Q){
Q->mu=0;
Q->nu=0;
Q->tu=0;
}
//计算M中每行第一个非零元素存储在M->data在的位置
PRls Accamulate_rpos(PRls M)
{
int num[30],t=1,col=2;
for(t=1;t<=M->mu;t++)
num[t]=0;
for(t=1;t<=M->tu;++t)
++num[M->data[t].i];//计算同行中非零元的个数
M->rpos[1]=1;
for(col=2;col<=M->mu;col++)
M->rpos[col]=M->rpos[col-1]+num[col-1];//后一行元素的位置等于前一行的位置
//加上前一行的非零元个数
printf("\n");
return M;
}
//构建矩阵M
Point Input(PRls M)
{
int i=0,j=0,k=1,num=1;
float e=0;
M->rpos[1]=1;M->data[0].e=0;M->tu=0;M->data[0].i=0;M->data[0].j=0;
while(true){
printf("请输入矩阵的行数,列数:\n行数::");
scanf("%d",&M->mu);
printf("列数::");
scanf("%d",&M->nu);
if(M->mu<=Maxmu&&M->nu<=Maxnu)
break;
else
printf("你输入的行列值太大了!!!行数小与%d,列数小于%d\n",Maxmu,Maxnu);
}
printf("请输入矩阵非零元的位置,行列下标,元素数值,若行列下标等于0则停止输入!!\n");
printf("输入时请按顺序输入,按照行列下标从小到大的顺序输入!!!!!!\n");
printf("请输入第 %d 个非零元的信息,形式为:*,*,*:",num);
scanf("%d,%d,%f",&i,&j,&e);
while(i!=0&&j!=0){
if(i<=M->mu&&j<=M->nu&&i>0&&j>0){
if(((i==M->data[k-1].i)&&(j>M->data[k-1].j))||i>M->data[k-1].i){
M->data[k].i=i;
M->data[k].j=j;
M->data[k++].e=e;
M->tu++;num++;
}
else
printf("输入没有按行列下标从小到大的顺序输入,请重新输入!!\n");
}
else
printf("你输入的行列下标不合法(大于矩阵的行数,列数,或小于 ),请重新输入!!!!\n");
printf("请输入第 %d 个非零元的信息,形式为:*,*,*::",num);
scanf("%d,%d,%f",&i,&j,&e);
}
M=Accamulate_rpos(M);//计算M中每行的第一个非0元的地址
return ok;
}
//进行乘法运算
Point Mul(Rls M,Rls N,Rls &Q)
{
int brow=0,tp=0,t=0,flag=0,ccol=1;
float ctemp[20];//用于存放一行中每列计算后的和
if(M.nu!=N.mu){
printf("被乘数的列数应该等与乘数的列数!!!!!\n");
return error;
}
Q.mu=M.mu;Q.nu=N.nu;Q.tu=0;
if(M.tu*N.tu!=0){
for(int arow=1;arow<=M.mu;++arow){
for(int i=1;i<=N.nu;i++)
ctemp[i]=0;
Q.rpos[arow]=Q.tu+1;
if(arow<M.mu) tp=M.rpos[arow+1];//指向下一行非零元的序号
else tp=M.tu+1;
for(int p=M.rpos[arow];p<tp;++p){
brow=M.data[p].j;
if(brow<N.mu) t=N.rpos[brow+1];
else t=N.tu+1;//指向下一行非零元的序号
for(int q=N.rpos[brow];q<t;q++){
ccol=N.data[q].j;//列的位置
ctemp[ccol]+=M.data[p].e*N.data[q].e;//计算这一行中每一列的元素值
}
}
for(ccol=1;ccol<=Q.nu;++ccol)
if(ctemp[ccol]){//非零元就插入
if(++Q.tu>MAXSIZE) {
return error;
flag=1;//空间分配的太小了啊
}
Q.data[Q.tu].i=arow;
Q.data[Q.tu].j=ccol;
Q.data[Q.tu].e=ctemp[ccol];//各个的插入中Q中去,注意行,列,元素值都要插入
} //if
if(flag==1)
return error;
}//for
}//if
return ok;
}
//加法运算
Point Add(Rls M,Rls N,Rls &Q)
{
int m=1,n=1;
float sum=0;
if((M.mu!=N.mu)&&(M.nu!=N.nu)){
printf("你输入的矩阵不能进行加减法运算\n");
return error;
}
Q.mu=M.mu;Q.nu=M.nu;Q.tu=0;
if(M.tu*N.tu!=0)
while(m<=M.tu&&n<=N.tu){
if((M.data[m].i==N.data[n].i)&&(M.data[m].j==N.data[n].j)){//行列下标相同
sum=M.data[m].e+N.data[n].e;
if(sum!=0){//相加的值不为零,存入Q
Q.data[++Q.tu].e=sum;
Q.data[Q.tu].i=M.data[m].i;
Q.data[Q.tu].j=M.data[m].j;
}
m++;
n++;//各指向下一个data
}
//以下利用行列下标的大小的决定谁先插入到矩阵中
else if((M.data[m].i==N.data[n].i)&&(M.data[m].j<N.data[n].j)) {
Q.data[++Q.tu].e=M.data[m].e;
Q.data[Q.tu].i=M.data[m].i;
Q.data[Q.tu].j=M.data[m++].j;
}
else if((M.data[m].i==N.data[n].i)&&(M.data[m].j>N.data[n].j)) {
Q.data[++Q.tu].e=N.data[n].e;
Q.data[Q.tu].i=N.data[n].i;
Q.data[Q.tu].j=N.data[n++].j;
}
else if(M.data[m].i<N.data[n].i){
Q.data[++Q.tu].e=M.data[m].e;
Q.data[Q.tu].i=M.data[m].i;
Q.data[Q.tu].j=M.data[m++].j;
}
else if(M.data[m].i>N.data[n].i){
Q.data[++Q.tu].e=N.data[n].e;
Q.data[Q.tu].i=N.data[n].i;
Q.data[Q.tu].j=N.data[n++].j;
}
}
if(m<=M.tu)//M中还有元素没有插入
for(m;m<=M.tu;m++){
Q.data[++Q.tu].e=M.data[m].e;
Q.data[Q.tu].i=M.data[m].i;
Q.data[Q.tu].j=M.data[m].j;
}
if(n<=N.tu) //N中还有元素没有插入
for(n;n<=N.tu;n++){
Q.data[++Q.tu].e=N.data[n].e;
Q.data[Q.tu].i=N.data[n].i;
Q.data[Q.tu].j=N.data[n].j;
}
return ok;
}
//减法运算,
Point Sub(Rls M,Rls &N,Rls &Q)
{
int i;
for(i=1;i<=N.tu;i++)
N.data[i].e=-N.data[i].e;//各元素值取反
Add(M,N,Q);
return ok;
}
//打印出矩阵
void print(Rls M)
{
int i,j,t=1;
for(i=1;i<=M.mu;i++){
for(j=1;j<=M.nu;j++)
if(M.data[t].i==i&&M.data[t].j==j)//若稀疏矩阵中存在非零的元素,则输出值
if(M.data[t].e==(int)M.data[t].e)
printf("%d\t",(int)M.data[t++].e);
else
printf("%.2f\t",M.data[t++].e);
else
printf("0\t");
printf("\n");
}
printf("\n");
}
//对相应的加减乘做相应的运算
Point Operate(PRls M,PRls N,PRls Q,char c)
{
Point a=error;
Input(M);
Input(N);
if(c=='1'){
printf("被加数是:\n");
print(*M);
printf("加数是:\n");
print(*N);
a=Add(*M,*N,*Q);
}
else if(c=='2'){
printf("被减数是:\n");
print(*M);
printf("减数是:\n");
print(*N);
a=Sub(*M,*N,*Q);
}
else if(c=='3'){
printf("被乘数是:\n");
print(*M);
printf("乘数是:\n");
print(*N);
a=Mul(*M,*N,*Q);
}
else
printf("你输入的运算选项有误");
if(a){
printf("运算的结果是:\n");
print(*Q);
}
return ok;
}
//对相应的加减乘做相应的运算
Point Operate1(PRls M,PRls N,PRls Q,char c)
{
Point a=ok;
if(c=='1'){
printf("被加数是:\n");
print(*M);
printf("加数是:\n");
print(*N);
a=Add(*M,*N,*Q);
}
else if(c=='2'){
printf("被减数是:\n");
print(*M);
printf("减数是:\n");
print(*N);
a=Sub(*M,*N,*Q);
}
else if(c=='3'){
printf("被乘数是:\n");
print(*M);
printf("乘数是:\n");
print(*N);
a=Mul(*M,*N,*Q);
}
else
printf("你输入的运算选项有误");
if(a){
printf("运算的结果是:\n");
print(*Q);
}
return ok;
}
int main()
{
char s[10];
PRls M,N,Q;
Point a=ok;
Limilit_input();//输入函数允许的最大的行列下标
while(true){
M=(PRls)malloc(sizeof(Rls));
N=(PRls)malloc(sizeof(Rls));
Q=(PRls)malloc(sizeof(Rls));
fflush(stdin);
Menu_print();
printf("\nEnter your choice(1~4):");
scanf("%s",s);
fflush(stdin);
if((strlen(s)==1)&&(s[0]=='1'||s[0]=='2'||s[0]=='3')){
Operate(M,N,Q,s[0]);
while(true){
if(s[0]=='2'){
int i;
for(i=1;i<=N->tu;i++)
N->data[i].e=-N->data[i].e;//如果第一布做了减法,由于本程序使用将减数
//的值取反实现,故做其他运算时应该将其返原
}
printf("你要对你刚才输入的数进行其他的运算吗?\n1,加法,2减法,3,乘法,4,退出\n");
printf("\nEnter your choice(1~4):");
fflush(stdin);
scanf("%s",s);
if((strlen(s)==1)&&(s[0]=='1'||s[0]=='2'||s[0]=='3')){
free1(Q);
Q=(PRls)malloc(sizeof(Rls));
Operate1(M,N,Q,s[0]);
}
else if(strlen(s)==1&&s[0]=='4')
break;
else
printf("你输入的数字不符要求,请重新输入吧!!!!!\nn");
}
}
else if((strlen(s)==1)&&s[0]=='4')
About();
else if((strlen(s)==1)&&s[0]=='5')
break;
else
printf("你输入了不合法的字符,请重新输入!!!!!!!\n");
free1(M);free1(N);free1(Q);
}
//system("pause");在dev-c++上运行时使用
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
#endif //检查内存是否泄露
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -