#c #stl #lower-bound
#c #stl #нижняя граница
Вопрос:
Я не могу понять, почему я получаю результат 200, тогда как, создав свою собственную функцию сравнения, я изменил условия, и результат должен быть 100.
#include <iostream>
#include <algorithm>
using namespace std;
bool compare(int a,int b){
return a<=b;
}
int main(){
int arr[]={1,2,5,10,20,50,100,200,500,2000};
int key=120;
int n=sizeof(arr)/sizeof(int);
int lb=lower_bound(arr,arr n,key,compare)-arr;
int x=arr[lb];
cout<<x<<endl;
return 0;
}
Комментарии:
1. lower_bound возвращает итератор, указывающий на первый элемент, который не сравнивается ниже искомого значения.
100 <= 120
,!(200 <= 120)
, он возвращает указатель на200
. Почему вывод должен быть 100?2. Вы не изменили условие, но ваша функция сравнения нарушена — она завершится ошибкой при поиске точного соответствия.
Ответ №1:
в то время как, создав свою собственную функцию сравнения, я изменил условия
Это не то, что вы compare
делаете. Вы только что изменили сравнение, но таким образом, что по-прежнему 200
является первым элементом, для которого compare
возвращается false
.
Если вы хотите получить 100
, вы можете использовать std::prev
, чтобы получить предыдущий элемент, на который указывает lower_bound
:
auto it = std::prev(lower_bound(std::begin(arr),std::end(arr),key), 1);
и теперь *it
будет 100
.
Если вам нужен индекс этого элемента, вы можете использовать std::distance
так:
int index = std::distance(std::begin(arr), it);
Вот демонстрация.
Обратите внимание, что вы должны учитывать тот факт, что lower_bound
может возвращать итератор в начало диапазона, и в этом случае вы не можете этого сделать std::prev
.
Комментарии:
1. Кроме того, хотя это не влияет на функциональность кода, поскольку
lower_bound
возвращает итератор, вам не нужно проходить арифметику указателей, а затем обращаться к массиву. Вы можете просто разыменовать возвращаемое значение илиstd::prev
возвращаемое значение или что у вас есть, если только вам не нужен индекс массива специально. (Он не используется в примере кода аскера, но может иметь отношение к их полному применению.)2. @NathanPierson Хорошая мысль. Я выделил итератор и индекс, поэтому OP может использовать то, что подходит.