前言
初版矩阵计算器有以下不足:
1.使用二维指针。
多维数组在计算机中的储存形式与一维数组并无本质区别。利用二维指针申请动态数组,表面上带来了操作的便捷,事实上却让问题更加复杂、以至于偏离核心。改进版本采用一维指针。
2.手动输入矩阵。
计算机往往需要处理大型矩阵,因此,在实际应用中,通过键盘手动输入矩阵并不现实。改进版本将读入文件中的数据,并将它们储存在一定规格的数组中。数组的行、列数仍需手动输入。
一、用一维指针动态申请二维数组
多维数组在计算机中的储存,可以近似理解为降维。类似于将高维空间按一定的规律压缩、铺平,最终成为一条直线。相对地,创建高维数组可以采取相应反过程,即先创建一维数组,然后按一定规律(取决于你想要的行和列数)切分、重新排出行列等。
在这里,我将利用一个函数和简单的数学运算
int TwoDimension(int i, int j, int n, const double p[])
{
int sum = i * n + j;
return p[sum];
}
该函数需要四个参数。i 和 j 是你在直观上想要调用的二维数组元素所在的行和列,m、n是你希望二维数组拥有的行数和列数,p是你已经创建的一维数组。p 的大小应等于m*n。
利用简单的sum运算来换算同一个元素在一维数组和二维数组中的位置。
示例:申请二维数组并将其打印出来。
#include<iostream>
#include<iomanip>
using namespace std;
int TwoDimension(int i, int j, int n, const int p[]);
int main()
{
int m, n;
cout << "请输入矩阵行数:";
cin >> m;
cout << "请输入矩阵列数:";
cin >> n;
int* p = new int[m * n];
cout << "请按行输入矩阵元素:";
for (int i = 0; i < m * n; i++)
cin >> p[i];
cout << setw(8);
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cout<<"max["<<i<<"]["<<j<<"] = "<<TwoDimension(i, j, n, p);
cout << setw(8);
}
cout << endl;
}
}
int TwoDimension(int i, int j, int n,const int p[])
{
int sum = i * n + j;
return p[sum];
}
二、读入文件并存入数组
1.读入数据
代码如下(示例):
#include<iostream>
#include<fstream> //头文件
#include<cstdlib> //EXIT_FAILURE需要
using namespace std;
const int SIZE = 60;
int main()
{
ifstream inFile; //声明一个对象
char filename[SIZE]; //文件名可以是变量
cout << "请输入文件名:";
cin.getline(filename, SIZE);
inFile.open(filename); //用open()将对象与文件关联起来
//然后就可以像使用cin那样使用inFile
if (!fin.is_open()) //检查文件是否顺利打开
{
cout << "Could not open the file " << filename << endl;
cout << "Program terminating.\n";
exit(EXIT_FAILURE);
}
inFile.close(); //关闭文件
}
C++ Primer简明而完整地介绍了读取文本文件的方法和详细的检验过程,贴在这里:
#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;
const int SIZE = 60;
int main()
{
char filename[SIZE];
ifstream inFile;
cout << "Enter name of data file:";
cin.getline(filename, SIZE);
inFile.open(filename);
if (!inFile.is_open())
{
cout << "Could not open the file" << filename << endl;
cout << "Program terminating.\n";
exit(EXIT_FAILURE);
}
double value;
double sum = 0.0;
int count = 0;
inFile >> value;
while (inFile.good()) //bool值为1条件为:读取文件时未发生任何错误。
{ //inFile.good()函数指出最后一次读取是否成功,因此需要在循环开始前放置输入语句
++count;
sum += value;
inFile >> value; //在循环结尾再次放入输入语句
}
if (inFile.eof()) //达到EOF终止
cout << "End of file reached.\n";
else if (inFile.fail()) //需要的数据类型与文件中的不匹配
cout << "Input terminated by data mismatch.\n";
else
cout << "Input terminated for unknown reason.\n";
if (count == 0)。//文件中没有数据
cout << "No data processed.\n";
else
{
cout << "Items read: " << count << endl;
cout << "Sum: " << sum << endl;
cout << "Average: " << sum / count << endl;
}
inFile.close();
return 0;
}
C++ Primer的作者尤其强调,检查文件是否被成功打开至关重要。很多初学者花了大量时间检查文件读取循环哪里出来问题,最终却发现问题在于程序没有打开文件。下面是文件不能打开的一些可能原因:
1.指定的文件不存在(输错了文件名)
2.文件与编译器程序不在同一文件夹内
3.输入文件名时忽略了扩展名(.txt等)
对我个人,需要注意的是char[SIZE] 的末尾是转义字符,因此需要输入的字符串长度不能恰好等于n。保险起见,可以让 SIZE 在适当范围内尽量大。
而定义常量SIZE的好处在于,当你想改变这个数字时,你不需要重复操作很多次,焦头烂额地检查还有哪里没改到。——在你真正吃过一次苦头前,你都意识不到常量的好处。
2.存入数组
代码如下:
#include<iostream>
#include<fstream>
#include<iomanip>
using namespace std;
const int SIZE = 60;
int main()
{
ifstream fin;
char fname[SIZE];
cout << "请输入文件名1:";
cin.getline(fname, SIZE);
fin.open(fname);
if (!fin.is_open())
{
cout << "Could not open the file " << fname << endl;
cout << "Program terminating.\n";
exit(EXIT_FAILURE);
}
double a;
int m, n;
cout << "请输入矩阵的行数:";
cin >> m;
cout << "请输入矩阵的列数:";
cin >> n;
double* max_1 = new double[m * n];
int count = 0;
while (fin >> a)
{
max_1[count] = a;
count++;
}
cout << setw(8);
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cout << "max[" << i << "][" << j << "] = " << TwoDimension(i, j, n, max_1);
cout << setw(8);
}
cout << endl;
}
double TwoDimension(int i, int j, int n, const double p[])
{
int sum = i * n + j;
return p[sum];
}
整体代码
#include<iostream>
#include<fstream>
#include<iomanip>
using namespace std;
const int SIZE = 60;
double TwoDimension(int i, int j, int n, const double p[]);
int main()
{
ifstream fin;
ifstream inFile;
char fname[SIZE];
char filename[SIZE];
cout << "请输入文件名1:";
cin.getline(fname, SIZE);
cout << "请输入文件名2:";
cin.getline(filename, SIZE);
fin.open(fname);
inFile.open(filename);
if (!fin.is_open())
{
cout << "Could not open the file " << fname << endl;
cout << "Program terminating.\n";
exit(EXIT_FAILURE);
}
if (!inFile.is_open())
{
cout << "Could not open the file" << filename << endl;
cout << "Program terminating.\n";
exit(EXIT_FAILURE);
}
double a;
fin >> a;
int m, n;
cout << "请输入矩阵1的行数:";
cin >> m;
cout << "请输入矩阵1的列数:";
cin >> n;
double* max_1 = new double[m * n];
int count = 0;
while (fin >> a)
{
max_1[count] = a;
count++;
}
cout << setw(8);
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cout << "max[" << i << "][" << j << "] = " << TwoDimension(i, j, n, max_1);
cout << setw(8);
}
cout << endl;
}
double b;
inFile >> b;
int p, q;
cout << "请输入矩阵2的行数:";
cin >> p;
cout << "请输入矩阵2的列数:";
cin >> q;
double* max_2 = new double[p * q];
count = 0;
while (inFile >> b)
{
max_2[count] = b;
count++;
}
cout << setw(8);
for (int i = 0; i < p; i++)
{
for (int j = 0; j < q; j++)
{
cout << "max[" << i << "][" << j << "] = " << TwoDimension(i, j, n, max_2);
cout << setw(8);
}
cout << endl;
}
cout << "结果为:\n";
cout << setw(10);
double* result = new double[m * q]();
for (int i = 0; i < m; i++)
{
for (int j = 0; j < q; j++)
{
for (int k = 0; k < p; k++)
{
int num = i * q + j;
result[num] += TwoDimension(i, k, n, max_1) * TwoDimension(k, j, q, max_2);
}
cout <<"result["<<i<<"]["<<j<<"]= "<<
TwoDimension(i, j, q, result) << setw(10);
}
cout << endl;
}
delete[]max_1;
delete[]max_2;
delete[]result;
inFile.close();
fin.close();
}
double TwoDimension(int i, int j, int n, const double p[])
{
int sum = i * n + j;
return p[sum];
}