动态数组vector用法

动态数组vector用法
动态数组vector用法

Vector用法介绍

这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作。本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用。通过阅读这篇文章读者应该能够有效地使用vector容器,而且应该不会再去使用C类型的动态数组了。

Vector总览

vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。为了可以使用vector,必须在你的头文件中包含下面的代码:

#include

vector属于std命名域的,因此需要通过命名限定,如下完成你的代码:

using std::vector; vector vInts;

或者连在一起,使用全名:

std::vector vInts;

建议使用全局的命名域方式:

using namespace std;

在后面的操作中全局的命名域方式会造成一些问题。vector容器提供了很多接口,在下面的表中列出vector的成员函数和操作。

Vector的函数

c.assign(beg,end)

将[beg; end)区间中的数据赋值给c。

c.assign(n,elem)

将n个elem的拷贝赋值给c。

c.at(idx)

传回索引idx所指的数据,如果idx越界,抛出out_of_range。

c.back()

传回最后一个数据,不检查这个数据是否存在。

c.begin()

传回迭代器中的一个数据。

c.capacity()

返回容器中数据个数。

c.clear()

移除容器中所有数据。

c.empty()

判断容器是否为空。

c.end()

指向迭代器中的最后一个数据地址。

c.erase(pos)

删除pos位置的数据,传回下一个数据的位置。

c.erase(beg,end)

删除[beg,end)区间的数据,传回下一个数据的位置。

c.front()

传回地一个数据。

get_allocator

使用构造函数返回一个拷贝。

c.insert(pos,elem)

在pos位置插入一个elem拷贝,传回新数据位置。

c.insert(pos,n,elem)

在pos位置插入n个elem数据。无返回值。

c.insert(pos,beg,end)

在pos位置插入在[beg,end)区间的数据。无返回值。

c.max_size()

返回容器中最大数据的数量。

c.pop_back()

删除最后一个数据。

c.push_back(elem)

在尾部加入一个数据。

c.rbegin()

传回一个逆向队列的第一个数据。

c.rend()

传回一个逆向队列的最后一个数据的下一个位置。

c.resize(num)

重新指定队列的长度。

c.reserve()

保留适当的容量。

c.size()

返回容器中实际数据的个数。

c1.swap(c2) swap(c1,c2)

将c1和c2元素互换。

同上操作。

vector c 创建一个空的vector。

vector c1(c2) 用c2拷贝c1

vector c(n) 创建一个vector,含有n个数据,数据均已缺省构造产生。vector c(n, elem) 创建一个含有n个elem拷贝的vector。

vector c(beg,end) 创建一个以[beg;end)区间的vector。

c.~ vector () 销毁所有数据,释放内存。

Vector操作

函数描述

operator[]

返回容器中指定位置的一个引用。

创建一个vector

vector容器提供了多种创建方法,下面介绍几种常用的。

创建一个Widget类型的空的vector对象:

vector vWidgets;

// ------

// |

// |- Since vector is a container, its member functions

// operate on iterators and the container itself so

// it can hold objects of any type.

创建一个包含500个Widget类型数据的vector:

vector vWidgets(500);

创建一个包含500个Widget类型数据的vector,并且都初始化为0:

vector vWidgets(500, Widget(0));

创建一个Widget的拷贝:

vector vWidgetsFromAnother(vWidgets);

向vector添加一个数据

vector添加数据的缺省方法是push_back()。push_back()函数表示将数据添加到vector的尾部,并按需要来分配内存。例如:向vector中添加10个数据,需要如下编写代码:

for(int i= 0; i<10; i++)

vWidgets.push_back(Widget(i));

获取vector中制定位置的数据

很多时候我们不必要知道vector里面有多少数据,vector里面的数据是动态分配的,使用push_back()的一系列分配空间常常决定于文件或一些数据源。如果你想知道vector存放了多少数据,你可以使用empty()。获取vector的大小,可以使用size()。例如,如果你想获

取一个vector v的大小,但不知道它是否为空,或者已经包含了数据,如果为空想设置为-1,你可以使用下面的代码实现:

int nSize = v.empty() ? -1 : static_cast(v.size());

访问vector中的数据

使用两种方法来访问vector。

1、vector::at()

2、vector::operator[]

operator[]主要是为了与C语言进行兼容。它可以像C语言数组一样操作。但at()是我们的首选,因为at()进行了边界检查,如果访问超过了vector的范围,将抛出一个例外。由于operator[]容易造成一些错误,所有我们很少用它,下面进行验证一下:

分析下面的代码:

vector v;

v.reserve(10);

for(int i=0; i<7; i++)

v.push_back(i);

try

{

int iVal1 = v[7]; // not bounds checked - will not throw

int iVal2 = v.at(7); // bounds checked - will throw if out of range

}

catch(const exception& e)

{

cout << e.what();

}

我们使用reserve()分配了10个int型的空间,但并不没有初始化。

你可以在这个代码中尝试不同条件,观察它的结果,但是无论何时使用at(),都是正确的。删除vector中的数据

