#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*, настолько проблематично, насколько это возможно. Вот как это возможно .