C ++: набор C-строк - PullRequest
       6

C ++: набор C-строк

2 голосов
/ 25 декабря 2010

Я хочу создать так, чтобы я мог проверить, есть ли определенное слово в наборе, используя set :: find

Однако C-строки являются указателями, поэтому набор будет сравнивать их по значениям указателя по умолчанию. Для правильного функционирования необходимо разыменовать их и сравнить строки.

Я мог бы просто передать конструктору указатель на функцию strcmp () в качестве компаратора, но это не совсем то, как я хочу, чтобы он работал. Слово, которое я хотел бы проверить, может быть частью более длинной строки, и я не хочу создавать новую строку из-за проблем с производительностью. Если бы не было набора, я бы использовал strncmp (a1, a2, 3), чтобы проверить первые 3 буквы. На самом деле, 3, вероятно, самое длинное, что может быть, поэтому я согласен с константой третьего аргумента.

Есть ли способ создать набор, который бы сравнивал его элементы, вызывая strncmp ()? Примеры кода будут с благодарностью.

Вот псевдокод того, что я хочу сделать:

bool WordInSet (string, set, length)
{
   for (each word in set)
    {
       if strncmp(string, word, length) == 0
            return true;
    }
    return false;
}

Но я бы предпочел реализовать это, используя стандартные библиотечные функции.

Ответы [ 3 ]

6 голосов
/ 25 декабря 2010

Вы можете создать объект функции сравнения.

struct set_object {
    bool operator()(const char* first, const char* second) {
        return strncmp(first, second, 3);
    }
};

std::set<const char*, set_object> c_string_set;

Однако было бы намного проще и надежнее создать набор из std::strings.

2 голосов
/ 25 декабря 2010

Сделать функцию-обертку:

bool myCompare(const char * lhs, const char * rhs)
{
    return strncmp(lhs, rhs, 3) < 0;
}
0 голосов
/ 25 декабря 2010

Предполагая, что постоянное значение в качестве длины слова выглядит для меня проблемой. Я рекомендую против этого решения.

Посмотрите: strcmp решение не работает для вас, потому что оно обрабатывает const char* аргументы как строки с нулевым символом в конце . Вам нужна функция, которая делает то же самое, но обрабатывает аргументы как words - что переводит в «что-нибудь-не-буква» -определенную строку.

Можно определить strcmp в общем виде как:

template<typename EndPredicate>
int generic_strcmp(const char* s1, const char* s2) {
    char c1;
    char c2;
    do { 
        c1 = *s1++; 
        c2 = *s2++; 
        if (EndPredicate(c1)) {
            return c1 - c2; 
        }
    } while (c1 == c2);

    return c1 - c2; 
}

Если EndPredicate - это функция, которая возвращает истину, если ее аргумент равен \0, то мы получаем регулярный strcmp, который сравнивает строки с 0-символами в конце.

Но для того, чтобы иметь функцию, которая сравнивает слова, единственное требуемое изменение - это предикат. Достаточно использовать инвертированную функцию isalpha из заголовочного файла <cctype>, чтобы указать, что строка заканчивается, когда встречается не алфавитный символ.

Так что в вашем случае ваш компаратор для набора будет выглядеть так:

#include <cctype>

int wordcmp(const char* s1, const char* s2) {
    char c1;
    char c2;
    do { 
        c1 = *s1++; 
        c2 = *s2++; 
        if (!isalpha(c1)) {
            return c1 - c2; 
        }
    } while (c1 == c2);

    return c1 - c2; 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...