C/C++ 中是不是存在锯齿状数组?

Posted

技术标签:

【中文标题】C/C++ 中是不是存在锯齿状数组?【英文标题】:Do jagged arrays exist in C/C++?C/C++ 中是否存在锯齿状数组? 【发布时间】:2010-11-08 04:37:44 【问题描述】:

C 或 C++ 中是否存在锯齿状数组?

当我编译这个时:

int jagged[][] =  0,1, 1,2,3 ;

我收到此错误:

错误:将“锯齿状”声明为多维数组必须对除第一个维度之外的所有维度都有边界

【问题讨论】:

【参考方案1】:

如果你只是想初始化它,你可以说:

int jagged[][3] =  0,1, 1,2,3 ;

但数组仍将具有 [2][3] 的形状。如果您想要一个真正的锯齿状数组,则必须动态创建它。如果你这样做,并且使用 C++,你应该使用 std::vector,正如 friol 建议的那样。

【讨论】:

【参考方案2】:

C++ 中(未编译,可能有更紧凑的语法):

std::vector<std::vector<int> > myArray;

myArray.push_back(std::vector<int>());
myArray.push_back(std::vector<int>());

myArray[0].push_back(0);
myArray[0].push_back(1);

myArray[1].push_back(1);
myArray[1].push_back(2);
myArray[1].push_back(3);

所以现在您可以使用例如 myArray[0][0] 等来访问元素。

【讨论】:

【参考方案3】:

在 C 中我会使用一个指针数组。

例如:

int *jagged[5];

jagged[0] = malloc(sizeof(int) * 10);
jagged[1] = malloc(sizeof(int) * 3);

等等等等

【讨论】:

在这个例子中,释放内存的正确方法是什么? 免费(锯齿状[0]);免费(锯齿状[1]);【参考方案4】:

有很多方法可以做到这一点。这是另一种方式:

int jagged_row0[] = 0,1;
int jagged_row1[] = 1,2,3;
int *jagged[] =  jagged_row0, jagged_row1 ;

【讨论】:

+1。这就是 C99 的复合文字大显身手的地方:int *jagged[] = (int[])0,1, (int[])1, 2, 3 ; 是不是也很好? 这个解决方案的问题是子数组会立即衰减为指针,所以你无法知道边界是什么。 @Neil,我完全没有想到这一点。你当然是对的。好点:) @Neil:这就是监护人值可以派上用场来标记数组末尾的地方 @Christoph Guardian 值对于数字数组可能存在问题,因为可能没有允许的“特殊”值。我认为以某种方式显式存储数组维度是更好的做法。【参考方案5】:

在 C99 中,您可以执行以下操作:

int jagged_row0[] = 0,1;
int jagged_row1[] = 1,2,3;

int (*jagged[])[] =  &jagged_row0, &jagged_row1 ; // note the ampersand

// also since compound literals are lvalues ...
int (*jagged2[])[] =  &(int[])0,1, &(int[])1,2,3 ;  

这里的唯一区别(与 rampion 的答案相比)是数组不会衰减为指针,并且必须通过另一个间接级别访问单个数组 - (例如 *jagged[0] - 以及每行的大小必须记录 - 即 sizeof(*jagged[0]) 不会编译) - 但它们看起来像是锯齿状的;)

【讨论】:

我认为你不能制作不完整类型的数组......哦,你正在制作一个指向不完整类型的指针数组,这是可能的,但不会为你买任何东西超过 rampion 的答案。 【参考方案6】:

您收到错误的原因是您必须至少指定外部尺寸的边界;即

int jagged[][3] = 0,1,1,2,3;

你不能让 jagged[0] 是一个 2 元素的 int 数组,而 jagged[1] 是一个 3 元素的 int 数组; N 元素数组与 M 元素数组(其中 N != M)的类型不同,并且数组的所有元素必须是相同类型。

可以做的是上面其他人建议的,并创建锯齿状作为指向 int 的指针数组;这样每个元素都可以指向不同大小的整数数组:

int row0[] = 0,1;
int row1[] = 1,2,3;
int *jagged[] = row0, row1;

尽管 row0 和 row1 是不同的类型(2 元素与 3 元素的 int 数组),但在初始化程序的上下文中,它们都被隐式转换为相同的类型 (int *)。

【讨论】:

【参考方案7】:

使用 C++11 初始化列表 this 可以更紧凑地编写:

#include <vector>
#include <iostream>

int main() 
    // declare and initialize array
    std::vector<std::vector<int>> arr = 1,2,3, 4,5;
    // print content of array
    for (auto row : arr) 
        for (auto col : row)
            std::cout << col << " ";
        std::cout << "\n";
    

输出是:

$ g++ test.cc -std=c++11 && ./a.out
1 2 3 
4 5 

供参考:

http://en.cppreference.com/w/cpp/utility/initializer_list

【讨论】:

【参考方案8】:

您还可以使用 c 中的复合文字来初始化一个真正的锯齿状数组,该数组在内存中是连续的,如下所示:

int (*arr[]) =  (int []) 0, 1, (int []) 2, 3, 4, (int [])5, 6, 7, 8 

这将在内存中连续排列。

【讨论】:

只是出于好奇:您知道需要哪种 C 标准才能工作吗? @Cherusker,C99 确实支持这一点。更多详情请见here。【参考方案9】:
//
//jaggedArrays.cpp
//
//program to implement jagged arrays in c++
//
#include<iostream>
#include<iomanip>
using namespace std;

