当前位置:首页 > 天道酬勤 > 正文内容

c允许对数组的长度进行动态调整(c语言定义动态数组)

张世龙2021年12月20日 04:47天道酬勤980

接下来,更新c入门教程“c的动态数组”

c的new运算符是该语言非常好的语法特性,但实际使用后发现new运算符有很多限制。 比较突出的是,用new运算符分配多维数组空间时,数组的各维不能动态变化。 本文对此提出了一个简单直观的解决方案,用实际问题的简化模型来说明,从而揭示许多初学者对c中new操纵子和多维数组的误解。 1 .问题的提出---多维可变数组的实际用途以下是在实际编程中遇到问题的简化模型。 ChessBoard是板类,其中m_board是用于保存板上棋子信息的二维排列。 DIMENSION是棋盘的尺寸和维数。 因为用于数组声明,所以必须是可以在编译过程中确定其值的常数。 这里使用了无名列列举。 根据将棋的种类不同,棋盘的大小也不同。 对于奥赛罗,DIMENSION定义为8,而对于五子棋,DIMENSION必须为15。 围棋时,必须是19。 此代码使用条件编译来确定DIMENSION常量的值,以确保高重用性。 因为m_board必须是编译时间常数,所以在程序运行时m_board数组的大小不能更改。 要在节目中同时实现奥赛罗、五子棋和围棋,就不能这样做。 当然,这有点夸张,但光围棋就有9x9、13x13、19x19种棋盘,必须让用户在运行程序时自由选择。

类别板

{

私有:

数字

# # ifdef奥特尔罗

DIMENSION=8 file://奥赛罗时,控制柜的大小为8x8

# # endif

# # ifdef笔

DIMENSION=15 file://五子棋时,棋盘的大小为15x15

# # endif

(;

intm _ board维度维度;

公共:

/*其他成员函数

…。

*/

与此相反,必须使用new操作符或malloc函数在程序运行时动态地为m_board分配空间。 由于new支持更多的c特性,所以我们的程序采用了new操作员。

2 .在MSDN上用new申请多维数组的说明---进一步认识到new算子下的代码摘自MSDN的“new operator”。 其中,用VC6.0编译第2行时会显示错误信息。 在此MSDN中的说明中,new操作符返回的类型为float[25][10]的正确代码应如第3、4行所示。

1 .浮点* FP;

2.FP=新浮点[ 10 ] [ 25 ] [ 10 ]; //错误消息:从浮点(* ) [ 25 ] [ 10 ] '到浮点* ] )。

浮动(* CP ) [25][10];

4.CP=新浮点[ 10 ] [ 25 ] [ 10 ]; 参考这个代码来考虑一下我们的主板问题吧。 根据葫芦画瓢,可以得到以下代码。

int(m_board )维度; //用类的成员变量声明

m _ board=新建可变更维度; //根据用户的选择决定适当的Changeable值,需要用编译时间常数DIMENSION声明数组,所以可以看出m_board数组只有一维的变量,这个方法对我们的问题没有帮助。

3 .解决方案这里给出了两个解决方案,第二个方案给出了具体的代码。 1 )申请大小为. XSIZE*YSIZE的一维数组,可以通过自己换算xy下标来查找对应的存储单元。 代码如下。

int * p=新int [符号*符号]; file://XSIZE和YSIZE需要定义为常数

file://但是,对p[y][x]的引用将出现语法错误,应该如下所示

p * xsize x=y * 1000 x; 这个方法最大的优点是数组的维数可以自由决定,甚至可以动态决定。 因为都将转换为一维数组。 但是,其最大的不便之处是下标转换的复杂性,在多维数组的情况下更为明显。 下面的代码是验证下标转换是否正确的程序,输出结果应该因数组单位而异,位于“开始地址”和“结束地址”之间。

一致符号=6;

恒定x大小=7;

恒定z大小=9;

int * p=新int [符号*符号* z符号];

file://但是,对p[y][x]的引用将出现语法错误,应该如下所示

cout (整数) p )开始地址\n );

计数(整数)大小)整数) *大小*大小* z大小'结束地址\n ';

for(intz=0; z<; z大小; z ) {2}

for (国际=0; y<;

YSIZE;Y++){     for(int x=0;x<XSIZE;X++){      p[z*YSIZE*XSIZE+y*XSIZE + x]=(z+1)*1000+y*10 + x;      cout << "当前单元地址:" << (int)&p[z*YSIZE*XSIZE+y*XSIZE + x]      << "----" << p[z*YSIZE*XSIZE+y*XSIZE + x] << "\t";     }    }   }

可以看到其中的数组p仅仅是一个三维数组的但是其下标转换z*YSIZE*XSIZE+y*XSIZE+x已经相当繁琐了,使用上的繁琐常常会成为程序中Bug的来源。因此这种方法对初学者并不适用,但它的灵活性与简单性使我们不能忽视它。利用这种方法可以将多维数组封装成一个通用类,不但可以动态改变数组每一维的大小,而且连数组的维数都可以动态改变(这个通用数组类正在笔者的计划之中)。  2). 将多维数组当作多个一维数组。  这里我们直接给出前面提出棋盘类问题的代码,构造函数ChessBoard、析构函数~ChessBoard和输出函数Output中分别对应给出了二维数组m_board的空间分配,空间释放和单元引用的相关代码。而且可以看出虽然这种方法需要用循环来分配、释放空间并且需要额外的存储空间,但从Output函数可以看到,它的使用与常规数组使用的语法是一致的,较上面的第一种方法繁琐的下标转换要方便得多。  由于代码并不复杂,除了代码中的注释外,就不再另外详细说明。虽然这里给出的是二维数组,但也不难将其扩充到多维数组。

class ChessBoard{    private:     const int DIMENSION;     int **m_board;    public:     void Output();     ~ChessBoard();     ChessBoard(int BoardSize);   };   ChessBoard::ChessBoard(int BoardSize=8):   DIMENSION(BoardSize){   m_board = new int*[DIMENSION]; //为m_board数组分配空间   for(int y=0;y<DIMENSION;Y++){    m_board[y] = new int[DIMENSION];    for(int x=0;x<DIMENSION;X++){     m_board[y][x]=0; file://对每个元素初始化    }   }   }   ChessBoard::~ChessBoard(){ //释放m_board的空间    for(int y=0;y<DIMENSION;Y++){     delete []m_board[y];    }    delete []m_board;   }   void ChessBoard::Output(){ //输出所有元素,其访问方法与常规数组一样,无需下标转换    for(int y=0;y<DIMENSION;Y++){      for(int x=0;x<DIMENSION;X++){       switch(m_board[y][x]){         case 1: cout << "●"; break;         case 0: cout << " "; break;         case 2: cout << "○"; break;       }      }    }   }

敢于本次的c++入门教程有不清楚的地方可以留言哈,更多的c++入门教程也会持续更新!

扫描二维码推送至手机访问。

版权声明:本文由花开半夏のブログ发布,如需转载请注明出处。

本文链接:https://www.zhangshilong.cn/work/25388.html

标签: int函数数组
分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。