List sorting problem

Hi, I'm not sure how the sort() function for list objects works.
I'm trying to sort a list of album titles alphabetically, but I'm having very little success.

It's hw. Can anyone give me a few tips or help?

Thank you.

.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifndef COLL_COLLECTION_H
#define COLL_COLLECTION_H

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <list>

struct CD {
    std::string title;
    float price;
    int year;
};

class Collection {
private:
    std::list<CD> cdList;
    std::list<CD>::iterator it;

public:
    Collection();

    void insert_sorted(std::string tempName, int tempYear, float tempPrice);

    void read_from_file(std::string fileName);

    void print();

    void find_cd(std::string fileName);

    void remove(std::string fileName);

    void write_to_file(std::string fileName);
};


#endif //COLL_COLLECTION_H 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <iostream>
#include <string>
#include <list>

#include "Collection.h"

using namespace std;

Collection::Collection() {

    list<CD> temp;
    cdList = temp;

}

void Collection::insert_sorted(string tempName, int tempYear, float tempPrice){

    CD x;

    x.title = tempName;
    x.price = tempPrice;
    x.year = tempYear;

    if(cdList.empty()){
        cdList.push_front(x);
    }

    else{

        it = cdList.begin();
        while(x.title.compare(it->title) <= 0 && it != cdList.end()){
            it++;

        }

        cdList.insert(it, x);

    }


}

void Collection::read_from_file(string fileName){

    ifstream fin;
    string alName;
    int alYear;
    double alPrice;

    fin.open(fileName);

    while(fin){

        getline(fin, alName);

        fin >> alPrice;
        fin >> alYear;
        fin.get();

        insert_sorted(alName, alYear, alPrice);

    }

    fin.close();
    cout << endl;

}

void Collection::print(){

    for(it = cdList.begin(); it != cdList.end(); it++) {
        cout << "Album Name: " << it -> title << endl;
        cout << "Album Year: " << it -> year << endl;
        cout << "Alum Price: $" << it -> price << endl;
    }

    cout << endl;
}

void Collection::find_cd(string fileName){

    for(it = cdList.begin(); it != cdList.end(); it++){

        if(it -> title == fileName){
            cout << "Album Name: " << it -> title << endl;
            cout << "Album Year: " << it -> year << endl;
            cout << "Alum Price: $" << it -> price << endl;
        }

    }

    cout << endl;

}

void Collection::remove(std::string fileName){

    for(it = cdList.begin(); it != cdList.end(); it++){

        if(it -> title == fileName){

            cout << "Now removing item!" << endl;

            cdList.erase(it++);

        }

    }

    cout << endl;

}

void Collection::write_to_file(std::string fileName){

    ofstream outputFile; 

    outputFile.open(fileName);

    if(outputFile.is_open()){

        for(it = cdList.begin(); it != cdList.end(); it++){
            outputFile << it -> title << endl;
            outputFile << it -> price << " " << it -> year << endl;
        }

    }

    else{
        cout << "ERROR! Opening write file!" << endl;
    }

    cout << "The file has now been created..." << endl << endl;
    outputFile.close();

}


Side note. I've also tried doing a string compare to dynamically insert them in the right location, but it doesn't even add anything at all.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void Collection::insert_sorted(string tempName, int tempYear, float tempPrice){

    CD x;

    x.title = tempName;
    x.price = tempPrice;
    x.year = tempYear;

    if(cdList.empty()){
        cdList.push_front(x);
    }

    else{

        it = cdList.begin();
        while(x.title.compare(it->title) <= 0 && it != cdList.end()){
            it++;

        }

        cdList.insert(it, x);

    }


}
Last edited on
jjordan33 wrote:
Can anyone give me a few tips?


Supply enough code to give us a chance of answering your question.
You need to use the sort algorithm (include <algorithm>).

 
    sort(cdList.begin(), cdList.end());

Assuming cdList is a vector of CD, you will need to supply a comparison function to indicate how to sort CD's. Maybe something like this inside the CD struct/class:

1
2
3
    bool operator<(const CD& cd) {
        return title < cd.title;
    }

>> lastchance

I updated the code. My mistake!

>> dutch

Hmm. Okay.
I was afraid I'd need another library. That will resort in a loss of a couple points, but it's a great last resort. Thank you for the advice!
I got it to work with this code, so I'll mark this as completed, but if anyone has a better solution, or how to fit it inside one function, please feel free to help me improve.

Thanks y'all.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool comp (const CD& a,const CD& b) // helper function
{
    return a.title < b.title; // returns the object valued lowest in ASCII
}


void Collection::insert_sorted(string tempName, int tempYear, float tempPrice){

    CD x;

    x.title = tempName;
    x.price = tempPrice;
    x.year = tempYear;

    cdList.push_front(x);

    cdList.sort(comp);
}
Last edited on
Resorting the list on each insert is expensive.
Simpler and faster to locate the right position in the list and directly insert it there.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <string>
#include <list>
#include <algorithm>
#include <fstream>

struct cd {

    std::string title ;
    double price = 0 ;
    int year = 0 ;

    // compare two cds with the < operator; compare (case-sensitive) titles
    friend bool operator< ( const cd& a, const cd& b ) {

            return a.title < b.title ;
    }

    friend std::ostream& operator<< ( std::ostream& stm, const cd& c ) {

            return stm << "cd{ " << c.title << ", "
                       << c.price << ", " << c.year << " }" ;
    }
};

struct cd_collection {

    std::list<cd> cd_list ;

    std::ostream& print( std::ostream& stm = std::cout ) const {

        for( const cd& c : cd_list ) stm << c << '\n' ;
        return stm ;
    }

    void insert_sorted( const cd& this_cd ) {

        // get an iterator to the first element in cd_list that is greater than this_cd
        // https://en.cppreference.com/w/cpp/algorithm/upper_bound
        const auto where = std::upper_bound( cd_list.begin(), cd_list.end(), this_cd ) ;

        // insert this_cd at that position
        cd_list.insert( where, this_cd ) ;
    }
};

int main() {

    cd_collection coll ;

    coll.insert_sorted( { "ijkl", 2.4, 2007 } ) ;
    coll.insert_sorted( { "abcd", 5.6, 2117 } ) ;
    coll.insert_sorted( { "mnop", 8.2, 2110 } ) ;
    coll.insert_sorted( { "efgh", 1.5, 2019 } ) ;
    coll.insert_sorted( { "qrst", 3.8, 2001 } ) ;

    coll.print() ; // print to stdout

    // print to file
    std::ofstream file { "my_cds.txt" } ;
    coll.print(file) ;
}

http://coliru.stacked-crooked.com/a/89ac6195b6660387
I didn't know you could declare a friend inside a struct like that at all.

But this brings up something that is a little confusing....

How did my code know how to act on the < operator with objects without it being overloaded?

I got pretty lucky there, seeing as how, if I had this thought before I tried it, I would've discarded it thinking it wouldn't work.
> How did my code know how to act on the < operator with objects without it being overloaded?

It is overloaded; line 14: friend bool operator< ( const cd& a, const cd& b )
It's not overloaded in mine though right? I'm confused about how my code worked at all now that I am looking at yours.
> I'm confused about how my code worked at all

You are passing a comparison function to sort: cdList.sort(comp);

" to compare the elements, the second version uses the given comparison function"
https://en.cppreference.com/w/cpp/container/list/sort
Thanks for the documentation. I learned several things.
Topic archived. No new replies allowed.