Как отсортировать вектор ?

#c #string #sorting #vector

#c #строка #сортировка #вектор

Вопрос:

 #include <algorithm>

bool comparisonFunc(char* c1, char* c2)
{
     return strcmp(c1, c2) ? 0 : 1;
}

vector<char*> myVec;
vector<char*>::iterator itr;
sort(myVec.begin(), myVec.end(), comparisonFunc)
 

Это правильно или есть лучший способ сделать это?

Комментарии:

1. itr кажется, он не используется. И strcmp(...) ? 0 : 1 было бы написано более идиоматично !strcmp(...) . Но я не знаю ответа на ваш настоящий вопрос.

2. @user1002288 Почему вы не используете std::sort(myVec.begin(), myVec.end(), ::strcmp); directlt?

3. Примечание: strcmp возвращает -1, 0 или 1 в зависимости от того, является ли c1 <, = или> c2 . Следовательно, вам нужно strcmp(lhs, rhs) < 0 выполнить сортировку меньше, чем.

Ответ №1:

std::sort ожидает предикат «меньше». Вы должны реализовать свой comparisonFunc() подобный:

 bool comparisonFunc(const char *c1, const char *c2)
{
    return strcmp(c1, c2) < 0;
}
 

(Обратите const внимание на буквы s; они важны.)

Ваша текущая реализация не может работать, потому что вы просто возвращаете, если значения равны или нет. Этой информации недостаточно для сортировки — вам нужно знать, какой из них меньше, а какой больше (если, конечно, значения не равны).

Комментарии:

1. почему const здесь важен?

2. std::sort никогда не позволит вам изменять содержимое контейнера, когда он просто хочет знать, какой из них меньше.

3. Как насчет bool comparisonFunc(const char* c1, const char* c2) const {} ?

4. Почему не std::sort(myVec.begin(), myVec.end(), ::strcmp); напрямую?

5. strcmp() не менее. Его нельзя использовать непосредственно в качестве предиката для упорядочения.

Ответ №2:

В современном C вы можете определить метод сравнения встроенным:

 std::vector<const char*> strings;
/* fill strings vector */
std::sort(strings.begin(), strings.end(), [](const char* lhs, const char* rhs) {
    return strcmp(lhs, rhs) < 0;
});
 

Обратите внимание, что strcmp возвращает -1/0/ 1 чтобы указать на ординарность, отсюда < 0 и сравнение.

Ответ №3:

Я чаще хочу отсортировать вектор указателя на записи, чем просто C-строки…

     template<>
    struct std::less<const foo*>
    {
       bool operator()(const foo* lhs, const foo* rhs) const
       {
          return strcmp(lhs->key, rhs->key);
       }
    };
 

Это переопределяет сравнение foo* таким образом, что сравнение по умолчанию работает при сортировке. Для меня этот стиль кажется более декларативным, другой — более процедурным. Если вам нужно несколько упорядочений, это использование значения по умолчанию проблематично; если вы хотите быть уверены, что все упорядоченные коллекции foo* s находятся в одном и том же порядке, это хорошо.

 std::vector<foo*> db;
std::sort(db.begin(), db.end());
 

Комментарии:

1. Ты не имеешь в виду return strcmp(...) < 0; ?

2. ИМО, это довольно проблематично. Вы создаете foo_p1 < foo_p2 и std::less<const foo*>()(foo_p1, foo_p2) ведете себя по-разному, и, кроме того, последнее имеет другой результат, чем std::less<foo*>()(foo_p1, foo_p2) .

3. … и стандарт, похоже, даже не предполагает, что алгоритмы сортировки должны использовать std::less по умолчанию. Ваш фрагмент полон ошибок и в конце дня вообще не будет работать.

4. Извините, я не прав в strcmp(). Что говорит стандарт о том, где он находит значение по умолчанию для T < T ? Может ли это быть … std::less(T) ?

5. Определение operator< для элементов, не относящихся к классу, таких как T*, настолько проблематично, насколько это возможно. Вот как это возможно .