How to sort a vector of objects by string variable alphabetically

I cannot figure out how to sort a vector of objects using one of the VIN member variables that is of data type string

. I have to either do bubble sort or sort. I'm most familiar with bubble sort, so that's the direction I tried to take. However, I know that I need to compare both strings by making them uppercase or lowercase. Be aware that strings will also contain numeric characters.

So my question is 1) How to convert the string to either all lowercase or all ASCII numbers and 2) What datatype the temporary variable should have (class datatype or some other datatype).

Here is the (incomplete) code I have so far:

    void sortInventory(vector<Vehicle> &carList)
    {
        bool swap; 
        string temp; 
        do
        {
            swap = false;

            for (int count = 0; count < carList.size(); count++)
            {
                if (carList[count].getVIN() > carList[count + 1].getVIN())
                {
                    temp = carList[count].getVIN();                                 
                    carList[count].getVIN() = carList[count + 1].getVIN();          
                    carList[count + 1].getVIN() = temp;                      
                    swap = true;                                               
                }
            }

        } while (swap);
}

      

Here is my class declaration:

class Vehicle
{
private:
    string VIN;

public:
    string getVIN();
    void   setVIN(string);

};

      

Here is my implementation of the class:

string Vehicle::getVIN()
{   return VIN;     }

void Vehicle::setVIN(string input)
{   VIN = input;    }

      

Thank!

+3


source to share


3 answers


You can do std::sort(carList.begin(),carList.end(),vehicleCompare)

where vehicleCompare

is the comparison function you are defining. See sorting documentation . Then to uppercase you can use std :: toupper as shown in this tutorial .

std::string myToUpper(std::string in) {
    std::transform(in.begin(), in.end(),in.begin(), ::toupper);
    return in;
}

      

So the comparison operator (*) would be:

bool vehicleCompare (const Vehicle a, const Vehicle b) {
    const std::string a_name = myToUpper(a.getVIN());
    const std::string b_name = myToupper(b.getVIN());
    return (a_name < b_name);
    }

      

Helpful read on string comparison operator .

By the way, your method string getVIN()

must be const

, that is, you must change its declaration to string getVIN() const

.

If you want to keep your sorting function, the point is that you will need to define the correct comparison operator anyway, as shown here.


To answer your second question, temp

maybe auto

in C ++ 11 or just std::string

. Then the wrong way to specify the value VIN

. Given the interface provided, it should be:



auto temp = carList[count].getVIN();                                 
carList[count].setVIN(carList[count + 1].getVIN() );          
carList[count + 1].setVIN(temp);

      

Although it can still get in trouble when you start copying more than one member variable: instead, you should build a copy constructor and change your code to:

auto temp = carList[count]; //you can use Vehicle instead of auto as type
carList[count] = carList[count + 1];          
carList[count + 1] = temp;

      

The copy constructor would be:

Vehicle(const Vehicle& in) 
  : VIN(in.getVIN() ) 
  {}

      

And at this point, you also need a string constructor and an empty constructor.

Vehicle(std::string& inVIN) 
  : VIN(inVIN) 
  {}

Vehicle(const Vehicle& in) 
  {} //All input members get initialized through the default constructor.

      

<h / "> (*) Note that this comparison method would not be the most efficient as it makes the entire string uppercase, while the first few characters are usually sufficient to determine their order. So, a more efficient way would be to capitalize one character at a time and compare it before deciding whether to capitalize another character.

+2


source


Answer to Question 1: You can make a simple function that converts std :: string to top.



void string_to_upper(string &s) {
  for(int l = 0; l < s.length(); ++l) {
     s[l] = toupper(s[l]);
  }
}

      

+1


source


First, your method Vehicle::getVIN()

must be marked as in order to implement correct const-correctness: const

string Vehicle::getVIN() const
{
    return VIN;   
}

      

Then note that you don't have to re-invent the wheel and re-execute the sorting algorithm from scratch in production C ++ code (unless this is a tutorial / homework exercise about writing sorting code).

You can simply use the standard algorithm implemented in the STL and set up the comparison criteria using the handy C ++ 11 lambda, for example: std::sort()

// std::vector<Vehicle> carList;

std::sort(carList.begin(), carList.end(), 
    [](const Vehicle& v1, const Vehicle& s2)
    {
        /* Code implementing custom Vehicle comparison */
    }
);

      

Your lambda code could be something like this:

    [](const Vehicle& v1, const Vehicle& s2)
    {
        // Use stricmp() to compare strings in a case insensitive way
        return (stricmp(v1.getVIN().c_str(), v2.getVIN().c_str()) < 0);
    }

      

Instead of calling, stricmp()

you can use boost::to_upper()

any other method among those shown, for example. in this thread on StackOverflow:

Comparing case insensitive strings in C ++

+1


source







All Articles