Compare string before inserting into C ++ set

I am trying to compare a string before pasting into my set by comparing the length of a string. First insert the shortest string. I do not know what is going on, but some of the words are not included.

My code is:

#include <iostream>
#include <string>
#include <set>

struct compare {
    bool operator() (const string& a, const string& b) const{
        return a.size() < b.size();
    }
};

template<typename T>
void print(const T& t){
    for(auto& it : t)
        cout << it << endl;
}

int main() {    
    string word;
    set<string, compare> c;

    while(cin >> word)
        c.insert(word);

    print(c);

    return 0;
}

Here are the test words to insert

Apple
Apricots
Avocado
Durian
Fig
Tangerine/Clementine
Kumquat
Lemon
Pear
Prunes
Raspberries
Strawberries
Watermelon

and here is OUTPUT

Fig
Pear
Apple
Durian
Avocado
Apricots
Watermelon
Raspberries
Strawberries
Tangerine/Clementine

It works as expected, but apparently some words are missing for example:

Kumquat
Lemon
Prunes
+4
source share
5 answers

The first step is to simplify, in this case, remove the input as a potential reason. This indicates that the problem is not caused by the data source. So let's see if the values ​​are saved:

#include <iostream>
#include <string>
#include <set>

struct compare {
    bool operator() (const std::string& a, const std::string& b) const{
        return a.size() < b.size();
    }
};

template<typename T>
void print(const T& t){
    for(auto& it : t)
        std::cout << it << "\n";
}

template<typename T>
void insert(T& t, const char* value)
{
    t.insert(value);
    std::cout << "After inserting " << value << "\n";
    print(t);
    std::cout << "\n";
}

int main() {    
    std::set<std::string, compare> c;

    insert(c, "Apple");
    insert(c, "Apricots");
    insert(c, "Avocado");
    insert(c, "Durian");
    insert(c, "Fig");
    insert(c, "Tangerine/Clementine");
    insert(c, "Kumquat");
    insert(c, "Lemon");
    insert(c, "Pear");
    insert(c, "Prunes");
    insert(c, "Raspberries");
    insert(c, "Strawberries");
    insert(c, "Watermelon");

    print(c);

    return 0;
}

Values ​​are not saved, but it seems we can return to the problem:

    insert(c, "Apple");
    insert(c, "Lemon");

http://ideone.com/aGZOIN

std::set::insert , : http://www.cplusplus.com/reference/set/set/insert/

    auto result = t.insert(value);

. (1) false (0) .

http://ideone.com/wP4CaG

After inserting Apple. inserted? 1
Apple

After inserting Lemon. inserted? 0
Apple

, . std::set < :

if (!cmp(a, b))
    if (!cmp(b, a))
        // equal;

:

struct compare {
    bool operator() (const string& a, const string& b) const{
        if (a.size() < b.size())
            return true;
        if (a.size() == b.size() && a.compare(b) < 0)
            return true;
        return false;
    }
};

:

#include <iostream>
#include <string>
#include <set>

struct compare {
    bool operator() (const std::string& a, const std::string& b) const{
        if (a.size() < b.size())
            return true;
        if (a.size() == b.size() && a.compare(b) < 0)
            return true;
        return false;
    }
};

template<typename T>
void print(const T& t){
    for(auto& it : t)
        std::cout << it << "\n";
}

template<typename T>
void insert(T& t, const char* value)
{
    auto result = t.insert(value);
    std::cout << "After inserting " << value << ". inserted? " << result.second << "\n";
    print(t);
    std::cout << "\n";
}

int main() {    
    std::set<std::string, compare> c;

    insert(c, "Apple");
    insert(c, "Lemon");
    insert(c, "Fig");
    insert(c, "Kumquat");

    print(c);

    return 0;
}

http://ideone.com/Vs5p0i

:

After inserting Apple. inserted? 1
Apple

After inserting Lemon. inserted? 1
Apple
Lemon

After inserting Fig. inserted? 1
Fig
Apple
Lemon

After inserting Kumquat. inserted? 1
Fig
Apple
Lemon
Kumquat
+2

A std:: set . . , std:: multiset?

#include <iostream>
#include <string>
#include <set>

struct compare {
    bool operator() (const std::string& a, const std::string& b) const{
        return a.size() < b.size();
    }
};

template<typename T>
void print(const T& t){
    for(auto& it : t)
        std::cout << it << std::endl;
}

int main() {
    std::string word;
    std::multiset<std::string, compare> c; // multiset!!!

    while(std::cin >> word)
        c.insert(word);

    print(c);

    return 0;
}

:

Fig
Pear
Apple
Lemon
Durian
Prunes
Avocado
Kumquat
Apricots
Watermelon
Raspberries
Strawberries
Tangerine/Clementine

.. , . , , .

+4

. less, !less(a, b) && !less(b, a), , (, , ).

, , <. , :

set::set<int> s;
int x = 42, y = 42;
s.insert(x);
s.insert(y);

, , , x < y , y < x , x == y .

, , . N, N, , ( , ).

std::set<string, compare> s;
s.insert("abc");
s.insert("def");

less("abc", "def") less("def", "abc") , "abc" "def" .

, tie-break less, :

bool operator() (const string& a, const string& b) const{
    if (a.size() == b.size()) {
      return a < b;
    }
    return a.size() < b.size();
}

, , . , .

+3

, ?

, compare , - , :

, key_comp (.. , ).

key_comp(word1, word2) key_comp(word2, word1) false, , .

:

bool operator() (const string& a, const string& b) const {
    if (a.size() == b.size()) return a < b;
    return a.size() < b.size();
}

( ), ).

+2

. : , .

#include <vector>
#include <set>
#include <algorithm>
#include <iostream>

std::set<std::string> InsertByLength(std::vector<std::string> src)
{
  std::sort(src.begin(), src.end(), [](const std::string& a, const std::string& b)
            {
            return a.size() < b.size();
            });

  std::set<std::string> ret;
  for(auto s : src) {
    std::cout << s << std::endl;
    ret.insert(s);
  }

  return ret;
}

int main()
{
  auto result = InsertByLength({
    "Apple", "Apricots", "Avocado", "Durian", "Fig", "Tangerine/Clementine",
    "Kumquat", "Lemon", "Pear", "Prunes"  "Raspberries", "Strawberries",
    "Watermelon"});

  std::cout << "Inserted: " << result.size() << " elements\n";

  return 0;
}

http://ideone.com/d1T0ew

+1
source

All Articles