vector能够非常容易地添加数据,也能很方便地取出数据,同样vector提供了erase(),pop_back(),clear()来删除数据,当你删除数据的时候,你应该知道要删除尾部的数据,或者是删除所有数据,还是个别的数据。在考虑删除等操作之前让我们静下来考虑一下在STL 中的一些应用。

Remove_if()算法

现在我们考虑操作里面的数据。如果要使用remove_if(),我们需要在头文件中包含如下代码::

#include

Remove_if()有三个参数:

1、iterator _First:指向第一个数据的迭代指针。

2、iterator _Last:指向最后一个数据的迭代指针。

3、predicate _Pred:一个可以对迭代操作的条件函数。

条件函数

条件函数是一个按照用户定义的条件返回是或否的结果,是最基本的函数指针,或者是一个函数对象。这个函数对象需要支持所有的函数调用操作,重载operator()()操作。remove_if()是通过unary_function继承下来的,允许传递数据作为条件。

例如,假如你想从一个vector中删除匹配的数据,如果字串中包含了一个值,从这个值开始,从这个值结束。首先你应该建立一个数据结构来包含这些数据,类似代码如下:#include

enum findmodes

{

FM_INVALID = 0,

FM_IS,

FM_STARTSWITH,

FM_ENDSWITH,

FM_CONTAINS

};

typedef struct tagFindStr

{

UINT iMode;

CString szMatchStr;

} FindStr;

typedef FindStr* LPFINDSTR;

然后处理条件判断:

class FindMatchingString : public std::unary_function

{

public:

FindMatchingString(const LPFINDSTR lpFS) : m_lpFS(lpFS) {}

bool operator()(CString& szStringToCompare) const

{

bool retVal = false;

switch(m_lpFS->iMode)

{

case FM_IS:

{

retVal = (szStringToCompare == m_lpFDD->szMatchStr);

break;

}

case FM_STARTSWITH:

{

retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength()) == m_lpFDD->szWindowTitle);

break;

}

case FM_ENDSWITH:

{

retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength()) == m_lpFDD->szMatchStr);

break;

}

case FM_CONTAINS:

{

retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1);

break;

}

}

return retVal;

}

private:

LPFINDSTR m_lpFS;

};

通过这个操作你可以从vector中有效地删除数据:

// remove all strings containing the value of

// szRemove from vector vs.

FindStr fs;

fs.iMode = FM_CONTAINS;

fs.szMatchStr = szRemove;

vs.erase(std::remove_if(vs.begin(), vs.end(), FindMatchingString(&fs)), vs.end());

Remove_if()能做什么?

你可能会疑惑,对于上面那个例子在调用remove_if()的时候还要使用erase()呢?这是因为大家并不熟悉STL中的算法。Remove(),remove_if()等所有的移出操作都是建立在一个迭代范围上的,那么不能操作容器中的数据。所以在使用remove_if(),实际上操作的时容器里数据的上面的。思考上面的例子:

1、szRemove = “o”.

2、vs见下面图表中的显示。

观察这个结果,我们可以看到remove_if()实际上是根据条件对迭代地址进行了修改,在数据的后面存在一些残余的数据,那些需要删除的数据。剩下的数据的位置可能不是原来的数据,但他们是不知道的。

调用erase()来删除那些残余的数据。注意上面例子中通过erase()删除remove_if()的结果和vs.enc()范围的数据。

压缩一个臃肿的vector

很多时候大量的删除数据,或者通过使用reserve(),结果vector的空间远远大于实际需要的。所有需要压缩vector到它实际的大小。resize()能够增加vector的大小。Clear()仅仅能够改变缓存的大小,所有的这些对于vector释放内存等九非常重要了。如何来解决这些问题呢,让我们来操作一下。

我们可以通过一个vector创建另一个vector。让我们看看这将发生什么。假定我们已经有

一个vector v,它的内存大小为1000,当我们调用size()的时候,它的大小仅为7。我们浪费了大量的内存。让我们在它的基础上创建一个vector。

std::vector vNew(v);

cout << vNew.capacity();

vNew.capacity()返回的是7。这说明新创建的只是根据实际大小来分配的空间。现在我们不想释放v,因为我们要在其它地方用到它,我们可以使用swap()将v和vNew互相交换一下vNew.swap(v);

cout << vNew.capacity();

cout << v.capacity();

有趣的是:vNew.capacity()是1000,而v.capacity()是7。

现在是达到我的目的了,但是并不是很好的解决方法,我们可以像下面这么写:std::vector(v).swap(v);

你可以看到我们做了什么?我们创建了一个临时变量代替那个命名的,然后使用swap(),这样我们就去掉了不必要的空间,得到实际大小的v。

C++定义动态数组

