草庐IT

C语言课程设计---矩阵的乘法

小鱼爱码士 2024-05-04 原文

目录

一、前言

二、题目

        1、题目分析:

        2、初步构建:

        3、预期流程:

三、结构

        1、程序组成

        2、数据存储

        3、函数声明

        4、运行结构

三、主要程序设计

        1、矩阵乘法实现的函数解析:

        2、文件操作函数

四、源码

matrix_fun.h中:

matrix_fun.c中:

 main.c中:


一、前言

        矩阵:在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合。只有当第一个矩阵(左矩阵)的列数等于第二矩阵(右矩阵)的行数时,两矩阵才能相乘。例如:矩阵 A(n×m) 和 B(m×k) 相乘,得到矩阵C(n×k)。

二、题目

        如题:编写一个函数实现矩阵A (2行3列)与 矩阵B相乘(3行2列),乘积放在C数组中。在主函数中输入相乘的两数组,并输出结果。

        1、题目分析:

        题中要求用函数实现矩阵AB的乘积,很明显题目给的两矩阵是可乘的,但是在程序中我们也不能少了判断矩阵是否可乘的步骤。根据题目我们需要使用三个数组来作为运算的矩阵的空间,根据算法实现矩阵的乘积运算...

        2、初步构建:

        数组、文件、结构体、stdIO、指针

        3、预期流程:

        运行程序--->输入矩阵的维--->判断是否可乘--->计算--->输出(1、到本地文件  2、到控制台)--->程序结束

三、结构

        1、程序组成

        main.c>各函数的调用

        matrix_fun.h>有关矩阵函数的声明

        matrix_fun.c>有关矩阵函数的定义

        2、数据存储

        typedef struct        //定义一个矩阵的结构体
        {
            int matrix[MAX][MAX];    //结构体中的3个成员变量

            int matr_row;            //数组的行
            int matr_col;            //数组的列

        }MATRIX;                    //结构体的成员

        3、函数声明

struct MATRIX* Matrix_multiplication(MATRIX* object1, MATRIX* object2); //矩阵的乘法
void Get_Matrix(MATRIX* object1, MATRIX* object2);                       //获取矩阵的值
void Out_Matrix_toConsole(MATRIX* object);                                    //将一个矩阵输出到控制台
void Out_Matrix_toFile(MATRIX* object, const char* filename);         //将一个矩阵输出到文件下


        4、运行结构

运行程序--->输入矩阵的维--->判断是否可乘--->计算--->输出(1、到本地文件  2、到控制台)--->程序结束

三、主要程序设计

        1、矩阵乘法实现的函数解析:

如图:假设矩阵A(ixj)B(ixj)明显AB可乘,设结果为矩阵C,那么矩阵C的行号为A矩阵的行号,列号为B矩阵的列号。图中能得到C11的值为A11*B11+A12*B21+A13*B31+....+A1j*Bi1

那么就能得到一个通式:A[][]*B[][]。 就是程序中的(object1->matrix[i][n]) * (object2->matrix[n][j]);

在 A[ i ][ n ]*B[ n ][ j ] 每计算一个值 n 都会从0--->n 然后求和 (其中n的最大值为A的列数或者B的行数),然后就是B矩阵的列数加1,在就算一组值,最后矩阵A的行数加一。容易看出上述过程可由三个循环嵌套完成。

/*乘法运算*/
        for (int i = 0; i < theResult->matr_row; i++)【1】
        {
            for (int j = 0; j < theResult->matr_col; j++)
【2】
            {

                for (int n = 0; n < object1->matr_col; n++) 【3】
                {
                    temp += (object1->matrix[i][n]) * (object2->matrix[n][j]); 【4】
                }
                theResult->matrix[i][j] = temp; 
【5】
                temp = 0;  【6】
            }
        }

 其中外面两层循【1】【2】同时可以遍历C(theResult->matrix[i][j])矩阵,当最里面的循环【3】结束时,说明完成了一个矩阵C的值的计算,这时就可以将所计算出的值存入C(theResult->matrix[i][j])中。这样就可以完成多维(可乘的)矩阵相乘。

函数源码:

/*
@函数作用:计算两个矩阵的乘法
@参数:MATRIX* object1, MATRIX* object2,分别是要计算的矩阵结构体指针对象
@返回值:struct MATRIX*re  返回一个计算后的矩阵结构体指针对象
*/
struct MATRIX* Matrix_multiplication(MATRIX* object1, MATRIX* object2)
{
	MATRIX* theResult = (MATRIX*)malloc(sizeof(MATRIX));	//申请空间
	theResult->matr_row = object1->matr_row;				//保存结果的行
	theResult->matr_col = object2->matr_col;				//保存结果的列

	int temp = 0;											//tenp为保存每一个点的值

