c++ 有没有可能写出一个能取n维数组的函数?

fbcarpbf  于 2023-02-01  发布在  其他
关注(0)|答案(6)|浏览(109)

我试图写一个函数,它可以接受任何维数的数组,并成功地打印数组中的值。但是我不能继续写下去,因为在声明函数时,我们必须声明除了最左边的维数之外的所有维数。有没有可能我们可以写一个广义函数,它可以接受数组作为任何维数的输入?
例如函数应该能够取2维数组或3维数组或n维数组,其中n是任意数。

c9qzyr3d

c9qzyr3d1#

对每个维度和模板使用 * recursion *(在C++中也是如此),以下内容可能会有所帮助:

template <typename T>
void print(const T&e)
{
    std::cout << e << " ";
}

template <typename T, std::size_t N>
void print(const T (&a)[N])
{
    std::cout << "{";
    for (const auto& e : a) {
        print(e);
    }
    std::cout << "}" << std::endl;
}

示例用法:

int a[2][3][4];
print(a);

Live example

zazmityj

zazmityj2#

如果你把数组编码为一维的,然后自己计算单个索引,你当然可以让程序表现得好像数组是为一个可变维数的数组所做的一样。
我最初的想法是从一个包含要使用的每个维度的范围的向量开始。
向量中元素的数量就是你的维数。

j2cgzkjk

j2cgzkjk3#

数组作为指向数组元素类型的指针传递给函数,而不管数组的维数如何。你可以有更多的参数来指定维数n,以及一个长度为n的数组(另一个)来指定每一维中的元素数。注意,[]符号只是一种执行指针加法的简洁方法。

68de4m5k

68de4m5k4#

如果你想访问特定的元素或者对数组进行操作,但是又想动态地创建矩阵,你可以使用指针来访问每个元素,方法是在print函数中传递维度。
因为如果多维数组定义为int [][],则x = y[a][b]等效于x = *((int *)y + a * NUMBER_OF_COLUMNS + b);
查看此帖子了解更多详情:How to use pointer expressions to access elements of a two-dimensional array in C?
所以,如果你想打印整个矩阵或访问任何特定的元素,你可以这样做:

#include <iostream>
using namespace std;

//the function print_2D_matrix receives 4 arguments: pointer to first element
//                                                   dimension of array arr, i.e. n x m
//                                                   index of the element to be printed, i.e. a and b
void print_2D_matrix(int *arr, int n, int m, int a, int b){
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++)
            printf("%d ", *(arr + (i * m) + j));
        printf("\n");
    }
    //go to the address just before a row, i.e. (a - 1) * NO_OF_COLUMNS 
    //then go to the address on b column, i.e. (a - 1) * NO_OF_COLUMNS + b
    //since we started from the base address, i.e. first element( arr[0][0] ), subtract 1 
    printf("arr[3][3] = %d\n", *(arr + ((a - 1) * m) + b - 1));    //print arr[a][b]
} 

int main() {
    int n, m;
    cin>>n>>m;
    int arr[n][m];

    for(int i = 0; i < n; i++)    //initialize the matrix
        for(int j = 0; j < m; j++)
            arr[i][j] = i * j;

    print_2D_matrix((int *) arr, n, m, 3, 3);

    return 0;
}

上述程序的输出(n x m = 4 x 5)为:

0 0 0 0 0
0 1 2 3 4
0 2 4 6 8
0 3 6 9 12
arr[3][3] = 4
jucafojl

jucafojl5#

我确信这至少违反了C标准的一条规则,但在实践中应该是可行的。注意,它使用0作为任意级别数组的终止元素的标记值。

void print(void* p, int dim)
{
    if (dim == 1)
    {
        int* a = (int*) p;
        while (*a)
        {
            printf("%d ", *a++);
        }
        printf("\n");
    }
    else
    {
        void** a = (void**)p;
        while (*a)
        {
            print(*a++, dim - 1);
        }
    }
}

void test()
{
    int x0 [] = { 11, 12, 13, 14, 15, 0 };
    int x1 [] = { 21, 22, 23, 0 };
    int x2 [] = { 0 };
    int x3 [] = { 41, 42, 0 };
    int x4 [] = { 51, 52, 53, 0 };
    int* y0 [] = { x0, x3, 0 };
    int* y1 [] = { 0 };
    int* y2 [] = { x1, x2, x4, 0 };
    int** z [] = { y0, y1, y2, 0 };

    print(z, 3);
}

图纸:

11 12 13 14 15
41 42
21 22 23

51 52 53
ztyzrc3y

ztyzrc3y6#

我做了一个函数,可以打印任何n维可迭代容器:

template<typename Object, typename Iterable>
void Print(
    const Iterable& iterable,
    const string& separatorDimensions = "\n",
    const function<void(const Object&)>& funcPrintElem = [] (const Object& obj) {
        static_assert(
            is_arithmetic_v<Object> || is_same_v<remove_const_t<remove_pointer_t<Object>>, char>,
            R"(The object from the innermost range is not a built-in/c-string type, please provide a valid print element function.)"
            );
        cout << obj << ' ';
    }
) {
    if constexpr (ranges::range<Iterable>) {
        ranges::for_each(iterable, [&] (const auto& it) { Print(it, separatorDimensions, funcPrintElem); });
        cout << separatorDimensions;
    } else {
        funcPrintElem(iterable);
    }
}

这个函数有一个默认的std::function,可以打印任何内置类型,如intunsigned charlong long等,还有c字符串,如charconst char*,如果你有另一个对象,如pairtuple或你的类的对象,你可以传递一个函数来打印你的对象。
您可以像这样使用函数:(你必须明确地告诉函数你最里面的对象,如下所示)

int main() {
    cout << "v: " << endl;
    vector<uint16_t> v { 1, 2, 3 };
    Print<uint16_t>(v);

    cout << endl << "ll: " << endl;
    list<list<const char*>> ll { { "a", "b" }, { "c", "d" } };
    Print<const char*>(ll);

    struct smth {
        int a;
        char b;
    };

    cout << endl << "smths: " << endl;
    vector<smth> smths { { 14, '0' }, { 18, '1' } };
    Print<smth>(smths, "\n", [] (const smth& obj) { cout << "a = " << obj.a << ", b = " << obj.b << endl; });

    return 0;
}

功能可以找到here,也许我会更新在未来支持更多的东西。
你需要至少有c++20这个函数的工作。

相关问题