C++定义动态数组 首先:为什么需要动态定义数组呢? 这是因为,很多情况下,在预编译过程阶段,数组的长度是不能预先知道的,必须在程序运行时动态的给出 但是问题是,c++要求定义数组时,必须明确给定数组的大小,要不然编译通不过 如:int Array[5];正确 int i=5; int Array[i]; 错误因为在编译阶段,编译器并不知道i 的值是多少 那么,我们该如何解决定义长度未知的数组呢? 答案是:new 动态定义数组 因为new 就是用来动态开辟空间的,所以当然可以用来开辟一个数组空间 这样,下面的语句: int size=50; int *p=new int[size]; 是正确的 但是二维动态数组能不能也这样定义呢 int size=50,Column=50; int (*p)[Column]=new int [size][Column] 这样的语句,编译器通不过,为什么呢? 首先new int[size][Column] 就是动态生成时确定的,所以它没有错 那么就是int(*p)[Column],这句有问题了,这句为什么不对呢,那是因为,这是一个定义语句,而定义语句先经过编译器进行编译,当编译器运行到此处时,发现Column 不是常数,因此不能通过编译。而之所以编译器认为Column 不是常数,是因为编译阶段,编译器起的作用是查语法错误,和预分配空间,它并不执行程序,因此,没有执行那个赋值语句(只是对这个语句检查错误,和分配空间),因此编译阶段,它将认为column 是个变量。所以上面的二维数组定义是错误的,它不能通过编译。 改成这样: int size=50 int (*p)[50]=new int [size][50] 便正确了。 由此可见,这种动态分配数组,仅对一维数组空间是真正动态分配的。 但是如何真正的动态分配二维数组呢,即如果Column 也不能预先知道的话,该如何处理呢? 上面的动态分配已经不能满足我们的要求,因为上面动态分配只对一维数组是真正动态的,对二维

如何在VC中创建动态数组

如何在VC中创建动态数组 怎样给多维数组动态分配内存 //Allocate: int **p = new int* [m]; for(int i = 0 ; i < m ; i++) p[i] = new int[n]; //Use: for(int i = 0 ; i < m; i++) for(int j = 0 ; j < n ; j++) p[i][j] = i * j; //Free: for(int i = 0 ; i < m ; i++) delete[] p[i]; delete[] p; 1. 演示形为int[2][3]的二维动态数组 /////////////////////////////////////////////////////////////////// int n1, n2; const int DIM1 = 2; const int DIM2 = 3; // 构造数组 int **ppi = new int*[DIM1]; for(n1 = 0; n1 < DIM1; n1++) { ppi[n1] = new int[DIM2]; } // 填充数据 for(n1 = 0; n1 < DIM1; n1++) { for(n2 = 0; n2 < DIM2; n2++) { ppi[n1][n2] = n1 * 10 + n2; } } // 输出 for(n1 = 0; n1 < DIM1; n1++) { for(n2 = 0; n2 < DIM2; n2++) {

afxDump << "ppi[" << n1 << "][" << n2 << "] = " << ppi[n1][n2] << "\n"; } } // 释放数组 for(n1 = 0; n1 < DIM1; n1++) { delete [] ppi[n1]; } delete [] ppi; 2. 三维动态数组(int[2][3][4]) /////////////////////////////////////////////////////////////////// int n1, n2, n3; const int DIM1 = 2; const int DIM2 = 3; const int DIM3 = 4; // 构造数组 int ***ppi = new int**[DIM1]; for(n1 = 0; n1 < DIM1; n1++) { ppi[n1] = new int*[DIM2]; for(n2 = 0; n2 < DIM2; n2++) { ppi[n1][n2] = new int[DIM3]; } } // 填充数据 for(n1 = 0; n1 < DIM1; n1++) { for(n2 = 0; n2 < DIM2; n2++) { for(n3 = 0; n3 < DIM3; n3++) { ppi[n1][n2][n3] = n1 * 100 + n2 * 10 + n3; } } } // 输出 for(n1 = 0; n1 < DIM1; n1++) { for(n2 = 0; n2 < DIM2; n2++) { for(n3 = 0; n3 < DIM3; n3++)

最新C++二维动态数组的申请与_释放汇总

C++二维动态数组的申请与_释放

一维数组是指针,可将二维数组看作是指针的指针:每一行是一个一维数组,而列是指向行的指针。在动态创建时,先分配指向行的指针空间,再循环维每一行申请空间。 #include using namespace std; int main() { //[3]4] //三行四列的二维数组 int x,y; int i,n,k; x=3; y=4; int **p; p = new int*[x]; //行 //申请行的空间 //每行的列申请空间 for(i=0; i

//赋值, k=0; for(i=0;i

delete [] p[i]; } delete [] p; return 0; 今天归纳总结了一下,希望以后的朋友可以少走些弯路:) 一:关于指针和堆的内存分配 先来介绍一下指针:指针一种类型,理论上来说它包含其他变量的地址,因此有的书上也叫它:地址变量。既然指针是一个类型,是类型就有大小,在达内的服务器上或者普通的PC机上,都是4个字节大小,里边只是存储了一个变量的地址而已。不管什么类型的指针,char * ,int * ,int (*) ,string * ,float * ,都是说明了本指针所指向的地址空间是什么类型而已,了解了这个基本上所有的问题都好象都变的合理了。 在C++中,申请和释放堆中分配的存贮空间,分别使用new和delete的两个运算符来完成: 指针类型指针变量名=new 指针类型 (初始化); delete 指针名; 例如:1、 int *p=new int(0); 它与下列代码序列大体等价: 2、int tmp=0, *p=&tmp; 区别:p所指向的变量是由库操作符new()分配的,位于内存的堆区中,并且该对象未命名。 下面是关于new 操作的说明:部分引自<>

c#中动态数组的使用

在向大家详细介绍C#动态数组之前,首先让大家了解下C#动态数组的方法及属性,然后全面介绍C#动态数组。 下面的例子向你演示C#动态数组的方法及属性,这样通过实例的演示介绍能够更加深刻的理解C#动态数组的各项基本概念和应用,希望对你有所帮助。 C#动态数组的详解实例: 1.ArrayList AL = new ArrayList(); 2.AL.Add("Hello"); 3.AL.Add(" World"); 4.Console.WriteLine("给数组添加元素:"); 5.foreach (Object obj in AL) 6.{ Console.Write(obj); } 7.Console.WriteLine(); 8.Console.WriteLine("个数:" + AL.Count); 9.Console.WriteLine("容量: " + AL.Capacity); 10.AL.Insert(1, " c#"); 11.//C#动态数组的详解实例 12.Console.Write("在索引值为1的地方插入 "); 13.foreach (Object obj in AL) 14.{Console.Write(obj); } 15.Console.WriteLine(); 16.Console.WriteLine("个数:" + AL.Count); 17.Console.WriteLine("容量: "+AL.Capacity); 18.AL.Add("。");//给集合添加“。”,查看集合的容量 19.Console.WriteLine("容量。: " + AL.Capacity); 20.AL.Add("---");//给集合添加“---”,查看当集合的容量不够时,倍数变化 21.Console.WriteLine("容量---: " + AL.Capacity); 22.Console.WriteLine("3号索引的:"+AL[3]); 23.//用索引方式获取集合元素值 24.//C#动态数组的详解实例 25.Console.WriteLine("数组中是否包含?:"+AL.Contains ("?")); 26.//利用contains方法,查找集合中是否包含“?” 27.Console.WriteLine("经过之前操作后的数组元素:"); 28.foreach (Object obj in AL) 29.{ Console.Write(obj); } 30.Console.WriteLine(); 31.Console.WriteLine("个数:" + AL.Count);

C语言中动态数组的实现

C语言中动态数组的实现 (2009-05-10 10:19:30) 转载 分类:C语言学习 标签: c中动态数组 教育 近来编写几个程序,很多都用到了数组。但是对于数组的大小却是没有固定的,也就是说可以更改数组大小,其大小是可以变化的。并不像初学时的那样,告诉你一个范围,你就必须取最大值以满足要求。那样可能就会浪费很多不必要的内存单元!那么到底应该怎样定义一个动态数组列? 在数组一章中,曾介绍过数组的长度是预先定义好的,在整个程序中固定不变。C语言中不允许动态数组类型。例如: int n;scanf("%d",&n);int a[n]; 用变量表示长度,想对数组的大小作动态说明,这是错误的。但是在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。对于这种问题,用数组的办法很难解决。为了解决上述问题,C语言提供了一些内存管理函数,这些内存管理函数可以按需要动态地分配内存空间,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。其它文献中所提到的"动态数组",指的就是利用内存的申请和释放函数,在程序的运行过程中,根据实际需要指定数组的大小.其本质是一个指向数组的指针变量.常用的内存管理函数有以下三个: 1.分配内存空间函数malloc 调用形式: (类型说明符*) malloc (size) 功能:在内存的动态存储区中分配一块长度为"size" 字节的连续区域。函数的返回值为该区域的首地址。“类型说明符”表示把该区域用于何种数据类型。(类型说明符*)表示把返回值强制转换为该类型指针。“size”是一个无符号数。例如: pc=(char *) malloc (100); 表示分配100个字节的内存空间,并强制转换为字符数组类型,函数的返回值为指向该字符数组的指针,把该指针赋予指针变量pc。 2.分配内存空间函数 calloc calloc 也用于分配内存空间。调用形式: (类型说明符*)calloc(n,size) 功能:在内存动态存储区中分配n块长度为“size”字节的连续区域。函数的返回值为该区域的首地址。(类型说明符*)用于强制类型转换。calloc函数与malloc 函数的区别仅在于一次可以分配n块区域。例如: ps=(struet stu*) calloc(2,sizeof (struct stu)); 其中的sizeof(struct stu)是求stu的结构长度。因此该语句的意思是:按stu的长度分配2块连续区域,强制转换为stu 类型,并把其首地址赋予指针变量ps。

c语言数组的动态分配

下面代码添加到头文件里面 #include #include struct data { int*p;//指针保存数组起始点 int length;//保存数组长度 int reallength;//实际分配内存长度 int state;//0代表无序,1代表有序从小到大,2代表有序从大到小 }; struct find { int**pp; int n; }; void init(struct data*pdata);//初始化 void reinit(struct data*pdata);//重新初始化 void addobject(struct data*pdata,int num);//增加一个元素 void addobjects(struct data*pdata,int*pnum,int n);//增加一个数组void printf1(struct data*pdata);//打印一个出来 void sort(struct data*pdata,int obj);//实现排序obj=0从小到大,否则从大到小 int*finddata(struct data*pdata,int num);//找到并返回第一次找到的地址void change(struct data*pdata,int oldnum,int newnum);//修改一个数据void insert(struct data*pdata,int num,int insertnum,int headback);//插入一个数据,0代表前插,1代表后插 void deleteone(struct data*pdata,int num);//删除第一个找到的数据 void deleteall(struct data*pdata,int num);//删除找到的全部数据 struct find findalldata(struct data*pdata,int num);//返回一片内存,包含所有找到的元素

Delphi之动态数组使用总结

Delphi之动态数组使用总结 传统的Pascal 语言其数组大小是预先确定的,当你用数组结构声明数据类型时,你必须指定数组元素的个数。专业程序员也许知道些许动态数组的实现技术,一般是采用指针,用手工分配并释放所需的内存。 Delphi 4中增加了非常简单的动态数组实现方法,实现过程效仿我前面讲过的动态长字符串。与长字符串一样,动态数组的内存动态分配并且引用记数,不过动态数组不支持copy-on-write 技术。这不是个大问题,因为你可以把变量值设置为nil释放数组内存。 这样你就可以声明一个不指定元素个数的数组,并用SetLength 过程给数组分配一个特定大小的内存,SetLength 过程还可以改变数组大小而不影响其内容,除此外还有一些字符串过程也可用于数组,如Copy 函数。 以下摘录的代码突出了一点,这就是:定义数组后必须先为它分配内存,然后才能开始使用: procedure TForm1.Button1Click(Sender: TObject);var Array1: array of Integer;begin Array1 [1] := 100; // error SetLength (Array1, 100); Array1 [99] := 100; // OK ...end; 如果你只定义一个数组元素个数,那么索引总是从0开始。Pascal 中的普通数组既能用不为零的下标,也能用非整数的下标,但动态数组均不支持这两种下标。象普通数组一样,你可以通过Length、High和Low 函数了解到动态数组的状况,不过对于动态数组,Low 函数返回值总是0,High函数返回数组大小减1,这意味着空的动态数组其函数High返回值是-1,这是一个很怪的值,因为它比Low的返回值还小。 图8.1:例DynArr 窗体 以上作了简短的介绍,现在举个简例,例名DynArr ,见图8.1。例子实在是很简单,其实动态数组没有什么特别复杂地方。我想通过该例说明几个程序员可能犯的错误。程序中声明了两个全程数组并在OnCreate 事件中初始化了第一个数组: var Array1, Array2: array of Integer;procedure TForm1.FormCreate(Sender: TObject);begin // allocate SetLength (Array1, 100);end; 这样就把数组所有值设置为0。完成这段代码你马上就能读写数组元素的值,而不用害怕内存出错,当然条件是你没有试图访问超过数组上界的元素。为了更好地初始化,程序中添加了一个按钮,执行数组元素赋值操作:

vc 创建动态数组

如何在VC中创建动态数组 关键词:VC 动态数组 怎样给多维数组动态分配内存 //Allocate: int **p = new int* [m]; for(int i = 0 ; i < m ; i++) p[i] = new int[n]; //Use: for(int i = 0 ; i < m; i++) for(int j = 0 ; j < n ; j++) p[i][j] = i * j; //Free: for(int i = 0 ; i < m ; i++) delete[] p[i]; delete[] p; 1. 演示形为int[2][3]的二维动态数组 /////////////////////////////////////////////////////////////////// int n1, n2; const int DIM1 = 2; const int DIM2 = 3; // 构造数组 int **ppi = new int*[DIM1]; for(n1 = 0; n1 < DIM1; n1++) { ppi[n1] = new int[DIM2]; } // 填充数据 for(n1 = 0; n1 < DIM1; n1++) { for(n2 = 0; n2 < DIM2; n2++) { ppi[n1][n2] = n1 * 10 + n2; } } // 输出 for(n1 = 0; n1 < DIM1; n1++) { for(n2 = 0; n2 < DIM2; n2++) { afxDump << "ppi[" << n1 << "][" << n2 << "] = " << ppi[n1][n2] << "\n"; } }

一维动态数组

用动态内存分配方法设计一个数组类,实现排序、插入等基本功能(特别注意拷贝构造函数的写法)#pragma once #include using namespace std; class myArrayList { public: myArrayList(int n=0); myArrayList(const int *a,int n); myArrayList(const int *a,int n,int max); myArrayList(const myArrayList &tList); ~myArrayList(void); void sort(); void show(); bool orderInsert(int num); private: int maxLen; int Len; int *arrPtr; }; #include"myArrayList.h" myArrayList::myArrayList(int n) { this->arrPtr=NULL; maxLen=Len=0; } myArrayList::~myArrayList(void) { delete [] arrPtr; } myArrayList::myArrayList(const int a[], int n) { maxLen=Len=n; this->arrPtr=new int[maxLen]; for(int i=0;iarrPtr=new int[maxLen];

C语言动态数组

动态数组是指在声明时没有确定数组大小的数组,即忽略圆括号中的下标;当要用它时,可随时用ReDim语句(C语言中用malloc语句)重新指出数组的大小。使用动态数组的优点是可以根据用户需要,有效利用存储空间。 动态数组,是相对于静态数组而言。静态数组的长度是预先定义好的,在整个程序中,一旦给定大小后就无法改变。而动态数组则不然,它可以随程序需要而重新指定大小。动态数组的内存空间是从堆(heap)上分配(即动态分配)的。是通过执行代码而为其分配存储空间。当程序执行到这些语句时,才为其分配。程序员自己负责释放内存。(欲详细了解堆请见堆栈) 为什么要使用动态数组? 在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。对于这种问题,用静态数组的办法很难解决。为了解决上述问题,C语言提供了一些内存管理函数,这些内存管理函数结合指针可以按需要动态地分配内存空间,来构建动态数组,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。 动态数组与静态数组的对比 对于静态数组,其创建非常方便,使用完也无需释放,要引用也简单,但是创建后无法改变其大小是其致命弱点! 对于动态数组,其创建麻烦,使用完必须由程序员自己释放,否则严重会引起内存泄露。但其使用非常灵活,能根据程序需要动态分配大小。 如何构建动态数组 遵循原则 申请的时候从外层往里层,逐层申请; 释放的时候从里层往外层,逐层释放。 构建所需指针 对于构建一维动态数组,需要一维指针;对于二维,则需要一维,二维指针;三维需要一,二,三维指针; 依此类推。 构建所需函数 函数原型返回 功能说明 void *malloc(unsigned int size); 成功:返回所开辟空间首地址失败:返回空指针向系统申请size字节的堆空间 void *calloc(unsigned int num, unsigned int size);成功:返回所开辟空间首地址失败:返回空指针按类型申请num个size字节的堆空间 void free(void *p); 无返回值 释放p指向的堆空间 void *realloc(void *p,unsigned int size); 成功:返回新开辟空间首地址失败:返回空指针将p指向的堆空间变为size 说明: (1)规定为void *类型,这并不是说该函数调用后无返回值,而是返回一个结点的地址,该地址的类型为void(无类型或类型不确定),即一段存储区的首址,其具体类型无法确定,只有使用时根据各个域值数据再确定。可以用强制转换的方法将其转换为别的类型。例

动态数组vector用法

Vector用法介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作。本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用。通过阅读这篇文章读者应该能够有效地使用vector容器,而且应该不会再去使用C类型的动态数组了。 Vector总览 vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。为了可以使用vector,必须在你的头文件中包含下面的代码: #include vector属于std命名域的,因此需要通过命名限定,如下完成你的代码: using std::vector; vector vInts; 或者连在一起,使用全名: std::vector vInts; 建议使用全局的命名域方式: using namespace std; 在后面的操作中全局的命名域方式会造成一些问题。vector容器提供了很多接口,在下面的表中列出vector的成员函数和操作。 Vector的函数 c.assign(beg,end) 将[beg; end)区间中的数据赋值给c。 c.assign(n,elem) 将n个elem的拷贝赋值给c。 c.at(idx) 传回索引idx所指的数据,如果idx越界,抛出out_of_range。

c.back() 传回最后一个数据,不检查这个数据是否存在。 c.begin() 传回迭代器中的一个数据。 c.capacity() 返回容器中数据个数。 c.clear() 移除容器中所有数据。 c.empty() 判断容器是否为空。 c.end() 指向迭代器中的最后一个数据地址。 c.erase(pos) 删除pos位置的数据,传回下一个数据的位置。 c.erase(beg,end) 删除[beg,end)区间的数据,传回下一个数据的位置。 c.front() 传回地一个数据。 get_allocator 使用构造函数返回一个拷贝。 c.insert(pos,elem) 在pos位置插入一个elem拷贝,传回新数据位置。 c.insert(pos,n,elem) 在pos位置插入n个elem数据。无返回值。 c.insert(pos,beg,end) 在pos位置插入在[beg,end)区间的数据。无返回值。

动态数组的创建

摘要的重要性是不言而喻的,每次发文章我都很纠结如何写出一个有特色的摘要来,能够以最为简短的文字向读者描述出我所要表达的东西。但是常常出现的问题是,摘要写得太简短了,读者看了不清楚文章究竟要讲啥;摘要写得稍微长点的话自然能够描述清楚所要表达的东西,但是却也出现了另外一个问题,就是读者看到大段的文字描述,觉得枯燥无味,直接二话不说给文章判了个“死刑”,导致这种情况下愿意真正的花时间看完摘要的读者屈指可数,更不用说文章的正文部分了,所以时长感慨写文章最头疼的莫过于摘要了。 很多人在编写C语言代码的时候很少使用动态数组,不管什么情况下通通使用静态数组的 方法来解决,在当初学习C语言的时候我就是一个典型的例子,但是现在发现这是一个相 当不好的习惯,甚至可能导致编写的程序出现一些致命的错误。尤其对于搞嵌入式的人来所,嵌入式系统的内存是宝贵的,内存是否高效率的使用往往意味着嵌入式设备是否高质量和高性能,所以高效的使用内存对我们来说是很重要的。那么我们在自己编写C语言代码的时 候就应该学会使用动态数组,这也就是我这篇博客要给大家讲的,我尽我所能的用一些简单的代码来讲解动态数组,希望我所讲的对你有所帮助。 那么我们首先来看看什么是动态数组,动态数组是相对于静态数组而言,从“动”字我们也可以看出它的灵活性,静态数组的长度是预先定义好的,在整个程序中,一旦给定大小后就无法改变。而动态数组则不然,它可以随程序需要而重新指定大小。动态数组的内存空间是从堆动态分配的。是通过执行代码而为其分配存储空间。当程序执行到我们编写的分配语句时,才为其分配。对于静态数组,其创建非常方便,使用完也无需释放,要引用也简单,但是创建后无法改变其大小是其致命弱点!对于动态数组,其创建麻烦,使用完必须由程序员自己释放,否则将会引起内存泄露。但其使用非常灵活,能根据程序需要动态分配大小。所以相对于静态数组的来说我们对于使用动态数组有很大的自由度。 在创建动态数组的过程中我们要遵循一个原则,那就是在创建的时候从外层往里层,逐层创建;而释放的时候从里层往外层,逐层释放。这个话你读了可能理解并不深刻,不过不要急,接下来我们看看两段代码。 一维动态数组的创建: #include #include int main() { int n1,i; int *array; printf("请输入所要创建的一维动态数组的长度:");

