So, I don't know how can I print elements of such a list.
list<int>* a;
a = new list<int>(4);
a[0].push_back(1);
a[0].push_back(3);
a[2].push_back(5);
a[2].push_back(7);
cout << a[0].front() << '\n';
cout << a[1].back() << '\n';
Firstly, I tried to print it via range-based for loop, but it didn't work either.
for(auto element: a[0]) cout << element << '\n'; // doesn't work
Are you trying to store a list of integer lists? Because this implementation will not work since you only have a list of integers and no push_back() operation is available for the elements.
Remove the index operator for all those push_back() operations and take out the index operator for the front() and back() as those are not available to the elements either.
I would use a std::vector instead of new (which should technically be new[] in this case anyway).
#include <iostream>
#include <list>
#include <vector>
int main() {
std::vector<std::list<int>> a(4);
a[0].push_back(1);
a[0].push_back(3);
a[2].push_back(5);
a[2].push_back(7);
for (std::list<int> const& l : a) {
for (int i : l) {
std::cout << i << ' ';
}
std::cout << '\n';
}
}
Output
1 3
5 7
Related
Consider the following code:
#include <vector>
#include <iostream>
void monitor_vector(std::vector<int> myV)
{
std::vector<int>::iterator it = myV.begin();
std::cout << "Vector size: " << myV.size() << std::endl;
while (*it)
{
std::cout << "Element " << it-myV.begin() << ": " << *it << std::endl;
it++;
}
}
int main()
{
std::vector<int> myVector(4,1);
monitor_vector(myVector);
return 0;
}
Basically, I create a std::vector<int> that has 4 elements, and assign each element 1. When I execute this code, all is well. The output shows each element.
However, when I execute it with this line
std::vector<int> myVector(4,1);
replaced by this line:
std::vector<int> myVector(4,0);
I can't see any output. The output is:
yilmazali#yilmazali:~/cpp_practice$ g++ -o la vector_practice.cpp
yilmazali#yilmazali:~/cpp_practice$ ./la
Vector size: 4
yilmazali#yilmazali:~/cpp_practice$
Why does it ignore the elements with default integer value? Still, they are there as the member of std::vector.
Thanks for your time,
Ali
You iterate while (*it).
If you fill your vector with zeros, *it == 0 and therefore if (*it) is like if (false): the loop body is never executed.
Instead, loop while it != myV.end()
Is there any alternative to a range-based for loop when it comes to vector arrays? I've noticed that c++98 won't allow range-based for loops. Here is some sample code looping through a vector array using a range based for loop:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vecArray1 (3,20);
for (int v: vecArray1) {
cout << "ArrayValue:" << v << endl;
}
return 0;
}
Now here is an alternative I've tried that didn't work:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vecArray1 (3,20);
for (int i=0; i<sizeof(vecArray1); ++i) {
cout << "ArrayValue:" << vecArray1[i] << endl;
}
return 0;
}
It outputs 10 elements instead of 3 defined by the vector array above. Are there any alternatives to range-based for loops that work with c++98?
C++98 does not allow for range-based for-loops.
In C++98 you would need to do the following:
for(unsigned int i=0;i<vecArray.size();++i)
std::cout << "ArrayValue: " << vecArray[i] << std::endl;
or
for(std::vector<int>::iterator it=vecArray.begin();it!=vecArray.end();++it)
std::cout << "ArrayValue: " << *it << std::endl;
The operator
sizeof
does NOT give you the length of an array. Instead, it returns an unsigned integer representing the number of bytes of the type you give as the argument.
For example,
std::cout << sizeof(unsigned long long) << std::endl;
prints
8
on my machine, because the type unsigned long long consista of 64-bits, or 64/8 = 8 bytes.
In C++11 we now have range-based for-loops:
Examples:
for(int i : vecArray)
std::cout << "i = " << i << std::endl;
for(const int& i : vecArray)
std::cout << "i = " << i << std::endl;
In the first example the values are copied from vecArray into the variable i. In the second example you are instead working with const references to the values in vecArray (which could be useful for objects which are expensive to copy).
In fact, the range-based for loops in C++11 are available for all types on which you can call begin() and end() (i.e. those which you can iterate through).
sizeof(vecArray1) doesn't do what you think it does.
Either use:
for (int i=0; i<vecArray1.size(); ++i) {
cout << "ArrayValue:" << vecArray1[i] << endl;
}
or:
for (std::vector<int>::iterator it = vecArray1.begin(); it != vecArray1.end(); it++) {
cout << "ArrayValue: " << *it << endl;
}
The second one is more verbose, but works for other types of collections as well (like std::list) and is more similar to what the range-based for loop does.
According to SGI, cplusplus.com, and every other source I've got, the sort() member function of the std::list should not invalidate iterators. However, that doesn't seem to be the case when I run this code (c++11):
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include "print.hpp"
unsigned int seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator(seed);
std::uniform_int_distribution<unsigned int> distribution(1, 1000000000);
auto rng = std::bind(distribution, generator);
// C++11 RNG stuff. Basically, rng() now gives some unsigned int [1, 1000000000]
int main() {
unsigned int values(0);
std::cin >> values; // Determine the size of the list
std::list<unsigned int> c;
for (unsigned int n(0); n < values; ++n) {
c.push_front(rng());
}
auto c0(c);
auto it(c.begin()), it0(c0.begin());
for (unsigned int n(0); n < 7; ++n) {
++it; // Offset these iterators so I can print 7 values
++it0;
}
std::cout << "With seed: " << seed << "\n";
std::cout << "Unsorted list: \n";
print(c.begin(), c.end()) << "\n";
print(c.begin(), it) << "\n\n";
auto t0 = std::chrono::steady_clock::now();
c0.sort();
auto d0 = std::chrono::steady_clock::now() - t0;
std::cout << "Sorted list: \n";
print(c0.begin(), c0.end()) << "\n";
print(c0.begin(), it0) << "\n"; // My own print function, given further below
std::cout << "Seconds: " << std::chrono::duration<double>(d0).count() << std::endl;
return 0;
}
In print.hpp:
#include <iostream>
template<class InputIterator>
std::ostream& print(InputIterator begin, const InputIterator& end,
std::ostream& out = std::cout) {
bool first(true);
out << "{";
for (; begin != end; ++begin) {
if (first) {
out << (*begin);
first = false;
} else {
out << ", " << (*begin);
}
}
out << "}";
return out;
}
Sample input/output:
11
With seed: 3454921017
Unsorted list:
{625860546, 672762972, 319409064, 8707580, 317964049, 762505303, 756270868, 249266563, 224065083, 843444019, 523600743}
{625860546, 672762972, 319409064, 8707580, 317964049, 762505303, 756270868}
Sorted list:
{8707580, 224065083, 249266563, 317964049, 319409064, 523600743, 625860546, 672762972, 756270868, 762505303, 843444019}
{8707580, 224065083}
Seconds: 2.7e-05
Everything works as expected, except for the printing. It is supposed to show 7 elements, but instead the actual number is fairly haphazard, provided "value" is set to more than 7. Sometimes it gives none, sometimes it gives 1, sometimes 10, sometimes 7, etc.
So, is there something observably wrong with my code, or does this indicate that g++'s std::list (and std::forward_list) is not standards conforming?
Thanks in advance!
The iterators remain valid and still refer to the same elements of the list, which have been re-ordered.
So I don't think your code does what you think it does. It prints the list from the beginning, to wherever the 7th element ended up after the list was sorted. The number of elements it prints therefore depends on the values in the list, of course.
Consider the following code:
#include <list>
#include <iostream>
int main() {
std::list<int> l;
l.push_back(1);
l.push_back(0);
std::cout << (void*)(&*l.begin()) << "\n";
l.sort();
std::cout << (void*)(&*l.begin()) << "\n";
}
The two address printed differ, showing that (unlike std::sort), std::list::sort has sorted by changing the links between the elements, not by assigning new values to the elements.
I've always assumed that this is mandated (likewise for reverse()). I can't actually find explicit text to say so, but if you look at the description of merge, and consider that the reason for list::sort to exist is presumably because mergesort works nicely with lists, then I think it's "obviously" intended. merge says, "Pointers and references to the moved elements of x now refer to those same elements but as members of *this" (23.3.5.5./23), and the start of the section that includes merge and sort says, "Since lists allow fast insertion and erasing from the middle of a list, certain operations are provided specifically for them" (23.3.5.5/1).
I do not understand why iterating through a container with a for loop produces different results than iterating through it with a while loop. The following MWE illustrates this with a vector and a set of 5 integers.
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int main()
{
vector<int> v;
set<int> s;
// add integers 0..5 to vector v and set s
for (int i = 0; i < 5; i++) {
v.push_back(i);
s.insert(i);
}
cout << "Iterating through vector with for loop.\n";
vector<int>::const_iterator itv;
for (itv = v.begin(); itv != v.end(); itv++) cout << *itv << ' ';
cout << '\n';
cout << "Iterating through set with for loop.\n";
set<int>::const_iterator its;
for (its = s.begin(); its != s.end(); its++) cout << *its << ' ';
cout << '\n';
cout << "Iterating through vector with while loop.\n";
itv = v.begin();
while (itv++ != v.end()) cout << *itv << ' ';
cout << '\n';
cout << "Iterating through set with while loop.\n";
its = s.begin();
while (its++ != s.end()) cout << *its << ' ';
cout << '\n';
}
The above produces:
Iterating through vector with for loop.
0 1 2 3 4
Iterating through set with for loop.
0 1 2 3 4
Iterating through vector with while loop.
1 2 3 4 0
Iterating through set with while loop.
1 2 3 4 5
The for loops work as expected but not the while loops. Since I'm using ++ as a postfix, I don't understand why the while loops behave as they do. Another mystery is why the while loop prints a 5 for set s, since this number was not inserted in s.
Your while loop is not equivalent to the for loop.
The for loop is equivalent to
itv = v.begin();
while(itv != v.end()) {
cout << *itv << ' ';
itv++;
}
Note that the increment happens after the cout. In your while loops, you do the increment in the test, before cout. Even though you use postincrement, the increment takes effect before your loop body is executed.
Write your while loops like I did there and the discrepancy should disappear.
When you iterate using the for loop you increment the iterator only after the body is evaluated. When you iterate using the while loop you increment the iterator after the check but before the body of the loop. Dereferencing the iterator in the last iteration of your while loops causes undefined behavior.
It could be because the compiler evaluates the its++ in the while expression first before evaluating the rest of the expression.
Since I'm using ++ as a postfix, I don't understand why the while loops behave as they do.
That's because first the while predicate is evaluated, and then (if the predicate was true) the body of the while loop. By the time you try to access the value in the body, the iterator was already incremented.
Just a few 'random' style hints, mainly showing algorithm use and modern C++11 features.
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <iterator>
int main()
{
const std::vector<int> v { 0,1,2,3,4 };
const std::set<int> s { 0,1,2,3,4 };
for (auto element : v)
std::cout << element << ' ';
std::cout << '\n';
for (auto element : s)
std::cout << element << ' ';
std::cout << '\n';
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
std::copy(s.begin(), s.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}
so suppose I have a vector called v and it has three elements: 1,2,3
is there a way to specifically pop 2 from the vector so the resulting vector becomes
1,3
//erase the i-th element
myvector.erase (myvector.begin() + i);
(Counting the first element in the vector as as i=0)
Assuming you're looking for the element containing the value 2, not the value at index 2.
#include<vector>
#include<algorithm>
int main(){
std::vector<int> a={1,2,3};
a.erase(std::find(a.begin(),a.end(),2));
}
(I used C++0x to avoid some boilerplate, but the actual use of std::find and vector::erase doesn't require C++0x)
Also, remember to use the erase-remove idiom if you are removing multiple elements.
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
unsigned int i;
vector<unsigned int> myvector;
// set some values (from 1 to 10)
for (i=1; i<=10; i++) myvector.push_back(i);
// erase the 6th element
myvector.erase (myvector.begin()+5);
// erase the first 3 elements:
myvector.erase (myvector.begin(),myvector.begin()+3);
cout << "myvector contains:";
for (i=0; i<myvector.size(); i++)
cout << " " << myvector[i];
cout << endl;
return 0;
}
From C++ 20, we can use std::erase for removing multiple elements.
(no need for "erase-remove idiom")
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1,2,2,3,4,5};
std::erase(v, 2);
for(auto e : v) std::cout << e << " ";
std::cout << '\n';
// output: 1 3 4 5
}