Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
2 / 2 / 4
Регистрация: 24.03.2016
Сообщений: 75

Поиск по вектору

31.10.2018, 13:51. Показов 3738. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
есть структура. нас интересует первый элемент fntname остальные не важны
C++
1
2
3
4
5
6
typedef struct 
{
    char fntname[30];
    XmFontList fntlist;
    VertFont *vfont;
} WFONT;
на ее основе делается класс

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class WidgetCommon
{
private:
 
    vector <WFONT *> wcpnt;
 
public:
 
    WidgetCommon()
    {    };
 
    ~WidgetCommon() {clear(); }
 
 
   WFONT *findFont(char *name)
    {
...
    }
 
 
    void clear(void)
    {
        for (vector<WFONT *>::iterator iter=wcpnt.begin(); iter!=wcpnt.end(); iter++)
            delete (*iter);
        wcpnt.clear();
 
    }
 
};
нужно реализовать поиск в векторе
для этого создаю

C++
1
2
3
4
    WFONT *findFont(char *name)
    {
        return *std::find_if( wcpnt.begin(), wcpnt.end(), name );
    }
но при сборке выдает ошибку ошибка: expression cannot be used as a function
{ return bool(_M_pred(*__it)); }
^

я так понимаю что проблема с оператором сравнения ==? т.к. пытаюсь сравнивать типы WFONT* и char*

как реализовать поиск чтобы все заработало?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
31.10.2018, 13:51
Ответы с готовыми решениями:

Поиск, Сортировка по Вектору в с++
Не могу разобраться как обратится к элементу класса например name. в векторе groupArray. Из за этого не могу реализовать поиск по имени,...

Поиск строки по вектору
Добрый день. Помогите разобраться с проблемой пожалуйста: я перегоняю данные из бинарного файла в вектор (так нужно по заданию), затем мне...

Поиск по вектору не работает
Есть класс и контейнер-вектор, надо отсортировать контейнер вектор,выполнить поиск #include &lt;iostream&gt; #include &lt;vector&gt; ...

14
261 / 111 / 53
Регистрация: 22.01.2017
Сообщений: 448
31.10.2018, 14:07
amd-hoja, неправильный 3-ий аргумент функции. Пример:
C++
1
2
3
4
5
6
7
8
9
bool compare(char *name)
{
    return name == currentName;
}
 
WFONT *findFont(char *name)
{
    return *std::find_if(wcpnt.begin(), wcpnt.end(), compare);
}
Один из вариантов, создать поле currentName и там хранить искомое имя
0
2 / 2 / 4
Регистрация: 24.03.2016
Сообщений: 75
31.10.2018, 14:29  [ТС]
нет. в векторе хранятся загруженные данные. нужную запись ищем по имени char *name.
поиск будет WidgetCommon::findFont(name);
нужна именно такая реализация.

создавать отдельное поле где то бесмысленно.

вроде где то читал что требуется перегрузка оператора ==. но это было давно и найти как это реализовать в данном случае не смог сейчас
0
261 / 111 / 53
Регистрация: 22.01.2017
Сообщений: 448
31.10.2018, 14:56
amd-hoja, лучше не использовать алгоритм find_if. Делайте поиск в цикле.
0
2 / 2 / 4
Регистрация: 24.03.2016
Сообщений: 75
31.10.2018, 15:05  [ТС]
через итератор?

пробовал. но самое смешное что тоже ошибка
0
261 / 111 / 53
Регистрация: 22.01.2017
Сообщений: 448
31.10.2018, 15:18
amd-hoja, правильно сравнивали? У вас вектор типа WFONT. Имя для первого элемента:
C++
1
2
WFONT *obj = wcpnt[0];
char *name = obj->fntname;
В функции такая же ошибка наблюдается
0
2 / 2 / 4
Регистрация: 24.03.2016
Сообщений: 75
31.10.2018, 15:36  [ТС]
не совсем так не WFONT а WFONT* т.е. в векторе хранятся ссылки.

и зачем мне первый элемент таким образом?


и кстати вот с итератором