(一)C++动态二维数组的申请、赋值、使用、释放以及作参数示例

/***************************/ /* DYNAMIC ARRAY EXEMPLE */ /* 唐国峰2011年月日 */ /***************************/ //按照动态二维数组的申请、赋初值、使用、释放空间五个部分给出代码,以示参考。//同时,给出了动态二维数组用作形参和实参的实例,方便大家查询。 #include using namespace std; //动态二维数组作形参 void display(int ** &p,int row,int col) { int i,j; for(i = 0;i <= row-1;i++) { for(j = 0; j <= col-1;j++) { cout << p[i][j]+i+j << "\t"; } cout << endl; } } //主函数 void main() { //-------格式化输出模板信息内容------开始------ cout << "程序输出结果如下所示:" << endl << endl; cout << "/***************************/" << endl; cout << "/* DYNAMIC ARRAY EXEMPLE */" << endl; cout << "/* 唐国峰2011年月日 */" << endl; cout << "/***************************/" << endl << endl; //-------格式化输出模板信息内容------结束------ int **p; //这是指向指针的指针 int row,col; //此动态二维数组为“row”行、“col”列 int i,j; //循环用变量 //动态二维数组p的申请 cout << "请输入行数和列数:" << endl << endl; cin >> row >> col; cout << endl; p = new int *[row]; for(int i = 0;i <= row-1;i++) { p[i]=new int[col]; } //为动态二维数组p的元素赋初值 for(i = 0;i <= row-1;i++) { for(j = 0; j <= col-1;j++)

c加加动态数组加无限内存人员管理系统

c加加动态数组加无限内存人员管理 系统

”信息与计算科学”专业 《C++语言程序设计》课程设计 班级计算科学 姓名 学号 指导教师 设计日期·春·19周~20周

( 一) 、设计菜单选择程序。 菜单是应用程序的界面, 经过控制语句改变程序执行的顺序, 设计菜单是程序设计的基础。本设计分两步: 第一步: 设计一个菜单程序。 1.菜单内容: 程序运行后, 给出3个菜单项的内容和输入提示, 如下: 1)利用克莱姆法则求解线性方程组 2)统计一篇英文文章的单词数 3)退出程序 第二步: 为上述菜单项配上相应的功能。

2.程序优缺点: 优点: 采用了动态开辟二维数组, 传递不知道大小的二维数组, 程序规范, 可读性强。 缺点:采用递归算法, 增加了程序的时间复杂度。 3.代码段: #include #include #include #include using namespace std; double **open_up(int row,int line); double Price(int row,int line,double *a); void Head(); void Cramer();