	if (object1->matr_col == object2->matr_row)				//判断是否可以乘
	{
		//如果可乘,提示信息
		printf("两个矩阵可乘!\n");
		/*乘法运算*/
		for (int i = 0; i < theResult->matr_row; i++)
		{
			for (int j = 0; j < theResult->matr_col; j++)
			{

				for (int n = 0; n < object1->matr_col; n++)
				{
					temp += (object1->matrix[i][n]) * (object2->matrix[n][j]);
				}
				theResult->matrix[i][j] = temp;
				temp = 0;
			}
		}
	}
	else		//如果不可乘,返回一个nullptr,方便主函数中判断
	{
		printf("两个矩阵不可乘!请重新输入!\n");
		theResult = NULL;
	}


	return theResult;
}

        2、文件操作函数

/*
@函数作用:输出一个矩阵到txt文件中
@参数:MATRIX* object 是要输出的矩阵结构体指针对象,const char* filename 输出到的文件名
@返回值:void
*/
void Out_Matrix_toFile(MATRIX* object, const char* filename)
{
	if (object)
	{
		FILE* file;						//文件处理的结构体,定义一个文件处理的结构体指针对象
		file = fopen(filename, "w+");	//使用fopen函数打开指定文件名的文件
		if (file)						//若打开成功,fopen返回非空指针
		{
			printf("成功打开文件:%s\n", filename);				//控制台提示打开成功
			fputs("两个矩阵相乘的结果为:\n", file);			//fputs()向file流中写入字符串

			/*将计算结果输出到file流中*/
			for (int i = 0; i < object->matr_row; i++)
			{
				for (int j = 0; j < object->matr_col; j++)
					fprintf(file, "%d\t", object->matrix[i][j]);	//向file流中格式化输出
				fprintf(file, "\n");								//换行
			}

			fclose(file);						//关闭文件流
		}
		else									//打开失败fopen返回空指针
		{
			printf("打开%s失败\n", filename);
		}

		free(file);								//释放file流
	}
	else
		printf("计算结果为空!");
}

文件的基本操作---略

【其他函数---读者自行理解】

四、源码

matrix_fun.h中:

/*
@C语言课程设计源代码
@功能;计算矩阵的乘法,并且输出到控制台或者文件中
@作者:机设21-6 孔*江
@日期:2022/06/24
*/
#ifndef _MATRIX_FUN_H_
#define _MATRIX_FUN_H_

/*头文件*/
#include <stdio.h>	
#include <stdlib.h>

//宏定义 数组的长度
#define MAX 1024
//定义一个矩阵的结构体
typedef struct
{
	int matrix[MAX][MAX];//结构体中的3个成员变量
	int matr_row;		//数组的行
	int matr_col;		//数组的列
}MATRIX;				//结构体的成员

//矩阵的乘法
struct MATRIX* Matrix_multiplication(MATRIX* object1, MATRIX* object2);
//获取矩阵的值
void Get_Matrix(MATRIX* object1, MATRIX* object2);
//将一个矩阵输出到控制台		
void Out_Matrix_toConsole(MATRIX* object);
//将一个矩阵输出到文件下
void Out_Matrix_toFile(MATRIX* object, const char* filename);


#endif  //_MATRIX_FUN_H_

matrix_fun.c中:



#include "matrix_func.h"


/*
@函数作用:从键盘获取矩阵的值
@参数:MATRIX* object1, MATRIX* object2,分别是要输入到的的矩阵结构体指针对象
@返回值:void
*/
void Get_Matrix(MATRIX* object1, MATRIX* object2)
{
	printf("请输入第一矩阵的行数与列数(以空格分隔!):");			//提示信息打印
	scanf("%d%d", &(object1->matr_row), &(object1->matr_col));		//读取到结构体object1中

	/*数组循环读入*/
	for (int i = 0; i < object1->matr_row; i++)
		for (int j = 0; j < object1->matr_col; j++)
			scanf("%d", &(object1->matrix[i][j]));

	printf("请输入第二矩阵的行数与列数(以空格分隔!):");			//提示信息打印
	scanf("%d%d", &(object2->matr_row), &(object2->matr_col));		//读取到结构体object2中
	/*数组循环读入*/
	for (int i = 0; i < object2->matr_row; i++)
		for (int j = 0; j < object2->matr_col; j++)
			scanf("%d", &(object2->matrix[i][j]));

	/*
	MATRIX* object1, MATRIX* object2分别指向两个结构体,通过传入这两个的结构体指针
	改变两个结构体指针指向的结构体成员的值。
	*/

}


/*
@函数作用:计算两个矩阵的乘法
@参数:MATRIX* object1, MATRIX* object2,分别是要计算的矩阵结构体指针对象
@返回值:struct MATRIX*re  返回一个计算后的矩阵结构体指针对象
*/
struct MATRIX* Matrix_multiplication(MATRIX* object1, MATRIX* object2)
{
	MATRIX* theResult = (MATRIX*)malloc(sizeof(MATRIX));	//申请空间
	theResult->matr_row = object1->matr_row;				//保存结果的行
	theResult->matr_col = object2->matr_col;				//保存结果的列