int main()

    int rows, i, j;
    cout << endl << "Enter no of rows : ";
    cin >> rows;

    int columnsSizeOfEachRow[rows];

    cout << endl;
    for( i = 0 ; i < rows ; i++ )
    
        cout << "Enter column size for row no " << i + 1 << " : ";
        cin >> columnsSizeOfEachRow[i];
    

    int *jaggedArray[rows];
    for (i = 0 ; i < rows ; i++)
        jaggedArray[i] = new int[columnsSizeOfEachRow[i]];

    cout << endl;
    for(i = 0 ; i < rows ; i++)
    
        for ( j = 0 ; j < columnsSizeOfEachRow[i] ;j++)
        
            cout << "Array[" << i + 1 << "][" << j + 1 << "] << ";
            cin >> jaggedArray[i][j];
        
        cout << endl;
    

    cout << endl << endl << "Jagged array is as follows : " << endl;
    for( i = 0 ; i < rows ; i++)
    
        for ( j = 0 ; j < columnsSizeOfEachRow[i] ;j++)
            cout << setw(3) <<jaggedArray[i][j] << " ";
        cout << endl;
        

    return 0;

【讨论】:

嘿...您可以查看我的代码以在 c++ 中实现锯齿状数组【参考方案10】:

通过在 cpp 中使用动态分配,我们可以创建锯齿状数组。

例如:

#include<iostream>
using namespace std;
    
int main()
    int n;
    cout<<"Enter n:";
    cin>>n;
    
    cout<<"Enter elements:"; 
    int **p = new int *[n];
    
    for(int i=0;i<n;i++)
        p[i] = new int[i+1];
        for(int j=0;j<(i+1);j++)
            cin>>p[i][j];
        
     
    
    cout<<"Jagged Array:"<<endl; 
    for(int i=0;i<n;i++)
        for(int j=0;j<(i+1);j++)
            cout<<p[i][j]<<" ";           
        
        cout<<endl;
    
    
    for(int i=0;i<n;i++)
        delete []p[i];
    
    delete []p;

    

对于n=3,我们创建了一个锯齿状数组,如下所示:

输入 n:3

输入元素: 1 1 2 1 2 3 锯齿状阵列: 1 1 2 1 2 3

【讨论】:

【参考方案11】:

c++/c 中确实存在锯齿状数组,但语法相当复杂,需要处理很多事情。

c++中有两种类型的锯齿状数组。1) STATIC JAGGED ARRAY(一个二维数组,其中大小为常数,每行有不同的列数) . 2) DYNAMIC JAGGED ARRAY(一个二维数组,其大小可以是从用户那里获取的任意数字,并且每行的列数不同)

1)实现静态锯齿阵列的步骤

使用数组和指针 1) 用您需要的行数声明一维数组 2) 每个数组(行中元素的数组)的大小将是行中的列数(或元素) 3) 声明一个包含箭头地址的一维指针数组 4) 一维数组的大小就是你想要的锯齿数组中的行数
#include<iostream>
#include<string>
using namespace std;
int main()

    int row0[4] =  1,2,3,4 ;
    int row1[2] =  5,6 ;
    int* jagged[2] =  row0,row1 ;
    int Size[2] =  4,2 , k = 0;
    for (int i = 0; i < 2; i++)
    
        int* ptr = jagged[i];
        for (int j = 0; j < Size[k]; j++)
        
            cout << *ptr << "";
            ptr++;
        
        cout << endl;
        k++;
        jagged[i]++;
    
    return 0;

输出如下


123456


1)实现动态锯齿阵列的步骤

使用指针数组 1) 声明一个指针数组(锯齿状数组) 2) 该数组的大小将是锯齿状数组中所需的行数 3) 为数组中的每个指针分配内存,以满足您在该行中所需的元素数量。
#include<iostream>
#include<string>
using namespace std;
int main()

    //2 rows
    int* jagged[2];

    //Allocate memeory for the elements in the row 0
    jagged[0] = new int[1];

    //Allocate memory for the elements in row 1
    jagged[1] = new int[5];

    //Array to hold the size of each row
    int Size[2] =  1,5 ,k = 0, number = 100;

    //User enters the numbers
    for (int i = 0; i < 2; i++)
    
        int* p = jagged[i];

        for (int j = 0; j < Size[k]; j++)
        
            *p = number++;

            //move the pointer
            p++;
        
        k++;
    
    k = 0;

    //Display elements in Jagged array
    for (int i = 0; i < 2; i++)
    
        int* q = jagged[i];
        for (int j = 0; j < Size[k]; j++)
        
            cout << *q << "";
            //move the pointer to the next element
            q++;
        
        cout << endl;
        k++;
        //move the pointer to the next row
        jagged[i]++;
    
    delete[] jagged[0];
    delete[] jagged[1];
    return 0;

输出如下

100 101102103104105


【讨论】:

我很确定这应该使用delete[] jagged[0];delete[] jagged[1];,而不是delete[] jagged; @Ruzihm 但是你知道当我们删除一个指针时,所有的索引都会被自动删除,所以我们想删除它们而不是只删除一个我们想要释放内存的索引。希望你理解。谢谢。 用 valgrind 在这个答案中运行代码说 肯定会丢失:2 个块中的 24 个字节,两者都在 operator new[](unsigned long)。但是,删除jagged[i]++; 并用delete[] jagged[0]; delete[] jagged[1]; 替换delete[] jagged; 报告不可能有泄漏 即使在 g++ 中编译此代码也会发出警告:foo.cpp:49:14: warning: deleting array ‘jagged’ 49 | delete[] jagged; @Ruzihm 谢谢先生。根据您的建议编辑。

以上是关于C/C++ 中是不是存在锯齿状数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何为锯齿状数组 java 覆盖 next()?

初始化锯齿状数组

如何按列对二维数组(锯齿状)进行排序[重复]

数组写为 name[x, y] 而不是 name[x][y] [重复]

C# 中锯齿状数组的内存分配与 C++ 中的二维数组内存分配

从锯齿状数组中提取子数组并用作一维数组