0

I have a vector with the following strings (for example): 0: "John - 204" 1: "Jack - 143" 2: "Alex - 504" and I want to sort them by the numbers so it would become Jack, John, Alex. I was using the following code:

bool myfunc(string i, string j) {
    return (stoi(i) < stoi(j));
}

sort(v1.begin(), v1.end(), myfunc); // sorts the players based on their position
for (unsigned int i = 0; i < v1.size(); i++) {
    cout << v1[i] << endl;
}

but aparently the stoi function doesn´t work in this case... If anyone has any other ideas of how I could achieve this, I would really appreciate it :)

Thanks!

  • 1
    You need to isolate the part of the string that contains the number first. This can be done with a mix of `std::string::find_last_of` and friends, and `std::string::substring`. As this might allocate, consider working with `std::string_view`, too. – lubgr May 27 '21 at 14:31
  • i would find '-' then going to extract it with substring method then use **atoi** method for converting. – N0ll_Boy May 27 '21 at 14:36

2 Answers2

0

Of course std::stoi wouldn't work in this case, because you are passing in the entirety of the string "John - 204" to myfunc, and that string has character values ("John") which doesn't have a valid conversion (at least in this case) to an integer value

You're very close though - in your comparator function (i.e. myfunc()), think of how you can consistently tease out the substrings 204, 143, 504. I would honestly write a small helper function to do this (to account for awkward cases like "John -204" (no second space character) or "John -" (no number).

Of course, if you're confident that the strings you'll receive are consistently formatted as in your example, then @lubgr's suggestion to use find_last_of and substring together is sound

Aiman
  • 59
  • 1
  • 4
0

I would go for a slightly different approach, using std::stringstreams:


#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <sstream>
using namespace std;

bool myfunc(std::string p1, std::string p2) {
    bool result;
    char ch;
    int p1int, p2int;

    stringstream comparator(p1 + " " + p2); //initialize stringstream
    while(comparator >> ch && !(isdigit(ch))); //read until the first digit
    comparator.putback(ch); //put it back
    comparator >> p1int; //read the int

    while (comparator >> ch && !(isdigit(ch))); //read until first digit
    comparator.putback(ch); //put it back
    comparator >> p2int; //read the whole int

    result = p1int < p2int; //get the result
    return result; //return it
}

int main() {
    std::vector<std::string> v1 { "John - 204","Jack - 143","Alex - 504" };

    sort(v1.begin(), v1.end(), myfunc); // sorts the players based on their position

    for (unsigned int i = 0; i < v1.size(); i++) {
        cout << v1[i] << endl;
    }
}

Output:

Jack - 143
John - 204
Alex - 504

More on std::stringstreams: https://www.cplusplus.com/reference/sstream/stringstream/.

Also, read Why is "using namespace std;" considered bad practice?.

When you passed your string to std::stoi, it had something that wasn't digits, so it failed, which is why your code did not work.