简体   繁体   中英

Sorting a vector of structs in C++

I have a problem. The statement says that the results at a contest are read from standard input and I have to print to the screen the final standings in decreasing order by the number of solved problems. Here is my code.

#include <cstdio>
#include <vector>
#include <cstdlib>
using namespace std;

struct results
{
  unsigned int id; //id of the team
  unsigned int m; //number of solved problems
};

int comparare(const void * i, const void * j) //compare function for qsort()
{
  return -( *(unsigned int*)i - *(unsigned int*)j );
}

int main()
{

  unsigned int n;
  vector<results> standings; //initializing an array of structs

  scanf("%u", &n); //the size of the vector
  for(unsigned int i=0; i<n; ++i)
  {
    scanf("%u%u", &standings[i].id, &standings[i].m); //reading the elements
    standings.push_back(results());
  }

  qsort(standings, n, sizeof(results), comparare); //sorting the array

  for(unsigned int i=0; i<n; ++i)
    printf("%u %u\n", standings[i].id, standings[i].m); //print the sorted array

  return 0;
}

When I want to compile the code, the compiler finds the error

cannot convert 'std::vector' to 'void*' for argument '1' to 'void qsort(void*, size_t, size_t, __compar_fn_t)'

in the line qsort(standings, n, sizeof(results), comparare);

What I have to do to repair this?

If you absolutely must use qsort on a vector (and you don't. And shouldn't), then you have to pass it like this:

qsort(standings.data(), standings.size(), sizeof(results), comparare);

vector::data fetches a pointer to the array stored in the vector . Simply passing a pointer to the vector itself will not help.

Note that vector::data requires C++11; use &vector[0] if data is not available to you.

But really, just use std::sort :

std::sort(standings.begin(), standings.end(), [](const results &lhs, const results &rhs) {return lhs.id < rhs.id;});

Obviously the lambda requires C++11; feel free to use a namespace-declared struct for earlier C++ versions.

You're using C constructs, but should be using more C++ constructs. std::sort is faster than qsort generally and it's usage is much more intuitive. Here's how you can rewrite it without C++11.

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

struct results {
  unsigned int id; //id of the team
  unsigned int m; //number of solved problems
};

// I guess you're trying to sort on number of solved problems. If not, change `.m` to `.id`
bool comparare(const results lhs, const results rhs) {
  return lhs.m > rhs.m;
}

int main() {

  size_t n;

  std::cout << "Enter number of results: " << std::endl;
  std::cin >> n;

 std::vector<results> standings(n); // Creates std::vector of results with n elements

  // read in id and number of problems solved
  for(size_t i=0; i < n; ++i) {
    std::cin >> standings[i].id >> standings[i].m;
  }

  // sort the array
  std::sort(standings.begin(), standings.end(), comparare);

  // output the sorted array's id
  for(size_t i = 0; i < standings.size(); ++i) {
    std::cout << "In " << i+1 << " place: " << standings[i].id << " with " << standings[i].m << " problems solved." << std::endl;
  }

  return 0;
}

Here's the ideone with an example.

Your comparison function comparare is not appropriate if the values can exceed INT_MAX . For example comparing UINT_MAX and 0 will cause an overflow when returning UINT_MAX - 0 as an int . It is undefined behavior and on common platforms it will actually be negative.

Use this comparison function instead:

//compare function for qsort()
int comparare(const void *i, const void *j) {
    unsigned int ni = *(unsigned int*)i;
    unsigned int nj = *(unsigned int*)j;
    return (ni > nj) - (ni < nj);
}

It returns -1 , 0 or 1 if *i is respectively smaller than, equal to or greater than *j .

In C++ there are other more idiomatic ways to sort an array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM