how to print an n-dimensional array in c++ - c++

I would like to write a function that can print different arrays. For instance:
#include<iostream>
using namespace std;
int main(){
int a[10];
int b[3][2];
for(int i = 0; i < 10; i++){
a[i] = i;
}
for(int i = 0; i < 3; i++){
for(int j = 0; j < 2; j++){
b[i][j] = i * 2 + j;
}
}
print_arr(a, /*some input*/);
// output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
print_arr(b, /*some input*/);
// output:
// 0, 1
// 2, 3
// 4, 5
return 0;
}
can somebody help me or say that this is impossible.
maybe this question is already answered. In that case please can you share the link of that question

You could create a function template that unwraps the array recursively.
Example:
#include <iostream>
#include <type_traits>
// only enable the function for arrays
template<class T, std::enable_if_t<std::is_array_v<T>, int> = 0>
void print_arr(const T& x) {
for(auto& in : x) {
if constexpr (std::rank_v<T> > 1) // more dimensions to go
print_arr(in); // call to unwrap next dimension
else
std::cout << in << ' '; // last dimension, print the value
}
std::cout << '\n';
}
Demo
Since the name print_arr suggests that you will not need SFINAE you could also replace the enable_if_t part of the template with a static_assert inside the function:
template<class T>
void print_arr(const T& x) {
static_assert(std::is_array_v<T>);
// ...
Instead of streaming directly to std::cout, you could add a std::ostream& parameter to make it stream to any stream
template<class T>
void print_arr(std::ostream& os, const T& x) {
static_assert(std::is_array_v<T>);
for(auto& in : x) {
if constexpr (std::rank_v<T> > 1)
print_arr(os, in);
else
os << in << ' ';
}
os << '\n';
}
// ...
print_arr(std::cout, a);
print_arr(std::cout, b);
Or you could make it return a std::string of the complete output which lets you do what you want with it afterwards.
Example:
#include <sstream>
template<class T>
std::string print_arr(const T& x) {
static_assert(std::is_array_v<T>);
std::ostringstream os;
for(auto& in : x) {
if constexpr (std::rank_v<T> > 1)
os << print_arr(in);
else
os << in << ' ';
}
os << '\n';
return os.str();
}
// ...
std::cout << print_arr(a);
std::cout << print_arr(b);

Ted Lyngmo's answer is definitely the most concise, and probably the closest to achieving what you asked for, but there's still a few things worth pointing out including an alternate solution that might make sense in some circumstances.
First of all, it's important for anyone reading this to understand that C and C++ types don't include any kind of runtime type information by default. Yes it's true, RTTI exists for record types, but a built-in C array like int arr[2][3] is not much more than a bit of sugar to say "give me a region of memory large enough to store 6 ints". This is in contrast for example to a language like python, where a list object will include metadata about the size and contents. It's this metadata that allows you to write very flexible functions than can query the object itself about its structure, and of course it comes at a cost.
When we introduce a templated solution like the one above, we haven't added runtime type information, we've asked the compiler to generate code for every possible permutation of array type that we might need. This is fine if you only have a couple of them, but if the function gets used a lot, with many different array types, things grow really fast. This could actually become a problem in some environments. Consider for example the following main function:
int main(int argc, char **argv)
{
int arr1[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
print_arr(arr1);
int arr2[3] = {13, 14, 15};
print_arr(arr2);
int arr3[3][2][2] = {{{10, 20}, {30, 40}}, {{50, 60}, {70, 80}}, {{90, 100}, {110, 120}}};
print_arr(arr3);
return 0;
}
And now look at the AST that gets generated:
jon#prompt$ clang++ -fsyntax-only -Xclang -ast-dump test.cpp -std=c++17 | grep FunctionDecl | grep print_arr
| |-FunctionDecl 0x10921fd88 <line:6:1, line:15:1> line:6:6 print_arr 'void (const T &)'
| |-FunctionDecl 0x109224c18 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[3][4])'
| |-FunctionDecl 0x109225ab8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[3])'
| |-FunctionDecl 0x1092270a8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[3][2][2])'
| |-FunctionDecl 0x10933db08 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[4])'
| |-FunctionDecl 0x1093539a8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[2][2])'
| `-FunctionDecl 0x1093552d8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[2])'
Here you see the compiler has emitted a different version of the print_arr function for every permutation of array size we've used. This isn't exactly what you could reasonably call "one function", it's actually many functions that have each been automatically generated by the compiler. It's a tiny amount of text to write in a cpp file, but the actual amount of code that gets generated is significant.
An alternate way to solve this problem is to just include type information in the print_arr function. Here's an example of an implementation that is WYSIWYG, and will let you do the same thing though you need to provide the type metadata manually:
const int *print_arr(const int *arr, const int rank, const int *lengths)
{
const char *p_sep = "";
printf("{");
if (rank > 1) {
for (int i = 0; i < lengths[0]; i++) {
printf("%s", p_sep);
arr = print_arr(arr, rank - 1, &lengths[1]);
p_sep = ", ";
}
} else {
for (int i = 0; i < lengths[0]; i++) {
printf("%s%d", p_sep, *arr++);
p_sep = ", ";
}
}
printf("}");
return arr;
}
And here's how you would use it with the same example arrays:
int main(int argc, char **argv)
{
int arr1[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
print_arr(&arr1[0][0], 2, (int[2]){3, 4});
printf("\n");
int arr2[3] = {13, 14, 15};
print_arr(&arr2[0], 1, (int[1]){3});
printf("\n");
int arr3[3][2][2] = {{{10, 20}, {30, 40}}, {{50, 60}, {70, 80}}, {{90, 100}, {110, 120}}};
print_arr(&arr3[0][0][0], 3, (int[3]){3, 2, 2});
printf("\n");
return 0;
}
Output:
jon#promptC$ ./test
{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}
{13, 14, 15}
{{{10, 20}, {30, 40}}, {{50, 60}, {70, 80}}, {{90, 100}, {110, 120}}}
This approach has a few advantages, the most important being that the compiler emits pretty much exactly what's written. It also forces you to be very explicit in the code, which is probably good in this case.
As always with C and C++ you need to know what's most appropriate for the situation you find yourself in.

Related

How to return a struct which contains an array pointer from a function?

I have this struct and declaration in .h file,
struct strct
{
int *arry;
};
strct func01();
and this function in .cpp file,
strct func01()
{
int temp_arry[] = {5, 6, 7, 8, 9};
strct rtrn;
rtrn.arry = temp_arry;
return rtrn;
}
and i call the function like,
strct test = func01();
printf("%d", test.arry);
It prints some random numbers. I want to print the full array.
Before we start, let's recall the behavior of the sizeof operator:
Case of : int *
int *arry;
int iSize = sizeof (arry); <-- Return size of pointer and NOT number of elements
Case of : int []
int temp_arry[] = {5, 6, 7, 8, 9};
int iSize = sizeof (temp_arry); <-- Return total memory size allocated for 5 elements
You understand now that the composition of your structure does not allow you to determine the number of elements of your int *arry struct member. Therefore, you don't know how many element you should display.
If you wish to keep your program without using the STL: vector, array, ... you must complete your structure as follows:
struct strct
{
int size; // Contains the number of elements to use
int *arry;
};
strct func01();
strct func01()
{
strct rtrn;
int tab_size = 5;
// it is a temp variable. Destroyed when function ends.You can not use it !
int temp_arry[] = {5, 6, 7, 8, 9};
// This table is allocated with new and can be used
int *permanent_arry = new int [tab_size];
for (int i=0; i<tab_size; i++)
permanent_arry[i] = i;
rtrn.arry = permanent_arry;
rtrn.size = tab_size;
return rtrn;
}
int main ()
{
strct test = func01();
for (int i=0; i<test.size; i++)
printf("%d ", test.arry[i]);
// dont forget to delete memory
delete [] test.arry;
}
First, this code is wrong because:
the lifetime of temp_arry[] is end after func01 returns.
you are printing a pointer, not an array.
Second, if you want to print the full array, you'd better redesign your code, for example, you may use vector to clean up your code. (this code needs C++ 11)
struct strct
{
std::vector<int> arry;
};
strct func01();
strct func01()
{
std::vector<int> temp_arry = {5, 6, 7, 8, 9};
strct rtrn;
rtrn.arry = temp_arry;
return rtrn;
}
strct test = func01();
for(auto i : test)
std::cout << i << " ";
Note: most of the time there's no point to use built-in arrays as return value, even though it will decay to a pointer prvalue.

Initializing an array of pointers to structs in C++

Initializing an array of pointers to structs in C can be done using compound literals.
typedef struct {
int a;
int b;
} s;
In C:
s *ptrArray[] = {
&(s){
.a = 1,
.b = 2
},
&(s){
.a = 4,
.b = 5
}
};
How can this be done in C++?
I have also seen the difference in initializing structs in C++ not using compound statements:
s s1 = { a: 7, b: 8 };
First - initializing anything to the address of a temporary value seems extremely fishy, in C as well. Are you sure that's valid? Hmmm. Anyway, a C++ compiler will really not let you do that.
As for the your designated (named-field) initialization C++ line - it's actually non-standard, it's a GNU C++ extension, and you can't rely on it.
You could do this:
struct s { int a, b; };
int main() {
s data[] = { { 1, 2 }, { 4, 5 } };
// instead of ptrArray[i], use &(data[i])
}
This compiles just fine. But - a more C++'ish version of this code would be:
#include <array>
struct s { int a, b; };
int main() {
std::array<s, 2> data { s{ 1, 2 }, s{ 4, 5 } };
// instead of ptrArray[i], use &(data[i]),
// or use iterators, or ranged for loops
}
Why would you want to use std::array? Here's one explanation of the benefits. Actually, you could do slightly better and repeat yourself less with:
int main() {
auto data = make_array(s{ 1, 2 }, s{ 4, 5 });
// instead of ptrArray[i], use &(data[i]),
// or use iterators, or ranged for loops
}
The make_array function is taken from here; you also have std::experimental::make_array(), but that's not standardized yet.
If you want to add or remove elements from data at run-time, you might switch to using std::vector:
#include <vector>
struct s { int a, b; };
int main() {
std::vector<s> data { s{ 1, 2 }, s{ 4, 5 } };
// instead of ptrArray[i], use &(data[i]),
// or use iterators, or ranged for loops
}
The reason your initialize was failing is you were attempting to initialize the array of pointers to struct to the address of numeric literal constants. The same as:
#define A 5
int b = &A; /* NOT HAPPENING */
(you can't take the address of 5)
You can solve your problem by simply initializing an array of s instead of an array of pointers to s, e.g.:
s ptrarr[] = { {1, 2}, {4, 5} };
With that change, your array will initialize fine, e.g.
#include <iostream>
typedef struct {
int a;
int b;
} s;
int main (void) {
s ptrarr[] = { {1, 2}, {4, 5} };
int cnt = 0;
for (auto& i : ptrarr)
std::cout << "ptrarr[" << cnt++ << "] : " << i.a << ", " << i.b << "\n";
}
Example Use/Output
$ ./bin/ptrarrystruct
ptrarr[0] : 1, 2
ptrarr[1] : 4, 5

C++ eigen pointer to a Eigen::Map<Eigen::VectorXd> object

Is it possible to define a pointer to a Eigen::Map object? The original code is quite complex but here is what I am trying to achieve (pseudo code)
void testfunction1(... XPtr){
// XPtr is a pointer
// create a vector, map it to a Map object and make XPtr point to the latter
VectorXd Xnew(9);
Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90;
Map<VectorXd> XnewMap(Xnew.data(), 9);
// make XPtr point to XnewMap so that Xnew data can be
// accessed outside testfunction1()
// ... how? I suspect this to involve some dynamic memory allocation
};
void testfunction2(bool yes){
// main function
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
const Map<VectorXd> X(XR.data(), 9); // yes the mapped version is needed
// create a pointer to X, say XPtr
// ... how?
if(yes){ // make XPtr point to XnewMap which is defined in testfunction1()
testfunction1(XPtr);
};
//... some computations
// make XPtr point again to X
// ... how?
};
First of all no need to use pointers here because Map is already essentially a pointer, so it would be simpler so update the Map object with placement new. Nonetheless, your current design would require allocation within testfunction1 and deallocation within testfunction2 in case it has been allocated, which is not really safe. So better adopt a functional design by putting "some computations" within a function (or a named lambda), make testfunction1 return by value:
VectorXd testFunction1() { return Xnew; }
void testfunction2(bool yes){
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
const Map<VectorXd> X(XR.data(), 9);
auto func = [&] (Eigen::Ref<VectorXd> X) {
/* some computation */
}
if(yes) func(testfunction1());
else func(X);
};
If you really want to keep your current logic, then here is a self-contained example using placement new:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
void testfunction1(Map<VectorXd> &XMap){
double * Xnew = new double[9];
::new (&XMap) Map<VectorXd>(Xnew,9);
XMap << 10, 20, 30, 40, 50, 60, 70, 80, 90;
};
int main()
{
bool yes = true;
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
Map<VectorXd> X(XR.data(), 9);
if(yes) testfunction1(X);
// use X ...
cout << X.transpose() << endl;
// restore X and free memory allocated in testfunction1
if(yes){
delete[] X.data();
::new (&X) Map<VectorXd>(XR.data(),9);
}
cout << X.transpose() << endl;
}
which is pretty bad because it can leak if an exception is raised when using X. You could workaround manual memory management by asking testFunction1 to return a VectorXd (or anything that handle memory allocation/deallocation on its own) and do the placement new in the main function:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
VectorXd testfunction1(){
VectorXd Xnew(9);
Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90;
return Xnew;
};
int main()
{
bool yes = true;
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
Map<VectorXd> X(XR.data(), 9);
{
VectorXd X2;
if(yes) {
X2 = testfunction1(); // shallow copy thanks to move semantic
::new (&X) Map<VectorXd>(X2.data(),9);
}
// use X ...
cout << X.transpose() << endl;
// restore X
::new (&X) Map<VectorXd>(XR.data(),9);
}
cout << X.transpose() << endl;
}
Finally, if the content of X should be read-only, then use Map<const VectorXd> and not const Map<VectorXd> as in your initial question.

Cannot convert vector<int> to int* for bool testPIN

For a class assignment I had to rewrite this code using vectors instead of arrays. I figured I would use the existing arrays and assign them as a vector. But I get:
error: cannot convert 'std::vector' to 'int*' for argument '1' to
'bool testPIN(int*, int*, int)'
How can I get around this error?
#include <iostream>
#include<vector>
using namespace std;
// Function Prototype
bool testPIN(int [], int [], int);
int main ()
{
const int NUM_DIGITS = 7; // Number of digits in a PIN
int cpin1[NUM_DIGITS] = {2, 4, 1, 8, 7, 9, 0}; // Base set of values.
int cpin2[NUM_DIGITS] = {2, 4, 6, 8, 7, 9, 0};
int cpin3[NUM_DIGITS] = {1, 2, 3, 4, 5, 6, 7};
vector<int> pin1(cpin1, cpin1+7) ;
vector<int> pin2(cpin2, cpin2+7) ;
vector<int> pin3(cpin3, cpin3+7) ;
if (testPIN(pin1, pin2, NUM_DIGITS))
cout << "ERROR: pin1 and pin2 report to be the same.\n";
else
cout << "SUCCESS: pin1 and pin2 are different.\n";
if (testPIN(pin1, pin3, NUM_DIGITS))
cout << "ERROR: pin1 and pin3 report to be the same.\n";
else
cout << "SUCCESS: pin1 and pin3 are different.\n";
if (testPIN(pin1, pin1, NUM_DIGITS))
cout << "SUCCESS: pin1 and pin1 report to be the same.\n";
else
cout << "ERROR: pin1 and pin1 report to be different.\n";
return 0;
}
bool testPIN(int custPIN[], int databasePIN[], int size)
{................}
In these situations, it helps to read a good reference. You would need to get the vector's underlying data array:
testPIN(pin1.data(), pin2.data(), NUM_DIGITS))
If your implementation does not support C++11, you can do the following:
testPIN(&pin1[0], &pin2[0], NUM_DIGITS))
But if you have been asked to re-implement some code to use vectors, you may want to re-implement the testPIN function instead:
bool testPIN(const std::vector<int>& custPIN1,
const std::vector<int>& custPIN2);
and then just pass the vectors:
testPIN(pin1, pin2);
testPIN(&pin1[0], &pin2[0], NUM_DIGITS)
because the vector's internal memory structure is same with array.
Please check this.
How to convert vector to array in C++

Returning a pointer to an array C++

I have a function that needs to return a pointer to an array:
int * count()
{
static int myInt[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
return &myInt[10];
}
inside my main function I want to display one of the ints from that array, like here at index 3
int main(int argc, const char * argv[])
{
int myInt2[10] = *count();
std::cout << myInt2[3] << "\n\n";
return 0;
}
this however gives me the error: "Array initializer must be an initializer list"
how do I create an array within my main function that uses the pointer to get the same elements as the array at the pointer?
A few problems in your code:
1) you need to return a pointer to the beginning of the array in count:
return &myInt[0];
or
return myInt; //should suffice.
Then when you initialize myInt2:
int* myInt2 = count();
You can also copy one array into the other:
int myInt2[10];
std::copy(count(), count()+10, myInt2);
Note copying will create a second array using separate memory than the first.
You don't need pointers, references are fine.
int (&count())[10]
{
static int myInt[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
return myInt;
}
int main(int argc, const char * argv[])
{
int (&myInt2)[10] = count();
std::cout << myInt2[3] << "\n\n";
return 0;
}