Passing an array by reference as a function parameter in C++ - c++

How can I pass an array, declared in main method by reference as a parameter to a function? Also the compiler wants dimentions, but when i give them with variables, the compiler gives errors of invalid integer dimensions of the array, here's the code:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int scanV(int Row, int value, int M, int (&tableValues)[])
{
for (int i = 0; i <= M; ++i)
{
if (tableValues[Row - 1][i] == 1)
{
if (i + value <= M)
{
tableValues[Row][i+value] == 1;
}
if (i - value >= 0)
{
tableValues[Row][i-value] = 1;
}
}
}
}
int main()
{
int C, B, M;
cin>>C;
int integers[C];
for (int i = 1; i < C; ++i)
{
cin>>integers[i];
}
cin>>B;
cin>>M;
integers[0] = B;
int tableValues[C][M + 1];
tableValues[0][B] = 1;
for (int i = 1; i < C; ++i)
{
scanV(i, integers[i], M, tableValues);
}
return 0;
}

One simple solution is to use vectors. Consider this simple example:
#include <iostream>
#include <vector>
void f (std::vector<std::vector<int> > &v)
{
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
v[i][j] = i * 3 + j;
}
int main()
{
std::vector<std::vector<int> > v (3, std::vector<int> (3, 0));
f (v);
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
std::cout << v[i][j] << ' ';
}
In main, a 2D vector of ints (3x3) is created. The constructor shows 3 elements, all initialized with a vector of ints, which are in turn created with 3 elements initialized to 0.
Then, the vector is passed by reference to the function f, which assigns increasing values. When the vector is printed in main, it shows:
0 1 2 3 4 5 6 7 8
As you can see, their use is very similar to normal arrays, but they are actually contained, and provide easy access to a new level of programming using the STL.
In C++11, their use becomes even more familiar. You can assign vectors as follows:
std::vector<int> v0 = {2, 5};
std::vector<std::vector<int> > v1 { {1,2,3} , {4,5,6} , {7,8,9} };
Note that for vectors of multiple dimensions it's a good idea to encapsulate it in a matrix class of some sort with an underlying 1D vector type instead.
Edit:
Here's an example of initializing a 1D and 2D vector to specified elements. As seen above, this is easy in C++11, but if you have an array already, it's still pretty quick.
int a [5] = {1,2,3,4,5}; //normal
std::vector<int> v1 (a, a +5); //create using beginning and ending addresses of a
int b[3][3] = { {1,2,3} , {4,5,6} , {7,8,9} }; //normal
std::vector<std::vector<int> > v2; //empty vector
for (int i = 0; i < 3; ++i) //3 in first dimension
v2.push_back (std::vector<int> (b [i], b [i] + 3)); //push a vector with the appropriate 3 elements of b onto the back of v2
For going through one element at a time, you can do this:
std::vector<std::vector<int> > v (3, std::vector<int> (3));
for (int i = 0; i < v.size(); ++i) //v.size() == 3
for (int j = 0; j < v [i].size(); ++j)
adjustElement (v [i][j]); //replace with what you need

std::vectors are the way to go in C++ as variable-length arrays (such as int integers[C];) are forbidden.
I recommend typedefing these to make your code easier to read:
#include <vector>
typedef std::vector<int> row_t;
typedef std::vector<row_t> table_t;
Then you can declare:
void scanV(int Row, int value, int M, table_t& tableValues)
I've made this void since it doesn't return anything.
Your variables in int main() then become:
row_t integers;
table_t tableValues;
Watch out for this line:
tableValues[Row][i+value] == 1;
You probably meant to assign, rather than to check equivalence!
And please try to pick some more meaningful variable names than B, M, C...

Related

Create matrix (2d-array) of size specified by parameter input in C++

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";
}
}

Getting huge random numbers error while trying to get the maximum element in array - C++ error

I am making a program in which
the program takes 3 numbers as input: "l", "r" and "a".
I get all the values of "x" between l and r, (l and r inclusive).
example, l = 1, r = 3, x values are 1, 2, 3. so now I have a function, f(n) = ((x/a) + (x % a)),(note: [x/a] is rounded down to an integer). so I have implemented this in c++ and my code is below.
#include<iostream>
using namespace std;
int main()
{
int l;
int r;
int a;
cin>>l>>r>>a;
int nums[(r-l)+2];
int answers[(r-l)+2];
for (int i = 1; i < (r-l)+2; i++)
{
nums[i] = i;
}
for (int i = 1; i < sizeof(nums)/sizeof(nums[0])-1; i++)
{
answers[i] = ((nums[i]/a) + (nums[i] % a));
}
int j = 0;
j = answers[0];
for (int i = 0; i < sizeof(answers); i++)
{
if (j < answers[i])
{
j = answers[i];
}
}
cout<<j;
}
but whenever I run this code, I get huge random numbers like 230984084 and all.So please point out what's wrong with my Code. Thanks in advance.
Request from Levi to post my comment as answer:
The point is that one of the successes of C++ is that it started from C, but it moved on quite a bit and the code in your question is still mostly C-code. Here is an example how it could be handled in C++ with more knowledge needed but less chance for errors:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <numeric>
int main()
{
std::cout << "Give 'left', 'right' and 'process' values: \n";
int l, r, a;
std::cin >> l >> r >> a;
std::vector<int> nums((r-l)+2);
std::vector<int> answers;
// fill container with ascending numbers
std::iota(nums.begin(), nums.end(), 1);
// transform as needed
std::transform(nums.begin(), nums.end(), std::back_inserter(answers), [a](int i) { return i/a + i%a; });
// find maximum element in container (returns iterator to element)
auto maxv = std::max_element(answers.begin(), answers.end());
std::cout << *maxv;
}

