实战——c/c ++读取包含结构体的二进制dat文件

        最近做了一个老师布置的计算方法题目,是让读取文件后解方程的,用python读取后是乱码的,不太好搞,想到这是用C语言编的,不如就用C/C ++ 来解码(其实特别简单)。

数据文件:

链接:https://pan.baidu.com/s/1TzusBPi9FPDYTNCQil-P9w 
提取码:1234

        题目如下:

给定数据读取后求解线性方程组;

序号

数据文件

规模

类型

说明

1

FuncData20211.dat

16阶

非压缩格式

1.414

用于测试程序

2

FuncData20212.dat

16阶

压缩格式

1.732

用于测试程序

3

FuncData20213.dat

2000阶左右

非压缩格式

待解

用于程序求解

4

FuncData20214.dat

50000阶左右

压缩格式

待解

用于程序求解

5

FuncData20215.dat

13w阶左右

压缩格式

待解

测试软件功能

附3:线性方程组数据文件格式说明

线性方程组的系数矩阵和右端常量将全部以二进制格式存贮在一个数据文件中, 在使用时必须按指定结构使用二进制格式进行读取

1.数据文件的文件名后缀为.dat,形式为:文件名.dat;

2.数据文件的结构,分为以下四个部分:

(1)文件类型标志部分:该部分存放本数据文件的描述信息,结构如下:

数据项

数据类型

说明

1

id

long int

该数据文件的标识,值为0x 0C0A8708,
即:十六进制的0C0A8708

2

ver

long int

数据文件的版本号,值为16进制数据,值的含义如下:

(1)0x102: 系数矩阵为非压缩格式带状矩阵

(2)0x202: 系数矩阵为压缩格式带状矩阵

3

id1

long int

备用标志字段,暂时未用

该部分的C语言格式描述为:

typedef struct FileInfo {

             long int id;               // 数据文件标示

            long int ver;             // 数据文件版本号

            long int id1;             // 备用标志

} FILEINFO;

(2)系数矩阵结构描述部分:该部分包括矩阵的阶数和上下带宽,如果是稀疏矩阵,则上下带宽值为0,结构如下:

数据项

数据类型

说明

1

n

long int

方程组的阶数

2

q

long int

带状矩阵的上带宽, 如果是稀疏矩阵,则值为0

3

p

long int

带状矩阵下带宽, 如果是稀疏矩阵,则值为0

该部分的C语言格式描述为:

  typedef struct HeadInfo {

          long int n;               // 方程组的阶数

         long int q;               //  上带宽

         long int p;               //  下带宽

       } HEADINFO;

(3) 系数矩阵数据部分:该部分存放方程组系数矩阵中的所有元素

①若存贮格式为非压缩格式,则按行方式顺序存贮系数矩阵中的每一个元素,元素总个数为 ,每个元素的类型为float型;

②若存贮格式是压缩方式,则同样是按行方式进行存贮,但每行中只存放上下带宽内的非零元素,即每行中存贮的元素都为 个,不足个数者以0填充;

(4)右端系数部分:该部分按顺序存放方程组中的右端的每个系数,个数为n个,每个系数的类型均为float型。

C语言文件那一章当时没咋学,这次特地又回去学了一下:

回顾一下主要内容:

1,文本文件操作中,getc / putc 函数 , fscanf / fprintf 函数 , fgets / fgets 函数 , 但只能用于操作 文本文件 ; fread / fwrite 函数(读和写) 既可以操作 二进制文件 , 又可以操作 文本文件 ;

2.FILE *fp为文件指针,随着对文件的读写,文件的位置指针(指向当前读写字节)向后移动 ;fopen(),fclose( ),文件的打开和关闭功能

3,fseek()移动文件指针的位置;SEEK_END文件尾部,SEEK_SET文件头部 ,rewind() 将指针回到文件流的开头, ftell( ),输出文件的字节大小

可编写代码如下:(部分代码)

// 首先将数据文件放在C++ 项目文件下
char tempstr[5][20] = {"FuncData20211.dat", "FuncData20212.dat", \
"FuncData20213.dat", "FuncData20214.dat", "FuncData20215.dat"};

float A[3000][3000], b[3000], temp[3000];
int n, len; // 全局变量

void read(int i)
{
    FILEINFO f; 
	HEADINFO h;
    FILE *fp = fopen(tempstr[i], "rb");
    if (!fp) 
    {
    	cout << "文件读入错误!" << endl;
		return ; 
	}

    //计算文件的大小
//	fseek(fp, 0, SEEK_END);  
//	int size = ftell(fp); 
//	cout << size << endl; 
//	rewind(fp);
	// 读入两个结构体头部的信息 
	fread(&f, sizeof (FILEINFO), 1, fp);  // &f 为读入数据放入的地址, sizeof (FILEINFO) 为单个数据元素的字节大小, 1 是指读入1个数据元素,fp 为文件指针
	fread(&h, sizeof (HEADINFO), 1, fp);
	printf("%08x %08x %08x\n", f.id, f.ver, f.id1); //输出头部信息, 8个位宽,不足以0填充
	printf("%08x %08x %08x\n", h.n, h.q, h.p);
	
    n = h.n;
    len = h.q + h.p + 1;
    // 非压缩矩阵
	if (f.ver == 0x102) {
		for (int i = 0; i < n; i ++ ) 
        {
			if (fread(&A[i], sizeof (float), n, fp) != n) 
            {
				cout << "矩阵读取错误!" << endl; 
				return ;
			}
		}			
	} else {
    // 压缩矩阵
		for (int i = 0; i < n; i ++ ) 
        {
			if (fread(&temp, sizeof (float), len, fp) != len)
            {
    	        cout << "矩阵读入错误!" << endl;
		        return ; 
	        }

			for (int j = 0; j < len; j ++ )
             {
				int pos = h.p - i;
				if (pos > 0) A[i][j] = temp[j + pos];
				else A[i][j - pos] = temp[j];
			}
		}
	}

	fread(&b, sizeof (float), n, fp); // 读右端系数b
	fclose(fp);
	//输出调试	
//	for (int i = 0; i < n; i ++ )
//	{
//		for (int j = 0; j < n; j ++ ) printf("%6.2f ", A[i][j]);
//		printf("%6.2f\n", b[i]);
//	}
}

 读取前两个数据如下:

 

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值