将c多维数组转换为多维c++向量

Posted

技术标签:

【中文标题】将c多维数组转换为多维c++向量【英文标题】:convert c multidimensional array to multidimensional c++ vector 【发布时间】:2021-05-11 10:12:52 【问题描述】:

我正在尝试将 c 多维数组转换为多维 c++ 向量,我的意思是,将类似 int arr[2][3] = 1,2,3, 4,5,6; 的内容转换为对应的向量。 数组不一定是二维的,也可以是这样的:

int arr[2][2][3] = 
   
      1,2,3,
      4,5,6,
   ,
   
      7,8,9,
      10,11,12,
   
;

最初我认为这样的事情会奏效,但事实并非如此,因为似乎std::vector 不允许从 C 数组进行转换。

std::vector<std::any> V(arr);

然后我想到函数递归之类的东西,这是我的尝试,(我不知道为什么!)抛出error: no matching function for call to 'length'

#include <iostream>
#include <type_traits>
#include <vector>
#include <any>

// Get the lenght of a classic C array.
template <class T, unsigned S>
inline unsigned length(const T (&v)[S]) 
  return S;
;

// Check wether the input is a classic C array or not.
template <class T>
bool is(const T& t) 
  return std::is_array_v<T>;
;

// Turn the classic C input array to vector.
template <class T>
std::vector<std::any> toVector(const T& t) 
  std::vector<std::any> V;
  for (int k = 0; k < length(t); k++) 
    if (is(t[k])) 
      V.push_back(toVector(t[k]));
     else 
      V.push_back(t[k]);
    
  
  return V;


int main() 

  int16 a[] = 1,2,3;

  auto b = toVector(a);


我在第二次尝试中做错了什么?或者,有没有更简单的方法来做到这一点? 另外,我认为将向量中的所有数字转换为唯一的给定数据类型会更好,这可能吗? 我使用 c++11 和 g++ 作为编译器 –

请注意,我不知道我的数组有多少维。

【问题讨论】:

可能是因为你拼错了length 而不是lenght @Pat.ANDRIA 一直拼错。如果这是问题所在,则错误将是“找不到标识符”类型,而不是“不匹配函数”(编译器识别名称但无法匹配类型)。 @Pat.ANDRIA 现在注意到了,但我在整个文件中拼错了,那么我应该不会有问题。无论如何我都会修复它。 【参考方案1】:

C 多维数组的等价物是一个平面 C++ 向量加上一个多维数组视图。

朴素的等价物是向量的向量(可能是向量),它实际上对应于 C“锯齿状”数组。内存布局和性能特征会有很大不同。

网络上有很多多维数组视图的实现。

template<class A>
struct raw_ptr  using type=A*; ;
template<class A, std::size_t N>
struct raw_ptr<A[N]>:raw_ptr<A>;

template<class A>
using raw_ptr_t = typename raw_ptr<A>::type;

template<class T>
struct array_view;

template<class T, std::size_t D0, std::size_t D1>
struct array_view<T[D0][D1]> 
  T(*data)[D1]=0;
  constexpr array_view( T(&arr)[D0][D1] ):data(arr) 
  explicit array_view( raw_ptr_t<T> buff ):data(reinterpret_cast<T(*)[D1]>(buff)) 
  constexpr array_view<T[D1]> operator[](std::size_t i)const
    return data[i];
  
;
template<class T, std::size_t D0>
struct array_view<T[D0]> 
  constexpr array_view( T(&arr)[D0] ):data(arr) 
  explicit constexpr array_view( T* buff ):data(buff) 

  T* data=0;
  constexpr T& operator[](std::size_t i)const
    return data[i];
  
;

要转换 int[4][5][6] 你会这样做:

int array[4][5][6]=/*whatever*/;
std::vector<int> buff(&array[0][0][0], &array[3][4][5]);
array_view<int[4][5][6]> viewbuff.data();

现在,view[a][b][c]array[a][b][c] 相同。

Live example.