Populating a two dimension static vector using C++98 standard

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.

2D Vectors Char to Int

I am trying to convert a 2D Vectors of randomly generated chars to int. For example, if the chars are 'abc' then I want my int vector to be '97,98,99' etc.
I tried looking on here and for the most part, people are asking about char to sting, string to char, etc.
This is what I have so far.
#include <vector>
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;
int main()
{
vector<vector<char> > vec(100, vector<char>(10));
vector<vector<int> > intVec(100, vector<int>(10));
srand(time(NULL));
int intAscii = 0;
// Fill 2D vector with random chars
for(int i = 0; i < 1; i++)
{
rand_num = (rand() % 8 + 3);
for(int j = 0; j < rand_num; j++)
{
//logic here... randomly gen a char and place it in the same position, but this time in the int vector as an int.
vec.at(i).push_back((rand() % 26 + 97));
intAscii = int(vec.at(i).at(j));
intVec.at(i).push_back(intAscii);
}
// Print Contents & print out the int vector.
for(int i = 0; i < vec.size(); i++)
{
for(int j = 0; j < vec.at(i).size(); j++)
{
cout << vec.at(i).at(j);
cout << intVec.at(i).at(j);
}
}
}
The problem that I am running into is that when it prints out both vectors, chars is fine, for int I am getting a whole bunch of zeros. Which doesn't seem right because the int(vec.at(i).at(j)) works i.e if char vector was a then the int vector would be 97 and so on.
At this point, my guess is that the syntax for the int vector might be wrong.
You may try this:
intAscii = (int)vec.at(i).at(j);
In addition, to access the elements it could be better to use indices instead of push_back, like:
intVec.at(i).at(j) = intAscii;
This should work because you already allocate memory for your vector at the very beginning.

Switching data from array to vector

I'm trying to convert my array to a vector, yet I'm having trouble printing it.
It says in int main() in my for loop that v is undefined. When I define
vector v; inside int main() the program compiles and runs and yet prints nothing. What am I doing wrong?
#include <iostream>
#include <vector>
using namespace std;
vector<int> a2v(int x[], int n)
{
vector<int> v(n);
for(int i = 0; i < n; i++)
{
v.push_back(x[i]);
}
return(v);
}
int main()
{
vector<int> a2v(int x[], int n);
int array[] = {11,12,13,14,15,16,17,18};
a2v(array, 8);
for(int i = 0; i < v.size(); i++)
{
cout << v[i] <<" ";
}
cout << endl;
return(0);
}
This is your program corrected:
#include <iostream>
#include <vector>
using namespace std;
vector<int> a2v(int x[], int n)
{
vector<int> v(0);
v.reserve(n); //optional
for(int i = 0; i < n; i++)
{
v.push_back(x[i]);
}
return(v);
}
int main()
{
int array[] = {11,12,13,14,15,16,17,18};
auto v = a2v(array, 8);
for(size_t i = 0; i < v.size(); i++)
{
cout << v[i] <<" ";
}
cout << endl;
return(0);
}
There were 2 errors:
In the function a2v, you instantiated a vector of 0 with length n, and then you pushed back other elements;
You were not defining v inside the main, as the return value of a2v
The vector you want to read is the return of the a2v function.
But there is a lot more simpler than that to go from C-array to vector array , I put here the example in found the vector reference web page :
http://www.cplusplus.com/reference/vector/vector/vector/
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
When you define a variable, such as your vector v, you always do it in a certain scope. The body of a function such as a2v, or main, is an example of a possible scope. So if you only do it in the function a2v, that's the only scope where it will be visible.
It says in int main() in my for loop that v is undefined.
Well it will be because there is no v in main()
a2v(array, 8);
The above function call returns a vector so you need to collect the returned vector like
vector<int> v=a2v(array,8)
Also,
vector<int> v(n);//creates a vector of size n
for(int i = 0; i < n; i++)
{
v.push_back(x[i]);//adds n more elements to the vector
}
The returned vector has 2n elements and not n
Finally you could directly create a vector from an array as
vector<int> v(arr,arr+n);//where n is the number of elements in arr