Ari*_*nen 25 c c++ arrays multidimensional-array
在C和/或C++中操作动态(所有维度直到运行时才知道)的多维数组的接受/最常用方法是什么.
我正在努力找到完成此Java代码的最简洁方法:
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int rows=sc.nextInt();
int cols=sc.nextInt();
int[][] data=new int[rows][cols];
manipulate(data);
}
public static void manipulate(int[][] data){
for(int i=0;i<data.length;i++)
for(int j=0;j<data[0].length.j++){
System.out.print(data[i][j]);
}
}
Run Code Online (Sandbox Code Playgroud)
(从std_in读取只是为了澄清维度直到运行时才知道).
编辑:我注意到这个问题非常受欢迎,即使它很老了.我实际上并不同意最高投票的答案.我认为C的最佳选择是使用一维数组,如Guge所说:"你可以分配行cols sizeof(int)并通过表[row*cols + col]来访问它."
C++有很多选择,如果你真的喜欢boost或stl,那么下面的答案可能更好,但最简单也可能最快的选择是使用C中的单维数组.
如果你想要[] []语法,那么在C和C++中另一个可行的选择是lillq在底部的答案是手动构建具有大量malloc的数组.
Kla*_*aim 21
在您的示例中,您在编译时唯一需要知道的是维数.这是文档中的第一个示例:
#include "boost/multi_array.hpp"
#include <cassert>
int
main () {
// Create a 3D array that is 3 x 4 x 2
typedef boost::multi_array<double, 3> array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
// Assign values to the elements
int values = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
A[i][j][k] = values++;
// Verify values
int verify = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
assert(A[i][j][k] == verify++);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:正如评论中所建议的,这是一个"简单"的示例应用程序,它允许您在运行时定义多维数组大小,从控制台输入询问.以下是此示例应用程序的示例输出(使用常量编译,表示它是3维):
Multi-Array test!
Please enter the size of the dimension 0 : 4
Please enter the size of the dimension 1 : 6
Please enter the size of the dimension 2 : 2
Text matrix with 3 dimensions of size (4,6,2) have been created.
Ready!
Type 'help' for the command list.
>read 0.0.0
Text at (0,0,0) :
""
>write 0.0.0 "This is a nice test!"
Text "This is a nice test!" written at position (0,0,0)
>read 0.0.0
Text at (0,0,0) :
"This is a nice test!"
>write 0,0,1 "What a nice day!"
Text "What a nice day!" written at position (0,0,1)
>read 0.0.0
Text at (0,0,0) :
"This is a nice test!"
>read 0.0.1
Text at (0,0,1) :
"What a nice day!"
>write 3,5,1 "This is the last text!"
Text "This is the last text!" written at position (3,5,1)
>read 3,5,1
Text at (3,5,1) :
"This is the last text!"
>exit
Run Code Online (Sandbox Code Playgroud)
代码中的重要部分是主要功能,我们从用户获取维度并使用以下内容创建数组:
const unsigned int DIMENSION_COUNT = 3; // dimension count for this test application, change it at will :)
// here is the type of the multi-dimensional (DIMENSION_COUNT dimensions here) array we want to use
// for this example, it own texts
typedef boost::multi_array< std::string , DIMENSION_COUNT > TextMatrix;
// this provide size/index based position for a TextMatrix entry.
typedef std::tr1::array<TextMatrix::index, DIMENSION_COUNT> Position; // note that it can be a boost::array or a simple array
/* This function will allow the user to manipulate the created array
by managing it's commands.
Returns true if the exit command have been called.
*/
bool process_command( const std::string& entry, TextMatrix& text_matrix );
/* Print the position values in the standard output. */
void display_position( const Position& position );
int main()
{
std::cout << "Multi-Array test!" << std::endl;
// get the dimension informations from the user
Position dimensions; // this array will hold the size of each dimension
for( int dimension_idx = 0; dimension_idx < DIMENSION_COUNT; ++dimension_idx )
{
std::cout << "Please enter the size of the dimension "<< dimension_idx <<" : ";
// note that here we should check the type of the entry, but it's a simple example so lets assume we take good numbers
std::cin >> dimensions[dimension_idx];
std::cout << std::endl;
}
// now create the multi-dimensional array with the previously collected informations
TextMatrix text_matrix( dimensions );
std::cout << "Text matrix with " << DIMENSION_COUNT << " dimensions of size ";
display_position( dimensions );
std::cout << " have been created."<< std::endl;
std::cout << std::endl;
std::cout << "Ready!" << std::endl;
std::cout << "Type 'help' for the command list." << std::endl;
std::cin.sync();
// we can now play with it as long as we want
bool wants_to_exit = false;
while( !wants_to_exit )
{
std::cout << std::endl << ">" ;
std::tr1::array< char, 256 > entry_buffer;
std::cin.getline(entry_buffer.data(), entry_buffer.size());
const std::string entry( entry_buffer.data() );
wants_to_exit = process_command( entry, text_matrix );
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
你可以看到,为了加入数组中的元素,它非常简单:你只需使用operator(),如下面的函数:
void write_in_text_matrix( TextMatrix& text_matrix, const Position& position, const std::string& text )
{
text_matrix( position ) = text;
std::cout << "Text \"" << text << "\" written at position ";
display_position( position );
std::cout << std::endl;
}
void read_from_text_matrix( const TextMatrix& text_matrix, const Position& position )
{
const std::string& text = text_matrix( position );
std::cout << "Text at ";
display_position(position);
std::cout << " : "<< std::endl;
std::cout << " \"" << text << "\"" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
注意:我在VC9 + SP1中编译了这个应用程序 - 得到了一些遗忘警告.
在C++中有两种表示二维数组的方法.一个比另一个更灵活.
数组数组
首先创建一个指针数组,然后用另一个数组初始化每个指针.
// First dimension
int** array = new int*[3];
for( int i = 0; i < 3; ++i )
{
// Second dimension
array[i] = new int[4];
}
// You can then access your array data with
for( int i = 0; i < 3; ++i )
{
for( int j = 0; j < 4; ++j )
{
std::cout << array[i][j];
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法的问题是你的第二个维度被分配了多个数组,因此不会减轻内存分配器的工作.你的记忆可能会碎片化导致性能下降.它提供了更大的灵活性,因为第二维中的每个数组可以具有不同的大小.
保持所有值的大数组
这里的技巧是创建一个大型数组来保存您需要的每个数据.如果您希望能够使用array [i] [j]语法访问数据,那么您仍然需要第一个指针数组.
int* buffer = new int[3*4];
int** array = new int*[3];
for( int i = 0; i < 3; ++i )
{
array[i] = array + i * 4;
}
Run Code Online (Sandbox Code Playgroud)
int*数组不是必需的,因为您可以通过从值的二维坐标计算缓冲区中的索引来直接在缓冲区中访问数据.
// You can then access your array data with
for( int i = 0; i < 3; ++i )
{
for( int j = 0; j < 4; ++j )
{
const int index = i * 4 + j;
std::cout << buffer[index];
}
}
Run Code Online (Sandbox Code Playgroud)
要记住的规则
计算机内存是线性的,并且仍然会持续很长时间.请记住,计算机本身不支持二维数组,因此唯一的方法是将数组"线性化"为一维数组.
这是在 C 中执行此操作的简单方法:
void manipulate(int rows, int cols, int (*data)[cols]) {
for(int i=0; i < rows; i++) {
for(int j=0; j < cols; j++) {
printf("%d ", data[i][j]);
}
printf("\n");
}
}
int main() {
int rows = ...;
int cols = ...;
int (*data)[cols] = malloc(rows*sizeof(*data));
manipulate(rows, cols, data);
free(data);
}
Run Code Online (Sandbox Code Playgroud)
这从 C99 开始就完全有效,但它不是任何标准的 C++:C++ 要求数组类型的大小是编译时常量。在这方面,C++ 现在落后 C 十五年。而且这种情况不会很快改变(C++17 的可变长度数组提案与 C99 可变长度数组的功能并不接近)。