This question already has answers here:
Why does auto works differently in "range for" in 2D and 1D arrays in C++
(4 answers)
Closed last month.
I was curious about why we go through a multidimensional array this way
for (auto& row : mat1)
{
for (int& elements : row)
{
cin >> elements;
}
}
Why do we use &(pass by ref) when we make a temp variable called elements that goes through the rows and gets each value. aswell as the & in the for (auto& row : mat1) Can someone explain this whole part with every detail please ?
using namespace std;
int main()
{
const int row{ 3 }, col{ 3 };
array<array<int, col>, row > mat1;
cout << "Enter matrix 1 elements: ";
for (auto& row : mat1)
{
for (int& elements : row)
{
cin >> elements;
}
}
for (auto& row : mat1)
{
for (int& elements : row)
cout << elements << " ";
cout << endl;
}
If you don't use references, then you will make copies of the data.
And if you make a copy (iterate by value) rather than using references, you will only modify the local copy, not the original data.
This is for the input loop of course, where you have
cin >> elements;
In the output loop there's no need for references for the int elements themselves, but I recommend using const references for the arrays since otherwise you make a copy which could be expensive.
So in the output loop to:
for (auto const& row : mat1)
{
for (auto element : row)
{
std::cout << element;
}
}
Related
Why do these loops give the same output:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> ar = {2, 3 ,4};
for(auto i: ar) //this line changes in the next loop
cout<<i<<" ";
cout<<"\n";
for(auto &i: ar) //i changed to &i
cout<<i<<" ";
}
They both give the same output:
2 3 4
2 3 4
When declaring the foreach loop variable, shouldn't adding ampersand make the variable take the references of the values in the array, and printing i make it print the references. What is happening here?
By print the references I meant something like this code prints:
for(auto i: ar)
cout<<&i<<" ";
Output:
0x61fdbc 0x61fdbc 0x61fdb
The results are the same because in the first loop you copy the variable's value in a new variable i and print its value. (Additional RAM allocated)
In the second loop you access the value of the current element from the memory by assigning its address to i. (No additional RAM allocated)
On the other side:
cout<<&i<<" ";
causes printing the address of i.
The ampersand operator has many purposes. These two of the many are hard to recognize, namely the & infront of a variable in a declaration ( such as int& i ( or int &i, same thing ) ), and the & infront of a variable not in a declaration, such as cout << &i.
Try these and you will get a better understanding.
for (auto i : ar)
cout << i << " "; // 2 3 4 // element of ar
for (auto &i : ar)
cout << i << " "; // 2 3 4 // element of ar
for (auto i : ar)
cout << &i << " "; // address of local variable i (probably same address)
for (auto &i: ar)
cout << &i << " "; // address of elements of ar (increasing addresses)
I'm trying to get a vector of string from input to create a graph , but i don't know why in middle my code it crashes. please help me fix it. I use Visual Studio.
#include <iostream>
#include <vector>
#include <iterator>
void main(void)
{
{
using namespace std;
int8_t n{ 0 };
cout << "enter the size of graph : ";
cin >> n;
vector<string> graph(n);
string connectionsWith;
vector<string>::iterator i;
string::iterator e;
int p{ 0 };
for (i = graph.begin(); i != graph.end(); ++i)
{
cout << '\n' << "enter the vertices that are connected to " << p << " : ";
cin >> connectionsWith;
graph.push_back(connectionsWith);
p++;
}
p = 0;
for (i = graph.begin(); i != graph.end(); ++i)
{
cout << p << " is connected to " << *i;
p++;
}
}
}
In your constructor of graph, you allocate n string. Inside the loop you add on top of the constructed n strings, n more strings via push back. That potentially invalidates your iterators, as ChrisMM said, also not the most efficient way to implement such a scenario.
So as a solution, instead of
vector<string> graph(n);
do
vector<string> graph;
graph.reserve(n);
and iterate over the index, e.g. from 0 to n, and push back.
Especially in the first loop you are not dereferencing the iterator at all, which suggests that using index based loop would show your intent better.
life_steal pointed out the problem. I would like to add few information and other way to solve the problem.
int8_t n{ 0 };
vector<string> graph(n); // Here initialization happening with ASCII. If input is "1" then it would be "49". Consider changing int8_t to int if you unaware of that.
graph.push_back(connectionsWith); //Instead of this line Use: *i = connectionsWith; it directly assign the value.
This question already has answers here:
Why does my vector print out all zeroes?
(4 answers)
Closed 1 year ago.
I'm trying to show the values of a dynamic array input using vector and a for range loop but when it prints it shows the 0's then the value that was input.
Please don't mind the if statement as I commented it out to use a smaller sample size when testing. But if I enter the size say its 3 then input values such as 1,2,3 the output would be 0 0 0 1 2 3. I'm trying to remove the first three 0's.
int main()
{
std::cout << "How many numerical values do you wish to enter: ";
int values, index, collect;
std::cin >> values;
std::vector<int> numbers(values);
//if(values == 31)
//{
for (index = 0; index < values; index++)
{
std::cout << "Enter value[" << (index + 1) << "]: ";
std::cin >> collect;
numbers.push_back(collect);
}
for (auto &showNumbers : numbers)
{
std::cout << showNumbers << " ";
}
//}
return 0;
}
This line creates a vector of values elements.
std::vector<int> numbers(values);
When you're entering the 3 as values, the vector will hold a three elements with values of 0.
Then you're pushing 3 more elements:
numbers.push_back(collect);
You could either:
replace std::vector<int> numbers(values); with std::vector<int> numbers; (this will create empty vector), or
replace numbers.push_back(collect); with numbers.at(index) = collect; (this will set element value)
Just do numbers[index] = collect; and you are good. You can even try this cin >> numbers[index];
You are using a constructor in
std::vector<int> numbers(values);
In your case:
values = 3
which sets the first 3 contents as zeros. Then using push_back you are adding values further. You must just declare the vector as:
std::vector<int> numbers;
I have a long vector of values, a specified user input of row/column size. I need to assign a set of 3 numbers into a vector, from the long list of vectors. The vector with 3 number set will be pushed back into another vector, with user input row/column size. 1 column = the 3 number vector set and so on, until every column is filled out. I have trouble making this code (it needs to be in a loop). Any help please?
The picture is an example of a 4x4 vector, with each column a vector of 3 numbers
It sounds as if you want nested vectors, where each smaller vector inside your "long vector" represents a column of 3 values. If so you could do so like:
std::vector<int> columnVec = { 1, 2, 3 };
std::vector<std::vector<int>> longVector;
longVector.push_back(columnVec);
In the first line we declare a vector representing our column and place three integers inside it. On line two we declare another vector, but this time containing vectors which themselves contain ints, i.e. a vector full of column vectors. We then used push_back() to push the column vector into our vector of vectors. If you needed to print the values you could do so like:
for(auto& vec : longVector) { //Walk through our vector of vectors.
for(int value : vec) { //Walk through our column vectors of values.
std::cout << value; //Print out each value of the column.
}
std::cout << std::endl; //Add a newline.
}
Note that if you print them, the columns will appear as rows in the console. If you care about the formatting in the console it will take a bit more effort and might be worth asking as a separate question.
One possible approach might look something like this:
#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
int main()
{
typedef std::vector<int> VecInt;
typedef VecInt::iterator VecIntIter;
typedef std::vector<VecInt> VecVecInt;
typedef VecVecInt::iterator VecVecIntIter;
VecVecInt rows;
const int maxRows = 10, maxCols = 10;
cout << "Values during creation" << endl;
cout << "----------------------" << endl;
for (int rowNum=0; rowNum<maxRows; rowNum++)
{
VecInt curRow;
for (int colNum=0; colNum<maxCols; colNum++)
{
if (colNum != 0)
cout << " ";
int cellValue = rand() % 32;
cout << cellValue;
curRow.push_back( cellValue );
}
cout << endl;
rows.push_back(curRow);
}
cout << endl;
cout << "Values during retrieval" << endl;
cout << "----------------------" << endl;
for (VecVecIntIter rowIter=rows.begin(); rowIter!=rows.end(); rowIter++)
{
VecInt curRow = (*rowIter);
for (VecIntIter colIter=curRow.begin(); colIter!=curRow.end(); colIter++)
{
if (colIter != curRow.begin())
cout << " ";
cout << (*colIter);
}
cout << endl;
}
}
Though, this will store a collection of rows, rather than a collection of columns. Easy enough to change the for loops.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
So I have to make a program that stores input piece by piece, until -1 is input. An example of this input would be 1 1 1 0 3 5 3 -1. And -1 would not be recorded. Then it plays the list back to you, but bacwards, so output would be 3 5 3 0 1 1 1
To do this I need to make a list of objects, but I have no clue how to declare them, or how to add/remove items to them. how do I do this?
You need a place to store values that can grow as values are read.
The simpler is probably std::vector, but also std::list or std::deque as well as whatever bidirectional container will do the game.
Then you need a loop to get the values an save them into the container (the push_back method has that purpose), and another loop getting the values from the container from the end and printing them.
This can be done using iterators or using indexes, depending on the container and on your own specific needs.
This may be a possibility:
#include <vector>
#include <iostream>
template<class V, class S>
void read_numbers(V& v, S& s, N end)
{
N x=0;
while(x << s)
{
if(x==end) return;
v.push_back(x);
}
std::cerr << "error: bad reading" << std::endl;
}
template<class V, class S>
void write_numbers(const V& v, S& s)
{
for(auto i=s.rbegin(); i!=s.rend(); ++i)
std::cout << *i << ' ';
std::cout << std::endl;
}
int main()
{
std::vector<int> nums;
read_numbers(nums, std::cin, -1); }
write_numbers(nums, std::cout);
return 0;
}
For a list of unknown size, you can declare a vector class:
std::vector<int> myVector;
Then to add an element, use push_back:
// assign some integer to myInt
myVector.push_back (myInt);
http://www.cplusplus.com/reference/vector/vector/push_back/
If you need to use a list, then you could use std::list.
You can declare them like this:
std::list<int> myList;
You can read more about std::list here.
You can use it for inspiration.
#include <vector>
#include <iostream>
int main(int argc, char * argv[]) {
std::vector<int> numbers;
int number;
do {
std::cin >> number;
if (number != -1) {
numbers.push_back(number);
}
} while(number != -1);
for (std::vector<int>::reverse_iterator it = numbers.rbegin(); it != numbers.rend(); ++it) {
std::cout << *it << " ";
}
std::cin.get();
return 0;
}
As was suggested already, you could use std::vector. It resizes as you push more elements. If the requirement is strictly a linked list, then go for std::list.
As to the requirement of playing them in reverse order, just use reverse_iterator and go through the list printing them.
std::list<int> mylist;
// Insert the elements.
for (std::list<int>::reverse_iterator rIt = mylist.rbegin();
rIt != mylist.rend(); ++rIt) {
cout << *rIt;
}
There are basically two options:
You can use a pointer int *data and manually allocate memory to it with new[]. You'll need to continually reallocate the array as you find that the array is larger than you expected.
You can use one of the wonderful containers that c++ provides. I might suggest std::vector.
Here's an example of how you might implement this:
#include <iostream>
#include <vector>
int main() {
std::vector<int> data;
while (true) {
int number;
std::cin >> number;
if (!std::cin)
break;
if (number == -1)
break;
data.push_back(number);
}
for (int datum : data)
std::cout << datum << " ";
std::cout << "\n";
}