⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 41.cpp

📁 一. 需求分析 1. 本程序的功能 进行稀疏矩阵的加减乘法 2. 输入形式 只需输入矩阵中的非零元
💻 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 + -