CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Mar 2001
    Posts
    37

    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

  2. #2
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,725
    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()

  3. #3
    Join Date
    Jun 2002
    Location
    Letchworth, UK
    Posts
    1,020
    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

  4. #4
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582
    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

  5. #5
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    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


  6. #6
    Join Date
    Apr 1999
    Posts
    27,449
    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

  7. #7
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582
    Boy, do I remember...

    The point I was attempting to make is correct. Unfortunately, the example wasn't.

    Jeff

  8. #8
    Join Date
    Mar 2001
    Posts
    37
    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

  9. #9
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,725
    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.

  10. #10
    Join Date
    Mar 2001
    Posts
    37
    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

  11. #11
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,725
    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.

  12. #12
    Join Date
    Mar 2001
    Posts
    37
    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

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449
    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.

  14. #14
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,725
    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;
    }

  15. #15
    Join Date
    Mar 2001
    Posts
    37
    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
  •  





Click Here to Expand Forum to Full Width

Featured