template<class Array>
struct wrap_array_in_vector 
  using raw_ptr = raw_ptr_t<Array>;
  using value_type = std::remove_pointer_t<raw_ptr>;
  std::vector<value_type> data;
  array_view<Array> view;
  wrap_array_in_vector(wrap_array_in_vector const& other):
    data(other.data),
    view(data.data())
  
  wrap_array_in_vector(wrap_array_in_vector && other):
    data(std::move(other.data)),
    view(data.data())
  
    other.view.data = nullptr; // no longer valid
  
  decltype(auto) operator[](std::size_t i)const 
    return view[i];
  
  wrap_array_in_vector( Array const& arr ):
    data( reinterpret_cast<value_type const*>(&arr[0]), reinterpret_cast<value_type const*>(&arr[1]) ),
    view(data.data())
  
;
template<class Array>
wrap_array_in_vector(Array&)->wrap_array_in_vector<Array>;
template<class Array>
wrap_array_in_vector(Array const&)->wrap_array_in_vector<Array>;

这样你就可以了

wrap_array_in_vector wrapped = array;

并且wrapped 会推断出它需要的所有类型信息。

【讨论】:

您好,感谢您回答我的问题。我用 c++ 写了几个星期,你的代码真的很密集!你能更好地解释一下这是如何工作的吗? @Giuppox 好吧,它实际上并不有效。 :) 数组视图存储一个指向内存缓冲区的指针,并执行 C++ 默认情况下执行a[1][2][3] 时执行的数组索引数学运算。 wrap_array_in_vector 使用推导指南允许您获取原始 C 数组,它会将其推入带有数据的std::vector 和 为它构建一个array_view。然后它暴露[]wrap_array_in_vector 的行为很像值类型;但是我没有实现operator=。我怀疑=default 可能有用吗? 如前所述,互联网上有许多个数组视图支持多维。找一个。我只是为了完整性而在此处添加了一个,并不是因为我认为我的会比您在互联网上随机找到的更好。【参考方案2】:

这应该接近于转换为向量的最佳值。描述中误导的部分是大小不规则,因为它们是列表初始化的,在这种情况下使用 int,将为零。

#include <type_traits>
#include <vector>
#include <iostream>

template<typename T, std::size_t N>
auto to_vectors( T const (&c_array)[N] ) 
    using element_base_type = std::decay_t<T>;
    if constexpr( std::is_array_v<T> ) 
        using child_t = std::remove_cv_t<std::remove_reference_t<decltype( to_vectors( c_array[0] ) )>>;
        auto result = std::vector<child_t>( );
        result.reserve( N );
        for( auto const & element: c_array ) 
            result.push_back( to_vectors( element ) );
        
        return result;
     else 
        return std::vector<T>( c_array, c_array + N );
    
 


 int arr[2][2][3] = 
   
      1,2,3,
      4,5,6,
   ,
   
      7,8,9,
   
;

auto v0 = to_vectors( arr );


template<typename Vec>
void display( Vec const & vec ) 
    if constexpr( std::is_same_v<int, typename Vec::value_type> ) 
        std::cout << "elements: ";
        for( int e: vec ) 
            std::cout << e << ',';
        
        std::cout << "\n";
     else 
        std::cout << "element count: " << vec.size( ) << '\n';
        for( auto const & child: vec ) 
            display( child );
        
    



int main( ) 
    display( v0 );

这将输出

element count: 2
element count: 2
elements: 1,2,3,
elements: 4,5,6,
element count: 2
elements: 7,8,9,
elements: 0,0,0,

【讨论】:

嗨,感谢您的回答和时间。 to_vectors 在哪里声明?抱歉,我不明白你回答的意思。 问题是如何将 c 多维数组转换为多维 c++ 向量。这样做,to_vectors 的结果,它位于包含下的代码 sn-p 的顶部,在示例情况下是 vector>>。 哎呀,我的错对不起。这实际上是一个非常好的答案! 是否可以将输出中的所有数字转换为唯一的数据类型(例如doublelong int)?当数组中的数字具有不同的 dtype 时,我需要。

以上是关于将c多维数组转换为多维c++向量的主要内容,如果未能解决你的问题,请参考以下文章

将嵌套 C++ 向量作为内置样式的多维数组传递

多维数组索引 C++ 中的多维数组

多维数组指向多维数组

c ++:解析包含表达式“访问多维数组”的字符串

有啥可以代替多维数组?

Array.reduce 将多维数组转换为对象数组