|
-
September 10th, 2002, 12:25 PM
#1
once more sorting structs....
hello,
i've implemented a structure like that:
struct file_struct
{
string strName;
string strType;
int nKB;
time_t date;
bool bIsDir;
};
these member-vars represent the attributes filled by the content of a directory, and the flag bIsDir shows if it is an directory or not.
the results are saved in an vector<file_struct>vc; for example:
1 ttt
2 adm(dir)
3 054(dir)
4 gah
5 j02(dir)
6 rec (dir)
7 fhr(dir)
now i've got 7 elements which are directories and 2 elements which are other files
i sort them like this:
int CompDir(const void* lhs, const void* rhs)
{
bool bLhs = ((file_struct*)lhs)->bIsDir;
bool bRhs = ((file_struct*)rhs)->bIsDir;
if (bLhs < bRhs) return 1;
if (bLhs > bRhs) return -1;
return 0;
}
and
qsort(static_cast<void*>(&vc[0]), vc.size(), sizeof(file_struct), CompDir);
getting something like that:
1 fhr(dir)
2 adm(dir)
3 054(dir)
4 rec (dir)
5 j02(dir)
6 gah
7 ttt
so i've sorted my array with directories and other files...
but now i'm searching for an possibility to sort the directory-elements and the file-elements in an alphabetical order which should lokk like similar to this way:
1 054 (dir)
2 adm(dir)
3 fhr(dir)
4 j02(dir)
5 rec (dir)
6 gah
7 ttt
i've tried it with std::sort and std::partial_sort but didn't get very far...
bool cn(const file_struct lhs, const file_struct rhs)
{
return lhs.strName.c_str() < rhs.strName.c_str();
}
sort(vc.begin(), vc.begin() + 5, cn);
normally i would do this with qsortand:
int CompName(const void* lhs, const void* rhs)
{
return _stricmp(((file_struct*)lhs)->strName.c_str(), ((file_struct*)rhs)->strName.c_str());
}
...so do i have to implement my struct as a class and do some operator work, in order to use the std::-sorting algos?
i would be very greatefull for any hints,
thanx in advance,
have a nice day,
ciao,
stefan
-
September 10th, 2002, 01:05 PM
#2
using std::sort(), here is a compare function :
Code:
inline bool sortCompare(file_struct& a, file_struct &b) // note the "&"
{
if ( a.bIsDir != b.bIsDir )
{
return a.bIsDir;
}
return a.strName < b.strName;
}
and here is its usage:
Code:
sort(vc.begin() , vc.end() , sortCompare); // note vc.end()
-
September 10th, 2002, 01:26 PM
#3
qsort is a C function: it doesn't know anything about vectors. If you intend to use qsort, you have to give it an array of pointers to structures: not a vector.
If you intend to use vectors, use Philip Nicoletti's solution.
Succinct is verbose for terse
-
September 10th, 2002, 01:42 PM
#4
I believe qsort will work on vector containers, because the storage is guaranteed to be contiguous. It won't work, however, on other STL containers.
Still, use std::sort.
Jeff
-
September 11th, 2002, 06:02 AM
#5
But the OP's file_struct is not POD, so qsort won't............ oh, no, not again!
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
September 11th, 2002, 06:11 AM
#6
Originally posted by jfaust
I believe qsort will work on vector containers, because the storage is guaranteed to be contiguous. It won't work, however, on other STL containers.
Still, use std::sort.
Jeff
Hello Jeff,
qsort() is only guaranteed to work on POD types. The OP has std::string, making the class non-POD. Therefore the only safe method is std::sort (remember the Portland compiler? )
Regards,
Paul McKenzie
-
September 11th, 2002, 10:10 AM
#7
Boy, do I remember...
The point I was attempting to make is correct. Unfortunately, the example wasn't.
Jeff
-
September 11th, 2002, 12:56 PM
#8
thank you all for your explenations!!!!
is it possible to sort a std::vector with std::sort this way?
my vector filled with std:string elements:
1 c
2 d
3 a
4 e
5 b
now i want to sort the first 3 elements like this:
1 a
2 c
3 d
4 e
5 b
and afterwards i sort the last 2 elements, so that the content of my vector looks like:
1 a
2 c
3 d
4 b
5 e
is it possible to change the position of the iterator to do this (just a scetch, symbolic syntax...):
sort(vc[0], vc[3], comp);
and afterwards
sort(vc[4], vc[5], comp);
thank you for your patience,
ciao,
stefan
-
September 11th, 2002, 01:18 PM
#9
Code:
sort(vc.begin(),vc.begin()+3);
sort(vc.begin()+3,vc.end());
of course, vector must be big enough for "vc.begin()+3" to
be valid in both sorts.
If sorting in ascending order, no need for a comparison function.
-
September 11th, 2002, 02:02 PM
#10
i'm very sorry for this seems to become one of these long postings, but i'm a beginner in stl c++ (i'm just used to the mfc-stuff)...
could you help me out with this, where is my mistake?
inline bool c(const string &lhs, const string &rhs)
{
return lhs.c_str() < rhs.c_str();
}
int main(int argc, char* argv[])
{
string s1 = "c";
string s2 = "d";
string s3 = "a";
string s4 = "e";
string s5 = "b";
vector<string>v;
v.push_back(s1);
v.push_back(s2);
v.push_back(s3);
v.push_back(s4);
v.push_back(s5);
sort(v.begin(), v.begin() + 3, c);
sort(v.begin() + 3, v.end(), c);
return 0;
}
this was just a test; the output looks like:
unsorted
c
d
a
e
b
sorted 1-3
a
d // wrong
c
e
b
sorted 3-5
a
d
c
b
e
thanx for now,
stefan
-
September 11th, 2002, 02:14 PM
#11
1) your comparison function is incorrect.
lhs.c_str() returns a pointer to a c-style string.
If you want to use those pointers, you should
use strcmp().
A simpler change would be ...
Code:
inline bool c(const string &lhs, const string &rhs)
{
// return lhs.c_str() < rhs.c_str();
return lhs < rhs;
}
2) if comparing strings using the default comparison, you
do not need a comparison function ...
Code:
sort(v.begin(), v.begin() + 3);
sort(v.begin() + 3, v.end());
Last edited by Philip Nicoletti; September 11th, 2002 at 02:18 PM.
-
September 11th, 2002, 04:41 PM
#12
hello again,
i've tried this function before
inline bool c(const string &lhs, const string &rhs)
{
return lhs < rhs;
}
but i'm not able to compile this code due to:
error C2678: binary '<' : no operator defined which takes a left-hand operand of type 'const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' (or there is no
acceptable conversion)
(i'm using vc++6.0)
what i would like to use is:
int CompName(const void* lhs, const void* rhs)
{
return _stricmp(((file_struct*)lhs)->strName.c_str(), ((file_struct*)rhs)->strName.c_str());
}
and calling afterwards
qsort(static_cast<void*>(&vc[0]), vc.size(), sizeof(file_struct), CompDir);
but i'm only able to sort the whole array and not parts of it with qsort which is my desire....
perhaps i have to write my own sort - function. i can't use the default stl sort-function because of the operator<(a,b) which would be rather complicate to implement for my structur, and also a bool compare-function would be (how should equal elements be sorted aso...)
thank you for your patience,
bye,
stefan
-
September 11th, 2002, 05:08 PM
#13
Hello Steve,
Your comparison is still wrong. Since you have a vector of file_struct, your comparison takes references to file_struct, not string. Here is a stripped down example. Adapt it to your example.
Code:
#include <string>
#include <vector>
#include <algorithm>
class A
{
public:
std::string sa;
};
std::vector<A> VA;
bool c(const A& A1, const A &A2)
{
return A1.sa < A2.sa;
}
int main()
{
std::sort(VA.begin(), VA.end(), c);
}
Note that this compiles cleanly. You are passing to std::sort's comparison function A objects, not std::string's. And as I pointed out, your class is a non-POD (plain old data) class because of std::string. Therefore you should not use qsort() on it since sorting non-POD objects is not guaranteed to work with qsort().
Regards,
Paul McKenzie
Last edited by Paul McKenzie; September 11th, 2002 at 05:11 PM.
-
September 11th, 2002, 06:04 PM
#14
Sorry. From your one message I thought the vector was
a vector<string> , not vector<file_struct>.
As Paul mentioned, if you are sorting vector<A> , the
comparison fucntion prototype will be :
bool comp(const A& lhs, const A& rhs);
Is there a reason you abandoned your first thought of
just using one sort and having the comparison put
the directories first ?
Here is a simple working example. I also made the comparison
function a functor - it is a little faster that way. Notice
the "()" after the sortCompare in the call to sort, and notice
the way sortCompare is written. It can also be made faster by
using specialization, but unless you have a large number of
elements it will not make that much difference.
Code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
struct file_struct
{
string strName;
string strType;
int nKB;
time_t date;
bool bIsDir;
};
struct sortCompare
{
inline bool operator ()(file_struct& a, file_struct& b)
{
if ( a.bIsDir != b.bIsDir )
{
return a.bIsDir;
}
return a.strName < b.strName;
}
};
int main()
{
vector<file_struct>vc;
file_struct fs;
fs.strName = "ttt";
fs.bIsDir = false;
vc.push_back(fs);
fs.strName = "adm";
fs.bIsDir = true;
vc.push_back(fs);
fs.strName = "054";
fs.bIsDir = true;
vc.push_back(fs);
fs.strName = "gah";
fs.bIsDir = false;
vc.push_back(fs);
fs.strName = "j02";
fs.bIsDir = true;
vc.push_back(fs);
fs.strName = "rec";
fs.bIsDir = true;
vc.push_back(fs);
fs.strName = "fhr";
fs.bIsDir = true;
vc.push_back(fs);
sort(vc.begin() , vc.end() , sortCompare());
for (int i=0; i<vc.size(); ++i)
{
cout << vc[i].strName << endl;
}
return 0;
}
-
September 12th, 2002, 06:22 PM
#15
hi again,
just wanted to say thank you very muchtoo all of you.
that was exactly what i was searching for. i'm sorry for my confusing postings, i just wanted to achieve those things i wrote in my first posting, later on i tried only to cope with the more simple string-vector-thing, but finally you told me how to succseed....
thanx,
stefan
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|