void Statis_Words(); int main() { char ch; // 选择变量 while(1) { Head(); cout<<"\t\t选择要进行的程序: "<

VB编程基础教程10–动态数组

VB编程基础教程10–动态数组 [ 程序乐园] 数组到底应该有多大才合适,有时可能不得而知。所以希望能够在运行时具有改变数组大小的能力。 动态数组就可以在任何时候改变大小。在visual basic 中,动态数组最灵活、最方便,有助于有效管理内存。例如,可短时间使用一个大数组,然后,在不使用这个数组时,将内存空间释放给系统。 如果不用动态数组,就要声明一个数组,它的大小尽可能达到最大,然后再抹去那些不必要的元素。但是,如果过度使用这种方法,会导致内存的操作环境变慢。 要创建动态数组,请按照以下步骤执行: (如果希望数组为公用数组,则)用public 语句声明数组,或者,(如果希望数组为模块级,则)在模块级用dim 语句声明数组,或者(如果希望数组为局部数组,则)在过程中用static 或dim 语句声明数组。给数组附以一个空维数表,这样就将数组声明为动态数组。 dim dynarray () 用redim 语句分配实际的元素个数。 redim dynarray (x + 1) redim 语句只能出现在过程中。与dim 语句、static 语句不同,redim 语句是一个可执行语句,由于这一语句,应用程序在运行时执行一个操作。 redim 语句支持这样的语法,它与固定数组中使用的语法相同。对于每一维数,每个redim 语句都能改变元素数目以及上下界。但是,数组的维数不能改变。 redim dynarray (4 to 12) 例如,用第一次声明在模块级所建立的动态数组matrix1: dim matrix1 () as integer 然后,在过程中给数组分配空间: sub calcvaluesnow () . . . redim matrix1 (19, 29) end sub 这里的redim 语句给matrix 分配一个20 ×30 的整数矩阵(元素总大小为600)。还有一个办法,用变量设置动态数组的边界: redim matrix1 (x, y) 注意您可以将字符串赋值给大小可变的字节数组。一个字节数组也可以被赋值给一个可变长的字符串。一定要注意字符串中的字节数会随平台而变化。同一个字符串在unicode 平台上的字节数是它在非unicode 平台上的两倍。 保留动态数组的内容 每次执行redim 语句时,当前存储在数组中的值都会全部丢失。visual basi 重新将数组元素的值置为empty(对variant 数组)、置为0(对numeric 数组)、置为零长度字符串(对string 数组)或者置为nothing(对于对象的数组)。 在为新数据准备数组,或者要缩减数组大小以节省内存时,这样做是非常有用的。有时希望改变数组大小又不丢失数组中的数据。使用具有preserve 关键字的redim 语句就可做到这点。例如,使用ubound 函数引用上界,使数组扩大、增加一个元素,而现有元素的值并

e_00005+Java动态数组的用法详解

?Java动态数组的用法详解 ? ? Java动态数组是一种可 以任意伸缩数组长度的对象,在 Java中比较常用的是ArrayLis t,ArrayList是javaAPI中自带 的java.util.ArrayList。下面 介绍一下ArrayList作为Java 动态数组的用法。 1.语法:add()是添加一个新 的元素,remove()删除一个元素, size()获得ArrayList的长度。A rrayList的下标是从0开始。 2.示例代码 package wang48.jiaocheng; import java.util.ArrayList; public class JavaArrayList { public static void main(String[]args) { //Java动态数组的初始化 ArrayList al=new ArrayList(); //向Java动态数组中添加数据 al.add("a"); al.add("b"); al.add("c"); //输出Java动态数组 for(int i=0;i

} //删除数组中的某个元素,删除第二个元素 al.remove(1); //修改Java动态数组,把新的元素放到第二个位置 al.add(1,"2"); ////输出Java动态数组 for(int i=0;i

动态二维数组的用法

1、动态创建二维数组 正确的做法: 方法一: void fun(int iRow, int iCol) { CString** ppData; ppData = new CString*[iRow]; for(int i=0;i< iRow;++i) { ppData[i] = new CString[iCol]; } } 方法二: void fun(int iRow, int iCol) { CString* pTemp; CString** ppData; pTemp =new CString[iRow*iCol]; ppData = new CString*[iRow]; for(int i=0;i< iRow;++i) { ppData[i] =&pTemp[i*iCol]; } } ppData就是我们创建的二维数组。 错误的做法: void fun(int iRow, int iCol) { CString** ppData; ppData = new CString[iRow][iCol]; } 错误提示:error C2540: non-constant expression as array bound 2、使用二维数组 (1)我们在应用中有时候会需要把一个二维数组作为参数传入一个函数中,这个函数的形式怎样才是正确的? void fun(CString** str, int iRow, int iCol); 正确 void fun(CString str[][], int iRow, int iCol); 错误,没有指定数组的列数! void fun(CString* str, int iRow, int iCol); 正确,可以在函数内部对str处理,变成一

C#动态数组动态分配长度的方法

C#之动态数组 C#中的数组是可以动态分配长度的,实现动态数组有以下几种途径,这里说的动态数组包括动态分配大小和动态增加数据. 先来看原始数组: int m = 5; int[] array = new int[m]; array[0] = 2; label1.Text = array[0].ToString() + " + " + array.Length.ToString(); 结果的输出自然是2 + 5; 动态分配: 1:m++; array = new int[m];//相当于重新初始化,原来的值被冲掉了 label2.Text = array[0].ToString() + " + " + array.Length.ToString(); 结果输出自然是0 + 6; 2:m++; Array.Resize(ref array, m); label2.Text = array[0].ToString() + " + " + array.Length.ToString(); 结果输出自然是2 + 6;

3:再有就是通过ArrayList的方法 第1种方案适合能够事先能从某处读出来长度的情况;第2,3种方案最适合在事先不知道数据长度究竟有多少,只能来一个算一个的情况,个人感觉,这才是动态数组真正的用途,也就是能够随着数据的增加而自动扩容。 在这方面ArrayList毫无疑问是首选,能够真正实现这个功能. ArrayList al = new ArrayList(); al.Add(NewData);//单个添加 如果增加的是同一类型的数据,用Array.Resize()也是能够实现的: if(产生了新数据)//增加个判断 { m++;//假设数组原来的长度是m Array.Resize(ref array,m); array[m] = NewData; } 虽然有同样的效果,但本质上是有差异的.ArrayList是真正的在变长. 而System.Array.Resize这个泛型方法是重新创建新设置大小的数组,用的是旧数组的元素初始化。随后以前的数组就废弃!也就是说并不是在原先的基础上扩容,而是新建了一个.但是无论如何在表面上看来确实实现了我们想要的功能.

相关文档
最新文档