2D Vector with 3 columns and undeclared number of rows - c++

How to declare a 2D Vector with following specifications:
Should have 3 columns (Ofcourse not actually but still)
Number of rows undeclared
Some suggest i should wrap an array inside a vector as below:
typedef array <float, 3> Point
vector <Point> 2DVector
But is there a way to use only vector to obtain the desired 2D Vector?

How to declare a 2D Vector with following specifications: [...]
A mix of std::vector and std::array is perfectly fine for the requirements:
using table = std::vector<std::array<float, 3>>;
table 2d_vector;
But is there a way to use only vector to obtain the desired 2D Vector?
Here it is:
using table = std::vector<std::vector<float>>;
table 2d_vector;
You'll have to be sure to only add 3 floats to the inner vectors though.
I need to return that vector to a function and the compiler doesn't seem to understand what is vector<array<float>>
Well, yes, of course it does not. std::vector<std::array<float>> does not name a type. You probably meant:
std::vector<std::array<float, 3>>;
// ^^^

Using an initializer_list could look like this;
First #include <initializer_list>
std::vector<std::initializer_list<float>> vec{ {1,2,3} };
vec.push_back( {4,5,6} ); // add a row
Accessing each element could be done like;
for (auto list: vec){
for(auto element: list){
std::cout<< element << " "; // access each element
}
std::cout<<"\n";
}
Getting at an individual element with (x, y) coords;
// access first row (y coord = 0), second element (x coord = 1, also the column)
std::cout<< "vec[0].begin() + 1 = (addr:" << (vec[0].begin() + 1)
<< " - value: " << *(vec[0].begin() + 1) << ')';
All of that together would output;
1 2 3
4 5 6
vec[0].begin() + 1 = (addr:0x40a0d4 - value: 2)
A cleaner way could be done like this;
// using a variable type of initializer_list
std::initializer_list<float> row = {1,2,3};
std::vector<std::initializer_list<float>> vec{ row };
row = {4,5,6}; // change list
vec.push_back(row); // add rows
vec.push_back({7,8,9});
for (auto list: vec){
for(auto value: list){
std::cout<< value <<" ";
}
std::cout<<"\n";
}
//access without looping
const float *element = vec[0].begin();
// pointer to first row, first element (value: 1)
element+=3;
// point to second row, first element (value: 4)
std::cout<<"\nElement("<<*element<<")\n";
// access the same element with x,y coords = (0,1)
int x = 0, y = 1;
std::cout<<"\ncoord(0,1) = "<< *(vec[y].begin() + x) << "\n";
Would output;
1 2 3
4 5 6
7 8 9
Element(4)
coord(0,1) = 4
Problems i can think of with this (assuming it's of any worth) are that;
1) the data is initialized as constant floats and as far as i know you cannot change them.and
2) if you change the list to equal {0,1,2,3,4,5} you now have more than 3 columns.

Related

How can I find the number of elements in an already declared array of size n, if it's partially filled?

Suppose I created an array of size 5. Filled two number 1 and 2 at index 0 and 1 respectively. Now I want to return number of elements currently present in the array, i.e. 2 and not 5 given by size below. How can I do that?
int arr[5];
arr[0] = 1;
arr[1] = 2;
//size returns 5 but I want it to return 2, since it has only 2 elements.
int size = sizeof(arr)/sizeof(arr[0]);
cout << size;
If you use a classic array, it is not possible to do what you say, you will get 5 outputs each time. But if you use std::vector, the size of the vector will change automatically every time you add a new element to the vector. Then, you can easily count the number of elements in the vector by using the size() function. you can print to the screen.
#include<iostream>
#include<vector>
int main() {
std::vector<int> vec;
for (size_t i = 1; i <= 2; ++i) { vec.push_back(i); }
std::cout << "number of elements= " << vec.size();
return 0;
}

C++ std::vectors with predefined sizes

While taking a look at a solution for a problem, I came across this implementation of a vector.
const int MX = 100000;
std::vector <int> adj[MX];
The push_back() function doesn't work with this implementation of the vector class, and to add an element, the following code was used:
std::ifstream fin ("file.in");
int N = 5;
for (int i = 0; i < (N-1); i++) {
int A,B; fin >> A >> B; // reading values from another file
adj[A].pb(B), adj[B].pb(A);
}
The way this code is adding is adding pushing back a value to a certain part of the list, which I imagine as a vector inside the vector of the form:
{
{ },
{ }
}
In addition, how would I loop through this vector because for (int n : adj) does not work. I am not sure what the form of this vector is because this method of looping does not work.
What you have is C style array of vectors, off the bat you could replace that with std::array:
std::array<std::vector<int>, MX> adj;
To loop through these you would have to use a nested one, the outer loop to go through the array, and the inner one to go through each vector, something like this:
const int MX = 3;
//array of 3 vectors
std::array<std::vector<int>, MX> adj {{{1,2,3,4}, {5,6,7,8}, {9, 10, 11, 12}}};
for(auto &v : adj){ //for the array
for(auto i : v){ //for each vector
std::cout << i << " ";
}
std::cout << "\n";
}
Output:
1 2 3 4
5 6 7 8
9 10 11 12
You can also access individual elements using C style indexing:
std::cout << adj[1][0]; // vector element index 0 of array index 1
Or in a safer way, using container member at:
std::cout << adj.at(1).at(0);
This would output 5.
You should be careful though, when randomly filling the array, an array is not meant to have empty elements, otherwise the loops will go through uninitialized array members, which is not ideal, perhaps you are looking for some other kind of container.

Multiplying and displaying the values of an array in C++

I am trying to complete a C++ exercise in which an array is displayed and the user is prompted to input a multiplier, which will result in the initial numbers that were displayed being multiplied by the user's input. Here is the code that I have so far:
#include <iostream>
using namespace std;
int main()
{
int array[5] = { 1, 2, 3, 4, 5 };
for (const auto& a : array)
{
std::cout << a << std::endl;
}
double multiplier;
cout << "Input a multiplier: ";
cin >> multiplier;
for (int array = 1; array <= 5; ++array)
{
array == multiplier * array;
std::cout << array << std::endl;
}
}
When it runs, it prints the correct array, with a newline being created after each array value, and prompts the user for the multiplier. However, when the multiplier is inputted, the values do not change. Here is an example output:
1
2
3
4
5
Input a multiplier: 2
1
2
3
4
5
The goal is to get this output:
1
2
3
4
5
Input a multiplier: 2
2
4
6
8
10
Any help or code improvement would be appreciated, as figuring out how to multiply and display the multiplied values is the only thing needed to be done in order to complete the exercise. Thank you in advance!
There are three big issues with your code:
1. Naming conventions.
Do not name your array and your temporary for loop variable the same thing. This will cause an issue further down the line, which I'll illustrate.
2. Incorrect operator
As minterm has mentioned, you are using a comparison operator instead of the equal operator. But that alone will not fix your issue.
3. Not accessing array values
You are not actually multiplying the array values with the multiplier. You have to access the elements, which means you cannot start the index at 1.
for (int i = 0; i < 5; i++){
array[i] *= multiplier
cout << array[i] << endl;
}
Use = instead of ==. Currently, it just evaluates a logical statement instead of setting it to a new value.
Also, you need to change "int array" in the for loop to a different name so as to not get it confused with the array called array. Call the variable in the for loop something else, like "int i".
So then the line in question would not be "array == multiplier*array", but instead something like "int j = multiplier * array[i]", and then have it print out j instead of array.
A simpler approach would be to use another range-based for loop instead of the indexed version:
for (auto& a : array)
{
a *= multiplier;
std::cout << a << std::endl;
}
If you don't need to update the array itself (after all, your code doesn't actually read from the array again), then you a very similar, though more straightforward version might be applicable:
for (const auto& a : array)
{
std::cout << a * multiplier << std::endl;
}
You have quite a few things going on that are incorrect.
First is your over scoping (maybe not the right term) the array value.
You have an array value declared outside of your for loop, and you're using the value array again inside of the for loop for the counter. So you're not actually doing anything to your array. You're actually trying to do something to the initialization variable.
Second you're using == instead of =
You're using a comparison operator (==) instead of an assignment operator (=), but there's other big no no's going on.
array is an int[5] not just an int
To actually modify each element of your array, you need to reference the index by saying array[index] where index is a value of 0 to length of array - 1, so 4 in your case.
You're using a double multiplier and trying to apply it to an int *
If you try to multiply by a double value like 2.5, your array values are going to be int's and not a number with a decimal value. You should make your int array [] into a double array []
Not accessing your array, starting from index 0
When looping through an array, the first index is always 0. You're using array = 1 and array <= 5. This would skip your first index, and give you an out of bound index at the end. You should use int index = 0; index < 5; index++; instead.
You're trying to print array
Since array is an int [] printing array in the for loop like that will just give you the address of where the array is. You'll have to either print out each index or use the enhanced for loop method after you've applied your multiplier.
If you're wanting to use your above implementation, do this
for (int index = 0; index < 5; index++)
{
array[index] *= multiplier; // Or you can use array[index] = multiplier * array[index]
std::cout << array[index] << std::endl;
}