	int temp = 0;											//tenp为保存每一个点的值

	if (object1->matr_col == object2->matr_row)				//判断是否可以乘
	{
		//如果可乘,提示信息
		printf("两个矩阵可乘!\n");
		/*乘法运算*/
		for (int i = 0; i < theResult->matr_row; i++)
		{
			for (int j = 0; j < theResult->matr_col; j++)
			{

				for (int n = 0; n < object1->matr_col; n++)
				{
					temp += (object1->matrix[i][n]) * (object2->matrix[n][j]);
				}
				theResult->matrix[i][j] = temp;
				temp = 0;
			}
		}
	}
	else		//如果不可乘,返回一个nullptr,方便主函数中判断
	{
		printf("两个矩阵不可乘!请重新输入!\n");
		theResult = NULL;
	}


	return theResult;
}


/*
@函数作用:输出一个矩阵到控制台
@参数:MATRIX* object 是要输出的矩阵结构体指针对象
@返回值:void
*/
void Out_Matrix_toConsole(MATRIX* object)
{
	if (object)
	{
		printf("矩阵1乘矩阵2的结果为:\n");
		/*循环访问数组的值,并且输出*/
		for (int i = 0; i < object->matr_row; i++)
		{
			for (int j = 0; j < object->matr_col; j++)
				printf("%d\t", object->matrix[i][j]);
			printf("\n");
		}
	}
	else
		printf("计算结果为空!");

}


/*
@函数作用:输出一个矩阵到txt文件中
@参数:MATRIX* object 是要输出的矩阵结构体指针对象,const char* filename 输出到的文件名
@返回值:void
*/
void Out_Matrix_toFile(MATRIX* object, const char* filename)
{
	if (object)
	{
		FILE* file;						//文件处理的结构体,定义一个文件处理的结构体指针对象
		file = fopen(filename, "w+");	//使用fopen函数打开指定文件名的文件
		if (file)						//若打开成功,fopen返回非空指针
		{
			printf("成功打开文件:%s\n", filename);				//控制台提示打开成功
			fputs("两个矩阵相乘的结果为:\n", file);			//fputs()向file流中写入字符串

			/*将计算结果输出到file流中*/
			for (int i = 0; i < object->matr_row; i++)
			{
				for (int j = 0; j < object->matr_col; j++)
					fprintf(file, "%d\t", object->matrix[i][j]);	//向file流中格式化输出
				fprintf(file, "\n");								//换行
			}

			fclose(file);						//关闭文件流
		}
		else									//打开失败fopen返回空指针
		{
			printf("打开%s失败\n", filename);
		}

		free(file);								//释放file流
	}
	else
		printf("计算结果为空!");
}

 main.c中:



/*头文件*/
#include "matrix_func.h"		

int main()
{
	
	MATRIX* matrix1 = (MATRIX*)malloc(sizeof(MATRIX));			//使用malloc给变量申请空间
	MATRIX* matrix2 = (MATRIX*)malloc(sizeof(MATRIX));			// 使用malloc给变量申请空间
	/*调用输入函数,将矩阵的值从键盘上输入*/
	Get_Matrix(matrix1, matrix2);								//传入指针,用户从键盘输入矩阵
	/*计算矩阵的乘,声明一个结构体指针存放数据*/
	MATRIX* theResult = Matrix_multiplication(matrix1, matrix2);//调用矩阵乘函数
	/*输出到“./Matrix_result.txt文件下”*/
	Out_Matrix_toFile(theResult, "./Matrix_result.txt");
	/*将计算结构输出到控制台*/
	Out_Matrix_toConsole(theResult);

	/*释放相关空间*/
	free(theResult);
	free(matrix1);
	free(matrix2);

	/*停止*/
	system("pause");
	return 0;
}


【欢迎指正!!!】

有关C语言课程设计---矩阵的乘法的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  3. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  4. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  5. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  6. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  7. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  8. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  9. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  10. ruby - ruby 乘法语句中星号中断语法前的空格 - 2

    在添加一些空格以使代码更具可读性时(与上面的代码对齐),我遇到了这个:classCdefx42endendm=C.new现在这将给出“错误数量的参数”:m.x*m.x这将给出“语法错误,意外的tSTAR,期待$end”:2/m.x*m.x这里的解析器到底发生了什么?我使用Ruby1.9.2和2.1.5进行了测试。 最佳答案 *用于运算符(42*42)和参数解包(myfun*[42,42])。当你这样做时:m.x*m.x2/m.x*m.xRuby将此解释为参数解包,而不是*运算符(即乘法)。如果您不熟悉它,参数解包(有时也称为“spl

随机推荐