目录
导言
数组,想必大家并不陌生,C语言中我们经常会定义各种数组,自然也包括二维数组。
所有数组都有一个特性,那就是我们在定义他们的时候必须限制他的大小,这是不能徇私的,大家都一样,必须遵守这个规则。
01.一个问题
如果在工作中要你用C++实现二维数组,并且这个二维数组还是动态可变的,你会怎么做?
如果说有一个东西,能够自动检测申请的空间够不够,不够就重新申请更大的空间,然后移动所有的数据,是不是就能解决这个问题。
这个问题,很久之前,软件界的前辈在设计STL标准的时候就已经解决了这个问题,提供了一个动态数组,就是我们工作中经常用的容器之一:vector容器。
vector容器是一种类数组的容器,封装好的数组,非常的好用,主要是,我们不用担心内存越界、空间不够等等问题。
至于STL,我后面有空会写各种STL基本的用法,为了能够在C++编程中更上一层楼,特意去买了STL源码剖析,后面我们在慢慢道来。
02.用法一(我没用过,借鉴知识点)
2.1二维vector的定义
#include <iostream>
#include <vector> //如果想用vector必须包含对应头文件
using namespace std;
int main()
{
//双vector里面一定带空格区分,以免出问题。
vector<vector<int> > vec(m); //这里m不能少,我没试过,你们可以试下这种写法
//这里创建一个m*n的二维vector
for(int i = 0;i<m;i++)
{//这里是给内层vector定义大小。默认是0,这里n是个数,不是值
vec[i].resize(n);
}
system("pause");
return 0;
}
2.2 二维vector实例
//下面就是二维vector,按照上面的方式的一个实例,请看
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<vector<int> > vec(4);
for(int i = 0;i<4;i++)
{
vec[i].resize(5);
}
//输出二维数组的行和列
cout << "row(行):" << vec.size() << "col(列):" << vec[0].size() << endl; //输出4和5
//输出二维vector的所有值
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 5; j++)
{
cout << vec[i][j];
}
cout << endl; //打完一行就换行
}
system("pause");
return 0;
}
03.vector遍历方法
下面我展示两种遍历vector或者说容器的方法:方便待会写的代码不用多做解释。
其实,除了这两种还有一种叫做迭代器遍历,但是这个我准备STL再说.
3.1 下标遍历方法(常用)
#include <iostream>
#include <vector>
using namespace std;
//下面定义一个宏
#define ROW 10
//traverse vector<vector<int> >
void TraverseVec(vector<int>& vec)
{
//1.parameter check(参数检查,好习惯)
if(vec.size() == 0)
{
return;
}
//2.start traverse (开始遍历)
for(int i = 0; i < ROW; i++)
{
cout << vec[i] << endl;
}
}
int main()
{
vector<int> vec;
for(int i = 0; i < ROW; i++)
{
vec.push_back(i); //尾插法,STL中再说,就是给vec中赋值
}
TraverseVec(vec);
system("pause");
return 0;
}
3.2 区间迭代(C++11新特性)
这也是我最喜欢的一种遍历容器的方法,超级好用,谁用谁喜欢。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//这个方法太好用了,所以不用函数,简单快捷.
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
//traverse
for(int a : vec)
{
cout << a;
}
cout << endl; //换行
system("pause");
return 0;
}
04.Working遇到的二维vector例子
下面的代码是MFC中的,C++语言编的程。看得懂看,看不懂跳过。
//读取打标数据函数
BOOL COnLineProcessParaDialog::ReadFolderPathData(CString strPassFilePath,CString sFileName)
{
theApp.m_Pref.m_Advance.data.MarkData.clear();
theApp.m_Pref.m_Advance.data.v_TargetFilePath.clear();
if(strPassFilePath.Right(1) != "\\")
{
strPassFilePath += "\\";
}
strPassFilePath += "*.txt";
CString startPath = strPassFilePath;
CFileFind finder; //查找类对象
BOOL bworking = finder.FindFile(startPath); //查找当前目录下是否有文件或者目录
while(bworking)
{
bworking = finder.FindNextFile(); //使用下面的IsDots()必须有此函数(前面)
if(!finder.IsDots())
{
if(!finder.IsDirectory())
{//是文件
CString strFileName = finder.GetFileName(); //获取文件名字
theApp.m_Pref.m_Advance.data.strQRCode = strFileName;
if(strFileName == sFileName) //QRCodeName and strFileName is or no equality?
{
CString TeamFilePath = finder.GetFilePath(); //获取文件完整路径
CString DesFilePath = TeamFilePath;
DesFilePath.MakeLower(); //转换为小写字母
if(DesFilePath.Right(4) == _T(".txt"))
{
//目标文件
heApp.m_Pref.m_Advance.data.v_TargetFilePath.push_back("TeamFilePath");
}
break;
}
else
{
continue;
//本来这里是用的递归遍历所有文件夹的,但是,考虑到不用,而且递归对空间的占用率就去掉了。
}
}
}
}
finder.Close(); //close finder
if(theApp.m_Pref.m_Advance.data.v_TargetFilePath.size() == 0)
{
return FALSE;
}
//deal vessel data, read data
vector<CString> v1 = theApp.m_Pref.m_Advance.data.v_TargetFilePath;
CString strLine = "";
int nTime = 0;
const char* s = NULL;
vector<char> tempLine;
vector<vector<char> > StrLine;
//这里就用到了上面的方法
for(CString DealPath : v1)
{
//这里是调用的公司自己封装的文件操作函数,不用管,只是对系统文件操作函数进行二次封装
CStdFile cf(DealPath);
if(!cf.Open())
{//open failed
return FALSE;
}
CDebug::GetObjectA()->Printf(CDebug::IL_INFO,"读取文件为"+DealFath);
while(cf.ReadLine(strLine))
{//get Data
s = strLine.GetBuffer(strLine.GetLength()); //change data
//analysis data
while(*s != '\0')
{
if(*s != ',')
{
tempLine.push_back(*s);
//nTime = tempLine.size();
s++;
}
else
{
s++;
}
}
StrLine.push_buck(tempLine);
tempLine.clear();
strLine = ""; //set string empty,reserved next string.
}
cf.Close(); //close file
}
//traverse vessel try data read rule -> vector
for(int j = 0; j < StrLine[0].size(); j++)
{
for(int i = 0; i < StrLine.size(); i++)
{
if(j % 2 == 0)
{
theApp.m_Pref.m_Advance.data.MarkData.push_back(StrLine[i][j]);
}
else
{
theApp.m_Pref.m_Advance.data.MarkData.push_back(StrLine[StrLine.size()-1 - i][j]);
}
}
}
return TRUE;
}
上面设计到很多其他文件或者说类的东西,看不懂就不用管,写出来只是想说还有其他写法,不在定义二维vector时给默认的值也是可以的,而且程序一样的稳定,不会有问题。
05.总结
上面列举了两种方式,和遍历容器的方法。如果觉得这个MFC这部分不好看,你们自己建立一个空项目也是可以这么测试的,当然,不用写这么多,这个函数的逻辑比较复杂。
vector容器是我们工作中最常用的,学了STL,但是我工作中基本只用两个容器就可以搞定,一个vector(数组),一个list(链表),他们的区别我就不说了,跟数组与链表一样的。
基础是死的,需求是活的,只有能用基础完成需求,才能说自己掌握了这个方法,这个知识点。
06.结语
上面就是STL容器实现二维数组的全部内容,相较其他的博主,自认为还是不是太差,希望大家能看懂,要是遇到看不懂的,可以直接下面评论或者直接私我,都会回复的。
版权声明:创作不易,转载请注明出处,谢谢各位捧场。