initialize 2d vector in c++

So, I have the following code in c++:
This is the 2d vector:
vector<vector<int>> adj;
Initialization of 2d vector:
adj[0].push_back(1);
adj[0].push_back(2);
adj[1].push_back(3);
adj[1].push_back(4);
adj[1].push_back(5);
Printing the vector:
for(auto i : adj) {
for(auto j : i)
cout << j << " ";
cout << endl;
}
Compilation is without error but when I try to run it shows nothing.
How to fix this?
When you write adj[0], you're implicitly assuming that the vector has a size of at least 1, in order for the zeroth element to exist. This is not the case for an empty vector, such as a newly initialized one. Unfortunately, this does not guarantee an error of any kind, it is Undefined Behavior, and the compiler is allowed to let literally anything happen. To avoid it, you need to make room for those elements, which can be done in a number of ways:
adj.resize(2); // now size == 2, and [0] and [1] can be safely accessed
adj[0].push_back(1);
adj[1].push_back(3);
or alternatively
adj.push_back({}); // append default-constructed vector
adj.back().push_back(1); // append 1 to the above vector
or, perhaps most concisely:
adj = {
{1, 2},
{3, 4, 5}
};
// adj now contains two vectors containing {1, 2} and {3, 4, 5} respectively
If you want to use the subscript [] operator for indexed access to a vector, consider using vector.at(), which performs the same functionality but throws an exception if the index is out of range. This can be very helpful for debugging.
You can initialize the size of the vector by calling its constructor:
vector< vector<int> > adj(row_size, vector<int>(col_size));
^^^ ^^^^^^^ ^^^
Dimension 1 Element Ctor Dimension 2
Then you can index it like an array.
std::vector operator[] expects an element to exist. It will result in undefined behavior if an undefined element is accessed. Push a std::vector to the outer vector before pushing int to the inner vector. The at() member can be used to safely access any array index with error handling.
#include <vector>
#include <iostream>
int main()
{
std::vector<std::vector<int>> adj(2); // add two std::vector<int>
adj[0].push_back(1);
adj[0].push_back(2);
adj[1].push_back(3);
adj[1].push_back(4);
adj[1].push_back(5);
for(auto const & i : adj) {
for(auto const & j : i)
std::cout << j << " ";
std::cout << std::endl;
}
}

C++ : auto variable deduction differs range for loop vs a normal for loop for multi dimensional array

Here's the following:
int ia [3][4] = {
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11}
};
Normal assignment:
auto p = ia;
This is understandable.
Array ia returns pointer to its first element which is the 1st row of 4 elements (batches of 4 elements).
p has int (*)[4]. Doing a p + 1 will point to the next batch of 4 elements.
Using range for:
for (auto row : ia) {
for (auto col: row)
cout << col << " ";
cout << endl;
}
Why row is not int (*)[4] since each loop it's returning batches of 4 elements just like the previous example?
Instead it is int *.
When I hovered mouse over row variable it gives me int *..
Thanks
The range-based for loop takes each array element and uses it in a declaration or expression derived from your given initializer in each loop round. An array element has type int[4], so for an invented variable int __elem[4] representing the current range element, your loop body effectively says:
const auto row = __elem; // __elem is int[4]
Now this should look familiar: the array expression on the right decays to a pointer to its first element, which has thus type int.
If you want to avoid the decay, you need to bind a reference instead:
const auto& row = __elem; // row is int(&)[4]
Putting this back into your range-based loop, you want:
for (const auto& row : ia) {
for (const int& cell : row) {
// ...
}
}