having a hard time comparing two different types

Hello, I am to search through the gamers vector to find if the names match, say which index it is at and then insert but they are both different types and both private so i am having quite an issue. I am not to use custom loops(for,if,ect) and have to compare both but I am having a really hard time.

1
2
3
4
5
6
7
8
9
10
11
class Tournament
{
private:
vector<Games>Gamers;
int FindGamers(const std::string& name);
:
int FindGamers(const std::string& name)
{
don't know how to search through different types but know i have to 
insert to put it back into vector.
} 
Last edited on
I don't think there's really enough information to help you.

If you're defining FindGamers outside of the class definition itself, it needs to be written like
1
2
3
4
int Tournament::FindGamers(const std::string& name)
{
    // ...
}


class member functions can access private member variables (e.g. Gamers).

_________________________

Are you saying that you aren't allowed to use basic loops and if statements? That makes no sense, are you sure you've read the directions correctly?

_________________________

Here's a perhaps slightly over-engineered example:
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>

class Gamer {
  public:
    std::string name;
};

/// Used by std::find to find a gamer based on their name
bool operator==(const Gamer& gamer, const std::string& name)
{
    return gamer.name == name;   
}

class Tournament
{
  public:
    Tournament(const std::vector<Gamer>& gamers)
    : gamers(gamers)
    { }

    int FindGamer(const std::string& name);
    
  private:
    std::vector<Gamer> gamers;
};

// Returns index of name if found,
// -1 otherwise
int Tournament::FindGamer(const std::string& name)
{  
    auto iter = std::find(gamers.begin(), gamers.end(), name);
    if (iter != gamers.end())
    {
        return std::distance(gamers.begin(), iter);
    }
    return -1; // -1 meaning "not found"
} 

int main()
{
    Tournament tourn( { {"Alice"}, {"Bob"}, {"Charlie"}, {"Eve"} } );
    
    int index = tourn.FindGamer("Charlie");
    if (index != -1)
    {
        std::cout << "Charlie found!\n";   
    }
    else
    {
        std::cout << "Charlie didn't show up...\n";   
    }
}


I could make it not have if-statements but this just seems silly.
Last edited on
it's specifically for my current assignment, they don't want me changing any function or using loops at all. only for_each and stuff
Since FindGamers() is a method of Tournament, it has access to Tournament::Gamers. In other words, you don't have to worry about Gamers being private.

Please provide the definition of class Games. Also, explain what it means for a (string) name to match an instance of Games.

I am to search through the gamers vector to find if the names match, say which index it is at and then insert

I think you're saying that FindGamers returns the index of vector "Gamers" that matches the parameter "name". If "name" doesn't match any existing value in "Gamers" then it should insert a new value and return the index of that new value. Do I understand correctly?
they don't want me changing any function

That is not exactly true. If it were, you were not allowed to write anything. Not even the FindGamer().

Perhaps there are some functions that you are supposed to use as is within the code you have to write. You did not show them.

they are both different types

Who?
The std::vector<Games> Tournament::Gamers and std::string name?

both private

Let me guess, a Games has a name. What is the interface of the Games?
(The "stuff" they provide and you are not allowed to change.)

i have to insert to put it back into vector.

Insert what? Into vector Gamers, I presume, but what? Into which point in vector?

If tournament already has Alice, then add another Alice Games?


EDIT: Ahh, you had another thread and "solved" your issue in there:http://www.cplusplus.com/forum/beginner/262128/
Last edited on
@dhayden that is exactly it!
and @keskiverto. I cannot change the function provided, i can of course put in code into the function, but not change it in any way, that is what the instructions were, which is why I was having a problem which is also why i created a thread which i double checked with the professor. So adding Tournament::FindGamers(const std::string& name) will not work... which is why I've been having a problem because I cannot seem to be able to compare the Gamers with the name
I have to sift through the Gamers, find the similar names, if similar, show the index, if not, make a new gamer and insert it in gamer vector
Last edited on
I cannot change the function provided

How could we tell how to use what you have if you don't show what has been provided to you?

Same goes for the class Games. If you don't show it, then we can't help you with it.

if similar, show the index
if not, make a new gamer and insert it

1. int FindGamers() always returns an index
2. Does it matter, where in vector you do insert?
ok
Last edited on
If you don't want to provide details, then getting a hint won't really be possible.

Call your doctor on the phone and say "I don't feel normal" and nothing else. See how far you get being treated.
yes
Last edited on
In your latest code shouldn't FindOrInsertPlayer() be a member function of the Glicko class? I see this function defined in the class definition (line 39).

Now we are talking. The essentials (now that we can see what is and what is not):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Player
{
public:
  Player( const std::string& name = "", double r = INITIAL_RATING,
    double rd = INITIAL_DIFFERENTIAL, double v = INITIAL_VOLATILITY );

  std::string Name() const;
};

class Glicko
{
  std::vector<Player> m_Players;
  int FindOrInsertPlayer( const std::string& name );
};

From that we do see that you can create a Player from a string. For example:
1
2
std::string john = "Doe";
Player bob( john ); // public and legal 

Furthermore, we can read the name of the Player.
1
2
Player mary_sue;
if ( mary_sue.Name() == john ) std::cout << "Hello Dolly!\n";

However, we cannot compare Player to string directly:
1
2
if ( mary_sue == john ) // error: no operator== for <Player> and <std::string>
  std::cout << "Hello Dolly!\n";


Ganado did already give a hint about finding, but std::find depends on operator==.
Hint 2: http://www.cplusplus.com/reference/algorithm/find_if/

A trivial way to write predicate today is lambda.
Hint 3: https://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11


Insertion to end, hint 4: http://www.cplusplus.com/reference/vector/vector/emplace_back/
// TODO Without writing a custom loop
What an asinine requirement. I appreciate your prof's desire to force you to use parts of the standard library, but in this case it just gets in the way.

Since FindOrInsertPlayer() is private, I think Professor Makework wants you to call it from LoadPlayers().

To avoid a custom loop, I used std::find_if(). find_if() requires that third argument that takes a single parameter: an iterator that points to an item. Since we want to compare that item's name to a string, I created a class called EqualName to store the string and handle the function call operator:

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
class EqualName
{
public:
    EqualName(const std::string &s) : name(s) {}
    std::string name;
    bool operator()(const Player &p) {
        return p.Name() == name;
    }
};

int Glicko::FindOrInsertPlayer(const std::string& name)
{
        //      TODO Without writing a custom loop, Search the m_Players
        //      vector to find the desired name If the player is
        //      found, return the index for the element in the vector
        //      If the player is not found, create a new player,
        //      insert it at the end of the vector and return the
        //      index for the newly inserted item

    EqualName pred(name);
    std::vector<Player>::iterator iter;
    iter = find_if(m_Players.begin(), m_Players.end(), pred);
    if (iter == m_Players.end()) {
        m_Players.emplace_back(name);
        iter = m_Players.end()-1;
    }
    return iter - m_Players.begin();
}


To show why this is dumb, here's a simpler implementation. No auxilliary predicate class needed, no iterator arithmetic, just a dirt-simple for loop.
1
2
3
4
5
6
7
8
9
10
11
int Glicko::FindOrInsertPlayer(const std::string& name)
{
    unsigned i;
    for (i=0; i< m_Players.size(); ++i) {
        if (m_Players[i].Name() == name) break;
    }
    if (i == m_Players.size()) {
        m_Players.emplace_back(name);
    }
    return i;
}
you guys are awesome! thank you so much. Yeah it would be quite easier to write a bunch of loops. i'm gonna give it a go, but that makes a lot more sense. thank you guys again
Topic archived. No new replies allowed.