I have declared my double array this way
double feature_values[] = {0.0003323988609746907, 0.6412162477054423, 9.545269768297, -1323.6125512135593, -1512.0718516647562, -2073.6020535721273, -2578.302701605687, 0.27304053703708875, 0.5580326301604825, 0.34912544310755905, 0.550917816717867, 49.7455110651867, 1821.15723334093, -61.3700045037962, -49.400686298507, 13.11111111111111, 26.0, 12.222222222222221, 18.0, 0.3111111111111111, 0.325, 0.4148148148148148, 0.43333333333333335, 0.5930328763108722, 0.7343377194812131, 0.23685155593995189, 0.6754530381265557, 0.16582557525922734, 0.009828988419922594, 0.00017475124235758377, 0.0003779194334627987, 0.0008100853061379151, 2.9387129701088046, 0.41880424639672703, 2.639057329615259, 0.0, 2.75, 2.807354922057604, 0.07124096827009982, 0 , 0.003, 0.1435385870250432, 0.5547574989867142, 0.1445909953802227};
int index;
for(int i=0;i<44;i++)
{
data[i].missing=-1;
data[i].fvalue=feature_values[i];
printf("feature[%d]=%.8f\n",i,feature_values[I]);
predict_res(data,0,result);
}
I have 6 different feature_values arrays. And I want to print result for each of them. Currently I need to change the array value every time to get the result. So, how do I declare array of double array and use it in for loop.
C++ has std::array, which has a size() member. If the size should very at runtime, use std::vector. It too has a size() member.
Just use the std::array for constant sized arrays. This example uses integers, but the concept is the same.
#include <iostream>
#include <array>
typedef std::array<std::array<int, 3>, 2> arr_2d_t;
int main(int argc, char* argv[]) {
arr_2d_t arr_2d;
int num = 0;
for (size_t i = 0; i < 2; ++i) {
for (size_t e = 0; e < 3; ++e) {
arr_2d[i][e] = num++;
}
}
for (size_t i = 0; i < 2; ++i) {
for (size_t e = 0; e < 3; ++e) {
std::cout << arr_2d[i][e] << " ";
}
std::cout << std::endl;
}
}
So How do I declare array of double array and use it in for loop.
The syntax of declaring an array of arrays is this:
double feature_values[6][44];
Note that elements of array are of same type. Hence, you cannot have sub arrays of different lengths.
how do I use it in for loop.
In the same way as any other array. Example:
for(auto& sub_array : feature_values) {
for(auto& element : sub_array) {
use_value(element);
Related
I am learning C++ with experiencein mostly Python, R and SQL.
The way arrays (and vectors which differes somehow from 1d-arrays? and matrices which are 2d-arrays?) work in C++ seems quite different as I cannot specify the size of dimension of the array with an argument from the function.
A toy-example of my goal is some thing like this:
Have a function my_2d_array which takes two arguments M and N and returns a matrix or 2d-array of dimension (MxN) with elements indicating the position of that element. E.g. calling my_2d_array(4,3) would return:
[[00, 01, 02],
[10, 11, 12],
[20, 21, 22],
[30, 31, 32]]
The main function should execute my_2d_array and be able to potentially perform calculations with the result or modify it.
This is my attempt (with errors):
int my_2d_array(int N, int M) {
int A[N][M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
std::string element = std::to_string(i) + std::to_string(j);
A[i][j] = element;
}
}
return A;
}
void main() {
int N, M;
N = 4;
M = 3;
int A[N][M] = my_2d_array(N, M);
// Print the array A
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
std::cout << A[i][j] << " ";
}
std::cout << "\n";
}
}
One (1) dimensional attempt of #JustLearning's suggestion:
int my_array(int N) {
std::array<int, N> A;
for (int i = 0; i < N; i++) {
A[i] = i;
}
return A;
}
int main() {
int N = 4;
int A[N] = my_array(N);
// Print the array A
for (int i = 0; i < N; i++) {
std::cout << A[i] << " ";
}
}
You can use a 2d vector like this
vector<vector int> A;
It works the same way as a 2d array
Welcome to C++! Your function my_2d_array has a couple of issues:
the return type is int, however you are attempting to return an array of ints.
the identifier of an array in C++ is actually a pointer to the first element of that array. Therefore, when you return A, you must be aware of how it should be passed to a new variable in the main part of the code. In particular, your code is passing a reference to a temporary variable A, which is not permitted or safe.
In addition, in C++, unless you know what you're doing, main should always return an int:
int main() { ... }
What is not clear from your question is whether you are attempting to implement your own "array" class, or simply want to use arrays already established in the standard. For the latter, std::array is a good place to start. The advantage is that you can return std::arrays from functions like you return ints or doubles.
std::arrays are good if you plan to work with arrays of fixed size, as the size becomes part of the type: std::array<int, 3> my_array;. Then you can fill it in manually or with member functions of the class (see dox linked above).
If for some reason you prefer to work with arrays of dynamical size (sizes that will change during running your program), std::vector is the way to go.
Finally, if you are actually learning C++ by attempting to implement a container MyArray, you should specify that in your question and be a bit more specific in what help you need.
Here's a working example in 1d:
#include <iostream>
#include <array>
template <int N>
std::array<int, N> my_array() {
std::array<int, N> A;
for (int i = 0; i < N; i++) {
A[i] = i;
}
return A;
}
int main() {
const int N = 4;
std::array<int, N> arr = my_array<N>();
// Print the array A
for (int i = 0; i < N; i++) {
std::cout << arr[i] << " ";
}
}
Since the size of a std::array is included it its type, you need to create a function template, which is basically a function that works for different types. (In C++, std::array<int, 3> and std::array<int, 4> are considered different types.)
In order to use this in main, the index is promoted to a const int, as plain ints can vary during run time, and therefore are not suitable for defining types. (In C++ jargon, look up constant expressions).
Finally, note that both the return type and the type of the variable that receives the value returned by the function must be std::array, not int as you tried in your 1d code.
Following your comment, I can see why you are confused in your attempts to use a matrix in code.
There are many types of containers in C++. Many of them you can find in the standard library (std::vector, std::list, std::set, ...), others you can create yourself or use other libraries. Plain arrays (like int a[5]) are a somewhat unique case because they come from C and are part of the language itself.
A plain array lives on the stack (not very important but you might want to read up on stack vs heap allocations), and refers to a contiguous region of memory.
If you declare some array a like int a[5], you get a region of 5 integers one after the other, and you can point to the first one by just writing a. You can access each of them using a[i] or, equivalently, *(a+i).
If you declare a like int a[5][3], you now get a region of 15 integers, but you can access them slightly differently, like a[i][j], which is equivalent to *(a+i*3+j).
The important thing to you here is that the sizes (5 and 3) must be compile-time constants, and you cannot change them at runtime.
The same is true for std::array: you could declare a like std::array<std::array<int, 3, 5> a and get a similar region of 15 integers, that you can access the same way, but with some convenience (for example you can return that type, whereas you cannot return a plain array type, only a pointer, losing the size information in the process).
My advice is not to think of these arrays as having dimensionality, but as simple containers that give you some memory to work with however you choose. You can very well declare a like std::array<int, 15> a and access elements in a 2D way by indexing like this: a[i*3+j]. Memory-wise, it's the same.
Now, if you want the ability to set the sizes at runtime, you can use std::vector in a similar way. Either you declare a like std::vector<std::vector<int>> a(5, std::vector<int>(3)) and deal with the nested vectors (that initialization creates 5 std::vector<int> of size 3 each), or you declare a as a single vector like std::vector<int> a(15) and index it like a[i*3+j]. You can even make your own class that wraps a vector and helps with the indexing.
Either way, it's rare in C++ to need a plain array, and you should generally use some kind of container, with std::vector being a good choice for a lot of things.
Here is an example of how your code would look like using vectors:
#include <vector>
#include <string>
#include <iostream>
std::vector<std::string> my_2d_array(int N, int M) {
std::vector<std::string> A(N*M);
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
std::string element = std::to_string(i) + std::to_string(j);
A[i*M+j] = element;
}
}
return A;
}
int main() {
int N, M;
N = 4;
M = 3;
std::vector<std::string> A = my_2d_array(N, M);
// Print the array A
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
std::cout << A[i*M+j] << " ";
}
std::cout << "\n";
}
}
And here is a very crude example of a Matrix class used to wrap the vectors:
#include <vector>
#include <string>
#include <iostream>
template<typename T>
class Matrix {
public:
Matrix(int rowCount, int columnCount) : v(rowCount*columnCount), columnCount(columnCount) {}
T& operator()(int row, int column) {
return v[row*columnCount + column];
}
private:
std::vector<T> v;
int columnCount;
};
Matrix<std::string> my_2d_array(int N, int M) {
Matrix<std::string> A(N, M);
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
std::string element = std::to_string(i) + std::to_string(j);
A(i, j) = element;
}
}
return A;
}
int main() {
int N, M;
N = 4;
M = 3;
Matrix<std::string> A = my_2d_array(N, M);
// Print the array A
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
std::cout << A(i, j) << " ";
}
std::cout << "\n";
}
}
I'm trying to make a generic function which will dynamically allocate 2D structure. Number of elements in every row doesn't have to be same for all rows. Structure is represented as a container type, whose elements are again of a container type (for example a set of lists). The type of elements of that inner container can also be arbitrary. Containers only support the begin, end, and size functions. Iterator operations must be supported for all iterator types. The function should first dynamically allocate the space for storing the 2D structure by the continuous allocation procedure, and then rewrite the elements of the structure it has accepted into the dynamic structure. The function returns a double pointer through which the elements of this structure can be accessed.
#include <iostream>
#include <set>
#include <list>
#include <vector>
template < typename tip >
auto Make2DStructure(tip mat) {
using tip_objekta = typename std::decay < decltype(mat[0][0]) > ::type;
tip_objekta ** dynamic_mat = nullptr;
int rows = 0, total = 0;
for (auto i: mat) {
rows++;
for (auto j: i)
total++;
}
int columns[rows];
int k = 0;
for (auto i: mat) {
int num_of_colums = 0;
for (auto j: i)
num_of_colums++;
columns[k] = num_of_colums;
k++;
}
try {
dynamic_mat = new tip_objekta * [rows];
dynamic_mat[0] = new tip_objekta[total];
for (int i = 1; i < rows; i++)
dynamic_mat[i] = dynamic_mat[i - 1] + columns[i];
for (int i = 0; i < rows; i++)
for (int j = 0; j < columns[i]; j++)
dynamic_mat[i][j] = mat[i][j];
} catch (...) {
delete[] dynamic_mat[0];
delete[] dynamic_mat;
throw std::bad_alloc();
}
return dynamic_mat;
}
int main() {
std::vector<std::vector<int>>mat{
{1,2},
{3,4,5,6},
{7,8,9}
};
int columns[3]={2,4,3};
try {
int ** dynamic_mat = Make2DStructure(mat);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < columns[i]; j++)
std::cout << dynamic_mat[i][j] << " ";
std::cout << std::endl;
}
delete[] dynamic_mat[0];
delete[] dynamic_mat;
} catch (...) {
std::cout << "Problems with memory";
}
return 0;
}
How could I modify this to work without indexing inside Make2DStrucure()?
Also, if I used std::set<std::list<int>> instead of std::vector<std::vector<int>> in main function I would have deduction problems. How could I modify this to work for different outside and inside container?
Here's one way to accomplish what you want:
#include <iterator>
#include <type_traits>
template <typename tip>
auto Make2DStructure(tip&& mat) {
// create an alias for the value type:
using value_type = std::decay_t<decltype(*std::begin(*std::begin(mat)))>;
// allocate memory for the return value, the pointer-pointer:
value_type** rv = new value_type*[mat.size()]; // C++17: std::size(mat)
// Calculate the number of values we need to allocate space for:
size_t values = 0;
for(auto& inner: mat) values += inner.size(); // C++17: std::size(inner)
// allocate the space for the values:
value_type* data = new value_type[values];
// loop over the outer and inner container and keep the index running:
size_t idx = 0;
for(auto& inner : mat) {
// assign the outer pointer into the flat data block:
rv[idx++] = data;
for(auto& val : inner) {
// assign values in the data block:
*data++ = val;
}
}
return rv;
}
With the use of std::size where indicated, this would work with plain arrays too, not only the container classes.
So i've got this 3 dimensional array that looks like this:
int map[100][100][100];
and I want to use it as a return type for a function, whether as a pointer or whatever like so:
int* World::CreateCell() {
int map[100][100][100];
return map;
}
However I cannot find the appropriate return type for a 3d array, it will not let me use an int* like you can for a 2D array.
Even things like this don't work:
int a[100][100][100];
int* b = a;
VS seems to think the data type is int*(100)(100) but that makes no sense and doesn't work.
For what it's worth, I've googled this and seen no solutions. Thank you
Since you want 3D C-style array, you need to have a pointer to a pointer to a pointer, i.e., int***. Also, you need to allocate the memory if you use a creation function like this. Otherwise, you return the statically allocated memory from that function.
Here is a quick example of how to do it:
#include <iostream>
static int*** create_cell() {
constexpr std::size_t n = 100;
int*** map = new int**[n];
for (std::size_t i = 0u; i < n; ++i) {
map[i] = new int*[n];
for (std::size_t j = 0u; j < n; ++j) {
map[i][j] = new int[n];
}
}
return map;
}
static void delete_cell(int***& map) {
constexpr std::size_t n = 100;
for (std::size_t i = 0u; i < n; ++i) {
for (std::size_t j = 0u; j < n; ++j) {
delete[] map[i][j];
}
delete[] map[i];
}
delete[] map;
}
int main()
{
int*** a = create_cell();
a[0][0][0] = 1;
std::cout << "a[0][0][0] = " << a[0][0][0] << std::endl;
delete_cell(a);
return 0;
}
It depends on your use case: BUT for modern c++ you can ease your life using containers from the stl such as std::vector and std::array. Check here for reference: std::array and std::vector
For example, you can define your 3D types:
#include <array>
#include <vector>
using vector_3d = std::vector<std::vector<std::vector<int>>>;
using array_3d = std::array<std::array<std::array<int, 100>, 100>, 100>;
and then use them as:
array_3d b;
b[0][0][0] = 1;
std::cout << "b[0][0][0] = " << b[0][0][0] << std::endl;
First you should
Never return a reference or a pointer to a local non-static variable.
Now coming to your question:
I want to use it as a return type for a function, whether as a pointer or whatever like so.However I cannot find the appropriate return type for a 3d array.
This(below) is how you can do it for a 3D array. Basically there are 2 ways to solve this:
Method 1
//CreateCell is a function that returns a pointer to a 3D array of the size 100,100,100
int (*CreateCell())[100][100][100] {
int map[100][100][100];
return ↦
}
Method 1 works as can be seen here.
Method 2
//CreateCell is a function that returns a pointer to a 3D array of the size 100,100,100
auto CreateCell() -> int(*)[100][100][100] {
int map[100][100][100];
return ↦
}
Method 2 uses trailing return type and works as can be seen here.
Note
Both methods return a pointer to a local variable which must be avoided. I have given/written the answer just so that you can see how to return a pointer for a 3D array as you desired. You can instead create and return a 3D `std::vector` by value.
Consider using a simple wrapper around your matrix:
struct Wrapper { int Mat[100][100][100] = {0}; };
The signature would then become something like:
Wrapper *foo(...) { ... }
Here is simple working example:
#include <iostream>
struct Wrapper { int Mat[100][100][100] = {0}; };
Wrapper *inc(Wrapper *w)
{
for (int i=0;i<100;i++)
for (int j=0;j<100;j++)
for (int k=0;k<100;k++)
w->Mat[i][j][k] += (i+j+k);
return w;
}
int main(int argc, char **argv)
{
Wrapper w;
Wrapper *out = inc(&w);
std::cout << out->Mat[5][6][7] << "\n";
return 0;
}
I have a two-dimensional static vector ( std::vector< std::vector<double> > ) which needs to be populated and I am working on an old project which requires to be compiled using C++98. Therefore, I am not allowed to use std::vector<...> v = { {1,2}, {3,4} }; syntax.
For unidimensional vectors, assigning an array as double a[] = {1,2}; and then using the std::vector<double> v(a, a+2) does the trick; however, it is not working for two dimensional vectors.
std::vector< std::vector<double> >
x1_step_lw_2(__x1_step_lw_2,
__x1_step_lw_2 + ARRAY_SIZE(__x1_step_lw_2));
I get the following error:
../src/energyConsumption/ue-eennlite-model-param-7IN-30NN.cpp:193:33: required from here
/usr/include/c++/4.8/bits/stl_construct.h:83:7: error: invalid conversion from ‘const double*’ to ‘std::vector<double>::size_type {aka long \
unsigned int}’ [-fpermissive]
::new(static_cast<void*>(__p)) _T1(__value);
(ARRAY_SIZE(x) is a macro which calculates the size of an array)
And since these vectors are attributes of the class, It would make no sense to initiate them on a constructor.
I am fighting against this problem for some time, and most of the 'solutions' involve to switch to C++11, which is not an option.
Any help is appreciated.
My C++98 is rusty, but something like this should work:
double a[] = { 1, 2 };
double b[] = { 3, 4 };
double c[] = { 5, 6 };
std::vector<double> v[] =
{
std::vector<double>(a, a + ARRAY_SIZE(a)),
std::vector<double>(b, b + ARRAY_SIZE(b)),
std::vector<double>(c, c + ARRAY_SIZE(c))
};
std::vector< std::vector<double> > vv(v, v + ARRAY_SIZE(v));
Try this:
#include <iostream>
#include <vector>
/**this generates a vector of T type of initial size N, of course it is upto you whether you want to use N or not, and returns the vector*/
template<class T>
std::vector<T> generateInitVecs(size_t N)
{
std::vector<T> returnable;
for(int i = 0; i < N; i++)
returnable.push_back(0);
return returnable;
}
int main()
{
std::vector< std::vector<double> > twoDvector;
/**Since twoDvector stores double type vectors it will be first populated by double type vectors*/
for(int i = 0; i < 10; i++){
twoDvector.push_back(generateInitVecs<double>(10));
}
/**populating the vector of vectors*/
for(int i = 0; i < 10; i++)
for(int j = 0; j < 10; j++){
/**can be treated as 2D array*/
twoDvector[i][j] = 50;
}
for(int i = 0; i < 10; i++){
for(int j = 0; j < 10; j++){
std::cout << twoDvector[i][j] << " ";
}
std::cout << "\n";
}
}
It will print a 10 x 10 matrix, with all values assigned 50.
If i had an array of lets say 15 elements is there anyway for me to make it into a 2d array having it 5x3?
Or if i had a string with 15 letters would it be possible to make it into a 2d array having it 5x3?
This is what i have(using variables but using 5 as a and 3 as b in console)
void finishMap(string map, int a, int b)
{
string finalMap[a][b];
for(int i = 0; b>i; i++)
{
for(int x = 0; a>x; x++)
{
finalMap[a][b] += {{map[x]}, {i}};
}
}
}
Also pretty new to c++ so if you see anything i shouldn't be please tell me :3
I'm using char arrays (c strings) in my answer because I think they are useful to illustrate how arrays work - and thre really isn't a point in using std::string in your case. std::string hides a lot of the underlying nuts and bolts so I would generally recommend to play around with C strings first to understand how std::string works. Also, check out this tutorial: http://www.cplusplus.com/doc/tutorial/arrays/
A 2-dimensional array has the same memory layout as a 1-d array. In terms of memory layout, char[3][5] is the same as char[3*5] is the same as char[15]. You can use a 1-d array as a 2-d array using char[column+row*width]. The only difference if you use subscripts is that the compiler remembers how many dimensions there are and will do the whole column+row*width calculation for you.
Take this example:
char temp[5] = "abcd"; //need 5 for string termination char `\0`
for(int i = 0; i < 4; ++i) {
std::cout << temp[i];
}
std::cout << "\n\n";
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
std::cout << temp[j+2*i];
}
std::cout << std::endl;
}
Will print:
abcd
ab
cd
You can always access an array in strides. Here's a possible example using templates to restride a 1D array as a 2D array:
template <typename T, unsigned int N1, unsigned int N2>
struct strider
{
using array_type = T[N1 * N2];
array_type & data_;
Strider(array_type & data) : data_(data) {}
T & operator()(std::size_t i1, std::size_t i2)
{
return data_[i1 * N2 + i2];
}
};
template <unsigned int N1, unsigned int N2, T>
strider<T, N1, N2> stride(T (&a)[N1, N2]) { return {a}; }
Usage:
int a[15] = {};
strider<int, 3, 5> s(a);
s(1, 2) = 20;
assert(a[7] == 20);
stride<5, 3>(a)(4, 2) = 10;
assert(a[14] == 10);
I've overloaded operator() for the strided access, since unlike operator[] it can have arbirary signatures.
With some more work you could make the rank of the strided view variadic.
Okey so i used something a bit different then what i mentioned. What i did was have the user enter 3 lines of 5 length letters, which i figured out how to add into the 2d array. If your having the same issue as me, heres my code:
int main()
{
string path;
int a, b;
cin >> a >> b;
string finalMap[a][b];
for(int i = 0; b>i; i++){
cin >> path;
for(int x = 0; a>x; x++){
finalMap[x][i] = (path[x]);
}
}
for(int x = 0; b>x; x++)
{
for(int y = 0; a>y; y++)
{
cout << finalMap[y][x];
}
cout << endl;
}
return 0;
}
Thanks for trying tho, really appreciate it ^.-
You can try to use reinterpret_cast. Complete example:
#include <iostream>
using namespace std;
typedef char mtrx[5][3];
int main(){
char data[15] = "Some String";
mtrx &m = *reinterpret_cast<mtrx*>(&data);
m[1][2] = '*';
cout << data << endl;
return 0;
}