Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

This initial version of the program relies on treating each attribute of a song

ID: 3667344 • Letter: T

Question

This initial version of the program relies on treating each attribute of a song as a distinct, separate entity. Look at songcollection.h, both the structure and the parameter lists of the functions declared there, to see how awkward this gets.

Your task is to simplify this code by doing the following:

Replace song.h and song.cpp by song2.h and song2.cpp (i.e., rename the ‘2’ files by removing the ‘2’). These declare a structured data type Song that gathers together all the attributes of a single song.

Similarly, replace chcheck.cpp by cdcheck2.cpp.

Rewrite songcollection.h and songcollection.cpp to take advantage of the new Song type. You will need to replace the multiple arrays currently in a SongCollection by a single array of Songs. Then rewrite the functions for manipulating song collections accordingly. (Hopefully, you will see that this simplifies the code overall.)

songcollection.h:

#ifndef SONGCOLLECTION_H
#define SONGCOLLECTION_H

#include <iostream>
#include <string>
#include "playlistitem.h"
#include "song.h"
#include "time.h"

const int MAXSONGS = 1000;

struct SongCollection {
int numSongs;
std::string titles[MAXSONGS];
std::string artists[MAXSONGS];
std::string albums[MAXSONGS];
int tracks[MAXSONGS];
int lengths[MAXSONGS];
Time totalTime;
};


/**
* Set up a new collection;
*/
void initialize (SongCollection& collection);


/**
* Add a single song to a collection.
*/
void addSong (SongCollection& toCollection,
       std::string title,
       std::string artist,
       std::string album,
       int track,
       Time length);

/**
* Add into one collection all songs from another collection that
* match a given artist and/or title.
*/
void addMatchesFor (const SongCollection& fromCollection,
      SongCollection& toCollection,
      std::string artist,
      std::string title);

/**
* Print a collection to the indicated output stream
*/
void print (std::ostream& out, const SongCollection& collection);

/**
* Attempt to read a collection of songs from an input stream,
* adding it to the collection if possible,
*/
bool read (std::istream& in, SongCollection& collection);


#endif

songcollection.cpp:

#include <iostream>
#include <string>
#include "songcollection.h"


using namespace std;

/**
* Set up a new collection;
*/
void initialize (SongCollection& collection)
{
collection.numSongs = 0;
collection.totalTime = time(0,0,0);
}

/**
* Add a single song to a collection.
*/
void addSong (SongCollection& toCollection,
  std::string title,
  std::string artist,
  std::string album,
  int track,
  Time length)
{
int n = toCollection.numSongs;
toCollection.titles[n] = title;
toCollection.artists[n] = artist;
toCollection.albums[n] = album;
toCollection.tracks[n] = track;
toCollection.lengths[n] = length;
++toCollection.numSongs;
add(toCollection.totalTime, length);
}


/**
* Add into one collection all songs from another collection that
* match a given artist and/or title.
*/
void addMatchesFor (const SongCollection& fromCollection,
      SongCollection& toCollection,
      std::string artist,
      std::string title)
{
for (int i = 0; i < fromCollection.numSongs; ++i)
    {
      if (matches(artist, title,
    fromCollection.artists[i],
    fromCollection.titles[i]))
{
   addSong (toCollection, fromCollection.artists[i],
        fromCollection.titles[i], fromCollection.albums[i],
        fromCollection.tracks[i], fromCollection.lengths[i]);
}
    }
}


void print (std::ostream& out, const SongCollection& collection)
{
for (int i = 0; i < collection.numSongs; ++i)
    {
      print (out, collection.titles[i], collection.artists[i],
      collection.albums[i], collection.tracks[i],
      collection.lengths[i]);
      out << endl;
    }
out << "Total: ";
print(out, collection.totalTime);
out << endl;
}


/**
* Attempt to read a song from an input stream, adding it
* to the collection if possible,
*/
bool read (std::istream& in, SongCollection& collection)
{
initialize(collection);
string title, artist, album;
int track;
Time length;
while (read(in, title, artist, album, track, length))
    {
      addSong(collection, title, artist, album, track, length);
    }
return in;
}

Explanation / Answer

I can help you with song.h and song.cpp

#include "song.h"
#include "csv.h"
#include <sstream>
#include <vector>
using namespace std;
bool read (std::istream& in, std::string& songTitle, std::string& songArtist,std::string& songAlbum, int& songTrack, Time& songLength)
{
string line;
if (!getline(in, line)) return in;
vector<string> fields = parseCSV(line);
if (fields.size() != 5)
{
in.setstate (ios::badbit);
return in;
}
songArtist = fields[0];
songAlbum = fields[1];
{
string trackstr = fields[2];
istringstream trackIn (trackstr);
if (!(trackIn >> songTrack))
{
in.setstate (ios::badbit);
return in;
}
}
songTitle = fields[3];
{
string timestr = fields[4];
istringstream timeIn (timestr);
if (!(read(timeIn, songLength)))
{
in.setstate (ios::badbit);
return in;
}
}
return (bool)in;
}

std::string pad (int width, const std::string s)
{
string r = s + string(width, ' ');
return r.substr(0, width);
}
void print (std::ostream& out, std::string songTitle, std::string songArtist,std::string songAlbum, int songTrack, Time songLength)
{
out << pad(24, songTitle) << ' '
<< pad(19, songArtist) << ' '
<< pad(24, songAlbum) << ' '
<< songTrack << ' ';
print (out, songLength);
}

Song.cpp

#include <iostream>
#include "song.h"
#include <cstring>
using namespace std;
void IgnoreNewLines( )
{
while(cin.peek( ) == ' ')
cin.ignore( );
}
Song::Song( )
{
strcpy(title, "");
strcpy(artist, "");
}
Song::Song(const char* t, const char* a)
{
Set(t, a);
}
void Song::Set(const char* t, const char* a)
{
if(strlen(t) < MAX_CHARS)
strcpy(title, t);
if(strlen(a) < MAX_CHARS)
strcpy(artist, a);
}
ostream& operator<<(ostream& os, const Song& song)
{
os << song.title << ", " << song.artist;
return os;
}
istream& operator>>(istream& is, Song& song)
{
IgnoreNewLines( );
cin.getline(song.title, Song::MAX_CHARS, ',');
if(cin.peek( ) == ' ')
cin.ignore( );
IgnoreNewLines( );
cin.getline(song.artist, Song::MAX_CHARS);
return is;
}
bool operator==(const Song& lhs, const Song& rhs)
{
if(strcmp(lhs.title, rhs.title))
return false;
if(strcmp(lhs.artist, rhs.artist))
return false;
return true;
}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote