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
}
Related
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
This question already has answers here:
Assigning values to 2D Vector by using indices
(3 answers)
Closed 1 year ago.
I have the following code c++ code
#include <vector>
#include <iostream>
using namespace std;
#define for_loop(upper_bound) for (int i=0;i<upper_bound; ++i)
// #define SHOW_VECTOR(vec_in) for(int j=0;j<vec_in.size();j++){ cout << vec_in[j] << " " << endl;};
int main(){
int dim_1=10;
int dim_2=3;
int outer_i;
// vector variable declared here to have 10 values
vector<vector<int>>vec_var(dim_1);
for_loop(dim_1){
outer_i = i;
for_loop(dim_2){
cout << outer_i << " " << i << endl;
vec_var[outer_i][i]=103;
}
}
return 0;
}
When I try and run it i get the following error:
Segmentation fault (core dumped)
You need to size both your outer and inner vectors
vector<vector<int>> vec_var(dim_1, vector<int>(dim_2));
// ^ inner vector default size
Otherwise as written, you have an outer vector if size dim_1 but all of the inner vectors are empty.
As an aside, since I notice you then filling the vector with constant values, you can do all that in one step too
vector<vector<int>> vec_var(dim_1, vector<int>(dim_2, 103));
// ^ default of inner vector elements
Subscripting a std::vector does not cause that element position to be created. You need to resize, push_back, or otherwise add elements to the vectors! You indexed things that are out of range.
The outer vector is defined with a constructor argument that sizes it to dim_1, but each of those inner vectors does not have any elements. So follow it up with:
for (auto& inner : vec_var) inner.resize(dim_2);
Also, suggest using the built-in range-based for loop instead of your macro. That you need to manually save the index in your outer loop shows that your macro is not really the most convenient!
int main()
{
constexpr int dim_1=10;
constexpr int dim_2=3;
vector<vector<int>>vec_var(dim_1);
for (auto& outer : vec_var) {
outer.resize (dim_2);
for (auto& inner : outer) {
inner=103;
}
}
return 0;
}
But really, this is not normal. You probably should be using push_back to add the values, rather than resizing it and then subscripting each element in order.
You only set the dimension of the outer vector. You need to set the dimension of the inner vectors as well.
#include <vector>
#include <iostream>
using namespace std;
#define for_loop(upper_bound) for (int i=0;i<upper_bound; ++i)
// #define SHOW_VECTOR(vec_in) for(int j=0;j<vec_in.size();j++){ cout <<
vec_in[j] << " " << endl;};
int main(){
int dim_1=10;
int dim_2=3;
int outer_i;
// vector variable declared here to have 10 values
vector<vector<int>>vec_var(dim_1);
for_loop(dim_1){
outer_i = i;
vec_var[outer_i].resize(dim_2); // ADD THIS
for_loop(dim_2){
cout << outer_i << " " << i << endl;
vec_var[outer_i][i]=103;
}
}
return 0;
}
I am trying to use a class to make a dictionary < key, value > in C++.
I found online that Map was the class I was suppoused to use.
However, when I try to use Map it FILLS the gaps between the keys.
This is an issue because keys are numbers, but they are incredibly sparse.
So in one set I may have the keys [1 , 20, 30000, 70000000]. I want my map to just store those 4 values, not every values between 1 and 70000000.
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<int,int> a = {{1,-1},{20,200}}; // I want this to just store {1,20}
for(int x = 0; x < a.size(); x++) cout << a[p(x)] << ","; //however, when I print it I get [0,1..,19,20]
return 0;
}
OUTPUT
0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200,
Is there some workaround to avoid C++ from "filling the gaps" or any other class in the STD that can be used for that purpose?
map::operator[] create entry for you (and increase it's size()). If you just want to iterate through std::map, use it's iterator.
for(auto& entry : a) cout << entry.second << ",";
As apple has commented, the operator[] creates the entry. See:
http://www.cplusplus.com/reference/map/map/operator[]/
mapped_type& operator[] (const key_type& k);
If k does not match the key of any element in the container, the function inserts a new element with that key and returns a reference to its mapped value.
If you want to check existence of the key, use map::find().
Here are some ways to print out the map: you can use a for-each loop or an iterator:
#include <iostream>
#include <map>
#include <random>
using namespace std;
int main()
{
map<int, int> myMap;
// filling map with random elements
random_device rd;
mt19937 rng(rd());
uniform_int_distribution<int> uni(0,1000);
for(int i = 0; i < 10; i++) {
// uses the [] operator to create an element
myMap[uni(rng)] = uni(rng);
}
// first method to print out map using for-each loop
for(auto a : myMap) {
// cannot change elements in map
cout << a.first << " " << a.second << endl;
}
// second method to print out map using iterator
for(map<int, int>::iterator it = myMap.begin(); it != myMap.end(); it++) {
// can change elements in map
cout << it->first << " " << it->second << endl;
}
}
Hope this helps!
By the way, thinking of using map is actually very intelligent when creating a dictionary, because map elements are automatically sorted! I assume you are mapping strings to ints, right?
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).