Using the code from cplusplus.com, I am trying to find the max int value in an vector<std::string>.
the vector is in std::string format and there is no choice here.
bool myfn(int i, int j)
{
return i < j;
}
vector<std::string> dat;
dat.push_back(2.1);
dat.push_back(5.3);
for (int l = 0; l < dat.size(); ++l)
{
std::cout << *std::max_element(dat.begin(), dat.end(), myfn) << '\n';
}
expected output:
3
error:
.cpp:76:93: error: no matching function for call to 'max_element(std::vector<std::basic_string<char> >&, std::vector<std::basic_string<char> >::size_type, bool (&)(int, int))'
How do you find the max value in a vector<std::string>?
You're calling max_element with the wrong arguments. It takes two iterators and a function:
template <class ForwardIterator, class Compare>
ForwardIterator max_element (ForwardIterator first, ForwardIterator last,
Compare comp);
You're calling it with a vector and a size. The confusion might stem from the example on the reference you link where they do:
std::min_element(myints, myints +7, myfn)
// ^^^^^^ ^^^^^^^^^
// int* int*
In this case, both myints and myints + 7 are of type int*, and a raw pointer is an iterator. In your case however, you are passing two different types (vector<string> and size_t), neither of which is an iterator. So you need to instead do:
*std::max_element(dat.begin(), dat.end(), myfn)
Or, to illustrate something equivalent to the example in the reference (although definitely prefer the above):
std::string* first = &dat[0];
*std::max_element(first, first + dat.size(), myfn)
Which works because in this case I am passing two string*'s, which are iterators.
(Also based on your usage, dat should be vector<int> not vector<string>.)
You have a vector that is full of strings vector<std::string> dat; but yet your comparison functions takes 2 integers. You might want to either change the type that is stored in the vector or change the comparison function you use. If you use integers then the default comparison operator will do what you want already without you needing to write a custom function.
Also std::max_element expects to get iterators one for the start and one for the end, so you need to change your call to be something like std::max_element(dat.begin(), dat.end(), myfn). You might notice that the loop you have is actually not needed because you already go over that range with the call to std::max_element all this loop does is compute the exact same value multiple times, you only need to compute it once.
Your std::vector dat declaration is wrong as you want to push_back int.
std::max_element and std::min_element returns an iterator not value. You can have a look into the following example
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> v {1,2,3,4,6};
auto biggest = std::max_element(std::begin(v), std::end(v));
std::cout << "Max element is " << *biggest
<< " at position " << std::distance(std::begin(v), biggest) << std::endl;
auto smallest = std::min_element(std::begin(v), std::end(v));
std::cout << "min element is " << *smallest
<< " at position " << std::distance(std::begin(v), smallest) << std::endl;
return 0;
}
Pointers can be iterators. This is what allows you to use arrays as a range in standard library functions. myints is an expression that refers to the first element of the array, and myints + 7 refers to one past the end of the array. Equivalently you can do std::begin(myints) and std::end(myints). Standard containers expose iterators in the form of these member functions myvector.begin() and myvector.end(). You pass these iterators, not the container and size, to std::max_element.
By default, std::max_element uses operator< to compare the elements. You don't need a comparator functor in this instance.
Your std::vector's value_type is std::string, but you're trying to pass an int. Either change the value_type to int, or use a string conversion function, i.e. C++11's std::to_string.
Finally, your loop is completely unnecessary. std::max_element operators over a range.
std::vector<int> dat;
dat.push_back(1);
dat.push_back(3);
std::cout << *std::max_element(dat.begin(), dat.end()) << '\n';
Related
std::multimap<std::string, std::string> authors;
authors.insert ({{"Steven,King", "Cujo"}, {"Jesse,James", "The Highlight"}});
auto it = authors.begin();
auto retVal2 = authors.erase(it+1);
for (auto &i : authors){
std::cout << i.first << " " << i.second << std::endl;
}
Is it not allowed to add values to the iterator to move to the desired location in the multimap?
In vectors this can be done.
Please clarify if there is anyway about this?
thank you.
std::multimap::iterator is a bidirectional iterator. A bidirectional iterator does not have operator+ because it can only advance one at a time making operator+ a very slow function. Maybe you're comparing it to the iterator of something like std::vector or std::array. However, those are random access iterators where operator+ can work in constant time.
Since you only need to add it by 1, you can easily replace it+1 with std::next(it). If you want to make a new iterator n elements after it you can also do std::next(it, n). Like std::next, there's also std::prev for going backwards. If you want to modify it itself, you can use operator++/operator-- (which act like how you would expect them to) or use std::advance(it, n) to go n elements forward or backward (There's no opposite of std::advance like std::recede, to make your iterator go back n should be a negative number).
I have the simple code below:
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
int main()
{
list<int> ints = { 3, 6, 1, 5, 8 };
int index;
index = 2;
std::list<int>::iterator it = ints.begin() + index;
cout << "Element at index " << index << " is " << *it << '\n';
return 0;
}
On compiling, it says:
error: no match for ‘operator+’ (operand types are ‘std::__cxx11::list::iterator’ {aka ‘std::_List_iterator’} and ‘int’)
std::list::iterator it = ints.begin() + index;
~~~~~~~~~~~~~^~~~~~~
I understand what the compiler is trying to say, but I am unsure how to resolve it. How do I convert the int to an iterator and get the element at that index? I did look for similar questions, but most of them seek the conversion in the opposite direction which can be done using std::distance, while the remaining were for different containers.
Thanks for your help!
Use std::next.
If you think of distance as the operator - between two iterators, then next, prev, and advance are respectively the +, -, and += between an iterator and an integer.
These functions are meant to treat all iterators the same way, even though the complexity of operations is different for different iterators. For a std::list, which uses "forward iterators", these are all linear. For a std::vector, which uses "random-access iterators", these are all constant.
Converting an integer to an iterator for std::list
Integers and iterators are quite separate concepts, so it is unclear what meaning such conversion would have. How does one convert a coconut into transitivity?
... and get the element at that index?
Now, this makes a bit more sense. List element do not have indices however. But presumably by index i, you mean the ith (zero based) successive element from beginning.
The standard library has a function for that: std::next. What this does (with non-random access iterators) is increment the iterator for given number of repetitions in a loop. Intuitively, the asymptotic complexity of such operation is linear.
Suppose, I have declared a vector in C++ like this:
vector<int>numbers = {4,5,3,2,5,42};
I can iterate it through the following code:
for (vector<int>::iterator it = numbers.begin(); it!=numbers.end(); it++){
// code goes here
}
Now, I would talk about coding in the block of for loop.
I can access and change any value using this iterator. say, I want to increase every value by 10 and the print. So, the code would be:
*it+=10;
cout << *it << endl;
I can print the address of both iterator and elements that are being iterated.
Address of iterator can be printed by:
cout << &it << endl;
Address of iterated elements can be printed by:
cout << &(*it) << endl;
But why the iterator itself could not printed by doing the following?
cout << it <<endl;
At first I thought the convention came from JAVA considering the security purpose. But if it is, then why I could print it's address?
However, Is there any other way to do this? If not, why?
Yes, there is a way to do it!
You can't print the iterator because it is not defined to have a value.
But you can perform arithematic operations on them and that helps you to print the value (of the iterator).
Do the following.
cout << it - v.begin();
Example:
#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
using namespace std;
int main () {
vector<int> v = {20,3,98,34,20,11,101,201};
sort (v.begin(), v.end());
vector<int>::iterator low,up;
low = lower_bound (v.begin(), v.end(), 20);
up = upper_bound (v.begin(), v.end(), 20);
std::cout << "lower_bound at position " << (low - v.begin()) << std::endl;
std::cout << "upper_bound at position " << (up - v.begin()) << std::endl;
return 0;
}
Output of the above code:
lower_bound at position 2
upper_bound at position 4
Note: this is just a way to get things done and no way I have claimed that we can print the iterator.
...
There is no predefined output operator for the standard iterators because there is no conventional meaning of printing an iterator. What would you expect such an operation to print? While you seem to expect to see the address of the object the iterator refers to, I find that not clear at all.
There is no universal answer to that, so the committee decided not to add a those operators. (The last half sentence is a guess, I am not part of the committee.)
If you want to print those iterators, I would define a function like print(Iterator); (or something like this, whatever fits your needs) that does what you want. I would not add an operator << for iterators for the reason I mentioned above.
why the iterator itself could not printed by doing the following?
Because, it is not defined to a value internally.
Is there any other way to do this?
Basically, the compiler does not facilitate it by default, you may try to edit the compiler code! But it is too terrific you know!
If not, why?
Because it has no well-defined way to express it.
You can't print the iterator because it is not defined to have a value. But you can perform arithematic operations on them and that helps you to print the value (of the iterator).
I have a function that does some computing and set the value returned into my vector.
#include <vector>
#include <algorithm>
#include <iostream>
void VectorLoop(vector<ClassName>& Vector)
{
float TempFloatVariable = 0.0;
int count = 0;
int update = 0;
while (count != Vector.size())
{
if (Vector[count].getValue() == 100.0) //I hardcode this so i can check if the Value is empty or not
{
//code that set all of the variable from the vector's memory's object
TempFloatVariable = AnotherClass.Formula //does the computing and return the value
//code that gets value from object for overloading
//code that gets value from object for overloading
//code that gets value from object for overloading
Vector[count].setValue(TempFloatVariable);
update++;
}
else
{
count++;
}
}
cout << "Computation completed! (" << update << " record(s) were updated)" << endl;
}
After all of the computing is done, I want to sort them from highest to lowest, base on the Value, but I have no idea how to do so, i tried to hard code it, pulling values out manually 1 by 1 to do comparison, but kept failing. And that would defeat the purpose of using vector, there are many examples of sorting using vector, but 90% of it are int values stored in the vectors.
As IgorTandetnik said: you could do
std::sort(Vector.begin(), Vector.end(), [](const PointTwoD& a, const PointTwoD& b)
{
return a.getcivIndex() > b.getcivIndex();
});
which will use the result from the lambda to sort the vector and should do what you want.
To print the objects in the vector you should do something like this:
for(int i = 0; i < Vector.size(); i++)
{
std::cout << Vector[i] << std::endl; //Or whatever your printing function is.
}
Which will iterate over all the objects in the vector and, as they should already be in descending order from the sort, it will print them out in descending order like you wanted.
Edit:
For non C++11 users: you can define a function that does the comparison
bool compare(const PointTwoD& a, const PointTwoD& b)
{
return a.getcivIndex() > b.getcivIndex();
}
and use it instead of the lambda. Like this:
std::sort(Vector.begin(), Vector.end(), compare);
Use std::sort:
template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);
The first argument is an iterator to the first element you want to sort. The second argument is the final iterator position after sorting (in other words, one past the final element you want to sort). So to sort you would do this:
std::sort(Vector.begin(), Vector.end());
To determine how the sorting is actually performed, you need to define a < operator for PointTwoD that compares the civ index. Alternately you can create an external function that takes two PointTwoDs as parameters and returns a boolean, and specify it through the third argument to std::sort. If the sort function needs to access private members you'll need to declare it as a friend function in the class definition, though.
You can also inline the compare function in the std::sort call using a lambda if you want, like Phantom posted in his answer.
I have a list:
list<Student>* l;
and I would like to get an element at a specified index. Example:
l->get(4)//getting 4th element
Is there a function or method in list which enables it to do so?
std::list does not have a random access iterator, so you have to step 4 times from the front iterator. You can do this manually or with std::advance, or std::next in C++11, but bear in mind that both O(N) operations for a list.
#include <iterator>
#include <list>
....
std::list<Student> l; // look, no pointers!
auto l_front = l.begin();
std::advance(l_front, 4);
std::cout << *l_front << '\n';
Edit: The original question asked about vector too. This is now irrelevant, but may be informative nonetheless:
std::vector does have random access iterators, so you can perform the equivalent operation in O(1) via the std::advance, std::next if you have C++11 support, the [] operator, or the at() member function:
std::vector<Student> v = ...;
std::cout << v[4] << '\n'; // UB if v has less than 4 elements
std::cout << v.at(4) << '\n'; // throws if v has less than 4 elements
Here's a get() function that returns the _ith Student in _list.
Student get(list<Student> _list, int _i){
list<Student>::iterator it = _list.begin();
for(int i=0; i<_i; i++){
++it;
}
return *it;
}
If you want random access to elements, you should use a vector and then you can use [] operator to get the 4th element.
vector<Student> myvector (5); // initializes the vector with 5 elements`
myvector[3]; // gets the 4th element in the vector
For std::vector you can use
myVector.at(i) //retrieve ith element