I am currently at a loss for what to do. This initial version of the program rel
ID: 3667457 • Letter: I
Question
I am currently at a loss for what to do.
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.)
Song.h:
#ifndef SONG_H
#define SONG_H
#include <iostream>
#include <string>
#include "time.h"
bool read (std::istream& in, std::string& songTitle, std::string& songArtist,
std::string& songAlbum, int& songTrack, Time& songLength);
void print (std::ostream& out, std::string songTitle, std::string songArtist,
std::string songAlbum, int songTrack, Time songLength);
#endif
Song2.h:
#ifndef SONG_H
#define SONG_H
#include <iostream>
#include <string>
#include "time.h"
struct Song {
std::string title;
std::string artist;
std::string album;
int track;
Time length;
};
bool read (std::istream& in, Song& song);
void print (std::ostream& out, const Song& song);
#endif
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);
}
Song2.cpp:
#include "song.h"
#include "csv.h"
#include <sstream>
#include <vector>
using namespace std;
bool read (std::istream& in, Song& song)
{
string line;
if (!getline(in, line)) return in;
vector<string> fields = parseCSV(line);
if (fields.size() != 5)
{
in.setstate (ios::badbit);
return in;
}
song.artist = fields[0];
song.album = fields[1];
{
string trackstr = fields[2];
istringstream trackIn (trackstr);
if (!(trackIn >> song.track))
{
in.setstate (ios::badbit);
return in;
}
}
song.title = fields[3];
{
string timestr = fields[4];
istringstream timeIn (timestr);
if (!(read(timeIn, song.length)))
{
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, const Song& song)
{
out << pad(24, song.title) << ' '
<< pad(19, song.artist) << ' '
<< pad(24, song.album) << ' '
<< song.track << ' ';
print (out, song.length);
}
/*
* Usage: cdcheck songsList.csv playlist.csv
*/
Chcheck.cpp:
#include "songcollection.h"
#include "playlistitem.h"
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main (int argc, char** argv)
{
if (argc != 3)
{
cerr << "Usage: " << argv[0] << " songsList.csv playlist.csv" << endl;
return -1;
}
SongCollection allSongs;
initialize (allSongs);
ifstream songsIn (argv[1]);
read (songsIn, allSongs);
cout << "Read " << allSongs.numSongs << " songs with a total time of ";
print (cout, allSongs.totalTime);
cout << endl;
SongCollection cd;
initialize (cd);
ifstream selectionsIn (argv[2]);
string itemTitle;
string itemArtist;
int itemCount = 0;
while (read(selectionsIn, itemArtist, itemTitle))
{
++itemCount;
addMatchesFor (allSongs, cd, itemArtist, itemTitle);
}
cout << "Processed " << itemCount << " playlist items. " << endl;
print (cout, cd);
cout << flush;
if (cd.totalTime > time(1,15,0))
cout << "This will not fit on a standard CD" << endl;
else
cout << "This will fit on a standard CD" << endl;
return 0;
}
/*
* Usage: cdcheck songsList.csv playlist.csv
*/
Chcheck2.cpp:
#include "songcollection.h"
#include "playlistitem.h"
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main (int argc, char** argv)
{
if (argc != 3)
{
cerr << "Usage: " << argv[0] << " songsList.csv playlist.csv" << endl;
return -1;
}
SongCollection allSongs;
initialize (allSongs);
ifstream songsIn (argv[1]);
read (songsIn, allSongs);
cout << "Read " << allSongs.numSongs << " songs with a total time of ";
print (cout, allSongs.totalTime);
cout << endl;
SongCollection cd;
initialize (cd);
ifstream selectionsIn (argv[2]);
string itemTitle;
string itemArtist;
int itemCount = 0;
while (read(selectionsIn, itemArtist, itemTitle))
{
++itemCount;
addMatchesFor (allSongs, cd, itemArtist, itemTitle);
}
cout << "Processed " << itemCount << " playlist items. " << endl;
print (cout, cd);
cout << flush;
if (cd.totalTime > time(1,15,0))
cout << "This will not fit on a standard CD" << endl;
else
cout << "This will fit on a standard CD" << endl;
return 0;
}
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
Here is the code for song.h
#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);
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.