C++
1
2
3
4
5
6
    WFONT *findFont(char *name)
    {
        std::vector<WFONT*>::iterator it = std::find_if (wcpnt.begin(), wcpnt.end(), name);
        if(*it!=wcpnt.end())
            //нашел
    }
ошибка таже самая что и начале.
0
166 / 109 / 57
Регистрация: 30.08.2018
Сообщений: 357
31.10.2018, 15:39
Лучший ответ Сообщение было отмечено amd-hoja как решение

Решение

Цитата Сообщение от n1b1ru Посмотреть сообщение
лучше не использовать алгоритм find_if. Делайте поиск в цикле.
да ладно ..
C++
1
2
3
4
5
6
7
8
9
10
WFONT *findFont(char *name)
    {
       auto w = std::find_if(wcpnt.begin(), wcpnt.end(),
                [name](std::vector <WFONT *>::value_type wfont){
            return ! strcmp(wfont->fntname, name);
        });
        if(w != wcpnt.end())
            return *w;
        return nullptr;
    }
1
2 / 2 / 4
Регистрация: 24.03.2016
Сообщений: 75
31.10.2018, 15:41  [ТС]
оу. заработало))) спасибо огромное.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
31.10.2018, 15:59
amd-hoja, причем здесь какое-то "отдельное поле"?

В данном случае перегрузка operator== для класса WFONT Вам не поможет, т.к. find_if использует для сравнения переданный функтор, а не переданный объект. А алгоритм find тоже не поможет, т.к. будет производить поиск указателя, а не объекта. Можно нагородить костылей для сравнения объекта типа WFONT с указателем, но это будет сомнительным решением, так что не буду на нем останавливаться.

Вы можете передать в find_if указатель на функцию сравнения, как предложили выше:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
bool compare(WFONT const * font)
{
    return strcmp(font->fntname, "Name") == 0;
}
//...
WFONT * findFont(char *name)
{
    auto it = std::find_if(wcpnt.begin(), wcpnt.end(), compare);
    if (it != wcpnt.end()) {
        return *it;
    }
    return nullptr;
}
В таком случае для поиска каждого имени надо будет писать отдельную функцию, что не есть хорошо. Так получается из-за того, что функция не хранит состояние. Однако, состояние могут хранить объекты классов.

Приведу краткое "отсебятное" описание концепции функциональных объектов.
Если кратко, то функциональный объект (функтор) - это объект класса с перегруженным operator(), и который,
соответственно, можно "вызывать" (поддерживает синтаксис вызова):

C++
1
2
3
4
5
6
7
8
9
10
struct MyFunctor
{
    void operator()() {
        std::cout << "Hello" << std::endl;
    }
};
//...
MyFunctor f;
f();//Синтаксически выглядит как вызов функции
//Будет выведен текст "Hello"
Так как вызов функции и вызов operator() функтора синтаксически одинаковы, то это часто используют в шаблонах, например:

C++
1
2
3
4
5
6
7
8
9
template<typename T>
void foo(T func)
{
    if (func()) {
        std::cout << "yes" << std::endl;
    } else {
        std::cout << "no" << std::endl;
    }
}
В этом коде в foo можно передать как указатель на функцию, так и функтор. В данном случае функтор или функция обязаны уметь вызываться без параметров и возвращать нечто, что может быть расценено как bool.
Функтор/функцию, возвращающую нечто, что можно использовать как bool используют как предикат (и называют тоже предикатом).

Очевидно, что предикат может принимать параметры.
Предикат, принимающий один параметр - унарный предикат.
Предикат, принимающий два параметра - бинарный предикат.

Так вот, find_if в качестве третьего параметра принимает унарный предикат, и использует его результат как сигнал о нахождении заданного значения. То есть возвращается итератор указывающий на объект, для которого предикат вернул true.

Если состряпать "на коленке" свой find_if, то получим нечто вроде:

C++
1
2
3
4
5
6
7
template<typename T, typename F>
T find_if(T first, T last, F pred)
{
   for (; first != last && !pred(*first); ++first) {//Выход в конце последовательности или если предикат вернул true
   }
   return first;//Вернет либо итератор на найденный элемент, либо last
}
Что же передать в find_if в вашем случае. Например, можно передавать объект такого типа:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class cmp_with_name
{
public:
   cmp_with_name(std::string name): m_name(std::move(name)) {} //Сохраняем в объекте искомое имя
   bool operator()(WFONT const * pfont) const noexcept {
       return m_name == pfont->fntname; //Сравниваем сохраненное имя с именем переданного шрифта
   }
   bool operator()(WFONT const & pfont) const noexcept {//Можно еще версию с ссылкой на шрифт добавить
       return m_name == pfont.fntname;
   }
private:
   std::string m_name;
};
//...
WFONT * findFont(char const * name)
{
    auto it = std::find_if(wcpnt.begin(), wcpnt.end(), cmp_with_name(name));
    if (it != wcpnt.end()) {
        return *it;
    }
    return nullptr;
}
Вместо создания отдельного класса можно воспользоваться лямбдой:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
WFONT * findFont(char const * name)
{
    auto it = std::find_if(
        wcpnt.begin(), 
        wcpnt.end(), 
        [name](WFONT const * font) { 
            return !strcmp(font->fntname, name); 
        }
    );
    if (it != wcpnt.end()) {
        return *it;
    }
    return nullptr;
}
В данном случае компилятор сам сгенерирует нужный тип на основе лямбды.

Вот как-то так можно решить Вашу проблему с помощью find_if.


P.S. Всё писалось прямо в редакторе на форуме, так что могут быть какие-то ошибки в коде.
4
2 / 2 / 4
Регистрация: 24.03.2016
Сообщений: 75
31.10.2018, 16:02  [ТС]
спасибо и ваш вариант подходит. посмотрю какой вариант лучше для моего случая. ваш вариант (не лямбда) сложнее но вроде понятнее для мозга)))
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
31.10.2018, 16:06
Цитата Сообщение от amd-hoja Посмотреть сообщение
но вроде понятнее для мозга
Если убрать оттуда нововведения C++11, то только такой вариант и был доступен ранее.
Вот чтобы не городить тьму таких типов используют лямбда-выражения, добавленные в C++11.
По лямбда-выражению компилятор сам генерирует тип (либо функцию, если возможно) с перегруженным operator().
Но в основе всё равно лежит концепция функциональных объектов.
0
31.10.2018, 17:04

Не по теме:

Цитата Сообщение от JaponDemon Посмотреть сообщение
да ладно ..
Вырываем слова из контекста... Красиво

0
31.10.2018, 17:11

Не по теме:

n1b1ru, это же всё сообщение целиком.

0
261 / 111 / 53
Регистрация: 22.01.2017
Сообщений: 448
31.10.2018, 17:37

Не по теме:

Croessmah, это я в ответ на мой 4 пост, который был продолжением диалога



Добавлено через 14 минут
Цитата Сообщение от amd-hoja Посмотреть сообщение
и кстати вот с итератором
Вот что я имел ввиду под циклом:
C++
1
2
3
4
5
6
for(unsigned int i = 0; i < wcpnt.size(); ++i)
{
    WFONT *obj = wcpnt[i];
    if(obj->fntname == name)
        return obj;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.10.2018, 17:37
Помогаю со студенческими работами здесь

Поиск по вектору с возвращением номера
привет. чтобы найти элемент в vector пользуюсь функцией find() из &lt;algorythm&gt;. он возвращает итератор. а существует ли способ возвращения...

Поиск по вектору наименьшего отсутствующего элемента
В общем, есть вектор, в нем хранятся значения типа &lt;unsigned int&gt;. Как за наименьшее количество проходов по вектору найти наименьший...

Не работает поиск по вектору и функция sort
Пишу программу которая должна иметь возможность поиска записи о студенте по имени, но при выполнении функции void poisc() не выдаёт...

Поиск кватерниона по конечному вектору и имеющемуся кватерниону
Доброго времени суток! Что имеется: IMU плата, опорная точка в пространстве. При старте у платы возвращается свой кватернион поворота, но...

Движение по вектору
Добрый день! Есть такой вопрос по матлабу: имеется 2 вектора: x =; y =; Можно ли реализовать движение по данному вектору...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru