I've built this little C++ program just to take some rust off my coding skills since it's been ages since the last time I coded something.
The purpose is to organize my music, so I've built the classes
'song' and 'playlist' with some methods which could come in handy - maybe -
such as printing on file the list of songs in the playlist and so on.
I'm not sure that std::vector
is the right choice to store the songs in the
playlist (as private member). Would a std::set
be more efficient?
Given a list of songs I wanted to sort out if each and every one of the songs in the list appeared at least in one playlist, with each playlist representing a musical genre.
I was also interested in listing the "overlaps" between two different playlists, to get a sort of Venn Diagram of my music. I've accomplished that by overloading the operators + and - for the playlist, and by defining a function "intersection".
I'm defenetly not sure about the best way to handle the const
functions.
I've used the following libraries:
#include <fstream>
#include <map>
#include <vector>
#include <set>
#include <iostream>
#include <string>
#include <sstream>
Here it is the implementation of the class song:
class song {
private:
std::string title;
std::string author;
std::string album;
public:
song(std::string tit) : title(tit), author("? "), album("? ") { }
song(std::string tit, std::string au, std::string al) : title(tit), author(au), album(al) { }
const std::string gettitle() {return title;}
const std::string getauthor() {return author;}
const std::string getalbum() {return album;}
const bool operator==(song & a) {
if(title == a.gettitle()) {
if(author == a.getauthor()) {
if(album == a.getalbum()) {
return true;
}
}
}else{ return false; }
}
void playsong() {
std::cout << std::endl;
std::cout << "\"" << title << "\"" << ", by " << author << ", \n";
std::cout << "from the album \"" << album << "\"." << std::endl;
}
void showtitle() { std::cout << title << std::endl; }
void showauthor() { std::cout << author << std::endl; }
void showalbum() { std::cout << album << std::endl; }
void showall() {
std::cout << title << " | " << author;
std::cout << " | " << album << std::endl;
}
};
And of the class playlist:
class playlist {
private:
std::string name;
std::vector<song> list;
public:
playlist() : name(" ") {}
playlist(std::string nam) : name(nam) {}
playlist(playlist & x, std::string nam) {
name = nam;
list = x.getlist();
}
playlist operator=(const playlist & x) {
list = x.getlist();
name = x.getname();
return *this;
}
const playlist operator+( const playlist & x) {
playlist z(*this);
for(int i=0; i<(x.getlist()).size(); i++) {
if (false == this->findsong((x.getlist())[i])){
z.addsong((x.getlist())[i]);
}
}
z.setname(this->getname() + "+" + x.getname());
return z;
}
const playlist operator-(const playlist & x) {
playlist z(*this);
for(int i=0; i<(x.getlist()).size(); i++) {
if (this->findsong((x.getlist())[i])){
z.deletesong((x.getlist())[i]);
}
}
z.setname(this->getname() + "-" + x.getname());
return z;
}
std::vector<song> getlist() const { return list; }
std::string getname() const { return name; }
song getsong(std::vector<song>::iterator it) const { return *it; }
std::vector<song>::iterator getsong(song & x) {
std::vector<song>::iterator it;
it = list.begin();
while (it != list.end()) {
if(*(it) == x) break;
it ++;
}
return it;
}
void setname(std::string nam) { name = nam; }
void addlist(std::string file) {
std::ifstream in(file);
std::string line;
while(std::getline(in, line)) {
std::stringstream linestream(line);
std::string tit, au, al;
getline(linestream, tit, '\t');
getline(linestream, au, '\t');
getline(linestream, al);
song x(tit, au, al);
this->addsong(x);
}
in.close();
}
void addsong(song x) { list.push_back(x); }
void deletesong(song x) {
int cont=0;
std::vector<song>::iterator it;
it = list.begin();
for(auto el : list) {
if(el == x){
list.erase(it);
std::vector<song>::iterator it;
it = list.begin() + cont;
}
cont ++;
}
}
bool findsong(song x) {
bool tobe = false;
for (auto el : list) {
if(el == x) tobe = true;
}
return tobe;
}
void showplaylist() {
int cont=0;
std::vector<song>::iterator it;
it = list.begin();
std::cout << std::endl << name << std::endl << std::endl;
while (it != list.end()) {
cont++;
std::cout << cont << ") ";
it->showall();
it++;
}
}
void playplaylist() {
int cont=0;
std::vector<song>::iterator it;
it = list.begin();
std::cout << std::endl << name << std::endl << std::endl;
while (it != list.end()) {
cont++;
std::cout << cont << ") ";
it->playsong();
it++;
}
}
std::ofstream printplaylist(std::string nam) {
std::ofstream out(nam + ".dat");
std::vector<song>::iterator it;
it = list.begin();
out << std::endl << name << std::endl << std::endl;
while (it != list.end()) {
out << it->gettitle() << "\t";
out << it->getauthor() << "\t";
out << it->getalbum() << std::endl;
it++;
}
out.close();
return out;
}
};
This is the only function I wrote:
playlist intersection(playlist & x, playlist & y) {
playlist z, q, t;
z = x + y;
t = x - y;
q = y - x;
z = z - q;
z = z - t;
z.setname("(" + x.getname() + ")^(" + y.getname() + ")" );
return z;
}
In the main
I tried my methods to check if they worked fine. The playlist are "loaded" in my program through some files.dat wich have the following structure:
Title \tab Author \tab Album