Jump to content
  • Advertisement
Sign in to follow this  
FGFS

search container

This topic is 2138 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi

how to modify so that it returns any containing the search string id? As below it only returns if all 4 letters are ok and the airport is found. But i would

like to show all for ex. A returns all airports beginning with A, AB etc. until only one left if all 4 chars are ok.

airportmap is defined as: typedef map<string, Airport*> AirportMap;

Many thanks

 

Airport* SDatabase::getAirport(const std::string &id)
{
    AirportMapIterator i = m_airport_map.find(id);
    if(i != m_airport_map.end())
        return (Airport*)(*i).second;
    else
        return NULL;
};

Share this post


Link to post
Share on other sites
Advertisement

Sounds like a job for regular expressions. Maybe theres a better way already implemented in the map but this seems to work:

#include <iostream>
#include <map>
#include <vector>
#include <regex>
#include <sstream>

using namespace std;

class Airport
{
	private:
		string _name;
	public:
		Airport(string name):_name(name)
		{
		}
		string GetName()
		{
			return _name;
		}
};

map<string, Airport*> airports;

std::vector<Airport*> getAirports(string searchTerm)
{
	std::vector<Airport*> matchingAirports;
	for (auto it = airports.begin(); it != airports.end(); it++)
	{
		auto mapEntry = (*it);

		stringstream ss;
		ss << ".*" << searchTerm << ".*";
		regex regEx(ss.str().c_str(), regex_constants::icase);

		if(regex_match(mapEntry.first, regEx))
		{
			matchingAirports.push_back(mapEntry.second);
		}
	}
	return matchingAirports;
}

int main()
{   
	Airport one("London Heathrow");
	Airport two("Tokyo International");
	Airport three("Los Angeles International");
	airports.insert(make_pair(one.GetName(), &one));
	airports.insert(make_pair(two.GetName(), &two));
	airports.insert(make_pair(three.GetName(), &three));

	string searchTerm;

	while(true)
	{
		cout << "Please enter a name to look for, 'exit' to quit: " << endl;

		getline(cin, searchTerm);

		if(searchTerm.find("exit") != -1)
		{
			break;
		}

		auto foundAirports = getAirports(searchTerm);

		cout << foundAirports.size() << " airports found: " << endl;

		for (auto it = foundAirports.begin(); it != foundAirports.end(); it++)
		{
			auto airport = (*it);

			cout << " - " << airport->GetName() << "\n";
		}
	}

	system("pause");
}

If you search for "dOn HeatHR" it will find London Heathrow.

Of course you can change how exactly you want it to match at this line:

ss << ".*" << searchTerm << ".*";

Here's a good reference for regular expressions:

http://msdn.microsoft.com/en-us/library/az24scfc.aspx

Hope this helps :)

Share this post


Link to post
Share on other sites

Trying to integrate it. I need it to return a string hence I try:

 

           std::string str(passendeAirports.begin(), passendeAirports.end());
           return str;

 

with the error:

/basic_string.h:384:6: error: invalid conversion from ‘Airport*’ to ‘std::char_traits<char>

 

Also I'm unshure on how to use the Airport class:

---------

class Airport : public Waypoint
{
public:

    Airport();

    Airport(const QString& id, const QString& name,
            const double& lat, const double& lon, int elevation_ft);

    virtual ~Airport() {};

    virtual Waypoint* deepCopy() const { return new Airport(*this); }

    inline virtual const Airport* asAirport() const { return this; }
    inline virtual Airport* asAirport() { return this; }

    virtual QString toString() const;
...

 

--------

What does asAirport or deepCopy etc. return? Maybe I could use:

    virtual QString toString() const;

How? Many thanks again

 

Share this post


Link to post
Share on other sites

If passendeAirports is a container, passendeAirports.begin() will just return a pointer to the first element I think.

So it wouldn't make sense to make a string out of a pointer to an Airport. Or maybe I just don't know everything that strings are capable of :P

Do you want to return a string like this: "Airport1, Airport2, Airport3"?

If so I would say use a stringstream:

stringstream ss;
for (auto it = foundAirports.begin(); it != foundAirports.end(); it++)
{
    auto airport = (*it);

    ss << airport->GetName();
    if(airport != foundAirports.back())
        ss << ", ";
}

return ss.str();

For your asAirport and deepCopy I would suggest using dynamic_cast and the copy constructor instead and not return something with new, because you will have to call delete on it, the problem is that this wouldn't be obvious, you might forget to call delete because you don't see any "new" in your code where you use this method.

Try it like this instead for copying:

// Copy constructor
Airport(const Airport& copyFrom):
	id(copyFrom.id),
	name(copyFrom.name),
	lat(copyFrom.lat),
	lon(copyFrom.lon),
	elevation_ft(copyFrom.elevation_ft)
{
}
// Somewhere else in the code
Airport newAirport(otherAirport);
// Or
Airport* newAirport = new Airport(otherAirport);

If you don't provide a copy constructor the compiler will generate one for you automatically, but I'm not sure how exactly it does the copying, maybe just like my example, so you wouldn't need to write your own unless you have pointers in your class. You don't really want two objects pointing to the same thing. You would need to create a copy for your copy. Well, you can look up copy constructors yourself, if this interests you :)

As for the dynamic_cast, that would look like this:

Waypoint* waypoint = new Waypoint();
Airport* airport = dynamic_cast<Airport*>(waypoint);
// You can't convert a base class to a derived, so this will fail, meaning airport will be 0 or nullptr.

Waypoint* waypoint = new Airport("London");
Airport* airport = dynamic_cast<Airport*>(waypoint);
// This will work because the object waypoint points to is indeed an Airport. So airport will be a valid pointer.

I hope I'm not explaining everything wrong here, I'm not an expert either sorry :)

But I think it should be correct... hopefully.

Share this post


Link to post
Share on other sites

Horscht, what lib are you linking for regex? I'm on Ubuntu, but should later be crossplatform.

Thanks.

Share this post


Link to post
Share on other sites
My Linux experience is limited but you do not need special link flags using MinGW. It's part of the standard library after all. Are you certain you are getting linker errors? It's far more likely you are getting compiler errors, either because your compiler does not support C++11 or you need to switch it on with an explicit flag.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!