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.