我正在尝试编写一个函数,可以接受任何维度的数组并成功打印数组中的值。但是我无法向前移动,因为在声明函数时必须声明除左侧最外维以外的所有维度。是否有可能编写通用函数,可以接受任何维数的数组作为输入?
例如,该函数应能够接受二维数组、三维数组或n维数组,其中n是任意数字。
例如,该函数应能够接受二维数组、三维数组或n维数组,其中n是任意数字。
使用递归来处理每个维度和模板(在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);
(涉及it技术)print(a[i]);
就可以完成任务)。 - Jarod42for (std::size_t i = 0; i != N; ++i) { print(a[i]); }
- Jarod42int [][]
,那么x = y[a][b]
等同于x = *((int *)y + a * NUMBER_OF_COLUMNS + b);
有关更多详细信息,请查看此帖子:如何使用指针表达式访问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
如果您将数组编码为一维数组,然后自己计算单个索引,那么您肯定可以让程序像为可变数量维度的数组那样运行。
我最初的想法是从包含每个要使用的维度的范围的向量开始。
该向量中的元素数目就是您所拥有的维度数。
将数组作为指向数组元素类型的指针传递给函数,而不考虑数组的维度。您可以有进一步的参数来指定维数n和一个长度为n的数组(另一个数组)来指定每个维度中的元素数量。请注意,[]符号仅是执行指针加法的整洁方式。
我相信这违反了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
const
。 - Jarod42template<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,可以打印任何内置类型,如int、unsigned char、long long等,以及c字符串,如char*或const char*,如果您有另一个对象,如pair或tuple或您的类的对象,您可以传递一个打印您的对象的函数。
您可以像这样使用该函数:(您必须明确告诉函数您的最内部对象,如下所示)
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;
}
你可以在这里找到该函数,也许将来我会更新以支持更多功能。
你需要至少c++20才能运行该函数。